Files
commafeed/commafeed-client/src/components/content/FeedEntryFooter.tsx

109 lines
5.0 KiB
TypeScript
Raw Normal View History

import { t, Trans } from "@lingui/macro"
import { Group, Indicator, MultiSelect, Popover } from "@mantine/core"
import { useMediaQuery } from "@mantine/hooks"
2022-10-25 10:18:50 +02:00
import { Constants } from "app/constants"
import { markEntriesUpToEntry, markEntry, starEntry, tagEntry } from "app/slices/entries"
2022-08-19 12:41:33 +02:00
import { useAppDispatch, useAppSelector } from "app/store"
import { Entry } from "app/types"
import { ActionButton } from "components/ActionButtton"
import { ButtonToolbar } from "components/ButtonToolbar"
2022-10-25 10:18:50 +02:00
import { useEffect, useState } from "react"
import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbShare, TbStar, TbStarOff, TbTag } from "react-icons/tb"
import { throttle } from "throttle-debounce"
2022-08-19 12:41:33 +02:00
import { ShareButtons } from "./ShareButtons"
interface FeedEntryFooterProps {
entry: Entry
}
export function FeedEntryFooter(props: FeedEntryFooterProps) {
2022-10-25 10:18:50 +02:00
const [scrollPosition, setScrollPosition] = useState(0)
2022-08-19 12:41:33 +02:00
const sharingSettings = useAppSelector(state => state.user.settings?.sharingSettings)
2022-10-25 10:18:50 +02:00
const tags = useAppSelector(state => state.user.tags)
2023-05-08 14:54:16 +02:00
const mobile = !useMediaQuery(`(min-width: ${Constants.layout.mobileBreakpoint})`)
const dispatch = useAppDispatch()
2022-08-19 12:41:33 +02:00
2023-02-04 08:34:23 +01:00
const showSharingButtons = sharingSettings && Object.values(sharingSettings).some(v => v)
2022-08-19 12:41:33 +02:00
const readStatusButtonClicked = () => dispatch(markEntry({ entry: props.entry, read: !props.entry.read }))
2022-10-25 10:18:50 +02:00
const onTagsChange = (values: string[]) =>
dispatch(
tagEntry({
entryId: +props.entry.id,
tags: values,
})
)
useEffect(() => {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
const listener = () => setScrollPosition(scrollArea ? scrollArea.scrollTop : 0)
const throttledListener = throttle(100, listener)
2023-02-24 14:53:15 +01:00
scrollArea?.addEventListener("scroll", throttledListener)
return () => scrollArea?.removeEventListener("scroll", throttledListener)
2022-10-25 10:18:50 +02:00
}, [])
return (
2022-08-24 09:08:10 +02:00
<Group position="apart">
<ButtonToolbar>
2022-08-24 09:08:10 +02:00
{props.entry.markable && (
<ActionButton
icon={props.entry.read ? <TbEyeOff size={18} /> : <TbEyeCheck size={18} />}
label={props.entry.read ? <Trans>Keep unread</Trans> : <Trans>Mark as read</Trans>}
onClick={readStatusButtonClicked}
2022-08-24 09:08:10 +02:00
/>
)}
<ActionButton
icon={props.entry.starred ? <TbStarOff size={18} /> : <TbStar size={18} />}
label={props.entry.starred ? <Trans>Unstar</Trans> : <Trans>Star</Trans>}
2022-08-24 09:08:10 +02:00
onClick={() => dispatch(starEntry({ entry: props.entry, starred: !props.entry.starred }))}
/>
2022-08-24 09:08:10 +02:00
{showSharingButtons && (
<Popover withArrow withinPortal shadow="md" positionDependencies={[scrollPosition]} closeOnClickOutside={!mobile}>
2022-08-24 09:08:10 +02:00
<Popover.Target>
<ActionButton icon={<TbShare size={18} />} label={<Trans>Share</Trans>} />
2022-08-24 09:08:10 +02:00
</Popover.Target>
<Popover.Dropdown>
<ShareButtons url={props.entry.url} description={props.entry.title} />
</Popover.Dropdown>
</Popover>
)}
2022-10-25 10:18:50 +02:00
{tags && (
<Popover withArrow withinPortal shadow="md" positionDependencies={[scrollPosition]} closeOnClickOutside={!mobile}>
2022-10-25 10:18:50 +02:00
<Popover.Target>
2023-05-08 14:54:16 +02:00
<Indicator label={props.entry.tags.length} disabled={props.entry.tags.length === 0} inline size={16}>
<ActionButton icon={<TbTag size={18} />} label={<Trans>Tags</Trans>} />
2022-10-27 14:32:23 +02:00
</Indicator>
2022-10-25 10:18:50 +02:00
</Popover.Target>
<Popover.Dropdown>
<MultiSelect
data={tags}
placeholder="Tags"
searchable
creatable
2022-10-25 18:05:46 +02:00
autoFocus
2022-10-25 10:18:50 +02:00
getCreateLabel={query => t`Create tag: ${query}`}
value={props.entry.tags}
onChange={onTagsChange}
/>
</Popover.Dropdown>
</Popover>
)}
2022-08-24 09:08:10 +02:00
<a href={props.entry.url} target="_blank" rel="noreferrer">
<ActionButton icon={<TbExternalLink size={18} />} label={<Trans>Open link</Trans>} />
2022-08-24 09:08:10 +02:00
</a>
</ButtonToolbar>
2022-08-24 09:08:10 +02:00
2022-08-19 10:34:04 +02:00
<ActionButton
2022-08-24 09:08:10 +02:00
icon={<TbArrowBarToDown size={18} />}
label={<Trans>Mark as read up to here</Trans>}
2022-08-24 09:08:10 +02:00
onClick={() => dispatch(markEntriesUpToEntry(props.entry))}
2022-08-19 10:34:04 +02:00
/>
</Group>
)
}