From 9f7f87b4ae332975b948df78f42094aecf7cf5a2 Mon Sep 17 00:00:00 2001 From: Athou Date: Sat, 2 May 2026 08:14:41 +0200 Subject: [PATCH] move handlers in Layout because they actually only apply to the reader pages --- commafeed-client/src/App.tsx | 89 +--------- commafeed-client/src/pages/app/Layout.tsx | 196 ++++++++++++++++------ 2 files changed, 142 insertions(+), 143 deletions(-) diff --git a/commafeed-client/src/App.tsx b/commafeed-client/src/App.tsx index 10fa065d..fd93c839 100644 --- a/commafeed-client/src/App.tsx +++ b/commafeed-client/src/App.tsx @@ -4,21 +4,16 @@ import { MantineProvider, v8CssVariablesResolver } from "@mantine/core" import { ModalsProvider } from "@mantine/modals" import { Notifications } from "@mantine/notifications" import type React from "react" -import { useEffect, useState } from "react" +import { useEffect } from "react" import { HashRouter, Navigate, Route, Routes, useNavigate } from "react-router-dom" -import Tinycon from "tinycon" import { Constants } from "@/app/constants" import { redirectTo } from "@/app/redirect/slice" import { redirectToInitialSetup } from "@/app/redirect/thunks" import { reloadServerInfos } from "@/app/server/thunks" import { useAppDispatch, useAppSelector } from "@/app/store" -import { categoryUnreadCount } from "@/app/utils" -import { DisablePullToRefresh } from "@/components/DisablePullToRefresh" import { ErrorBoundary } from "@/components/ErrorBoundary" import { Header } from "@/components/header/Header" import { Tree } from "@/components/sidebar/Tree" -import { useAppLoading } from "@/hooks/useAppLoading" -import { useBrowserExtension } from "@/hooks/useBrowserExtension" import { useI18n } from "@/i18n" import { AdminUsersPage } from "@/pages/admin/AdminUsersPage" import { MetricsPage } from "@/pages/admin/MetricsPage" @@ -146,83 +141,8 @@ function RedirectHandler() { return null } -function UnreadCountTitleHandler({ - enabled, -}: Readonly<{ - enabled?: boolean -}>) { - const root = useAppSelector(state => state.tree.rootCategory) - const unreadCount = categoryUnreadCount(root) - return {enabled && unreadCount > 0 ? `(${unreadCount}) CommaFeed` : "CommaFeed"} -} - -function UnreadCountFaviconHandler({ enabled }: { enabled?: boolean }) { - const root = useAppSelector(state => state.tree.rootCategory) - const unreadCount = categoryUnreadCount(root) - useEffect(() => { - if (enabled && unreadCount > 0) { - Tinycon.setBubble(unreadCount) - } else { - Tinycon.reset() - } - }, [unreadCount, enabled]) - - return null -} - -function BrowserExtensionBadgeUnreadCountHandler() { - const root = useAppSelector(state => state.tree.rootCategory) - const { setBadgeUnreadCount } = useBrowserExtension() - useEffect(() => { - if (!root) return - const unreadCount = categoryUnreadCount(root) - setBadgeUnreadCount(unreadCount) - }, [root, setBadgeUnreadCount]) - - return null -} - -function CustomJsHandler() { - const [scriptLoaded, setScriptLoaded] = useState(false) - const { loading } = useAppLoading() - - useEffect(() => { - if (scriptLoaded || loading) { - return - } - - const script = document.createElement("script") - script.src = "custom_js.js" - script.async = true - document.body.appendChild(script) - - setScriptLoaded(true) - - return () => script.remove() - }, [scriptLoaded, loading]) - - return null -} - -function CustomCssHandler() { - useEffect(() => { - const link = document.createElement("link") - link.rel = "stylesheet" - link.type = "text/css" - link.href = "custom_css.css" - document.head.appendChild(link) - - return () => link.remove() - }, []) - - return null -} - export function App() { useI18n() - 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 dispatch = useAppDispatch() useEffect(() => { @@ -231,13 +151,6 @@ export function App() { return ( - - - - - - - diff --git a/commafeed-client/src/pages/app/Layout.tsx b/commafeed-client/src/pages/app/Layout.tsx index 48846e4d..0b44928d 100644 --- a/commafeed-client/src/pages/app/Layout.tsx +++ b/commafeed-client/src/pages/app/Layout.tsx @@ -1,10 +1,11 @@ import { msg } from "@lingui/core/macro" import { ActionIcon, AppShell, Box, Center, Group, ScrollArea, Title, useMantineTheme } from "@mantine/core" -import { type ReactNode, type RefObject, Suspense, useEffect, useRef } from "react" +import { type ReactNode, type RefObject, Suspense, useEffect, useRef, useState } from "react" import Draggable from "react-draggable" import { TbMenu2, TbPlus, TbX } from "react-icons/tb" import { Outlet } from "react-router-dom" import { useSwipeable } from "react-swipeable" +import Tinycon from "tinycon" import { Constants } from "@/app/constants" import { redirectToAdd, redirectToRootCategory } from "@/app/redirect/thunks" import { useAppDispatch, useAppSelector } from "@/app/store" @@ -12,8 +13,10 @@ import { setMobileMenuOpen } from "@/app/tree/slice" import { reloadTree } from "@/app/tree/thunks" import { setSidebarWidth } from "@/app/user/slice" import { reloadProfile, reloadSettings, reloadTags } from "@/app/user/thunks" +import { categoryUnreadCount } from "@/app/utils" import { ActionButton } from "@/components/ActionButton" import { AnnouncementDialog } from "@/components/AnnouncementDialog" +import { DisablePullToRefresh } from "@/components/DisablePullToRefresh" import { Loader } from "@/components/Loader" import { Logo } from "@/components/Logo" import { MarkAllAsReadConfirmationDialog } from "@/components/MarkAllAsReadConfirmationDialog" @@ -51,6 +54,78 @@ function LogoAndTitle() { ) } +function UnreadCountTitleHandler({ + enabled, +}: Readonly<{ + enabled?: boolean +}>) { + const root = useAppSelector(state => state.tree.rootCategory) + const unreadCount = categoryUnreadCount(root) + return {enabled && unreadCount > 0 ? `(${unreadCount}) CommaFeed` : "CommaFeed"} +} + +function UnreadCountFaviconHandler({ enabled }: { enabled?: boolean }) { + const root = useAppSelector(state => state.tree.rootCategory) + const unreadCount = categoryUnreadCount(root) + useEffect(() => { + if (enabled && unreadCount > 0) { + Tinycon.setBubble(unreadCount) + } else { + Tinycon.reset() + } + }, [unreadCount, enabled]) + + return null +} + +function BrowserExtensionBadgeUnreadCountHandler() { + const root = useAppSelector(state => state.tree.rootCategory) + const { setBadgeUnreadCount } = useBrowserExtension() + useEffect(() => { + if (!root) return + const unreadCount = categoryUnreadCount(root) + setBadgeUnreadCount(unreadCount) + }, [root, setBadgeUnreadCount]) + + return null +} + +function CustomJsHandler() { + const [scriptLoaded, setScriptLoaded] = useState(false) + const { loading } = useAppLoading() + + useEffect(() => { + if (scriptLoaded || loading) { + return + } + + const script = document.createElement("script") + script.src = "custom_js.js" + script.async = true + document.body.appendChild(script) + + setScriptLoaded(true) + + return () => script.remove() + }, [scriptLoaded, loading]) + + return null +} + +function CustomCssHandler() { + useEffect(() => { + const link = document.createElement("link") + link.rel = "stylesheet" + link.type = "text/css" + link.href = "custom_css.css" + document.head.appendChild(link) + + return () => link.remove() + }, []) + + return null +} + const useStyles = tss .withParams<{ sidebarWidth: number @@ -75,6 +150,9 @@ export default function Layout(props: Readonly) { const draggableSeparator = useRef(null) const { loading } = useAppLoading() + 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 mobileMenuOpen = useAppSelector(state => state.tree.mobileMenuOpen) const webSocketConnected = useAppSelector(state => state.server.webSocketConnected) const treeReloadInterval = useAppSelector(state => state.server.serverInfos?.treeReloadInterval) @@ -173,61 +251,69 @@ export default function Layout(props: Readonly) { if (loading) return return ( - - - {!headerInFooter && header} - {headerInFooter && header} - - - {props.sidebar} - - - - } - axis="x" - defaultPosition={{ - x: sidebarWidth, - y: 0, - }} - bounds={{ - left: 120, - right: 1000, - }} - grid={[30, 30]} - onDrag={(_e, data) => { - dispatch(setSidebarWidth(data.x)) - }} - > - + + + + + + + + + {!headerInFooter && header} + {headerInFooter && header} + + + {props.sidebar} + + + + } + axis="x" + defaultPosition={{ + x: sidebarWidth, + y: 0, }} - /> - - + bounds={{ + left: 120, + right: 1000, + }} + grid={[30, 30]} + onDrag={(_e, data) => { + dispatch(setSidebarWidth(data.x)) + }} + > + + + - - }> - - - - - - - + + }> + + + + + + + + ) }