Warnings clean up

This commit is contained in:
Jackson Harper
2023-06-20 13:36:36 +08:00
parent b8886c96da
commit e270d4acf9
27 changed files with 388 additions and 333 deletions

View File

@ -1,4 +1,4 @@
import { getLuminance, lighten, parseToRgba, toHsla } from 'color2k'
import { getLuminance } from 'color2k'
import { useRouter } from 'next/router'
import { Button } from './Button'
import { SpanBox, HStack } from './LayoutPrimitives'

View File

@ -1,6 +1,6 @@
import React, { useMemo, useRef, useState } from 'react'
import React, { useRef, useState } from 'react'
import { styled } from '../tokens/stitches.config'
import { Box, HStack, SpanBox } from './LayoutPrimitives'
import { Box, HStack } from './LayoutPrimitives'
import { StyledText } from './StyledText'
import {
LabelColorDropdownProps,
@ -116,7 +116,6 @@ export const LabelColorDropdown = (props: LabelColorDropdownProps) => {
}
function LabelOption(props: LabelOptionProps): JSX.Element {
const { color, isDropdownOption, isCreateMode, labelId } = props
return (
<HStack
alignment="center"
@ -156,19 +155,6 @@ function LabelOption(props: LabelOptionProps): JSX.Element {
)
}
function getLabelColorObject(color: LabelColor) {
if (labelColorObjects[color]) {
return labelColorObjects[color]
}
const colorObject: LabelColorObject = {
colorName: 'Custom',
text: color,
border: color + '66',
background: color + '0D',
}
return colorObject
}
function LabelColorIcon(props: { color: string }): JSX.Element {
return (
<Box

View File

@ -1,11 +1,11 @@
import AutosizeInput from 'react-input-autosize'
import { Box, SpanBox } from './LayoutPrimitives'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { Label } from '../../lib/networking/fragments/labelFragment'
import { useGetLabelsQuery } from '../../lib/networking/queries/useGetLabelsQuery'
import { LabelChip } from './LabelChip'
import { isTouchScreenDevice } from '../../lib/deviceType'
import { EditLabelLabelChip } from './EditLabelChip'
import { LabelsDispatcher } from '../../lib/hooks/useSetPageLabels'
type LabelsPickerProps = {
selectedLabels: Label[]
@ -16,7 +16,7 @@ type LabelsPickerProps = {
clearInputState: () => void
onFocus?: () => void
setSelectedLabels: (labels: Label[]) => void
dispatchLabels: LabelsDispatcher
deleteLastLabel: () => void
selectOrCreateLabel: (value: string) => void
@ -33,32 +33,42 @@ type LabelsPickerProps = {
export const LabelsPicker = (props: LabelsPickerProps): JSX.Element => {
const inputRef = useRef<HTMLInputElement | null>()
const availableLabels = useGetLabelsQuery()
const {
focused,
inputValue,
tabCount,
tabStartValue,
selectedLabels,
setInputValue,
setTabCount,
setTabStartValue,
} = props
useEffect(() => {
if (!isTouchScreenDevice() && props.focused && inputRef.current) {
if (!isTouchScreenDevice() && focused && inputRef.current) {
inputRef.current.focus()
}
}, [props.focused])
}, [focused])
const autoComplete = useCallback(() => {
const lowerCasedValue = props.inputValue.toLowerCase()
const lowerCasedValue = inputValue.toLowerCase()
if (lowerCasedValue.length < 1) {
return
}
let _tabCount = props.tabCount
let _tabStartValue = props.tabStartValue.toLowerCase()
let _tabCount = tabCount
let _tabStartValue = tabStartValue.toLowerCase()
if (_tabCount === -1) {
_tabCount = 0
_tabStartValue = lowerCasedValue
props.setTabCount(0)
props.setTabStartValue(lowerCasedValue)
setTabCount(0)
setTabStartValue(lowerCasedValue)
} else {
_tabCount = props.tabCount + 1
props.setTabCount(_tabCount)
_tabCount = tabCount + 1
setTabCount(_tabCount)
}
const matches = availableLabels.labels.filter((l) =>
@ -66,21 +76,29 @@ export const LabelsPicker = (props: LabelsPickerProps): JSX.Element => {
)
if (_tabCount < matches.length) {
props.setInputValue(matches[_tabCount].name)
setInputValue(matches[_tabCount].name)
} else if (matches.length > 0) {
props.setTabCount(0)
props.setInputValue(matches[0].name)
setTabCount(0)
setInputValue(matches[0].name)
}
}, [props.inputValue, availableLabels, props.tabCount, props.tabStartValue])
}, [
inputValue,
availableLabels,
tabCount,
tabStartValue,
setInputValue,
setTabCount,
setTabStartValue,
])
const clearTabState = useCallback(() => {
props.setTabCount(-1)
props.setTabStartValue('')
}, [])
setTabCount(-1)
setTabStartValue('')
}, [setTabCount, setTabStartValue])
const isEmpty = useMemo(() => {
return props.selectedLabels.length === 0 && props.inputValue.length === 0
}, [props.inputValue, props.selectedLabels])
return selectedLabels.length === 0 && inputValue.length === 0
}, [inputValue, selectedLabels])
return (
<Box
@ -129,6 +147,7 @@ export const LabelsPicker = (props: LabelsPickerProps): JSX.Element => {
inputRef.current?.focus()
props.setHighlightLastLabel(false)
inputRef.current?.setSelectionRange(0, inputRef.current?.value.length)
event.preventDefault()
}}
>
{props.selectedLabels.map((label, idx) => (
@ -144,7 +163,10 @@ export const LabelsPicker = (props: LabelsPickerProps): JSX.Element => {
if (idx !== -1) {
const _selectedLabels = props.selectedLabels
_selectedLabels.splice(idx, 1)
props.setSelectedLabels([..._selectedLabels])
props.dispatchLabels({
type: 'SAVE',
labels: [..._selectedLabels],
})
}
}}
/>

View File

@ -2,7 +2,6 @@ import type { ReactNode } from 'react'
import { Dropdown, DropdownOption } from '../elements/DropdownElements'
import { LibraryItemNode } from '../../lib/networking/queries/useGetLibraryItemsQuery'
import { UserBasicData } from '../../lib/networking/queries/useGetViewerQuery'
import { isVipUser } from '../../lib/featureFlag'
export type CardMenuDropdownAction =
| 'mark-read'

View File

@ -1,10 +1,6 @@
import { ReactNode, useMemo, useState } from 'react'
import { HStack, VStack } from './../elements/LayoutPrimitives'
import {
Dropdown,
DropdownOption,
DropdownSeparator,
} from '../elements/DropdownElements'
import { Dropdown, DropdownOption } from '../elements/DropdownElements'
import { StyledText } from '../elements/StyledText'
import { Button } from '../elements/Button'
import { currentThemeName } from '../../lib/themeUpdater'

View File

@ -4,7 +4,7 @@ import type { LinkedItemCardProps } from './CardTypes'
import { CoverImage } from '../../elements/CoverImage'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { useCallback, useMemo, useState } from 'react'
import { useCallback, useState } from 'react'
import { DotsThreeVertical } from 'phosphor-react'
import Link from 'next/link'
import { CardMenu } from '../CardMenu'
@ -104,12 +104,13 @@ export function LibraryGridCard(props: LinkedItemCardProps): JSX.Element {
}
const LibraryGridCardContent = (props: LinkedItemCardProps): JSX.Element => {
const { isChecked, setIsChecked, item } = props
const [menuOpen, setMenuOpen] = useState(false)
const originText = siteName(props.item.originalArticleUrl, props.item.url)
const handleCheckChanged = useCallback(() => {
props.setIsChecked(props.item.id, !props.isChecked)
}, [props.isChecked])
setIsChecked(item.id, !isChecked)
}, [setIsChecked, isChecked])
return (
<>

View File

@ -1,5 +1,5 @@
import { Box, VStack, HStack, SpanBox } from '../../elements/LayoutPrimitives'
import { useCallback, useMemo, useState } from 'react'
import { useMemo, useState } from 'react'
import { CaretDown, CaretUp } from 'phosphor-react'
import { MetaStyle, timeAgo, TitleStyle } from './LibraryCardStyles'
import { styled } from '@stitches/react'

View File

@ -76,12 +76,13 @@ export function LibraryListCard(props: LinkedItemCardProps): JSX.Element {
export function LibraryListCardContent(
props: LinkedItemCardProps
): JSX.Element {
const { isChecked, setIsChecked, item } = props
const [menuOpen, setMenuOpen] = useState(false)
const originText = siteName(props.item.originalArticleUrl, props.item.url)
const handleCheckChanged = useCallback(() => {
props.setIsChecked(props.item.id, !props.isChecked)
}, [props.isChecked])
setIsChecked(item.id, !isChecked)
}, [isChecked, setIsChecked, item])
return (
<>

View File

@ -1,4 +1,4 @@
import { Box, HStack, VStack } from '../elements/LayoutPrimitives'
import { Box, HStack } from '../elements/LayoutPrimitives'
import { OmnivoreNameLogo } from '../elements/images/OmnivoreNameLogo'
import { UserBasicData } from '../../lib/networking/queries/useGetViewerQuery'
import { PrimaryDropdown } from '../templates/PrimaryDropdown'

View File

@ -13,7 +13,7 @@ import * as Progress from '@radix-ui/react-progress'
import { theme } from '../tokens/stitches.config'
import { uploadFileRequestMutation } from '../../lib/networking/mutations/uploadFileMutation'
import axios from 'axios'
import { CheckCircle, File } from 'phosphor-react'
import { File } from 'phosphor-react'
import { showErrorToast } from '../../lib/toastHelpers'
const DragnDropContainer = styled('div', {

View File

@ -1,23 +1,12 @@
import { Separator } from '@radix-ui/react-separator'
import {
ArchiveBox,
Notebook,
Info,
TagSimple,
Trash,
Tray,
Tag,
} from 'phosphor-react'
import { ArchiveBox, Notebook, Info, Trash, Tray, Tag } from 'phosphor-react'
import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticleQuery'
import { Button } from '../../elements/Button'
import { Box, SpanBox } from '../../elements/LayoutPrimitives'
import { TooltipWrapped } from '../../elements/Tooltip'
import { styled, theme } from '../../tokens/stitches.config'
import { useReaderSettings } from '../../../lib/hooks/useReaderSettings'
import { ReaderSettings } from '../../../lib/hooks/useReaderSettings'
import { useRef } from 'react'
import { setLabelsMutation } from '../../../lib/networking/mutations/setLabelsMutation'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { SetLabelsModal } from './SetLabelsModal'
export type ArticleActionsMenuLayout = 'top' | 'side'
@ -25,6 +14,7 @@ type ArticleActionsMenuProps = {
article?: ArticleAttributes
layout: ArticleActionsMenuLayout
showReaderDisplaySettings?: boolean
readerSettings: ReaderSettings
articleActionHandler: (action: string, arg?: unknown) => void
}
@ -45,7 +35,6 @@ const MenuSeparator = (props: MenuSeparatorProps): JSX.Element => {
export function ArticleActionsMenu(
props: ArticleActionsMenuProps
): JSX.Element {
const readerSettings = useReaderSettings()
const displaySettingsButtonRef = useRef<HTMLElement | null>(null)
return (
@ -73,7 +62,7 @@ export function ArticleActionsMenu(
<>
<Button
style="articleActionIcon"
onClick={() => readerSettings.setShowSetLabelsModal(true)}
onClick={() => props.readerSettings.setShowSetLabelsModal(true)}
>
<TooltipWrapped
tooltipContent="Edit labels (l)"
@ -216,30 +205,6 @@ export function ArticleActionsMenu(
<DotsThree size={24} color={theme.colors.readerFont.toString()} />
</Button> */}
</Box>
{props.article && readerSettings.showSetLabelsModal && (
<SetLabelsModal
provider={props.article}
onOpenChange={(open: boolean) => {
readerSettings.setShowSetLabelsModal(false)
}}
onLabelsUpdated={(labels: Label[]) => {
props.articleActionHandler('refreshLabels', labels)
}}
save={async (labels: Label[]) => {
if (props.article?.id) {
const result =
(await setLabelsMutation(
props.article?.id,
labels.map((l) => l.id)
)) ?? []
props.article.labels = result
return Promise.resolve(result)
}
return Promise.resolve(labels)
}}
/>
)}
</>
)
}

View File

@ -12,19 +12,13 @@ import { Button } from '../../elements/Button'
import { useEffect, useState, useRef, useMemo, useCallback } from 'react'
import { ReportIssuesModal } from './ReportIssuesModal'
import { reportIssueMutation } from '../../../lib/networking/mutations/reportIssueMutation'
import {
currentTheme,
updateTheme,
updateThemeLocally,
} from '../../../lib/themeUpdater'
import { updateTheme, updateThemeLocally } from '../../../lib/themeUpdater'
import { ArticleMutations } from '../../../lib/articleActions'
import { LabelChip } from '../../elements/LabelChip'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { Recommendation } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { Avatar } from '../../elements/Avatar'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import Downshift from 'downshift'
import { LabelsPicker } from '../../elements/LabelsPicker'
type ArticleContainerProps = {
viewer: UserBasicData
@ -145,9 +139,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
const updateFontSize = useCallback(
(newFontSize: number) => {
if (fontSize !== newFontSize) {
setFontSize(newFontSize)
}
setFontSize(newFontSize)
},
[setFontSize]
)
@ -155,7 +147,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
useEffect(() => {
setLabels(props.labels)
updateFontSize(props.fontSize ?? 20)
}, [props.labels, props.fontSize])
}, [props.labels, props.fontSize, updateFontSize])
// Listen for preference change events sent from host apps (ios, macos...)
useEffect(() => {

View File

@ -1,9 +1,6 @@
import { useState } from 'react'
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import {
LibraryItem,
ReadableItem,
} from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { ReadableItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import { HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
import { HighlightView } from '../../patterns/HighlightView'

View File

@ -22,12 +22,9 @@ import { NotebookModal } from './NotebookModal'
import { showErrorToast } from '../../../lib/toastHelpers'
import { ArticleMutations } from '../../../lib/articleActions'
import { isTouchScreenDevice } from '../../../lib/deviceType'
import { SetLabelsModal } from './SetLabelsModal'
import { setLabelsForHighlight } from '../../../lib/networking/mutations/setLabelsForHighlight'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import { ReadableItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { useRegisterActions } from 'kbar'
import { SetHighlightLabelsModalPresenter } from './SetLabelsModalPresenter'
type HighlightsLayerProps = {
viewer: UserBasicData
@ -673,18 +670,10 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
if (labelsTarget) {
return (
<SetLabelsModal
provider={labelsTarget}
onOpenChange={function (): void {
setLabelsTarget(undefined)
}}
save={function (labels: Label[]): Promise<Label[] | undefined> {
const result = setLabelsForHighlight(
labelsTarget.id,
labels.map((label) => label.id)
)
return result
}}
<SetHighlightLabelsModalPresenter
highlight={labelsTarget}
highlightId={labelsTarget.id}
onOpenChange={() => setLabelsTarget(undefined)}
/>
)
}

View File

@ -4,27 +4,21 @@ import { theme } from '../../tokens/stitches.config'
import type { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react'
import { BookOpen, PencilLine, X } from 'phosphor-react'
import { SetLabelsModal } from './SetLabelsModal'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { setLabelsForHighlight } from '../../../lib/networking/mutations/setLabelsForHighlight'
import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation'
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
import { diff_match_patch } from 'diff-match-patch'
import { highlightsAsMarkdown } from '../homeFeed/HighlightItem'
import 'react-markdown-editor-lite/lib/index.css'
import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation'
import { v4 as uuidv4 } from 'uuid'
import { nanoid } from 'nanoid'
import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation'
import { HighlightNoteBox, MarkdownNote } from '../../patterns/HighlightNotes'
import { HighlightNoteBox } from '../../patterns/HighlightNotes'
import { HighlightViewItem } from './HighlightViewItem'
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
import { TrashIcon } from '../../elements/images/TrashIcon'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import {
LibraryItem,
ReadableItem,
} from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { ReadableItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { SetHighlightLabelsModalPresenter } from './SetLabelsModalPresenter'
type NotebookProps = {
viewer: UserBasicData
@ -289,6 +283,7 @@ export function Notebook(props: NotebookProps): JSX.Element {
},
[annotations, props.item]
)
return (
<VStack
distribution="start"
@ -385,21 +380,10 @@ export function Notebook(props: NotebookProps): JSX.Element {
/>
)}
{labelsTarget && (
<SetLabelsModal
provider={labelsTarget}
onOpenChange={function (open: boolean): void {
setLabelsTarget(undefined)
}}
onLabelsUpdated={function (labels: Label[]): void {
updateState({})
}}
save={function (labels: Label[]): Promise<Label[] | undefined> {
const result = setLabelsForHighlight(
labelsTarget.id,
labels.map((label) => label.id)
)
return result
}}
<SetHighlightLabelsModalPresenter
highlight={labelsTarget}
highlightId={labelsTarget.id}
onOpenChange={() => setLabelsTarget(undefined)}
/>
)}
{props.showConfirmDeleteNote && (

View File

@ -3,7 +3,7 @@ import {
ModalOverlay,
ModalContent,
} from '../../elements/ModalPrimitives'
import { HStack, SpanBox } from '../../elements/LayoutPrimitives'
import { HStack } from '../../elements/LayoutPrimitives'
import { Button } from '../../elements/Button'
import { StyledText } from '../../elements/StyledText'
import { theme } from '../../tokens/stitches.config'
@ -19,7 +19,6 @@ import 'react-markdown-editor-lite/lib/index.css'
import { Notebook } from './Notebook'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import { ReadableItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { MarkdownNote } from '../../patterns/HighlightNotes'
type NotebookModalProps = {
viewer: UserBasicData
@ -49,7 +48,7 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element {
const handleClose = useCallback(() => {
props.onClose(allAnnotations ?? [], deletedAnnotations ?? [])
}, [allAnnotations, deletedAnnotations])
}, [props, allAnnotations, deletedAnnotations])
const handleAnnotationsChange = useCallback(
(allAnnotations, deletedAnnotations) => {

View File

@ -12,7 +12,7 @@ import {
import { TickedRangeSlider } from '../../elements/TickedRangeSlider'
import { showSuccessToast } from '../../../lib/toastHelpers'
import { ReaderSettings } from '../../../lib/hooks/useReaderSettings'
import { useCallback, useMemo, useState } from 'react'
import { useCallback, useState } from 'react'
import { currentThemeName, updateTheme } from '../../../lib/themeUpdater'
import { LineHeightIncreaseIcon } from '../../elements/images/LineHeightIncreaseIconProps'
import { LineHeightDecreaseIcon } from '../../elements/images/LineHeightDecreaseIcon'
@ -70,6 +70,8 @@ export function ReaderSettingsControl(props: ReaderSettingsProps): JSX.Element {
}
function AdvancedSettings(props: SettingsProps): JSX.Element {
const { readerSettings } = props
return (
<VStack
css={{ width: '100%', minHeight: '320px', p: '10px' }}
@ -122,9 +124,9 @@ function AdvancedSettings(props: SettingsProps): JSX.Element {
</Label>
<SwitchRoot
id="justify-text"
checked={props.readerSettings.justifyText ?? false}
checked={readerSettings.justifyText ?? false}
onCheckedChange={(checked) => {
props.readerSettings.setJustifyText(checked)
readerSettings.setJustifyText(checked)
}}
>
<SwitchThumb />
@ -153,9 +155,9 @@ function AdvancedSettings(props: SettingsProps): JSX.Element {
</Label>
<SwitchRoot
id="high-contrast-text"
checked={props.readerSettings.highContrastText ?? false}
checked={readerSettings.highContrastText ?? false}
onCheckedChange={(checked) => {
props.readerSettings.setHighContrastText(checked)
readerSettings.setHighContrastText(checked)
}}
>
<SwitchThumb />
@ -196,17 +198,18 @@ const Label = styled('label', {
})
function BasicSettings(props: SettingsProps): JSX.Element {
const { readerSettings } = props
return (
<VStack css={{ width: '100%' }}>
<FontControls readerSettings={props.readerSettings} />
<FontControls readerSettings={readerSettings} />
<HorizontalDivider />
<LayoutControls readerSettings={props.readerSettings} />
<LayoutControls readerSettings={readerSettings} />
<HorizontalDivider />
<ThemeSelector {...props} />
<ThemeSelector />
<HorizontalDivider />
@ -228,10 +231,10 @@ function BasicSettings(props: SettingsProps): JSX.Element {
},
}}
onClick={() => {
props.readerSettings.setFontFamily('Inter')
props.readerSettings.setMarginWidth(290)
props.readerSettings.setLineHeight(150)
props.readerSettings.actionHandler('resetReaderSettings')
readerSettings.setFontFamily('Inter')
readerSettings.setMarginWidth(290)
readerSettings.setLineHeight(150)
readerSettings.actionHandler('resetReaderSettings')
showSuccessToast('Reader Preferences Reset', {
position: 'bottom-right',
})
@ -272,6 +275,7 @@ type FontControlsProps = {
}
function FontControls(props: FontControlsProps): JSX.Element {
const { readerSettings } = props
const FontSelect = styled('select', {
pl: '5px',
height: '30px',
@ -281,16 +285,16 @@ function FontControls(props: FontControlsProps): JSX.Element {
fontSize: '12px',
background: '$thBackground',
border: '1px solid $thBorderColor',
fontFamily: props.readerSettings.fontFamily,
fontFamily: readerSettings.fontFamily,
textTransform: 'capitalize',
borderRadius: '4px',
})
const handleFontSizeChange = useCallback(
(value) => {
props.readerSettings.actionHandler('setFontSize', value)
readerSettings.actionHandler('setFontSize', value)
},
[props.readerSettings.actionHandler]
[readerSettings]
)
return (
@ -304,13 +308,13 @@ function FontControls(props: FontControlsProps): JSX.Element {
<FontSelect
css={{ marginLeft: 'auto' }}
tabIndex={-1}
defaultValue={props.readerSettings.fontFamily}
defaultValue={readerSettings.fontFamily}
onChange={(e: React.FormEvent<HTMLSelectElement>) => {
const font = e.currentTarget.value
if (FONT_FAMILIES.indexOf(font) < 0) {
return
}
props.readerSettings.setFontFamily(font)
readerSettings.setFontFamily(font)
}}
>
{FONT_FAMILIES.map((family) => (
@ -329,7 +333,7 @@ function FontControls(props: FontControlsProps): JSX.Element {
style="plainIcon"
css={{ py: '0px', width: '60px' }}
onClick={() => {
props.readerSettings.actionHandler('decrementFontSize')
readerSettings.actionHandler('decrementFontSize')
}}
>
<SpanBox
@ -391,11 +395,13 @@ type LayoutControlsProps = {
}
function LayoutControls(props: LayoutControlsProps): JSX.Element {
const { readerSettings } = props
const handleMarginWidthChange = useCallback(
(value) => {
props.readerSettings.setMarginWidth(value)
readerSettings.setMarginWidth(value)
},
[props.readerSettings.actionHandler, props.readerSettings.setMarginWidth]
[readerSettings]
)
return (
@ -425,10 +431,10 @@ function LayoutControls(props: LayoutControlsProps): JSX.Element {
css={{ py: '0px', width: '60px' }}
onClick={() => {
const newMarginWith = Math.max(
props.readerSettings.marginWidth - 45,
readerSettings.marginWidth - 45,
200
)
props.readerSettings.setMarginWidth(newMarginWith)
readerSettings.setMarginWidth(newMarginWith)
}}
>
<ArrowsHorizontal size={24} color="#969696" />
@ -437,7 +443,7 @@ function LayoutControls(props: LayoutControlsProps): JSX.Element {
min={200}
max={560}
step={45}
value={props.readerSettings.marginWidth}
value={readerSettings.marginWidth}
onChange={handleMarginWidthChange}
/>
<Button
@ -445,10 +451,10 @@ function LayoutControls(props: LayoutControlsProps): JSX.Element {
css={{ py: '0px', width: '60px' }}
onClick={() => {
const newMarginWith = Math.min(
props.readerSettings.marginWidth + 45,
readerSettings.marginWidth + 45,
560
)
props.readerSettings.setMarginWidth(newMarginWith)
readerSettings.setMarginWidth(newMarginWith)
}}
>
<ArrowsInLineHorizontal size={24} color="#969696" />
@ -522,7 +528,7 @@ function LayoutControls(props: LayoutControlsProps): JSX.Element {
)
}
function ThemeSelector(props: ReaderSettingsProps): JSX.Element {
function ThemeSelector(): JSX.Element {
const [currentTheme, setCurrentTheme] = useState(currentThemeName())
return (
<VStack

View File

@ -1,23 +1,17 @@
import { useCallback, useRef, useState, useMemo, useEffect } from 'react'
import Link from 'next/link'
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
import { Button } from '../../elements/Button'
import { StyledText } from '../../elements/StyledText'
import { styled, theme } from '../../tokens/stitches.config'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery'
import {
Check,
Circle,
PencilSimple,
Plus,
WarningCircle,
} from 'phosphor-react'
import { Check, Circle, Plus, WarningCircle } from 'phosphor-react'
import { createLabelMutation } from '../../../lib/networking/mutations/createLabelMutation'
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
import { randomLabelColorHex } from '../../../utils/settings-page/labels/labelColorObjects'
import { useRouter } from 'next/router'
import { LabelsPicker } from '../../elements/LabelsPicker'
import { LabelsDispatcher } from '../../../lib/hooks/useSetPageLabels'
export interface LabelsProvider {
labels?: Label[]
@ -31,9 +25,7 @@ type SetLabelsControlProps = {
clearInputState: () => void
selectedLabels: Label[]
setSelectedLabels: (labels: Label[]) => void
onLabelsUpdated?: (labels: Label[]) => void
dispatchLabels: LabelsDispatcher
tabCount: number
setTabCount: (count: number) => void
@ -49,27 +41,9 @@ type SetLabelsControlProps = {
errorMessage?: string
}
type HeaderProps = {
type HeaderProps = SetLabelsControlProps & {
focused: boolean
resetFocusedIndex: () => void
inputValue: string
setInputValue: (value: string) => void
clearInputState: () => void
selectedLabels: Label[]
setSelectedLabels: (labels: Label[]) => void
tabCount: number
setTabCount: (count: number) => void
tabStartValue: string
setTabStartValue: (value: string) => void
highlightLastLabel: boolean
setHighlightLastLabel: (set: boolean) => void
deleteLastLabel: () => void
selectOrCreateLabel: (value: string) => void
}
const StyledLabel = styled('label', {
@ -93,7 +67,7 @@ function Header(props: HeaderProps): JSX.Element {
inputValue={props.inputValue}
setInputValue={props.setInputValue}
selectedLabels={props.selectedLabels}
setSelectedLabels={props.setSelectedLabels}
dispatchLabels={props.dispatchLabels}
tabCount={props.tabCount}
setTabCount={props.setTabCount}
tabStartValue={props.tabStartValue}
@ -263,6 +237,8 @@ function Footer(props: FooterProps): JSX.Element {
export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
const router = useRouter()
const { inputValue, setInputValue, selectedLabels, setHighlightLastLabel } =
props
const { labels, revalidate } = useGetLabelsQuery()
// Move focus through the labels list on tab or arrow up/down keys
const [focusedIndex, setFocusedIndex] = useState<number | undefined>(
@ -271,22 +247,22 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
useEffect(() => {
setFocusedIndex(undefined)
}, [props.inputValue])
}, [inputValue])
const isSelected = useCallback(
(label: Label): boolean => {
return props.selectedLabels.some((other) => {
return selectedLabels.some((other) => {
return other.id === label.id
})
},
[props.selectedLabels]
[selectedLabels]
)
useEffect(() => {
if (focusedIndex === 0) {
props.setHighlightLastLabel(false)
setHighlightLastLabel(false)
}
}, [focusedIndex])
}, [setHighlightLastLabel, focusedIndex])
const toggleLabel = useCallback(
async (label: Label) => {
@ -298,13 +274,9 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
} else {
newSelectedLabels = [...props.selectedLabels, label]
}
props.setSelectedLabels(newSelectedLabels)
props.dispatchLabels({ type: 'SAVE', labels: newSelectedLabels })
props.provider.labels = newSelectedLabels
if (props.onLabelsUpdated) {
props.onLabelsUpdated(newSelectedLabels)
}
props.clearInputState()
revalidate()
},
@ -317,12 +289,12 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
}
return labels
.filter((label) => {
return label.name.toLowerCase().includes(props.inputValue.toLowerCase())
return label.name.toLowerCase().includes(inputValue.toLowerCase())
})
.sort((left: Label, right: Label) => {
return left.name.localeCompare(right.name)
})
}, [labels, props.inputValue])
}, [labels, inputValue])
const createLabelFromFilterText = useCallback(
async (text: string) => {
@ -336,7 +308,7 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
showErrorToast('Failed to create label', { position: 'bottom-right' })
}
},
[props.inputValue, toggleLabel]
[toggleLabel]
)
const handleKeyDown = useCallback(
@ -352,7 +324,7 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
}
// If the `Create New label` button isn't visible we skip it
// when navigating with the arrow keys
if (focusedIndex === maxIndex && !props.inputValue) {
if (focusedIndex === maxIndex && !inputValue) {
newIndex = maxIndex - 2
}
setFocusedIndex(newIndex)
@ -367,7 +339,7 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
}
// If the `Create New label` button isn't visible we skip it
// when navigating with the arrow keys
if (focusedIndex === maxIndex - 2 && !props.inputValue) {
if (focusedIndex === maxIndex - 2 && !inputValue) {
newIndex = maxIndex
}
setFocusedIndex(newIndex)
@ -379,8 +351,8 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
return
}
if (focusedIndex === maxIndex - 1) {
const _filterText = props.inputValue
props.setInputValue('')
const _filterText = inputValue
setInputValue('')
await createLabelFromFilterText(_filterText)
return
}
@ -393,7 +365,8 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
}
},
[
props.inputValue,
inputValue,
setInputValue,
filteredLabels,
focusedIndex,
createLabelFromFilterText,
@ -412,12 +385,13 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
}}
>
<Header
provider={props.provider}
focused={focusedIndex === undefined}
resetFocusedIndex={() => setFocusedIndex(undefined)}
inputValue={props.inputValue}
setInputValue={props.setInputValue}
inputValue={inputValue}
setInputValue={setInputValue}
selectedLabels={props.selectedLabels}
setSelectedLabels={props.setSelectedLabels}
dispatchLabels={props.dispatchLabels}
tabCount={props.tabCount}
setTabCount={props.setTabCount}
tabStartValue={props.tabStartValue}
@ -472,7 +446,7 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element {
))}
</VStack>
<Footer
filterText={props.inputValue}
filterText={inputValue}
focused={focusedIndex === filteredLabels.length + 1}
/>
</VStack>

View File

@ -13,17 +13,20 @@ import { showSuccessToast } from '../../../lib/toastHelpers'
import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery'
import { v4 as uuidv4 } from 'uuid'
import { randomLabelColorHex } from '../../../utils/settings-page/labels/labelColorObjects'
import { LabelsDispatcher } from '../../../lib/hooks/useSetPageLabels'
type SetLabelsModalProps = {
provider: LabelsProvider
onLabelsUpdated?: (labels: Label[]) => void
onOpenChange: (open: boolean) => void
save: (labels: Label[]) => Promise<Label[] | undefined>
selectedLabels: Label[]
dispatchLabels: LabelsDispatcher
}
export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
const [inputValue, setInputValue] = useState('')
const { selectedLabels, dispatchLabels } = props
const availableLabels = useGetLabelsQuery()
const [tabCount, setTabCount] = useState(-1)
const [tabStartValue, setTabStartValue] = useState('')
@ -33,24 +36,6 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
const errorTimeoutRef = useRef<NodeJS.Timeout | undefined>()
const [highlightLastLabel, setHighlightLastLabel] = useState(false)
const [selectedLabels, setSelectedLabels] = useState(
props.provider.labels ?? []
)
const containsTemporaryLabel = (labels: Label[]) => {
return !!labels.find((l) => '_temporary' in l)
}
const onOpenChange = useCallback(
(open: boolean) => {
;(async () => {
await props.save(selectedLabels)
props.onOpenChange(open)
})()
},
[props, selectedLabels]
)
const showMessage = useCallback(
(msg: string, timeout?: number) => {
if (errorTimeoutRef.current) {
@ -83,14 +68,14 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
if (inputValue.length > 0) {
setHighlightLastLabel(false)
}
}, [inputValue, showMessage])
}, [errorMessage, inputValue, showMessage])
const clearInputState = useCallback(() => {
setTabCount(-1)
setInputValue('')
setTabStartValue('')
setHighlightLastLabel(false)
}, [tabCount, tabStartValue, highlightLastLabel])
}, [])
const createLabelAsync = useCallback(
(newLabels: Label[], tempLabel: Label) => {
@ -107,20 +92,23 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
})
if (idx !== -1) {
currentLabels[idx] = newLabel
setSelectedLabels([...currentLabels])
dispatchLabels({ type: 'SAVE', labels: [...currentLabels] })
} else {
setSelectedLabels([...currentLabels, newLabel])
dispatchLabels({
type: 'SAVE',
labels: [...currentLabels, newLabel],
})
}
} else {
showMessage(`Error creating label ${tempLabel.name}`, 5000)
if (idx !== -1) {
currentLabels.splice(idx, 1)
setSelectedLabels([...currentLabels])
dispatchLabels({ type: 'SAVE', labels: [...currentLabels] })
}
}
})()
},
[selectedLabels]
[dispatchLabels, showMessage]
)
const selectOrCreateLabel = useCallback(
@ -140,7 +128,7 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
(l) => l.name.toLowerCase() == lowerCasedValue
)
if (!isAdded) {
setSelectedLabels([...current, existing])
dispatchLabels({ type: 'SAVE', labels: [...current, existing] })
clearInputState()
} else {
showMessage(`label ${value} already added.`, 5000)
@ -152,10 +140,9 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
color: randomLabelColorHex(),
description: '',
createdAt: new Date(),
_temporary: true,
}
const newLabels = [...current, tempLabel]
setSelectedLabels(newLabels)
dispatchLabels({ type: 'TEMP', labels: newLabels })
clearInputState()
createLabelAsync(newLabels, tempLabel)
@ -164,6 +151,7 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
[
availableLabels,
selectedLabels,
dispatchLabels,
clearInputState,
createLabelAsync,
showMessage,
@ -174,23 +162,15 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
if (highlightLastLabel) {
const current = selectedLabels
current.pop()
setSelectedLabels([...current])
dispatchLabels({ type: 'SAVE', labels: [...current] })
setHighlightLastLabel(false)
} else {
setHighlightLastLabel(true)
}
}, [highlightLastLabel, selectedLabels])
useEffect(() => {
if (!containsTemporaryLabel(selectedLabels)) {
;(async () => {
await props.save(selectedLabels)
})()
}
}, [props.save, selectedLabels])
}, [highlightLastLabel, selectedLabels, dispatchLabels])
return (
<ModalRoot defaultOpen onOpenChange={onOpenChange}>
<ModalRoot defaultOpen onOpenChange={props.onOpenChange}>
<ModalOverlay />
<ModalContent
css={{
@ -199,21 +179,20 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element {
}}
onPointerDownOutside={(event) => {
event.preventDefault()
onOpenChange(false)
props.onOpenChange(false)
}}
>
<VStack distribution="start" css={{ height: '100%' }}>
<SpanBox css={{ pt: '0px', px: '16px', width: '100%' }}>
<ModalTitleBar title="Labels" onOpenChange={onOpenChange} />
<ModalTitleBar title="Labels" onOpenChange={props.onOpenChange} />
</SpanBox>
<SetLabelsControl
provider={props.provider}
inputValue={inputValue}
setInputValue={setInputValue}
clearInputState={clearInputState}
selectedLabels={selectedLabels}
setSelectedLabels={setSelectedLabels}
onLabelsUpdated={props.onLabelsUpdated}
selectedLabels={props.selectedLabels}
dispatchLabels={props.dispatchLabels}
tabCount={tabCount}
setTabCount={setTabCount}
tabStartValue={tabStartValue}

View File

@ -0,0 +1,61 @@
import { useEffect } from 'react'
import { useSetPageLabels } from '../../../lib/hooks/useSetPageLabels'
import { LabelsProvider } from './SetLabelsControl'
import { SetLabelsModal } from './SetLabelsModal'
import { useSetHighlightLabels } from '../../../lib/hooks/useSetHighlightLabels'
type SetPageLabelsModalPresenterProps = {
articleId: string
article: LabelsProvider
onOpenChange: (open: boolean) => void
}
export function SetPageLabelsModalPresenter(
props: SetPageLabelsModalPresenterProps
): JSX.Element {
const [labels, dispatchLabels] = useSetPageLabels(props.articleId)
useEffect(() => {
dispatchLabels({
type: 'RESET',
labels: props.article.labels ?? [],
})
}, [props.article, dispatchLabels])
return (
<SetLabelsModal
provider={props.article}
selectedLabels={labels.labels}
dispatchLabels={dispatchLabels}
onOpenChange={props.onOpenChange}
/>
)
}
type SetHighlightLabelsModalPresenterProps = {
highlightId: string
highlight: LabelsProvider
onOpenChange: (open: boolean) => void
}
export function SetHighlightLabelsModalPresenter(
props: SetHighlightLabelsModalPresenterProps
): JSX.Element {
const [labels, dispatchLabels] = useSetHighlightLabels(props.highlightId)
useEffect(() => {
dispatchLabels({
type: 'RESET',
labels: props.highlight.labels ?? [],
})
}, [props.highlight, dispatchLabels])
return (
<SetLabelsModal
provider={props.highlight}
selectedLabels={labels.labels}
dispatchLabels={dispatchLabels}
onOpenChange={props.onOpenChange}
/>
)
}

View File

@ -2,7 +2,6 @@ import {
ArchiveBox,
DotsThreeOutline,
Info,
TagSimple,
TextAa,
Trash,
Tray,

View File

@ -1,6 +1,4 @@
import { Item } from '@radix-ui/react-dropdown-menu'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { DotsThreeVertical } from 'phosphor-react'
import { useCallback } from 'react'
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
@ -12,7 +10,7 @@ import {
DropdownOption,
DropdownSeparator,
} from '../../elements/DropdownElements'
import { Box, SpanBox } from '../../elements/LayoutPrimitives'
import { Box } from '../../elements/LayoutPrimitives'
import { styled, theme } from '../../tokens/stitches.config'

View File

@ -12,8 +12,6 @@ import {
PageType,
State,
} from '../../../lib/networking/fragments/articleFragment'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { setLabelsMutation } from '../../../lib/networking/mutations/setLabelsMutation'
import {
SearchItem,
TypeaheadSearchItemsData,
@ -33,7 +31,6 @@ import { StyledText } from '../../elements/StyledText'
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
import { LinkedItemCardAction } from '../../patterns/LibraryCards/CardTypes'
import { LinkedItemCard } from '../../patterns/LibraryCards/LinkedItemCard'
import { SetLabelsModal } from '../article/SetLabelsModal'
import { Box, HStack, VStack } from './../../elements/LayoutPrimitives'
import { AddLinkModal } from './AddLinkModal'
import { EditLibraryItemModal } from './EditItemModals'
@ -45,6 +42,7 @@ import { UploadModal } from '../UploadModal'
import { BulkAction } from '../../../lib/networking/mutations/bulkActionMutation'
import { bulkActionMutation } from '../../../lib/networking/mutations/bulkActionMutation'
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
import { SetPageLabelsModalPresenter } from '../article/SetLabelsModalPresenter'
export type LayoutType = 'LIST_LAYOUT' | 'GRID_LAYOUT'
export type LibraryMode = 'reads' | 'highlights'
@ -1005,23 +1003,9 @@ function LibraryItemsLayout(props: LibraryItemsLayoutProps): JSX.Element {
/>
)}
{props.labelsTarget?.node.id && (
<SetLabelsModal
provider={props.labelsTarget.node}
onLabelsUpdated={(labels: Label[]) => {
if (props.labelsTarget) {
props.labelsTarget.node.labels = labels
updateState({})
}
}}
save={(labels: Label[]) => {
if (props.labelsTarget?.node.id) {
return setLabelsMutation(
props.labelsTarget.node.id,
labels.map((label) => label.id)
)
}
return Promise.resolve(undefined)
}}
<SetPageLabelsModalPresenter
articleId={props.labelsTarget.node.id}
article={props.labelsTarget.node}
onOpenChange={() => {
if (props.labelsTarget) {
const activate = props.labelsTarget

View File

@ -418,20 +418,6 @@ function MultiSelectControlButtonBox(
/>
<SpanBox css={{ '@lgDown': { display: 'none' } }}>Archive</SpanBox>
</Button>
{/* <Button
style="outline"
onClick={(e) => {
props.performMultiSelectAction(BulkAction.ADD_LABELS)
e.preventDefault()
}}
>
<TagSimple
width={20}
height={20}
color={theme.colors.thTextContrast2.toString()}
/>
<SpanBox css={{ '@lgDown': { display: 'none' } }}>Label</SpanBox>
</Button> */}
<Button
style="outline"
onClick={(e) => {

View File

@ -0,0 +1,69 @@
import { useReducer } from 'react'
import { Label } from '../networking/fragments/labelFragment'
import { showErrorToast } from '../toastHelpers'
import { setLabelsForHighlight } from '../networking/mutations/setLabelsForHighlight'
export type LabelAction = 'RESET' | 'TEMP' | 'SAVE'
export type LabelsDispatcher = (action: {
type: LabelAction
labels: Label[]
}) => void
export const useSetHighlightLabels = (
highlightId?: string
): [{ labels: Label[] }, LabelsDispatcher] => {
const labelsReducer = (
state: {
labels: Label[]
},
action: {
type: string
labels: Label[]
}
) => {
switch (action.type) {
case 'RESET': {
return {
labels: action.labels,
}
}
case 'TEMP': {
return {
labels: action.labels,
}
}
case 'SAVE': {
const labelIds = action.labels.map((l) => l.id)
if (highlightId) {
;(async () => {
const result = await setLabelsForHighlight(highlightId, labelIds)
if (result) {
dispatchLabels({
type: 'RESET',
// Use original list so we don't reorder
labels: action.labels ?? [],
})
} else {
showErrorToast('Error saving labels', {
position: 'bottom-right',
})
}
})()
} else {
showErrorToast('Unable to update labels')
}
return {
labels: action.labels,
}
}
default:
return state
}
}
const [labels, dispatchLabels] = useReducer(labelsReducer, {
labels: [],
})
return [labels, dispatchLabels]
}

View File

@ -0,0 +1,71 @@
import { useReducer } from 'react'
import { setLabelsMutation } from '../networking/mutations/setLabelsMutation'
import { Label } from '../networking/fragments/labelFragment'
import { showErrorToast } from '../toastHelpers'
export type LabelAction = 'RESET' | 'TEMP' | 'SAVE'
export type LabelsDispatcher = (action: {
type: LabelAction
labels: Label[]
}) => void
export const useSetPageLabels = (
articleId?: string
): [{ labels: Label[] }, LabelsDispatcher] => {
const labelsReducer = (
state: {
labels: Label[]
},
action: {
type: string
labels: Label[]
}
) => {
switch (action.type) {
case 'RESET': {
return {
labels: action.labels,
}
}
case 'TEMP': {
return {
labels: action.labels,
}
}
case 'SAVE': {
const labelIds = action.labels.map((l) => l.id)
if (articleId) {
;(async () => {
const result = await setLabelsMutation(articleId, labelIds)
if (result) {
dispatchLabels({
type: 'RESET',
// Use the original labels value here so we dont re-order
labels: action.labels ?? [],
})
} else {
showErrorToast('Error saving labels', {
position: 'bottom-right',
})
}
})()
} else {
showErrorToast('Unable to update labels', {
position: 'bottom-right',
})
}
return {
labels: action.labels,
}
}
default:
return state
}
}
const [labels, dispatchLabels] = useReducer(labelsReducer, {
labels: [],
})
return [labels, dispatchLabels]
}

View File

@ -12,11 +12,10 @@ import {
UpdateTitleEvent,
} from './../../../components/templates/article/ArticleContainer'
import { PdfArticleContainerProps } from './../../../components/templates/article/PdfArticleContainer'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
import { navigationCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts'
import dynamic from 'next/dynamic'
import { webBaseURL } from '../../../lib/appConfig'
import { Toaster } from 'react-hot-toast'
import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation'
import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation'
@ -36,12 +35,12 @@ import { SkeletonArticleContainer } from '../../../components/templates/article/
import { useRegisterActions } from 'kbar'
import { deleteLinkMutation } from '../../../lib/networking/mutations/deleteLinkMutation'
import { ConfirmationModal } from '../../../components/patterns/ConfirmationModal'
import { setLabelsMutation } from '../../../lib/networking/mutations/setLabelsMutation'
import { ReaderHeader } from '../../../components/templates/reader/ReaderHeader'
import { EditArticleModal } from '../../../components/templates/homeFeed/EditItemModals'
import { VerticalArticleActionsMenu } from '../../../components/templates/article/VerticalArticleActions'
import { PdfHeaderSpacer } from '../../../components/templates/article/PdfHeaderSpacer'
import { EpubContainerProps } from '../../../components/templates/article/EpubContainer'
import { useSetPageLabels } from '../../../lib/hooks/useSetPageLabels'
const PdfArticleContainerNoSSR = dynamic<PdfArticleContainerProps>(
() => import('./../../../components/templates/article/PdfArticleContainer'),
@ -56,8 +55,6 @@ const EpubContainerNoSSR = dynamic<EpubContainerProps>(
export default function Home(): JSX.Element {
const router = useRouter()
const { cache, mutate } = useSWRConfig()
const { slug } = router.query
const [showEditModal, setShowEditModal] = useState(false)
const [showHighlightsModal, setShowHighlightsModal] = useState(false)
const { viewerData } = useGetViewerQuery()
@ -69,12 +66,12 @@ export default function Home(): JSX.Element {
includeFriendsHighlights: false,
})
const article = articleData?.article.article
const [labels, setLabels] = useState<Label[]>([])
useEffect(() => {
if (article?.labels) {
setLabels(article.labels)
}
}, [article])
dispatchLabels({
type: 'RESET',
labels: article?.labels ?? [],
})
}, [articleData?.article.article])
useKeyboardShortcuts(navigationCommands(router))
@ -150,7 +147,10 @@ export default function Home(): JSX.Element {
}
break
case 'refreshLabels':
setLabels(arg as Label[])
dispatchLabels({
type: 'RESET',
labels: arg as Label[],
})
break
case 'showHighlights':
setShowHighlightsModal(true)
@ -364,6 +364,8 @@ export default function Home(): JSX.Element {
[readerSettings]
)
const [labels, dispatchLabels] = useSetPageLabels(article?.id)
if (articleFetchError && articleFetchError.indexOf('NOT_FOUND') > -1) {
router.push('/404')
return <LoadingView />
@ -377,6 +379,7 @@ export default function Home(): JSX.Element {
article={article}
layout="top"
showReaderDisplaySettings={article?.contentReader != 'PDF'}
readerSettings={readerSettings}
articleActionHandler={actionHandler}
/>
}
@ -430,6 +433,7 @@ export default function Home(): JSX.Element {
<ArticleActionsMenu
article={article}
layout="side"
readerSettings={readerSettings}
showReaderDisplaySettings={true}
articleActionHandler={actionHandler}
/>
@ -467,7 +471,7 @@ export default function Home(): JSX.Element {
margin={readerSettings.marginWidth}
lineHeight={readerSettings.lineHeight}
fontFamily={readerSettings.fontFamily}
labels={labels}
labels={labels.labels}
showHighlightsModal={showHighlightsModal}
setShowHighlightsModal={setShowHighlightsModal}
justifyText={readerSettings.justifyText ?? undefined}
@ -523,15 +527,8 @@ export default function Home(): JSX.Element {
{article && readerSettings.showSetLabelsModal && (
<SetLabelsModal
provider={article}
onLabelsUpdated={(labels: Label[]) => {
actionHandler('refreshLabels', labels)
}}
save={(labels: Label[]) => {
return setLabelsMutation(
article.linkId,
labels.map((label) => label.id)
)
}}
selectedLabels={labels.labels}
dispatchLabels={dispatchLabels}
onOpenChange={() => readerSettings.setShowSetLabelsModal(false)}
/>
)}