From dda33474c3641a0ba950f5adc53c041279ea8fc4 Mon Sep 17 00:00:00 2001 From: Innei Date: Fri, 24 May 2024 21:12:42 +0800 Subject: [PATCH] refactor: extract outlet context as a outside context Signed-off-by: Innei --- .../src/components/entry-column/index.tsx | 28 ++++++----- .../components/entry-column/item-wrapper.tsx | 17 ++++--- .../src/components/feed-column/category.tsx | 46 ++++++++++--------- .../src/components/feed-column/index.tsx | 28 ++++++----- .../src/components/feed-column/item.tsx | 36 +++++++-------- .../src/components/feed-column/list.tsx | 14 ++---- .../src/contexts/outlet/main-layout.tsx | 17 +++++++ src/renderer/src/lib/types.ts | 2 +- .../src/pages/(main)/(context)/index.tsx | 33 ++++++------- .../src/pages/(main)/(context)/layout.tsx | 32 ++++++------- src/renderer/src/pages/(main)/layout.tsx | 25 +++++----- 11 files changed, 141 insertions(+), 137 deletions(-) create mode 100644 src/renderer/src/contexts/outlet/main-layout.tsx diff --git a/src/renderer/src/components/entry-column/index.tsx b/src/renderer/src/components/entry-column/index.tsx index 74f1839e2..4531126e2 100644 --- a/src/renderer/src/components/entry-column/index.tsx +++ b/src/renderer/src/components/entry-column/index.tsx @@ -1,5 +1,5 @@ import { useEntries } from "@renderer/lib/queries/entries" -import { ActivedList, ActivedEntry } from "@renderer/lib/types" +import { ActiveList, ActivedEntry } from "@renderer/lib/types" import { m } from "framer-motion" import { cn } from "@renderer/lib/utils" import { ArticleItem } from "./article-item" @@ -8,23 +8,21 @@ import { PictureItem } from "./picture-item" import { VideoItem } from "./video-item" import { NotificationItem } from "./notification-item" import { EntryItemWrapper } from "./item-wrapper" -import { useOutletContext } from "react-router-dom" + +import { useMainLayoutContext } from "@renderer/contexts/outlet/main-layout" const gridMode = [2, 3] export function EntryColumn() { - const { activedList, setActivedEntry } = useOutletContext<{ - activedList: ActivedList - setActivedEntry: (value: ActivedEntry) => void - }>() + const { activeList, setActiveEntry: setActivedEntry } = useMainLayoutContext() const entries = useEntries({ - level: activedList?.level, - id: activedList?.id, - view: activedList?.view, + level: activeList?.level, + id: activeList?.id, + view: activeList?.view, }) let Item - switch (activedList?.view) { + switch (activeList?.view) { case 0: Item = ArticleItem break @@ -47,7 +45,7 @@ export function EntryColumn() { return (
setActivedEntry(null)}>
-
{activedList?.name}
+
{activeList?.name}
{entries.data?.pages?.[0].total} Items
@@ -55,13 +53,13 @@ export function EntryColumn() {
{entries.data?.pages?.map((page, index) => ( @@ -69,7 +67,7 @@ export function EntryColumn() { diff --git a/src/renderer/src/components/entry-column/item-wrapper.tsx b/src/renderer/src/components/entry-column/item-wrapper.tsx index c47f65c11..74d40b5d0 100644 --- a/src/renderer/src/components/entry-column/item-wrapper.tsx +++ b/src/renderer/src/components/entry-column/item-wrapper.tsx @@ -1,8 +1,8 @@ -import { ActivedEntry, EntriesResponse } from "@renderer/lib/types" -import { cn } from "@renderer/lib/utils" -import { showNativeMenu } from "@renderer/lib/native-menu" +import { useMainLayoutContext } from "@renderer/contexts/outlet/main-layout" import { useEntryActions } from "@renderer/hooks/useEntryActions" -import { useOutletContext } from "react-router-dom" +import { showNativeMenu } from "@renderer/lib/native-menu" +import { EntriesResponse } from "@renderer/lib/types" +import { cn } from "@renderer/lib/utils" export function EntryItemWrapper({ entry, @@ -19,17 +19,16 @@ export function EntryItemWrapper({ view, entry, }) - const { activedEntry, setActivedEntry } = useOutletContext<{ - activedEntry: ActivedEntry - setActivedEntry: (value: ActivedEntry) => void - }>() + + const { activeEntry, setActiveEntry: setActivedEntry } = + useMainLayoutContext() return (
{ e.stopPropagation() diff --git a/src/renderer/src/components/feed-column/category.tsx b/src/renderer/src/components/feed-column/category.tsx index 388a009a3..4f7d2290c 100644 --- a/src/renderer/src/components/feed-column/category.tsx +++ b/src/renderer/src/components/feed-column/category.tsx @@ -2,20 +2,19 @@ import { Collapsible, CollapsibleTrigger, } from "@renderer/components/ui/collapsible" -import { m, AnimatePresence } from "framer-motion" -import { useEffect, useState } from "react" -import { levels } from "@renderer/lib/constants" -import { ActivedList } from "@renderer/lib/types" -import { cn } from "@renderer/lib/utils" -import { Response as SubscriptionsResponse } from "@renderer/lib/queries/subscriptions" -import { showNativeMenu } from "@renderer/lib/native-menu" -import { client } from "@renderer/lib/client" -import { useMutation, useQueryClient } from "@tanstack/react-query" -import { apiFetch } from "@renderer/lib/queries/api-fetch" -import { CategoryRenameDialog } from "./category-rename-dialog" import { Dialog } from "@renderer/components/ui/dialog" +import { useMainLayoutContext } from "@renderer/contexts/outlet/main-layout" +import { client } from "@renderer/lib/client" +import { levels } from "@renderer/lib/constants" +import { showNativeMenu } from "@renderer/lib/native-menu" +import { apiFetch } from "@renderer/lib/queries/api-fetch" +import { Response as SubscriptionsResponse } from "@renderer/lib/queries/subscriptions" +import { cn } from "@renderer/lib/utils" +import { useMutation, useQueryClient } from "@tanstack/react-query" +import { AnimatePresence, m } from "framer-motion" +import { useEffect, useState } from "react" +import { CategoryRenameDialog } from "./category-rename-dialog" import { FeedItem } from "./item" -import { useOutletContext } from "react-router-dom" export function FeedCategory({ data, @@ -26,10 +25,13 @@ export function FeedCategory({ view?: number expansion: boolean }) { - const { activedList, setActivedList } = useOutletContext<{ - activedList: ActivedList - setActivedList: ((value: ActivedList) => void) | null - }>() + const { + activeList, + setActiveEntry: setActivedEntry, + setActiveList, + activeEntry, + } = useMainLayoutContext() + const [open, setOpen] = useState(!data.name) const [dialogOpen, setDialogOpen] = useState(false) @@ -59,7 +61,7 @@ export function FeedCategory({ const setCatrgoryActive = () => { view !== undefined && - setActivedList?.({ + setActiveList?.({ level: levels.folder, id: data.list.map((feed) => feed.feedId).join(","), name: data.name, @@ -78,8 +80,8 @@ export function FeedCategory({
{ @@ -120,15 +122,15 @@ export function FeedCategory({ - {!setActivedList && ( + {!setActiveList && ( {data.name} )} - {setActivedList && {data.name}} + {setActiveList && {data.name}}
{!!data.unread && (
{data.unread}
diff --git a/src/renderer/src/components/feed-column/index.tsx b/src/renderer/src/components/feed-column/index.tsx index a2a5b6270..27a909ffd 100644 --- a/src/renderer/src/components/feed-column/index.tsx +++ b/src/renderer/src/components/feed-column/index.tsx @@ -1,27 +1,25 @@ +import { Button } from "@renderer/components/ui/button" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@renderer/components/ui/tooltip" -import { useEffect, useRef, useState } from "react" -import { useWheel } from "@use-gesture/react" -import { Lethargy } from "lethargy" -import { cn, clamp } from "@renderer/lib/utils" -import { m, useSpring } from "framer-motion" -import { FeedList } from "./list" -import { ActivedList } from "@renderer/lib/types" import { UserButton } from "@renderer/components/user-button" +import { useMainLayoutContext } from "@renderer/contexts/outlet/main-layout" import { levels, views } from "@renderer/lib/constants" -import { Link, useOutletContext } from "react-router-dom" -import { Button } from "@renderer/components/ui/button" +import { clamp, cn } from "@renderer/lib/utils" +import { useWheel } from "@use-gesture/react" +import { m, useSpring } from "framer-motion" +import { Lethargy } from "lethargy" +import { useEffect, useRef, useState } from "react" +import { Link } from "react-router-dom" +import { FeedList } from "./list" const lethargy = new Lethargy() export function FeedColumn() { - const { setActivedList } = useOutletContext<{ - setActivedList: (value: ActivedList) => void - }>() + const { setActiveList } = useMainLayoutContext() const carouselRef = useRef(null) const [active, setActive] = useState(0) @@ -61,7 +59,7 @@ export function FeedColumn() {
- setActivedList?.({ + setActiveList?.({ level: levels.view, id: active, name: views[active].name, @@ -75,7 +73,7 @@ export function FeedColumn() { className="font-bold text-xl flex items-center gap-1" onClick={(e) => { e.stopPropagation() - setActivedList?.({ + setActiveList?.({ level: levels.view, id: active, name: views[active].name, @@ -113,7 +111,7 @@ export function FeedColumn() { size="sm" onClick={(e) => { setActive(index) - setActivedList?.({ + setActiveList?.({ level: "view", id: index, name: views[index].name, diff --git a/src/renderer/src/components/feed-column/item.tsx b/src/renderer/src/components/feed-column/item.tsx index 7ca0a4fed..d1a3da613 100644 --- a/src/renderer/src/components/feed-column/item.tsx +++ b/src/renderer/src/components/feed-column/item.tsx @@ -1,25 +1,24 @@ -import { useState } from "react" -import { levels } from "@renderer/lib/constants" -import { ActivedList, SubscriptionResponse } from "@renderer/lib/types" -import { cn } from "@renderer/lib/utils" +import { FeedIcon } from "@renderer/components/feed-icon" +import { FollowDialog } from "@renderer/components/follow/dialog" +import { Dialog } from "@renderer/components/ui/dialog" +import { ToastAction } from "@renderer/components/ui/toast" import { Tooltip, TooltipContent, + TooltipPortal, TooltipProvider, TooltipTrigger, - TooltipPortal, } from "@renderer/components/ui/tooltip" -import { FeedIcon } from "@renderer/components/feed-icon" +import { useToast } from "@renderer/components/ui/use-toast" +import { useMainLayoutContext } from "@renderer/contexts/outlet/main-layout" +import { levels } from "@renderer/lib/constants" import dayjs from "@renderer/lib/dayjs" import { showNativeMenu } from "@renderer/lib/native-menu" -import { useMutation, useQueryClient } from "@tanstack/react-query" import { apiFetch } from "@renderer/lib/queries/api-fetch" -import { Dialog } from "@renderer/components/ui/dialog" -import { FollowDialog } from "@renderer/components/follow/dialog" -import { useToast } from "@renderer/components/ui/use-toast" -import { ToastAction } from "@renderer/components/ui/toast" -import { useOutletContext } from "react-router-dom" - +import { SubscriptionResponse } from "@renderer/lib/types" +import { cn } from "@renderer/lib/utils" +import { useMutation, useQueryClient } from "@tanstack/react-query" +import { useState } from "react" export function FeedItem({ feed, view, @@ -30,14 +29,11 @@ export function FeedItem({ className?: string }) { const [dialogOpen, setDialogOpen] = useState(false) - const { activedList, setActivedList } = useOutletContext<{ - activedList: ActivedList - setActivedList: (value: ActivedList) => void - }>() + const { activeList, setActiveList } = useMainLayoutContext() const setFeedActive = (feed: SubscriptionResponse[number]) => { view !== undefined && - setActivedList?.({ + setActiveList?.({ level: levels.feed, id: feed.feedId, name: feed.feeds.title || "", @@ -98,8 +94,8 @@ export function FeedItem({
void - }>() + const { setActiveList } = useMainLayoutContext() return (
@@ -33,7 +29,7 @@ export function FeedList({ onClick={(e) => { e.stopPropagation() view !== undefined && - setActivedList({ + setActiveList({ level: levels.view, id: view, name: views[view].name, diff --git a/src/renderer/src/contexts/outlet/main-layout.tsx b/src/renderer/src/contexts/outlet/main-layout.tsx new file mode 100644 index 000000000..549fe9205 --- /dev/null +++ b/src/renderer/src/contexts/outlet/main-layout.tsx @@ -0,0 +1,17 @@ +import type { ActiveList, ActivedEntry } from "@renderer/lib/types" +import { Outlet, useOutletContext } from "react-router-dom" + +export interface MainLayoutContextType { + activeList: ActiveList + setActiveEntry: (value: ActivedEntry) => void + + activeEntry: ActivedEntry + setActiveList: (value: ActiveList) => void +} + +export const useMainLayoutContext = () => + useOutletContext() + +export const MainLayoutOutlet = (ctxValue: MainLayoutContextType) => ( + +) diff --git a/src/renderer/src/lib/types.ts b/src/renderer/src/lib/types.ts index d944d4614..f124cad7b 100644 --- a/src/renderer/src/lib/types.ts +++ b/src/renderer/src/lib/types.ts @@ -1,4 +1,4 @@ -export type ActivedList = { +export type ActiveList = { level: string id: string | number name: string diff --git a/src/renderer/src/pages/(main)/(context)/index.tsx b/src/renderer/src/pages/(main)/(context)/index.tsx index 750d762ef..611871e51 100644 --- a/src/renderer/src/pages/(main)/(context)/index.tsx +++ b/src/renderer/src/pages/(main)/(context)/index.tsx @@ -1,30 +1,28 @@ import { EntryColumn } from "@renderer/components/entry-column" -import { useEffect } from "react" -import { ActivedList, ActivedEntry } from "@renderer/lib/types" -import { cn } from "@renderer/lib/utils" import { EntryContent } from "@renderer/components/entry-content" +import { useMainLayoutContext } from "@renderer/contexts/outlet/main-layout" +import { cn } from "@renderer/lib/utils" import { AnimatePresence } from "framer-motion" -import { useOutletContext } from "react-router-dom" +import { useEffect } from "react" const wideMode = [1, 2, 3, 4] export function Component() { - const { activedList, activedEntry, setActivedEntry } = useOutletContext<{ - activedList: ActivedList - activedEntry: ActivedEntry - setActivedEntry: (value: ActivedEntry) => void - }>() - + const { + activeList, + activeEntry, + setActiveEntry: setActivedEntry, + } = useMainLayoutContext() useEffect(() => { setActivedEntry(null) - }, [activedList]) + }, [activeList]) return ( <>
- {!(activedList && wideMode.includes(activedList.view)) && - activedEntry && ( -
- -
- )} + {!(activeList && wideMode.includes(activeList.view)) && activeEntry && ( +
+ +
+ )}
) diff --git a/src/renderer/src/pages/(main)/(context)/layout.tsx b/src/renderer/src/pages/(main)/(context)/layout.tsx index ae47a4f2a..5559c9a6a 100644 --- a/src/renderer/src/pages/(main)/(context)/layout.tsx +++ b/src/renderer/src/pages/(main)/(context)/layout.tsx @@ -1,27 +1,27 @@ import { FeedColumn } from "@renderer/components/feed-column" -import { ActivedEntry, ActivedList } from "@renderer/lib/types" -import { Outlet, useOutletContext } from "react-router-dom" +import { + MainLayoutOutlet, + useMainLayoutContext, +} from "@renderer/contexts/outlet/main-layout" export function Component() { - const { activedList, setActivedList, activedEntry, setActivedEntry } = - useOutletContext<{ - activedList: ActivedList - setActivedList: (value: ActivedList) => void - activedEntry: ActivedEntry - setActivedEntry: (value: ActivedEntry) => void - }>() - + const { + activeEntry, + activeList, + setActiveList, + setActiveEntry: setActivedEntry, + } = useMainLayoutContext() return (
-
diff --git a/src/renderer/src/pages/(main)/layout.tsx b/src/renderer/src/pages/(main)/layout.tsx index 196460446..a07d94894 100644 --- a/src/renderer/src/pages/(main)/layout.tsx +++ b/src/renderer/src/pages/(main)/layout.tsx @@ -1,38 +1,39 @@ import { useEffect, useState } from "react" -import { ActivedList, ActivedEntry } from "@renderer/lib/types" +import { ActiveList, ActivedEntry } from "@renderer/lib/types" import { Outlet } from "react-router-dom" import { useNavigate } from "react-router-dom" import { useSession } from "@hono/auth-js/react" +import { MainLayoutOutlet } from "@renderer/contexts/outlet/main-layout" export function Component() { const { status } = useSession() const navigate = useNavigate() - const [activedList, setActivedList] = useState({ + const [activeList, setActiveList] = useState({ level: "view", id: 0, name: "Articles", view: 0, }) - const [activedEntry, setActivedEntry] = useState(null) + const [activeEntry, setActiveEntry] = useState(null) useEffect(() => { - setActivedEntry(null) - if (!activedList?.preventNavigate) { + setActiveEntry(null) + if (!activeList?.preventNavigate) { navigate("/") } - }, [activedList]) + }, [activeList]) if (status !== "authenticated") { return navigate("/login") } return ( - )