Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-06-19 13:10:19 +08:00
parent 7b349895b1
commit 7928e0faf3
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
17 changed files with 94 additions and 46 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="#fff" fill-opacity=".01" d="M24 0v24H0V0z"/><path stroke="#10161F" stroke-linecap="round" stroke-width="2" d="M4 20 20 4"/></svg>

After

Width:  |  Height:  |  Size: 216 B

View File

@ -10,8 +10,8 @@ describe("test route builder", () => {
"./pages/(external)/layout.tsx": fakePromise,
"./pages/(external)/(with-layout)/index.tsx": fakePromise,
"./pages/(external)/(with-layout)/layout.tsx": fakePromise,
"./pages/(external)/(with-layout)/feed/[:id]/index.tsx": fakePromise,
"./pages/(external)/(with-layout)/feed/[:id]/layout.tsx": fakePromise,
"./pages/(external)/(with-layout)/feed/[id]/index.tsx": fakePromise,
"./pages/(external)/(with-layout)/feed/[id]/layout.tsx": fakePromise,
"./pages/(main)/layout.tsx": fakePromise,
"./pages/(main)/(context)/layout.tsx": fakePromise,

View File

@ -189,7 +189,7 @@ const normalizePathKey = (key: string) => {
return ""
}
if (key.startsWith("[:") && key.endsWith("]")) {
if (key.startsWith("[") && key.endsWith("]")) {
return `:${key.slice(2, -1)}`
}
return key

View File

@ -21,6 +21,7 @@ import {
useUnreadStore,
} from "@renderer/store"
import { useMutation } from "@tanstack/react-query"
import { useNavigate } from "react-router-dom"
import { toast } from "sonner"
import { FeedForm } from "../discover/feed-form"
@ -97,6 +98,7 @@ export function FeedItem({
const feedUnread = useUnreadStore((state) => state.data[feed.feedId] || 0)
const { present } = useModalStack()
const navigate = useNavigate()
return (
<div
className={cn(
@ -109,6 +111,7 @@ export function FeedItem({
onClick={(e) => {
e.stopPropagation()
setFeedActive(feed)
navigate(`/feeds/${feed.feedId}`)
}}
onDoubleClick={() => {
window.open(

View File

@ -1,17 +0,0 @@
import { setMainContainerElement } from "@renderer/atoms"
import { FeedColumn } from "@renderer/modules/feed-column"
import { Outlet } from "react-router-dom"
export function Component() {
return (
<div className="flex h-full">
<div className="w-64 shrink-0 border-r">
<FeedColumn />
</div>
{/* NOTE: tabIndex for main element can get by `document.activeElement` */}
<main ref={setMainContainerElement} className="flex min-w-0 flex-1 bg-theme-background !outline-none" tabIndex={-1}>
<Outlet />
</main>
</div>
)
}

View File

@ -3,13 +3,12 @@ import { cn } from "@renderer/lib/utils"
import { EntryColumn } from "@renderer/modules/entry-column"
import { EntryContent } from "@renderer/modules/entry-content"
import {
feedActions,
uiActions,
useFeedStore,
useUIStore,
} from "@renderer/store"
import { AnimatePresence } from "framer-motion"
import { useEffect, useMemo, useRef } from "react"
import { useMemo, useRef } from "react"
import { useResizable } from "react-resizable-layout"
import { useShallow } from "zustand/react/shallow"
@ -20,10 +19,7 @@ export function Component() {
activeEntry: state.activeEntryId,
})),
)
const { setActiveEntry } = feedActions
useEffect(() => {
setActiveEntry(null)
}, [activeList?.id])
const containerRef = useRef<HTMLDivElement>(null)
// Memo this initial value to avoid re-render

View File

@ -0,0 +1 @@
export { Outlet as Component } from "react-router-dom"

View File

@ -0,0 +1,70 @@
import { views } from "@renderer/lib/constants"
import { cn } from "@renderer/lib/utils"
import { EntryColumn } from "@renderer/modules/entry-column"
import { EntryContent } from "@renderer/modules/entry-content"
import {
uiActions,
useFeedStore,
useUIStore,
} from "@renderer/store"
import { AnimatePresence } from "framer-motion"
import { useMemo, useRef } from "react"
import { useResizable } from "react-resizable-layout"
import { useShallow } from "zustand/react/shallow"
export function Component() {
const { activeEntry, activeList } = useFeedStore(
useShallow((state) => ({
activeList: state.activeList,
activeEntry: state.activeEntryId,
})),
)
const containerRef = useRef<HTMLDivElement>(null)
// Memo this initial value to avoid re-render
// eslint-disable-next-line react-compiler/react-compiler
const entryColWidth = useMemo(() => useUIStore.getState().entryColWidth, [])
const { position, separatorProps } = useResizable({
axis: "x",
min: 300,
max: 450,
initial: entryColWidth,
containerRef,
onResizeEnd({ position }) {
uiActions.setEntryColWidth(position)
},
})
const inWideMode = activeList && views[activeList.view].wideMode
return (
<div ref={containerRef} className="flex min-w-0 grow">
<div
className={cn(
"h-full shrink-0 overflow-y-auto",
inWideMode ? "flex-1" : "border-r",
"will-change-[width]",
)}
style={{
width: position,
}}
>
<EntryColumn />
</div>
{!inWideMode && (
<div
{...separatorProps}
className="h-full w-px shrink-0 cursor-ew-resize hover:bg-border"
/>
)}
<AnimatePresence>
{!inWideMode && (
<div className="min-w-0 flex-1">
<EntryContent entry={activeEntry} />
</div>
)}
</AnimatePresence>
</div>
)
}

View File

@ -1,22 +1,17 @@
import { feedActions, useFeedStore } from "@renderer/store"
import { useEffect } from "react"
import { Outlet, useNavigate } from "react-router-dom"
import { setMainContainerElement } from "@renderer/atoms"
import { FeedColumn } from "@renderer/modules/feed-column"
import { Outlet } from "react-router-dom"
function MainLayout() {
const navigate = useNavigate()
const changed = useFeedStore(
(state) => `${state.activeList?.view}-${state.activeList?.id}`,
export function Component() {
return (
<div className="flex h-full">
<div className="w-64 shrink-0 border-r">
<FeedColumn />
</div>
{/* NOTE: tabIndex for main element can get by `document.activeElement` */}
<main ref={setMainContainerElement} className="flex min-w-0 flex-1 bg-theme-background !outline-none" tabIndex={-1}>
<Outlet />
</main>
</div>
)
useEffect(() => {
feedActions.setActiveEntry(null)
if (changed) {
navigate("/")
}
}, [changed])
return <Outlet />
}
export { MainLayout as Component }

View File

@ -5,7 +5,6 @@ import { buildGlobRoutes } from "./lib/route-builder"
const globTree = import.meta.glob("./pages/**/*.tsx")
const tree = buildGlobRoutes(globTree)
// console.log(tree)
export const router = createBrowserRouter([
{