use std::{f32::consts::E, path::PathBuf, sync::Arc, thread, time::Duration}; use crossbeam_channel::Receiver; use egui::{mutex::Mutex}; use log::{debug, info}; use crate::{config::{self, ConfigProvider}, omori_locator}; #[derive(Clone)] pub enum UiState { Loading, KeyRequired(String), PickGame(Result, Vec<(PathBuf, u64)>), Error(String) } #[derive(Clone)] pub struct UiStateHolder { pub state: Arc> } pub enum UiEvent { SetKey(Vec), UsePath(PathBuf), UseSteamPath } pub struct AppThread { ui_state: UiStateHolder, context: egui::Context, ui_event_channel: Receiver, decryption_key: Vec } impl AppThread { fn commit(&self, s: UiState) { let mut state = self.ui_state.state.lock(); *state = s; } fn get_key(&mut self, reason: String) -> anyhow::Result> { self.commit(UiState::KeyRequired(reason)); loop { match self.ui_event_channel.recv()? { UiEvent::SetKey(key) => { self.commit(UiState::Loading); return Ok(key); } _ => {} } } } fn pick_game(&mut self, provider: &mut ConfigProvider) -> anyhow::Result { let steam_location = match omori_locator::get_omori_path() { Ok(l) => Ok(l), Err(e) => Err(String::from(format!("{:#}", e))) }; let location_history = provider.get_game_paths()?; self.commit(UiState::PickGame(steam_location.clone(), location_history.clone())); loop { match self.ui_event_channel.recv()? { UiEvent::UsePath(path) => { provider.set_game_path_used(&path)?; self.commit(UiState::Loading); return Ok(path); }, UiEvent::UseSteamPath => { self.commit(UiState::Loading); return Ok(steam_location.expect("The steam location was not set even if the UI told us to use it. This should never happen")); } _ => {} } } } pub fn create(state_holder: &UiStateHolder, context: &egui::Context, ui_event_channel: &Receiver) -> AppThread { AppThread { ui_state: state_holder.clone(), context: context.clone(), ui_event_channel: ui_event_channel.clone(), decryption_key: Vec::new() } } fn real_main(&mut self) -> anyhow::Result<()> { debug!("I am ALIVE! HAHAHAHA!"); self.commit(UiState::Loading); let mut config_provider = config::ConfigProvider::new()?; self.decryption_key = match config_provider.get_key() { Some(key) => key, None => match omori_locator::get_omori_key() { Ok(key) => key, Err(reason) => self.get_key(format!("{:#}", reason))?, } }; config_provider.set_key(&self.decryption_key)?; let game_path = self.pick_game(&mut config_provider)?; info!("Will use {:?}", game_path); Ok(()) } pub fn main(&mut self) { match self.real_main() { Ok(_) => {}, Err(e) => self.commit(UiState::Error(format!("{:#}", e))), } } }