move other settings to localSettings too

This commit is contained in:
Athou
2024-09-10 18:11:16 +02:00
parent e119941762
commit 5f2d213419
7 changed files with 48 additions and 42 deletions

View File

@@ -44,7 +44,6 @@
"throttle-debounce": "^5.0.2", "throttle-debounce": "^5.0.2",
"tinycon": "^0.6.8", "tinycon": "^0.6.8",
"tss-react": "^4.9.13", "tss-react": "^4.9.13",
"use-local-storage": "^3.0.0",
"vite-plugin-biome": "^1.0.12", "vite-plugin-biome": "^1.0.12",
"websocket-heartbeat-js": "^1.1.3" "websocket-heartbeat-js": "^1.1.3"
}, },
@@ -8380,15 +8379,6 @@
} }
} }
}, },
"node_modules/use-local-storage": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/use-local-storage/-/use-local-storage-3.0.0.tgz",
"integrity": "sha512-wlPNnBCG3ULIJMr5A+dvWqLiPWCfsN1Kwijq+sAhT5yV4ex0u6XmZuNwP+RerIOfzBuz1pwSZuzhZMiluGQHfQ==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.8.1"
}
},
"node_modules/use-sidecar": { "node_modules/use-sidecar": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",

View File

@@ -51,7 +51,6 @@
"throttle-debounce": "^5.0.2", "throttle-debounce": "^5.0.2",
"tinycon": "^0.6.8", "tinycon": "^0.6.8",
"tss-react": "^4.9.13", "tss-react": "^4.9.13",
"use-local-storage": "^3.0.0",
"vite-plugin-biome": "^1.0.12", "vite-plugin-biome": "^1.0.12",
"websocket-heartbeat-js": "^1.1.3" "websocket-heartbeat-js": "^1.1.3"
}, },

View File

@@ -3,8 +3,7 @@ import { entriesSlice } from "app/entries/slice"
import { redirectSlice } from "app/redirect/slice" import { redirectSlice } from "app/redirect/slice"
import { serverSlice } from "app/server/slice" import { serverSlice } from "app/server/slice"
import { treeSlice } from "app/tree/slice" import { treeSlice } from "app/tree/slice"
import type { ViewMode } from "app/types" import { initialLocalSettings, userSlice } from "app/user/slice"
import { userSlice } from "app/user/slice"
import { type TypedUseSelectorHook, useDispatch, useSelector } from "react-redux" import { type TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"
export const reducers = { export const reducers = {
@@ -19,15 +18,13 @@ export const store = configureStore({
reducer: reducers, reducer: reducers,
preloadedState: { preloadedState: {
user: { user: {
localSettings: { localSettings: JSON.parse(localStorage.getItem("commafeed-local-settings") ?? JSON.stringify(initialLocalSettings)),
viewMode: localStorage.getItem("view-mode") as ViewMode,
},
}, },
}, },
}) })
store.subscribe(() => { store.subscribe(() => {
const state = store.getState() const localSettings = store.getState().user.localSettings
localStorage.setItem("view-mode", state.user.localSettings.viewMode) localStorage.setItem("commafeed-local-settings", JSON.stringify(localSettings))
}) })
export type RootState = ReturnType<typeof store.getState> export type RootState = ReturnType<typeof store.getState>

View File

@@ -254,6 +254,12 @@ export interface Settings {
sharingSettings: SharingSettings sharingSettings: SharingSettings
} }
export interface LocalSettings {
viewMode: ViewMode
sidebarWidth: number
announcementHash: string
}
export interface StarRequest { export interface StarRequest {
id: string id: string
feedId: number feedId: number

View File

@@ -1,7 +1,7 @@
import { t } from "@lingui/macro" import { t } from "@lingui/macro"
import { showNotification } from "@mantine/notifications" import { showNotification } from "@mantine/notifications"
import { type PayloadAction, createSlice, isAnyOf } from "@reduxjs/toolkit" import { type PayloadAction, createSlice, isAnyOf } from "@reduxjs/toolkit"
import type { Settings, UserModel, ViewMode } from "app/types" import type { LocalSettings, Settings, UserModel, ViewMode } from "app/types"
import { import {
changeCustomContextMenu, changeCustomContextMenu,
changeEntriesToKeepOnTopWhenScrolling, changeEntriesToKeepOnTopWhenScrolling,
@@ -26,17 +26,19 @@ import {
interface UserState { interface UserState {
settings?: Settings settings?: Settings
localSettings: { localSettings: LocalSettings
viewMode: ViewMode
}
profile?: UserModel profile?: UserModel
tags?: string[] tags?: string[]
} }
export const initialLocalSettings: LocalSettings = {
viewMode: "detailed",
sidebarWidth: 360,
announcementHash: "no-hash",
}
const initialState: UserState = { const initialState: UserState = {
localSettings: { localSettings: initialLocalSettings,
viewMode: "detailed",
},
} }
export const userSlice = createSlice({ export const userSlice = createSlice({
@@ -46,6 +48,12 @@ export const userSlice = createSlice({
setViewMode: (state, action: PayloadAction<ViewMode>) => { setViewMode: (state, action: PayloadAction<ViewMode>) => {
state.localSettings.viewMode = action.payload state.localSettings.viewMode = action.payload
}, },
setSidebarWidth: (state, action: PayloadAction<number>) => {
state.localSettings.sidebarWidth = action.payload
},
setAnnouncementHash: (state, action: PayloadAction<string>) => {
state.localSettings.announcementHash = action.payload
},
}, },
extraReducers: builder => { extraReducers: builder => {
builder.addCase(reloadSettings.fulfilled, (state, action) => { builder.addCase(reloadSettings.fulfilled, (state, action) => {
@@ -148,4 +156,4 @@ export const userSlice = createSlice({
}, },
}) })
export const { setViewMode } = userSlice.actions export const { setViewMode, setSidebarWidth, setAnnouncementHash } = userSlice.actions

View File

@@ -1,9 +1,9 @@
import { Trans } from "@lingui/macro" import { Trans } from "@lingui/macro"
import { Box, Dialog, Text } from "@mantine/core" import { Box, Dialog, Text } from "@mantine/core"
import { useAppSelector } from "app/store" import { useAppDispatch, useAppSelector } from "app/store"
import { setAnnouncementHash } from "app/user/slice"
import { Content } from "components/content/Content" import { Content } from "components/content/Content"
import { useAsync } from "react-async-hook" import { useAsync } from "react-async-hook"
import useLocalStorage from "use-local-storage"
const sha256Hex = async (input: string | undefined) => { const sha256Hex = async (input: string | undefined) => {
const data = new TextEncoder().encode(input) const data = new TextEncoder().encode(input)
@@ -15,10 +15,11 @@ const sha256Hex = async (input: string | undefined) => {
export function AnnouncementDialog() { export function AnnouncementDialog() {
const announcement = useAppSelector(state => state.server.serverInfos?.announcement) const announcement = useAppSelector(state => state.server.serverInfos?.announcement)
const announcementHash = useAsync(sha256Hex, [announcement]).result const announcementHash = useAsync(sha256Hex, [announcement]).result
const [localStorageHash, setLocalStorageHash] = useLocalStorage("announcement-hash", "no-hash") const existingAnnouncementHash = useAppSelector(state => state.user.localSettings.announcementHash)
const dispatch = useAppDispatch()
const opened = !!announcementHash && announcementHash !== localStorageHash const opened = !!announcementHash && announcementHash !== existingAnnouncementHash
const onClosed = () => setLocalStorageHash(announcementHash) const onClosed = () => announcementHash && dispatch(setAnnouncementHash(announcementHash))
if (!announcement) return null if (!announcement) return null
return ( return (

View File

@@ -5,6 +5,7 @@ import { redirectToAdd, redirectToRootCategory } from "app/redirect/thunks"
import { useAppDispatch, useAppSelector } from "app/store" import { useAppDispatch, useAppSelector } from "app/store"
import { setMobileMenuOpen } from "app/tree/slice" import { setMobileMenuOpen } from "app/tree/slice"
import { reloadTree } from "app/tree/thunks" import { reloadTree } from "app/tree/thunks"
import { setSidebarWidth } from "app/user/slice"
import { reloadProfile, reloadSettings, reloadTags } from "app/user/thunks" import { reloadProfile, reloadSettings, reloadTags } from "app/user/thunks"
import { ActionButton } from "components/ActionButton" import { ActionButton } from "components/ActionButton"
import { AnnouncementDialog } from "components/AnnouncementDialog" import { AnnouncementDialog } from "components/AnnouncementDialog"
@@ -23,7 +24,6 @@ import { TbMenu2, TbPlus, TbX } from "react-icons/tb"
import { Outlet } from "react-router-dom" import { Outlet } from "react-router-dom"
import { useSwipeable } from "react-swipeable" import { useSwipeable } from "react-swipeable"
import { tss } from "tss" import { tss } from "tss"
import useLocalStorage from "use-local-storage"
interface LayoutProps { interface LayoutProps {
sidebar: ReactNode sidebar: ReactNode
@@ -64,21 +64,23 @@ export default function Layout(props: LayoutProps) {
const theme = useMantineTheme() const theme = useMantineTheme()
const mobile = useMobile() const mobile = useMobile()
const { isBrowserExtensionPopup } = useBrowserExtension() const { isBrowserExtensionPopup } = useBrowserExtension()
const [sidebarWidth, setSidebarWidth] = useLocalStorage("sidebar-width", 350)
const { loading } = useAppLoading()
const mobileMenuOpen = useAppSelector(state => state.tree.mobileMenuOpen)
const webSocketConnected = useAppSelector(state => state.server.webSocketConnected)
const treeReloadInterval = useAppSelector(state => state.server.serverInfos?.treeReloadInterval)
const mobileFooter = useAppSelector(state => state.user.settings?.mobileFooter)
const sidebarWidth = useAppSelector(state => state.user.localSettings.sidebarWidth)
const headerInFooter = mobile && !isBrowserExtensionPopup && mobileFooter
const dispatch = useAppDispatch()
useWebSocket()
const sidebarPadding = theme.spacing.xs const sidebarPadding = theme.spacing.xs
const { classes } = useStyles({ const { classes } = useStyles({
sidebarWidth, sidebarWidth,
sidebarPadding, sidebarPadding,
sidebarRightBorderWidth: "1px", sidebarRightBorderWidth: "1px",
}) })
const { loading } = useAppLoading()
const mobileMenuOpen = useAppSelector(state => state.tree.mobileMenuOpen)
const webSocketConnected = useAppSelector(state => state.server.webSocketConnected)
const treeReloadInterval = useAppSelector(state => state.server.serverInfos?.treeReloadInterval)
const mobileFooter = useAppSelector(state => state.user.settings?.mobileFooter)
const headerInFooter = mobile && !isBrowserExtensionPopup && mobileFooter
const dispatch = useAppDispatch()
useWebSocket()
useEffect(() => { useEffect(() => {
// load initial data // load initial data
@@ -192,7 +194,10 @@ export default function Layout(props: LayoutProps) {
right: 1000, right: 1000,
}} }}
grid={[30, 30]} grid={[30, 30]}
onDrag={(_e, data) => setSidebarWidth(data.x)} onDrag={(_e, data) => {
dispatch(setSidebarWidth(data.x))
return
}}
> >
<Box <Box
style={{ style={{