mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Fix Iced sample
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -1790,9 +1790,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.12.0"
|
version = "3.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
|
checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ members = [
|
|||||||
"src/bins",
|
"src/bins",
|
||||||
"src/lib-rust",
|
"src/lib-rust",
|
||||||
"src/lib-nodejs/crates/velopack_nodeffi",
|
"src/lib-nodejs/crates/velopack_nodeffi",
|
||||||
# "src/lib-cpp/generator"
|
# "src/lib-cpp/generator,"
|
||||||
|
]
|
||||||
|
exclude = [
|
||||||
|
"samples/RustIced",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ publish = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
iced = { version = "0.12", features = ["async-std", "debug"] }
|
iced = { version = "0.13", features = ["async-std", "debug"] }
|
||||||
async-std = "1.5"
|
async-std = "1.5"
|
||||||
once_cell = "1.19"
|
once_cell = "1.19"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
@@ -14,4 +14,4 @@ serde_json = "1.0"
|
|||||||
uuid = { version = "1.0", features = ["v4", "fast-rng", "serde"] }
|
uuid = { version = "1.0", features = ["v4", "fast-rng", "serde"] }
|
||||||
directories-next = "2.0"
|
directories-next = "2.0"
|
||||||
tracing-subscriber = "0.3"
|
tracing-subscriber = "0.3"
|
||||||
velopack = { path = "../../", features = ["async"]}
|
velopack = { path = "../../src/lib-rust", features = ["async"] }
|
||||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
127
samples/RustIced/src/main.rs
Normal file
127
samples/RustIced/src/main.rs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
#![windows_subsystem = "windows"]
|
||||||
|
use anyhow::Result;
|
||||||
|
use iced::widget::{Button, Column, Text};
|
||||||
|
|
||||||
|
use velopack::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Message {
|
||||||
|
CheckForUpdates,
|
||||||
|
UpdatesFound(Option<UpdateInfo>),
|
||||||
|
DownloadUpdates,
|
||||||
|
DownloadProgress(i16),
|
||||||
|
DownloadComplete,
|
||||||
|
Restart,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GUI {
|
||||||
|
update_manager: Option<UpdateManager>,
|
||||||
|
state: GUIState,
|
||||||
|
current_version: Option<String>,
|
||||||
|
update_info: Option<UpdateInfo>,
|
||||||
|
download_progress: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum GUIState {
|
||||||
|
NotInstalled,
|
||||||
|
Idle,
|
||||||
|
Checking,
|
||||||
|
UpdatesAvailable,
|
||||||
|
Downloading,
|
||||||
|
ReadyToRestart,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
VelopackApp::build().run();
|
||||||
|
|
||||||
|
let source = sources::FileSource::new(env!("RELEASES_DIR"));
|
||||||
|
let um = UpdateManager::new(source, None, None);
|
||||||
|
let mut version: Option<String> = None;
|
||||||
|
let mut state = GUIState::NotInstalled;
|
||||||
|
if um.is_ok() {
|
||||||
|
state = GUIState::Idle;
|
||||||
|
version = Some(um.as_ref().unwrap().current_version().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let gui = GUI { update_manager: um.ok(), state, current_version: version, update_info: None, download_progress: 0 };
|
||||||
|
|
||||||
|
iced::application("A cool application", update, view)
|
||||||
|
.window_size(iced::Size::new(400.0, 200.0))
|
||||||
|
.run_with(move || (gui, iced::Task::none()))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(gui: &mut GUI, message: Message) -> iced::Task<Message> {
|
||||||
|
match message {
|
||||||
|
Message::CheckForUpdates => {
|
||||||
|
gui.state = GUIState::Checking;
|
||||||
|
iced::Task::perform(gui.update_manager.as_ref().unwrap().check_for_updates_async(), |result| match result {
|
||||||
|
Ok(update_info) => {
|
||||||
|
match update_info {
|
||||||
|
UpdateCheck::RemoteIsEmpty => Message::UpdatesFound(None),
|
||||||
|
UpdateCheck::NoUpdateAvailable => Message::UpdatesFound(None),
|
||||||
|
UpdateCheck::UpdateAvailable(updates) => Message::UpdatesFound(Some(updates)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// Handle the error case, perhaps by logging or setting an error state
|
||||||
|
// For simplicity, we're sending a None update here, but you should handle errors appropriately
|
||||||
|
Message::UpdatesFound(None)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Message::UpdatesFound(update) => {
|
||||||
|
gui.update_info = update;
|
||||||
|
gui.state = match gui.update_info {
|
||||||
|
Some(_) => GUIState::UpdatesAvailable,
|
||||||
|
None => GUIState::Idle,
|
||||||
|
};
|
||||||
|
iced::Task::none()
|
||||||
|
}
|
||||||
|
Message::DownloadUpdates => {
|
||||||
|
gui.state = GUIState::Downloading;
|
||||||
|
let update_info = gui.update_info.clone().unwrap(); // Ensure you handle this safely in your actual code
|
||||||
|
iced::Task::perform(gui.update_manager.as_ref().unwrap().download_updates_async(&update_info, None), |_| Message::DownloadComplete)
|
||||||
|
}
|
||||||
|
Message::DownloadProgress(progress) => {
|
||||||
|
gui.download_progress = progress;
|
||||||
|
iced::Task::none()
|
||||||
|
}
|
||||||
|
Message::DownloadComplete => {
|
||||||
|
gui.state = GUIState::ReadyToRestart;
|
||||||
|
iced::Task::none()
|
||||||
|
}
|
||||||
|
Message::Restart => {
|
||||||
|
let update_info = gui.update_info.clone().unwrap(); // Ensure you handle this safely in your actual code
|
||||||
|
gui.update_manager.as_ref().unwrap().apply_updates_and_restart(update_info).unwrap();
|
||||||
|
iced::Task::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(gui: &GUI) -> iced::Element<Message> {
|
||||||
|
let content = match gui.state {
|
||||||
|
GUIState::NotInstalled => Column::new()
|
||||||
|
.push(Text::new("Can't check for updates if not installed")),
|
||||||
|
GUIState::Idle => Column::new()
|
||||||
|
.push(Text::new(format!("Current version: {}", gui.current_version.as_ref().unwrap_or(&"Unknown".to_string()))))
|
||||||
|
.push(Button::new(Text::new("Check for updates")).on_press(Message::CheckForUpdates)),
|
||||||
|
GUIState::Checking => Column::new()
|
||||||
|
.push(Text::new("Checking for updates...")),
|
||||||
|
GUIState::UpdatesAvailable => {
|
||||||
|
let update_version = gui.update_info.as_ref().map_or("Unknown", |info| &info.TargetFullRelease.Version);
|
||||||
|
Column::new()
|
||||||
|
.push(Text::new(format!("Update available: {}", update_version)))
|
||||||
|
.push(Button::new(Text::new("Download updates")).on_press(Message::DownloadUpdates))
|
||||||
|
}
|
||||||
|
GUIState::Downloading => Column::new()
|
||||||
|
.push(Text::new(format!("Downloading updates... Progress: {}%", gui.download_progress))),
|
||||||
|
GUIState::ReadyToRestart => Column::new()
|
||||||
|
.push(Text::new("Updates downloaded. Ready to restart."))
|
||||||
|
.push(Button::new(Text::new("Restart")).on_press(Message::Restart)),
|
||||||
|
};
|
||||||
|
|
||||||
|
content.into()
|
||||||
|
}
|
||||||
@@ -5,3 +5,4 @@
|
|||||||
- [**CSharpUnityMono**](CSharpUnityMono) - Velopack with [Unity Game Engine](https://unity.com/) and Mono.
|
- [**CSharpUnityMono**](CSharpUnityMono) - Velopack with [Unity Game Engine](https://unity.com/) and Mono.
|
||||||
- [**CSharpUno**](CSharpUno) - Velopack in a cross-platform app with [Uno Platform](https://github.com/unoplatform/uno).
|
- [**CSharpUno**](CSharpUno) - Velopack in a cross-platform app with [Uno Platform](https://github.com/unoplatform/uno).
|
||||||
- [**CSharpWpf**](CSharpWpf) - Velopack with WPF on Windows.
|
- [**CSharpWpf**](CSharpWpf) - Velopack with WPF on Windows.
|
||||||
|
- [**RustIced**](RustIced) - Velopack in a cross-platform app with [Iced](https://github.com/iced-rs/iced).
|
||||||
|
|||||||
@@ -205,7 +205,6 @@ fn js_appbuilder_run(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|||||||
|
|
||||||
let undefined = cx.undefined();
|
let undefined = cx.undefined();
|
||||||
let cx_ref = Rc::new(RefCell::new(cx));
|
let cx_ref = Rc::new(RefCell::new(cx));
|
||||||
let cx_ref2 = cx_ref.clone();
|
|
||||||
|
|
||||||
let hook_handler = move |hook_name: &str, current_version: Version| {
|
let hook_handler = move |hook_name: &str, current_version: Version| {
|
||||||
let mut cx = cx_ref.borrow_mut();
|
let mut cx = cx_ref.borrow_mut();
|
||||||
@@ -228,14 +227,11 @@ fn js_appbuilder_run(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
|||||||
builder = builder.set_locator(locator);
|
builder = builder.set_locator(locator);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(argarray) = argarray {
|
if let Some(arg_array) = argarray {
|
||||||
builder = builder.set_args(argarray);
|
builder = builder.set_args(arg_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.run().or_else(|e| {
|
builder.run();
|
||||||
let mut cx = cx_ref2.borrow_mut();
|
|
||||||
cx.throw_error(e.to_string())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(undefined)
|
Ok(undefined)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
#![windows_subsystem = "windows"]
|
|
||||||
use anyhow::Result;
|
|
||||||
use iced::theme::Theme;
|
|
||||||
use iced::widget::{Button, Column, Text};
|
|
||||||
use iced::{Command, Application};
|
|
||||||
|
|
||||||
use velopack::*;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Message {
|
|
||||||
CheckForUpdates,
|
|
||||||
UpdatesFound(Option<UpdateInfo>),
|
|
||||||
DownloadUpdates,
|
|
||||||
DownloadProgress(i16),
|
|
||||||
DownloadComplete,
|
|
||||||
Restart,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct GUI {
|
|
||||||
update_manager: Option<UpdateManager<sources::FileSource>>,
|
|
||||||
state: GUIState,
|
|
||||||
current_version: Option<String>,
|
|
||||||
update_info: Option<UpdateInfo>,
|
|
||||||
download_progress: i16,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum GUIState {
|
|
||||||
NotInstalled,
|
|
||||||
Idle,
|
|
||||||
Checking,
|
|
||||||
UpdatesAvailable,
|
|
||||||
Downloading,
|
|
||||||
ReadyToRestart,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
VelopackApp::build().run();
|
|
||||||
let mut set = iced::Settings::default();
|
|
||||||
set.window.size = iced::Size { width: 400.0, height: 200.0 };
|
|
||||||
GUI::run(set)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Application for GUI {
|
|
||||||
type Message = Message;
|
|
||||||
type Theme = Theme;
|
|
||||||
type Executor = iced::executor::Default;
|
|
||||||
type Flags = ();
|
|
||||||
|
|
||||||
fn new(_flags: ()) -> (Self, Command<Self::Message>) {
|
|
||||||
let sounce = sources::FileSource::new(env!("RELEASES_DIR"));
|
|
||||||
let um = UpdateManager::new(sounce, None);
|
|
||||||
let mut version: Option<String> = None;
|
|
||||||
let mut state = GUIState::NotInstalled;
|
|
||||||
if um.is_ok() {
|
|
||||||
state = GUIState::Idle;
|
|
||||||
version = Some(um.as_ref().unwrap().current_version().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
let gui = Self { update_manager: um.ok(), state: state, current_version: version, update_info: None, download_progress: 0 };
|
|
||||||
(gui, iced::Command::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self) -> String {
|
|
||||||
String::from("Velopack Rust Demo")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Self::Message) -> iced::Command<Self::Message> {
|
|
||||||
match message {
|
|
||||||
Message::CheckForUpdates => {
|
|
||||||
self.state = GUIState::Checking;
|
|
||||||
iced::Command::perform(self.update_manager.as_ref().unwrap().check_for_updates_async(), |result| match result {
|
|
||||||
Ok(update_info) => Message::UpdatesFound(update_info),
|
|
||||||
Err(_) => {
|
|
||||||
// Handle the error case, perhaps by logging or setting an error state
|
|
||||||
// For simplicity, we're sending a None update here, but you should handle errors appropriately
|
|
||||||
Message::UpdatesFound(None)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Message::UpdatesFound(update) => {
|
|
||||||
self.update_info = update;
|
|
||||||
self.state = match self.update_info {
|
|
||||||
Some(_) => GUIState::UpdatesAvailable,
|
|
||||||
None => GUIState::Idle,
|
|
||||||
};
|
|
||||||
iced::Command::none()
|
|
||||||
}
|
|
||||||
Message::DownloadUpdates => {
|
|
||||||
self.state = GUIState::Downloading;
|
|
||||||
let update_info = self.update_info.clone().unwrap(); // Ensure you handle this safely in your actual code
|
|
||||||
iced::Command::perform(self.update_manager.as_ref().unwrap().download_updates_async(&update_info, None), |_| Message::DownloadComplete)
|
|
||||||
}
|
|
||||||
Message::DownloadProgress(progress) => {
|
|
||||||
self.download_progress = progress;
|
|
||||||
iced::Command::none()
|
|
||||||
}
|
|
||||||
Message::DownloadComplete => {
|
|
||||||
self.state = GUIState::ReadyToRestart;
|
|
||||||
iced::Command::none()
|
|
||||||
}
|
|
||||||
Message::Restart => {
|
|
||||||
let update_info = self.update_info.clone().unwrap(); // Ensure you handle this safely in your actual code
|
|
||||||
self.update_manager.as_ref().unwrap().apply_updates_and_restart(update_info, RestartArgs::None).unwrap();
|
|
||||||
iced::Command::none()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn view(&self) -> iced::Element<Self::Message> {
|
|
||||||
let content = match self.state {
|
|
||||||
GUIState::NotInstalled => Column::new()
|
|
||||||
.push(Text::new("Can't check for updates if not installed")),
|
|
||||||
GUIState::Idle => Column::new()
|
|
||||||
.push(Text::new(format!("Current version: {}", self.current_version.as_ref().unwrap_or(&"Unknown".to_string()))))
|
|
||||||
.push(Button::new(Text::new("Check for updates")).on_press(Message::CheckForUpdates)),
|
|
||||||
GUIState::Checking => Column::new()
|
|
||||||
.push(Text::new("Checking for updates...")),
|
|
||||||
GUIState::UpdatesAvailable => {
|
|
||||||
let update_version = self.update_info.as_ref().map_or("Unknown", |info| &info.TargetFullRelease.Version);
|
|
||||||
Column::new()
|
|
||||||
.push(Text::new(format!("Update available: {}", update_version)))
|
|
||||||
.push(Button::new(Text::new("Download updates")).on_press(Message::DownloadUpdates))
|
|
||||||
},
|
|
||||||
GUIState::Downloading => Column::new()
|
|
||||||
.push(Text::new(format!("Downloading updates... Progress: {}%", self.download_progress))),
|
|
||||||
GUIState::ReadyToRestart => Column::new()
|
|
||||||
.push(Text::new("Updates downloaded. Ready to restart."))
|
|
||||||
.push(Button::new(Text::new("Restart")).on_press(Message::Restart)),
|
|
||||||
};
|
|
||||||
|
|
||||||
content.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -111,7 +111,7 @@ impl<'a> VelopackApp<'a> {
|
|||||||
|
|
||||||
/// Runs the Velopack startup logic. This should be the first thing to run in your app.
|
/// Runs the Velopack startup logic. This should be the first thing to run in your app.
|
||||||
/// In some circumstances it may terminate/restart the process to perform tasks.
|
/// In some circumstances it may terminate/restart the process to perform tasks.
|
||||||
pub fn run(&mut self) -> Result<(), Error> {
|
pub fn run(&mut self) {
|
||||||
let args: Vec<String> = self.args.clone();
|
let args: Vec<String> = self.args.clone();
|
||||||
|
|
||||||
info!("VelopackApp: Running with args: {:?}", args);
|
info!("VelopackApp: Running with args: {:?}", args);
|
||||||
@@ -126,14 +126,14 @@ impl<'a> VelopackApp<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let locator = if let Some(config) = &self.locator {
|
let locator = self.load_locator();
|
||||||
let manifest = config.load_manifest()?;
|
|
||||||
VelopackLocator::new(config.clone(), manifest)
|
|
||||||
} else {
|
|
||||||
auto_locate_app_manifest(LocationContext::FromCurrentExe)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let my_version = locator.get_manifest_version();
|
if let Err(e) = locator {
|
||||||
|
error!("VelopackApp: Error loading locator: {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let my_version = locator.unwrap().get_manifest_version();
|
||||||
|
|
||||||
let firstrun = env::var("VELOPACK_FIRSTRUN").is_ok();
|
let firstrun = env::var("VELOPACK_FIRSTRUN").is_ok();
|
||||||
let restarted = env::var("VELOPACK_RESTART").is_ok();
|
let restarted = env::var("VELOPACK_RESTART").is_ok();
|
||||||
@@ -147,8 +147,6 @@ impl<'a> VelopackApp<'a> {
|
|||||||
if restarted {
|
if restarted {
|
||||||
Self::call_hook(&mut self.restarted_hook, &my_version);
|
Self::call_hook(&mut self.restarted_hook, &my_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_hook(hook_option: &mut Option<Box<dyn FnOnce(Version) + 'a>>, version: &Version) {
|
fn call_hook(hook_option: &mut Option<Box<dyn FnOnce(Version) + 'a>>, version: &Version) {
|
||||||
@@ -168,4 +166,14 @@ impl<'a> VelopackApp<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_locator(&self) -> Result<VelopackLocator, Error> {
|
||||||
|
let locator = if let Some(config) = &self.locator {
|
||||||
|
let manifest = config.load_manifest()?;
|
||||||
|
VelopackLocator::new(config.clone(), manifest)
|
||||||
|
} else {
|
||||||
|
auto_locate_app_manifest(LocationContext::FromCurrentExe)?
|
||||||
|
};
|
||||||
|
Ok(locator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user