mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-21 18:19:03 +08:00
fix(frontend): stabilize tauri listeners and logging payloads
This commit is contained in:
+27
-9
@@ -15,16 +15,34 @@ function MainContent(): React.JSX.Element {
|
||||
const [messageApi, contextHolder] = message.useMessage()
|
||||
|
||||
useEffect(() => {
|
||||
if (!(window as any).api) return
|
||||
const unlisten = (window as any).api.onNavigate((route: string) => {
|
||||
const currentPath = location.pathname === "/" ? "/home" : location.pathname
|
||||
const targetPath = route === "/" ? "/home" : route
|
||||
const api = (window as any).api
|
||||
if (!api) return
|
||||
|
||||
if (currentPath !== targetPath) {
|
||||
navigate(route)
|
||||
}
|
||||
})
|
||||
return () => unlisten()
|
||||
let disposed = false
|
||||
let unlisten: (() => void) | null = null
|
||||
|
||||
api
|
||||
.onNavigate((route: string) => {
|
||||
const currentPath = location.pathname === "/" ? "/home" : location.pathname
|
||||
const targetPath = route === "/" ? "/home" : route
|
||||
|
||||
if (currentPath !== targetPath) {
|
||||
navigate(route)
|
||||
}
|
||||
})
|
||||
.then((fn: () => void) => {
|
||||
if (disposed) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
unlisten = fn
|
||||
})
|
||||
.catch(() => void 0)
|
||||
|
||||
return () => {
|
||||
disposed = true
|
||||
if (unlisten) unlisten()
|
||||
}
|
||||
}, [navigate, location.pathname])
|
||||
|
||||
const [wizardVisible, setWizardVisible] = useState(false)
|
||||
|
||||
+28
-12
@@ -95,20 +95,36 @@ export const Settings: React.FC<{ permission: permissionLevel }> = ({ permission
|
||||
|
||||
useEffect(() => {
|
||||
loadAll()
|
||||
if (!(window as any).api) return
|
||||
const unsubscribe = (window as any).api.onSettingChanged((change: any) => {
|
||||
setSettings((prev) => {
|
||||
if (change?.key === "log_level") return { ...prev, log_level: change.value }
|
||||
if (change?.key === "is_wizard_completed")
|
||||
return { ...prev, is_wizard_completed: change.value }
|
||||
if (change?.key === "window_zoom") return { ...prev, window_zoom: change.value }
|
||||
if (change?.key === "auto_score_enabled")
|
||||
return { ...prev, auto_score_enabled: change.value }
|
||||
return prev
|
||||
const api = (window as any).api
|
||||
if (!api) return
|
||||
|
||||
let disposed = false
|
||||
let unlisten: (() => void) | null = null
|
||||
|
||||
api
|
||||
.onSettingChanged((change: any) => {
|
||||
setSettings((prev) => {
|
||||
if (change?.key === "log_level") return { ...prev, log_level: change.value }
|
||||
if (change?.key === "is_wizard_completed")
|
||||
return { ...prev, is_wizard_completed: change.value }
|
||||
if (change?.key === "window_zoom") return { ...prev, window_zoom: change.value }
|
||||
if (change?.key === "auto_score_enabled")
|
||||
return { ...prev, auto_score_enabled: change.value }
|
||||
return prev
|
||||
})
|
||||
})
|
||||
})
|
||||
.then((fn: () => void) => {
|
||||
if (disposed) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
unlisten = fn
|
||||
})
|
||||
.catch(() => void 0)
|
||||
|
||||
return () => {
|
||||
if (typeof unsubscribe === "function") unsubscribe()
|
||||
disposed = true
|
||||
if (unlisten) unlisten()
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
||||
@@ -39,15 +39,30 @@ export function Sidebar({ activeMenu, permission, onMenuChange }: SidebarProps):
|
||||
const handleStatusChange = () => {
|
||||
loadDbStatus()
|
||||
}
|
||||
if ((window as any).api) {
|
||||
const unsubscribe = (window as any).api.onSettingChanged(
|
||||
(change: { key: string; value: any }) => {
|
||||
if (change.key === "pg_connection_status") {
|
||||
handleStatusChange()
|
||||
}
|
||||
const api = (window as any).api
|
||||
if (!api) return
|
||||
|
||||
let disposed = false
|
||||
let unlisten: (() => void) | null = null
|
||||
|
||||
api
|
||||
.onSettingChanged((change: { key: string; value: any }) => {
|
||||
if (change.key === "pg_connection_status") {
|
||||
handleStatusChange()
|
||||
}
|
||||
)
|
||||
return unsubscribe
|
||||
})
|
||||
.then((fn: () => void) => {
|
||||
if (disposed) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
unlisten = fn
|
||||
})
|
||||
.catch(() => void 0)
|
||||
|
||||
return () => {
|
||||
disposed = true
|
||||
if (unlisten) unlisten()
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
||||
@@ -16,13 +16,34 @@ export function TitleBar({ children }: TitleBarProps): 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 disposed = false
|
||||
let unlisten: (() => void) | null = null
|
||||
|
||||
api
|
||||
.windowIsMaximized()
|
||||
.then((v: boolean) => setIsMaximized(v))
|
||||
.catch(() => void 0)
|
||||
|
||||
api
|
||||
.onWindowMaximizedChanged((maximized: boolean) => {
|
||||
setIsMaximized(maximized)
|
||||
})
|
||||
.then((fn: () => void) => {
|
||||
if (disposed) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
unlisten = fn
|
||||
})
|
||||
.catch(() => void 0)
|
||||
|
||||
return () => {
|
||||
disposed = true
|
||||
if (unlisten) unlisten()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const minimize = () => {
|
||||
|
||||
@@ -14,6 +14,7 @@ export function WindowControls(): React.JSX.Element {
|
||||
const api = (window as any).api
|
||||
if (!api) return
|
||||
|
||||
let disposed = false
|
||||
let unlisten: (() => void) | null = null
|
||||
|
||||
api
|
||||
@@ -26,11 +27,16 @@ export function WindowControls(): React.JSX.Element {
|
||||
setIsMaximized(maximized)
|
||||
})
|
||||
.then((fn: () => void) => {
|
||||
if (disposed) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
unlisten = fn
|
||||
})
|
||||
.catch(() => void 0)
|
||||
|
||||
return () => {
|
||||
disposed = true
|
||||
if (unlisten) unlisten()
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -120,23 +120,36 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ childre
|
||||
}, [applyThemeConfig])
|
||||
|
||||
useEffect(() => {
|
||||
if (!(window as any).api) return
|
||||
const api = (window as any).api
|
||||
if (!api) return
|
||||
|
||||
;(async () => {
|
||||
await loadThemes()
|
||||
await loadCurrentTheme()
|
||||
})()
|
||||
|
||||
const unsubscribe = (window as any).api.onThemeChanged((theme: themeConfig) => {
|
||||
setCurrentTheme(theme)
|
||||
currentThemeRef.current = theme
|
||||
applyThemeConfig(theme)
|
||||
loadThemes()
|
||||
})
|
||||
let disposed = false
|
||||
let unlisten: (() => void) | null = null
|
||||
|
||||
api
|
||||
.onThemeChanged((theme: themeConfig) => {
|
||||
setCurrentTheme(theme)
|
||||
currentThemeRef.current = theme
|
||||
applyThemeConfig(theme)
|
||||
loadThemes()
|
||||
})
|
||||
.then((fn: () => void) => {
|
||||
if (disposed) {
|
||||
fn()
|
||||
return
|
||||
}
|
||||
unlisten = fn
|
||||
})
|
||||
.catch(() => void 0)
|
||||
|
||||
return () => {
|
||||
if (typeof unsubscribe === "function") {
|
||||
unsubscribe()
|
||||
}
|
||||
disposed = true
|
||||
if (unlisten) unlisten()
|
||||
}
|
||||
}, [applyThemeConfig, loadCurrentTheme, loadThemes])
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ const safeWriteLog = (payload: {
|
||||
try {
|
||||
const api = (window as any).api
|
||||
if (!api?.writeLog) return
|
||||
api.writeLog(payload)
|
||||
Promise.resolve(api.writeLog(payload)).catch(() => void 0)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -188,15 +188,19 @@ const api = {
|
||||
},
|
||||
|
||||
// Logger
|
||||
queryLogs: (params?: { lines?: number }): Promise<{ success: boolean; data: string[] }> =>
|
||||
invoke("log_query", { params }),
|
||||
queryLogs: (
|
||||
input?: number | { lines?: number }
|
||||
): Promise<{ success: boolean; data: string[] }> => {
|
||||
const lines = typeof input === "number" ? input : input?.lines
|
||||
return invoke("log_query", { lines })
|
||||
},
|
||||
clearLogs: (): Promise<{ success: boolean }> => invoke("log_clear"),
|
||||
setLogLevel: (level: string): Promise<{ success: boolean }> => invoke("log_set_level", { level }),
|
||||
writeLog: (payload: {
|
||||
level: string
|
||||
message: string
|
||||
meta?: any
|
||||
}): Promise<{ success: boolean }> => invoke("log_write", payload),
|
||||
}): Promise<{ success: boolean }> => invoke("log_write", { payload }),
|
||||
|
||||
// Database Connection
|
||||
dbTestConnection: (
|
||||
|
||||
Reference in New Issue
Block a user