feat: clear terminal button, cleanup styling

This commit is contained in:
Maarten van Heusden
2026-02-02 09:44:33 +01:00
parent f12000df52
commit 2995a28d5c
3 changed files with 35 additions and 16 deletions

View File

@@ -5,6 +5,8 @@ use tauri::State;
use crate::AppState; use crate::AppState;
use crate::steam::SteamDownload; use crate::steam::SteamDownload;
/* Parts of this file are derived from https://github.com/cablehead/tauri-xtermjs-nushell/blob/0bdd4a27ee2874de12e99bccd6c91d6ec5d28fbc/src-tauri/src/main.rs */
#[tauri::command] #[tauri::command]
pub async fn async_write_to_pty(data: &str, state: State<'_, AppState>) -> Result<(), ()> { pub async fn async_write_to_pty(data: &str, state: State<'_, AppState>) -> Result<(), ()> {
write!(state.writer.lock().await, "{}", data).map_err(|_| ()) write!(state.writer.lock().await, "{}", data).map_err(|_| ())
@@ -18,7 +20,7 @@ pub async fn async_read_from_pty(state: State<'_, AppState>) -> Result<Option<St
let data = reader.fill_buf().map_err(|_| ())?; let data = reader.fill_buf().map_err(|_| ())?;
// Send the data to the webview if necessary // Send the data to the webview if necessary
if data.len() > 0 { if !data.is_empty() {
std::str::from_utf8(data) std::str::from_utf8(data)
.map(|v| Some(v.to_string())) .map(|v| Some(v.to_string()))
.map_err(|_| ())? .map_err(|_| ())?
@@ -64,14 +66,14 @@ pub fn create_depotdownloader_command(steam_download: &SteamDownload, cwd: &Path
command.cwd(cwd); command.cwd(cwd);
if !steam_download.is_anonymous() { if !steam_download.is_anonymous() {
command.args(["-username", &*steam_download.username().clone().unwrap()]); command.args(["-username", &steam_download.username().clone().unwrap()]);
command.args(["-password", &*steam_download.password().clone().unwrap()]); command.args(["-password", &steam_download.password().clone().unwrap()]);
} }
command.args(["-app", &*steam_download.app_id()]); command.args(["-app", steam_download.app_id()]);
command.args(["-depot", &*steam_download.depot_id()]); command.args(["-depot", steam_download.depot_id()]);
command.args(["-manifest", &*steam_download.manifest_id()]); command.args(["-manifest", steam_download.manifest_id()]);
command.args(["-dir", &*steam_download.output_path()]); command.args(["-dir", &steam_download.output_path()]);
command command
} }

View File

@@ -17,7 +17,7 @@
<body class="select-none"> <body class="select-none">
<div class="f1-light text-center mb-1">Steam Depot Downloader</div> <div class="f1-light text-center mb-1">Steam Depot Downloader</div>
<div class="flex justify-between gap-2 w-svw flex-row"> <div class="flex justify-between gap-2 w-svw flex-row">
<div class="w-1/2 h-full"> <div class="w-1/2 h-full" id="left-side">
<div class="mx-auto"> <div class="mx-auto">
<form id="theform"> <form id="theform">
<div class="form-group mx-3 mt-1"> <div class="form-group mx-3 mt-1">
@@ -159,10 +159,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="w-1/2 h-full px-2"> <div class="w-1/2 h-full px-2" id="right-side">
<div class="mt-2 h-full w-full mx-auto"> <div class="mt-2 h-full w-full mx-auto">
<div class="border border-gray-300 rounded-md bg-gray-900 text-white shadow shadow-blue-200"> <div class="border border-gray-300 rounded-md bg-gray-900 text-white shadow shadow-blue-200">
<span class="text-md font-semibold block text-center">Download output</span> <div class="text-md font-semibold w-full inline-flex my-px items-center">
<span class="text-center w-full">Download output</span>
<button id="clear-terminal" class="disabled:pointer-events-none disabled:line-through disabled:text-gray-300 ml-auto py-px px-2 border-2 rounded-xs border-red-500/75 font-normal enabled:hover:bg-red-200/30 enabled:active:bg-red-200/50">
Clear
</button>
</div>
<div class="max-h-[70vh]" id="xtermjs"></div> <div class="max-h-[70vh]" id="xtermjs"></div>
</div> </div>
<div class="mt-3 justify-between flex flex-row gap-3"> <div class="mt-3 justify-between flex flex-row gap-3">

View File

@@ -7,8 +7,10 @@ import {Terminal} from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit"; import { FitAddon } from "@xterm/addon-fit";
import { listen } from "@tauri-apps/api/event"; import { listen } from "@tauri-apps/api/event";
function setLoader(state: boolean) { /* Parts of this file are derived from https://github.com/cablehead/tauri-xtermjs-nushell/blob/0bdd4a27ee2874de12e99bccd6c91d6ec5d28fbc/src/main.ts */
$("#busy").prop("hidden", !state);
function blockTerminalClearButton(state: boolean) {
$("#clear-terminal").prop( "disabled", state );
} }
@@ -16,8 +18,9 @@ function setLoadingState(state: boolean) {
$("#busy").prop("hidden", !state); $("#busy").prop("hidden", !state);
// loop through all buttons and input fields and disable them // loop through all buttons and input fields and disable them
for (const element of document.querySelectorAll("button, input")) { for (const element of document.querySelectorAll("button, input, div[role='button']")) {
if (element.closest("#settings-content")) continue; if (element.closest("#settings-content")) continue;
if (element.closest("#right-side")) continue;
(element as any).disabled = state; (element as any).disabled = state;
} }
@@ -49,7 +52,7 @@ const invalidFields = () => {
return invalidFields; return invalidFields;
}; };
const registerTerminal = async (terminalElement: HTMLElement) => { const registerTerminal: (terminalElement: HTMLElement) => Promise<Terminal> = async (terminalElement: HTMLElement) => {
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
const term = new Terminal({ const term = new Terminal({
fontSize: 10, fontSize: 10,
@@ -57,7 +60,7 @@ const registerTerminal = async (terminalElement: HTMLElement) => {
rows: 100, rows: 100,
cols: 100, cols: 100,
theme: { theme: {
background: "rgb(47, 47, 47)", background: "rgb(33, 33, 33)",
}, },
}); });
term.loadAddon(fitAddon); term.loadAddon(fitAddon);
@@ -97,11 +100,13 @@ const registerTerminal = async (terminalElement: HTMLElement) => {
} }
window.requestAnimationFrame(readFromPty); window.requestAnimationFrame(readFromPty);
return term;
}; };
$(async () => { $(async () => {
await registerTerminal($("#xtermjs")[0]); let terminal = await registerTerminal($("#xtermjs")[0]);
let downloadDirectory: string | null; let downloadDirectory: string | null;
// Startup logic // Startup logic
@@ -109,6 +114,9 @@ $(async () => {
await invoke("preload_vectum"); await invoke("preload_vectum");
setLoadingState(false); setLoadingState(false);
$("#clear-terminal").on("click", async () => {
terminal.reset()
})
$("#pickpath").on("click", async () => { $("#pickpath").on("click", async () => {
// Open a dialog // Open a dialog
@@ -196,6 +204,9 @@ $(async () => {
setLoadingState(true); setLoadingState(true);
await invoke("start_download", {steamDownload: steamDownload}); await invoke("start_download", {steamDownload: steamDownload});
// Block clear terminal button (to avoid clearing ongoing download logs)
blockTerminalClearButton(true);
console.log("Send frontend data over to backend. Ready for next download."); console.log("Send frontend data over to backend. Ready for next download.");
}); });
@@ -230,4 +241,5 @@ $(async () => {
listen<string>("command-exited", () => { listen<string>("command-exited", () => {
setLoadingState(false); setLoadingState(false);
blockTerminalClearButton(false);
}); });