add footer with the curr version
This commit is contained in:
parent
fff8be3a96
commit
fabb1f8760
5 changed files with 152 additions and 8 deletions
|
|
@ -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<ShortcutToggleStates>;
|
||||
|
||||
#[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");
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
"width": 540,
|
||||
"height": 400,
|
||||
"minWidth": 460,
|
||||
"minHeight": 400,
|
||||
"minHeight": 440,
|
||||
"resizable": true,
|
||||
"maximizable": false
|
||||
}
|
||||
|
|
|
|||
12
src/App.tsx
12
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 (
|
||||
<div className="min-h-screen flex flex-col items-center pt-6 w-full gap-4 px-4">
|
||||
<HandyTextLogo width={300} />
|
||||
<AccessibilityPermissions />
|
||||
<Settings />
|
||||
<div className="min-h-screen flex flex-col w-full">
|
||||
<div className="flex flex-col items-center pt-6 gap-4 px-4 flex-1">
|
||||
<HandyTextLogo width={300} />
|
||||
<AccessibilityPermissions />
|
||||
<Settings />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
130
src/components/footer/Footer.tsx
Normal file
130
src/components/footer/Footer.tsx
Normal file
|
|
@ -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 (
|
||||
<div className="w-full border-t border-mid-gray/20 mt-4 pt-3">
|
||||
<div className="flex justify-between items-center text-xs px-4 pb-3 text-text/60">
|
||||
<div className="flex items-center">
|
||||
<span>v{version}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{updateAvailable ? (
|
||||
<button
|
||||
onClick={installUpdate}
|
||||
disabled={isUpdating}
|
||||
className="text-logo-primary hover:text-logo-primary/80 transition-colors disabled:opacity-50 font-medium"
|
||||
>
|
||||
{isUpdating ? "Installing..." : "Update available"}
|
||||
</button>
|
||||
) : showUpToDate ? (
|
||||
<span className="text-text/60">Up to date</span>
|
||||
) : (
|
||||
<button
|
||||
onClick={handleManualUpdateCheck}
|
||||
disabled={isChecking}
|
||||
className="text-text/60 hover:text-text/80 transition-colors disabled:opacity-50"
|
||||
>
|
||||
{isChecking ? "Checking..." : "Check for updates"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
1
src/components/footer/index.ts
Normal file
1
src/components/footer/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './Footer';
|
||||
Loading…
Reference in a new issue