feat(ui): added discord rpc icon selection
This commit is contained in:
parent
15fde05021
commit
df7726101d
2 changed files with 147 additions and 4 deletions
|
@ -4,7 +4,7 @@ use anime_launcher_sdk::config::ConfigExt;
|
||||||
use anime_launcher_sdk::genshin::config::{Config, Schema};
|
use anime_launcher_sdk::genshin::config::{Config, Schema};
|
||||||
|
|
||||||
use anime_launcher_sdk::genshin::states::LauncherState;
|
use anime_launcher_sdk::genshin::states::LauncherState;
|
||||||
use anime_launcher_sdk::genshin::consts::launcher_dir;
|
use anime_launcher_sdk::genshin::consts::*;
|
||||||
|
|
||||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||||
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
|
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
|
||||||
|
@ -46,11 +46,14 @@ lazy_static::lazy_static! {
|
||||||
/// Path to launcher folder. Standard is `$HOME/.local/share/anime-game-launcher`
|
/// Path to launcher folder. Standard is `$HOME/.local/share/anime-game-launcher`
|
||||||
pub static ref LAUNCHER_FOLDER: PathBuf = launcher_dir().expect("Failed to get launcher folder");
|
pub static ref LAUNCHER_FOLDER: PathBuf = launcher_dir().expect("Failed to get launcher folder");
|
||||||
|
|
||||||
|
/// Path to launcher's cache folder. Standard is `$HOME/.cache/anime-game-launcher`
|
||||||
|
pub static ref CACHE_FOLDER: PathBuf = cache_dir().expect("Failed to get launcher's cache folder");
|
||||||
|
|
||||||
/// Path to `debug.log` file. Standard is `$HOME/.local/share/anime-game-launcher/debug.log`
|
/// Path to `debug.log` file. Standard is `$HOME/.local/share/anime-game-launcher/debug.log`
|
||||||
pub static ref DEBUG_FILE: PathBuf = LAUNCHER_FOLDER.join("debug.log");
|
pub static ref DEBUG_FILE: PathBuf = LAUNCHER_FOLDER.join("debug.log");
|
||||||
|
|
||||||
/// Path to `background` file. Standard is `$HOME/.local/share/anime-game-launcher/background`
|
/// Path to `background` file. Standard is `$HOME/.cache/anime-game-launcher/background`
|
||||||
pub static ref BACKGROUND_FILE: PathBuf = LAUNCHER_FOLDER.join("background");
|
pub static ref BACKGROUND_FILE: PathBuf = CACHE_FOLDER.join("background");
|
||||||
|
|
||||||
/// Path to `.keep-background` file. Used to mark launcher that it shouldn't update background picture
|
/// Path to `.keep-background` file. Used to mark launcher that it shouldn't update background picture
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use relm4::prelude::*;
|
use relm4::prelude::*;
|
||||||
use relm4::component::*;
|
use relm4::component::*;
|
||||||
|
use relm4::factory::*;
|
||||||
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
|
|
||||||
|
@ -7,6 +8,9 @@ use anime_launcher_sdk::config::ConfigExt;
|
||||||
use anime_launcher_sdk::genshin::config::Config;
|
use anime_launcher_sdk::genshin::config::Config;
|
||||||
use anime_launcher_sdk::config::schema_blanks::prelude::*;
|
use anime_launcher_sdk::config::schema_blanks::prelude::*;
|
||||||
|
|
||||||
|
use anime_launcher_sdk::anime_game_core::installer::downloader::Downloader;
|
||||||
|
|
||||||
|
use anime_launcher_sdk::discord_rpc::DiscordRpc;
|
||||||
use anime_launcher_sdk::is_available;
|
use anime_launcher_sdk::is_available;
|
||||||
|
|
||||||
pub mod game;
|
pub mod game;
|
||||||
|
@ -23,7 +27,69 @@ use crate::*;
|
||||||
use super::gamescope::*;
|
use super::gamescope::*;
|
||||||
use super::main::PreferencesAppMsg;
|
use super::main::PreferencesAppMsg;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct DiscordRpcIcon {
|
||||||
|
pub check_button: gtk::CheckButton,
|
||||||
|
|
||||||
|
pub name: String,
|
||||||
|
pub path: PathBuf
|
||||||
|
}
|
||||||
|
|
||||||
|
#[relm4::factory(async)]
|
||||||
|
impl AsyncFactoryComponent for DiscordRpcIcon {
|
||||||
|
type Init = Self;
|
||||||
|
type Input = EnhancementsAppMsg;
|
||||||
|
type Output = EnhancementsAppMsg;
|
||||||
|
type CommandOutput = ();
|
||||||
|
type ParentInput = EnhancementsAppMsg;
|
||||||
|
type ParentWidget = adw::ExpanderRow;
|
||||||
|
|
||||||
|
view! {
|
||||||
|
root = adw::ActionRow {
|
||||||
|
set_title: &self.name,
|
||||||
|
// set_subtitle: &self.name,
|
||||||
|
|
||||||
|
// Don't even try to understand
|
||||||
|
add_prefix = &self.check_button.clone(),
|
||||||
|
|
||||||
|
add_suffix = >k::Picture {
|
||||||
|
set_margin_start: 4,
|
||||||
|
set_margin_top: 4,
|
||||||
|
set_margin_end: 4,
|
||||||
|
set_margin_bottom: 4,
|
||||||
|
|
||||||
|
add_css_class: "round-bin",
|
||||||
|
|
||||||
|
set_filename: Some(&self.path)
|
||||||
|
},
|
||||||
|
|
||||||
|
set_activatable: true,
|
||||||
|
|
||||||
|
connect_activated[sender, index] => move |_| {
|
||||||
|
sender.output(EnhancementsAppMsg::SetDiscordRpcIcon(index.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
async fn init_model(
|
||||||
|
init: Self::Init,
|
||||||
|
_index: &DynamicIndex,
|
||||||
|
_sender: AsyncFactorySender<Self>,
|
||||||
|
) -> Self {
|
||||||
|
init
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||||
|
Some(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct EnhancementsApp {
|
pub struct EnhancementsApp {
|
||||||
|
discord_rpc_icons: AsyncFactoryVecDeque<DiscordRpcIcon>,
|
||||||
|
discord_rpc_root_check_button: gtk::CheckButton,
|
||||||
|
|
||||||
gamescope: AsyncController<GamescopeApp>,
|
gamescope: AsyncController<GamescopeApp>,
|
||||||
game_page: AsyncController<GamePage>,
|
game_page: AsyncController<GamePage>,
|
||||||
sandbox_page: AsyncController<SandboxPage>,
|
sandbox_page: AsyncController<SandboxPage>,
|
||||||
|
@ -34,6 +100,8 @@ pub struct EnhancementsApp {
|
||||||
pub enum EnhancementsAppMsg {
|
pub enum EnhancementsAppMsg {
|
||||||
SetGamescopeParent(adw::PreferencesWindow),
|
SetGamescopeParent(adw::PreferencesWindow),
|
||||||
|
|
||||||
|
SetDiscordRpcIcon(DynamicIndex),
|
||||||
|
|
||||||
OpenGamescope,
|
OpenGamescope,
|
||||||
OpenMainPage,
|
OpenMainPage,
|
||||||
OpenGameSettingsPage,
|
OpenGameSettingsPage,
|
||||||
|
@ -372,6 +440,12 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[local_ref]
|
||||||
|
discord_rpc_icons -> adw::ExpanderRow {
|
||||||
|
// TODO: add localization
|
||||||
|
set_title: "Icon"
|
||||||
|
},
|
||||||
|
|
||||||
adw::EntryRow {
|
adw::EntryRow {
|
||||||
set_title: &tr("title"),
|
set_title: &tr("title"),
|
||||||
set_text: &CONFIG.launcher.discord_rpc.title,
|
set_text: &CONFIG.launcher.discord_rpc.title,
|
||||||
|
@ -573,7 +647,10 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
||||||
) -> AsyncComponentParts<Self> {
|
) -> AsyncComponentParts<Self> {
|
||||||
tracing::info!("Initializing enhancements settings");
|
tracing::info!("Initializing enhancements settings");
|
||||||
|
|
||||||
let model = Self {
|
let mut model = Self {
|
||||||
|
discord_rpc_icons: AsyncFactoryVecDeque::new(adw::ExpanderRow::new(), sender.input_sender()),
|
||||||
|
discord_rpc_root_check_button: gtk::CheckButton::new(),
|
||||||
|
|
||||||
gamescope: GamescopeApp::builder()
|
gamescope: GamescopeApp::builder()
|
||||||
.launch(())
|
.launch(())
|
||||||
.detach(),
|
.detach(),
|
||||||
|
@ -591,6 +668,57 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
||||||
.forward(sender.input_sender(), std::convert::identity)
|
.forward(sender.input_sender(), std::convert::identity)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
match DiscordRpc::get_assets(CONFIG.launcher.discord_rpc.app_id) {
|
||||||
|
Ok(icons) => {
|
||||||
|
for icon in icons {
|
||||||
|
let cache_file = CACHE_FOLDER.join("discord-rpc").join(&icon.name);
|
||||||
|
// let sender = sender.clone();
|
||||||
|
|
||||||
|
if !cache_file.exists() {
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
Downloader::new(icon.get_uri())
|
||||||
|
.expect("Failed to init Discord RPC icon downloader")
|
||||||
|
.with_continue_downloading(false)
|
||||||
|
.with_free_space_check(false)
|
||||||
|
.download(cache_file, |_, _| {})
|
||||||
|
.expect("Failed to download Discord RPC icon");
|
||||||
|
|
||||||
|
/*if let Err(err) = result {
|
||||||
|
sender.input(EnhancementsAppMsg::Toast {
|
||||||
|
title: String::from("Failed to download Discord RPC icon"), // TODO: add localizations
|
||||||
|
description: Some(err.to_string())
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add icons after thread above finishes its work as well
|
||||||
|
else {
|
||||||
|
let check_button = gtk::CheckButton::new();
|
||||||
|
|
||||||
|
check_button.set_group(Some(&model.discord_rpc_root_check_button));
|
||||||
|
|
||||||
|
if CONFIG.launcher.discord_rpc.icon == icon.name {
|
||||||
|
check_button.set_active(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
model.discord_rpc_icons.guard().push_back(DiscordRpcIcon {
|
||||||
|
check_button,
|
||||||
|
name: icon.name.clone(),
|
||||||
|
path: cache_file.clone()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(err) => sender.input(EnhancementsAppMsg::Toast {
|
||||||
|
title: String::from("Failed to fetch Discord RPC icons"), // TODO: add localizations
|
||||||
|
description: Some(err.to_string())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let discord_rpc_icons = model.discord_rpc_icons.widget();
|
||||||
|
|
||||||
let game_page = model.game_page.widget();
|
let game_page = model.game_page.widget();
|
||||||
let sandbox_page = model.sandbox_page.widget();
|
let sandbox_page = model.sandbox_page.widget();
|
||||||
let environment_page = model.environment_page.widget();
|
let environment_page = model.environment_page.widget();
|
||||||
|
@ -606,6 +734,18 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
||||||
self.gamescope.widget().set_transient_for(Some(&parent));
|
self.gamescope.widget().set_transient_for(Some(&parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnhancementsAppMsg::SetDiscordRpcIcon(index) => {
|
||||||
|
if let Some(icon) = self.discord_rpc_icons.guard().get(index.current_index()) {
|
||||||
|
if let Ok(mut config) = Config::get() {
|
||||||
|
config.launcher.discord_rpc.icon = icon.name.clone();
|
||||||
|
|
||||||
|
Config::update(config);
|
||||||
|
|
||||||
|
icon.check_button.set_active(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EnhancementsAppMsg::OpenGamescope => {
|
EnhancementsAppMsg::OpenGamescope => {
|
||||||
self.gamescope.widget().present();
|
self.gamescope.widget().present();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue