diff --git a/Cargo.lock b/Cargo.lock index 4404b4f..3419938 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,7 +181,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -207,21 +207,33 @@ checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.4.1", + "futures-lite 2.6.1", "pin-project-lite", "slab", ] +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "blocking", + "futures-lite 1.13.0", +] + [[package]] name = "async-fs" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" dependencies = [ - "async-lock", + "async-lock 3.4.2", "blocking", - "futures-lite", + "futures-lite 2.6.1", ] [[package]] @@ -234,7 +246,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "parking", "polling", "rustix 1.1.4", @@ -242,13 +254,22 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + [[package]] name = "async-lock" version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -261,7 +282,7 @@ checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" dependencies = [ "async-io", "blocking", - "futures-lite", + "futures-lite 2.6.1", ] [[package]] @@ -272,13 +293,13 @@ checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ "async-channel", "async-io", - "async-lock", + "async-lock 3.4.2", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener", - "futures-lite", + "event-listener 5.4.1", + "futures-lite 2.6.1", "rustix 1.1.4", ] @@ -300,7 +321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" dependencies = [ "async-io", - "async-lock", + "async-lock 3.4.2", "atomic-waker", "cfg-if", "futures-core", @@ -464,7 +485,7 @@ dependencies = [ "async-channel", "async-task", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "piper", ] @@ -510,6 +531,12 @@ dependencies = [ "syn", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "byteorder-lite" version = "0.1.0" @@ -986,6 +1013,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "event-listener" version = "5.4.1" @@ -1003,7 +1036,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener", + "event-listener 5.4.1", "pin-project-lite", ] @@ -1022,6 +1055,15 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.4.1" @@ -1201,13 +1243,28 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-lite" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand", + "fastrand 2.4.1", "futures-core", "futures-io", "parking", @@ -1289,6 +1346,16 @@ dependencies = [ "wasip3", ] +[[package]] +name = "gif" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gif" version = "0.14.2" @@ -1514,7 +1581,7 @@ dependencies = [ "iced_runtime", "iced_widget", "iced_winit", - "image", + "image 0.25.10", "thiserror 2.0.18", ] @@ -1574,7 +1641,7 @@ dependencies = [ "half", "iced_core", "iced_futures", - "image", + "image 0.25.10", "kamadak-exif", "log", "raw-window-handle", @@ -1583,6 +1650,20 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "iced_moving_picture" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a058d0a3f6d4195fea964c68947e87ade42b1c3842f4a836c1fbecf5969a4fd" +dependencies = [ + "async-fs 1.6.0", + "iced_futures", + "iced_runtime", + "iced_widget", + "image 0.24.9", + "thiserror 1.0.69", +] + [[package]] name = "iced_program" version = "0.14.0" @@ -1711,6 +1792,24 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif 0.13.3", + "jpeg-decoder", + "num-traits", + "png 0.17.16", + "qoi", + "tiff 0.9.1", +] + [[package]] name = "image" version = "0.25.10" @@ -1721,16 +1820,16 @@ dependencies = [ "byteorder-lite", "color_quant", "exr", - "gif", + "gif 0.14.2", "image-webp", "moxcms", "num-traits", - "png", + "png 0.18.1", "qoi", "ravif", "rayon", "rgb", - "tiff", + "tiff 0.11.3", "zune-core", "zune-jpeg", ] @@ -1763,6 +1862,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -1882,6 +1990,15 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" +dependencies = [ + "rayon", +] + [[package]] name = "js-sys" version = "0.3.95" @@ -1924,9 +2041,11 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" name = "kira-installer" version = "0.1.0" dependencies = [ + "blocking", "iced", + "iced_moving_picture", "rust-i18n", - "serde", + "smol", "toml 1.1.2+spec-1.1.0", ] @@ -2154,7 +2273,7 @@ dependencies = [ "cfg-if", "dispatch", "futures-channel", - "futures-lite", + "futures-lite 2.6.1", "jni 0.21.1", "ndk-context", "objc2 0.6.4", @@ -2831,7 +2950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", - "fastrand", + "fastrand 2.4.1", "futures-io", ] @@ -2847,6 +2966,19 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "png" version = "0.18.1" @@ -3623,13 +3755,13 @@ checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" dependencies = [ "async-channel", "async-executor", - "async-fs", + "async-fs 2.2.0", "async-io", - "async-lock", + "async-lock 3.4.2", "async-net", "async-process", "blocking", - "futures-lite", + "futures-lite 2.6.1", ] [[package]] @@ -3649,7 +3781,7 @@ checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" dependencies = [ "as-raw-xcb-connection", "bytemuck", - "fastrand", + "fastrand 2.4.1", "js-sys", "memmap2", "ndk", @@ -3742,7 +3874,7 @@ version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "fastrand", + "fastrand 2.4.1", "getrandom 0.4.2", "once_cell", "rustix 1.1.4", @@ -3798,6 +3930,17 @@ dependencies = [ "syn", ] +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "tiff" version = "0.11.3" @@ -4096,6 +4239,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.5.0" @@ -5141,16 +5290,16 @@ dependencies = [ "async-broadcast", "async-executor", "async-io", - "async-lock", + "async-lock 3.4.2", "async-process", "async-recursion", "async-task", "async-trait", "blocking", "enumflags2", - "event-listener", + "event-listener 5.4.1", "futures-core", - "futures-lite", + "futures-lite 2.6.1", "hex", "libc", "ordered-stream", diff --git a/Cargo.toml b/Cargo.toml index 71e252f..fb6062e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,9 +4,11 @@ version = "0.1.0" edition = "2024" [dependencies] +blocking = "1.6.2" iced = { version = "0.14", features = ["smol", "image"] } +iced_moving_picture = "0" rust-i18n = "3" -serde = "1.0.228" +smol = "2.0.2" toml = "1" [profile.release] diff --git a/src/locales/en.json b/src/locales/en.json index e555cf8..6223d8f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -10,6 +10,8 @@ "license.license": "This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with this program. If not, see .", "license.accept_text": "By pressing 'Accept' button you agreening to terms described above.", "license.button.accept": "Accept", + "license.button.decline": "Decline", "network.reuse_checkbox_caption": "Reuse settings?", - "network.reuse_question": "Do you want to apply current network settings to installing system?" + "network.reuse_question": "Do you want to apply current network settings to installing system?", + "network.checking": "Checking network connectivity, please wait..." } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 766d0e0..a347d6f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,64 +1,54 @@ - // - // Copyright (C) <2026> +// +// Copyright (C) <2026> - // This program is free software: you can redistribute it and/or modify - // it under the terms of the GNU General Public License as published by - // the Free Software Foundation, either version 3 of the License, or - // (at your option) any later version. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - // This program is distributed in the hope that it will be useful, - // but WITHOUT ANY WARRANTY; without even the implied warranty of - // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - // GNU General Public License for more details. - - // You should have received a copy of the GNU General Public License - // along with this program. If not, see . +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . /* - This file is the main application file. - Main logic and stuff is located here. Including config loading. - stages loading, switching between stages, and stuff. - */ - - + This file is the main application file. + Main logic and stuff is located here. Including config loading. + stages loading, switching between stages, and stuff. +*/ use iced::widget; -use iced::Alignment; -use std::collections::{HashMap}; -use std::path::{PathBuf,Path}; -use std::str::FromStr; use std::process::ExitCode; use iced::{Element, Task}; -use crate::stage::{StageAction, KiraConfig}; +use crate::stage::{KiraConfig, StageAction}; use crate::stages::license; use crate::stages::network; use crate::stages::welcome; use crate::stages::welcome::WelcomeStage; - rust_i18n::i18n!("src/locales", fallback = "en"); mod stage; mod stages; mod theme; - enum Views { Start, Welcome(welcome::WelcomeStage), License(license::LicenseStage), Network(stages::network::NetworkStage), - } enum Message { Start, - Welcome(welcome::Message), - License(license::Message), - Network(stages::network::Message) + Welcome(welcome::Message), + License(license::Message), + Network(stages::network::Message), } struct KiraState { @@ -84,11 +74,16 @@ fn load_kira_config(config_path: &str) -> Result (Self, Task) { - (Self { - current_view: Views::Start, - toml_config: toml::Table::new(), - config: KiraConfig { config_trail: Vec::new() } - }, Task::done(Message::Start)) + ( + Self { + current_view: Views::Start, + toml_config: toml::Table::new(), + config: KiraConfig { + config_trail: Vec::new(), + }, + }, + Task::done(Message::Start), + ) } } @@ -101,14 +96,12 @@ impl KiraState { // config: KiraConfig { config_trail: Vec::new() } // } // } - + // } - - fn view(k_state: &KiraState) -> Element<'_, Message> { match &k_state.current_view { - Views::Start => Element::new(widget::space()) , + Views::Start => Element::new(widget::space()), Views::Welcome(wellcome_stage) => wellcome_stage.view().map(Message::Welcome), Views::License(license_stage) => license_stage.view().map(Message::License), Views::Network(network_stage) => network_stage.view().map(Message::Network), @@ -117,18 +110,16 @@ fn view(k_state: &KiraState) -> Element<'_, Message> { fn update(k_state: &mut KiraState, message: Message) -> Task { match message { - Message::Start => { - match load_kira_config(CONFIG_PATH_STR) { - Ok(conf) => { - println!("Config loaded!"); - k_state.toml_config = conf; - k_state.current_view = Views::Welcome(WelcomeStage::new()); - Task::none() - }, - Err(ex) => { - println!("Error reading config {}: {}", CONFIG_PATH_STR, ex); - iced::exit() - } + Message::Start => match load_kira_config(CONFIG_PATH_STR) { + Ok(conf) => { + println!("Config loaded!"); + k_state.toml_config = conf; + k_state.current_view = Views::Welcome(WelcomeStage::new()); + Task::none() + } + Err(ex) => { + println!("Error reading config {}: {}", CONFIG_PATH_STR, ex); + iced::exit() } }, Message::Welcome(wlc_msg) => { @@ -136,48 +127,57 @@ fn update(k_state: &mut KiraState, message: Message) -> Task { let action = wlc_view.update(wlc_msg); if let StageAction::Next(welcome_res) = action { k_state.config.config_trail.push(welcome_res); - k_state.current_view = Views::License(license::LicenseStage{}); + k_state.current_view = Views::License(license::LicenseStage {}); } } Task::none() - }, + } Message::License(license_message) => { if let Views::License(license_view) = &mut k_state.current_view { let action = license_view.update(license_message); match action { StageAction::Next(license_res) => { k_state.config.config_trail.push(license_res); - k_state.current_view = Views::Network(network::NetworkStage::new(&k_state.toml_config)); - Task::none() - }, + k_state.current_view = + Views::Network(network::NetworkStage::new(&k_state.toml_config)); + Task::done(Message::Network(network::Message::CheckNetwork)) + } StageAction::Abort(_) => iced::exit(), StageAction::Back => iced::exit(), - StageAction::None => Task::none() + StageAction::None => Task::none(), } - } - else { + } else { Task::none() } - }, + } Message::Network(network_message) => { if let Views::Network(network_view) = &mut k_state.current_view { + let update_result = network_view.update(network_message); + match update_result { + network::UpdateResult::Task(t) => t.map(Message::Network), + network::UpdateResult::StageAction(action) => match action { + StageAction::Next(network_res) => { + k_state.config.config_trail.push(network_res); + iced::exit() + } + StageAction::Back => { + k_state.current_view = Views::License(license::LicenseStage {}); + Task::none() + } + _ => Task::none(), + }, + } + } else { Task::none() } - else { - Task::none() - } - } } } - // pub fn main_interface() -> iced::Result { // iced::run(WellcomeStage::update, WellcomeStage::view) // } pub fn main() -> ExitCode { - - // let app_init = || { // let mut k_state = KiraState::default() // k_state.current_view = Views::Welcome(WelcomeStage::new()); @@ -185,16 +185,13 @@ pub fn main() -> ExitCode { // }; let iced_result = iced::application(KiraState::boot, update, view) - .window(iced::window::Settings { - icon: Some( - iced::window::icon::from_file_data( - include_bytes!("icon.png"), - None, - ) - .expect("icon should be a valid PNG"), - ), - ..Default::default() - }) + .window(iced::window::Settings { + icon: Some( + iced::window::icon::from_file_data(include_bytes!("icon.png"), None) + .expect("icon should be a valid PNG"), + ), + ..Default::default() + }) .centered() .theme(theme::main_theme()) .run(); @@ -203,10 +200,8 @@ pub fn main() -> ExitCode { Ok(()) => ExitCode::SUCCESS, Err(_) => ExitCode::from(42), // Custom error code } - } - // fn main() { // println!("Hello, world!"); // println!("{}", t!("wellcome.text")); diff --git a/src/spiner.apng b/src/spiner.apng new file mode 100644 index 0000000..d028973 Binary files /dev/null and b/src/spiner.apng differ diff --git a/src/stage.rs b/src/stage.rs index ffde012..2ad8e9e 100644 --- a/src/stage.rs +++ b/src/stage.rs @@ -21,7 +21,6 @@ use std::collections::HashMap; - #[derive(Debug, Clone)] pub enum ConfigValue { String(String), diff --git a/src/stages/network/mod.rs b/src/stages/network/mod.rs index d2e790e..33fb65a 100644 --- a/src/stages/network/mod.rs +++ b/src/stages/network/mod.rs @@ -19,24 +19,27 @@ it needed for installation to process. */ -use toml::Table; -use iced::{Alignment, widget}; - +use iced::{Alignment, Task, widget}; +use iced_moving_picture::widget::apng; use rust_i18n::t; +use smol; use std::collections::HashMap; +use toml::Table; use crate::stage; use crate::stage::StageResult; - - #[derive(Debug, Clone)] pub enum State { - Init, Cheking, - ConnOK, - ConnBad, - CheckFailed, + Normal, +} + +#[derive(Debug, Clone)] +pub enum CheckResult { + Connected, + NoConnection, + CheckError, } #[derive(Debug, Clone)] @@ -45,103 +48,173 @@ pub struct NetworkStage { state: State, use_net_settings: bool, reqire_network: bool, + spinner_frames: apng::Frames, } #[derive(Debug, Clone)] pub enum Message { Next, Back, - StateChange(State), - UseSettingsTogle(bool) + UseSettingsTogle(bool), + CheckNetwork, + CheckCompleted(CheckResult), } +#[derive(Debug)] +pub enum UpdateResult { + StageAction(stage::StageAction), + Task(Task), +} +fn check_connection_blocking() -> CheckResult { + use std::process::Command; + + match Command::new("nm-online").arg("-q").status() { + Ok(status) => { + if status.success() { + CheckResult::Connected + } else { + CheckResult::NoConnection + } + } + Err(ex) => { + println!("Exception while trying to chen net connectivity: {}", ex); + CheckResult::CheckError + } + } +} + +async fn check_connected() -> CheckResult { + use blocking; + let chek_result = blocking::unblock(|| check_connection_blocking()).await; + return chek_result; +} impl NetworkStage { pub fn new(toml_config: &Table) -> Self { - let mut reqire_network = false; - if let Some(reqire_network_conf) = toml_config.get("network") - .and_then(|v|v.as_table()) - .and_then(|v| v.get("reqire_network")) - .and_then(|v| v.as_bool()) + if let Some(reqire_network_conf) = toml_config + .get("network") + .and_then(|v| v.as_table()) + .and_then(|v| v.get("reqire_network")) + .and_then(|v| v.as_bool()) { println!("Config value reqire_network read {}", reqire_network_conf); reqire_network = reqire_network_conf; - } - else { + } else { println!("Error parsing network config. Using default values."); } + let spinner_frames = + apng::Frames::from_bytes(include_bytes!("spiner.apng").to_vec()).unwrap(); + Self { internet_active: false, - state: State::Init, + state: State::Cheking, use_net_settings: false, - reqire_network: reqire_network + reqire_network: reqire_network, + spinner_frames: spinner_frames, } } - fn check_connected(&mut self) -> Result { - use std::process::Command; - let status = Command::new("nm-online").arg("-q").status()?; - - if status.success() { - self.internet_active = true; - Ok(true) - } else { - self.internet_active = false; - Ok(false) - } - } fn gen_result(&self) -> StageResult { StageResult { name: "network".into(), - config: Some(HashMap::from([( - "accepted".to_string(), - stage::ConfigValue::Bool(true), - )])), + config: Some(HashMap::from([ + ( + "internet_active".to_string(), + stage::ConfigValue::Bool(self.internet_active), + ), + ( + "use_net_settings".to_string(), + stage::ConfigValue::Bool(self.use_net_settings), + ), + ])), resuts: None, error: None, } } - pub fn update(&mut self, message: Message) -> stage::StageAction { + pub fn update(&mut self, message: Message) -> UpdateResult { match message { - Message::Next => stage::StageAction::Next(self.gen_result()), - Message::Back => stage::StageAction::Back, - Message::StateChange(new_state) => { - self.state = new_state; - stage::StageAction::None - }, - Message::UseSettingsTogle(toggle) => { - self.use_net_settings = toggle; - stage::StageAction::None + Message::CheckNetwork => { + self.state = State::Cheking; + UpdateResult::Task(Task::perform(check_connected(), Message::CheckCompleted)) + } + Message::CheckCompleted(check_status) => { + match check_status { + CheckResult::Connected => { + self.internet_active = true; + self.state = State::Normal; + } + CheckResult::NoConnection => { + self.internet_active = false; + self.state = State::Normal; + } + CheckResult::CheckError => { + self.internet_active = false; + self.state = State::Normal; + } + } + UpdateResult::StageAction(stage::StageAction::None) + } + Message::Next => UpdateResult::StageAction(stage::StageAction::Next(self.gen_result())), + Message::Back => UpdateResult::StageAction(stage::StageAction::Back), + Message::UseSettingsTogle(use_net_settings) => { + self.use_net_settings = use_net_settings; + UpdateResult::StageAction(stage::StageAction::None) } } } pub fn view(&self) -> iced::Element<'_, Message> { - let next_button = - widget::button(widget::text(t!("button.next"))).on_press(Message::Next); - let back_button = widget::button(widget::text(t!("button.back"))).on_press(Message::Back); + let (next_button, back_button) = match self.state { + State::Cheking => ( + widget::button(widget::text(t!("button.next"))), + widget::button(widget::text(t!("button.back"))), + ), + State::Normal => ( + widget::button(widget::text(t!("button.next"))).on_press(Message::Next), + widget::button(widget::text(t!("button.back"))).on_press(Message::Back), + ), + }; + + let mut info_column = match self.state { + State::Cheking => widget::Column::new() + .push( + widget::container(apng(&self.spinner_frames)) + .center_x(iced::Length::Fill) + .center_y(iced::Length::Fill), + ) + .push(widget::text(t!("network.checking"))), + State::Normal => widget::Column::new(), + }; + + info_column = info_column.push(widget::text(t!("network.reuse_question"))); + + info_column = match self.state { + State::Cheking => info_column.push( + widget::checkbox(self.use_net_settings).label(t!("network.reuse_checkbox_caption")), + ), + State::Normal => info_column.push( + widget::checkbox(self.use_net_settings) + .label(t!("network.reuse_checkbox_caption")) + .on_toggle(Message::UseSettingsTogle), + ) + }; + + info_column = info_column + .align_x(Alignment::Center) + .padding(20) + .spacing(5); widget::column![ - widget::container( - widget::column![ - widget::text(t!("network.reuse_question")), - widget::checkbox(self.use_net_settings) - .label(t!("network.reuse_checkbox_caption")) - .on_toggle(Message::UseSettingsTogle) - ] + widget::container(info_column) + .height(iced::Length::Fill) + .width(iced::Length::Fill) .align_x(Alignment::Center) - .padding(20) - .spacing(5) - ) - .height(iced::Length::Fill) - .width(iced::Length::Fill) - .align_x(Alignment::Center) - .align_y(Alignment::Center), + .align_y(Alignment::Center), widget::row![ back_button, widget::space::horizontal(), // Pushes the right button to the far right diff --git a/src/stages/network/spiner.apng b/src/stages/network/spiner.apng new file mode 100644 index 0000000..d028973 Binary files /dev/null and b/src/stages/network/spiner.apng differ