Clean up notebooks design and saving

This commit is contained in:
Jackson Harper 2023-06-22 17:16:54 +08:00
parent fa0efe7794
commit e294ed4b4b
11 changed files with 324 additions and 332 deletions

View file

@ -26,6 +26,9 @@ import {
import { CloseButton } from '../elements/CloseButton'
import { StyledText } from '../elements/StyledText'
import remarkGfm from 'remark-gfm'
import { RcEditorStyles } from './RcEditorStyles'
import { isDarkTheme } from '../../lib/themeUpdater'
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
const mdParser = new MarkdownIt()
@ -34,6 +37,8 @@ MdEditor.use(Plugins.TabInsert, {
})
type NoteSectionProps = {
targetId: string
placeHolder: string
mode: 'edit' | 'preview'
@ -60,6 +65,7 @@ export function HighlightNoteBox(props: NoteSectionProps): JSX.Element {
return (
<MarkdownNote
targetId={props.targetId}
placeHolder={props.placeHolder}
mode={props.mode}
sizeMode={props.sizeMode}
@ -73,6 +79,8 @@ export function HighlightNoteBox(props: NoteSectionProps): JSX.Element {
}
type HighlightViewNoteProps = {
targetId: string
placeHolder: string
mode: 'edit' | 'preview'
@ -99,6 +107,13 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
setLastSaved(updateTime)
props.highlight.annotation = text
props.updateHighlight(props.highlight)
showSuccessToast('Note saved.', {
position: 'bottom-right',
})
} else {
showErrorToast('Error saving note.', {
position: 'bottom-right',
})
}
})()
},
@ -107,6 +122,7 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
return (
<MarkdownNote
targetId={props.targetId}
placeHolder={props.placeHolder}
mode={props.mode}
sizeMode={props.sizeMode}
@ -120,6 +136,8 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
}
type MarkdownNote = {
targetId: string
placeHolder: string
mode: 'edit' | 'preview'
@ -137,37 +155,7 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
const editorRef = useRef<MdEditor | null>(null)
const [lastChanged, setLastChanged] = useState<Date | undefined>(undefined)
const [errorSaving, setErrorSaving] = useState<string | undefined>(undefined)
const saveRef = useRef(props.saveText)
useEffect(() => {
saveRef.current = props.saveText
}, [props.lastSaved, lastChanged])
const debouncedSave = useMemo<
(text: string, updateTime: Date) => void
>(() => {
const func = (text: string, updateTime: Date) => {
saveRef.current?.(text, updateTime)
}
return throttle(func, 3000)
}, [])
const handleEditorChange = useCallback(
(
data: { text: string; html: string },
event?: ChangeEvent<HTMLTextAreaElement> | undefined
) => {
if (event) {
event.preventDefault()
}
const updateTime = new Date()
setLastChanged(updateTime)
debouncedSave(data.text, updateTime)
},
[props.lastSaved, lastChanged]
)
const isDark = isDarkTheme()
return (
<>
@ -175,28 +163,13 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
<VStack
css={{
width: '100%',
mt: '15px',
'.rc-md-editor': {
borderRadius: '5px',
},
'.rc-md-navigation': {
borderRadius: '5px',
borderBottomLeftRadius: '0px',
borderBottomRightRadius: '0px',
},
'.rc-md-editor .editor-container >.section': {
borderRight: 'unset',
},
'.rc-md-editor .editor-container .sec-md .input': {
padding: '10px',
borderRadius: '5px',
fontSize: '16px',
},
...RcEditorStyles(isDark),
}}
onKeyDown={(event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.code.toLowerCase() === 'escape') {
props.setEditMode('preview')
event.preventDefault()
event.stopPropagation()
}
}}
>
@ -233,7 +206,6 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
height: props.sizeMode == 'normal' ? '160px' : '320px',
}}
renderHTML={(text: string) => mdParser.render(text)}
onChange={handleEditorChange}
/>
<HStack
css={{
@ -258,46 +230,32 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
{errorSaving}
</SpanBox>
)}
{props.lastSaved !== undefined ? (
<>
{lastChanged === props.lastSaved
? 'Saved'
: `Last saved ${formattedShortTime(
props.lastSaved.toISOString()
)}`}
</>
) : null}
{lastChanged !== props.lastSaved && (
<SpanBox
css={{
fontSize: '9px',
mt: '1px',
color: 'green',
marginLeft: 'auto',
<SpanBox
css={{
fontSize: '9px',
mt: '10px',
color: 'green',
marginLeft: 'auto',
}}
>
<Button
style="ctaDarkYellow"
onClick={(event) => {
const value = editorRef.current?.getMdValue()
if (value) {
props.saveText(value, new Date())
props.setEditMode('preview')
} else {
showErrorToast('Error saving note.', {
position: 'bottom-right',
})
}
event.preventDefault()
}}
>
<Button
css={{
textDecoration: 'underline',
border: 'unset',
background: 'unset',
'&:hover': {
border: 'unset',
background: 'unset',
},
}}
onClick={(event) => {
const value = editorRef.current?.getMdValue()
if (value) {
props.saveText(value, new Date())
}
event.preventDefault()
}}
>
Save
</Button>
</SpanBox>
)}
Save
</Button>
</SpanBox>
</HStack>
</VStack>
) : (
@ -306,9 +264,9 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
css={{
p: '5px',
width: '100%',
fontSize: '15px',
// borderRadius: '3px',
marginTop: props.fillBackground || !props.text ? '10px' : '0px',
fontSize: '12px',
marginTop: '0px',
paddingTop: '0px',
paddingLeft:
props.fillBackground && props.text
@ -344,6 +302,8 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element {
}
type MarkdownModalProps = {
targetId: string
placeHolder: string
mode: 'edit' | 'preview'
@ -435,6 +395,7 @@ export function MarkdownModal(props: MarkdownModalProps): JSX.Element {
</HStack>
<SpanBox css={{ padding: '20px', width: '100%', height: '100%' }}>
<MarkdownNote
targetId={props.targetId}
placeHolder={props.placeHolder}
mode={props.mode}
sizeMode={props.sizeMode}

View file

@ -14,6 +14,7 @@ import { styled } from '../tokens/stitches.config'
import { HighlightViewNote } from './HighlightNotes'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { isDarkTheme } from '../../lib/themeUpdater'
type HighlightViewProps = {
highlight: Highlight
@ -23,62 +24,70 @@ type HighlightViewProps = {
}
const StyledQuote = styled(Blockquote, {
p: '10px',
margin: '0px 0px 0px 0px',
fontSize: '18px',
lineHeight: '27px',
borderRadius: '4px',
width: '100%',
background: 'rgba(255, 210, 52, 0.10)',
})
export function HighlightView(props: HighlightViewProps): JSX.Element {
const isDark = isDarkTheme()
const [noteMode, setNoteMode] = useState<'preview' | 'edit'>('preview')
return (
<HStack
css={{
p: '5px',
width: '100%',
height: '100%',
alignItems: 'stretch',
background: '$thBackground',
bg: isDark ? '#3D3D3D' : '$thBackground',
borderRadius: '6px',
boxShadow: '0px 4px 4px rgba(33, 33, 33, 0.1)',
'@mdDown': {
p: '0px',
},
}}
// <Box
// css={{
// width: '100%',
// height: '100%',
// padding: '10px',
// background: '$thBackground',
// borderRadius: '6px',
// boxShadow: '0px 4px 4px rgba(33, 33, 33, 0.1)',
// }}
// >
>
<VStack
css={{
minHeight: '100%',
width: '10px',
pt: '15px',
pt: '10px',
pl: '10px',
pr: '10px',
'@mdDown': {
display: 'none',
},
}}
>
<CaretDown size={15} color="#898989" weight="fill" />
{/* <CaretDown size={12} color="#898989" weight="fill" /> */}
<Box
css={{
width: '2px',
flexGrow: '1',
background: '#FFD234',
marginTop: '5px',
marginLeft: '6px',
marginLeft: '5px',
flex: '1',
marginBottom: '10px',
marginBottom: '25px',
}}
/>
</VStack>
<VStack
css={{
width: '100%',
padding: '10px',
paddingLeft: '20px',
paddingTop: '15px',
paddingRight: '15px',
'@mdDown': {
padding: '0px',
},
}}
>
<StyledQuote>
@ -89,7 +98,7 @@ export function HighlightView(props: HighlightViewProps): JSX.Element {
},
fontSize: '15px',
lineHeight: 1.5,
color: '$grayText',
color: '$thTextSubtle2',
img: {
display: 'block',
margin: '0.5em auto !important',
@ -110,11 +119,18 @@ export function HighlightView(props: HighlightViewProps): JSX.Element {
))}
</Box>
<HStack
css={{ width: '100%', height: '100%', pt: '15px' }}
css={{
width: '100%',
pt: '15px',
'@mdDown': {
p: '10px',
},
}}
alignment="start"
distribution="start"
>
<HighlightViewNote
targetId={props.highlight.id}
text={props.highlight.annotation}
placeHolder="Add notes to this highlight..."
highlight={props.highlight}
@ -123,28 +139,6 @@ export function HighlightView(props: HighlightViewProps): JSX.Element {
setEditMode={setNoteMode}
updateHighlight={props.updateHighlight}
/>
<SpanBox
css={{
lineHeight: '1',
marginLeft: '20px',
marginTop: '15px',
cursor: 'pointer',
borderRadius: '1000px',
'&:hover': {
background: '#EBEBEB',
},
}}
onClick={(event) => {
setNoteMode(noteMode == 'preview' ? 'edit' : 'preview')
event.preventDefault()
}}
>
{noteMode === 'edit' ? (
<BookOpen size={15} color="#898989" />
) : (
<PencilLine size={15} color="#898989" />
)}
</SpanBox>
</HStack>
</VStack>
</HStack>

View file

@ -18,9 +18,9 @@ export const MenuStyle = {
display: 'flex',
marginLeft: 'auto',
height: '30px',
width: '150px',
mt: '-5px',
mr: '-5px',
width: '180px',
// mt: '-5px',
// mr: '-5px',
pt: '2px',
alignItems: 'center',
justifyContent: 'center',

View file

@ -145,9 +145,6 @@ const LibraryGridCardContent = (props: LinkedItemCardProps): JSX.Element => {
gap: '10px',
px: '20px',
borderRadius: '1000px',
bg: 'red',
visibility: props.isHovered || menuOpen ? 'unset' : 'hidden',
'@media (hover: none)': {
visibility: 'unset',

View file

@ -6,6 +6,8 @@ import {
Archive,
ArchiveBox,
DotsThree,
Note,
Notebook,
Tag,
Trash,
Tray,
@ -116,6 +118,27 @@ export function LibraryListCardContent(
},
}}
>
<Button
style="hoverActionIcon"
onClick={(event) => {
props.handleAction('open-notebook')
event.preventDefault()
}}
>
<Notebook
size={19}
color={theme.colors.thHighContrast.toString()}
/>
</Button>
<Button
style="hoverActionIcon"
onClick={(event) => {
props.handleAction('set-labels')
event.preventDefault()
}}
>
<Tag size={18} color={theme.colors.thHighContrast.toString()} />
</Button>
<Button
style="hoverActionIcon"
onClick={(event) => {
@ -145,15 +168,6 @@ export function LibraryListCardContent(
>
<Trash size={18} color={theme.colors.thHighContrast.toString()} />
</Button>
<Button
style="hoverActionIcon"
onClick={(event) => {
props.handleAction('set-labels')
event.preventDefault()
}}
>
<Tag size={18} color={theme.colors.thHighContrast.toString()} />
</Button>
<CardMenu
item={props.item}
viewer={props.viewer}

View file

@ -25,38 +25,29 @@ export function HighlightViewItem(props: HighlightViewItemProps): JSX.Element {
return (
<HStack
css={{ width: '100%', py: '20px' }}
css={{
width: '100%',
pt: '10px',
pb: '20px',
}}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
<VStack css={{ width: '100%' }}>
<VStack css={{ width: '100%', height: '100%' }}>
<HighlightView
highlight={props.highlight}
updateHighlight={props.updateHighlight}
/>
<SpanBox css={{ mb: '15px' }} />
</VStack>
<SpanBox
css={{
marginLeft: 'auto',
width: '20px',
visibility: hover ? 'unset' : 'hidden',
'@media (hover: none)': {
visibility: 'unset',
},
}}
>
<HighlightsMenu
item={props.item}
viewer={props.viewer}
highlight={props.highlight}
viewInReader={props.viewInReader}
setLabelsTarget={props.setSetLabelsTarget}
setShowConfirmDeleteHighlightId={
props.setShowConfirmDeleteHighlightId
}
/>
</SpanBox>
<HighlightsMenu
item={props.item}
viewer={props.viewer}
highlight={props.highlight}
viewInReader={props.viewInReader}
setLabelsTarget={props.setSetLabelsTarget}
setShowConfirmDeleteHighlightId={props.setShowConfirmDeleteHighlightId}
/>
</HStack>
)
}

View file

@ -3,7 +3,15 @@ import { StyledText } from '../../elements/StyledText'
import { theme } from '../../tokens/stitches.config'
import type { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react'
import { BookOpen, CaretDown, PencilLine, X } from 'phosphor-react'
import {
BookOpen,
CaretDown,
CaretRight,
DotsThree,
Pencil,
PencilLine,
X,
} from 'phosphor-react'
import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation'
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
import { diff_match_patch } from 'diff-match-patch'
@ -20,6 +28,8 @@ import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery
import { ReadableItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { SetHighlightLabelsModalPresenter } from './SetLabelsModalPresenter'
import { Button } from '../../elements/Button'
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
import { ArticleNoteBox } from '../../patterns/ArticleNotes'
type NotebookProps = {
viewer: UserBasicData
@ -93,6 +103,7 @@ export function Notebook(props: NotebookProps): JSX.Element {
if (!action.note) {
throw new Error('No note on CREATE_NOTE action')
}
console.log(' - CREATE_NOTE', action.note)
return {
...state,
note: action.note,
@ -234,6 +245,14 @@ export function Notebook(props: NotebookProps): JSX.Element {
const handleSaveNoteText = useCallback(
(text, cb: (success: boolean) => void) => {
console.log(
'saving note text: ',
text,
'annotations.loaded: ',
annotations.loaded,
'annotations.note: ',
annotations.note
)
if (!annotations.loaded) {
// We haven't loaded the user's annotations yet, so we can't
// find or create their highlight note.
@ -285,72 +304,89 @@ export function Notebook(props: NotebookProps): JSX.Element {
[annotations, props.item]
)
const [articleNotesCollapsed, setArticleNotesCollapsed] = useState(false)
const [highlightsCollapsed, setHighlightsCollapsed] = useState(false)
return (
<VStack
distribution="start"
css={{ height: '100%', width: '100%', p: '20px' }}
css={{
height: '100%',
width: '100%',
p: '40px',
'@mdDown': { p: '10px' },
}}
>
<TitledSection
<SectionTitle
title="Article Notes"
editMode={notesEditMode == 'edit'}
setEditMode={(edit) => setNotesEditMode(edit ? 'edit' : 'preview')}
collapsed={articleNotesCollapsed}
setCollapsed={setArticleNotesCollapsed}
/>
<Box
css={{
width: '100%',
height: '100%',
padding: '10px',
background: '$thBackground',
borderRadius: '6px',
boxShadow: '0px 4px 4px rgba(33, 33, 33, 0.1)',
}}
>
<HighlightNoteBox
mode={notesEditMode}
sizeMode={props.sizeMode}
setEditMode={setNotesEditMode}
text={annotations.note?.annotation}
placeHolder="Add notes to this document..."
saveText={handleSaveNoteText}
/>
</Box>
{!articleNotesCollapsed && (
<HStack
alignment="start"
distribution="start"
css={{ width: '100%', mt: '10px', gap: '10px' }}
>
<ArticleNoteBox
mode={notesEditMode}
targetId={props.item.id}
sizeMode={props.sizeMode}
setEditMode={setNotesEditMode}
text={annotations.note?.annotation}
placeHolder="Add notes to this document..."
saveText={handleSaveNoteText}
/>
</HStack>
)}
<SpanBox css={{ mt: '10px', mb: '25px' }} />
<Box css={{ width: '100%' }}>
<TitledSection title="Highlights" />
<SectionTitle
title="Highlights"
collapsed={highlightsCollapsed}
setCollapsed={setHighlightsCollapsed}
/>
{sortedHighlights.map((highlight) => (
<HighlightViewItem
key={highlight.id}
item={props.item}
viewer={props.viewer}
highlight={highlight}
viewInReader={props.viewInReader}
setSetLabelsTarget={setLabelsTarget}
setShowConfirmDeleteHighlightId={setShowConfirmDeleteHighlightId}
updateHighlight={() => {
dispatchAnnotations({
type: 'UPDATE_HIGHLIGHT',
updateHighlight: highlight,
})
}}
/>
))}
{sortedHighlights.length === 0 && (
<Box
css={{
mt: '15px',
width: '100%',
fontSize: '9px',
color: '$thTextSubtle',
alignItems: 'center',
justifyContent: 'center',
mb: '100px',
}}
>
You have not added any highlights to this document.
</Box>
{!highlightsCollapsed && (
<>
{sortedHighlights.map((highlight) => (
<HighlightViewItem
key={highlight.id}
item={props.item}
viewer={props.viewer}
highlight={highlight}
viewInReader={props.viewInReader}
setSetLabelsTarget={setLabelsTarget}
setShowConfirmDeleteHighlightId={
setShowConfirmDeleteHighlightId
}
updateHighlight={() => {
dispatchAnnotations({
type: 'UPDATE_HIGHLIGHT',
updateHighlight: highlight,
})
}}
/>
))}
{sortedHighlights.length === 0 && (
<Box
css={{
mt: '15px',
width: '100%',
fontSize: '9px',
color: '$thTextSubtle',
alignItems: 'center',
justifyContent: 'center',
mb: '100px',
}}
>
You have not added any highlights to this document.
</Box>
)}
</>
)}
<Box
{/* <Box
css={{
'@mdDown': {
height: '320px',
@ -358,7 +394,7 @@ export function Notebook(props: NotebookProps): JSX.Element {
background: 'transparent',
},
}}
/>
/> */}
</Box>
{showConfirmDeleteHighlightId && (
@ -419,62 +455,52 @@ export function Notebook(props: NotebookProps): JSX.Element {
)
}
type TitledSectionProps = {
type SectionTitleProps = {
title: string
editMode?: boolean
setEditMode?: (set: boolean) => void
collapsed: boolean
setCollapsed: (set: boolean) => void
}
function TitledSection(props: TitledSectionProps): JSX.Element {
function SectionTitle(props: SectionTitleProps): JSX.Element {
return (
<>
<HStack
css={{ width: '100%', gap: '10px' }}
alignment="center"
distribution="start"
<Button
style="plainIcon"
css={{
display: 'flex',
alignItems: 'center',
width: '100%',
gap: '5px',
}}
onClick={(event) => {
props.setCollapsed(!props.collapsed)
event.stopPropagation()
}}
>
{/* <CaretDown size={12} color={theme.colors.thNotebookSubtle.toString()} /> */}
{props.collapsed ? (
<CaretRight
size={12}
color={theme.colors.thNotebookSubtle.toString()}
/>
) : (
<CaretDown
size={12}
color={theme.colors.thNotebookSubtle.toString()}
/>
)}
<StyledText
css={{
m: '0px',
pt: '2px',
fontFamily: '$inter',
fontStyle: 'normal',
fontWeight: '500',
fontSize: '12px',
lineHeight: '20px',
color: '$thNotebookSubtle',
}}
>
{props.title}
</StyledText>
{props.setEditMode && (
<SpanBox
css={{
marginLeft: 'auto',
justifyContent: 'end',
lineHeight: '1',
alignSelf: 'end',
padding: '2px',
cursor: 'pointer',
borderRadius: '1000px',
'&:hover': {
background: '#EBEBEB',
},
}}
onClick={(event) => {
if (props.setEditMode) {
props.setEditMode(!props.editMode)
}
event.preventDefault()
}}
>
{props.editMode ? (
<BookOpen size={15} color="#898989" />
) : (
<PencilLine size={15} color="#898989" />
)}
</SpanBox>
)}
</HStack>
</Button>
</>
)
}

View file

@ -89,8 +89,9 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element {
css={{
overflow: 'auto',
bg: '$thLibraryBackground',
width: '100%',
height: sizeMode === 'normal' ? 'unset' : '100%',
maxWidth: sizeMode === 'normal' ? '640px' : '100%',
maxWidth: sizeMode === 'normal' ? '748px' : '1050px',
minHeight: sizeMode === 'normal' ? '525px' : 'unset',
'@mdDown': {
top: '20px',
@ -102,7 +103,7 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element {
}}
>
<HStack
distribution="between"
distribution="center"
alignment="center"
css={{
width: '100%',
@ -127,7 +128,7 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element {
distribution="center"
alignment="center"
>
<SizeToggle mode={sizeMode} setMode={setSizeMode} />
{/* <SizeToggle mode={sizeMode} setMode={setSizeMode} /> */}
<Dropdown triggerElement={<MenuTrigger />}>
<DropdownOption
onSelect={() => {

View file

@ -10,7 +10,7 @@ import {
DropdownOption,
DropdownSeparator,
} from '../../elements/DropdownElements'
import { Box } from '../../elements/LayoutPrimitives'
import { Box, VStack } from '../../elements/LayoutPrimitives'
import { styled, theme } from '../../tokens/stitches.config'
@ -57,70 +57,76 @@ export function HighlightsMenu(props: HighlightsMenuProps): JSX.Element {
}, [props.highlight])
return (
<Dropdown
triggerElement={
<Box
css={{
display: 'flex',
height: '20px',
width: '20px',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '1000px',
'&:hover': {
bg: '#898989',
},
}}
>
<DotsThreeVertical
size={20}
color={theme.colors.thTextContrast2.toString()}
weight="bold"
/>
</Box>
}
<VStack
distribution="center"
alignment="center"
css={{ height: '100%', pl: '5px', pt: '5px' }}
>
<DropdownOption
onSelect={async () => {
copyHighlight()
}}
title="Copy"
/>
<DropdownOption
onSelect={() => {
props.setLabelsTarget(props.highlight)
}}
title="Labels"
/>
<DropdownOption
onSelect={() => {
props.setShowConfirmDeleteHighlightId(props.highlight.id)
}}
title="Delete"
/>
<DropdownSeparator />
<Link
href={`/${props.viewer.profile.username}/${props.item.slug}#${props.highlight.id}`}
<Dropdown
triggerElement={
<Box
css={{
display: 'flex',
height: '20px',
width: '20px',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '1000px',
'&:hover': {
bg: '#898989',
},
}}
>
<DotsThreeVertical
size={20}
color={theme.colors.thTextContrast2.toString()}
weight="bold"
/>
</Box>
}
>
<StyledLinkItem
onClick={(event) => {
console.log('event.ctrlKey: ', event.ctrlKey, event.metaKey)
if (event.ctrlKey || event.metaKey) {
window.open(
`/${props.viewer.profile.username}/${props.item.slug}#${props.highlight.id}`,
'_blank'
)
return
}
props.viewInReader(props.highlight.id)
event.preventDefault()
event.stopPropagation()
<DropdownOption
onSelect={async () => {
copyHighlight()
}}
title="Copy"
/>
<DropdownOption
onSelect={() => {
props.setLabelsTarget(props.highlight)
}}
title="Labels"
/>
<DropdownOption
onSelect={() => {
props.setShowConfirmDeleteHighlightId(props.highlight.id)
}}
title="Delete"
/>
<DropdownSeparator />
<Link
href={`/${props.viewer.profile.username}/${props.item.slug}#${props.highlight.id}`}
>
View In Reader
</StyledLinkItem>
</Link>
</Dropdown>
<StyledLinkItem
onClick={(event) => {
console.log('event.ctrlKey: ', event.ctrlKey, event.metaKey)
if (event.ctrlKey || event.metaKey) {
window.open(
`/${props.viewer.profile.username}/${props.item.slug}#${props.highlight.id}`,
'_blank'
)
return
}
props.viewInReader(props.highlight.id)
event.preventDefault()
event.stopPropagation()
}}
>
View In Reader
</StyledLinkItem>
</Link>
</Dropdown>
</VStack>
)
}

View file

@ -277,6 +277,7 @@ const darkThemeSpec = {
thLibrarySelectionColor: '#3D3D3D',
thNotebookSubtle: '#898989',
thNotebookHighContrast: '#2A2A2A',
thTextContrast: '#FFFFFF',
thTextContrast2: '#EBEBEB',

View file

@ -107,6 +107,7 @@ export function isDarkTheme(): boolean {
return (
currentTheme === 'Dark' ||
currentTheme === 'Darker' ||
currentTheme === 'Apollo' ||
currentTheme == 'Black'
)
}