[improve] set game dir on client -> updates Play/Install button based on games existing

This commit is contained in:
2024-11-14 19:41:55 +01:00
parent c00b7dbe9c
commit 942eb8003e
12 changed files with 873 additions and 53 deletions

View File

@ -1,8 +1,13 @@
use std::net::SocketAddr;
use std::{
net::SocketAddr,
path::{Path, PathBuf},
sync::Arc,
};
use lanspread_client::{ClientCommand, ClientEvent};
use lanspread_db::db::{Game, GameDB};
use lanspread_mdns::{discover_service, LANSPREAD_INSTANCE_NAME, LANSPREAD_SERVICE_TYPE};
use tauri::{AppHandle, Emitter as _, Listener as _, Manager};
use tauri::{AppHandle, Emitter as _, Manager};
use tokio::sync::{mpsc::UnboundedSender, Mutex};
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
@ -10,6 +15,7 @@ use tokio::sync::{mpsc::UnboundedSender, Mutex};
struct LanSpreadState {
server_addr: Mutex<Option<SocketAddr>>,
client_ctrl: UnboundedSender<ClientCommand>,
games: Arc<Mutex<GameDB>>,
}
#[tauri::command]
@ -40,6 +46,67 @@ fn run_game_backend(id: String, state: tauri::State<LanSpreadState>) -> String {
// }
}
fn set_game_install_state_from_path(game_db: &mut GameDB, path: &Path, installed: bool) {
if let Some(file_name) = path.file_name() {
if let Some(file_name) = file_name.to_str() {
if let Some(game) = game_db.get_mut_game_by_id(file_name) {
if installed {
log::error!("Game is installed: {game}");
} else {
log::error!("Game is missing: {game}");
}
game.installed = installed;
}
}
}
}
#[tauri::command]
fn update_game_directory(app_handle: tauri::AppHandle, path: String) {
let path = PathBuf::from(path);
if !path.exists() {
log::error!("game dir {path:?} does not exist");
}
let entries = match path.read_dir() {
Ok(entries) => entries,
Err(e) => {
log::error!("Failed to read game dir: {e}");
return;
}
};
tauri::async_runtime::spawn(async move {
let mut game_db = app_handle
.state::<LanSpreadState>()
.inner()
.games
.lock()
.await;
// Reset all games to uninstalled
game_db.set_all_uninstalled();
// update game_db with installed games from real game directory
entries.into_iter().for_each(|entry| {
if let Ok(entry) = entry {
if let Ok(path_type) = entry.file_type() {
if path_type.is_dir() {
let path = entry.path();
if path.join(".softlan_game_installed").exists() {
set_game_install_state_from_path(&mut game_db, &path, true);
}
}
}
}
});
if let Err(e) = app_handle.emit("games-list-updated", Some(game_db.all_games())) {
log::error!("Failed to emit games-list-updated event: {e}");
}
});
}
async fn find_server(app: AppHandle) {
log::info!("Looking for server...");
@ -57,6 +124,7 @@ async fn find_server(app: AppHandle) {
.client_ctrl
.send(ClientCommand::ServerAddr(server_addr))
.unwrap();
request_games(state);
break;
}
Err(e) => {
@ -66,6 +134,25 @@ async fn find_server(app: AppHandle) {
}
}
async fn update_game_db(games: Vec<Game>, app: AppHandle) {
for game in &games {
log::trace!("client event ListGames iter: {game:?}");
}
let state = app.state::<LanSpreadState>();
// Store games list
let mut state_games = state.games.lock().await;
*state_games = GameDB::from(games.clone());
// Tell Frontend about new games list
if let Err(e) = app.emit("games-list-updated", Some(games)) {
log::error!("Failed to emit games-list-updated event: {e}");
} else {
log::info!("Emitted games-list-updated event");
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let tauri_logger_builder = tauri_plugin_log::Builder::new()
@ -89,12 +176,19 @@ pub fn run() {
let lanspread_state = LanSpreadState {
server_addr: Mutex::new(None),
client_ctrl: tx_client_control,
games: Arc::new(Mutex::new(GameDB::empty())),
};
tauri::Builder::default()
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_logger_builder.build())
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![run_game_backend, request_games])
.invoke_handler(tauri::generate_handler![
run_game_backend,
request_games,
update_game_directory
])
.manage(lanspread_state)
.setup(|app| {
let app_handle = app.handle().clone();
@ -110,16 +204,7 @@ pub fn run() {
match event {
ClientEvent::ListGames(games) => {
log::debug!("Received client event: ListGames");
for game in &games {
log::trace!("client event ListGames iter: {game:?}");
}
if let Err(e) = app_handle.emit("games-list-updated", Some(games)) {
log::error!("Failed to emit games-list-updated event: {e}");
} else {
log::info!("Emitted games-list-updated event");
}
update_game_db(games, app_handle.clone()).await;
}
}
}