From fabb1f87600615991ad913af1548cb83ebea974f Mon Sep 17 00:00:00 2001 From: CJ Pais Date: Thu, 26 Jun 2025 14:03:40 -0700 Subject: [PATCH] add footer with the curr version --- src-tauri/src/lib.rs | 15 +++- src-tauri/tauri.conf.json | 2 +- src/App.tsx | 12 ++- src/components/footer/Footer.tsx | 130 +++++++++++++++++++++++++++++++ src/components/footer/index.ts | 1 + 5 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 src/components/footer/Footer.tsx create mode 100644 src/components/footer/index.ts diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 8b69733..18aac40 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -11,7 +11,8 @@ use std::sync::{Arc, Mutex}; use tauri::image::Image; use tauri::menu::{Menu, MenuItem, PredefinedMenuItem}; use tauri::tray::TrayIconBuilder; -use tauri::Manager; +use tauri::Emitter; +use tauri::{AppHandle, Manager}; use tauri_plugin_autostart::{MacosLauncher, ManagerExt}; #[derive(Default)] @@ -22,6 +23,13 @@ struct ShortcutToggleStates { type ManagedToggleState = Mutex; +#[tauri::command] +fn trigger_update_check(app: AppHandle) -> Result<(), String> { + app.emit("check-for-updates", ()) + .map_err(|e| e.to_string())?; + Ok(()) +} + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { env_logger::init(); @@ -108,7 +116,7 @@ pub fn run() { } } "check_updates" => { - // TODO: Implement update check + let _ = app.emit("check-for-updates", ()); } "quit" => { app.exit(0); @@ -158,7 +166,8 @@ pub fn run() { .invoke_handler(tauri::generate_handler![ shortcut::change_binding, shortcut::reset_binding, - shortcut::change_ptt_setting + shortcut::change_ptt_setting, + trigger_update_check ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6da3b2d..ff8c92f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -16,7 +16,7 @@ "width": 540, "height": 400, "minWidth": 460, - "minHeight": 400, + "minHeight": 440, "resizable": true, "maximizable": false } diff --git a/src/App.tsx b/src/App.tsx index 0bc85c1..5aed574 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,13 +2,17 @@ import "./App.css"; import { Settings } from "./components/settings/Settings"; import HandyTextLogo from "./components/icons/HandyTextLogo"; import AccessibilityPermissions from "./components/AccessibilityPermissions"; +import Footer from "./components/footer"; function App() { return ( -
- - - +
+
+ + + +
+
); } diff --git a/src/components/footer/Footer.tsx b/src/components/footer/Footer.tsx new file mode 100644 index 0000000..0e9bc61 --- /dev/null +++ b/src/components/footer/Footer.tsx @@ -0,0 +1,130 @@ +import React, { useState, useEffect } from "react"; +import { check } from "@tauri-apps/plugin-updater"; +import { relaunch } from "@tauri-apps/plugin-process"; +import { getVersion } from "@tauri-apps/api/app"; +import { listen } from "@tauri-apps/api/event"; + +const Footer: React.FC = () => { + const [isChecking, setIsChecking] = useState(false); + const [updateAvailable, setUpdateAvailable] = useState(false); + const [isUpdating, setIsUpdating] = useState(false); + const [version, setVersion] = useState(""); + const [showUpToDate, setShowUpToDate] = useState(false); + const [isManualCheck, setIsManualCheck] = useState(false); + + useEffect(() => { + // Get version from Tauri app info + const fetchVersion = async () => { + try { + const appVersion = await getVersion(); + setVersion(appVersion); + } catch (error) { + console.error("Failed to get app version:", error); + setVersion("0.1.1"); // fallback version + } + }; + + fetchVersion(); + + // Automatically check for updates on launch + checkForUpdates(); + + // Listen for menu-triggered update checks + const unlisten = listen("check-for-updates", () => { + checkForUpdates(); + }); + + return () => { + unlisten.then((fn) => fn()); + }; + }, []); + + const checkForUpdates = async () => { + // Don't check again if already checking + if (isChecking) return; + + try { + setIsChecking(true); + const update = await check(); + + if (update) { + setUpdateAvailable(true); + setShowUpToDate(false); + console.log("Update available:", update.version); + } else { + console.log("No updates available"); + // Reset update available state in case it was previously true + setUpdateAvailable(false); + + // Show "up to date" message only for manual checks + if (isManualCheck) { + setShowUpToDate(true); + // Hide the message after 3 seconds + setTimeout(() => setShowUpToDate(false), 3000); + } + } + } catch (error) { + console.error("Failed to check for updates:", error); + } finally { + setIsChecking(false); + setIsManualCheck(false); + } + }; + + const handleManualUpdateCheck = () => { + setIsManualCheck(true); + checkForUpdates(); + }; + + const installUpdate = async () => { + try { + setIsUpdating(true); + const update = await check(); + + if (update) { + console.log("Installing update..."); + await update.downloadAndInstall(); + + // Restart the app to apply the update + await relaunch(); + } + } catch (error) { + console.error("Failed to install update:", error); + setIsUpdating(false); + } + }; + + return ( +
+
+
+ v{version} +
+ +
+ {updateAvailable ? ( + + ) : showUpToDate ? ( + Up to date + ) : ( + + )} +
+
+
+ ); +}; + +export default Footer; diff --git a/src/components/footer/index.ts b/src/components/footer/index.ts new file mode 100644 index 0000000..be92134 --- /dev/null +++ b/src/components/footer/index.ts @@ -0,0 +1 @@ +export { default } from './Footer';