Remove some unused code
This commit is contained in:
@ -1,16 +1,4 @@
|
||||
import { config } from '../../tokens/stitches.config'
|
||||
|
||||
type PenWithColorProps = {
|
||||
color?: string
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
|
||||
export function PenWithColorIcon({
|
||||
color,
|
||||
height,
|
||||
width,
|
||||
}: PenWithColorProps): JSX.Element {
|
||||
export function PenWithColorIcon(): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
width="24"
|
||||
|
||||
@ -10,8 +10,6 @@ export type CardMenuDropdownAction =
|
||||
| 'archive'
|
||||
| 'unarchive'
|
||||
| 'delete'
|
||||
| 'share'
|
||||
| 'snooze'
|
||||
| 'set-labels'
|
||||
| 'showOriginal'
|
||||
| 'unsubscribe'
|
||||
@ -52,20 +50,6 @@ export function CardMenu(props: CardMenuProps): JSX.Element {
|
||||
onSelect={() => props.actionHandler('editTitle')}
|
||||
title="Edit Metadata"
|
||||
/>
|
||||
{isVipUser(props.viewer) && (
|
||||
<DropdownOption
|
||||
onSelect={() => {
|
||||
props.actionHandler('snooze')
|
||||
}}
|
||||
title="Snooze"
|
||||
/>
|
||||
)}
|
||||
{/* <DropdownOption
|
||||
onSelect={() => {
|
||||
props.actionHandler('share')
|
||||
}}
|
||||
title="Share"
|
||||
/> */}
|
||||
{props.item.readingProgressPercent < 98 ? (
|
||||
<DropdownOption
|
||||
onSelect={() => {
|
||||
|
||||
@ -11,8 +11,6 @@ export type LinkedItemCardAction =
|
||||
| 'delete'
|
||||
| 'mark-read'
|
||||
| 'mark-unread'
|
||||
| 'share'
|
||||
| 'snooze'
|
||||
| 'set-labels'
|
||||
| 'unsubscribe'
|
||||
| 'update-item'
|
||||
|
||||
@ -4,12 +4,9 @@ import { DropdownMenu, HeaderDropdownAction } from './../patterns/DropdownMenu'
|
||||
import { updateTheme } from '../../lib/themeUpdater'
|
||||
import { AvatarDropdown } from './../elements/AvatarDropdown'
|
||||
import { ThemeId } from './../tokens/stitches.config'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useKeyboardShortcuts } from '../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { primaryCommands } from '../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { UserBasicData } from '../../lib/networking/queries/useGetViewerQuery'
|
||||
import { setupAnalytics } from '../../lib/analytics'
|
||||
|
||||
type HeaderProps = {
|
||||
user?: UserBasicData
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { Separator } from '@radix-ui/react-separator'
|
||||
import {
|
||||
ArchiveBox,
|
||||
DotsThree,
|
||||
HighlighterCircle,
|
||||
TagSimple,
|
||||
TextAa,
|
||||
Trash,
|
||||
Tray,
|
||||
} from 'phosphor-react'
|
||||
@ -14,7 +12,6 @@ import { Dropdown } from '../../elements/DropdownElements'
|
||||
import { Box, SpanBox } from '../../elements/LayoutPrimitives'
|
||||
import { TooltipWrapped } from '../../elements/Tooltip'
|
||||
import { styled, theme } from '../../tokens/stitches.config'
|
||||
import { SetLabelsControl } from './SetLabelsControl'
|
||||
import { DisplaySettingsModal } from './DisplaySettingsModal'
|
||||
import { useReaderSettings } from '../../../lib/hooks/useReaderSettings'
|
||||
import { useRef } from 'react'
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
import { useCallback } from 'react'
|
||||
import { CommentIcon } from '../../elements/images/CommentIcon'
|
||||
import { CopyLinkIcon } from '../../elements/images/CopyLinkIcon'
|
||||
import { PostIcon } from '../../elements/images/PostIcon'
|
||||
import { ShareIcon } from '../../elements/images/ShareIcon'
|
||||
import { HStack } from './../../elements/LayoutPrimitives'
|
||||
import { useCopyLink } from '../../../lib/hooks/useCopyLink'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { theme } from './../../tokens/stitches.config'
|
||||
import { StyledText } from './../../elements/StyledText'
|
||||
import { useCanShareNative } from '../../../lib/hooks/useCanShareNative'
|
||||
|
||||
type ArticleHeaderToolbarProps = {
|
||||
articleTitle: string
|
||||
articleShareURL: string
|
||||
hasHighlights: boolean
|
||||
setShowHighlightsModal: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
export function ArticleHeaderToolbar(
|
||||
props: ArticleHeaderToolbarProps
|
||||
): JSX.Element {
|
||||
return (
|
||||
<HStack distribution="between" alignment="center" css={{ gap: '$2' }}>
|
||||
{props.hasHighlights && (
|
||||
<Button
|
||||
style="plainIcon"
|
||||
onClick={() => {
|
||||
if (props.setShowHighlightsModal) {
|
||||
props.setShowHighlightsModal(true)
|
||||
}
|
||||
}}
|
||||
title="Notebook"
|
||||
>
|
||||
<CommentIcon
|
||||
size={24}
|
||||
strokeColor={theme.colors.grayTextContrast.toString()}
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
{/* <Button style="plainIcon" onClick={copyLink} title="Copy Link">
|
||||
<CopyLinkIcon
|
||||
isCompleted={isLinkCopied}
|
||||
strokeColor={theme.colors.grayTextContrast.toString()}
|
||||
/>
|
||||
</Button>
|
||||
{enablePostAction ? (
|
||||
<Button style="plainIcon" onClick={() => console.log('post action')} title="Post to Profile">
|
||||
<PostIcon
|
||||
isCompleted={false}
|
||||
size={24}
|
||||
strokeColor={theme.colors.grayTextContrast.toString()}
|
||||
/>
|
||||
</Button>
|
||||
) : null}
|
||||
<Button style="plainIcon" onClick={() => shareAction()} title="Share">
|
||||
<ShareIcon
|
||||
isCompleted={false}
|
||||
size={24}
|
||||
strokeColor={theme.colors.grayTextContrast.toString()}
|
||||
/>
|
||||
</Button>
|
||||
{isLinkCopied ? (
|
||||
<StyledText style="caption" css={{ m: 0, p: 0 }}>
|
||||
Link Copied
|
||||
</StyledText>
|
||||
) : null} */}
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
@ -5,11 +5,7 @@ import {
|
||||
ModalTitleBar,
|
||||
ModalButtonBar,
|
||||
} from './../../elements/ModalPrimitives'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { CommentIcon } from '../../elements/images/CommentIcon'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { VStack } from '../../elements/LayoutPrimitives'
|
||||
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { StyledTextArea } from '../../elements/StyledTextArea'
|
||||
@ -17,7 +13,6 @@ import { updateHighlightMutation } from '../../../lib/networking/mutations/updat
|
||||
import { readableUpdatedAtMessage } from './../../../lib/dateFormatting'
|
||||
import { useConfirmListener } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { showErrorToast } from '../../../lib/toastHelpers'
|
||||
import { CrossIcon } from '../../elements/images/CrossIcon'
|
||||
|
||||
type HighlightNoteModalProps = {
|
||||
author: string
|
||||
|
||||
@ -1,219 +0,0 @@
|
||||
import {
|
||||
ModalContent,
|
||||
ModalOverlay,
|
||||
ModalRoot,
|
||||
} from '../../elements/ModalPrimitives'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { X, Check } from 'phosphor-react'
|
||||
import { useState } from 'react'
|
||||
import { showErrorToast } from '../../../lib/toastHelpers'
|
||||
|
||||
enum ButtonPosition {
|
||||
Top,
|
||||
Middle,
|
||||
Bottom,
|
||||
Standalone,
|
||||
}
|
||||
|
||||
type SnoozeOptionButtonProps = {
|
||||
title: string
|
||||
position: ButtonPosition
|
||||
onClick: () => void
|
||||
selected?: boolean
|
||||
borderRadius?: string
|
||||
}
|
||||
|
||||
function SnoozeOptionButton(props: SnoozeOptionButtonProps): JSX.Element {
|
||||
let borderRadius = '0px'
|
||||
let borderWidth = '1px'
|
||||
switch (props.position) {
|
||||
case ButtonPosition.Top:
|
||||
borderWidth = '1px'
|
||||
borderRadius = '8px 8px 0px 0px'
|
||||
break
|
||||
case ButtonPosition.Middle:
|
||||
borderWidth = '0px 1px 0px 1px'
|
||||
borderRadius = '0px'
|
||||
break
|
||||
case ButtonPosition.Bottom:
|
||||
borderWidth = '1px'
|
||||
borderRadius = '0px 0px 8px 8px'
|
||||
break
|
||||
case ButtonPosition.Standalone:
|
||||
borderWidth = '1px'
|
||||
borderRadius = '8px'
|
||||
break
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
style="modalOption"
|
||||
onClick={props.onClick}
|
||||
css={{
|
||||
borderRadius,
|
||||
borderWidth,
|
||||
background: props.selected ? '#FDFAEC' : undefined,
|
||||
}}
|
||||
>
|
||||
<HStack
|
||||
css={{
|
||||
pl: '16px',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<SpanBox>{props.title}</SpanBox>
|
||||
{props.selected && <Check width={24} height={24} color="#E2B513" />}
|
||||
</HStack>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export function SnoozeLinkModal(props: ShareArticleModalProps): JSX.Element {
|
||||
const [sendReminder, setSendReminder] = useState(false)
|
||||
const [snoozeOption, setSnoozeOption] = useState<string | undefined>(
|
||||
undefined
|
||||
)
|
||||
|
||||
const setOption = (option: string) => {
|
||||
setSnoozeOption(option)
|
||||
setSendReminder(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalRoot defaultOpen onOpenChange={props.onOpenChange}>
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
onPointerDownOutside={(event) => {
|
||||
event.preventDefault()
|
||||
}}
|
||||
css={{
|
||||
m: '0px',
|
||||
p: '0px',
|
||||
width: '375px',
|
||||
height: '388px',
|
||||
overflow: 'auto',
|
||||
background: 'white',
|
||||
}}
|
||||
>
|
||||
<VStack css={{ px: '24px', pt: '22px', m: '0px' }}>
|
||||
<HStack
|
||||
alignment="start"
|
||||
distribution="end"
|
||||
css={{ pb: '16px', width: '100%' }}
|
||||
>
|
||||
<StyledText
|
||||
css={{ fontSize: '24px', m: '0px', mr: '0px', color: '#0A0806' }}
|
||||
>
|
||||
Snooze
|
||||
</StyledText>
|
||||
<Button
|
||||
style="ghost"
|
||||
onClick={() => {
|
||||
props.onOpenChange(false)
|
||||
}}
|
||||
tabIndex={-1}
|
||||
css={{ marginLeft: 'auto', p: '0px' }}
|
||||
>
|
||||
<X color="black" width={24} height={24} />
|
||||
</Button>
|
||||
</HStack>
|
||||
<VStack
|
||||
css={{ width: '100%', background: '#F8F8F8', borderRadius: '8px' }}
|
||||
>
|
||||
<SnoozeOptionButton
|
||||
title="Snooze until tonight"
|
||||
position={ButtonPosition.Top}
|
||||
selected={snoozeOption == 'tonight'}
|
||||
onClick={() => setOption('tonight')}
|
||||
/>
|
||||
<SnoozeOptionButton
|
||||
title="Snooze until tomorrow"
|
||||
position={ButtonPosition.Middle}
|
||||
selected={snoozeOption == 'tomorrow'}
|
||||
onClick={() => setOption('tomorrow')}
|
||||
/>
|
||||
<SnoozeOptionButton
|
||||
title="Snooze until the weekend"
|
||||
position={ButtonPosition.Bottom}
|
||||
selected={snoozeOption == 'weekend'}
|
||||
onClick={() => setOption('weekend')}
|
||||
/>
|
||||
</VStack>
|
||||
|
||||
<Box css={{ mt: '16px', width: '100%', background: '#F8F8F8' }}>
|
||||
<SnoozeOptionButton
|
||||
title="Send me a reminder"
|
||||
position={ButtonPosition.Standalone}
|
||||
selected={sendReminder}
|
||||
onClick={() => {
|
||||
setSendReminder(!sendReminder)
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<HStack
|
||||
css={{ mt: '16px', justifyContent: 'space-between', width: '100%' }}
|
||||
>
|
||||
<Button
|
||||
title="Cancel"
|
||||
css={{
|
||||
fontSize: '16px',
|
||||
width: '158px',
|
||||
height: '52px',
|
||||
background: 'unset',
|
||||
border: 'unset',
|
||||
color: '#0A0806',
|
||||
fontWeight: '400',
|
||||
}}
|
||||
onClick={() => {
|
||||
props.onOpenChange(false)
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
style="ctaDarkYellow"
|
||||
title="Save"
|
||||
css={{
|
||||
fontSize: '16px',
|
||||
width: '158px',
|
||||
height: '52px',
|
||||
marginLeft: 'auto',
|
||||
color: '#0A0806',
|
||||
fontWeight: '400',
|
||||
}}
|
||||
onClick={() => {
|
||||
if (snoozeOption) {
|
||||
let msg = 'Link snoozed until '
|
||||
switch (snoozeOption) {
|
||||
case 'tonight':
|
||||
msg += 'tonight.'
|
||||
break
|
||||
case 'tomorrow':
|
||||
msg += 'tomorrow.'
|
||||
break
|
||||
case 'weekend':
|
||||
msg += 'the weekend.'
|
||||
break
|
||||
}
|
||||
props.submit(snoozeOption, sendReminder, msg)
|
||||
props.onOpenChange(false)
|
||||
} else {
|
||||
showErrorToast('No option selected', {
|
||||
position: 'bottom-right',
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</ModalContent>
|
||||
</ModalRoot>
|
||||
)
|
||||
}
|
||||
@ -27,14 +27,8 @@ import {
|
||||
} from '../../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { SnoozeLinkModal } from '../article/SnoozeLinkModal'
|
||||
import {
|
||||
createReminderMutation,
|
||||
ReminderType,
|
||||
} from '../../../lib/networking/mutations/createReminderMutation'
|
||||
import { useFetchMore } from '../../../lib/hooks/useFetchMoreScroll'
|
||||
import { usePersistedState } from '../../../lib/hooks/usePersistedState'
|
||||
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
|
||||
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
|
||||
import { SetLabelsModal } from '../article/SetLabelsModal'
|
||||
import { Label } from '../../../lib/networking/fragments/labelFragment'
|
||||
@ -104,10 +98,6 @@ export function HomeFeedContainer(): JSX.Element {
|
||||
|
||||
const gridContainerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const [snoozeTarget, setSnoozeTarget] = useState<LibraryItem | undefined>(
|
||||
undefined
|
||||
)
|
||||
|
||||
const [labelsTarget, setLabelsTarget] = useState<LibraryItem | undefined>(
|
||||
undefined
|
||||
)
|
||||
@ -338,12 +328,6 @@ export function HomeFeedContainer(): JSX.Element {
|
||||
case 'mark-unread':
|
||||
performActionOnItem('mark-unread', item)
|
||||
break
|
||||
case 'share':
|
||||
setShareTarget(item)
|
||||
break
|
||||
case 'snooze':
|
||||
setSnoozeTarget(item)
|
||||
break
|
||||
case 'set-labels':
|
||||
setLabelsTarget(item)
|
||||
break
|
||||
@ -356,14 +340,8 @@ export function HomeFeedContainer(): JSX.Element {
|
||||
}
|
||||
|
||||
const modalTargetItem = useMemo(() => {
|
||||
return (
|
||||
labelsTarget ||
|
||||
snoozeTarget ||
|
||||
linkToEdit ||
|
||||
linkToRemove ||
|
||||
linkToUnsubscribe
|
||||
)
|
||||
}, [labelsTarget, snoozeTarget, linkToEdit, linkToRemove, linkToUnsubscribe])
|
||||
return labelsTarget || linkToEdit || linkToRemove || linkToUnsubscribe
|
||||
}, [labelsTarget, linkToEdit, linkToRemove, linkToUnsubscribe])
|
||||
|
||||
useKeyboardShortcuts(
|
||||
libraryListCommands((action) => {
|
||||
@ -589,8 +567,6 @@ export function HomeFeedContainer(): JSX.Element {
|
||||
hasData={!!itemsPages}
|
||||
totalItems={itemsPages?.[0].search.pageInfo.totalCount || 0}
|
||||
isValidating={isValidating}
|
||||
snoozeTarget={snoozeTarget}
|
||||
setSnoozeTarget={setSnoozeTarget}
|
||||
labelsTarget={labelsTarget}
|
||||
setLabelsTarget={setLabelsTarget}
|
||||
showAddLinkModal={showAddLinkModal}
|
||||
@ -621,8 +597,6 @@ type HomeFeedContentProps = {
|
||||
totalItems: number
|
||||
isValidating: boolean
|
||||
loadMore: () => void
|
||||
snoozeTarget: LibraryItem | undefined
|
||||
setSnoozeTarget: (target: LibraryItem | undefined) => void
|
||||
labelsTarget: LibraryItem | undefined
|
||||
setLabelsTarget: (target: LibraryItem | undefined) => void
|
||||
showAddLinkModal: boolean
|
||||
@ -1019,39 +993,6 @@ function HomeFeedGrid(props: HomeFeedContentProps): JSX.Element {
|
||||
item={props.linkToEdit as LibraryItem}
|
||||
/>
|
||||
)}
|
||||
{props.snoozeTarget && (
|
||||
<SnoozeLinkModal
|
||||
submit={(option: string, sendReminder: boolean, msg: string) => {
|
||||
if (!props.snoozeTarget) return
|
||||
createReminderMutation(
|
||||
props.snoozeTarget?.node.id,
|
||||
ReminderType.Tonight,
|
||||
true,
|
||||
sendReminder
|
||||
)
|
||||
.then(() => {
|
||||
return props.actionHandler('archive', props.snoozeTarget)
|
||||
})
|
||||
.then(() => {
|
||||
showSuccessToast(msg, { position: 'bottom-right' })
|
||||
})
|
||||
.catch((error) => {
|
||||
showErrorToast('There was an error snoozing your link.', {
|
||||
position: 'bottom-right',
|
||||
})
|
||||
})
|
||||
}}
|
||||
onOpenChange={() => {
|
||||
if (props.snoozeTarget) {
|
||||
const item = document.getElementById(props.snoozeTarget.node.id)
|
||||
if (item) {
|
||||
item.focus()
|
||||
}
|
||||
props.setSnoozeTarget(undefined)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{showRemoveLinkConfirmation && (
|
||||
<ConfirmationModal
|
||||
richMessage={
|
||||
|
||||
@ -1,38 +1,12 @@
|
||||
import {
|
||||
InputHTMLAttributes,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { ReactNode, useMemo, useState } from 'react'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { SearchIcon } from '../../elements/images/SearchIcon'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
|
||||
import { FormInput } from '../../elements/FormElements'
|
||||
import { searchBarCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { Button, IconButton } from '../../elements/Button'
|
||||
import {
|
||||
Circle,
|
||||
DotsThree,
|
||||
MagnifyingGlass,
|
||||
Plus,
|
||||
Textbox,
|
||||
X,
|
||||
} from 'phosphor-react'
|
||||
import { OmnivoreNameLogo } from '../../elements/images/OmnivoreNameLogo'
|
||||
import { OmnivoreFullLogo } from '../../elements/images/OmnivoreFullLogo'
|
||||
import { AvatarDropdown } from '../../elements/AvatarDropdown'
|
||||
import { ListSelectorIcon } from '../../elements/images/ListSelectorIcon'
|
||||
import { GridSelectorIcon } from '../../elements/images/GridSelectorIcon'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { Circle, DotsThree, Plus } from 'phosphor-react'
|
||||
import { useGetSubscriptionsQuery } from '../../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery'
|
||||
import { Label } from '../../../lib/networking/fragments/labelFragment'
|
||||
import { Checkbox } from '@radix-ui/react-checkbox'
|
||||
import { LayoutType } from './HomeFeedContainer'
|
||||
|
||||
type LibraryFilterMenuProps = {
|
||||
setShowAddLinkModal: (show: boolean) => void
|
||||
@ -237,8 +211,11 @@ type FilterButtonProps = {
|
||||
}
|
||||
|
||||
function FilterButton(props: FilterButtonProps): JSX.Element {
|
||||
const isInboxFilter = (filter: string) => {
|
||||
return filter === '' || filter === 'in:inbox'
|
||||
}
|
||||
const selected = useMemo(() => {
|
||||
if (props.filterTerm === '' && !props.searchTerm) {
|
||||
if (isInboxFilter(props.filterTerm) && !props.searchTerm) {
|
||||
return true
|
||||
}
|
||||
return props.searchTerm === props.filterTerm
|
||||
|
||||
@ -1,30 +1,16 @@
|
||||
import {
|
||||
InputHTMLAttributes,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { SearchIcon } from '../../elements/images/SearchIcon'
|
||||
import { theme, ThemeId } from '../../tokens/stitches.config'
|
||||
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { FormInput } from '../../elements/FormElements'
|
||||
import { searchBarCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { Button, IconButton } from '../../elements/Button'
|
||||
import { MagnifyingGlass, Textbox, X } from 'phosphor-react'
|
||||
import { MagnifyingGlass, X } from 'phosphor-react'
|
||||
import { OmnivoreNameLogo } from '../../elements/images/OmnivoreNameLogo'
|
||||
import { OmnivoreFullLogo } from '../../elements/images/OmnivoreFullLogo'
|
||||
import { AvatarDropdown } from '../../elements/AvatarDropdown'
|
||||
import { ListSelectorIcon } from '../../elements/images/ListSelectorIcon'
|
||||
import { GridSelectorIcon } from '../../elements/images/GridSelectorIcon'
|
||||
import { LayoutType } from './HomeFeedContainer'
|
||||
import { DropdownMenu, HeaderDropdownAction } from '../../patterns/DropdownMenu'
|
||||
import { updateTheme } from '../../../lib/themeUpdater'
|
||||
import { useRouter } from 'next/router'
|
||||
import { PrimaryDropdown } from '../PrimaryDropdown'
|
||||
|
||||
type LibraryHeaderProps = {
|
||||
@ -170,7 +156,7 @@ function SearchBox(props: SearchBoxProps): JSX.Element {
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
{props.searchTerm ? (
|
||||
{searchTerm && searchTerm.length > 0 ? (
|
||||
<Button
|
||||
style="plainIcon"
|
||||
onClick={(event) => {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { styled } from '@stitches/react'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
@ -9,7 +8,10 @@ import { StyledText } from '../../elements/StyledText'
|
||||
import { FormInput } from '../../elements/FormElements'
|
||||
|
||||
import { setIntegrationMutation } from '../../../lib/networking/mutations/setIntegrationMutation'
|
||||
import { Integration, useGetIntegrationsQuery } from '../../../lib/networking/queries/useGetIntegrationsQuery'
|
||||
import {
|
||||
Integration,
|
||||
useGetIntegrationsQuery,
|
||||
} from '../../../lib/networking/queries/useGetIntegrationsQuery'
|
||||
import { useRouter } from 'next/router'
|
||||
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
|
||||
import { deleteIntegrationMutation } from '../../../lib/networking/mutations/deleteIntegrationMutation'
|
||||
@ -22,7 +24,7 @@ const Header = styled(Box, {
|
||||
})
|
||||
|
||||
export function Readwise(): JSX.Element {
|
||||
const { integrations, isValidating, revalidate } = useGetIntegrationsQuery()
|
||||
const { integrations, revalidate } = useGetIntegrationsQuery()
|
||||
const readwiseIntegration = useMemo(() => {
|
||||
return integrations.find((i) => i.type == 'READWISE')
|
||||
}, [integrations])
|
||||
@ -57,23 +59,23 @@ export function Readwise(): JSX.Element {
|
||||
</HStack>
|
||||
|
||||
{readwiseIntegration && (
|
||||
<RemoveReadwiseForm integration={readwiseIntegration} revalidate={revalidate} />
|
||||
)}
|
||||
|
||||
{!readwiseIntegration && (
|
||||
<AddReadwiseForm />
|
||||
<RemoveReadwiseForm
|
||||
integration={readwiseIntegration}
|
||||
revalidate={revalidate}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!readwiseIntegration && <AddReadwiseForm />}
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
function AddReadwiseForm(): JSX.Element {
|
||||
const router = useRouter()
|
||||
|
||||
const [errorMessage, setErrorMessage] =
|
||||
useState<string | undefined>(undefined)
|
||||
const [errorMessage, setErrorMessage] = useState<string | undefined>(
|
||||
undefined
|
||||
)
|
||||
const [token, setToken] = useState<string>('')
|
||||
|
||||
const setReadwiseToken = useCallback(async () => {
|
||||
@ -94,64 +96,64 @@ function AddReadwiseForm(): JSX.Element {
|
||||
}
|
||||
}, [token, router])
|
||||
|
||||
return (<>
|
||||
<HStack
|
||||
css={{
|
||||
fontSize: '18px',
|
||||
color: '$utilityTextDefault',
|
||||
my: '20px',
|
||||
whiteSpace: 'pre-wrap'
|
||||
}}
|
||||
>
|
||||
<SpanBox>Enter your API key from Readwise below. You can get your token{' '}
|
||||
<a
|
||||
target='_blank'
|
||||
rel="noreferrer"
|
||||
referrerPolicy='no-referrer'
|
||||
style={{ color: '$utilityTextDefault' }}
|
||||
href="https://readwise.io/access_token"
|
||||
return (
|
||||
<>
|
||||
<HStack
|
||||
css={{
|
||||
fontSize: '18px',
|
||||
color: '$utilityTextDefault',
|
||||
my: '20px',
|
||||
whiteSpace: 'pre-wrap',
|
||||
}}
|
||||
>
|
||||
here
|
||||
</a>.</SpanBox>
|
||||
</HStack>
|
||||
<SpanBox>
|
||||
Enter your API key from Readwise below. You can get your token{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
referrerPolicy="no-referrer"
|
||||
style={{ color: '$utilityTextDefault' }}
|
||||
href="https://readwise.io/access_token"
|
||||
>
|
||||
here
|
||||
</a>
|
||||
.
|
||||
</SpanBox>
|
||||
</HStack>
|
||||
|
||||
<FormInput
|
||||
type="token"
|
||||
key="token"
|
||||
value={token}
|
||||
placeholder={'Readwise Token'}
|
||||
onChange={(e) => {
|
||||
e.preventDefault()
|
||||
setToken(e.target.value)
|
||||
}}
|
||||
disabled={false}
|
||||
hidden={false}
|
||||
required={true}
|
||||
css={{
|
||||
border: '1px solid $textNonessential',
|
||||
borderRadius: '8px',
|
||||
width: '80%',
|
||||
bg: 'transparent',
|
||||
fontSize: '16px',
|
||||
textIndent: '8px',
|
||||
my: '20px',
|
||||
height: '38px',
|
||||
color: '$grayTextContrast',
|
||||
'&:focus': {
|
||||
outline: 'none',
|
||||
boxShadow: '0px 0px 2px 2px rgba(255, 234, 159, 0.56)',
|
||||
},
|
||||
}}
|
||||
min={200}
|
||||
/>
|
||||
{errorMessage && <StyledText style="error">{errorMessage}</StyledText>}
|
||||
<Button
|
||||
style="ctaDarkYellow"
|
||||
css={{ }}
|
||||
onClick={setReadwiseToken}
|
||||
>
|
||||
Set Token
|
||||
</Button>
|
||||
<FormInput
|
||||
type="token"
|
||||
key="token"
|
||||
value={token}
|
||||
placeholder={'Readwise Token'}
|
||||
onChange={(e) => {
|
||||
e.preventDefault()
|
||||
setToken(e.target.value)
|
||||
}}
|
||||
disabled={false}
|
||||
hidden={false}
|
||||
required={true}
|
||||
css={{
|
||||
border: '1px solid $textNonessential',
|
||||
borderRadius: '8px',
|
||||
width: '80%',
|
||||
bg: 'transparent',
|
||||
fontSize: '16px',
|
||||
textIndent: '8px',
|
||||
my: '20px',
|
||||
height: '38px',
|
||||
color: '$grayTextContrast',
|
||||
'&:focus': {
|
||||
outline: 'none',
|
||||
boxShadow: '0px 0px 2px 2px rgba(255, 234, 159, 0.56)',
|
||||
},
|
||||
}}
|
||||
min={200}
|
||||
/>
|
||||
{errorMessage && <StyledText style="error">{errorMessage}</StyledText>}
|
||||
<Button style="ctaDarkYellow" css={{}} onClick={setReadwiseToken}>
|
||||
Set Token
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -179,19 +181,23 @@ function RemoveReadwiseForm(props: RemoveReadwiseFormProps): JSX.Element {
|
||||
}, [props])
|
||||
|
||||
return (
|
||||
<>
|
||||
<HStack
|
||||
css={{
|
||||
fontSize: '18px',
|
||||
color: '$utilityTextDefault',
|
||||
my: '20px',
|
||||
whiteSpace: 'pre-wrap'
|
||||
}}
|
||||
>
|
||||
<SpanBox>Omnivore is configured to send all your highlights to Readwise.</SpanBox>
|
||||
</HStack>
|
||||
<>
|
||||
<HStack
|
||||
css={{
|
||||
fontSize: '18px',
|
||||
color: '$utilityTextDefault',
|
||||
my: '20px',
|
||||
whiteSpace: 'pre-wrap',
|
||||
}}
|
||||
>
|
||||
<SpanBox>
|
||||
Omnivore is configured to send all your highlights to Readwise.
|
||||
</SpanBox>
|
||||
</HStack>
|
||||
|
||||
<Button style="ctaDarkYellow" onClick={deleteIntegration}>Remove Readwise Integration</Button>
|
||||
</>
|
||||
<Button style="ctaDarkYellow" onClick={deleteIntegration}>
|
||||
Remove Readwise Integration
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import Link from 'next/link'
|
||||
import { Box, HStack, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { GithubLogo, DiscordLogo, TwitterLogo } from 'phosphor-react'
|
||||
import { styled, theme } from '../../tokens/stitches.config'
|
||||
import { HStack, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { styled } from '../../tokens/stitches.config'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
|
||||
const containerStyles = {
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
import { SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
|
||||
import { styled } from '../../tokens/stitches.config'
|
||||
import { Root, Image, Fallback } from '@radix-ui/react-avatar'
|
||||
|
||||
type AvatarProps = {
|
||||
viewer?: UserBasicData
|
||||
}
|
||||
|
||||
export function LibraryAvatar(props: AvatarProps): JSX.Element {
|
||||
return (
|
||||
<VStack alignment="center" distribution="start" css={{ pl: '8px', width: '100%', height: '100%' }}>
|
||||
<VStack css={{ height: '100%' }}>
|
||||
<StyledAvatar
|
||||
css={{
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
borderRadius: '50%',
|
||||
}}
|
||||
>
|
||||
{props.viewer?.profile.pictureUrl
|
||||
? <StyledImage src={props.viewer.profile.pictureUrl} />
|
||||
: <StyledFallback>{props.viewer?.name.charAt(0) ?? ''}</StyledFallback>
|
||||
}
|
||||
</StyledAvatar>
|
||||
</VStack>
|
||||
{/* This spacer is to help align with items in the search box */}
|
||||
<SpanBox css={{ marginTop: 'auto', height: '10px', width: '100%' }} />
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
const StyledAvatar = styled(Root, {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
verticalAlign: 'middle',
|
||||
overflow: 'hidden',
|
||||
userSelect: 'none',
|
||||
})
|
||||
|
||||
const StyledImage = styled(Image, {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
|
||||
'&:hover': {
|
||||
opacity: '48%',
|
||||
},
|
||||
})
|
||||
|
||||
const StyledFallback = styled(Fallback, {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: '16px',
|
||||
fontWeight: '600',
|
||||
color: '$utilityTextDefault',
|
||||
backgroundColor: '$libraryActiveMenuItem',
|
||||
})
|
||||
@ -1,76 +0,0 @@
|
||||
import { HStack, SpanBox, VStack } from './../../elements/LayoutPrimitives'
|
||||
import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { useGetUserPreferences } from '../../../lib/networking/queries/useGetUserPreferences'
|
||||
import { LibraryMenu } from './LibraryMenu'
|
||||
import { LibraryAvatar } from './LibraryAvatar'
|
||||
import { LibrarySearchBar } from './LibrarySearchBar'
|
||||
import { LibraryList } from './LibraryList'
|
||||
import { LibraryHeadline } from './LibraryHeadline'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { LibraryItemsQueryInput } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
|
||||
import { usePersistedState } from '../../../lib/hooks/usePersistedState'
|
||||
|
||||
|
||||
|
||||
export type SearchCoordinator = {
|
||||
applySearch: (searchTerm: string) => void
|
||||
}
|
||||
|
||||
const useSearchCoordinator = () => {
|
||||
const applySearch = useCallback((searchTerm: string) => {
|
||||
console.log('applying search')
|
||||
}, [])
|
||||
|
||||
return {
|
||||
applySearch
|
||||
}
|
||||
}
|
||||
|
||||
export type LibraryLayoutType = 'LIST_LAYOUT' | 'GRID_LAYOUT'
|
||||
|
||||
export type LayoutCoordinator = {
|
||||
layout: LibraryLayoutType
|
||||
setLayout: (type: LibraryLayoutType) => void
|
||||
}
|
||||
|
||||
const useLibraryLayoutCoordinator = () => {
|
||||
const [layout, setLayout] = usePersistedState<LibraryLayoutType>({
|
||||
key: 'libraryLayout',
|
||||
initialValue: 'GRID_LAYOUT',
|
||||
})
|
||||
|
||||
return {
|
||||
layout,
|
||||
setLayout
|
||||
}
|
||||
}
|
||||
|
||||
export function LibraryContainer(): JSX.Element {
|
||||
useGetUserPreferences()
|
||||
|
||||
const { viewerData } = useGetViewerQuery()
|
||||
const searchCoordinator = useSearchCoordinator()
|
||||
const layoutCoordinator = useLibraryLayoutCoordinator()
|
||||
|
||||
return (
|
||||
<>
|
||||
<VStack alignment="start" distribution="start" css={{ width: '100vw', height: '100vh', overflow: 'hidden', bg: '$libraryBackground' }}>
|
||||
<HStack alignment="start" distribution="start" css={{ width: '100%' }}>
|
||||
<SpanBox css={{ width: '100%', height: '90px' }}>
|
||||
<LibrarySearchBar coordinator={searchCoordinator} />
|
||||
</SpanBox>
|
||||
<SpanBox css={{ marginLeft: 'auto', width: '130px', height: '100%' }}>
|
||||
<LibraryAvatar viewer={viewerData?.me} />
|
||||
</SpanBox>
|
||||
</HStack>
|
||||
<HStack alignment="start" distribution="start" css={{ width: '100%', height: '100%' }}>
|
||||
<LibraryMenu />
|
||||
<VStack alignment="start" distribution="start" css={{ width: '100%', height: '100%', mr: '20px' }}>
|
||||
<LibraryHeadline layoutCoordinator={layoutCoordinator} />
|
||||
<LibraryList layoutCoordinator={layoutCoordinator} />
|
||||
</VStack>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
import { HStack, SpanBox } from '../../elements/LayoutPrimitives'
|
||||
import { useGetUserPreferences } from '../../../lib/networking/queries/useGetUserPreferences'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { LibraryListLayoutIcon } from '../../elements/images/LibraryListLayoutIcon'
|
||||
import { LibraryGridLayoutIcon } from '../../elements/images/LibraryGridLayoutIcon'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { LayoutCoordinator, LibraryLayoutType } from './LibraryContainer'
|
||||
import { useCallback } from 'react'
|
||||
import { Plus } from 'phosphor-react'
|
||||
|
||||
export type LibraryHeadlineProps = {
|
||||
layoutCoordinator: LayoutCoordinator
|
||||
}
|
||||
|
||||
export function LibraryHeadline(props: LibraryHeadlineProps): JSX.Element {
|
||||
|
||||
const typeColor = useCallback((type: LibraryLayoutType) => {
|
||||
return (
|
||||
props.layoutCoordinator.layout === type
|
||||
? theme.colors.omnivoreCtaYellow.toString()
|
||||
: "#D6D6D6"
|
||||
)
|
||||
}, [props.layoutCoordinator.layout])
|
||||
|
||||
return (
|
||||
<HStack alignment="center" distribution="start" css={{ pt: '8px', pb: '14px', width: '100%', pr: '15px' }}>
|
||||
<StyledText style="libraryHeader">Home</StyledText>
|
||||
<HStack alignment="center" distribution="start" css={{ marginLeft: 'auto', gap: '8px' }}>
|
||||
<Button style="ctaDarkYellow" css={{ py: '10px', px: '14px', mr: '16px', display: 'flex', alignItems: 'center' }}>
|
||||
<Plus size={16} weight='bold' />
|
||||
<SpanBox css={{ pl: '10px', fontWeight: '600', fontSize: '16px' }}>Add Link</SpanBox>
|
||||
</Button>
|
||||
<Button style="ghost" onClick={() => props.layoutCoordinator.setLayout('LIST_LAYOUT')} css={{ display: 'flex', alignItems: 'center' }}>
|
||||
<LibraryListLayoutIcon color={typeColor('LIST_LAYOUT')} />
|
||||
</Button>
|
||||
<Button style="ghost" onClick={() => props.layoutCoordinator.setLayout('GRID_LAYOUT')} css={{ display: 'flex', alignItems: 'center' }}>
|
||||
<LibraryGridLayoutIcon color={typeColor('GRID_LAYOUT')} />
|
||||
</Button>
|
||||
</HStack>
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
@ -1,143 +0,0 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
import Dropzone from 'react-dropzone'
|
||||
import { Box } from '../../elements/LayoutPrimitives'
|
||||
import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { useGetUserPreferences } from '../../../lib/networking/queries/useGetUserPreferences'
|
||||
import { useGetLibraryItemsQuery } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
|
||||
import { LinkedItemCardAction } from '../../patterns/LibraryCards/CardTypes'
|
||||
import { LibraryGridCard } from '../../patterns/LibraryCards/LibraryGridCard'
|
||||
import { LayoutCoordinator } from './LibraryContainer'
|
||||
import { EmptyLibrary } from '../homeFeed/EmptyLibrary'
|
||||
// import Masonry from 'react-masonry-css'
|
||||
|
||||
export type LibraryListProps = {
|
||||
layoutCoordinator: LayoutCoordinator
|
||||
}
|
||||
|
||||
export function LibraryList(props: LibraryListProps): JSX.Element {
|
||||
useGetUserPreferences()
|
||||
|
||||
const { viewerData } = useGetViewerQuery()
|
||||
|
||||
const defaultQuery = {
|
||||
limit: 50,
|
||||
sortDescending: true,
|
||||
searchQuery: undefined,
|
||||
}
|
||||
|
||||
const { itemsPages, size, setSize, isValidating, performActionOnItem } =
|
||||
useGetLibraryItemsQuery(defaultQuery)
|
||||
|
||||
const [fileNames, setFileNames] = useState([])
|
||||
const [inDragOperation, setInDragOperation] = useState(false)
|
||||
const [uploadingFiles, setUploadingFiles] = useState([])
|
||||
|
||||
const handleDrop = (acceptedFiles: any) => {
|
||||
setFileNames(acceptedFiles.map((file: { name: any }) => file.name))
|
||||
setUploadingFiles(acceptedFiles.map((file: { name: any }) => file.name))
|
||||
}
|
||||
|
||||
const libraryItems = useMemo(() => {
|
||||
const items =
|
||||
itemsPages?.flatMap((ad) => {
|
||||
return ad.search.edges
|
||||
}) || []
|
||||
return items
|
||||
}, [itemsPages, performActionOnItem])
|
||||
|
||||
if (!isValidating && libraryItems.length == 0) {
|
||||
return (
|
||||
<EmptyLibrary
|
||||
onAddLinkClicked={() => {
|
||||
console.log('onAddLinkClicked')
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
// <Box
|
||||
// css={{
|
||||
// border: '3px dashed gray',
|
||||
// backgroundColor: 'aliceblue',
|
||||
// borderRadius: '5px',
|
||||
// position: 'absolute',
|
||||
// opacity: '0.8',
|
||||
// display: 'flex',
|
||||
// justifyContent: 'center',
|
||||
// alignItems: 'center',
|
||||
// padding: '30px',
|
||||
// }}
|
||||
// >
|
||||
|
||||
return (
|
||||
<Box css={{ overflowY: 'scroll', width: '100%' }}>
|
||||
<Box
|
||||
css={{
|
||||
display: 'grid',
|
||||
gridAutoRows: 'auto',
|
||||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||
maxWidth: '1024px',
|
||||
gridGap: '20px',
|
||||
|
||||
// '@smDown': {
|
||||
// border: 'unset',
|
||||
// width:
|
||||
// props.layoutCoordinator.layout == 'LIST_LAYOUT'
|
||||
// ? '100vw'
|
||||
// : undefined,
|
||||
// },
|
||||
// '@md': {
|
||||
// gridTemplateColumns:
|
||||
// props.layoutCoordinator.layout == 'LIST_LAYOUT'
|
||||
// ? 'none'
|
||||
// : '1fr 1fr',
|
||||
// },
|
||||
// '@lg': {
|
||||
// gridTemplateColumns:
|
||||
// props.layoutCoordinator.layout == 'LIST_LAYOUT'
|
||||
// ? 'none'
|
||||
// : 'repeat(3, 1fr)',
|
||||
// },
|
||||
}}
|
||||
>
|
||||
{libraryItems.map((linkedItem) => (
|
||||
<Box
|
||||
className="linkedItemCard"
|
||||
data-testid="linkedItemCard"
|
||||
id={linkedItem.node.id}
|
||||
tabIndex={0}
|
||||
key={linkedItem.node.id}
|
||||
// css={{
|
||||
// width: '100%',
|
||||
// '&> div': {
|
||||
// bg: '$libraryBackground',
|
||||
// },
|
||||
// '&:focus': {
|
||||
// '> div': {
|
||||
// bg: '$grayBgActive',
|
||||
// },
|
||||
// },
|
||||
// '&:hover': {
|
||||
// '> div': {
|
||||
// bg: '$grayBgActive',
|
||||
// },
|
||||
// },
|
||||
// }}
|
||||
>
|
||||
{viewerData?.me && (
|
||||
<LibraryGridCard
|
||||
layout={props.layoutCoordinator.layout}
|
||||
item={linkedItem.node}
|
||||
viewer={viewerData.me}
|
||||
handleAction={(action: LinkedItemCardAction) => {
|
||||
console.log('card clicked')
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
<Box css={{ width: '100%', height: '200px' }} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
import { VStack } from '../../elements/LayoutPrimitives'
|
||||
import { useGetUserPreferences } from '../../../lib/networking/queries/useGetUserPreferences'
|
||||
import { Menubar } from '../Menu'
|
||||
|
||||
export function LibraryMenu(): JSX.Element {
|
||||
useGetUserPreferences()
|
||||
|
||||
return (
|
||||
<VStack
|
||||
alignment="start"
|
||||
distribution="start"
|
||||
css={{
|
||||
width: '286px',
|
||||
minWidth: '286px',
|
||||
pl:'15px',
|
||||
height: 'calc(100% - 100px)',
|
||||
overflowY: 'auto',
|
||||
fontWeight: '600',
|
||||
}}
|
||||
>
|
||||
<Menubar />
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
@ -1,215 +0,0 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Clock, Sliders, X } from 'phosphor-react'
|
||||
import Downshift from 'downshift'
|
||||
|
||||
import { HStack, SpanBox, VStack } from './../../elements/LayoutPrimitives'
|
||||
import { FormInput } from '../../elements/FormElements'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { styled, theme } from '../../tokens/stitches.config'
|
||||
import { SearchCoordinator } from './LibraryContainer'
|
||||
|
||||
// Styles
|
||||
const List = styled('ul', {
|
||||
width: '91%',
|
||||
maxHeight: '400px',
|
||||
overflow: 'auto',
|
||||
top: '65px',
|
||||
left: '-32px',
|
||||
color: 'var(--colors-utilityTextDefault)',
|
||||
backgroundColor: 'var(--colors-grayBase)',
|
||||
position: 'absolute',
|
||||
zIndex: '2',
|
||||
'@smDown': {
|
||||
fontSize: 16,
|
||||
},
|
||||
})
|
||||
|
||||
const Item = styled('li', {
|
||||
listStyleType: 'none',
|
||||
m: '8px',
|
||||
borderRadius: '5px',
|
||||
width: '100%',
|
||||
})
|
||||
|
||||
export type LibrarySearchBarProps = {
|
||||
coordinator: SearchCoordinator
|
||||
}
|
||||
|
||||
export function LibrarySearchBar(props: LibrarySearchBarProps): JSX.Element {
|
||||
const [recentSearches, setRecentSearches] = useState(Array<unknown[]>())
|
||||
|
||||
useEffect(() => {
|
||||
setRecentSearches(Object.values(localStorage))
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Downshift itemToString={(item) => (item ? item : '')}>
|
||||
{({
|
||||
getInputProps,
|
||||
getRootProps,
|
||||
getMenuProps,
|
||||
getItemProps,
|
||||
isOpen,
|
||||
highlightedIndex,
|
||||
inputValue,
|
||||
clearSelection,
|
||||
openMenu,
|
||||
}) => (
|
||||
<VStack
|
||||
alignment="start"
|
||||
distribution="start"
|
||||
css={{ pl: '32px', width: '100%', height: '100%' }}
|
||||
>
|
||||
<HStack
|
||||
alignment="start"
|
||||
distribution="start"
|
||||
css={{ width: '100%', borderBottom: 'solid 1px $grayBorder' }}
|
||||
{...getRootProps({ refKey: 'ref' }, { suppressRefError: true })}
|
||||
>
|
||||
<form
|
||||
style={{ width: '100%' }}
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault()
|
||||
// props.applySearchQuery(searchTerm || '')
|
||||
// inputRef.current?.blur()
|
||||
}}
|
||||
{...getRootProps()}
|
||||
>
|
||||
<FormInput
|
||||
css={{
|
||||
width: '77%',
|
||||
height: '80px',
|
||||
fontSize: '24px',
|
||||
fontFamily: 'Inter',
|
||||
}}
|
||||
type="text"
|
||||
tabIndex={0}
|
||||
value={inputValue}
|
||||
placeholder="Search"
|
||||
onFocus={(event: any) => {
|
||||
event.preventDefault()
|
||||
openMenu()
|
||||
//props.applySearchQuery('')
|
||||
// inputRef.current?.blur()
|
||||
}}
|
||||
onChange={(event: any) => {
|
||||
event.preventDefault()
|
||||
}}
|
||||
{...getInputProps()}
|
||||
/>
|
||||
|
||||
{/* {searchTerm && ( */}
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution="start"
|
||||
css={{
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'right',
|
||||
alignItems: 'center',
|
||||
margin: '-57px 0 10px',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
style="plainIcon"
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
clearSelection()
|
||||
//props.applySearchQuery('')
|
||||
// inputRef.current?.blur()
|
||||
}}
|
||||
css={{
|
||||
mr: '15px',
|
||||
}}
|
||||
>
|
||||
<X
|
||||
width={24}
|
||||
height={24}
|
||||
color={theme.colors.grayTextContrast.toString()}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
style="ctaDarkYellow"
|
||||
type="submit"
|
||||
css={{
|
||||
mr: '15px',
|
||||
}}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
if (inputValue && inputValue.length > 0) {
|
||||
localStorage.setItem(inputValue, inputValue)
|
||||
setRecentSearches(Object.values(localStorage))
|
||||
}
|
||||
// props.applySearchQuery('')
|
||||
// inputRef.current?.blur()
|
||||
}}
|
||||
>
|
||||
Search
|
||||
</Button>
|
||||
{/* )} */}
|
||||
{/* {!searchTerm && ( */}
|
||||
<Button
|
||||
style="plainIcon"
|
||||
onClick={(event) => {
|
||||
// Display the advanced search sheet
|
||||
}}
|
||||
>
|
||||
<Sliders
|
||||
size={24}
|
||||
color={theme.colors.utilityTextDefault.toString()}
|
||||
/>
|
||||
</Button>
|
||||
{/* )} */}
|
||||
</HStack>
|
||||
|
||||
<List>
|
||||
{isOpen &&
|
||||
recentSearches
|
||||
.filter((item) => !inputValue || item.includes(inputValue))
|
||||
.map((item, index) => (
|
||||
<SpanBox
|
||||
{...getMenuProps()}
|
||||
key={item}
|
||||
css={{
|
||||
paddingLeft: '15px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
borderBottom: '1px solid $grayBorder',
|
||||
'& svg': {
|
||||
margin: '10px',
|
||||
},
|
||||
backgroundColor:
|
||||
index === highlightedIndex
|
||||
? 'var(--colors-grayBg)'
|
||||
: 'transparent',
|
||||
}}
|
||||
>
|
||||
<Clock size={20} />
|
||||
<Item
|
||||
{...getItemProps({
|
||||
item,
|
||||
index,
|
||||
})}
|
||||
>
|
||||
{item}
|
||||
</Item>
|
||||
<X
|
||||
width={20}
|
||||
height={20}
|
||||
color={theme.colors.grayTextContrast.toString()}
|
||||
onClick={() => {
|
||||
localStorage.removeItem(`${item}`)
|
||||
setRecentSearches(Object.values(localStorage))
|
||||
}}
|
||||
/>
|
||||
</SpanBox>
|
||||
))}
|
||||
</List>
|
||||
</form>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)}
|
||||
</Downshift>
|
||||
)
|
||||
}
|
||||
@ -1,36 +1,8 @@
|
||||
import {
|
||||
InputHTMLAttributes,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { SearchIcon } from '../../elements/images/SearchIcon'
|
||||
import { theme, ThemeId } from '../../tokens/stitches.config'
|
||||
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
|
||||
import { FormInput } from '../../elements/FormElements'
|
||||
import { searchBarCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { Button, IconButton } from '../../elements/Button'
|
||||
import {
|
||||
DotsThree,
|
||||
DotsThreeOutline,
|
||||
MagnifyingGlass,
|
||||
TextAa,
|
||||
Textbox,
|
||||
X,
|
||||
} from 'phosphor-react'
|
||||
import { HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { DotsThreeOutline, TextAa } from 'phosphor-react'
|
||||
import { OmnivoreNameLogo } from '../../elements/images/OmnivoreNameLogo'
|
||||
import { OmnivoreFullLogo } from '../../elements/images/OmnivoreFullLogo'
|
||||
import { AvatarDropdown } from '../../elements/AvatarDropdown'
|
||||
import { ListSelectorIcon } from '../../elements/images/ListSelectorIcon'
|
||||
import { GridSelectorIcon } from '../../elements/images/GridSelectorIcon'
|
||||
import { DropdownMenu, HeaderDropdownAction } from '../../patterns/DropdownMenu'
|
||||
import { updateTheme } from '../../../lib/themeUpdater'
|
||||
import { useRouter } from 'next/router'
|
||||
import { PrimaryDropdown } from '../PrimaryDropdown'
|
||||
import { TooltipWrapped } from '../../elements/Tooltip'
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import Link from 'next/link'
|
||||
import { Plus, Trash } from 'phosphor-react'
|
||||
import { Trash } from 'phosphor-react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
|
||||
@ -7,7 +6,7 @@ import { MoreOptionsIcon } from '../../elements/images/MoreOptionsIcon'
|
||||
import { InfoLink } from '../../elements/InfoLink'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { styled, theme } from '../../tokens/stitches.config'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { PrimaryLayout } from '../PrimaryLayout'
|
||||
|
||||
type SettingsTableProps = {
|
||||
|
||||
@ -1,44 +1,6 @@
|
||||
import { VStack, Box } from './../components/elements/LayoutPrimitives'
|
||||
import {
|
||||
LandingSectionsContainer,
|
||||
GetStartedButton,
|
||||
} from '../components/templates/landing/LandingSectionsContainer'
|
||||
import { LandingHeader } from '../components/templates/landing/LandingHeader'
|
||||
import { LandingFooter } from '../components/templates/landing/LandingFooter'
|
||||
import { PageMetaData } from '../components/patterns/PageMetaData'
|
||||
import { About } from '../components/templates/About'
|
||||
|
||||
const containerStyles = {
|
||||
alignSelf: 'center',
|
||||
marginTop: 80,
|
||||
maxWidth: 960,
|
||||
px: '2vw',
|
||||
'@md': {
|
||||
px: '6vw',
|
||||
},
|
||||
'@xl': {
|
||||
px: '120px',
|
||||
},
|
||||
}
|
||||
|
||||
const headingStyles = {
|
||||
fontWeight: '700',
|
||||
color: '#3D3D3D',
|
||||
fontSize: 45,
|
||||
lineHeight: '53px',
|
||||
padding: '10px',
|
||||
paddingBottom: '0px',
|
||||
textAlign: 'center',
|
||||
}
|
||||
|
||||
const subHeadingStyles = {
|
||||
color: 'rgb(125, 125, 125)',
|
||||
padding: '10px',
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
fontWeight: '600',
|
||||
}
|
||||
|
||||
export default function LandingPage(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -1,47 +1,9 @@
|
||||
import { VStack, Box } from './../components/elements/LayoutPrimitives'
|
||||
import {
|
||||
LandingSectionsContainer,
|
||||
GetStartedButton,
|
||||
} from '../components/templates/landing/LandingSectionsContainer'
|
||||
import { LandingHeader } from '../components/templates/landing/LandingHeader'
|
||||
import { LandingFooter } from '../components/templates/landing/LandingFooter'
|
||||
import { useGetViewerQuery } from '../lib/networking/queries/useGetViewerQuery'
|
||||
import { useRouter } from 'next/router'
|
||||
import { PageMetaData } from '../components/patterns/PageMetaData'
|
||||
import { LoadingView } from '../components/patterns/LoadingView'
|
||||
import { About } from '../components/templates/About'
|
||||
|
||||
const containerStyles = {
|
||||
alignSelf: 'center',
|
||||
marginTop: 80,
|
||||
maxWidth: 960,
|
||||
px: '2vw',
|
||||
'@md': {
|
||||
px: '6vw',
|
||||
},
|
||||
'@xl': {
|
||||
px: '120px',
|
||||
},
|
||||
}
|
||||
|
||||
const headingStyles = {
|
||||
fontWeight: '700',
|
||||
color: '#3D3D3D',
|
||||
fontSize: 45,
|
||||
lineHeight: '53px',
|
||||
padding: '10px',
|
||||
paddingBottom: '0px',
|
||||
textAlign: 'center',
|
||||
}
|
||||
|
||||
const subHeadingStyles = {
|
||||
color: 'rgb(125, 125, 125)',
|
||||
padding: '10px',
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
fontWeight: '600',
|
||||
}
|
||||
|
||||
export default function LandingPage(): JSX.Element {
|
||||
const router = useRouter()
|
||||
const { viewerData, isLoading } = useGetViewerQuery()
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
import { LibraryContainer } from '../components/templates/library/LibraryContainer'
|
||||
|
||||
export default function Library(): JSX.Element {
|
||||
return <LibraryContainer />
|
||||
}
|
||||
Reference in New Issue
Block a user