Compare commits
2 Commits
fcbf4a69a0
...
614d7fea06
| Author | SHA1 | Date | |
|---|---|---|---|
|
614d7fea06
|
|||
|
74abea5467
|
+14
-18
@@ -449,33 +449,29 @@ 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<UpdateInfo, String> {
|
||||
// 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::<Value>().await
|
||||
};
|
||||
|
||||
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("https://spaceshell.ru/download/spacesh.dmg")
|
||||
.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
|
||||
/// download action — the GUI itself never streams the .dmg.
|
||||
|
||||
+6
-4
@@ -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",
|
||||
}}
|
||||
>
|
||||
<RefreshCw size={15} style={{ animation: checking ? "spaceshSpin 0.8s linear infinite" : "none" }} />
|
||||
<CloudDownload size={15} style={{ animation: checking ? "spaceshBlink 1s ease-in-out infinite" : "none" }} />
|
||||
</button>
|
||||
|
||||
{open && (
|
||||
@@ -83,8 +83,10 @@ function UpdateControl({ update, checking, onCheck }: { update: UpdateInfo | nul
|
||||
>
|
||||
<Download size={14} /> Скачать {update?.latest}
|
||||
</button>
|
||||
) : (
|
||||
) : update?.latest ? (
|
||||
<div style={{ marginTop: 10, fontSize: 12, color: COLORS.stDone }}>Установлена последняя версия</div>
|
||||
) : (
|
||||
<div style={{ marginTop: 10, fontSize: 12, color: COLORS.textMuted }}>Не удалось проверить сервер</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
@@ -151,7 +153,7 @@ export function TopBar({
|
||||
<div style={{ flex: 1 }} />
|
||||
|
||||
<style>{`
|
||||
@keyframes spaceshSpin { to { transform: rotate(360deg); } }
|
||||
@keyframes spaceshBlink { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
||||
@keyframes spaceshPulse { 0%,100% { box-shadow: 0 0 6px rgba(52,211,194,0.35); } 50% { box-shadow: 0 0 14px rgba(52,211,194,0.7); } }
|
||||
`}</style>
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ services:
|
||||
|
||||
proxy:
|
||||
image: nginx:1.27-alpine
|
||||
# Stable name so NPM can forward by name (spacesh-proxy:80) instead of a
|
||||
# pinned IP that another webproxy container could grab.
|
||||
container_name: spacesh-proxy
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- landing
|
||||
|
||||
+1
-1
@@ -1105,7 +1105,7 @@
|
||||
Скачать для macOS
|
||||
</a>
|
||||
</div>
|
||||
<a href="https://github.com/spacesh" target="_blank" rel="noopener" class="cta-github">
|
||||
<a href="https://git.realmanual.ru/realmanual/spaceshell" target="_blank" rel="noopener" class="cta-github">
|
||||
Исходники на GitHub →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user