From d9617bacc18cdc8f2bbb6992575e5782bc943e3a Mon Sep 17 00:00:00 2001 From: PANDA-JSR Date: Tue, 17 Mar 2026 21:40:03 +0800 Subject: [PATCH] fix(tauri): restore window controls and expose renderer api --- .gitignore | 1 + src/components/ContentArea.tsx | 6 +++++- src/components/WindowControls.tsx | 27 +++++++++++++++++++++------ src/main.tsx | 5 +++++ src/preload/types.ts | 25 +++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index dc6ef01..c09cea9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ out src-tauri/target src-tauri/Cargo.lock src-tauri/gen +.cargo-local/ # Database data.sql diff --git a/src/components/ContentArea.tsx b/src/components/ContentArea.tsx index b175d49..b968003 100644 --- a/src/components/ContentArea.tsx +++ b/src/components/ContentArea.tsx @@ -2,6 +2,7 @@ import React, { Suspense, lazy } from "react" import { Layout, Space, Button, Tag, Spin } from "antd" import { Routes, Route, Navigate } from "react-router-dom" import { useTranslation } from "react-i18next" +import { WindowControls } from "./WindowControls" const Home = lazy(() => import("./Home").then((m) => ({ default: m.Home }))) const StudentManager = lazy(() => @@ -67,6 +68,7 @@ export function ContentArea({ background: "var(--ss-header-bg)", borderBottom: "1px solid var(--ss-border-color)", flexShrink: 0, + WebkitAppRegion: "drag", } as React.CSSProperties } > @@ -76,7 +78,8 @@ export function ContentArea({ { display: "flex", alignItems: "center", - paddingRight: "12px", + paddingRight: "8px", + WebkitAppRegion: "no-drag", } as React.CSSProperties } > @@ -94,6 +97,7 @@ export function ContentArea({ )} + diff --git a/src/components/WindowControls.tsx b/src/components/WindowControls.tsx index b6c4596..b5eeba9 100644 --- a/src/components/WindowControls.tsx +++ b/src/components/WindowControls.tsx @@ -11,13 +11,28 @@ export function WindowControls(): React.JSX.Element { const [isMaximized, setIsMaximized] = useState(false) useEffect(() => { - if (!(window as any).api) return - ;(window as any).api.windowIsMaximized().then((v: boolean) => setIsMaximized(v)) + const api = (window as any).api + if (!api) return - const cleanup = (window as any).api.onWindowMaximizedChanged((maximized: boolean) => { - setIsMaximized(maximized) - }) - return cleanup + let unlisten: (() => void) | null = null + + api + .windowIsMaximized() + .then((v: boolean) => setIsMaximized(v)) + .catch(() => void 0) + + api + .onWindowMaximizedChanged((maximized: boolean) => { + setIsMaximized(maximized) + }) + .then((fn: () => void) => { + unlisten = fn + }) + .catch(() => void 0) + + return () => { + if (unlisten) unlisten() + } }, []) const minimize = () => { diff --git a/src/main.tsx b/src/main.tsx index 0f8455c..03fb68f 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -7,6 +7,11 @@ import App from "./App" import { ClientContext } from "./ClientContext" import { StudentService } from "./services/StudentService" import { ServiceProvider } from "./contexts/ServiceContext" +import { api } from "./preload/types" + +if (!(window as any).api) { + ;(window as any).api = api +} const ctx = new ClientContext() new StudentService(ctx) diff --git a/src/preload/types.ts b/src/preload/types.ts index 8179ae5..3d97cf4 100644 --- a/src/preload/types.ts +++ b/src/preload/types.ts @@ -173,6 +173,9 @@ const api = { windowMaximize: (): Promise => invoke("window_maximize"), windowClose: (): Promise => invoke("window_close"), windowIsMaximized: (): Promise => invoke("window_is_maximized"), + toggleDevTools: (): Promise => invoke("toggle_devtools"), + windowResize: (width: number, height: number): Promise => + invoke("window_resize", { width, height }), onWindowMaximizedChanged: (callback: (maximized: boolean) => void): Promise => { return listen("window:maximized-changed", (event) => { callback(event.payload) @@ -291,6 +294,28 @@ const api = { ruleIds: number[] ): Promise<{ success: boolean; data?: boolean; message?: string }> => invoke("auto_score_sort_rules", { ruleIds }), + + // Generic invoke wrapper for backward compatibility with callers using `api.invoke` + invoke: async (channel: string, ...args: any[]): Promise => { + switch (channel) { + case "auto-score:getRules": + return api.autoScoreGetRules() + case "auto-score:addRule": + return api.autoScoreAddRule(args[0]) + case "auto-score:updateRule": + return api.autoScoreUpdateRule(args[0]) + case "auto-score:deleteRule": + return api.autoScoreDeleteRule(args[0]) + case "auto-score:toggleRule": + return api.autoScoreToggleRule(args[0]) + case "auto-score:sortRules": + return api.autoScoreSortRules(args[0]) + case "auto-score:getStatus": + return api.autoScoreGetStatus() + default: + throw new Error(`Unsupported legacy invoke channel: ${channel}`) + } + }, } export default api