mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-02-16 07:11:26 +03:00
general settings: added test launcher style switcher
- classic style loads its background from "config's_tmp_path/background" so from "launcher folder/background" by default - icons will be changed in some future
This commit is contained in:
parent
949a0f37e9
commit
5870316724
8 changed files with 228 additions and 18 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 8a32066c07cd471fe2a33ecfa778edffb8796f19
|
||||
Subproject commit a62aeef9cd9caa0e147fddcf05f4c412c942b736
|
12
assets/images/classic.svg
Normal file
12
assets/images/classic.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="90" height="60" viewBox="0 0 90 60" xml:space="preserve">
|
||||
<defs>
|
||||
</defs>
|
||||
<g transform="matrix(1.58 0 0 0.39 62.57 51.18)" id="HUkKwqLQOm47Zs9qaMmTc" >
|
||||
<path style="stroke: rgb(242,144,30); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(53,132,228); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(0, 0)" d="M -8.25689 0.69081 C -8.25689 -4.25086 -7.26151 -8.256879999999999 -6.03365 -8.256879999999999 L 6.03365 -8.256879999999999 L 6.03365 -8.256879999999999 C 7.2615099999999995 -8.256879999999999 8.25689 -4.2508599999999985 8.25689 0.6908100000000008 L 8.25689 0.6908100000000008 L 8.25689 0.6908100000000008 C 8.25689 4.869440000000001 7.41521 8.256890000000002 6.37694 8.256890000000002 L -6.37694 8.256890000000002 L -6.37694 8.256890000000002 C -7.41521 8.256890000000002 -8.25689 4.869440000000003 -8.25689 0.6908100000000017 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(0.39 0 0 0.39 79.98 51.2)" id="3u3imhfuSenPkHHelxk_U" >
|
||||
<path style="stroke: rgb(242,144,30); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(230,230,230); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(0, 0)" d="M -8.25689 0.72542 C -8.25689 -4.2353700000000005 -4.26412 -8.25688 0.6612200000000001 -8.25688 L 0.6612200000000001 -8.25688 L 0.6612200000000001 -8.25688 C 4.85619 -8.25688 8.25689 -4.8317000000000005 8.25689 -0.6065400000000007 L 8.25689 0.6615399999999994 L 8.25689 0.6615399999999994 C 8.25689 4.85633 4.88064 8.256889999999999 0.7158300000000004 8.256889999999999 L -0.7792399999999995 8.256889999999999 L -0.7792399999999995 8.256889999999999 C -4.90902 8.256889999999999 -8.256879999999999 4.8849399999999985 -8.256879999999999 0.7254299999999985 z" stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
12
assets/images/modern.svg
Normal file
12
assets/images/modern.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="90" height="60" viewBox="0 0 90 60" xml:space="preserve">
|
||||
<defs>
|
||||
</defs>
|
||||
<g transform="matrix(1.58 0 0 0.39 41.18 39.34)" id="HUkKwqLQOm47Zs9qaMmTc" >
|
||||
<path style="stroke: rgb(242,144,30); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(53,132,228); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(0, 0)" d="M -8.25689 0.69081 C -8.25689 -4.25086 -7.26151 -8.256879999999999 -6.03365 -8.256879999999999 L 6.03365 -8.256879999999999 L 6.03365 -8.256879999999999 C 7.2615099999999995 -8.256879999999999 8.25689 -4.2508599999999985 8.25689 0.6908100000000008 L 8.25689 0.6908100000000008 L 8.25689 0.6908100000000008 C 8.25689 4.869440000000001 7.41521 8.256890000000002 6.37694 8.256890000000002 L -6.37694 8.256890000000002 L -6.37694 8.256890000000002 C -7.41521 8.256890000000002 -8.25689 4.869440000000003 -8.25689 0.6908100000000017 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(0.39 0 0 0.39 58.59 39.36)" id="3u3imhfuSenPkHHelxk_U" >
|
||||
<path style="stroke: rgb(242,144,30); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(230,230,230); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(0, 0)" d="M -8.25689 0.72542 C -8.25689 -4.2353700000000005 -4.26412 -8.25688 0.6612200000000001 -8.25688 L 0.6612200000000001 -8.25688 L 0.6612200000000001 -8.25688 C 4.85619 -8.25688 8.25689 -4.8317000000000005 8.25689 -0.6065400000000007 L 8.25689 0.6615399999999994 L 8.25689 0.6615399999999994 C 8.25689 4.85633 4.88064 8.256889999999999 0.7158300000000004 8.256889999999999 L -0.7792399999999995 8.256889999999999 L -0.7792399999999995 8.256889999999999 C -4.90902 8.256889999999999 -8.256879999999999 4.8849399999999985 -8.256879999999999 0.7254299999999985 z" stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -3,4 +3,10 @@
|
|||
<gresource prefix="/org/app">
|
||||
<file compressed="true">images/icon.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/app">
|
||||
<file compressed="true">images/modern.svg</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/app">
|
||||
<file compressed="true">images/classic.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
20
src/main.rs
20
src/main.rs
|
@ -6,6 +6,8 @@ use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
|
|||
|
||||
use tracing_subscriber::prelude::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod i18n;
|
||||
pub mod ui;
|
||||
|
||||
|
@ -110,14 +112,22 @@ fn main() {
|
|||
}
|
||||
|
||||
// Create the app
|
||||
let app = RelmApp::new("moe.launcher.an-anime-game-launcher");
|
||||
let app = RelmApp::new(APP_ID);
|
||||
|
||||
// Set global css
|
||||
relm4::set_global_css("
|
||||
progressbar > text {
|
||||
relm4::set_global_css(&format!("
|
||||
progressbar > text {{
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
");
|
||||
}}
|
||||
|
||||
window.classic-style {{
|
||||
background: url(\"file://{}/background\");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}}
|
||||
",
|
||||
CONFIG.launcher.temp.as_ref().unwrap_or(&PathBuf::from("/tmp")).to_string_lossy()
|
||||
));
|
||||
|
||||
// Run the app
|
||||
app.run::<ui::main::App>(());
|
||||
|
|
102
src/ui/main.rs
102
src/ui/main.rs
|
@ -8,6 +8,9 @@ use relm4::{
|
|||
use gtk::prelude::*;
|
||||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::launcher::LauncherStyle;
|
||||
|
||||
use crate::*;
|
||||
use crate::i18n::tr;
|
||||
|
||||
use super::preferences::main::App as PreferencesApp;
|
||||
|
@ -25,13 +28,16 @@ static mut PREFERENCES_WINDOW: Option<AsyncController<PreferencesApp>> = None;
|
|||
static mut ABOUT_DIALOG: Option<Controller<AboutDialog>> = None;
|
||||
|
||||
pub struct App {
|
||||
loading: Option<Option<String>>
|
||||
loading: Option<Option<String>>,
|
||||
style: LauncherStyle
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AppMsg {
|
||||
PerformAction,
|
||||
OpenPreferences,
|
||||
ClosePreferences
|
||||
ClosePreferences,
|
||||
UpdateLauncherStyle(LauncherStyle)
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
|
@ -57,12 +63,47 @@ impl SimpleComponent for App {
|
|||
view! {
|
||||
main_window = adw::Window {
|
||||
set_title: Some("An Anime Game Launcher"),
|
||||
set_default_size: (900, 600),
|
||||
|
||||
#[watch]
|
||||
set_default_size: (
|
||||
match model.style {
|
||||
LauncherStyle::Modern => 900,
|
||||
LauncherStyle::Classic => 1094 // (w = 1280 / 730 * h, where 1280x730 is default background picture resolution)
|
||||
},
|
||||
match model.style {
|
||||
LauncherStyle::Modern => 600,
|
||||
LauncherStyle::Classic => 624
|
||||
}
|
||||
),
|
||||
|
||||
#[watch]
|
||||
add_css_class: match model.style {
|
||||
LauncherStyle::Modern => "",
|
||||
LauncherStyle::Classic => "classic-style"
|
||||
},
|
||||
|
||||
#[watch]
|
||||
remove_css_class: match model.style {
|
||||
LauncherStyle::Modern => "classic-style",
|
||||
LauncherStyle::Classic => ""
|
||||
},
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
adw::HeaderBar {
|
||||
#[watch]
|
||||
add_css_class: match model.style {
|
||||
LauncherStyle::Modern => "",
|
||||
LauncherStyle::Classic => "flat"
|
||||
},
|
||||
|
||||
#[watch]
|
||||
remove_css_class: match model.style {
|
||||
LauncherStyle::Modern => "flat",
|
||||
LauncherStyle::Classic => ""
|
||||
},
|
||||
|
||||
pack_end = >k::MenuButton {
|
||||
set_icon_name: "open-menu-symbolic",
|
||||
set_menu_model: Some(&main_menu)
|
||||
|
@ -89,6 +130,9 @@ impl SimpleComponent for App {
|
|||
set_visible: model.loading.is_none(),
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
#[watch]
|
||||
set_visible: model.style == LauncherStyle::Modern,
|
||||
|
||||
gtk::Image {
|
||||
set_resource: Some("/org/app/images/icon.png"),
|
||||
set_vexpand: true,
|
||||
|
@ -103,11 +147,33 @@ impl SimpleComponent for App {
|
|||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_valign: gtk::Align::Center,
|
||||
#[watch]
|
||||
set_valign: match model.style {
|
||||
LauncherStyle::Modern => gtk::Align::Center,
|
||||
LauncherStyle::Classic => gtk::Align::End
|
||||
},
|
||||
|
||||
#[watch]
|
||||
set_width_request: match model.style {
|
||||
LauncherStyle::Modern => -1,
|
||||
LauncherStyle::Classic => 800
|
||||
},
|
||||
|
||||
set_vexpand: true,
|
||||
|
||||
gtk::Box {
|
||||
set_halign: gtk::Align::Center,
|
||||
#[watch]
|
||||
set_halign: match model.style {
|
||||
LauncherStyle::Modern => gtk::Align::Center,
|
||||
LauncherStyle::Classic => gtk::Align::End
|
||||
},
|
||||
|
||||
#[watch]
|
||||
set_height_request: match model.style {
|
||||
LauncherStyle::Modern => -1,
|
||||
LauncherStyle::Classic => 40
|
||||
},
|
||||
|
||||
set_margin_top: 64,
|
||||
set_spacing: 8,
|
||||
|
||||
|
@ -117,12 +183,16 @@ impl SimpleComponent for App {
|
|||
set_width_request: 200,
|
||||
add_css_class: "suggested-action",
|
||||
|
||||
connect_clicked => |_| {
|
||||
anime_launcher_sdk::game::run().expect("Failed to run the game");
|
||||
}
|
||||
connect_clicked => AppMsg::PerformAction
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
#[watch]
|
||||
set_width_request: match model.style {
|
||||
LauncherStyle::Modern => -1,
|
||||
LauncherStyle::Classic => 40
|
||||
},
|
||||
|
||||
set_icon_name: "emblem-system-symbolic",
|
||||
|
||||
connect_clicked => AppMsg::OpenPreferences
|
||||
|
@ -137,12 +207,13 @@ impl SimpleComponent for App {
|
|||
fn init(
|
||||
_counter: Self::Init,
|
||||
root: &Self::Root,
|
||||
_sender: ComponentSender<Self>,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
tracing::info!("Initializing main window");
|
||||
|
||||
let model = App {
|
||||
loading: None
|
||||
loading: None,
|
||||
style: CONFIG.launcher.style
|
||||
};
|
||||
|
||||
let widgets = view_output!();
|
||||
|
@ -156,7 +227,7 @@ impl SimpleComponent for App {
|
|||
unsafe {
|
||||
PREFERENCES_WINDOW = Some(PreferencesApp::builder()
|
||||
.launch(widgets.main_window.clone().into())
|
||||
.detach());
|
||||
.forward(sender.input_sender(), std::convert::identity));
|
||||
|
||||
ABOUT_DIALOG = Some(AboutDialog::builder()
|
||||
.transient_for(widgets.main_window.clone())
|
||||
|
@ -166,6 +237,7 @@ impl SimpleComponent for App {
|
|||
|
||||
let group = RelmActionGroup::<WindowActionGroup>::new();
|
||||
|
||||
// TODO
|
||||
group.add_action::<LauncherFolder>(&RelmAction::new_stateless(move |_| {
|
||||
println!("Open launcher folder!");
|
||||
}));
|
||||
|
@ -197,6 +269,10 @@ impl SimpleComponent for App {
|
|||
tracing::debug!("Called main window event: {:?}", msg);
|
||||
|
||||
match msg {
|
||||
AppMsg::PerformAction => {
|
||||
anime_launcher_sdk::game::run().expect("Failed to run the game");
|
||||
}
|
||||
|
||||
AppMsg::OpenPreferences => unsafe {
|
||||
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().widget().show();
|
||||
}
|
||||
|
@ -204,6 +280,10 @@ impl SimpleComponent for App {
|
|||
AppMsg::ClosePreferences => unsafe {
|
||||
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().widget().hide();
|
||||
}
|
||||
|
||||
AppMsg::UpdateLauncherStyle(style) => {
|
||||
self.style = style;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,61 @@ impl WidgetTemplate for General {
|
|||
set_title: &tr("general"),
|
||||
set_icon_name: Some("applications-system-symbolic"),
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: "Appearance",
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_halign: gtk::Align::Center,
|
||||
|
||||
set_spacing: 32,
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
#[name(modern_style_button)]
|
||||
gtk::ToggleButton {
|
||||
add_css_class: "card",
|
||||
|
||||
set_width_request: 180,
|
||||
set_height_request: 120,
|
||||
|
||||
gtk::Image {
|
||||
set_from_resource: Some("/org/app/images/modern.svg")
|
||||
}
|
||||
},
|
||||
|
||||
gtk::Label {
|
||||
set_text: "Modern",
|
||||
|
||||
set_margin_top: 16
|
||||
}
|
||||
},
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
#[name(classic_style_button)]
|
||||
gtk::ToggleButton {
|
||||
add_css_class: "card",
|
||||
|
||||
set_width_request: 180,
|
||||
set_height_request: 120,
|
||||
|
||||
gtk::Image {
|
||||
set_from_resource: Some("/org/app/images/classic.svg")
|
||||
}
|
||||
},
|
||||
|
||||
gtk::Label {
|
||||
set_text: "Classic",
|
||||
|
||||
set_margin_top: 16
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr("general"),
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use gtk::prelude::*;
|
|||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config;
|
||||
use anime_launcher_sdk::config::launcher::LauncherStyle;
|
||||
use anime_launcher_sdk::components::*;
|
||||
use anime_launcher_sdk::wincompatlib::prelude::*;
|
||||
|
||||
|
@ -20,6 +21,8 @@ pub struct App {
|
|||
wine_components: AsyncController<ComponentsList>,
|
||||
dxvk_components: AsyncController<ComponentsList>,
|
||||
|
||||
style: LauncherStyle,
|
||||
|
||||
downloaded_wine_versions: Vec<wine::Version>,
|
||||
downloaded_dxvk_versions: Vec<dxvk::Version>,
|
||||
|
||||
|
@ -36,6 +39,7 @@ pub enum AppMsg {
|
|||
title: String,
|
||||
description: Option<String>
|
||||
},
|
||||
UpdateLauncherStyle(LauncherStyle),
|
||||
WineRecommendedOnly(bool),
|
||||
DxvkRecommendedOnly(bool),
|
||||
UpdateDownloadedWine,
|
||||
|
@ -50,7 +54,7 @@ pub enum AppMsg {
|
|||
impl SimpleAsyncComponent for App {
|
||||
type Init = gtk::Window;
|
||||
type Input = AppMsg;
|
||||
type Output = ();
|
||||
type Output = crate::ui::main::AppMsg;
|
||||
|
||||
view! {
|
||||
preferences_window = adw::PreferencesWindow {
|
||||
|
@ -65,6 +69,22 @@ impl SimpleAsyncComponent for App {
|
|||
// but I have no idea how to do it other way
|
||||
// There're no graphical glitches so don't care
|
||||
|
||||
#[template_child]
|
||||
modern_style_button {
|
||||
#[watch]
|
||||
set_active: model.style == LauncherStyle::Modern,
|
||||
|
||||
connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Modern)
|
||||
},
|
||||
|
||||
#[template_child]
|
||||
classic_style_button {
|
||||
#[watch]
|
||||
set_active: model.style == LauncherStyle::Classic,
|
||||
|
||||
connect_clicked => AppMsg::UpdateLauncherStyle(LauncherStyle::Classic)
|
||||
},
|
||||
|
||||
#[template_child]
|
||||
wine_versions {
|
||||
add = model.wine_components.widget(),
|
||||
|
@ -191,6 +211,8 @@ impl SimpleAsyncComponent for App {
|
|||
})
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
style: CONFIG.launcher.style,
|
||||
|
||||
downloaded_wine_versions: vec![],
|
||||
downloaded_dxvk_versions: vec![],
|
||||
|
||||
|
@ -253,6 +275,19 @@ impl SimpleAsyncComponent for App {
|
|||
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().add_toast(&toast);
|
||||
}
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
AppMsg::UpdateLauncherStyle(style) => {
|
||||
if let Ok(mut config) = config::get() {
|
||||
config.launcher.style = style;
|
||||
|
||||
config::update(config);
|
||||
}
|
||||
|
||||
self.style = style;
|
||||
|
||||
sender.output(Self::Output::UpdateLauncherStyle(style));
|
||||
}
|
||||
|
||||
AppMsg::WineRecommendedOnly(state) => {
|
||||
// todo
|
||||
self.wine_components.sender().send(components::list::AppMsg::ShowRecommendedOnly(state)).unwrap();
|
||||
|
|
Loading…
Add table
Reference in a new issue