diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 7c21f3c..a492034 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -610,6 +610,25 @@ async fn open_in_explorer(state: State<'_, AppState>, target: String) -> Result< Ok(()) } +/// Open a local file with its associated application (e.g. launch Unreal for a +/// `.uproject`). Uses the shell `start` so there are no path-scope restrictions. +#[tauri::command] +async fn launch_file(path: String) -> Result<(), String> { + if !std::path::Path::new(&path).exists() { + return Err(format!("File not found: {path}")); + } + let mut c = Command::new("cmd"); + #[cfg(windows)] + { + use std::os::windows::process::CommandExt; + c.creation_flags(0x0800_0000); + } + c.args(["/C", "start", "", &path]) + .spawn() + .map_err(|e| format!("Could not launch: {e}"))?; + Ok(()) +} + /// Look for an Unreal `.uproject` inside the working-folder scope (resolved to a /// local dir via `p4 where`). Checks the folder itself and one level of subdirs. /// Returns the local path of the first match, or "" if the scope isn't a UE project. @@ -751,6 +770,7 @@ pub fn run() { p4_undo_change, open_in_explorer, find_uproject, + launch_file, p4_describe, read_file, read_depot, diff --git a/src/App.tsx b/src/App.tsx index fd68d78..2dc7ab0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,6 @@ import type { MouseEvent as ReactMouseEvent, CSSProperties, ReactNode } from "re import { getCurrentWindow } from "@tauri-apps/api/window"; import { getCurrentWebview } from "@tauri-apps/api/webview"; import { listen } from "@tauri-apps/api/event"; -import { openPath } from "@tauri-apps/plugin-opener"; import ModelViewer from "./ModelViewer"; import UpdateBanner from "./Updater"; import "./App.css"; @@ -504,7 +503,7 @@ function Workbench({ info, session, light, toggleTheme, lang, setLang, zoom, set // launch Unreal by opening the detected .uproject (file association starts UE) async function launchUE() { if (!uproject) return; - try { await openPath(uproject); flash(t("Launching Unreal…")); } + try { await p4.launchFile(uproject); flash(t("Launching Unreal…")); } catch (e) { flash(String(e), true); } } @@ -564,6 +563,7 @@ function Workbench({ info, session, light, toggleTheme, lang, setLang, zoom, set if (errors.length) flash(errors.join(" · "), true); else flash(t("Sent to the server: {n} changelist(s).", { n })); await refresh(); + await loadHistory(); // the submit created a new submitted changelist — refresh History } async function doRevert(file: OpenedFile) { @@ -638,6 +638,7 @@ function Workbench({ info, session, light, toggleTheme, lang, setLang, zoom, set
startResize(e, "sync")} title={t("Drag to resize")} />
browseTo("")} title={t("Choose the project working folder · right-click for more")} onContextMenu={(e) => openCtx(e, [ + ...(uproject ? [{ label: t("Launch Unreal Engine"), act: launchUE }] : []), { label: t("Open in Explorer"), act: () => reveal(activePath || String(info?.clientRoot || "")) }, { label: t("Choose another folder…"), act: () => browseTo("") }, { label: t("Copy path"), act: () => copyText(activePath || "//…", t("Path")) }, @@ -646,12 +647,6 @@ function Workbench({ info, session, light, toggleTheme, lang, setLang, zoom, set {t("Working folder")}{activePath || t("whole workspace (//…)")} {I.chev}
- {uproject && ( - - )} {pending.length > 0 ? (
diff --git a/src/i18n.ts b/src/i18n.ts index 40a87e1..900d1ba 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -68,6 +68,7 @@ const D: Record = { "Working…": { ru: "Работаю…", de: "Arbeite…", fr: "En cours…", es: "Trabajando…" }, "pull from server": { ru: "забрать с сервера (pull)", de: "vom Server holen (pull)", fr: "récupérer du serveur (pull)", es: "traer del servidor (pull)" }, "Launch": { ru: "Запустить", de: "Starten", fr: "Lancer", es: "Iniciar" }, + "Launch Unreal Engine": { ru: "Запустить Unreal Engine", de: "Unreal Engine starten", fr: "Lancer Unreal Engine", es: "Iniciar Unreal Engine" }, "Open this project in Unreal Engine": { ru: "Открыть проект в Unreal Engine", de: "Projekt in Unreal Engine öffnen", fr: "Ouvrir le projet dans Unreal Engine", es: "Abrir el proyecto en Unreal Engine" }, "Launching Unreal…": { ru: "Запуск Unreal…", de: "Unreal wird gestartet…", fr: "Lancement d’Unreal…", es: "Iniciando Unreal…" }, diff --git a/src/p4.ts b/src/p4.ts index e2c1c56..926a69d 100644 --- a/src/p4.ts +++ b/src/p4.ts @@ -73,6 +73,7 @@ export const p4 = { undoChange: (change: string) => invoke("p4_undo_change", { change }), openInExplorer: (target: string) => invoke("open_in_explorer", { target }), findUproject: (scope: string) => invoke("find_uproject", { scope }), + launchFile: (path: string) => invoke("launch_file", { path }), readDepot: async (depot: string): Promise => { const r: unknown = await invoke("read_depot", { depot }); if (r instanceof ArrayBuffer) return r;