chore: migrate to gpui updater #42
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -9117,6 +9117,7 @@ name = "workspace"
|
|||||||
version = "1.0.0-beta5"
|
version = "1.0.0-beta5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"auto_update",
|
||||||
"browser-signer-proxy",
|
"browser-signer-proxy",
|
||||||
"chat",
|
"chat",
|
||||||
"chat_ui",
|
"chat_ui",
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#![cfg(not(target_arch = "wasm32"))]
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
|
|
||||||
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Window};
|
use gpui::{App, AppContext, Context, Entity, Global, SharedString, Subscription, Window};
|
||||||
use gpui_updater::{EngineConfig, GitHubSource, UpdateStatus, Updater, Version};
|
use gpui_updater::{EngineConfig, GitHubSource, UpdateStatus, Updater, Version};
|
||||||
use instant::Duration;
|
use instant::{Duration, Instant};
|
||||||
|
|
||||||
const COOP_UPDATE_EXPLANATION: &str = "COOP_UPDATE_EXPLANATION";
|
const COOP_UPDATE_EXPLANATION: &str = "COOP_UPDATE_EXPLANATION";
|
||||||
|
|
||||||
@@ -52,6 +52,8 @@ pub struct AutoUpdater {
|
|||||||
pub version: Version,
|
pub version: Version,
|
||||||
/// Keeps the observer subscription alive.
|
/// Keeps the observer subscription alive.
|
||||||
_subscription: Subscription,
|
_subscription: Subscription,
|
||||||
|
/// When the last error was recorded, so we can reset to idle after 5s.
|
||||||
|
error_time: Option<Instant>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AutoUpdater {
|
impl AutoUpdater {
|
||||||
@@ -83,11 +85,24 @@ impl AutoUpdater {
|
|||||||
// When an update becomes available, automatically download and install it.
|
// When an update becomes available, automatically download and install it.
|
||||||
let subscription = cx.observe(&updater, |this: &mut AutoUpdater, _updater, cx| {
|
let subscription = cx.observe(&updater, |this: &mut AutoUpdater, _updater, cx| {
|
||||||
let status = this.updater.read(cx).status().clone();
|
let status = this.updater.read(cx).status().clone();
|
||||||
|
|
||||||
if matches!(status, UpdateStatus::Available(_)) {
|
if matches!(status, UpdateStatus::Available(_)) {
|
||||||
this.updater.update(cx, |updater, cx| {
|
this.updater.update(cx, |updater, cx| {
|
||||||
updater.download_and_install(cx);
|
updater.download_and_install(cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if matches!(status, UpdateStatus::Errored(_)) {
|
||||||
|
this.error_time = Some(Instant::now());
|
||||||
|
cx.spawn(async move |this, cx| {
|
||||||
|
cx.background_executor().timer(Duration::from_secs(5)).await;
|
||||||
|
this.update(cx, |_this, cx| cx.notify()).ok();
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
} else {
|
||||||
|
this.error_time = None;
|
||||||
|
}
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -111,6 +126,55 @@ impl AutoUpdater {
|
|||||||
updater,
|
updater,
|
||||||
version,
|
version,
|
||||||
_subscription: subscription,
|
_subscription: subscription,
|
||||||
|
error_time: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn idle(&self, cx: &App) -> bool {
|
||||||
|
let status = self.updater.read(cx).status();
|
||||||
|
if status == &UpdateStatus::Idle {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if matches!(status, UpdateStatus::Errored(_))
|
||||||
|
&& self
|
||||||
|
.error_time
|
||||||
|
.is_some_and(|t| t.elapsed() >= Duration::from_secs(5))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status(&self, cx: &App) -> SharedString {
|
||||||
|
let status = self.updater.read(cx).status();
|
||||||
|
|
||||||
|
match status {
|
||||||
|
UpdateStatus::Idle => "Up to date".into(),
|
||||||
|
UpdateStatus::Checking => "Checking for updates…".into(),
|
||||||
|
UpdateStatus::UpToDate => "Up to date".into(),
|
||||||
|
UpdateStatus::Available(version) => format!("Version {version} available").into(),
|
||||||
|
UpdateStatus::Downloading { downloaded, total } => {
|
||||||
|
let total_mb = total.map(|t| t as f64 / 1_048_576.0);
|
||||||
|
let downloaded_mb = *downloaded as f64 / 1_048_576.0;
|
||||||
|
match total_mb {
|
||||||
|
Some(t) => format!("Downloading {downloaded_mb:.1} / {t:.1} MB").into(),
|
||||||
|
None => format!("Downloading {downloaded_mb:.1} MB").into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateStatus::Installing => "Installing update…".into(),
|
||||||
|
UpdateStatus::Staged(version) => {
|
||||||
|
format!("Version {version} ready — restart to apply").into()
|
||||||
|
}
|
||||||
|
UpdateStatus::Errored(msg) => {
|
||||||
|
if self
|
||||||
|
.error_time
|
||||||
|
.is_some_and(|t| t.elapsed() >= Duration::from_secs(5))
|
||||||
|
{
|
||||||
|
"Up to date".into()
|
||||||
|
} else {
|
||||||
|
format!("Update failed: {msg}").into()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,12 +164,8 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="logo">
|
|
||||||
<div class="logo__mark">C</div>
|
|
||||||
<span class="logo__text">Coop</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1 class="heading">Web Signer</h1>
|
<h1 class="heading">Web Signer</h1>
|
||||||
|
|
||||||
<p class="subtitle">
|
<p class="subtitle">
|
||||||
This page connects the app to your Nostr Web Signer extension so you can sign in and use Coop securely.
|
This page connects the app to your Nostr Web Signer extension so you can sign in and use Coop securely.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ chat = { path = "../chat" }
|
|||||||
chat_ui = { path = "../chat_ui" }
|
chat_ui = { path = "../chat_ui" }
|
||||||
settings = { path = "../settings" }
|
settings = { path = "../settings" }
|
||||||
person = { path = "../person" }
|
person = { path = "../person" }
|
||||||
|
auto_update = { path = "../auto_update" }
|
||||||
|
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
nostr-sdk.workspace = true
|
nostr-sdk.workspace = true
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use ::settings::AppSettings;
|
use ::settings::AppSettings;
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use auto_update::AutoUpdater;
|
||||||
use chat::{ChatEvent, ChatRegistry};
|
use chat::{ChatEvent, ChatRegistry};
|
||||||
use common::{CoopImageCache, download_dir};
|
use common::{CoopImageCache, download_dir};
|
||||||
use device::{DeviceEvent, DeviceRegistry};
|
use device::{DeviceEvent, DeviceRegistry};
|
||||||
@@ -379,7 +380,12 @@ impl Workspace {
|
|||||||
self.import_encryption(window, cx);
|
self.import_encryption(window, cx);
|
||||||
}
|
}
|
||||||
Command::Update => {
|
Command::Update => {
|
||||||
//
|
let auto_updater = AutoUpdater::global(cx);
|
||||||
|
auto_updater.update(cx, |this, cx| {
|
||||||
|
this.updater.update(cx, |updater, cx| {
|
||||||
|
updater.check(cx);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -604,6 +610,7 @@ impl Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn titlebar_right(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
|
fn titlebar_right(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
|
let updater = AutoUpdater::global(cx);
|
||||||
let chat = ChatRegistry::global(cx);
|
let chat = ChatRegistry::global(cx);
|
||||||
let nip4e_enabled = AppSettings::get_nip4e(cx);
|
let nip4e_enabled = AppSettings::get_nip4e(cx);
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
@@ -615,10 +622,15 @@ impl Workspace {
|
|||||||
let persons = PersonRegistry::global(cx);
|
let persons = PersonRegistry::global(cx);
|
||||||
let profile = persons.read(cx).get(&public_key, cx);
|
let profile = persons.read(cx).get(&public_key, cx);
|
||||||
let announcement = profile.announcement();
|
let announcement = profile.announcement();
|
||||||
|
let updater_idle = updater.read(cx).idle(cx);
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
|
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
|
||||||
.gap_2()
|
.gap_2()
|
||||||
|
.when(!updater_idle, |this| {
|
||||||
|
let status = updater.read(cx).status(cx);
|
||||||
|
this.child(div().text_xs().italic().child(status))
|
||||||
|
})
|
||||||
.when(nip4e_enabled, |this| {
|
.when(nip4e_enabled, |this| {
|
||||||
this.child(
|
this.child(
|
||||||
Button::new("key")
|
Button::new("key")
|
||||||
|
|||||||
Reference in New Issue
Block a user