fix: import-circular for settings (#100)
Signed-off-by: Innei <i@innei.in>
This commit is contained in:
parent
942239d191
commit
2fec96b925
|
|
@ -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
|
||||
}, [])
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
export * from "./useAsRead"
|
||||
export * from "./useAuth"
|
||||
export * from "./useBizQuery"
|
||||
export * from "./useEntryActions"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export * from "./useBizQuery"
|
||||
export * from "./useDark"
|
||||
export * from "./usePrevious"
|
||||
export * from "./useRefValue"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 />
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue