// // 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 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. */ use iced::widget; use std::process::ExitCode; use iced::{Element, Task}; 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 kira_theming; mod stage; mod stages; enum Views { Start, Welcome(welcome::WelcomeStage), License(license::LicenseStage), Network(stages::network::NetworkStage), TimeZone(stages::timezone::TimeZoneStage), Locale(stages::locale::LocaleStage), } enum Message { Start, Welcome(welcome::Message), License(license::Message), Network(stages::network::Message), TimeZone(stages::timezone::Message), Locale(stages::locale::Message), } struct KiraState { current_view: Views, toml_config: toml::Table, config: KiraConfig, } const CONFIG_PATH_STR: &str = "kira_config.toml"; fn load_kira_config(config_path: &str) -> Result> { use std::fs; use toml::Table; // 1. Read the file content into a String let content = fs::read_to_string(config_path)?; // 2. Parse the string into a Table let table: Table = content.parse()?; println!("{:?}", table); Ok(table) } impl KiraState { fn boot() -> (Self, Task) { ( Self { current_view: Views::Start, toml_config: toml::Table::new(), config: KiraConfig { config_trail: Vec::new(), }, }, Task::done(Message::Start), ) } } // impl KiraState { // fn new(toml_config: toml::Table) -> Self { // Self { // current_view: Views::Start, // toml_config: toml_config, // 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::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), Views::TimeZone(timezone_stage) => timezone_stage.view().map(Message::TimeZone), Views::Locale(locale_stage) => locale_stage.view().map(Message::Locale), } } 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::Welcome(wlc_msg) => { if let Views::Welcome(wlc_view) = &mut k_state.current_view { match wlc_view.update(wlc_msg) { StageAction::Next(welcome_res) => { k_state.config.config_trail.push(welcome_res); k_state.current_view = Views::License(license::LicenseStage {}); Task::none() } StageAction::Abort => iced::exit(), _ => Task::none(), } } else { 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::done(Message::Network(network::Message::CheckNetwork)) } StageAction::Abort => iced::exit(), StageAction::Back => { k_state.current_view = Views::Welcome(WelcomeStage::new()); k_state.config.config_trail.pop(); Task::none() } StageAction::None => Task::none(), } } 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); k_state.current_view = Views::TimeZone(stages::timezone::TimeZoneStage::new()); Task::none() } StageAction::Back => { k_state.current_view = Views::License(license::LicenseStage {}); k_state.config.config_trail.pop(); Task::none() } _ => Task::none(), }, } } else { Task::none() } }, Message::TimeZone(timezone_message) => { if let Views::TimeZone(timezone_view) = &mut k_state.current_view { let action = timezone_view.update(timezone_message); match action { StageAction::Next(tz_res) => { k_state.config.config_trail.push(tz_res); k_state.current_view = Views::Locale(stages::locale::LocaleStage::new(&k_state.config)); Task::none() } StageAction::Abort => iced::exit(), StageAction::Back => { k_state.config.config_trail.pop(); k_state.current_view = Views::Network(network::NetworkStage::new(&k_state.toml_config)); Task::done(Message::Network(network::Message::CheckNetwork)) } StageAction::None => Task::none(), } } else { Task::none() } }, Message::Locale(locale_msg) => { if let Views::Locale(locale_view) = &mut k_state.current_view { match locale_view.update(locale_msg) { StageAction::Next(locale_res) => { k_state.config.config_trail.push(locale_res); iced::exit() } StageAction::Back => { k_state.config.config_trail.pop(); k_state.current_view = Views::TimeZone(stages::timezone::TimeZoneStage::new()); Task::none() } _ => 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()); // k_stateapp_init // }; let iced_result = iced::application(KiraState::boot, update, view) .window(iced::window::Settings { icon: Some( iced::window::icon::from_file_data(include_bytes!("media/icon.png"), None) .expect("icon should be a valid PNG"), ), ..Default::default() }) .centered() .theme(kira_theming::main_theme()) .default_font(iced::Font::MONOSPACE) .run(); match iced_result { Ok(()) => ExitCode::SUCCESS, Err(ex) => { println!("ICED Error: {}", ex); ExitCode::from(42) }, // Custom error code } } // fn main() { // println!("Hello, world!"); // println!("{}", t!("wellcome.text")); // // Initialize the state // let _res = main_interface(); // }