Files
omnivore/packages/web/components/templates/article/ArticleActionsMenu.tsx
2022-12-29 17:45:29 +08:00

298 lines
9.2 KiB
TypeScript

import { Separator } from '@radix-ui/react-separator'
import {
ArchiveBox,
DotsThree,
HighlighterCircle,
TagSimple,
TextAa,
Trash,
Tray,
} from 'phosphor-react'
import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticleQuery'
import { Button } from '../../elements/Button'
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'
import { setLabelsMutation } from '../../../lib/networking/mutations/setLabelsMutation'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { SetLabelsModal } from './SetLabelsModal'
export type ArticleActionsMenuLayout = 'top' | 'side'
type ArticleActionsMenuProps = {
article?: ArticleAttributes
layout: ArticleActionsMenuLayout
showReaderDisplaySettings?: boolean
articleActionHandler: (action: string, arg?: unknown) => void
}
type MenuSeparatorProps = {
layout: ArticleActionsMenuLayout
}
const MenuSeparator = (props: MenuSeparatorProps): JSX.Element => {
const LineSeparator = styled(Separator, {
width: '100%',
margin: 0,
borderBottom: `1px solid ${theme.colors.grayLine.toString()}`,
my: '8px',
})
return props.layout == 'side' ? <LineSeparator /> : <></>
}
type ActionDropdownProps = {
layout: ArticleActionsMenuLayout
triggerElement: JSX.Element
children: JSX.Element
}
const ActionDropdown = (props: ActionDropdownProps): JSX.Element => {
return (
<Dropdown
css={{
m: '0px',
p: '0px',
overflow: 'hidden',
width: '265px',
maxWidth: '265px',
'@smDown': { width: '230px' },
}}
side={props.layout == 'side' ? 'right' : 'bottom'}
sideOffset={props.layout == 'side' ? 8 : 0}
align={props.layout == 'side' ? 'start' : 'center'}
alignOffset={props.layout == 'side' ? -18 : undefined}
triggerElement={props.triggerElement}
>
{props.children}
</Dropdown>
)
}
export function ArticleActionsMenu(
props: ArticleActionsMenuProps
): JSX.Element {
const readerSettings = useReaderSettings()
const displaySettingsButtonRef = useRef<HTMLElement | null>(null)
return (
<>
<Box
css={{
display: 'flex',
alignItems: 'center',
flexDirection: props.layout == 'side' ? 'column' : 'row',
justifyContent: props.layout == 'side' ? 'center' : 'flex-end',
gap: props.layout == 'side' ? '8px' : '24px',
paddingTop: '6px',
}}
>
{props.showReaderDisplaySettings && (
<>
<Button
style="articleActionIcon"
onClick={() =>
readerSettings.setShowEditDisplaySettingsModal(true)
}
>
<TooltipWrapped
tooltipContent="Adjust Display Settings"
tooltipSide={props.layout == 'side' ? 'right' : 'bottom'}
>
<TextAa size={24} color={theme.colors.readerFont.toString()} />
</TooltipWrapped>
</Button>
<MenuSeparator layout={props.layout} />
</>
)}
<SpanBox
css={{
display: 'flex',
'@smDown': {
display: 'none',
},
}}
>
{props.article ? (
<>
<Button
style="articleActionIcon"
onClick={() => readerSettings.setShowSetLabelsModal(true)}
>
<TooltipWrapped
tooltipContent="Edit labels"
tooltipSide={props.layout == 'side' ? 'right' : 'bottom'}
>
<SpanBox ref={displaySettingsButtonRef}>
<TagSimple
size={24}
color={theme.colors.readerFont.toString()}
/>
</SpanBox>
</TooltipWrapped>
</Button>
<MenuSeparator layout={props.layout} />
</>
) : (
// <ActionDropdown
// layout={props.layout}
// triggerElement={
// <TooltipWrapped
// tooltipContent="Edit labels"
// tooltipSide={props.layout == 'side' ? 'right' : 'bottom'}
// >
// <TagSimple
// size={24}
// color={theme.colors.readerFont.toString()}
// />
// </TooltipWrapped>
// }
// >
// <SetLabelsControl
// provider={props.article}
// save={(labels: Label[]) => {
// if (props.article?.id) {
// return setLabelsMutation(
// props.article?.id,
// labels.map((label) => label.id)
// )
// }
// return Promise.resolve(undefined)
// }}
// onLabelsChanged={(labels) => {
// props.articleActionHandler('refreshLabels', labels)
// }}
// />
// </ActionDropdown>
<Button
style="articleActionIcon"
css={{
'@smDown': {
display: 'flex',
},
}}
>
<TagSimple size={24} color={theme.colors.readerFont.toString()} />
</Button>
)}
</SpanBox>
<Button
style="articleActionIcon"
onClick={() => props.articleActionHandler('setLabels')}
css={{
display: 'none',
'@smDown': {
display: 'flex',
},
}}
>
<TagSimple size={24} color={theme.colors.readerFont.toString()} />
</Button>
<Button
style="articleActionIcon"
onClick={() => props.articleActionHandler('showHighlights')}
>
<TooltipWrapped
tooltipContent="View Highlights"
tooltipSide={props.layout == 'side' ? 'right' : 'bottom'}
>
<HighlighterCircle
size={24}
color={theme.colors.readerFont.toString()}
/>
</TooltipWrapped>
</Button>
<MenuSeparator layout={props.layout} />
<Button
style="articleActionIcon"
onClick={() => {
props.articleActionHandler('delete')
}}
>
<TooltipWrapped
tooltipContent="Delete"
tooltipSide={props.layout == 'side' ? 'right' : 'bottom'}
>
<Trash size={24} color={theme.colors.readerFont.toString()} />
</TooltipWrapped>
</Button>
{!props.article?.isArchived ? (
<Button
style="articleActionIcon"
onClick={() => props.articleActionHandler('archive')}
>
<TooltipWrapped
tooltipContent="Archive"
tooltipSide={props.layout == 'side' ? 'right' : 'bottom'}
>
<ArchiveBox
size={24}
color={theme.colors.readerFont.toString()}
/>
</TooltipWrapped>
</Button>
) : (
<Button
style="articleActionIcon"
onClick={() => props.articleActionHandler('unarchive')}
>
<TooltipWrapped
tooltipContent="Unarchive"
tooltipSide={props.layout == 'side' ? 'right' : 'bottom'}
>
<Tray size={24} color={theme.colors.readerFont.toString()} />
</TooltipWrapped>
</Button>
)}
{/* <MenuSeparator layout={props.layout} />
<Button style='articleActionIcon'>
<DotsThree size={24} color={theme.colors.readerFont.toString()} />
</Button> */}
</Box>
{readerSettings.showEditDisplaySettingsModal && (
<DisplaySettingsModal
centerX={props.layout != 'side'}
triggerElementRef={displaySettingsButtonRef}
articleActionHandler={props.articleActionHandler}
onOpenChange={() =>
readerSettings.setShowEditDisplaySettingsModal(false)
}
/>
)}
{props.article && readerSettings.showSetLabelsModal && (
<SetLabelsModal
provider={props.article}
onOpenChange={(open: boolean) => {
readerSettings.setShowSetLabelsModal(false)
}}
onLabelsUpdated={(labels: Label[]) => {
props.articleActionHandler('refreshLabels', labels)
}}
save={(labels: Label[]) => {
if (props.article?.id) {
return (
setLabelsMutation(
props.article?.id,
labels.map((l) => l.id)
) ?? []
)
}
return Promise.resolve(labels)
}}
/>
)}
</>
)
}