From a1fb5871d15029048e604be2c4e4159ddd0fcc66 Mon Sep 17 00:00:00 2001 From: Athou Date: Tue, 23 Aug 2022 13:42:28 +0200 Subject: [PATCH] add initial support for expanded mode --- commafeed-client/.eslintrc | 2 +- commafeed-client/src/app/slices/user.ts | 12 ++++- .../src/components/content/FeedEntries.tsx | 3 +- .../src/components/content/FeedEntry.tsx | 6 ++- .../src/components/header/ProfileMenu.tsx | 49 ++++++++++++++++++- commafeed-client/src/locales/en/messages.po | 9 ++++ commafeed-client/src/locales/fr/messages.po | 9 ++++ 7 files changed, 83 insertions(+), 7 deletions(-) diff --git a/commafeed-client/.eslintrc b/commafeed-client/.eslintrc index 3607f9e1..cf364c03 100644 --- a/commafeed-client/.eslintrc +++ b/commafeed-client/.eslintrc @@ -35,7 +35,7 @@ "react-hooks/exhaustive-deps": [ "warn", { - "additionalHooks": "(^useAsync$)" + "additionalHooks": "(^useAsync$|useDidUpdate)" } ], diff --git a/commafeed-client/src/app/slices/user.ts b/commafeed-client/src/app/slices/user.ts index e8dabb38..3e5ada5d 100644 --- a/commafeed-client/src/app/slices/user.ts +++ b/commafeed-client/src/app/slices/user.ts @@ -3,7 +3,7 @@ import { showNotification } from "@mantine/notifications" import { createAsyncThunk, createSlice, isAnyOf } from "@reduxjs/toolkit" import { client } from "app/client" import { RootState } from "app/store" -import { ReadingMode, ReadingOrder, Settings, SharingSettings, UserModel } from "app/types" +import { ReadingMode, ReadingOrder, Settings, SharingSettings, UserModel, ViewMode } from "app/types" import { reloadEntries } from "./entries" interface UserState { @@ -33,6 +33,12 @@ export const changeReadingOrder = createAsyncThunk("settings/viewMode", (viewMode, thunkApi) => { + const { settings } = thunkApi.getState().user + if (!settings) return + client.user.saveSettings({ ...settings, viewMode }) + thunkApi.dispatch(reloadEntries()) +}) export const changeLanguage = createAsyncThunk("settings/language", (language, thunkApi) => { const { settings } = thunkApi.getState().user if (!settings) return @@ -82,6 +88,10 @@ export const userSlice = createSlice({ if (!state.settings) return state.settings.readingOrder = action.meta.arg }) + builder.addCase(changeViewMode.pending, (state, action) => { + if (!state.settings) return + state.settings.viewMode = action.meta.arg + }) builder.addCase(changeLanguage.pending, (state, action) => { if (!state.settings) return state.settings.language = action.meta.arg diff --git a/commafeed-client/src/components/content/FeedEntries.tsx b/commafeed-client/src/components/content/FeedEntries.tsx index de4d479d..6bb2437a 100644 --- a/commafeed-client/src/components/content/FeedEntries.tsx +++ b/commafeed-client/src/components/content/FeedEntries.tsx @@ -25,6 +25,7 @@ export function FeedEntries() { const entriesTimestamp = useAppSelector(state => state.entries.timestamp) const selectedEntryId = useAppSelector(state => state.entries.selectedEntryId) const hasMore = useAppSelector(state => state.entries.hasMore) + const viewMode = useAppSelector(state => state.user.settings?.viewMode) const dispatch = useAppDispatch() const selectedEntry = entries.find(e => e.id === selectedEntryId) @@ -151,7 +152,7 @@ export function FeedEntries() { refs.current[e.id] = el! }} > - + ))} diff --git a/commafeed-client/src/components/content/FeedEntry.tsx b/commafeed-client/src/components/content/FeedEntry.tsx index 793d09dd..34881c7b 100644 --- a/commafeed-client/src/components/content/FeedEntry.tsx +++ b/commafeed-client/src/components/content/FeedEntry.tsx @@ -1,9 +1,10 @@ import { Anchor, Box, createStyles, Divider, Paper } from "@mantine/core" +import { useDidUpdate } from "@mantine/hooks" import { Constants } from "app/constants" import { markEntry, selectEntry } from "app/slices/entries" import { useAppDispatch, useAppSelector } from "app/store" import { Entry } from "app/types" -import React, { useEffect, useRef } from "react" +import React, { useRef } from "react" import { FeedEntryBody } from "./FeedEntryBody" import { FeedEntryFooter } from "./FeedEntryFooter" import { FeedEntryHeader } from "./FeedEntryHeader" @@ -53,8 +54,9 @@ export function FeedEntry(props: FeedEntryProps) { } // scroll to entry when expanded + // we use useDidUpdate to avoid scrolling towards all entries during initial load when viewMode is "expanded" const ref = useRef(null) - useEffect(() => { + useDidUpdate(() => { setTimeout(() => { if (!ref.current) return if (!props.expanded) return diff --git a/commafeed-client/src/components/header/ProfileMenu.tsx b/commafeed-client/src/components/header/ProfileMenu.tsx index a5f9f259..b4692b07 100644 --- a/commafeed-client/src/components/header/ProfileMenu.tsx +++ b/commafeed-client/src/components/header/ProfileMenu.tsx @@ -1,16 +1,48 @@ import { Trans } from "@lingui/macro" -import { Divider, Menu, useMantineColorScheme } from "@mantine/core" +import { Box, Divider, Group, Menu, SegmentedControl, SegmentedControlItem, useMantineColorScheme } from "@mantine/core" import { redirectToAbout, redirectToAdminUsers, redirectToMetrics, redirectToSettings } from "app/slices/redirect" +import { changeViewMode } from "app/slices/user" import { useAppDispatch, useAppSelector } from "app/store" +import { ViewMode } from "app/types" import { useState } from "react" -import { TbChartLine, TbHelp, TbMoon, TbPower, TbSettings, TbSun, TbUsers } from "react-icons/tb" +import { TbChartLine, TbHelp, TbList, TbMoon, TbNotes, TbPower, TbSettings, TbSun, TbUsers } from "react-icons/tb" interface ProfileMenuProps { control: React.ReactElement } +interface ViewModeControlItem extends SegmentedControlItem { + value: ViewMode +} + +const viewModeData: ViewModeControlItem[] = [ + { + value: "title", + label: ( + + + + Compact + + + ), + }, + { + value: "expanded", + label: ( + + + + Expanded + + + ), + }, +] + export function ProfileMenu(props: ProfileMenuProps) { const [opened, setOpened] = useState(false) + const viewMode = useAppSelector(state => state.user.settings?.viewMode) const admin = useAppSelector(state => state.user.profile?.admin) const dispatch = useAppDispatch() const { colorScheme, toggleColorScheme } = useMantineColorScheme() @@ -33,9 +65,22 @@ export function ProfileMenu(props: ProfileMenuProps) { > Settings + + + + Display + : } onClick={() => toggleColorScheme()}> Theme + dispatch(changeViewMode(e as ViewMode))} + mb="xs" + /> {admin && ( <> diff --git a/commafeed-client/src/locales/en/messages.po b/commafeed-client/src/locales/en/messages.po index 8cea0ddf..f8f304cc 100644 --- a/commafeed-client/src/locales/en/messages.po +++ b/commafeed-client/src/locales/en/messages.po @@ -161,6 +161,10 @@ msgstr "CommaFeed next unread item" msgid "CommaFeed version {version} ({revision})" msgstr "CommaFeed version {version} ({revision})" +#: src/components/header/ProfileMenu.tsx +msgid "Compact" +msgstr "Compact" + #: src/components/header/MarkAllAsReadButton.tsx #: src/components/settings/ProfileSettings.tsx #: src/pages/admin/AdminUsersPage.tsx @@ -202,6 +206,7 @@ msgstr "Delete user" msgid "Desc" msgstr "Desc" +#: src/components/header/ProfileMenu.tsx #: src/pages/app/SettingsPage.tsx msgid "Display" msgstr "Display" @@ -252,6 +257,10 @@ msgstr "Error" msgid "Example: {example}." msgstr "Example: {example}." +#: src/components/header/ProfileMenu.tsx +msgid "Expanded" +msgstr "Expanded" + #: src/components/settings/ProfileSettings.tsx msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services" msgstr "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services" diff --git a/commafeed-client/src/locales/fr/messages.po b/commafeed-client/src/locales/fr/messages.po index 819956ce..97e81aa8 100644 --- a/commafeed-client/src/locales/fr/messages.po +++ b/commafeed-client/src/locales/fr/messages.po @@ -161,6 +161,10 @@ msgstr "CommaFeed prochain article non lu" msgid "CommaFeed version {version} ({revision})" msgstr "CommaFeed version {version} ({revision})" +#: src/components/header/ProfileMenu.tsx +msgid "Compact" +msgstr "Compact" + #: src/components/header/MarkAllAsReadButton.tsx #: src/components/settings/ProfileSettings.tsx #: src/pages/admin/AdminUsersPage.tsx @@ -202,6 +206,7 @@ msgstr "Effacer l'utilisateur" msgid "Desc" msgstr "Descendant" +#: src/components/header/ProfileMenu.tsx #: src/pages/app/SettingsPage.tsx msgid "Display" msgstr "Affichage" @@ -252,6 +257,10 @@ msgstr "Erreur" msgid "Example: {example}." msgstr "Exemple : {example}." +#: src/components/header/ProfileMenu.tsx +msgid "Expanded" +msgstr "Vue étendue" + #: src/components/settings/ProfileSettings.tsx msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services" msgstr "Exporter vos abonnements et catégories en tant que fichier OPML qui peut être importé dans d'autres services de lecture de flux"