import { msg } from "@lingui/core/macro" import { useLingui } from "@lingui/react" import { Trans } from "@lingui/react/macro" import { Box, Divider, Group, NumberInput, Radio, Select, type SelectProps, SimpleGrid, Stack, Switch } from "@mantine/core" import type { ComboboxData } from "@mantine/core/lib/components/Combobox/Combobox.types" import type { ReactNode } from "react" import { Constants } from "@/app/constants" import { useAppDispatch, useAppSelector } from "@/app/store" import type { IconDisplayMode, ScrollMode, SharingSettings } from "@/app/types" import { changeCustomContextMenu, changeDisablePullToRefresh, changeEntriesToKeepOnTopWhenScrolling, changeExternalLinkIconDisplayMode, changeLanguage, changeMarkAllAsReadConfirmation, changeMarkAllAsReadNavigateToUnread, changeMobileFooter, changePrimaryColor, changeScrollMarks, changeScrollMode, changeScrollSpeed, changeSharingSetting, changeShowRead, changeStarIconDisplayMode, changeUnreadCountFavicon, changeUnreadCountTitle, } from "@/app/user/thunks" import { locales } from "@/i18n" export function DisplaySettings() { const language = useAppSelector(state => state.user.settings?.language) const scrollSpeed = useAppSelector(state => state.user.settings?.scrollSpeed) const showRead = useAppSelector(state => state.user.settings?.showRead) const scrollMarks = useAppSelector(state => state.user.settings?.scrollMarks) const scrollMode = useAppSelector(state => state.user.settings?.scrollMode) const entriesToKeepOnTop = useAppSelector(state => state.user.settings?.entriesToKeepOnTopWhenScrolling) const starIconDisplayMode = useAppSelector(state => state.user.settings?.starIconDisplayMode) const externalLinkIconDisplayMode = useAppSelector(state => state.user.settings?.externalLinkIconDisplayMode) const markAllAsReadConfirmation = useAppSelector(state => state.user.settings?.markAllAsReadConfirmation) const markAllAsReadNavigateToNextUnread = useAppSelector(state => state.user.settings?.markAllAsReadNavigateToNextUnread) const customContextMenu = useAppSelector(state => state.user.settings?.customContextMenu) const mobileFooter = useAppSelector(state => state.user.settings?.mobileFooter) const unreadCountTitle = useAppSelector(state => state.user.settings?.unreadCountTitle) const unreadCountFavicon = useAppSelector(state => state.user.settings?.unreadCountFavicon) const disablePullToRefresh = useAppSelector(state => state.user.settings?.disablePullToRefresh) const sharingSettings = useAppSelector(state => state.user.settings?.sharingSettings) const primaryColor = useAppSelector(state => state.user.settings?.primaryColor) || Constants.theme.defaultPrimaryColor const { _ } = useLingui() const dispatch = useAppDispatch() const scrollModeOptions: Record = { always: Always, never: Never, if_needed: If the entry doesn't entirely fit on the screen, } const displayModeData: ComboboxData = [ { value: "always", label: _(msg`Always`), }, { value: "on_desktop", label: _(msg`On desktop`), }, { value: "on_mobile", label: _(msg`On mobile`), }, { value: "never", label: _(msg`Never`), }, ] const colorData: ComboboxData = [ { value: "dark", label: _(msg`Dark`) }, { value: "gray", label: _(msg`Gray`) }, { value: "red", label: _(msg`Red`) }, { value: "pink", label: _(msg`Pink`) }, { value: "grape", label: _(msg`Grape`) }, { value: "violet", label: _(msg`Violet`) }, { value: "indigo", label: _(msg`Indigo`) }, { value: "blue", label: _(msg`Blue`) }, { value: "cyan", label: _(msg`Cyan`) }, { value: "green", label: _(msg`Green`) }, { value: "lime", label: _(msg`Lime`) }, { value: "yellow", label: _(msg`Yellow`) }, { value: "orange", label: _(msg`Orange`) }, { value: "teal", label: _(msg`Teal`) }, ].sort((a, b) => a.label.localeCompare(b.label)) const colorRenderer: SelectProps["renderOption"] = ({ option }) => ( {option.label} ) return ( Display} labelPosition="center" /> Primary color} data={colorData} value={primaryColor} onChange={async value => value && (await dispatch(changePrimaryColor(value)))} renderOption={colorRenderer} /> Show feeds and categories with no unread entries} checked={showRead} onChange={async e => await dispatch(changeShowRead(e.currentTarget.checked))} /> Show confirmation when marking all entries as read} checked={markAllAsReadConfirmation} onChange={async e => await dispatch(changeMarkAllAsReadConfirmation(e.currentTarget.checked))} /> Navigate to the next category/feed with unread entries when marking all entries as read} checked={markAllAsReadNavigateToNextUnread} onChange={async e => await dispatch(changeMarkAllAsReadNavigateToUnread(e.currentTarget.checked))} /> On mobile, show action buttons at the bottom of the screen} checked={mobileFooter} onChange={async e => await dispatch(changeMobileFooter(e.currentTarget.checked))} /> Browser tab} labelPosition="center" /> Show unread count in tab title} checked={unreadCountTitle} onChange={async e => await dispatch(changeUnreadCountTitle(e.currentTarget.checked))} /> Show unread count in tab favicon} checked={unreadCountFavicon} onChange={async e => await dispatch(changeUnreadCountFavicon(e.currentTarget.checked))} /> Entry headers} labelPosition="center" /> Show external link icon} value={externalLinkIconDisplayMode} data={displayModeData} onChange={async s => await dispatch(changeExternalLinkIconDisplayMode(s as IconDisplayMode))} /> Show CommaFeed's own context menu on right click} checked={customContextMenu} onChange={async e => await dispatch(changeCustomContextMenu(e.currentTarget.checked))} /> Scrolling} labelPosition="center" /> Scroll selected entry to the top of the page} value={scrollMode} onChange={async value => await dispatch(changeScrollMode(value as ScrollMode))} > {Object.entries(scrollModeOptions).map(e => ( ))} Entries to keep above the selected entry when scrolling} description={Only applies to compact, cozy and detailed modes} min={0} value={entriesToKeepOnTop} onChange={async value => await dispatch(changeEntriesToKeepOnTopWhenScrolling(+value))} /> Scroll smoothly when navigating between entries} checked={scrollSpeed ? scrollSpeed > 0 : false} onChange={async e => await dispatch(changeScrollSpeed(e.currentTarget.checked))} /> In expanded view, scrolling through entries mark them as read} checked={scrollMarks} onChange={async e => await dispatch(changeScrollMarks(e.currentTarget.checked))} /> Disable "Pull to refresh" browser behavior} description={This setting can cause scrolling issues on some browsers (e.g. Safari)} checked={disablePullToRefresh} onChange={async e => await dispatch(changeDisablePullToRefresh(e.currentTarget.checked))} /> Sharing sites} labelPosition="center" /> {(Object.keys(Constants.sharing) as Array).map(site => ( await dispatch( changeSharingSetting({ site, value: e.currentTarget.checked, }) ) } /> ))} ) }