From 898a0120b8530d36fc914f60810df45026919d25 Mon Sep 17 00:00:00 2001 From: CJ Pais Date: Thu, 26 Jun 2025 13:50:11 -0700 Subject: [PATCH 1/3] auto update code + revised menu --- .github/workflows/release.yml | 9 +- bun.lockb | Bin 65841 -> 67231 bytes package.json | 4 +- src-tauri/Cargo.lock | 778 +++++++++++++++++----------- src-tauri/Cargo.toml | 1 + src-tauri/capabilities/desktop.json | 3 +- src-tauri/src/lib.rs | 28 +- src-tauri/tauri.conf.json | 11 +- 8 files changed, 513 insertions(+), 321 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b819b8..97ba970 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: "Release" -on: - workflow_dispatch +on: workflow_dispatch # on: # push: # branches: @@ -48,11 +47,11 @@ jobs: with: version: 1.4.309.0 cache: true - + - name: Install trusted-signing-cli if: matrix.platform == 'windows-latest' # This must match the platform value defined above. run: cargo install trusted-signing-cli - + - name: Prepare Vulkan SDK for Ubuntu 22.04 run: | wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc @@ -111,6 +110,8 @@ jobs: AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} with: tagName: v__VERSION__ releaseName: "v__VERSION__" diff --git a/bun.lockb b/bun.lockb index 39652e83085393c7e1a50de9c2e188cacff58d69..9efbf5563f3017e821a09073c25eae05a4bd0e85 100755 GIT binary patch delta 11455 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 let settings_i = MenuItem::with_id(app, "settings", "Settings", true, None::<&str>)?; + let check_updates_i = MenuItem::with_id( + app, + "check_updates", + "Check for Updates", + true, + None::<&str>, + )?; let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?; - let menu = Menu::with_items(app, &[&settings_i, &quit_i])?; + let menu = Menu::with_items( + app, + &[ + &version_i, + &PredefinedMenuItem::separator(app)?, + &settings_i, + &check_updates_i, + &PredefinedMenuItem::separator(app)?, + &quit_i, + ], + )?; let tray = TrayIconBuilder::new() .icon(Image::from_path(app.path().resolve( "resources/tray_idle.png", @@ -73,6 +94,9 @@ pub fn run() { eprintln!("Main window not found"); } } + "check_updates" => { + // TODO: Implement update check + } "quit" => { app.exit(0); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c66333d..6da3b2d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -27,6 +27,7 @@ }, "bundle": { "active": true, + "createUpdaterArtifacts": true, "targets": "all", "resources": ["resources/**/*"], "license": "MIT", @@ -54,5 +55,13 @@ "windows": { "signCommand": "trusted-signing-cli -e https://eus.codesigning.azure.net/ -a CJ-Signing -c cjpais-dev -d Handy %1" } + }, + "plugins": { + "updater": { + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEJBQjcyMDk1MjA2NjAxRjkKUldUNUFXWWdsU0MzdXRRZi8zYzhqV2FaNUVDbDd2Rk5VM1IvWWowVXdmRFNKQ1BrMXF5RFFsLy8K", + "endpoints": [ + "https://github.com/cjpais/Handy/releases/latest/download/latest.json" + ] + } } -} \ No newline at end of file +} From fff8be3a96a4d830fb76ff354fd44181cc674d24 Mon Sep 17 00:00:00 2001 From: CJ Pais Date: Thu, 26 Jun 2025 13:53:17 -0700 Subject: [PATCH 2/3] better menu --- .github/workflows/release.yml | 5 +++++ src-tauri/src/lib.rs | 19 ++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 97ba970..9ccc60b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,6 +35,11 @@ jobs: # Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds. targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} + - name: Rust cache + uses: swatinem/rust-cache@v2 + with: + workspaces: "./src-tauri -> target" + - name: install dependencies (ubuntu only) if: matrix.platform == 'ubuntu-22.04' # This must match the platform value defined above. run: | diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 360d3b0..8b69733 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -43,15 +43,28 @@ pub fn run() { let version = env!("CARGO_PKG_VERSION"); let version_label = format!("Handy v{}", version); let version_i = MenuItem::with_id(app, "version", &version_label, false, None::<&str>)?; - let settings_i = MenuItem::with_id(app, "settings", "Settings", true, None::<&str>)?; + + // Platform-specific accelerators + #[cfg(target_os = "macos")] + let settings_accelerator = Some("Cmd+,"); + #[cfg(not(target_os = "macos"))] + let settings_accelerator = Some("Ctrl+,"); + + #[cfg(target_os = "macos")] + let quit_accelerator = Some("Cmd+Q"); + #[cfg(not(target_os = "macos"))] + let quit_accelerator = Some("Ctrl+Q"); + + let settings_i = + MenuItem::with_id(app, "settings", "Settings...", true, settings_accelerator)?; let check_updates_i = MenuItem::with_id( app, "check_updates", - "Check for Updates", + "Check for Updates...", true, None::<&str>, )?; - let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?; + let quit_i = MenuItem::with_id(app, "quit", "Quit", true, quit_accelerator)?; let menu = Menu::with_items( app, &[ From fabb1f87600615991ad913af1548cb83ebea974f Mon Sep 17 00:00:00 2001 From: CJ Pais Date: Thu, 26 Jun 2025 14:03:40 -0700 Subject: [PATCH 3/3] 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';