fix(tauri): restore window controls and expose renderer api

This commit is contained in:
2026-03-17 21:40:03 +08:00
parent 0d86f38ed7
commit d9617bacc1
5 changed files with 57 additions and 7 deletions
+1
View File
@@ -13,6 +13,7 @@ out
src-tauri/target
src-tauri/Cargo.lock
src-tauri/gen
.cargo-local/
# Database
data.sql
+5 -1
View File
@@ -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({
)}
</Space>
</div>
<WindowControls />
</div>
<Content style={{ flex: 1, overflowY: "auto" }}>
+21 -6
View File
@@ -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 = () => {
+5
View File
@@ -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)
+25
View File
@@ -173,6 +173,9 @@ const api = {
windowMaximize: (): Promise<boolean> => invoke("window_maximize"),
windowClose: (): Promise<void> => invoke("window_close"),
windowIsMaximized: (): Promise<boolean> => invoke("window_is_maximized"),
toggleDevTools: (): Promise<void> => invoke("toggle_devtools"),
windowResize: (width: number, height: number): Promise<void> =>
invoke("window_resize", { width, height }),
onWindowMaximizedChanged: (callback: (maximized: boolean) => void): Promise<UnlistenFn> => {
return listen<boolean>("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<any> => {
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