summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--installer-downloader/src/controller.rs96
-rw-r--r--installer-downloader/src/delegate.rs16
-rw-r--r--installer-downloader/src/resource.rs3
-rw-r--r--installer-downloader/src/winapi_impl/delegate.rs43
-rw-r--r--installer-downloader/src/winapi_impl/ui.rs29
-rw-r--r--installer-downloader/tests/controller.rs31
-rw-r--r--installer-downloader/tests/snapshots/controller__download.snap4
-rw-r--r--installer-downloader/tests/snapshots/controller__failed_directory_creation.snap4
-rw-r--r--installer-downloader/tests/snapshots/controller__failed_verification.snap5
-rw-r--r--installer-downloader/tests/snapshots/controller__fetch_version.snap4
10 files changed, 217 insertions, 18 deletions
diff --git a/installer-downloader/src/controller.rs b/installer-downloader/src/controller.rs
index 100fcf1796..e241daf4d8 100644
--- a/installer-downloader/src/controller.rs
+++ b/installer-downloader/src/controller.rs
@@ -19,6 +19,8 @@ enum TaskMessage {
SetVersionInfo(VersionInfo),
BeginDownload,
Cancel,
+ TryBeta,
+ TryStable,
}
/// Provide a directory to use for [AppDownloader]
@@ -78,6 +80,7 @@ impl AppController {
delegate.disable_download_button();
delegate.hide_cancel_button();
delegate.hide_beta_text();
+ delegate.hide_stable_text();
let (task_tx, task_rx) = mpsc::channel(1);
tokio::spawn(handle_action_messages::<D, A, DirProvider>(
@@ -105,6 +108,14 @@ impl AppController {
delegate.on_cancel(move || {
let _ = tx.try_send(TaskMessage::Cancel);
});
+ let tx = task_tx.clone();
+ delegate.on_beta_link(move || {
+ let _ = tx.try_send(TaskMessage::TryBeta);
+ });
+ let tx = task_tx.clone();
+ delegate.on_stable_link(move || {
+ let _ = tx.try_send(TaskMessage::TryStable);
+ });
}
}
@@ -139,6 +150,12 @@ where
}
}
+#[derive(Clone, Copy, PartialEq)]
+enum TargetVersion {
+ Beta,
+ Stable,
+}
+
/// Async worker that handles actions such as initiating a download, cancelling it, and updating
/// labels.
async fn handle_action_messages<D, A, DirProvider>(
@@ -152,6 +169,8 @@ async fn handle_action_messages<D, A, DirProvider>(
let mut version_info = None;
let mut active_download = None;
+ let mut target_version = TargetVersion::Stable;
+
while let Some(msg) = rx.recv().await {
match msg {
TaskMessage::SetVersionInfo(new_version_info) => {
@@ -166,6 +185,38 @@ async fn handle_action_messages<D, A, DirProvider>(
});
version_info = Some(new_version_info);
}
+ TaskMessage::TryBeta => {
+ let Some(version_info) = version_info.as_ref() else {
+ continue;
+ };
+ let Some(beta_info) = version_info.beta.as_ref() else {
+ continue;
+ };
+
+ target_version = TargetVersion::Beta;
+ let version_label = format_latest_version(beta_info);
+
+ queue.queue_main(move |self_| {
+ self_.show_stable_text();
+ self_.hide_beta_text();
+ self_.set_status_text(&version_label);
+ });
+ }
+ TaskMessage::TryStable => {
+ let Some(version_info) = version_info.as_ref() else {
+ continue;
+ };
+ let stable_info = &version_info.stable;
+
+ target_version = TargetVersion::Stable;
+ let version_label = format_latest_version(stable_info);
+
+ queue.queue_main(move |self_| {
+ self_.hide_stable_text();
+ self_.show_beta_text();
+ self_.set_status_text(&version_label);
+ });
+ }
TaskMessage::BeginDownload => {
if active_download.is_some() {
continue;
@@ -188,17 +239,25 @@ async fn handle_action_messages<D, A, DirProvider>(
// Begin download
let (tx, rx) = oneshot::channel();
queue.queue_main(move |self_| {
+ let selected_version = match target_version {
+ TargetVersion::Stable => &version_info.stable,
+ TargetVersion::Beta => {
+ version_info.beta.as_ref().expect("selected version exists")
+ }
+ };
+
// TODO: Select appropriate URLs
- let Some(app_url) = version_info.stable.urls.first() else {
+ let Some(app_url) = selected_version.urls.first() else {
return;
};
- let app_version = version_info.stable.version;
- let app_sha256 = version_info.stable.sha256;
- let app_size = version_info.stable.size;
+ let app_version = selected_version.version.clone();
+ let app_sha256 = selected_version.sha256;
+ let app_size = selected_version.size;
self_.set_download_text("");
self_.hide_download_button();
self_.hide_beta_text();
+ self_.hide_stable_text();
self_.show_cancel_button();
self_.enable_cancel_button();
self_.show_download_progress();
@@ -224,22 +283,33 @@ async fn handle_action_messages<D, A, DirProvider>(
active_download.abort();
let _ = active_download.await;
- let (version_label, has_beta) = if let Some(version_info) = &version_info {
- (
- format_latest_version(&version_info.stable),
- version_info.beta.is_some(),
- )
- } else {
- ("".to_owned(), false)
+ let Some(version_info) = version_info.as_ref() else {
+ continue;
};
+ let selected_version = match target_version {
+ TargetVersion::Stable => &version_info.stable,
+ TargetVersion::Beta => {
+ version_info.beta.as_ref().expect("selected version exists")
+ }
+ };
+
+ let version_label = format_latest_version(&selected_version);
+ let has_beta = version_info.beta.is_some();
+
queue.queue_main(move |self_| {
self_.set_status_text(&version_label);
self_.set_download_text("");
self_.show_download_button();
- if has_beta {
- self_.show_beta_text();
+
+ if target_version == TargetVersion::Stable {
+ if has_beta {
+ self_.show_beta_text();
+ }
+ } else {
+ self_.show_stable_text();
}
+
self_.hide_cancel_button();
self_.hide_download_progress();
self_.set_download_progress(0);
diff --git a/installer-downloader/src/delegate.rs b/installer-downloader/src/delegate.rs
index 3e82d2ef31..de4313aeb2 100644
--- a/installer-downloader/src/delegate.rs
+++ b/installer-downloader/src/delegate.rs
@@ -17,6 +17,16 @@ pub trait AppDelegate {
where
F: Fn() + Send + 'static;
+ /// Register click handler for the beta link
+ fn on_beta_link<F>(&mut self, callback: F)
+ where
+ F: Fn() + Send + 'static;
+
+ /// Register click handler for the stable link
+ fn on_stable_link<F>(&mut self, callback: F)
+ where
+ F: Fn() + Send + 'static;
+
/// Set status text
fn set_status_text(&mut self, text: &str);
@@ -62,6 +72,12 @@ pub trait AppDelegate {
/// Hide beta text
fn hide_beta_text(&mut self);
+ /// Show stable text
+ fn show_stable_text(&mut self);
+
+ /// Hide stable text
+ fn hide_stable_text(&mut self);
+
/// Exit the application
fn quit(&mut self);
diff --git a/installer-downloader/src/resource.rs b/installer-downloader/src/resource.rs
index b5f5a0bf85..af54455872 100644
--- a/installer-downloader/src/resource.rs
+++ b/installer-downloader/src/resource.rs
@@ -16,6 +16,9 @@ pub const BETA_PREFACE_DESC: &str = "Want to try the new Beta version? ";
/// Beta link text
pub const BETA_LINK_TEXT: &str = "Click here!";
+/// Stable link text
+pub const STABLE_LINK_TEXT: &str = "Back to stable version";
+
/// Dimensions of cancel button (including padding)
pub const CANCEL_BUTTON_SIZE: (usize, usize) = (150, 40);
diff --git a/installer-downloader/src/winapi_impl/delegate.rs b/installer-downloader/src/winapi_impl/delegate.rs
index 353dff9691..69176cf897 100644
--- a/installer-downloader/src/winapi_impl/delegate.rs
+++ b/installer-downloader/src/winapi_impl/delegate.rs
@@ -24,6 +24,20 @@ impl AppDelegate for AppWindow {
register_click_handler(self.window.handle, self.cancel_button.handle, callback);
}
+ fn on_beta_link<F>(&mut self, callback: F)
+ where
+ F: Fn() + Send + 'static,
+ {
+ register_label_click_handler(self.window.handle, self.beta_link.handle, callback);
+ }
+
+ fn on_stable_link<F>(&mut self, callback: F)
+ where
+ F: Fn() + Send + 'static,
+ {
+ register_label_click_handler(self.window.handle, self.stable_link.handle, callback);
+ }
+
fn set_status_text(&mut self, text: &str) {
self.status_text.set_text(text);
}
@@ -91,6 +105,14 @@ impl AppDelegate for AppWindow {
self.beta_link.set_visible(false);
}
+ fn show_stable_text(&mut self) {
+ self.stable_link.set_visible(true);
+ }
+
+ fn hide_stable_text(&mut self) {
+ self.stable_link.set_visible(false);
+ }
+
fn quit(&mut self) {
nwg::stop_thread_dispatch();
}
@@ -108,8 +130,27 @@ fn register_click_handler(
button: nwg::ControlHandle,
callback: impl Fn() + 'static,
) {
+ register_click_handler_inner(parent, button, callback, Event::OnButtonClick);
+}
+
+/// Register a window message for clicking this button that triggers `callback`.
+fn register_label_click_handler(
+ parent: nwg::ControlHandle,
+ button: nwg::ControlHandle,
+ callback: impl Fn() + 'static,
+) {
+ register_click_handler_inner(parent, button, callback, Event::OnLabelClick);
+}
+
+/// Register a window message for clicking this button that triggers `callback`.
+fn register_click_handler_inner(
+ parent: nwg::ControlHandle,
+ button: nwg::ControlHandle,
+ callback: impl Fn() + 'static,
+ click_event: Event,
+) {
nwg::bind_event_handler(&button, &parent, move |evt, _, handle| {
- if evt == Event::OnButtonClick && handle == button {
+ if evt == click_event && handle == button {
callback();
}
});
diff --git a/installer-downloader/src/winapi_impl/ui.rs b/installer-downloader/src/winapi_impl/ui.rs
index 1b4704ad3d..f53d00dccd 100644
--- a/installer-downloader/src/winapi_impl/ui.rs
+++ b/installer-downloader/src/winapi_impl/ui.rs
@@ -14,7 +14,8 @@ use windows_sys::Win32::UI::WindowsAndMessaging::WM_CTLCOLORSTATIC;
use crate::resource::{
BANNER_DESC, BETA_LINK_TEXT, BETA_PREFACE_DESC, CANCEL_BUTTON_SIZE, CANCEL_BUTTON_TEXT,
- DOWNLOAD_BUTTON_SIZE, DOWNLOAD_BUTTON_TEXT, WINDOW_HEIGHT, WINDOW_TITLE, WINDOW_WIDTH,
+ DOWNLOAD_BUTTON_SIZE, DOWNLOAD_BUTTON_TEXT, STABLE_LINK_TEXT, WINDOW_HEIGHT, WINDOW_TITLE,
+ WINDOW_WIDTH,
};
use super::delegate::QueueContext;
@@ -32,6 +33,8 @@ pub const SET_LABEL_HANDLER_ID: usize = 0x10000;
pub const QUEUE_MESSAGE_HANDLER_ID: usize = 0x10001;
/// Custom window message used to process requests from other threads.
pub const QUEUE_MESSAGE: u32 = 0x10001;
+/// Unique ID of the handler for the stable link.
+pub const STABLE_LINK_HANDLER_ID: usize = 0x10003;
/// Unique ID of the handler for the beta link.
pub const BETA_LINK_HANDLER_ID: usize = 0x10002;
@@ -57,6 +60,7 @@ pub struct AppWindow {
pub beta_prefix: nwg::Label,
pub beta_link: nwg::Label,
+ pub stable_link: nwg::Label,
}
impl AppWindow {
@@ -121,14 +125,26 @@ impl AppWindow {
.text(BETA_PREFACE_DESC)
.h_align(nwg::HTextAlign::Left)
.build(&mut self.beta_prefix)?;
+
+ let link_font = create_link_font()?;
+
nwg::Label::builder()
.parent(&self.window)
.size((128, 24))
.text(BETA_LINK_TEXT)
- .font(Some(&create_link_font()?))
+ .font(Some(&link_font))
.h_align(nwg::HTextAlign::Left)
.build(&mut self.beta_link)?;
+ nwg::Label::builder()
+ .parent(&self.window)
+ .size((240, 24))
+ .text(STABLE_LINK_TEXT)
+ .font(Some(&link_font))
+ .h_align(nwg::HTextAlign::Left)
+ .build(&mut self.stable_link)?;
+ self.stable_link.set_visible(false);
+
const PROGRESS_BAR_MARGIN: i32 = 48;
nwg::ProgressBar::builder()
.parent(&self.window)
@@ -167,6 +183,11 @@ impl AppWindow {
+ LOWER_AREA_YPADDING,
);
+ self.stable_link.set_position(
+ 24,
+ self.window.size().1 as i32 - 24 - self.stable_link.size().1 as i32,
+ );
+ handle_link_messages(&self.window, &self.stable_link, STABLE_LINK_HANDLER_ID)?;
self.beta_prefix.set_position(
24,
self.window.size().1 as i32 - 24 - self.beta_prefix.size().1 as i32,
@@ -175,7 +196,7 @@ impl AppWindow {
self.beta_prefix.position().0 + self.beta_prefix.size().0 as i32,
self.beta_prefix.position().1,
);
- handle_beta_link_messages(&self.window, &self.beta_link, BETA_LINK_HANDLER_ID)?;
+ handle_link_messages(&self.window, &self.beta_link, BETA_LINK_HANDLER_ID)?;
self.window.set_visible(true);
@@ -277,7 +298,7 @@ fn handle_banner_label_colors(
}
/// Register a window message handler for the beta link component
-fn handle_beta_link_messages(
+fn handle_link_messages(
parent: &nwg::Window,
link: &nwg::Label,
handler_id: usize,
diff --git a/installer-downloader/tests/controller.rs b/installer-downloader/tests/controller.rs
index 03a4842ec7..8ac544b98a 100644
--- a/installer-downloader/tests/controller.rs
+++ b/installer-downloader/tests/controller.rs
@@ -147,6 +147,10 @@ pub struct FakeAppDelegate {
pub download_callback: Option<Box<dyn Fn() + Send>>,
/// Callback registered by `on_cancel`
pub cancel_callback: Option<Box<dyn Fn() + Send>>,
+ /// Callback registered by `on_beta_link`
+ pub beta_callback: Option<Box<dyn Fn() + Send>>,
+ /// Callback registered by `on_stable_link`
+ pub stable_callback: Option<Box<dyn Fn() + Send>>,
/// State of delegate
pub state: DelegateState,
/// Queue used to simulate the main thread
@@ -165,6 +169,7 @@ pub struct DelegateState {
pub download_progress: u32,
pub download_progress_visible: bool,
pub beta_text_visible: bool,
+ pub stable_text_visible: bool,
pub quit: bool,
/// Record of method calls.
pub call_log: Vec<String>,
@@ -189,6 +194,22 @@ impl AppDelegate for FakeAppDelegate {
self.cancel_callback = Some(Box::new(callback));
}
+ fn on_beta_link<F>(&mut self, callback: F)
+ where
+ F: Fn() + Send + 'static,
+ {
+ self.state.call_log.push("on_beta_link".into());
+ self.beta_callback = Some(Box::new(callback));
+ }
+
+ fn on_stable_link<F>(&mut self, callback: F)
+ where
+ F: Fn() + Send + 'static,
+ {
+ self.state.call_log.push("on_stable_link".into());
+ self.stable_callback = Some(Box::new(callback));
+ }
+
fn set_status_text(&mut self, text: &str) {
self.state
.call_log
@@ -270,6 +291,16 @@ impl AppDelegate for FakeAppDelegate {
self.state.beta_text_visible = false;
}
+ fn show_stable_text(&mut self) {
+ self.state.call_log.push("show_stable_text".into());
+ self.state.stable_text_visible = true;
+ }
+
+ fn hide_stable_text(&mut self) {
+ self.state.call_log.push("hide_stable_text".into());
+ self.state.stable_text_visible = false;
+ }
+
fn quit(&mut self) {
self.state.call_log.push("quit".into());
self.state.quit = true;
diff --git a/installer-downloader/tests/snapshots/controller__download.snap b/installer-downloader/tests/snapshots/controller__download.snap
index 3d79a1922e..ded40dd4a4 100644
--- a/installer-downloader/tests/snapshots/controller__download.snap
+++ b/installer-downloader/tests/snapshots/controller__download.snap
@@ -12,6 +12,7 @@ download_button_enabled: true
download_progress: 0
download_progress_visible: false
beta_text_visible: false
+stable_text_visible: false
quit: false
call_log:
- hide_download_progress
@@ -19,8 +20,11 @@ call_log:
- disable_download_button
- hide_cancel_button
- hide_beta_text
+ - hide_stable_text
- "set_status_text: Loading version details..."
- on_download
- on_cancel
+ - on_beta_link
+ - on_stable_link
- "set_status_text: Version: 2025.1"
- enable_download_button
diff --git a/installer-downloader/tests/snapshots/controller__failed_directory_creation.snap b/installer-downloader/tests/snapshots/controller__failed_directory_creation.snap
index 9cb6d6fcb1..2abc026735 100644
--- a/installer-downloader/tests/snapshots/controller__failed_directory_creation.snap
+++ b/installer-downloader/tests/snapshots/controller__failed_directory_creation.snap
@@ -12,6 +12,7 @@ download_button_enabled: true
download_progress: 0
download_progress_visible: false
beta_text_visible: false
+stable_text_visible: false
quit: false
call_log:
- hide_download_progress
@@ -19,9 +20,12 @@ call_log:
- disable_download_button
- hide_cancel_button
- hide_beta_text
+ - hide_stable_text
- "set_status_text: Loading version details..."
- on_download
- on_cancel
+ - on_beta_link
+ - on_stable_link
- "set_status_text: Version: 2025.1"
- enable_download_button
- "set_status_text: Failed to create download directory"
diff --git a/installer-downloader/tests/snapshots/controller__failed_verification.snap b/installer-downloader/tests/snapshots/controller__failed_verification.snap
index b7825fb1d5..acf41ff257 100644
--- a/installer-downloader/tests/snapshots/controller__failed_verification.snap
+++ b/installer-downloader/tests/snapshots/controller__failed_verification.snap
@@ -12,6 +12,7 @@ download_button_enabled: true
download_progress: 100
download_progress_visible: true
beta_text_visible: false
+stable_text_visible: false
quit: false
call_log:
- hide_download_progress
@@ -19,14 +20,18 @@ call_log:
- disable_download_button
- hide_cancel_button
- hide_beta_text
+ - hide_stable_text
- "set_status_text: Loading version details..."
- on_download
- on_cancel
+ - on_beta_link
+ - on_stable_link
- "set_status_text: Version: 2025.1"
- enable_download_button
- "set_download_text: "
- hide_download_button
- hide_beta_text
+ - hide_stable_text
- show_cancel_button
- enable_cancel_button
- show_download_progress
diff --git a/installer-downloader/tests/snapshots/controller__fetch_version.snap b/installer-downloader/tests/snapshots/controller__fetch_version.snap
index 24c54ce95c..17f1b954cf 100644
--- a/installer-downloader/tests/snapshots/controller__fetch_version.snap
+++ b/installer-downloader/tests/snapshots/controller__fetch_version.snap
@@ -12,6 +12,7 @@ download_button_enabled: false
download_progress: 0
download_progress_visible: false
beta_text_visible: false
+stable_text_visible: false
quit: false
call_log:
- hide_download_progress
@@ -19,6 +20,9 @@ call_log:
- disable_download_button
- hide_cancel_button
- hide_beta_text
+ - hide_stable_text
- "set_status_text: Loading version details..."
- on_download
- on_cancel
+ - on_beta_link
+ - on_stable_link