From 1f60af1c3a8ad45eadd0c48d7391ad5691247488 Mon Sep 17 00:00:00 2001 From: Francisco Salgueiro Date: Sun, 15 Oct 2023 16:08:58 +0100 Subject: [PATCH] kill engines on tab close --- src-tauri/src/chess.rs | 26 ++++++ src-tauri/src/main.rs | 3 +- src/bindings.ts | 95 +++++++++++--------- src/components/panels/analysis/BestMoves.tsx | 2 - src/components/tabs/BoardsPage.tsx | 10 ++- 5 files changed, 86 insertions(+), 50 deletions(-) diff --git a/src-tauri/src/chess.rs b/src-tauri/src/chess.rs index 8517e233..d187fd9b 100644 --- a/src-tauri/src/chess.rs +++ b/src-tauri/src/chess.rs @@ -101,6 +101,11 @@ impl EngineProcess { self.stdin.write_all(b"stop\n").await?; Ok(()) } + + async fn kill(&mut self) -> Result<(), Error> { + self.stdin.write_all(b"quit\n").await?; + Ok(()) + } } #[cfg(target_os = "windows")] @@ -243,6 +248,27 @@ pub enum GoMode { Infinite, } +#[tauri::command] +#[specta::specta] +pub async fn kill_engines(tab: String, state: tauri::State<'_, AppState>) -> Result<(), Error> { + let keys: Vec<_> = state + .engine_processes + .iter() + .map(|x| x.key().clone()) + .collect(); + for key in keys.clone() { + if key.0 == tab { + { + let process = state.engine_processes.get_mut(&key).unwrap(); + let mut process = process.lock().await; + process.kill().await?; + } + state.engine_processes.remove(&key).unwrap(); + } + } + Ok(()) +} + #[tauri::command] #[specta::specta] pub async fn stop_engine( diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a57c97d1..54077766 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -31,7 +31,7 @@ use tauri::{ use tauri_plugin_log::LogTarget; use crate::chess::{ - analyze_game, get_engine_name, get_pieces_count, get_single_best_move, make_move, + analyze_game, get_engine_name, get_pieces_count, get_single_best_move, kill_engines, make_move, make_random_move, put_piece, similar_structure, stop_engine, validate_fen, }; use crate::db::{ @@ -163,6 +163,7 @@ fn main() { get_best_moves, analyze_game, stop_engine, + kill_engines )) .events(tauri_specta::collect_events!(BestMovesPayload)); diff --git a/src/bindings.ts b/src/bindings.ts index a2ccaefd..a1f1e58f 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -1,47 +1,55 @@ -// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually. + // This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually. -export const commands = { - async closeSplashscreen(): Promise { - return await TAURI_INVOKE("plugin:tauri-specta|close_splashscreen"); - }, - async findFidePlayer(player: string): Promise<__Result__<{ fideid: number; name: string; country: string; sex: string; title: string | null; w_title: string | null; o_title: string | null; foa_title: string | null; rating: number | null; games: number | null; k: number | null; rapid_rating: number | null; rapid_games: number | null; rapid_k: number | null; blitz_rating: number | null; blitz_games: number | null; blitz_k: number | null; birthday: number | null; flag: string | null } | null, string>> { - try { - return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|find_fide_player", { player }) }; - } catch (e) { - if (e instanceof Error) throw e; - else return { status: "error", error: e as any }; - } - }, - async getBestMoves(engine: string, tab: string, goMode: GoMode, options: EngineOptions): Promise<__Result__> { - try { - return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|get_best_moves", { engine, tab, goMode, options }) }; - } catch (e) { - if (e instanceof Error) throw e; - else return { status: "error", error: e as any }; - } - }, - async analyzeGame(moves: string[], engine: string, goMode: GoMode, options: AnalysisOptions): Promise<__Result__<{ best: BestMoves; novelty: boolean }[], string>> { - try { - return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|analyze_game", { moves, engine, goMode, options }) }; - } catch (e) { - if (e instanceof Error) throw e; - else return { status: "error", error: e as any }; - } - }, - async stopEngine(engine: string, tab: string): Promise<__Result__> { - try { - return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|stop_engine", { engine, tab }) }; - } catch (e) { - if (e instanceof Error) throw e; - else return { status: "error", error: e as any }; - } - } + export const commands = { +async closeSplashscreen() : Promise { +return await TAURI_INVOKE("plugin:tauri-specta|close_splashscreen"); +}, +async findFidePlayer(player: string) : Promise<__Result__<{ fideid: number; name: string; country: string; sex: string; title: string | null; w_title: string | null; o_title: string | null; foa_title: string | null; rating: number | null; games: number | null; k: number | null; rapid_rating: number | null; rapid_games: number | null; rapid_k: number | null; blitz_rating: number | null; blitz_games: number | null; blitz_k: number | null; birthday: number | null; flag: string | null } | null, string>> { +try { + return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|find_fide_player", { player }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, +async getBestMoves(engine: string, tab: string, goMode: GoMode, options: EngineOptions) : Promise<__Result__> { +try { + return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|get_best_moves", { engine, tab, goMode, options }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, +async analyzeGame(moves: string[], engine: string, goMode: GoMode, options: AnalysisOptions) : Promise<__Result__<{ best: BestMoves; novelty: boolean }[], string>> { +try { + return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|analyze_game", { moves, engine, goMode, options }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, +async stopEngine(engine: string, tab: string) : Promise<__Result__> { +try { + return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|stop_engine", { engine, tab }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, +async killEngines(tab: string) : Promise<__Result__> { +try { + return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|kill_engines", { tab }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +} } export const events = __makeEvents__<{ - bestMovesPayload: BestMovesPayload +bestMovesPayload: BestMovesPayload }>({ - bestMovesPayload: "plugin:tauri-specta:best-moves-payload" +bestMovesPayload: "plugin:tauri-specta:best-moves-payload" }) /** user-defined types **/ @@ -55,7 +63,7 @@ export type Score = { type: "cp"; value: number } | { type: "mate"; value: numbe /** tauri-specta globals **/ -import { invoke as TAURI_INVOKE } from "@tauri-apps/api"; + import { invoke as TAURI_INVOKE } from "@tauri-apps/api"; import * as TAURI_API_EVENT from "@tauri-apps/api/event"; import { type WebviewWindowHandle as __WebviewWindowHandle__ } from "@tauri-apps/api/window"; @@ -67,8 +75,8 @@ type __EventObj__ = { cb: TAURI_API_EVENT.EventCallback ) => ReturnType>; emit: T extends null - ? (payload?: T) => ReturnType - : (payload: T) => ReturnType; + ? (payload?: T) => ReturnType + : (payload: T) => ReturnType; }; type __Result__ = @@ -88,7 +96,7 @@ function __makeEvents__>( get: (_, event) => { const name = mappings[event as keyof T]; - return new Proxy((() => { }) as any, { + return new Proxy((() => {}) as any, { apply: (_, __, [window]: [__WebviewWindowHandle__]) => ({ listen: (arg: any) => window.listen(name, arg), once: (arg: any) => window.once(name, arg), @@ -110,3 +118,4 @@ function __makeEvents__>( ); } + \ No newline at end of file diff --git a/src/components/panels/analysis/BestMoves.tsx b/src/components/panels/analysis/BestMoves.tsx index e0d7242d..92e23970 100644 --- a/src/components/panels/analysis/BestMoves.tsx +++ b/src/components/panels/analysis/BestMoves.tsx @@ -85,9 +85,7 @@ export default function BestMovesComponent({ useEffect(() => { async function waitForMove() { - console.log("waiting for move"); const unlisten = await events.bestMovesPayload.listen(({ payload }) => { - console.log("got move", payload); const ev = payload.bestLines; if (payload.engine === engine.path && payload.tab === activeTab) { startTransition(() => { diff --git a/src/components/tabs/BoardsPage.tsx b/src/components/tabs/BoardsPage.tsx index 3135e620..927f6664 100644 --- a/src/components/tabs/BoardsPage.tsx +++ b/src/components/tabs/BoardsPage.tsx @@ -21,6 +21,8 @@ import { activeTabAtom, tabsAtom } from "@/atoms/atoms"; import ConfirmChangesModal from "./ConfirmChangesModal"; import { match } from "ts-pattern"; import { Reorder } from "framer-motion"; +import { commands } from "@/bindings"; +import { unwrap } from "@/utils/invoke"; const useStyles = createStyles((theme) => ({ newTab: { @@ -41,9 +43,10 @@ export default function BoardsPage() { const { classes } = useStyles(); const [tabs, setTabs] = useAtom(tabsAtom); const [activeTab, setActiveTab] = useAtom(activeTabAtom); + const [saveModalOpened, toggleSaveModal] = useToggle(); const closeTab = useCallback( - (value: string | null, forced?: boolean) => { + async (value: string | null, forced?: boolean) => { if (value !== null) { const closedTab = tabs.find((tab) => tab.value === value); const tabState = JSON.parse(sessionStorage.getItem(value) || "{}"); @@ -63,9 +66,10 @@ export default function BoardsPage() { } } setTabs((prev) => prev.filter((tab) => tab.value !== value)); + unwrap(await commands.killEngines(value)); } }, - [tabs, activeTab, setTabs, setActiveTab] + [tabs, activeTab, setTabs, toggleSaveModal, setActiveTab] ); function selectTab(index: number) { @@ -165,8 +169,6 @@ export default function BoardsPage() { ["ctrl+9", () => selectTab(tabs.length - 1)], ]); - const [saveModalOpened, toggleSaveModal] = useToggle(); - return ( <>