Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions src/components/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,39 @@ import { type JSX, useState } from 'react'
import { twMerge } from 'tailwind-merge'
import type { VariantProps } from 'tailwind-variants'
import { badgeCVA, typeColors, typeIcons } from '@/components/design'
import type { CommentTableRow } from '@/entrypoints/background'

import { CodePreview } from './BadgePreviews/CodePreview'
import { ImagePreview } from './BadgePreviews/ImagePreview'
import { LinkPreview } from './BadgePreviews/LinkPreview'
import { TextPreview } from './BadgePreviews/TextPreview'
import { TimePreview } from './BadgePreviews/TimePreview'
import { CodePreview } from './BadgePopups/CodePreview'
import { ImagePreview } from './BadgePopups/ImagePreview'
import { LinkPreview } from './BadgePopups/LinkPreview'
import { OpenTabPopup } from './BadgePopups/OpenTabPopup'
import { TextPreview } from './BadgePopups/TextPreview'
import { TimePreview } from './BadgePopups/TimePreview'

const typeTooltips = {
const typePopups = {
code: CodePreview,
image: ImagePreview,
link: LinkPreview,
open: OpenTabPopup,
text: TextPreview,
time: TimePreview,
} satisfies Partial<Record<keyof typeof typeIcons, () => JSX.Element>>
} satisfies Partial<Record<keyof typeof typeIcons, (props: BadgePopupProps) => JSX.Element>>

export interface BadgePopupProps {
row: CommentTableRow
}

export type BadgeProps = VariantProps<typeof badgeCVA> & {
type: keyof typeof typeIcons
text?: number | string
data?: CommentTableRow
}

const Badge = ({ text, type }: BadgeProps) => {
const Badge = ({ text, type, data }: BadgeProps) => {
const Icon = typeIcons[type]
const [showTooltip, setShowTooltip] = useState(false)
const TooltipComponent =
showTooltip && type in typeTooltips && typeTooltips[type as keyof typeof typeTooltips]
const PopupComponent =
showTooltip && type in typePopups && typePopups[type as keyof typeof typePopups]
return (
<button
type='button'
Expand All @@ -37,22 +45,22 @@ const Badge = ({ text, type }: BadgeProps) => {
<span
className={twMerge(
badgeCVA({
clickable: type in typeTooltips,
clickable: type in typePopups,
type,
}),
)}
>
{type === 'blank' || <Icon className='h-3 w-3' />}
{text || type}
</span>
{TooltipComponent && (
{PopupComponent && data && (
<div
className={twMerge(
'absolute top-full z-10 w-30 rounded border px-2 py-1 text-left text-xs shadow-lg',
typeColors[type],
)}
>
<TooltipComponent />
<PopupComponent row={data} />
</div>
)}
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export function CodePreview() {
import type { BadgePopupProps } from '@/components/Badge'

export function CodePreview({ row: _row }: BadgePopupProps) {
return (
<>
TODO{' '}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export function ImagePreview() {
import type { BadgePopupProps } from '@/components/Badge'

export function ImagePreview({ row: _row }: BadgePopupProps) {
return (
<>
TODO{' '}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export function LinkPreview() {
import type { BadgePopupProps } from '@/components/Badge'

export function LinkPreview({ row: _row }: BadgePopupProps) {
return (
<>
TODO{' '}
Expand Down
19 changes: 19 additions & 0 deletions src/components/BadgePopups/OpenTabPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { BadgePopupProps } from '@/components/Badge'
import { openOrFocusComment } from '@/entrypoints/popup/popup'

export function OpenTabPopup({ row }: BadgePopupProps) {
const handleClick = () => {
openOrFocusComment(row.spot.unique_key)
}

return (
<button
onClick={handleClick}
className='w-full cursor-pointer text-left hover:bg-opacity-80'
type='button'
>
<p>Tab is already open.</p>
<p>Click to activate.</p>
</button>
)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export function TextPreview() {
import type { BadgePopupProps } from '@/components/Badge'

export function TextPreview({ row: _row }: BadgePopupProps) {
return (
<>
TODO{' '}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export function TimePreview() {
import type { BadgePopupProps } from '@/components/Badge'

export function TimePreview({ row: _row }: BadgePopupProps) {
return (
<>
TODO{' '}
Expand Down
25 changes: 17 additions & 8 deletions src/components/CommentRow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Badge from '@/components/Badge'
import { timeAgo } from '@/components/misc'
import type { CommentTableRow } from '@/entrypoints/background'
import { openOrFocusComment } from '@/entrypoints/popup/popup'
import { EnhancerRegistry } from '@/lib/registries'

const enhancers = new EnhancerRegistry()
Expand All @@ -15,6 +16,10 @@ type CommentRowProps = {

export function CommentRow({ row, selectedIds, toggleSelection }: CommentRowProps) {
const enhancer = enhancers.enhancerFor(row.spot)

const handleTitleClick = () => {
openOrFocusComment(row.spot.unique_key)
}
return (
<tr className='hover:bg-gray-50'>
<td className='px-3 py-3'>
Expand All @@ -34,25 +39,29 @@ export function CommentRow({ row, selectedIds, toggleSelection }: CommentRowProp
</div>
<div className='flex flex-shrink-0 items-center gap-1'>
{row.latestDraft.stats.links.length > 0 && (
<Badge type='link' text={row.latestDraft.stats.links.length} />
<Badge type='link' text={row.latestDraft.stats.links.length} data={row} />
)}
{row.latestDraft.stats.images.length > 0 && (
<Badge type='image' text={row.latestDraft.stats.images.length} />
<Badge type='image' text={row.latestDraft.stats.images.length} data={row} />
)}
{row.latestDraft.stats.codeBlocks.length > 0 && (
<Badge type='code' text={row.latestDraft.stats.codeBlocks.length} />
<Badge type='code' text={row.latestDraft.stats.codeBlocks.length} data={row} />
)}
<Badge type='text' text={row.latestDraft.stats.charCount} />
<Badge type='time' text={timeAgo(row.latestDraft.time)} />
{row.isOpenTab && <Badge type='open' />}
<Badge type='text' text={row.latestDraft.stats.charCount} data={row} />
<Badge type='time' text={timeAgo(row.latestDraft.time)} data={row} />
{row.isOpenTab && <Badge type='open' data={row} />}
</div>
</div>

{/* Title */}
<div className='flex items-center gap-1'>
<a href='TODO' className='truncate font-medium text-sm hover:underline'>
<button
type='button'
onClick={handleTitleClick}
className='cursor-pointer truncate text-left font-medium text-sm hover:underline'
>
{enhancer.tableTitle(row.spot)}
</a>
</button>
<Badge type={row.isSent ? 'sent' : 'unsent'} />
{row.isTrashed && <Badge type='trashed' />}
</div>
Expand Down
25 changes: 15 additions & 10 deletions src/entrypoints/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
CLOSE_MESSAGE_PORT,
isContentToBackgroundMessage,
isGetOpenSpotsMessage,
isSwitchToTabMessage,
isOpenOrFocusMessage,
KEEP_PORT_OPEN,
} from '@/lib/messages'

Expand Down Expand Up @@ -106,16 +106,21 @@ export function handlePopupMessage(
const response: GetTableRowsResponse = { rows }
sendResponse(response)
return KEEP_PORT_OPEN
} else if (isSwitchToTabMessage(message)) {
} else if (isOpenOrFocusMessage(message)) {
logger.debug('received switch tab message', message)
browser.windows
.update(message.windowId, { focused: true })
.then(() => {
return browser.tabs.update(message.tabId, { active: true })
})
.catch((error) => {
console.error('Error switching to tab:', error)
})
const storage = openSpots.get(message.uniqueKey)
if (storage) {
browser.windows
.update(storage.tab.windowId, { focused: true })
.then(() => {
return browser.tabs.update(storage.tab.tabId, { active: true })
})
.catch((error) => {
console.error('Error switching to tab:', error)
})
} else {
console.error('TODO: implement opening a previous comment', message.uniqueKey)
}
return CLOSE_MESSAGE_PORT
} else {
logger.error('received unknown message', message)
Expand Down
24 changes: 9 additions & 15 deletions src/entrypoints/popup/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createRoot } from 'react-dom/client'
import { PopupRoot } from '@/components/PopupRoot'
import type { CommentTableRow } from '@/entrypoints/background'
import { logger } from '@/lib/logger'
import type { GetOpenSpotsMessage, GetTableRowsResponse } from '@/lib/messages'
import type { GetOpenSpotsMessage, GetTableRowsResponse, OpenOrFocusMessage } from '@/lib/messages'

export interface FilterState {
sentFilter: 'both' | 'sent' | 'unsent'
Expand All @@ -24,20 +24,14 @@ async function getOpenSpots(): Promise<CommentTableRow[]> {
}
}

// function switchToTab(tabId: number, windowId: number): void {
// const message: SwitchToTabMessage = {
// tabId,
// type: 'SWITCH_TO_TAB',
// windowId,
// }
// browser.runtime.sendMessage(message)
// window.close()
// }

// const handleSpotClick = (spot: CommentTableRow) => {
// console.log('TODO: switchToTab')
// //switchToTab(spot.tab.tabId, spot.tab.windowId)
// }
export function openOrFocusComment(uniqueKey: string): void {
const message: OpenOrFocusMessage = {
type: 'OPEN_OR_FOCUS_COMMENT',
uniqueKey,
}
browser.runtime.sendMessage(message)
window.close()
}

const app = document.getElementById('app')
if (app) {
Expand Down
16 changes: 6 additions & 10 deletions src/lib/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ export interface GetOpenSpotsMessage {
type: 'GET_OPEN_SPOTS'
}

export interface SwitchToTabMessage {
type: 'SWITCH_TO_TAB'
tabId: number
windowId: number
export interface OpenOrFocusMessage {
type: 'OPEN_OR_FOCUS_COMMENT'
uniqueKey: string
}

export type PopupToBackgroundMessage = GetOpenSpotsMessage | SwitchToTabMessage
export type PopupToBackgroundMessage = GetOpenSpotsMessage | OpenOrFocusMessage

// All messages sent to background
export type ToBackgroundMessage = ContentToBackgroundMessage | PopupToBackgroundMessage
Expand Down Expand Up @@ -63,12 +62,9 @@ export function isGetOpenSpotsMessage(message: any): message is GetOpenSpotsMess
return message && message.type === 'GET_OPEN_SPOTS'
}

export function isSwitchToTabMessage(message: any): message is SwitchToTabMessage {
export function isOpenOrFocusMessage(message: any): message is OpenOrFocusMessage {
return (
message &&
message.type === 'SWITCH_TO_TAB' &&
typeof message.tabId === 'number' &&
typeof message.windowId === 'number'
message && message.type === 'OPEN_OR_FOCUS_COMMENT' && typeof message.uniqueKey === 'string'
)
}

Expand Down