game picker

This commit is contained in:
Rph :3
2025-04-17 00:39:10 +02:00
parent 89f08ff580
commit 165a9fc139
5 changed files with 243 additions and 14 deletions

View File

@@ -2,7 +2,7 @@ use std::{f32::consts::E, path::PathBuf, sync::Arc, thread, time::Duration};
use crossbeam_channel::Receiver;
use egui::{mutex::Mutex};
use log::debug;
use log::{debug, info};
use crate::{config::{self, ConfigProvider}, omori_locator};
@@ -10,7 +10,7 @@ use crate::{config::{self, ConfigProvider}, omori_locator};
pub enum UiState {
Loading,
KeyRequired(String),
PickGame(Result<PathBuf, String>, Vec<PathBuf>),
PickGame(Result<PathBuf, String>, Vec<(PathBuf, u64)>),
Error(String)
}
@@ -20,7 +20,9 @@ pub struct UiStateHolder {
}
pub enum UiEvent {
SetKey(Vec<u8>)
SetKey(Vec<u8>),
UsePath(PathBuf),
UseSteamPath
}
pub struct AppThread {
@@ -49,7 +51,7 @@ impl AppThread {
}
}
fn pick_game(&mut self, provider: &ConfigProvider) -> anyhow::Result<()> {
fn pick_game(&mut self, provider: &mut ConfigProvider) -> anyhow::Result<PathBuf> {
let steam_location = match omori_locator::get_omori_path() {
Ok(l) => Ok(l),
Err(e) => Err(String::from(format!("{:#}", e)))
@@ -59,7 +61,20 @@ impl AppThread {
self.commit(UiState::PickGame(steam_location.clone(), location_history.clone()));
Ok(())
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<UiEvent>) -> AppThread {
@@ -87,7 +102,8 @@ impl AppThread {
config_provider.set_key(&self.decryption_key)?;
self.pick_game(&config_provider);
let game_path = self.pick_game(&mut config_provider)?;
info!("Will use {:?}", game_path);
Ok(())
}

View File

@@ -66,11 +66,11 @@ impl ConfigProvider {
Ok(())
}
pub fn get_game_paths(&self) -> anyhow::Result<Vec<PathBuf>> {
pub fn get_game_paths(&self) -> anyhow::Result<Vec<(PathBuf, u64)>> {
let mut paths: Vec<(&PathBuf, &u64)> = self.config.recently_used_game_paths.iter().collect();
paths.sort_by(|a, b| a.1.cmp(b.1));
paths.sort_by(|a, b| a.1.cmp(b.1).reverse());
Ok(paths.iter().map(|v| v.0.clone()).collect())
Ok(paths.iter().map(|v| (v.0.clone(), *v.1)).collect())
}
pub fn set_game_path_used(&mut self, which: &PathBuf) -> anyhow::Result<()> {

View File

@@ -2,13 +2,14 @@ mod omori_locator;
mod app_logic;
mod config;
use std::{sync::Arc, thread, time::Duration};
use std::{sync::Arc, thread, time::{Duration, SystemTime}};
use app_logic::{AppThread, UiEvent, UiState, UiStateHolder};
use crossbeam_channel::{Receiver, Sender};
use eframe::egui;
use egui::{mutex::{Mutex, RwLock}, Align, Layout, RichText, ThemePreference};
use egui_alignments::{center_horizontal, center_vertical, top_horizontal, Aligner};
use egui_extras::{Column, TableBuilder};
use egui_modal::Modal;
use sha2::Digest;
@@ -39,6 +40,9 @@ fn main() -> anyhow::Result<()> {
eframe::run_native("TundleBool", options, Box::new(|cc| {
cc.egui_ctx.set_theme(ThemePreference::System);
cc.egui_ctx.style_mut(|style| {
style.interaction.selectable_labels = false;
});
let mut app_thread = AppThread::create(&app_state, &cc.egui_ctx, &receiver);
@@ -164,7 +168,9 @@ impl eframe::App for Application {
Ok(path) => {
ui.label(RichText::new(format!("Found game at:\n{}", path.display())).italics());
ui.separator();
ui.button(RichText::new("Use Steam version").size(16.0));
if ui.button(RichText::new("Use Steam version").size(16.0)).clicked() {
self.sender.send(UiEvent::UseSteamPath).expect("Failed to send");
}
},
Err(e) => {
ui.label(RichText::new(format!("Failed to find game:\n{}", e)).color(ui.visuals().error_fg_color));
@@ -175,11 +181,44 @@ impl eframe::App for Application {
columns[1].vertical(|ui| {
ui.label(RichText::new("Custom").size(24.0));
if ui.button(RichText::new("Pick game location").size(16.0)).clicked() {
rfd::FileDialog::new().pick_folder();
invalid_path_modal.open();
match rfd::FileDialog::new().pick_folder() {
Some(path) => {
if omori_locator::validate_omori_installation(&path) {
self.sender.send(UiEvent::UsePath(path)).expect("Failed to send");
} else {
invalid_path_modal.open();
}
},
None => {}
}
}
ui.separator();
if others.len() > 0 {
ui.label("History of game locations");
TableBuilder::new(ui)
.striped(true)
.column(Column::remainder())
.column(Column::auto())
.body(|body| {
body.rows(20.0, others.len(), |mut row| {
let item = &others[row.index()];
let dt =
(item.1 as i64) -
(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).expect("Failed to get the time").as_secs() as i64);
let dt = chrono::Duration::from(chrono::TimeDelta::seconds(dt as i64));
row.col(|ui| {
ui.label(format!("{}", item.0.display()));
});
row.col(|ui| {
ui.label(format!("{}", chrono_humanize::HumanTime::from(dt)));
});
});
});
} else {
ui.label("Once you use a custom location, it will be remembered here.");