From 614d7fea0685c0cf3683f4aded7fdb82922218ae Mon Sep 17 00:00:00 2001 From: Vassiliy Yegorov Date: Mon, 15 Jun 2026 14:36:30 +0700 Subject: [PATCH] Add cloud download icon and improve update UI handling Update UI to use CloudDownload icon instead of RefreshCw Improve error handling for update checks Add better visual feedback for update states Change GitHub link to RealManual repository --- app/src-tauri/src/bridge.rs | 38 +++++++++++++++++-------------------- app/src/TopBar.tsx | 10 ++++++---- landing/index.html | 2 +- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/app/src-tauri/src/bridge.rs b/app/src-tauri/src/bridge.rs index 0738e17..803a877 100644 --- a/app/src-tauri/src/bridge.rs +++ b/app/src-tauri/src/bridge.rs @@ -449,32 +449,28 @@ fn parse_ver(v: &str) -> (u64, u64, u64) { /// which `make dmg` bumps on every build. #[tauri::command] pub async fn check_update(app: AppHandle) -> Result { + // The local version is always known; the server may be unreachable (no manifest + // yet, offline). Never fail the command for that — return the current version with + // an empty `latest` so the UI can show "couldn't check" instead of blanking out. let current = app.package_info().version.to_string(); + let fallback_url = "https://spaceshell.ru/download/spacesh.dmg".to_string(); let manifest_url = std::env::var("SPACESH_UPDATE_URL").ok().filter(|s| !s.is_empty()).unwrap_or_else(|| DEFAULT_UPDATE_URL.to_string()); - let client = reqwest::Client::builder() - .timeout(Duration::from_secs(10)) - .build() - .map_err(|e| e.to_string())?; - let manifest: Value = client - .get(&manifest_url) - .send() - .await - .map_err(|e| e.to_string())? - .json() - .await - .map_err(|e| e.to_string())?; + let fetch = || async { + let client = reqwest::Client::builder().timeout(Duration::from_secs(10)).build()?; + client.get(&manifest_url).send().await?.error_for_status()?.json::().await + }; - let latest = manifest.get("version").and_then(|v| v.as_str()).unwrap_or("").to_string(); - let url = manifest - .get("url") - .and_then(|v| v.as_str()) - .unwrap_or("https://spaceshell.ru/download/spacesh.dmg") - .to_string(); - let has_update = !latest.is_empty() && parse_ver(&latest) > parse_ver(¤t); - - Ok(UpdateInfo { current, latest, has_update, url }) + match fetch().await { + Ok(manifest) => { + let latest = manifest.get("version").and_then(|v| v.as_str()).unwrap_or("").to_string(); + let url = manifest.get("url").and_then(|v| v.as_str()).unwrap_or(&fallback_url).to_string(); + let has_update = !latest.is_empty() && parse_ver(&latest) > parse_ver(¤t); + Ok(UpdateInfo { current, latest, has_update, url }) + } + Err(_) => Ok(UpdateInfo { current, latest: String::new(), has_update: false, url: fallback_url }), + } } /// Open a URL in the default browser (macOS `open`). Used by the update popover's diff --git a/app/src/TopBar.tsx b/app/src/TopBar.tsx index 13c3c1c..169ca6e 100644 --- a/app/src/TopBar.tsx +++ b/app/src/TopBar.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { FolderGit2, PanelLeft, PanelRight, Search, Bell, Settings, ChevronDown, RefreshCw, Download } from "lucide-react"; +import { FolderGit2, PanelLeft, PanelRight, Search, Bell, Settings, ChevronDown, CloudDownload, Download } from "lucide-react"; import { COLORS, FONT } from "./theme"; import type { WorkspaceView } from "./layoutTypes"; import { leafIds } from "./layoutTypes"; @@ -51,7 +51,7 @@ function UpdateControl({ update, checking, onCheck }: { update: UpdateInfo | nul animation: hasUpdate ? "spaceshPulse 2s ease-in-out infinite" : "none", }} > - + {open && ( @@ -83,8 +83,10 @@ function UpdateControl({ update, checking, onCheck }: { update: UpdateInfo | nul > Скачать {update?.latest} - ) : ( + ) : update?.latest ? (
Установлена последняя версия
+ ) : ( +
Не удалось проверить сервер
)}