From a2cadc69ff6da1864c76822b35ac41caa0924609 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 24 Sep 2025 16:46:23 -0700 Subject: [PATCH 1/6] Rename `BadgePreviews` to `BadgePopups`. Some are preview popups, some will be other kinds of popup. --- src/components/Badge.tsx | 22 +++++++++---------- .../CodePreview.tsx | 0 .../ImagePreview.tsx | 0 .../LinkPreview.tsx | 0 .../TextPreview.tsx | 0 .../TimePreview.tsx | 0 6 files changed, 11 insertions(+), 11 deletions(-) rename src/components/{BadgePreviews => BadgePopups}/CodePreview.tsx (100%) rename src/components/{BadgePreviews => BadgePopups}/ImagePreview.tsx (100%) rename src/components/{BadgePreviews => BadgePopups}/LinkPreview.tsx (100%) rename src/components/{BadgePreviews => BadgePopups}/TextPreview.tsx (100%) rename src/components/{BadgePreviews => BadgePopups}/TimePreview.tsx (100%) diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 6ffb90a..b096199 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -3,13 +3,13 @@ import { twMerge } from 'tailwind-merge' import type { VariantProps } from 'tailwind-variants' import { badgeCVA, typeColors, typeIcons } from '@/components/design' -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 { TextPreview } from './BadgePopups/TextPreview' +import { TimePreview } from './BadgePopups/TimePreview' -const typeTooltips = { +const typePopups = { code: CodePreview, image: ImagePreview, link: LinkPreview, @@ -25,8 +25,8 @@ export type BadgeProps = VariantProps & { const Badge = ({ text, type }: 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 ( diff --git a/src/components/BadgePreviews/CodePreview.tsx b/src/components/BadgePopups/CodePreview.tsx similarity index 100% rename from src/components/BadgePreviews/CodePreview.tsx rename to src/components/BadgePopups/CodePreview.tsx diff --git a/src/components/BadgePreviews/ImagePreview.tsx b/src/components/BadgePopups/ImagePreview.tsx similarity index 100% rename from src/components/BadgePreviews/ImagePreview.tsx rename to src/components/BadgePopups/ImagePreview.tsx diff --git a/src/components/BadgePreviews/LinkPreview.tsx b/src/components/BadgePopups/LinkPreview.tsx similarity index 100% rename from src/components/BadgePreviews/LinkPreview.tsx rename to src/components/BadgePopups/LinkPreview.tsx diff --git a/src/components/BadgePreviews/TextPreview.tsx b/src/components/BadgePopups/TextPreview.tsx similarity index 100% rename from src/components/BadgePreviews/TextPreview.tsx rename to src/components/BadgePopups/TextPreview.tsx diff --git a/src/components/BadgePreviews/TimePreview.tsx b/src/components/BadgePopups/TimePreview.tsx similarity index 100% rename from src/components/BadgePreviews/TimePreview.tsx rename to src/components/BadgePopups/TimePreview.tsx From 98698724a6831bfd319fe2bb6c5f830e70dbf2c4 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 24 Sep 2025 16:49:15 -0700 Subject: [PATCH 2/6] Add a popup for the OpenTab signalling that the tab should be opened. --- src/components/Badge.tsx | 2 ++ src/components/BadgePopups/OpenTabPopup.tsx | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 src/components/BadgePopups/OpenTabPopup.tsx diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index b096199..6a96a49 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -6,6 +6,7 @@ import { badgeCVA, typeColors, typeIcons } from '@/components/design' 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' @@ -13,6 +14,7 @@ const typePopups = { code: CodePreview, image: ImagePreview, link: LinkPreview, + open: OpenTabPopup, text: TextPreview, time: TimePreview, } satisfies Partial JSX.Element>> diff --git a/src/components/BadgePopups/OpenTabPopup.tsx b/src/components/BadgePopups/OpenTabPopup.tsx new file mode 100644 index 0000000..e7a78ec --- /dev/null +++ b/src/components/BadgePopups/OpenTabPopup.tsx @@ -0,0 +1,8 @@ +export function OpenTabPopup() { + return ( + <> +

Tab is already open.

+

Click to activate.

+ + ) +} From 37a9f490af2ae97c86e5b98e232f43e81d62df3d Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 24 Sep 2025 17:07:05 -0700 Subject: [PATCH 3/6] Pipe the data to the "Open" badge. --- src/components/Badge.tsx | 7 +++--- src/components/BadgePopups/OpenTabPopup.tsx | 20 ++++++++++++++--- src/components/CommentRow.tsx | 2 +- src/entrypoints/background.ts | 21 +++++++++++------- src/entrypoints/popup/popup.tsx | 24 ++++++++------------- src/lib/messages.ts | 10 ++------- 6 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 6a96a49..64839ef 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -17,14 +17,15 @@ const typePopups = { open: OpenTabPopup, text: TextPreview, time: TimePreview, -} satisfies Partial JSX.Element>> +} satisfies Partial JSX.Element>> export type BadgeProps = VariantProps & { type: keyof typeof typeIcons text?: number | string + data?: any } -const Badge = ({ text, type }: BadgeProps) => { +const Badge = ({ text, type, data }: BadgeProps) => { const Icon = typeIcons[type] const [showTooltip, setShowTooltip] = useState(false) const PopupComponent = @@ -54,7 +55,7 @@ const Badge = ({ text, type }: BadgeProps) => { typeColors[type], )} > - + )} diff --git a/src/components/BadgePopups/OpenTabPopup.tsx b/src/components/BadgePopups/OpenTabPopup.tsx index e7a78ec..f77a5d3 100644 --- a/src/components/BadgePopups/OpenTabPopup.tsx +++ b/src/components/BadgePopups/OpenTabPopup.tsx @@ -1,8 +1,22 @@ -export function OpenTabPopup() { +import { switchToTab } from '@/entrypoints/popup/popup' + +interface OpenTabPopupProps { + uniqueKey: string +} + +export function OpenTabPopup({ uniqueKey }: OpenTabPopupProps) { + const handleClick = () => { + switchToTab(uniqueKey) + } + return ( - <> + ) } diff --git a/src/components/CommentRow.tsx b/src/components/CommentRow.tsx index d35fb1f..83cfba0 100644 --- a/src/components/CommentRow.tsx +++ b/src/components/CommentRow.tsx @@ -44,7 +44,7 @@ export function CommentRow({ row, selectedIds, toggleSelection }: CommentRowProp )} - {row.isOpenTab && } + {row.isOpenTab && } diff --git a/src/entrypoints/background.ts b/src/entrypoints/background.ts index e9e4812..2c0c22d 100644 --- a/src/entrypoints/background.ts +++ b/src/entrypoints/background.ts @@ -108,14 +108,19 @@ export function handlePopupMessage( return KEEP_PORT_OPEN } else if (isSwitchToTabMessage(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('No tab found for unique key:', message.uniqueKey) + } return CLOSE_MESSAGE_PORT } else { logger.error('received unknown message', message) diff --git a/src/entrypoints/popup/popup.tsx b/src/entrypoints/popup/popup.tsx index 7788059..8635cd8 100644 --- a/src/entrypoints/popup/popup.tsx +++ b/src/entrypoints/popup/popup.tsx @@ -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, SwitchToTabMessage } from '@/lib/messages' export interface FilterState { sentFilter: 'both' | 'sent' | 'unsent' @@ -24,20 +24,14 @@ async function getOpenSpots(): Promise { } } -// 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 switchToTab(uniqueKey: string): void { + const message: SwitchToTabMessage = { + type: 'SWITCH_TO_TAB', + uniqueKey, + } + browser.runtime.sendMessage(message) + window.close() +} const app = document.getElementById('app') if (app) { diff --git a/src/lib/messages.ts b/src/lib/messages.ts index da7fa54..c908d58 100644 --- a/src/lib/messages.ts +++ b/src/lib/messages.ts @@ -15,8 +15,7 @@ export interface GetOpenSpotsMessage { export interface SwitchToTabMessage { type: 'SWITCH_TO_TAB' - tabId: number - windowId: number + uniqueKey: string } export type PopupToBackgroundMessage = GetOpenSpotsMessage | SwitchToTabMessage @@ -64,12 +63,7 @@ export function isGetOpenSpotsMessage(message: any): message is GetOpenSpotsMess } export function isSwitchToTabMessage(message: any): message is SwitchToTabMessage { - return ( - message && - message.type === 'SWITCH_TO_TAB' && - typeof message.tabId === 'number' && - typeof message.windowId === 'number' - ) + return message && message.type === 'SWITCH_TO_TAB' && typeof message.uniqueKey === 'string' } // Message handler types From 915d76c2c169200b4d1e7c1db609017828a9e6ef Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 24 Sep 2025 17:13:13 -0700 Subject: [PATCH 4/6] Wire-up title clicking also. --- src/components/CommentRow.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/CommentRow.tsx b/src/components/CommentRow.tsx index 83cfba0..56e9848 100644 --- a/src/components/CommentRow.tsx +++ b/src/components/CommentRow.tsx @@ -1,6 +1,7 @@ import Badge from '@/components/Badge' import { timeAgo } from '@/components/misc' import type { CommentTableRow } from '@/entrypoints/background' +import { switchToTab } from '@/entrypoints/popup/popup' import { EnhancerRegistry } from '@/lib/registries' const enhancers = new EnhancerRegistry() @@ -15,6 +16,10 @@ type CommentRowProps = { export function CommentRow({ row, selectedIds, toggleSelection }: CommentRowProps) { const enhancer = enhancers.enhancerFor(row.spot) + + const handleTitleClick = () => { + switchToTab(row.spot.unique_key) + } return ( @@ -50,9 +55,13 @@ export function CommentRow({ row, selectedIds, toggleSelection }: CommentRowProp {/* Title */} From ea983561cf8a2db53dde51945e47b7333cc38d82 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 24 Sep 2025 17:20:00 -0700 Subject: [PATCH 5/6] Rename the "SwitchToTab" message to just "OpenOrFocus" --- src/components/BadgePopups/OpenTabPopup.tsx | 4 ++-- src/components/CommentRow.tsx | 4 ++-- src/entrypoints/background.ts | 6 +++--- src/entrypoints/popup/popup.tsx | 8 ++++---- src/lib/messages.ts | 12 +++++++----- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/components/BadgePopups/OpenTabPopup.tsx b/src/components/BadgePopups/OpenTabPopup.tsx index f77a5d3..76eb009 100644 --- a/src/components/BadgePopups/OpenTabPopup.tsx +++ b/src/components/BadgePopups/OpenTabPopup.tsx @@ -1,4 +1,4 @@ -import { switchToTab } from '@/entrypoints/popup/popup' +import { openOrFocusComment } from '@/entrypoints/popup/popup' interface OpenTabPopupProps { uniqueKey: string @@ -6,7 +6,7 @@ interface OpenTabPopupProps { export function OpenTabPopup({ uniqueKey }: OpenTabPopupProps) { const handleClick = () => { - switchToTab(uniqueKey) + openOrFocusComment(uniqueKey) } return ( diff --git a/src/components/CommentRow.tsx b/src/components/CommentRow.tsx index 56e9848..0213163 100644 --- a/src/components/CommentRow.tsx +++ b/src/components/CommentRow.tsx @@ -1,7 +1,7 @@ import Badge from '@/components/Badge' import { timeAgo } from '@/components/misc' import type { CommentTableRow } from '@/entrypoints/background' -import { switchToTab } from '@/entrypoints/popup/popup' +import { openOrFocusComment } from '@/entrypoints/popup/popup' import { EnhancerRegistry } from '@/lib/registries' const enhancers = new EnhancerRegistry() @@ -18,7 +18,7 @@ export function CommentRow({ row, selectedIds, toggleSelection }: CommentRowProp const enhancer = enhancers.enhancerFor(row.spot) const handleTitleClick = () => { - switchToTab(row.spot.unique_key) + openOrFocusComment(row.spot.unique_key) } return ( diff --git a/src/entrypoints/background.ts b/src/entrypoints/background.ts index 2c0c22d..54d451c 100644 --- a/src/entrypoints/background.ts +++ b/src/entrypoints/background.ts @@ -6,7 +6,7 @@ import { CLOSE_MESSAGE_PORT, isContentToBackgroundMessage, isGetOpenSpotsMessage, - isSwitchToTabMessage, + isOpenOrFocusMessage, KEEP_PORT_OPEN, } from '@/lib/messages' @@ -106,7 +106,7 @@ 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) const storage = openSpots.get(message.uniqueKey) if (storage) { @@ -119,7 +119,7 @@ export function handlePopupMessage( console.error('Error switching to tab:', error) }) } else { - console.error('No tab found for unique key:', message.uniqueKey) + console.error('TODO: implement opening a previous comment', message.uniqueKey) } return CLOSE_MESSAGE_PORT } else { diff --git a/src/entrypoints/popup/popup.tsx b/src/entrypoints/popup/popup.tsx index 8635cd8..96d6e23 100644 --- a/src/entrypoints/popup/popup.tsx +++ b/src/entrypoints/popup/popup.tsx @@ -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, SwitchToTabMessage } from '@/lib/messages' +import type { GetOpenSpotsMessage, GetTableRowsResponse, OpenOrFocusMessage } from '@/lib/messages' export interface FilterState { sentFilter: 'both' | 'sent' | 'unsent' @@ -24,9 +24,9 @@ async function getOpenSpots(): Promise { } } -export function switchToTab(uniqueKey: string): void { - const message: SwitchToTabMessage = { - type: 'SWITCH_TO_TAB', +export function openOrFocusComment(uniqueKey: string): void { + const message: OpenOrFocusMessage = { + type: 'OPEN_OR_FOCUS_COMMENT', uniqueKey, } browser.runtime.sendMessage(message) diff --git a/src/lib/messages.ts b/src/lib/messages.ts index c908d58..f61a833 100644 --- a/src/lib/messages.ts +++ b/src/lib/messages.ts @@ -13,12 +13,12 @@ export interface GetOpenSpotsMessage { type: 'GET_OPEN_SPOTS' } -export interface SwitchToTabMessage { - type: 'SWITCH_TO_TAB' +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 @@ -62,8 +62,10 @@ export function isGetOpenSpotsMessage(message: any): message is GetOpenSpotsMess return message && message.type === 'GET_OPEN_SPOTS' } -export function isSwitchToTabMessage(message: any): message is SwitchToTabMessage { - return message && message.type === 'SWITCH_TO_TAB' && typeof message.uniqueKey === 'string' +export function isOpenOrFocusMessage(message: any): message is OpenOrFocusMessage { + return ( + message && message.type === 'OPEN_OR_FOCUS_COMMENT' && typeof message.uniqueKey === 'string' + ) } // Message handler types From 5169253af478976fd9eab22d14f5762db10465ed Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 24 Sep 2025 18:30:31 -0700 Subject: [PATCH 6/6] Pipe data to all of our row badges. --- src/components/Badge.tsx | 13 +++++++++---- src/components/BadgePopups/CodePreview.tsx | 4 +++- src/components/BadgePopups/ImagePreview.tsx | 4 +++- src/components/BadgePopups/LinkPreview.tsx | 4 +++- src/components/BadgePopups/OpenTabPopup.tsx | 9 +++------ src/components/BadgePopups/TextPreview.tsx | 4 +++- src/components/BadgePopups/TimePreview.tsx | 4 +++- src/components/CommentRow.tsx | 12 ++++++------ 8 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 64839ef..478a947 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -2,6 +2,7 @@ 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 './BadgePopups/CodePreview' import { ImagePreview } from './BadgePopups/ImagePreview' @@ -17,12 +18,16 @@ const typePopups = { open: OpenTabPopup, text: TextPreview, time: TimePreview, -} satisfies Partial JSX.Element>> +} satisfies Partial JSX.Element>> + +export interface BadgePopupProps { + row: CommentTableRow +} export type BadgeProps = VariantProps & { type: keyof typeof typeIcons text?: number | string - data?: any + data?: CommentTableRow } const Badge = ({ text, type, data }: BadgeProps) => { @@ -48,14 +53,14 @@ const Badge = ({ text, type, data }: BadgeProps) => { {type === 'blank' || } {text || type} - {PopupComponent && ( + {PopupComponent && data && (
- +
)} diff --git a/src/components/BadgePopups/CodePreview.tsx b/src/components/BadgePopups/CodePreview.tsx index 5a929a4..6ed9b36 100644 --- a/src/components/BadgePopups/CodePreview.tsx +++ b/src/components/BadgePopups/CodePreview.tsx @@ -1,4 +1,6 @@ -export function CodePreview() { +import type { BadgePopupProps } from '@/components/Badge' + +export function CodePreview({ row: _row }: BadgePopupProps) { return ( <> TODO{' '} diff --git a/src/components/BadgePopups/ImagePreview.tsx b/src/components/BadgePopups/ImagePreview.tsx index b4d7ccd..1f95e67 100644 --- a/src/components/BadgePopups/ImagePreview.tsx +++ b/src/components/BadgePopups/ImagePreview.tsx @@ -1,4 +1,6 @@ -export function ImagePreview() { +import type { BadgePopupProps } from '@/components/Badge' + +export function ImagePreview({ row: _row }: BadgePopupProps) { return ( <> TODO{' '} diff --git a/src/components/BadgePopups/LinkPreview.tsx b/src/components/BadgePopups/LinkPreview.tsx index 768e97b..cce1184 100644 --- a/src/components/BadgePopups/LinkPreview.tsx +++ b/src/components/BadgePopups/LinkPreview.tsx @@ -1,4 +1,6 @@ -export function LinkPreview() { +import type { BadgePopupProps } from '@/components/Badge' + +export function LinkPreview({ row: _row }: BadgePopupProps) { return ( <> TODO{' '} diff --git a/src/components/BadgePopups/OpenTabPopup.tsx b/src/components/BadgePopups/OpenTabPopup.tsx index 76eb009..2d3d240 100644 --- a/src/components/BadgePopups/OpenTabPopup.tsx +++ b/src/components/BadgePopups/OpenTabPopup.tsx @@ -1,12 +1,9 @@ +import type { BadgePopupProps } from '@/components/Badge' import { openOrFocusComment } from '@/entrypoints/popup/popup' -interface OpenTabPopupProps { - uniqueKey: string -} - -export function OpenTabPopup({ uniqueKey }: OpenTabPopupProps) { +export function OpenTabPopup({ row }: BadgePopupProps) { const handleClick = () => { - openOrFocusComment(uniqueKey) + openOrFocusComment(row.spot.unique_key) } return ( diff --git a/src/components/BadgePopups/TextPreview.tsx b/src/components/BadgePopups/TextPreview.tsx index 266c4ef..e6878c4 100644 --- a/src/components/BadgePopups/TextPreview.tsx +++ b/src/components/BadgePopups/TextPreview.tsx @@ -1,4 +1,6 @@ -export function TextPreview() { +import type { BadgePopupProps } from '@/components/Badge' + +export function TextPreview({ row: _row }: BadgePopupProps) { return ( <> TODO{' '} diff --git a/src/components/BadgePopups/TimePreview.tsx b/src/components/BadgePopups/TimePreview.tsx index 1d13c70..b9813a1 100644 --- a/src/components/BadgePopups/TimePreview.tsx +++ b/src/components/BadgePopups/TimePreview.tsx @@ -1,4 +1,6 @@ -export function TimePreview() { +import type { BadgePopupProps } from '@/components/Badge' + +export function TimePreview({ row: _row }: BadgePopupProps) { return ( <> TODO{' '} diff --git a/src/components/CommentRow.tsx b/src/components/CommentRow.tsx index 0213163..5ffd695 100644 --- a/src/components/CommentRow.tsx +++ b/src/components/CommentRow.tsx @@ -39,17 +39,17 @@ export function CommentRow({ row, selectedIds, toggleSelection }: CommentRowProp
{row.latestDraft.stats.links.length > 0 && ( - + )} {row.latestDraft.stats.images.length > 0 && ( - + )} {row.latestDraft.stats.codeBlocks.length > 0 && ( - + )} - - - {row.isOpenTab && } + + + {row.isOpenTab && }