From e341b2e1fe9e02ec711028269138d57f05de2852 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 22 Jun 2024 20:57:07 +0800 Subject: [PATCH] fix: ban global `location` (#84) * fix: ban global `location` Signed-off-by: Innei * fix: modal transition and tab layout id Signed-off-by: Innei * fix Signed-off-by: Innei --------- Signed-off-by: Innei --- eslint.config.mjs | 7 +++++++ .../src/components/ui/modal/stacked/modal.tsx | 4 +++- src/renderer/src/components/ui/tabs.tsx | 19 +++++++++++++++++-- .../(with-layout)/feed/[id]/index.tsx | 5 +++-- src/renderer/src/pages/(external)/login.tsx | 7 +++---- .../src/pages/(external)/redirect.tsx | 4 +++- src/renderer/src/pages/add/index.tsx | 4 +++- src/renderer/src/pages/preview.tsx | 3 +++ src/renderer/src/router.tsx | 6 ++++-- src/shared/src/electron.ts | 1 + 10 files changed, 47 insertions(+), 13 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index af3c48b34d..5e039595e0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -24,6 +24,13 @@ export default defineConfig( }, rules: { "unicorn/prefer-module": "off", + "no-restricted-globals": [ + "error", + { + name: "location", + message: "Since you don't use the same router instance in electron and browser, you can't use the global location to get the route info. \n\n" + "You can use `useLocaltion` or `getReadonlyRoute` to get the route info.", + }, + ], }, }, ) diff --git a/src/renderer/src/components/ui/modal/stacked/modal.tsx b/src/renderer/src/components/ui/modal/stacked/modal.tsx index 5543a0cc8e..112837e454 100644 --- a/src/renderer/src/components/ui/modal/stacked/modal.tsx +++ b/src/renderer/src/components/ui/modal/stacked/modal.tsx @@ -92,7 +92,9 @@ export const ModalInternal: Component<{ const animateController = useAnimationControls() useEffect(() => { - requestAnimationFrame(() => animateController.start(modalMontionConfig.animate)) + requestAnimationFrame(() => { + animateController.start(modalMontionConfig.animate) + }) }, [animateController]) const noticeModal = useCallback(() => { animateController diff --git a/src/renderer/src/components/ui/tabs.tsx b/src/renderer/src/components/ui/tabs.tsx index 848ea9913f..e086de7a68 100644 --- a/src/renderer/src/components/ui/tabs.tsx +++ b/src/renderer/src/components/ui/tabs.tsx @@ -5,7 +5,20 @@ import { cva } from "class-variance-authority" import { m } from "framer-motion" import * as React from "react" -const Tabs = TabsPrimitive.Root +const TabsIdContext = React.createContext(null) + +const Tabs: typeof TabsPrimitive.Root = React.forwardRef((props, ref) => { + const { children, ...rest } = props + const id = React.useId() + + return ( + + + {children} + + + ) +}) const tabsListVariants = cva("", { variants: { @@ -63,6 +76,8 @@ const TabsTrigger = React.forwardRef< React.useImperativeHandle(ref, () => triggerRef.current!, [ref]) const [isSelect, setIsSelect] = React.useState(false) + const id = React.useContext(TabsIdContext) + const layoutId = `tab-selected-underline-${id}` React.useLayoutEffect(() => { if (!triggerRef.current) return @@ -98,7 +113,7 @@ const TabsTrigger = React.forwardRef< {children} {isSelect && ( )} diff --git a/src/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx b/src/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx index b4e8e75d0f..063f85e90f 100644 --- a/src/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx +++ b/src/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx @@ -17,12 +17,13 @@ import { useFeed } from "@renderer/queries/feed" import { DEEPLINK_SCHEME } from "@shared/constants" import type { FC } from "react" import { Helmet } from "react-helmet-async" -import { useParams } from "react-router-dom" +import { useParams, useSearchParams } from "react-router-dom" export function Component() { const { id } = useParams() + const [search] = useSearchParams() const view = Number.parseInt( - new URLSearchParams(location.search).get("view") || "0", + search.get("view") || "0", ) const feed = useFeed({ diff --git a/src/renderer/src/pages/(external)/login.tsx b/src/renderer/src/pages/(external)/login.tsx index 9402426293..43b37a7805 100644 --- a/src/renderer/src/pages/(external)/login.tsx +++ b/src/renderer/src/pages/(external)/login.tsx @@ -5,15 +5,15 @@ import { useSignOut } from "@renderer/hooks" import { LOGIN_CALLBACK_URL, loginHandler } from "@renderer/lib/auth" import { APP_NAME } from "@renderer/lib/constants" import { useEffect, useState } from "react" -import { useNavigate } from "react-router-dom" +import { useLocation, useNavigate } from "react-router-dom" export function Component() { const { status } = useSession() const navigate = useNavigate() const [redirecting, setRedirecting] = useState(false) const signOut = useSignOut() - - const urlParams = new URLSearchParams(window.location.search) + const location = useLocation() + const urlParams = new URLSearchParams(location.search) const provider = urlParams.get("provider") useEffect(() => { if (!window.electron && provider) { @@ -36,7 +36,6 @@ export function Component() {

Log in to - {" "} {APP_NAME}

{redirecting ? ( diff --git a/src/renderer/src/pages/(external)/redirect.tsx b/src/renderer/src/pages/(external)/redirect.tsx index 1714a7b774..71f7108957 100644 --- a/src/renderer/src/pages/(external)/redirect.tsx +++ b/src/renderer/src/pages/(external)/redirect.tsx @@ -22,7 +22,9 @@ export function Component() { if (window.electron) { navigate("/") } else { - getCallbackUrl().then((url) => window.open(url)) + getCallbackUrl().then((url) => { + window.open(url) + }) } }, []) diff --git a/src/renderer/src/pages/add/index.tsx b/src/renderer/src/pages/add/index.tsx index d9610744b4..a5b7fd2def 100644 --- a/src/renderer/src/pages/add/index.tsx +++ b/src/renderer/src/pages/add/index.tsx @@ -1,9 +1,11 @@ import { FeedViewType } from "@renderer/lib/enum" import { FeedForm } from "@renderer/modules/discover/feed-form" import { useLayoutEffect } from "react" +import { useSearchParams } from "react-router-dom" export function Component() { - const urlSearchParams = new URLSearchParams(location.search) + const [urlSearchParams] = useSearchParams() + const paramUrl = urlSearchParams.get("url") const url = paramUrl ? decodeURIComponent(paramUrl) : undefined const id = urlSearchParams.get("id") || undefined diff --git a/src/renderer/src/pages/preview.tsx b/src/renderer/src/pages/preview.tsx index afe2c76fc4..ad232e12c0 100644 --- a/src/renderer/src/pages/preview.tsx +++ b/src/renderer/src/pages/preview.tsx @@ -1,4 +1,7 @@ +import { useLocation } from "react-router-dom" + export function Component() { + const location = useLocation() const urlSearchParams = new URLSearchParams(location.search) const url = urlSearchParams.get("url") diff --git a/src/renderer/src/router.tsx b/src/renderer/src/router.tsx index 6e0aeb425e..a83abb165d 100644 --- a/src/renderer/src/router.tsx +++ b/src/renderer/src/router.tsx @@ -1,4 +1,4 @@ -import { createHashRouter } from "react-router-dom" +import { createBrowserRouter, createHashRouter } from "react-router-dom" import App from "./App" import { NotFound } from "./components/ui/not-found" @@ -7,7 +7,9 @@ import { buildGlobRoutes } from "./lib/route-builder" const globTree = import.meta.glob("./pages/**/*.tsx") const tree = buildGlobRoutes(globTree) -export const router = createHashRouter([ +const routerCreator = window.electron ? createHashRouter : createBrowserRouter + +export const router = routerCreator([ { path: "/", element: , diff --git a/src/shared/src/electron.ts b/src/shared/src/electron.ts index bc9344dc7b..1db67db1e0 100644 --- a/src/shared/src/electron.ts +++ b/src/shared/src/electron.ts @@ -26,6 +26,7 @@ export const openElectronWindow = async ( window.open(urlObject.toString()) } else { + // eslint-disable-next-line no-restricted-globals window.open(url.replace(DEEPLINK_SCHEME, `${location.origin}/`)) } }