Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.1.25 #72

Merged
merged 10 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rai-pal"
version = "0.1.24"
version = "0.1.25"
authors = ["Raicuparta"]
license = "GPL-3.0-or-later"
repository = "https://github.com/Raicuparta/rai-pal"
Expand All @@ -24,7 +24,7 @@ specta = "1.0.5"
tauri-specta = { version = "1.0.2", features = ["typescript"] }
serde = { version = "1.0", features = ["derive"] }
byteorder = "1.5.0"
tauri = { version = "1.5.2", features = [ "dialog-open", "updater", "shell-open", "dialog"] }
tauri = { version = "1.5.2", features = [ "dialog-confirm", "dialog-open", "updater", "shell-open", "dialog"] }
reqwest = "0.11.22"
goblin = "0.7.1"
open = "5.0.0"
Expand Down
19 changes: 6 additions & 13 deletions backend/src/events.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,25 @@
use serde::Serialize;
use tauri::Manager;

use crate::{
result::Result,
serializable_enum,
};
use crate::serializable_enum;

serializable_enum!(AppEvent {
SyncInstalledGames,
SyncOwnedGames,
SyncDiscoverGames,
SyncMods,
ExecutedSteamCommand,
GameAdded,
GameRemoved,
Error,
});

pub trait EventEmitter {
fn emit_event<TPayload: Serialize + Clone>(&self, event: AppEvent, payload: TPayload)
-> Result;
fn emit_event<TPayload: Serialize + Clone>(&self, event: AppEvent, payload: TPayload);
}

impl EventEmitter for tauri::AppHandle {
fn emit_event<TPayload: Serialize + Clone>(
&self,
event: AppEvent,
payload: TPayload,
) -> Result {
Ok(self.emit_all(&event.to_string(), payload)?)
fn emit_event<TPayload: Serialize + Clone>(&self, event: AppEvent, payload: TPayload) {
self.emit_all(&event.to_string(), payload)
.unwrap_or_else(|err| eprintln!("Failed to emit event: {err}"));
}
}
85 changes: 32 additions & 53 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ use result::{
Error,
Result,
};
use steam::{
appinfo,
id_lists::SteamGame,
};
use steamlocate::SteamDir;
use tauri::{
api::dialog::message,
Expand All @@ -61,7 +57,6 @@ mod windows;
struct AppState {
installed_games: Mutex<Option<installed_game::Map>>,
owned_games: Mutex<Option<Vec<OwnedGame>>>,
discover_games: Mutex<Option<Vec<SteamGame>>>,
mod_loaders: Mutex<Option<mod_loader::DataMap>>,
}

Expand Down Expand Up @@ -106,12 +101,6 @@ async fn get_owned_games(state: tauri::State<'_, AppState>) -> Result<Vec<OwnedG
get_state_data(&state.owned_games)
}

#[tauri::command]
#[specta::specta]
async fn get_discover_games(state: tauri::State<'_, AppState>) -> Result<Vec<SteamGame>> {
get_state_data(&state.discover_games)
}

#[tauri::command]
#[specta::specta]
async fn get_mod_loaders(state: tauri::State<'_, AppState>) -> Result<mod_loader::DataMap> {
Expand All @@ -123,17 +112,15 @@ fn update_state<TData>(
data: TData,
mutex: &Mutex<Option<TData>>,
handle: &tauri::AppHandle,
) -> Result {
) {
if let Ok(mut mutex_guard) = mutex.lock() {
*mutex_guard = Some(data);
}

// Sends a signal to make the frontend request an app state refresh.
// I would have preferred to just send the state with the signal,
// but it seems like Tauri events are really slow for large data.
handle.emit_event(event, ())?;

Ok(())
handle.emit_event(event, ());
}

#[tauri::command]
Expand Down Expand Up @@ -213,7 +200,7 @@ fn refresh_single_game(
installed_games,
&state.installed_games,
handle,
)?;
);

Ok(())
}
Expand Down Expand Up @@ -246,20 +233,19 @@ async fn update_data(handle: tauri::AppHandle, state: tauri::State<'_, AppState>
mod_loaders.clone(),
&state.mod_loaders,
&handle,
)?;
);

let provider_map = provider::get_map();

let steam_dir = SteamDir::locate()?;
let app_info = appinfo::read(steam_dir.path())?;
let provider_map = provider::get_map(&handle);

let installed_games: HashMap<_, _> = provider_map
.values()
.flat_map(|provider| match provider.get_installed_games() {
Ok(games) => games,
Err(err) => {
// TODO properly handle these errors message to frontend.
eprintln!("Error getting installed games for provider: {}", err);
handle.emit_event(
AppEvent::Error,
format!("Error getting installed games for provider: {err}"),
);
Vec::default()
}
})
Expand All @@ -274,37 +260,24 @@ async fn update_data(handle: tauri::AppHandle, state: tauri::State<'_, AppState>
installed_games.clone(),
&state.installed_games,
&handle,
)?;

let (discover_games_result, owned_games_result) = futures::future::join(
steam::discover_games::get(&app_info),
futures::future::join_all(
provider_map
.values()
.map(provider::ProviderActions::get_owned_games),
),
)
.await;

let owned_games: Vec<OwnedGame> = owned_games_result
.into_iter()
.flat_map(result::Result::unwrap_or_default)
.collect();
);

let discover_games = discover_games_result.unwrap_or_default();
update_state(
AppEvent::SyncDiscoverGames,
discover_games,
&state.discover_games,
&handle,
)?;
let owned_games: Vec<OwnedGame> = futures::future::join_all(
provider_map
.values()
.map(provider::ProviderActions::get_owned_games),
)
.await
.into_iter()
.flat_map(result::Result::unwrap_or_default)
.collect();

update_state(
AppEvent::SyncOwnedGames,
owned_games,
&state.owned_games,
&handle,
)?;
);

Ok(())
}
Expand Down Expand Up @@ -335,9 +308,9 @@ async fn add_game(
installed_games,
&state.installed_games,
&handle,
)?;
);

handle.emit_event(AppEvent::GameAdded, game_name)?;
handle.emit_event(AppEvent::GameAdded, game_name);

Ok(())
}
Expand All @@ -360,13 +333,20 @@ async fn remove_game(
installed_games,
&state.installed_games,
&handle,
)?;
);

handle.emit_event(AppEvent::GameRemoved, game.name)?;
handle.emit_event(AppEvent::GameRemoved, game.name);

Ok(())
}

#[tauri::command]
#[specta::specta]
async fn delete_steam_appinfo_cache() -> Result {
let steam_dir = SteamDir::locate()?;
steam::appinfo::delete(steam_dir.path())
}

#[tauri::command]
#[specta::specta]
// This command is here just so tauri_specta exports these types.
Expand All @@ -392,7 +372,6 @@ fn main() {
.manage(AppState {
installed_games: Mutex::default(),
owned_games: Mutex::default(),
discover_games: Mutex::default(),
mod_loaders: Mutex::default(),
})
.setup(|_app| {
Expand Down Expand Up @@ -425,7 +404,6 @@ fn main() {
update_data,
get_installed_games,
get_owned_games,
get_discover_games,
get_mod_loaders,
open_game_folder,
install_mod,
Expand All @@ -436,6 +414,7 @@ fn main() {
open_mods_folder,
add_game,
remove_game,
delete_steam_appinfo_cache,
]
);

Expand Down
14 changes: 9 additions & 5 deletions backend/src/providers/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ use async_trait::async_trait;
use enum_dispatch::enum_dispatch;

use crate::{
events::{
AppEvent,
EventEmitter,
},
installed_game::InstalledGame,
owned_game::OwnedGame,
providers::{
Expand Down Expand Up @@ -49,23 +53,23 @@ where
Ok((TProvider::ID.to_string(), mod_loader))
}

fn add_entry<TProvider: ProviderActions + ProviderStatic>(map: &mut Map)
fn add_entry<TProvider: ProviderActions + ProviderStatic>(map: &mut Map, handle: &tauri::AppHandle)
where
Provider: std::convert::From<TProvider>,
{
match create_map_entry::<TProvider>() {
Ok((key, value)) => {
map.insert(key, value);
}
Err(err) => eprintln!("Failed to create map entry: {err}"),
Err(err) => handle.emit_event(AppEvent::Error, format!("Failed to set up provider: {err}")),
}
}

pub fn get_map() -> Map {
pub fn get_map(handle: &tauri::AppHandle) -> Map {
let mut map = Map::new();

add_entry::<SteamProvider>(&mut map);
add_entry::<ManualProvider>(&mut map);
add_entry::<SteamProvider>(&mut map, handle);
add_entry::<ManualProvider>(&mut map, handle);

map
}
4 changes: 4 additions & 0 deletions backend/src/steam/appinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,7 @@ pub fn read(steam_path: &Path) -> Result<SteamAppInfoFile> {
let mut appinfo_file = BufReader::new(fs::File::open(get_path(steam_path))?);
SteamAppInfoFile::load(&mut appinfo_file)
}

pub fn delete(steam_path: &Path) -> Result {
Ok(fs::remove_file(get_path(steam_path))?)
}
2 changes: 1 addition & 1 deletion backend/src/steam/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ use crate::{

pub fn run(command: &str, handle: &tauri::AppHandle) -> Result {
open::that_detached(format!("steam://{command}"))?;
handle.emit_event(AppEvent::ExecutedSteamCommand, ())?;
handle.emit_event(AppEvent::ExecutedSteamCommand, ());
Ok(())
}
26 changes: 0 additions & 26 deletions backend/src/steam/discover_games.rs

This file was deleted.

1 change: 0 additions & 1 deletion backend/src/steam/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pub mod appinfo;
pub mod command;
pub mod discover_games;
pub mod id_lists;
pub mod thumbnail;
2 changes: 1 addition & 1 deletion backend/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"dialog": {
"all": false,
"ask": false,
"confirm": false,
"confirm": true,
"message": false,
"open": true,
"save": false
Expand Down
11 changes: 5 additions & 6 deletions frontend/api/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ export function getOwnedGames() {
return invoke()<OwnedGame[]>("get_owned_games")
}

export function getDiscoverGames() {
return invoke()<SteamGame[]>("get_discover_games")
}

export function getModLoaders() {
return invoke()<{ [key: string]: ModLoaderData }>("get_mod_loaders")
}
Expand Down Expand Up @@ -70,12 +66,15 @@ export function removeGame(gameId: string) {
return invoke()<null>("remove_game", { gameId })
}

export function deleteSteamAppinfoCache() {
return invoke()<null>("delete_steam_appinfo_cache")
}

export type GameExecutable = { path: string; engine: GameEngine | null; architecture: Architecture | null; operatingSystem: OperatingSystem | null; scriptingBackend: UnityScriptingBackend | null }
export type InstalledGame = { id: string; name: string; providerId: ProviderId; discriminator: string | null; steamLaunch: SteamLaunchOption | null; executable: GameExecutable; thumbnailUrl: string | null; availableMods: { [key: string]: boolean } }
export type ProviderId = "Steam" | "Manual"
export type AppEvent = "SyncInstalledGames" | "SyncOwnedGames" | "SyncDiscoverGames" | "SyncMods" | "ExecutedSteamCommand" | "GameAdded" | "GameRemoved"
export type SteamGame = { id: string; nsfw: boolean; engine: GameEngineBrand }
export type GameEngine = { brand: GameEngineBrand; version: GameEngineVersion | null }
export type AppEvent = "SyncInstalledGames" | "SyncOwnedGames" | "SyncMods" | "ExecutedSteamCommand" | "GameAdded" | "GameRemoved" | "Error"
export type Mod = { id: string; name: string; scriptingBackend: UnityScriptingBackend | null; engine: GameEngineBrand | null; kind: ModKind; path: string }
export type ModLoaderData = { id: string; path: string; mods: Mod[] }
export type OwnedGame = { id: string; providerId: ProviderId; name: string; installed: boolean; osList: OperatingSystem[]; engine: GameEngineBrand; releaseDate: number; thumbnailUrl: string }
Expand Down
Loading