Remove some unused code

This commit is contained in:
Jackson Harper
2023-02-27 09:49:49 +08:00
parent 35b94ee237
commit 65441ae06d
24 changed files with 110 additions and 1206 deletions

View File

@ -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"

View File

@ -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={() => {

View File

@ -11,8 +11,6 @@ export type LinkedItemCardAction =
| 'delete'
| 'mark-read'
| 'mark-unread'
| 'share'
| 'snooze'
| 'set-labels'
| 'unsubscribe'
| 'update-item'

View File

@ -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

View File

@ -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'

View File

@ -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>
)
}

View File

@ -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

View File

@ -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>
)
}

View File

@ -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={

View File

@ -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

View File

@ -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) => {

View File

@ -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>
</>
)
}
}

View File

@ -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 = {

View File

@ -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',
})

View File

@ -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>
</>
)
}

View File

@ -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>
)
}

View File

@ -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>
)
}

View File

@ -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>
)
}

View File

@ -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>
)
}

View File

@ -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'

View File

@ -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 = {

View File

@ -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 (
<>

View File

@ -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()

View File

@ -1,5 +0,0 @@
import { LibraryContainer } from '../components/templates/library/LibraryContainer'
export default function Library(): JSX.Element {
return <LibraryContainer />
}