From bac1c608fec78fd817e1b84171b15fb95f134d46 Mon Sep 17 00:00:00 2001 From: Alex Emmet <111742636+Alex-Emmet@users.noreply.github.com> Date: Wed, 18 Feb 2026 19:11:43 +0100 Subject: [PATCH] [Add] Terms UI, [WIP] Main UI --- logs/log_1771436282.txt | 63 +++++++++++++ logs/log_1771436538.txt | 166 +++++++++++++++++++++++++++++++++ logs/log_1771437605.txt | 11 +++ logs/log_1771438219.txt | 11 +++ logs/log_1771438233.txt | 11 +++ logs/log_1771438242.txt | 16 ++++ src/gui/input_handler.rs | 7 +- src/gui/interaction_result.rs | 5 +- src/gui/mod.rs | 1 + src/gui/screens/main_screen.rs | 41 ++++++++ src/gui/ui.rs | 42 +++++++-- src/main.rs | 28 ++++-- src/terms/consent_state.rs | 160 +++++++++++++------------------ 13 files changed, 450 insertions(+), 112 deletions(-) create mode 100644 logs/log_1771436282.txt create mode 100644 logs/log_1771436538.txt create mode 100644 logs/log_1771437605.txt create mode 100644 logs/log_1771438219.txt create mode 100644 logs/log_1771438233.txt create mode 100644 logs/log_1771438242.txt create mode 100644 src/gui/screens/main_screen.rs diff --git a/logs/log_1771436282.txt b/logs/log_1771436282.txt new file mode 100644 index 0000000..20174df --- /dev/null +++ b/logs/log_1771436282.txt @@ -0,0 +1,63 @@ +1771436282065 IOTA ID: 1771072674214 +1771436282065 User IDS: +1771436282073 Community IDS: +1771436282073 TLS certificate 'certs/cert.pem' not found. +1771436282073 HTTP Server running on 0.0.0.0:1984 +1771436282074 Communities active on ws://192.168.178.51:1984/community/... +1771436282074 OMIKRON_CONNECTING +1771436282318 OMIKRON_CONNECTION_SUCCESS +1771436282318 Launched +1771436302354 error_internal +1771436302374 Connection closed. +1771436303341 OMIKRON_CONNECTING +1771436303520 OMIKRON_CONNECTION_SUCCESS +1771436303521 Launched +1771436323545 error_internal +1771436323567 Connection closed. +1771436324551 OMIKRON_CONNECTING +1771436324737 OMIKRON_CONNECTION_SUCCESS +1771436324737 Launched +1771436344754 error_internal +1771436344797 Connection closed. +1771436345760 OMIKRON_CONNECTING +1771436345918 OMIKRON_CONNECTION_SUCCESS +1771436345918 Launched +1771436365940 error_internal +1771436365965 Connection closed. +1771436366944 OMIKRON_CONNECTING +1771436367109 OMIKRON_CONNECTION_SUCCESS +1771436367110 Launched +1771436387137 error_internal +1771436387158 Connection closed. +1771436388134 OMIKRON_CONNECTING +1771436388297 OMIKRON_CONNECTION_SUCCESS +1771436388297 Launched +1771436408315 error_internal +1771436408358 Connection closed. +1771436409322 OMIKRON_CONNECTING +1771436409495 OMIKRON_CONNECTION_SUCCESS +1771436409495 Launched +1771436429520 error_internal +1771436429580 Connection closed. +1771436430519 OMIKRON_CONNECTING +1771436430704 OMIKRON_CONNECTION_SUCCESS +1771436430704 Launched +1771436450728 error_internal +1771436450789 Connection closed. +1771436451729 OMIKRON_CONNECTING +1771436451884 OMIKRON_CONNECTION_SUCCESS +1771436451884 Launched +1771436471909 error_internal +1771436471981 Connection closed. +1771436472909 OMIKRON_CONNECTING +1771436473084 OMIKRON_CONNECTION_SUCCESS +1771436473084 Launched +1771436493113 error_internal +1771436493159 Connection closed. +1771436494110 OMIKRON_CONNECTING +1771436494331 OMIKRON_CONNECTION_SUCCESS +1771436494331 Launched +1771436514369 error_internal +1771436514430 Connection closed. +1771436515164 Shutdown signal received. +1771436515164 Web Server shutdown complete. diff --git a/logs/log_1771436538.txt b/logs/log_1771436538.txt new file mode 100644 index 0000000..c083923 --- /dev/null +++ b/logs/log_1771436538.txt @@ -0,0 +1,166 @@ +1771436538793 IOTA ID: 1771072674214 +1771436538793 User IDS: +1771436538799 Community IDS: +1771436538800 TLS certificate 'certs/cert.pem' not found. +1771436538800 HTTP Server running on 0.0.0.0:1984 +1771436538800 Communities active on ws://192.168.178.51:1984/community/... +1771436538800 OMIKRON_CONNECTING +1771436538965 OMIKRON_CONNECTION_SUCCESS +1771436538965 Launched +1771436558993 error_internal +1771436559015 Connection closed. +1771436559988 OMIKRON_CONNECTING +1771436560155 OMIKRON_CONNECTION_SUCCESS +1771436560156 Launched +1771436580192 error_internal +1771436580244 Connection closed. +1771436581177 OMIKRON_CONNECTING +1771436581398 OMIKRON_CONNECTION_SUCCESS +1771436581399 Launched +1771436601424 error_internal +1771436601483 Connection closed. +1771436602422 OMIKRON_CONNECTING +1771436602569 OMIKRON_CONNECTION_SUCCESS +1771436602569 Launched +1771436622588 error_internal +1771436622615 Connection closed. +1771436623593 OMIKRON_CONNECTING +1771436623791 OMIKRON_CONNECTION_SUCCESS +1771436623791 Launched +1771436643819 error_internal +1771436643844 Connection closed. +1771436644814 OMIKRON_CONNECTING +1771436645183 OMIKRON_CONNECTION_SUCCESS +1771436645183 Launched +1771436665215 error_internal +1771436665238 Connection closed. +1771436666208 OMIKRON_CONNECTING +1771436666364 OMIKRON_CONNECTION_SUCCESS +1771436666364 Launched +1771436686383 error_internal +1771436686411 Connection closed. +1771436687388 OMIKRON_CONNECTING +1771436687544 OMIKRON_CONNECTION_SUCCESS +1771436687544 Launched +1771436707570 error_internal +1771436707626 Connection closed. +1771436708570 OMIKRON_CONNECTING +1771436708771 OMIKRON_CONNECTION_SUCCESS +1771436708771 Launched +1771436728792 error_internal +1771436728812 Connection closed. +1771436729798 OMIKRON_CONNECTING +1771436729969 OMIKRON_CONNECTION_SUCCESS +1771436729970 Launched +1771436749991 error_internal +1771436750026 Connection closed. +1771436750993 OMIKRON_CONNECTING +1771436751270 OMIKRON_CONNECTION_SUCCESS +1771436751270 Launched +1771436771291 error_internal +1771436771313 Connection closed. +1771436772294 OMIKRON_CONNECTING +1771436772455 OMIKRON_CONNECTION_SUCCESS +1771436772455 Launched +1771436792476 error_internal +1771436792506 Connection closed. +1771436793481 OMIKRON_CONNECTING +1771436793642 OMIKRON_CONNECTION_SUCCESS +1771436793643 Launched +1771436813670 error_internal +1771436813707 Connection closed. +1771436814668 OMIKRON_CONNECTING +1771436814859 OMIKRON_CONNECTION_SUCCESS +1771436814859 Launched +1771436834885 error_internal +1771436834911 Connection closed. +1771436835882 OMIKRON_CONNECTING +1771436836100 OMIKRON_CONNECTION_SUCCESS +1771436836100 Launched +1771436856123 error_internal +1771436856157 Connection closed. +1771436857125 OMIKRON_CONNECTING +1771436857279 OMIKRON_CONNECTION_SUCCESS +1771436857279 Launched +1771436877297 error_internal +1771436877330 Connection closed. +1771436878301 OMIKRON_CONNECTING +1771436878459 OMIKRON_CONNECTION_SUCCESS +1771436878459 Launched +1771436898482 error_internal +1771436898510 Connection closed. +1771436899487 OMIKRON_CONNECTING +1771436899669 OMIKRON_CONNECTION_SUCCESS +1771436899670 Launched +1771436919688 error_internal +1771436919716 Connection closed. +1771436920695 OMIKRON_CONNECTING +1771436920924 OMIKRON_CONNECTION_SUCCESS +1771436920924 Launched +1771436940946 error_internal +1771436940976 Connection closed. +1771436941950 OMIKRON_CONNECTING +1771436942115 OMIKRON_CONNECTION_SUCCESS +1771436942115 Launched +1771436962136 error_internal +1771436962218 Connection closed. +1771436963138 OMIKRON_CONNECTING +1771436963295 OMIKRON_CONNECTION_SUCCESS +1771436963295 Launched +1771436983318 error_internal +1771436983351 Connection closed. +1771436984321 OMIKRON_CONNECTING +1771436984488 OMIKRON_CONNECTION_SUCCESS +1771436984488 Launched +1771437004506 error_internal +1771437004546 Connection closed. +1771437005514 OMIKRON_CONNECTING +1771437005674 OMIKRON_CONNECTION_SUCCESS +1771437005674 Launched +1771437025693 error_internal +1771437025714 Connection closed. +1771437026696 OMIKRON_CONNECTING +1771437026985 OMIKRON_CONNECTION_SUCCESS +1771437026985 Launched +1771437047052 error_internal +1771437047072 Connection closed. +1771437048010 OMIKRON_CONNECTING +1771437048193 OMIKRON_CONNECTION_SUCCESS +1771437048193 Launched +1771437068214 error_internal +1771437068248 Connection closed. +1771437069215 OMIKRON_CONNECTING +1771437069393 OMIKRON_CONNECTION_SUCCESS +1771437069393 Launched +1771437089412 error_internal +1771437089436 Connection closed. +1771437090417 OMIKRON_CONNECTING +1771437090587 OMIKRON_CONNECTION_SUCCESS +1771437090588 Launched +1771437110609 error_internal +1771437110646 Connection closed. +1771437111610 OMIKRON_CONNECTING +1771437111764 OMIKRON_CONNECTION_SUCCESS +1771437111765 Launched +1771437131785 error_internal +1771437131847 Connection closed. +1771437132791 OMIKRON_CONNECTING +1771437132976 OMIKRON_CONNECTION_SUCCESS +1771437132977 Launched +1771437152997 error_internal +1771437153061 Connection closed. +1771437154000 OMIKRON_CONNECTING +1771437154171 OMIKRON_CONNECTION_SUCCESS +1771437154172 Launched +1771437174193 error_internal +1771437174213 Connection closed. +1771437175196 OMIKRON_CONNECTING +1771437175344 OMIKRON_CONNECTION_SUCCESS +1771437175345 Launched +1771437195364 error_internal +1771437195401 Connection closed. +1771437196369 OMIKRON_CONNECTING +1771437196525 OMIKRON_CONNECTION_SUCCESS +1771437196525 Launched +1771437202079 Shutdown signal received. +1771437202079 Web Server shutdown complete. diff --git a/logs/log_1771437605.txt b/logs/log_1771437605.txt new file mode 100644 index 0000000..5ffeff1 --- /dev/null +++ b/logs/log_1771437605.txt @@ -0,0 +1,11 @@ +1771437605589 IOTA ID: 1771072674214 +1771437605589 User IDS: +1771437605596 Community IDS: +1771437605596 TLS certificate 'certs/cert.pem' not found. +1771437605596 HTTP Server running on 0.0.0.0:1984 +1771437605597 Communities active on ws://192.168.178.51:1984/community/... +1771437605597 OMIKRON_CONNECTING +1771437605895 OMIKRON_CONNECTION_SUCCESS +1771437605895 Launched +1771437616609 Shutdown signal received. +1771437616609 Web Server shutdown complete. diff --git a/logs/log_1771438219.txt b/logs/log_1771438219.txt new file mode 100644 index 0000000..263f06f --- /dev/null +++ b/logs/log_1771438219.txt @@ -0,0 +1,11 @@ +1771438219620 IOTA ID: 1771072674214 +1771438219620 User IDS: +1771438219626 Community IDS: +1771438219626 TLS certificate 'certs/cert.pem' not found. +1771438219626 HTTP Server running on 0.0.0.0:1984 +1771438219627 Communities active on ws://192.168.178.51:1984/community/... +1771438219627 OMIKRON_CONNECTING +1771438219823 OMIKRON_CONNECTION_SUCCESS +1771438219823 Launched +1771438222468 Shutdown signal received. +1771438222468 Web Server shutdown complete. diff --git a/logs/log_1771438233.txt b/logs/log_1771438233.txt new file mode 100644 index 0000000..19e1c53 --- /dev/null +++ b/logs/log_1771438233.txt @@ -0,0 +1,11 @@ +1771438233418 IOTA ID: 1771072674214 +1771438233418 User IDS: +1771438233424 Community IDS: +1771438233425 TLS certificate 'certs/cert.pem' not found. +1771438233425 HTTP Server running on 0.0.0.0:1984 +1771438233425 Communities active on ws://192.168.178.51:1984/community/... +1771438233425 OMIKRON_CONNECTING +1771438233604 OMIKRON_CONNECTION_SUCCESS +1771438233604 Launched +1771438236430 Shutdown signal received. +1771438236431 Web Server shutdown complete. diff --git a/logs/log_1771438242.txt b/logs/log_1771438242.txt new file mode 100644 index 0000000..7a483f6 --- /dev/null +++ b/logs/log_1771438242.txt @@ -0,0 +1,16 @@ +1771438242873 IOTA ID: 1771072674214 +1771438242873 User IDS: +1771438242879 Community IDS: +1771438242879 TLS certificate 'certs/cert.pem' not found. +1771438242879 HTTP Server running on 0.0.0.0:1984 +1771438242880 Communities active on ws://192.168.178.51:1984/community/... +1771438242880 OMIKRON_CONNECTING +1771438243059 OMIKRON_CONNECTION_SUCCESS +1771438243059 Launched +1771438263092 error_internal +1771438263152 Connection closed. +1771438264100 OMIKRON_CONNECTING +1771438264278 OMIKRON_CONNECTION_SUCCESS +1771438264278 Launched +1771438284301 error_internal +1771438284320 Connection closed. diff --git a/src/gui/input_handler.rs b/src/gui/input_handler.rs index 901ab56..5205dda 100644 --- a/src/gui/input_handler.rs +++ b/src/gui/input_handler.rs @@ -1,5 +1,5 @@ use crate::ACTIVE_TASKS; -use crate::gui::ui::UI; +use crate::gui::ui::{UI, UNIQUE}; use crate::{RELOAD, SHUTDOWN}; use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, poll, read}; use std::sync::Arc; @@ -31,8 +31,9 @@ pub fn setup_input_handler(ui: Arc) { Ok(event) => { if let Event::Key(key_event) = event { if key_event.kind == KeyEventKind::Press { - let ui_clone = ui.clone(); - handle_input(key_event, ui_clone).await; + let uic = ui.clone(); + handle_input(key_event, uic).await; + *UNIQUE.write().await = true; } } } diff --git a/src/gui/interaction_result.rs b/src/gui/interaction_result.rs index 1ec2d23..b6fa626 100644 --- a/src/gui/interaction_result.rs +++ b/src/gui/interaction_result.rs @@ -1,9 +1,10 @@ -use std::fmt::Debug; +use std::fmt::{Debug, Formatter}; use std::future::Future; use std::pin::Pin; use crate::gui::screens::screens::Screen; +#[allow(unused)] pub enum InteractionResult { CloseScreen, OpenScreen { @@ -17,7 +18,7 @@ pub enum InteractionResult { } impl Debug for InteractionResult { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { InteractionResult::OpenScreen { screen: _ } => write!(f, "OpenScreen"), InteractionResult::OpenFutureScreen { screen: _ } => write!(f, "OpenFutureScreen"), diff --git a/src/gui/mod.rs b/src/gui/mod.rs index fc4bc6b..0593313 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -3,6 +3,7 @@ pub mod elements { pub mod log_card; } pub mod screens { + pub mod main_screen; pub mod screens; pub mod terms_checker; pub mod terms_updater; diff --git a/src/gui/screens/main_screen.rs b/src/gui/screens/main_screen.rs new file mode 100644 index 0000000..e739190 --- /dev/null +++ b/src/gui/screens/main_screen.rs @@ -0,0 +1,41 @@ +use std::{any::Any, sync::Arc}; + +use crossterm::event::KeyEvent; +use ratatui::{ + Frame, + layout::Rect, + widgets::{Block, Borders}, +}; + +use crate::gui::{interaction_result::InteractionResult, screens::screens::Screen, ui::UI}; + +pub struct MainScreen { + ui: Arc, +} + +impl MainScreen { + pub async fn new(ui: Arc) -> Self { + MainScreen { ui } + } +} +impl Screen for MainScreen { + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn get_ui(&self) -> &Arc { + &self.ui + } + + fn render(&self, f: &mut Frame, rect: Rect) { + f.render_widget(Block::default().title("Main").borders(Borders::ALL), rect); + } + + fn handle_input(&mut self, event: KeyEvent) -> InteractionResult { + InteractionResult::Unhandled + } +} diff --git a/src/gui/ui.rs b/src/gui/ui.rs index bccde68..89ecb74 100644 --- a/src/gui/ui.rs +++ b/src/gui/ui.rs @@ -1,15 +1,47 @@ -use crate::gui::{interaction_result::InteractionResult, screens::screens::Screen}; +use crate::{ + SHUTDOWN, + gui::{ + input_handler::setup_input_handler, interaction_result::InteractionResult, + screens::screens::Screen, + }, +}; use crossterm::event::KeyEvent; +use once_cell::sync::Lazy; use ratatui::{Terminal, backend::CrosstermBackend, init}; -use std::sync::{Arc, Mutex}; +use std::{ + io::Stdout, + sync::{Arc, Mutex}, + time::Duration, +}; use tokio::sync::RwLock; /// UI state and rendering +pub static UNIQUE: Lazy> = Lazy::new(|| RwLock::new(true)); pub struct UI { - pub terminal: Arc>>>, + pub terminal: Arc>>>, screen: Arc>>>, } +pub fn start_tui() -> Arc { + let ui = Arc::new(UI::new()); + let uic = ui.clone(); + tokio::spawn(async move { + loop { + if *SHUTDOWN.read().await { + break; + } + + if *UNIQUE.read().await { + uic.render().await; + } else { + tokio::time::sleep(Duration::from_millis(50)).await; + } + } + ratatui::restore(); + }); + setup_input_handler(ui.clone()); + ui +} impl UI { pub fn new() -> Self { let terminal = init(); @@ -42,9 +74,7 @@ impl UI { ui.set_screen(screen).await; } InteractionResult::CloseScreen => { - /* TODO - self.set_screen(); - */ + *self.screen.write().await = None; } InteractionResult::Handled => {} InteractionResult::Unhandled => {} diff --git a/src/main.rs b/src/main.rs index 102880f..9df4b24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,8 +20,8 @@ mod util; use crate::communities::community_manager; use crate::communities::interactables::registry; use crate::gui::app_state::AppState; -use crate::gui::input_handler::setup_input_handler; -use crate::gui::ui::UI; +use crate::gui::screens::main_screen::MainScreen; +use crate::gui::ui::start_tui; use crate::langu::language_creator; use crate::omikron::omikron_connection::{OMIKRON_CONNECTION, OmikronConnection}; use crate::server::server::start; @@ -46,8 +46,7 @@ async fn main() { *RELOAD.write().await = false; *SHUTDOWN.write().await = false; - let ui = Arc::new(UI::new()); - setup_input_handler(ui.clone()); + let ui = start_tui(); let ui_clone = ui.clone(); tokio::spawn(async move { @@ -60,15 +59,25 @@ async fn main() { let (eula, tos_pp) = ConsentManager::check(ui.clone()).await; if !eula { - ui.terminal.lock().unwrap().clear(); - ui.terminal.lock().unwrap().flush(); + *SHUTDOWN.write().await = true; + loop { + if ACTIVE_TASKS.lock().unwrap().is_empty() { + break; + } + sleep(Duration::from_secs(1)).await; + } println!("You need to accept our End User Licence Agreement before launching!"); println!("You can find this at 'agreements'!"); return; } if !tos_pp { - ui.terminal.lock().unwrap().clear(); - ui.terminal.lock().unwrap().flush(); + *SHUTDOWN.write().await = true; + loop { + if ACTIVE_TASKS.lock().unwrap().is_empty() { + break; + } + sleep(Duration::from_secs(1)).await; + } println!( "Please accept our Privacy Policy & Terms of Serivce before using Tensamin Services!" ); @@ -77,6 +86,9 @@ async fn main() { return; } + let main_screen = MainScreen::new(ui.clone()).await; + ui.set_screen(Box::new(main_screen)).await; + // LANGUAGE PACK if let Err(e) = language_creator::create_languages() { println!("Language pack creation failed: {}", e); diff --git a/src/terms/consent_state.rs b/src/terms/consent_state.rs index 8464df6..def25a3 100644 --- a/src/terms/consent_state.rs +++ b/src/terms/consent_state.rs @@ -17,125 +17,99 @@ use std::time::{SystemTime, UNIX_EPOCH}; pub struct ConsentManager; impl ConsentManager { pub async fn check(ui: Arc) -> (bool, bool) { - let (tx, rx) = oneshot::channel(); - let file = load_file("", "agreements"); - let mut file_state = ConsentState::from_str(&file).sanitize(); - ui.set_screen(Box::new(TermsCheckerScreen::new(ui.clone(), Some(tx)))) - .await; + let mut state = ConsentState::from_str(&file).sanitize(); - let result = rx.await.unwrap_or(UserChoice::Deny); + if !state.accepted_eula { + let (tx, rx) = oneshot::channel(); - match result { - UserChoice::AcceptEULA | UserChoice::AcceptAll => { - if let Some((current_eula, current_tos, current_privacy)) = get_current_docs().await - { - file_state.accepted_eula = true; - file_state.eula = Some(current_eula); + ui.set_screen(Box::new(TermsCheckerScreen::new(ui.clone(), Some(tx)))) + .await; - if matches!(result, UserChoice::AcceptAll) { - file_state.accepted_tos = true; - file_state.accepted_pp = true; - file_state.tos = Some(current_tos); - file_state.privacy = Some(current_privacy); + let result = rx.await.unwrap_or(UserChoice::Deny); + + match result { + UserChoice::AcceptEULA | UserChoice::AcceptAll => { + if let Some((current_eula, current_tos, current_privacy)) = + get_current_docs().await + { + state.accepted_eula = true; + state.eula = Some(current_eula); + + if matches!(result, UserChoice::AcceptAll) { + state.accepted_tos = true; + state.accepted_pp = true; + state.tos = Some(current_tos); + state.privacy = Some(current_privacy); + } } } + UserChoice::Deny => return (false, false), } - UserChoice::Deny => { - return (false, false); - } + + save_file("", "agreements", &state.to_string()); } - save_file("", "agreements", &file_state.to_string()); - if let Some((eula_update, tos_update, privacy_update)) = Self::get_updates().await { - let _is_forced = matches!(eula_update, UpdateDecision::Forced(_)) + let is_forced = matches!(eula_update, UpdateDecision::Forced(_)) || matches!(tos_update, UpdateDecision::Forced(_)) || matches!(privacy_update, UpdateDecision::Forced(_)); - if let Some((eula_update, tos_update, privacy_update)) = Self::get_updates().await { - let is_forced = matches!(eula_update, UpdateDecision::Forced(_)) - || matches!(tos_update, UpdateDecision::Forced(_)) - || matches!(privacy_update, UpdateDecision::Forced(_)); + let (tx, rx) = oneshot::channel(); - let (tx, rx) = oneshot::channel(); + ui.set_screen(Box::new(TermsUpdaterScreen::new( + ui.clone(), + eula_update.clone(), + tos_update.clone(), + privacy_update.clone(), + Some(tx), + ))) + .await; - ui.set_screen(Box::new(TermsUpdaterScreen::new( - ui.clone(), - eula_update.clone(), - tos_update.clone(), - privacy_update.clone(), - Some(tx), - ))) - .await; + let result = rx.await.unwrap_or(UserChoice::Deny); - if is_forced { - let result = rx.await.unwrap_or(UserChoice::Deny); - - let file = load_file("", "agreements"); - let mut state = ConsentState::from_str(&file).sanitize(); - - match result { - UserChoice::AcceptAll => { - state.accepted_eula = true; - state.accepted_tos = true; - state.accepted_pp = true; + if is_forced { + match result { + UserChoice::AcceptAll => { + state.accepted_eula = true; + state.accepted_tos = true; + state.accepted_pp = true; + } + UserChoice::AcceptEULA => { + state.accepted_eula = true; + } + UserChoice::Deny => return (false, false), + } + } else { + match result { + UserChoice::AcceptAll => { + if let UpdateDecision::Future { newest } = eula_update { + state.future_eula = Some(newest); } - UserChoice::AcceptEULA => { - state.accepted_eula = true; + if let UpdateDecision::Future { newest } = tos_update { + state.future_tos = Some(newest); } - UserChoice::Deny => { - return (false, false); + if let UpdateDecision::Future { newest } = privacy_update { + state.future_privacy = Some(newest); } } - - let state = state.sanitize(); - save_file("", "agreements", &state.to_string()); - } else { - tokio::spawn(async move { - let result = rx.await.unwrap_or(UserChoice::Deny); - - let file = load_file("", "agreements"); - let mut state = ConsentState::from_str(&file).sanitize(); - - match result { - UserChoice::AcceptAll => { - state.future_eula = match eula_update { - UpdateDecision::Future { newest } => Some(newest), - _ => state.future_eula, - }; - state.future_tos = match tos_update { - UpdateDecision::Future { newest } => Some(newest), - _ => state.future_tos, - }; - state.future_privacy = match privacy_update { - UpdateDecision::Future { newest } => Some(newest), - _ => state.future_privacy, - }; - } - UserChoice::AcceptEULA => { - if let UpdateDecision::Future { newest } = eula_update { - state.future_eula = Some(newest); - } - } - UserChoice::Deny => {} + UserChoice::AcceptEULA => { + if let UpdateDecision::Future { newest } = eula_update { + state.future_eula = Some(newest); } - - let state = state.sanitize(); - save_file("", "agreements", &state.to_string()); - }); + } + UserChoice::Deny => {} } } + + state = state.sanitize(); + save_file("", "agreements", &state.to_string()); } - let file = load_file("", "agreements"); - let final_state = ConsentState::from_str(&file).sanitize(); + state = ConsentState::from_str(&load_file("", "agreements")).sanitize(); + save_file("", "agreements", &state.to_string()); - save_file("", "agreements", &final_state.to_string()); - ( - final_state.accepted_eula, - final_state.accepted_tos && final_state.accepted_pp, - ) + (state.accepted_eula, state.accepted_tos && state.accepted_pp) } async fn get_updates() -> Option<(