mirror of
https://github.com/Athou/commafeed.git
synced 2026-09-20 19:51:09 +00:00
simplify settings thunks
This commit is contained in:
@@ -1,32 +1,8 @@
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { showNotification } from "@mantine/notifications"
|
||||
import { createSlice, isAnyOf, type PayloadAction } from "@reduxjs/toolkit"
|
||||
import { createSlice, type PayloadAction } from "@reduxjs/toolkit"
|
||||
import type { LocalSettings, Settings, UserModel, ViewMode } from "@/app/types"
|
||||
import {
|
||||
changeCustomContextMenu,
|
||||
changeDisablePullToRefresh,
|
||||
changeEntriesToKeepOnTopWhenScrolling,
|
||||
changeExternalLinkIconDisplayMode,
|
||||
changeLanguage,
|
||||
changeMarkAllAsReadConfirmation,
|
||||
changeMarkAllAsReadNavigateToUnread,
|
||||
changeMobileFooter,
|
||||
changePrimaryColor,
|
||||
changePushNotificationSettings,
|
||||
changeReadingMode,
|
||||
changeReadingOrder,
|
||||
changeScrollMarks,
|
||||
changeScrollMode,
|
||||
changeScrollSpeed,
|
||||
changeSharingSetting,
|
||||
changeShowRead,
|
||||
changeStarIconDisplayMode,
|
||||
changeUnreadCountFavicon,
|
||||
changeUnreadCountTitle,
|
||||
reloadProfile,
|
||||
reloadSettings,
|
||||
reloadTags,
|
||||
} from "./thunks"
|
||||
import { changeSettings, reloadProfile, reloadSettings, reloadTags } from "./thunks"
|
||||
|
||||
interface UserState {
|
||||
settings?: Settings
|
||||
@@ -73,115 +49,16 @@ export const userSlice = createSlice({
|
||||
builder.addCase(reloadTags.fulfilled, (state, action) => {
|
||||
state.tags = action.payload
|
||||
})
|
||||
builder.addCase(changeReadingMode.pending, (state, action) => {
|
||||
builder.addCase(changeSettings.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.readingMode = action.meta.arg
|
||||
state.settings = { ...state.settings, ...action.meta.arg }
|
||||
})
|
||||
builder.addCase(changeReadingOrder.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.readingOrder = action.meta.arg
|
||||
builder.addCase(changeSettings.fulfilled, () => {
|
||||
showNotification({
|
||||
message: t`Settings saved.`,
|
||||
color: "green",
|
||||
})
|
||||
})
|
||||
builder.addCase(changeLanguage.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.language = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeScrollSpeed.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.scrollSpeed = action.meta.arg ? 400 : 0
|
||||
})
|
||||
builder.addCase(changeShowRead.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.showRead = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeScrollMarks.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.scrollMarks = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeScrollMode.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.scrollMode = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeEntriesToKeepOnTopWhenScrolling.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.entriesToKeepOnTopWhenScrolling = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeStarIconDisplayMode.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.starIconDisplayMode = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeExternalLinkIconDisplayMode.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.externalLinkIconDisplayMode = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeMarkAllAsReadConfirmation.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.markAllAsReadConfirmation = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeMarkAllAsReadNavigateToUnread.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.markAllAsReadNavigateToNextUnread = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeCustomContextMenu.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.customContextMenu = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeMobileFooter.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.mobileFooter = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeUnreadCountTitle.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.unreadCountTitle = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeUnreadCountFavicon.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.unreadCountFavicon = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeDisablePullToRefresh.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.disablePullToRefresh = action.meta.arg
|
||||
})
|
||||
builder.addCase(changePrimaryColor.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.primaryColor = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeSharingSetting.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.sharingSettings[action.meta.arg.site] = action.meta.arg.value
|
||||
})
|
||||
builder.addCase(changePushNotificationSettings.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.pushNotificationSettings = action.meta.arg
|
||||
})
|
||||
|
||||
builder.addMatcher(
|
||||
isAnyOf(
|
||||
changeLanguage.fulfilled,
|
||||
changeScrollSpeed.fulfilled,
|
||||
changeShowRead.fulfilled,
|
||||
changeScrollMarks.fulfilled,
|
||||
changeScrollMode.fulfilled,
|
||||
changeEntriesToKeepOnTopWhenScrolling.fulfilled,
|
||||
changeStarIconDisplayMode.fulfilled,
|
||||
changeExternalLinkIconDisplayMode.fulfilled,
|
||||
changeMarkAllAsReadConfirmation.fulfilled,
|
||||
changeMarkAllAsReadNavigateToUnread.fulfilled,
|
||||
changeCustomContextMenu.fulfilled,
|
||||
changeMobileFooter.fulfilled,
|
||||
changeUnreadCountTitle.fulfilled,
|
||||
changeUnreadCountFavicon.fulfilled,
|
||||
changeDisablePullToRefresh.fulfilled,
|
||||
changePrimaryColor.fulfilled,
|
||||
changeSharingSetting.fulfilled,
|
||||
changePushNotificationSettings.fulfilled
|
||||
),
|
||||
() => {
|
||||
showNotification({
|
||||
message: t`Settings saved.`,
|
||||
color: "green",
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { createAppAsyncThunk } from "@/app/async-thunk"
|
||||
import { client } from "@/app/client"
|
||||
import { reloadEntries } from "@/app/entries/thunks"
|
||||
import type { IconDisplayMode, PushNotificationSettings, ReadingMode, ReadingOrder, ScrollMode, SharingSettings } from "@/app/types"
|
||||
import type { Settings } from "@/app/types"
|
||||
|
||||
export const reloadSettings = createAppAsyncThunk("settings/reload", async () => await client.user.getSettings().then(r => r.data))
|
||||
|
||||
@@ -9,163 +8,8 @@ export const reloadProfile = createAppAsyncThunk("profile/reload", async () => a
|
||||
|
||||
export const reloadTags = createAppAsyncThunk("entries/tags", async () => await client.entry.getTags().then(r => r.data))
|
||||
|
||||
export const changeReadingMode = createAppAsyncThunk("settings/readingMode", (readingMode: ReadingMode, thunkApi) => {
|
||||
export const changeSettings = createAppAsyncThunk("settings/change", async (newSettings: Partial<Settings>, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, readingMode })
|
||||
thunkApi.dispatch(reloadEntries())
|
||||
await client.user.saveSettings({ ...settings, ...newSettings })
|
||||
})
|
||||
|
||||
export const changeReadingOrder = createAppAsyncThunk("settings/readingOrder", (readingOrder: ReadingOrder, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, readingOrder })
|
||||
thunkApi.dispatch(reloadEntries())
|
||||
})
|
||||
|
||||
export const changeLanguage = createAppAsyncThunk("settings/language", (language: string, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, language })
|
||||
})
|
||||
|
||||
export const changeScrollSpeed = createAppAsyncThunk("settings/scrollSpeed", (speed: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, scrollSpeed: speed ? 400 : 0 })
|
||||
})
|
||||
|
||||
export const changeShowRead = createAppAsyncThunk("settings/showRead", (showRead: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, showRead })
|
||||
})
|
||||
|
||||
export const changeScrollMarks = createAppAsyncThunk("settings/scrollMarks", (scrollMarks: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, scrollMarks })
|
||||
})
|
||||
|
||||
export const changeScrollMode = createAppAsyncThunk("settings/scrollMode", (scrollMode: ScrollMode, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, scrollMode })
|
||||
})
|
||||
|
||||
export const changeEntriesToKeepOnTopWhenScrolling = createAppAsyncThunk(
|
||||
"settings/entriesToKeepOnTopWhenScrolling",
|
||||
(entriesToKeepOnTopWhenScrolling: number, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, entriesToKeepOnTopWhenScrolling })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeStarIconDisplayMode = createAppAsyncThunk(
|
||||
"settings/starIconDisplayMode",
|
||||
(starIconDisplayMode: IconDisplayMode, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, starIconDisplayMode })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeExternalLinkIconDisplayMode = createAppAsyncThunk(
|
||||
"settings/externalLinkIconDisplayMode",
|
||||
(externalLinkIconDisplayMode: IconDisplayMode, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, externalLinkIconDisplayMode })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeMarkAllAsReadConfirmation = createAppAsyncThunk(
|
||||
"settings/markAllAsReadConfirmation",
|
||||
(markAllAsReadConfirmation: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, markAllAsReadConfirmation })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeMarkAllAsReadNavigateToUnread = createAppAsyncThunk(
|
||||
"settings/markAllAsReadNavigateToUnread",
|
||||
(markAllAsReadNavigateToNextUnread: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, markAllAsReadNavigateToNextUnread })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeCustomContextMenu = createAppAsyncThunk("settings/customContextMenu", (customContextMenu: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, customContextMenu })
|
||||
})
|
||||
|
||||
export const changeMobileFooter = createAppAsyncThunk("settings/mobileFooter", (mobileFooter: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, mobileFooter })
|
||||
})
|
||||
|
||||
export const changeUnreadCountTitle = createAppAsyncThunk("settings/unreadCountTitle", (unreadCountTitle: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, unreadCountTitle })
|
||||
})
|
||||
|
||||
export const changeUnreadCountFavicon = createAppAsyncThunk("settings/unreadCountFavicon", (unreadCountFavicon: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, unreadCountFavicon })
|
||||
})
|
||||
|
||||
export const changeDisablePullToRefresh = createAppAsyncThunk(
|
||||
"settings/disablePullToRefresh",
|
||||
(disablePullToRefresh: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, disablePullToRefresh })
|
||||
}
|
||||
)
|
||||
|
||||
export const changePrimaryColor = createAppAsyncThunk("settings/primaryColor", (primaryColor: string, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, primaryColor })
|
||||
})
|
||||
|
||||
export const changeSharingSetting = createAppAsyncThunk(
|
||||
"settings/sharingSetting",
|
||||
(
|
||||
sharingSetting: {
|
||||
site: keyof SharingSettings
|
||||
value: boolean
|
||||
},
|
||||
thunkApi
|
||||
) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({
|
||||
...settings,
|
||||
sharingSettings: {
|
||||
...settings.sharingSettings,
|
||||
[sharingSetting.site]: sharingSetting.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
export const changePushNotificationSettings = createAppAsyncThunk(
|
||||
"settings/pushNotificationSettings",
|
||||
(pushNotificationSettings: PushNotificationSettings, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({
|
||||
...settings,
|
||||
pushNotificationSettings,
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "react-icons/tb"
|
||||
import { markAllAsReadWithConfirmationIfRequired, reloadEntries, search, selectNextEntry, selectPreviousEntry } from "@/app/entries/thunks"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
import { changeReadingMode, changeReadingOrder } from "@/app/user/thunks"
|
||||
import { changeSettings } from "@/app/user/thunks"
|
||||
import { ActionButton } from "@/components/ActionButton"
|
||||
import { Loader } from "@/components/Loader"
|
||||
import { useActionButton } from "@/hooks/useActionButton"
|
||||
@@ -73,6 +73,25 @@ export function Header() {
|
||||
}, [setValues, searchFromStore])
|
||||
|
||||
if (!settings) return <Loader />
|
||||
|
||||
const toggleReadingMode = async () => {
|
||||
await dispatch(
|
||||
changeSettings({
|
||||
readingMode: settings.readingMode === "all" ? "unread" : "all",
|
||||
})
|
||||
)
|
||||
dispatch(reloadEntries())
|
||||
}
|
||||
|
||||
const toggleReadingOrder = async () => {
|
||||
await dispatch(
|
||||
changeSettings({
|
||||
readingOrder: settings.readingOrder === "asc" ? "desc" : "asc",
|
||||
})
|
||||
)
|
||||
dispatch(reloadEntries())
|
||||
}
|
||||
|
||||
return (
|
||||
<Center className="cf-toolbar-wrapper">
|
||||
<HeaderToolbar>
|
||||
@@ -121,12 +140,12 @@ export function Header() {
|
||||
<ActionButton
|
||||
icon={settings.readingMode === "all" ? <TbEye size={iconSize} /> : <TbEyeOff size={iconSize} />}
|
||||
label={settings.readingMode === "all" ? msg`All` : msg`Unread`}
|
||||
onClick={async () => await dispatch(changeReadingMode(settings.readingMode === "all" ? "unread" : "all"))}
|
||||
onClick={toggleReadingMode}
|
||||
/>
|
||||
<ActionButton
|
||||
icon={settings.readingOrder === "asc" ? <TbSortAscending size={iconSize} /> : <TbSortDescending size={iconSize} />}
|
||||
label={settings.readingOrder === "asc" ? msg`Asc` : msg`Desc`}
|
||||
onClick={async () => await dispatch(changeReadingOrder(settings.readingOrder === "asc" ? "desc" : "asc"))}
|
||||
onClick={toggleReadingOrder}
|
||||
/>
|
||||
|
||||
<Popover>
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
type ComboboxData,
|
||||
Divider,
|
||||
Group,
|
||||
Loader,
|
||||
NumberInput,
|
||||
Radio,
|
||||
Select,
|
||||
@@ -18,45 +19,11 @@ 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 { changeSettings } 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 settings = useAppSelector(state => state.user.settings)
|
||||
const { _ } = useLingui()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
@@ -108,50 +75,51 @@ export function DisplaySettings() {
|
||||
</Group>
|
||||
)
|
||||
|
||||
if (!settings) return <Loader />
|
||||
return (
|
||||
<Stack>
|
||||
<Divider label={<Trans>Display</Trans>} labelPosition="center" />
|
||||
|
||||
<Select
|
||||
label={<Trans>Language</Trans>}
|
||||
value={language}
|
||||
value={settings.language}
|
||||
data={locales.map(l => ({
|
||||
value: l.key,
|
||||
label: l.label,
|
||||
}))}
|
||||
onChange={async s => await (s && dispatch(changeLanguage(s)))}
|
||||
onChange={language => language && dispatch(changeSettings({ language }))}
|
||||
/>
|
||||
|
||||
<Select
|
||||
label={<Trans>Primary color</Trans>}
|
||||
data={colorData}
|
||||
value={primaryColor}
|
||||
onChange={async value => value && (await dispatch(changePrimaryColor(value)))}
|
||||
value={settings.primaryColor}
|
||||
onChange={primaryColor => primaryColor && dispatch(changeSettings({ primaryColor }))}
|
||||
renderOption={colorRenderer}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show feeds and categories with no unread entries</Trans>}
|
||||
checked={showRead}
|
||||
onChange={async e => await dispatch(changeShowRead(e.currentTarget.checked))}
|
||||
checked={settings.showRead}
|
||||
onChange={e => dispatch(changeSettings({ showRead: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show confirmation when marking all entries as read</Trans>}
|
||||
checked={markAllAsReadConfirmation}
|
||||
onChange={async e => await dispatch(changeMarkAllAsReadConfirmation(e.currentTarget.checked))}
|
||||
checked={settings.markAllAsReadConfirmation}
|
||||
onChange={e => dispatch(changeSettings({ markAllAsReadConfirmation: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Navigate to the next category/feed with unread entries when marking all entries as read</Trans>}
|
||||
checked={markAllAsReadNavigateToNextUnread}
|
||||
onChange={async e => await dispatch(changeMarkAllAsReadNavigateToUnread(e.currentTarget.checked))}
|
||||
checked={settings.markAllAsReadNavigateToNextUnread}
|
||||
onChange={e => dispatch(changeSettings({ markAllAsReadNavigateToNextUnread: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>On mobile, show action buttons at the bottom of the screen</Trans>}
|
||||
checked={mobileFooter}
|
||||
onChange={async e => await dispatch(changeMobileFooter(e.currentTarget.checked))}
|
||||
checked={settings.mobileFooter}
|
||||
onChange={e => dispatch(changeSettings({ mobileFooter: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Scrolling</Trans>} labelPosition="center" />
|
||||
@@ -159,14 +127,14 @@ export function DisplaySettings() {
|
||||
<Switch
|
||||
label={<Trans>Disable "Pull to refresh" browser behavior</Trans>}
|
||||
description={<Trans>This setting can cause scrolling issues on some browsers (e.g. Safari)</Trans>}
|
||||
checked={disablePullToRefresh}
|
||||
onChange={async e => await dispatch(changeDisablePullToRefresh(e.currentTarget.checked))}
|
||||
checked={settings.disablePullToRefresh}
|
||||
onChange={e => dispatch(changeSettings({ disablePullToRefresh: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Radio.Group
|
||||
label={<Trans>Scroll selected entry to the top of the page</Trans>}
|
||||
value={scrollMode}
|
||||
onChange={async value => await dispatch(changeScrollMode(value as ScrollMode))}
|
||||
value={settings.scrollMode}
|
||||
onChange={value => dispatch(changeSettings({ scrollMode: value }))}
|
||||
>
|
||||
<Group mt="xs">
|
||||
{Object.entries(scrollModeOptions).map(e => (
|
||||
@@ -179,56 +147,56 @@ export function DisplaySettings() {
|
||||
label={<Trans>Entries to keep above the selected entry when scrolling</Trans>}
|
||||
description={<Trans>Only applies to compact, cozy and detailed modes</Trans>}
|
||||
min={0}
|
||||
value={entriesToKeepOnTop}
|
||||
onChange={async value => await dispatch(changeEntriesToKeepOnTopWhenScrolling(+value))}
|
||||
value={settings.entriesToKeepOnTopWhenScrolling}
|
||||
onChange={value => dispatch(changeSettings({ entriesToKeepOnTopWhenScrolling: +value }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Scroll smoothly when navigating between entries</Trans>}
|
||||
checked={scrollSpeed ? scrollSpeed > 0 : false}
|
||||
onChange={async e => await dispatch(changeScrollSpeed(e.currentTarget.checked))}
|
||||
checked={settings.scrollSpeed ? settings.scrollSpeed > 0 : false}
|
||||
onChange={e => dispatch(changeSettings({ scrollSpeed: e.currentTarget.checked ? 400 : 0 }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>In expanded view, scrolling through entries mark them as read</Trans>}
|
||||
checked={scrollMarks}
|
||||
onChange={async e => await dispatch(changeScrollMarks(e.currentTarget.checked))}
|
||||
checked={settings.scrollMarks}
|
||||
onChange={e => dispatch(changeSettings({ scrollMarks: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Browser tab</Trans>} labelPosition="center" />
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show unread count in tab title</Trans>}
|
||||
checked={unreadCountTitle}
|
||||
onChange={async e => await dispatch(changeUnreadCountTitle(e.currentTarget.checked))}
|
||||
checked={settings.unreadCountTitle}
|
||||
onChange={e => dispatch(changeSettings({ unreadCountTitle: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show unread count in tab favicon</Trans>}
|
||||
checked={unreadCountFavicon}
|
||||
onChange={async e => await dispatch(changeUnreadCountFavicon(e.currentTarget.checked))}
|
||||
checked={settings.unreadCountFavicon}
|
||||
onChange={e => dispatch(changeSettings({ unreadCountFavicon: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Entry headers</Trans>} labelPosition="center" />
|
||||
|
||||
<Select
|
||||
label={<Trans>Show star icon</Trans>}
|
||||
value={starIconDisplayMode}
|
||||
value={settings.starIconDisplayMode}
|
||||
data={displayModeData}
|
||||
onChange={async s => await dispatch(changeStarIconDisplayMode(s as IconDisplayMode))}
|
||||
onChange={value => dispatch(changeSettings({ starIconDisplayMode: value as IconDisplayMode }))}
|
||||
/>
|
||||
|
||||
<Select
|
||||
label={<Trans>Show external link icon</Trans>}
|
||||
value={externalLinkIconDisplayMode}
|
||||
value={settings.externalLinkIconDisplayMode}
|
||||
data={displayModeData}
|
||||
onChange={async s => await dispatch(changeExternalLinkIconDisplayMode(s as IconDisplayMode))}
|
||||
onChange={value => dispatch(changeSettings({ externalLinkIconDisplayMode: value as IconDisplayMode }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show CommaFeed's own context menu on right click</Trans>}
|
||||
checked={customContextMenu}
|
||||
onChange={async e => await dispatch(changeCustomContextMenu(e.currentTarget.checked))}
|
||||
checked={settings.customContextMenu}
|
||||
onChange={e => dispatch(changeSettings({ customContextMenu: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Sharing sites</Trans>} labelPosition="center" />
|
||||
@@ -238,12 +206,14 @@ export function DisplaySettings() {
|
||||
<Switch
|
||||
key={site}
|
||||
label={Constants.sharing[site].label}
|
||||
checked={sharingSettings?.[site]}
|
||||
onChange={async e =>
|
||||
await dispatch(
|
||||
changeSharingSetting({
|
||||
site,
|
||||
value: e.currentTarget.checked,
|
||||
checked={settings.sharingSettings[site]}
|
||||
onChange={e =>
|
||||
dispatch(
|
||||
changeSettings({
|
||||
sharingSettings: {
|
||||
...settings.sharingSettings,
|
||||
[site]: e.currentTarget.checked,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { client, errorToStrings } from "@/app/client"
|
||||
import { redirectToSelectedSource } from "@/app/redirect/thunks"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
import type { PushNotificationSettings as PushNotificationSettingsModel } from "@/app/types"
|
||||
import { changePushNotificationSettings } from "@/app/user/thunks"
|
||||
import { changeSettings } from "@/app/user/thunks"
|
||||
import { Alert } from "@/components/Alert"
|
||||
|
||||
export function PushNotificationSettings() {
|
||||
@@ -25,7 +25,7 @@ export function PushNotificationSettings() {
|
||||
}, [form.initialize, notificationSettings])
|
||||
|
||||
const handleSubmit = (values: PushNotificationSettingsModel) => {
|
||||
dispatch(changePushNotificationSettings(values))
|
||||
dispatch(changeSettings({ pushNotificationSettings: values }))
|
||||
}
|
||||
|
||||
const sendTestPushNotification = useAsyncCallback(client.user.sendTestPushNotification)
|
||||
|
||||
Reference in New Issue
Block a user