fix: import-circular for settings (#100)

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-07-01 14:08:56 +08:00 committed by GitHub
parent 942239d191
commit 2fec96b925
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 56 additions and 32 deletions

View File

@ -4,13 +4,12 @@ import { useEffect } from "react"
import { Outlet } from "react-router-dom"
import { useDark } from "./hooks/common/useDark"
import { useSettingModal } from "./modules/settings/modal/hooks"
import { RootProviders } from "./providers/root-providers"
import { handlers } from "./tipc"
function App() {
useDark()
const showSetting = useSettingModal()
useEffect(() => {
const cleanup = handlers?.invalidateQuery.listen((queryKey) => {
queryClient.invalidateQueries({
@ -19,7 +18,7 @@ function App() {
})
registerGlobalContext({
showSetting,
showSetting: window.router.showSettings,
})
return cleanup
}, [])

View File

@ -1,4 +1,3 @@
export * from "./useAsRead"
export * from "./useAuth"
export * from "./useBizQuery"
export * from "./useEntryActions"

View File

@ -1,3 +1,4 @@
export * from "./useBizQuery"
export * from "./useDark"
export * from "./usePrevious"
export * from "./useRefValue"

View File

@ -1,4 +1,5 @@
import { get, omit } from "lodash-es"
import { Fragment } from "react/jsx-runtime"
import type { RouteObject } from "react-router-dom"
type NestedStructure = { [key: string]: NestedStructure }
@ -83,7 +84,7 @@ export function buildGlobRoutes(
if (isGroupedRoute) {
const accessPath = `${segmentPathKey}/layout.tsx`
const globGetter = get(glob, accessPath)
const globGetter = get(glob, accessPath) || (() => Fragment)
if (pathGetterSet.has(accessPath)) {
// throw new Error(`duplicate path: ` + accessPath)
@ -91,9 +92,9 @@ export function buildGlobRoutes(
}
pathGetterSet.add(accessPath)
if (!globGetter) {
throw new Error("grouped route must have a layout file")
}
// if (!globGetter) {
// throw new Error("grouped route must have a layout file")
// }
const childrenChildren: RouteObject[] = []
dtsRoutes(`${segmentPathKey}/`, childrenChildren, paths[key], parentPath)

View File

@ -1,7 +1,8 @@
import type { SettingPageConfig } from "./utils"
function getSettings() {
const map = import.meta.glob("../../pages/settings/*.tsx", { eager: true })
// eslint-disable-next-line unicorn/prefer-string-raw
const map = import.meta.glob("../../pages/settings/\\(settings\\)/*", { eager: true })
const settings = [] as {
name: string
@ -9,9 +10,10 @@ function getSettings() {
path: string
Component: () => JSX.Element
priority: number
loader: () => SettingPageConfig
}[]
for (const path in map) {
const p = path.split("/").pop()?.replace(".tsx", "")!
const p = path.split("/").pop()?.replace(".tsx", "").replace("(settings)", "")!
if (p === "index" || p === "layout") continue
@ -24,6 +26,7 @@ function getSettings() {
settings.push({
...Module.loader(),
Component: Module.Component,
loader: Module.loader,
path: p,
})
}

View File

@ -1,21 +1,22 @@
import { LoadRemixAsyncComponent } from "@renderer/components/common/LoadRemixAsyncComponent"
import { MotionButtonBase } from "@renderer/components/ui/button"
import { useCurrentModal } from "@renderer/components/ui/modal"
import { ScrollArea } from "@renderer/components/ui/scroll-area"
import { SettingsTitle } from "@renderer/modules/settings/title"
import type { FC } from "react"
import { settings } from "../constants"
import { SettingTabProvider, useSettingTab } from "./context"
import { SettingModalLayout } from "./layout"
const pages = (() => {
const map = import.meta.glob("@renderer/pages/settings/*.tsx")
const pages = {}
for (const key in map) {
const filename = key.split("/").pop()
if (!filename) continue
const settingKey = filename.split(".").slice(0, -1).join(".")
pages[settingKey] = map[key]
for (const setting of settings) {
const filename = setting.path
pages[filename] = {
Component: setting.Component,
loader: setting.loader,
}
}
return pages
})()
@ -49,10 +50,16 @@ const Close = () => {
}
const Content = () => {
const key = useSettingTab()
const Component = pages[key]
const key = useSettingTab() || "general"
const { Component, loader } = pages[key]
if (!Component) return null
return <LoadRemixAsyncComponent Header={SettingsTitle} loader={Component} />
return (
<>
<SettingsTitle loader={loader} />
<Component />
</>
)
}

View File

@ -0,0 +1,3 @@
// HACK: Use expose the navigate function in the window object, avoid to import `router` circular issue.
// eslint-disable-next-line @eslint-react/hooks-extra/ensure-custom-hooks-using-other-hooks
export const useSettingModal = () => window.router.showSettings

View File

@ -12,7 +12,7 @@ import { from, subtract, toNumber } from "dnum"
import type { FC } from "react"
import { useState } from "react"
import { useSettingModal } from "../settings/modal/hooks"
import { useSettingModal } from "../settings/modal/hooks-hack"
const DEFAULT_RECOMMENDED_TIP = 0.1

View File

@ -1,8 +1,11 @@
import { redirect } from "react-router-dom"
import { nextFrame } from "@renderer/lib/dom"
import { useLayoutEffect } from "react"
export const Component = () => null
export const loader = () => {
redirect("/settings/general")
export const Component = () => {
useLayoutEffect(() => {
nextFrame(
() => router.navigate("/settings/general"),
)
}, [])
return null
}

View File

@ -1,4 +1,5 @@
import { setNavigate, setRoute } from "@renderer/atoms"
import { useSettingModal } from "@renderer/modules/settings/modal/hooks"
import { useLayoutEffect } from "react"
import type { NavigateFunction } from "react-router-dom"
import {
@ -11,11 +12,17 @@ import {
declare global {
export const router: {
navigate: NavigateFunction
showSettings: (initialTab?: string | undefined) => () => void
}
interface Window {
router: typeof router
}
}
window.router = {
navigate() {},
// eslint-disable-next-line unicorn/consistent-function-scoping
showSettings: () => () => {},
}
/**
* Why this.
@ -30,17 +37,18 @@ export const StableRouterProvider = () => {
const nav = useNavigate()
const location = useLocation()
const showSettings = useSettingModal()
// NOTE: This is a hack to expose the navigate function to the window object, avoid to import `router` circular issue.
window.router = {
navigate: nav,
}
useLayoutEffect(() => {
window.router.navigate = nav
window.router.showSettings = showSettings
setRoute({
params,
searchParams,
location,
})
setNavigate({ fn: nav })
}, [searchParams, params, location, nav])
}, [searchParams, params, location, nav, showSettings])
return null
}

View File

@ -7,7 +7,7 @@ import { feedActions } from "@renderer/store"
import { useMutation } from "@tanstack/react-query"
import { toast } from "sonner"
import { Queries } from "."
import { entries } from "./entries"
export const feed = {
byId: ({ id, url }: { id?: string, url?: string }) =>
@ -80,7 +80,7 @@ export const useRefreshFeedMutation = (feedId?: string) =>
onSuccess() {
if (!feedId) return
Queries.entries
entries
.entries({
id: feedId!,
})