// #![windows_subsystem = "windows"] mod utils; mod components; use components::settings::{SettingsModal, SettingsMessage}; use components::installer::{install_game, refresh_install}; use directories::ProjectDirs; use ::image::{DynamicImage, ImageReader}; use iced::{ alignment::Vertical::{Bottom, Top}, border, event, font::{Stretch, Weight}, mouse::Interaction, widget::{button, center, column, container, image, mouse_area, opaque, row, stack, text, Space}, window::{self, icon, Settings}, Alignment::Center, Color, Element, Event, Font, Length, Padding, Size, Subscription, Task }; use iced_video_player::{Video, VideoPlayer}; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; use strum_macros::EnumIter; use utils::visual_helper::{get_game_background, get_game_icon_dynamic_image, get_game_splash_dynamic_image, style_container}; use std::{ collections::HashMap, env, fs::{self, create_dir_all, read_to_string}, io::{Cursor, Write}, path::PathBuf }; pub const ORGANIZATION: &str = "ReversedRooms"; pub const PRODUCT: &str = "RoomsLauncher"; // Trait for converting DynamicImage to image::Handle trait InterfaceImage { fn into_handle(self) -> image::Handle; } impl InterfaceImage for DynamicImage { fn into_handle(self) -> image::Handle { image::Handle::from_rgba(self.width(), self.height(), self.to_rgba8().into_raw()) } } pub fn main() -> iced::Result { let icon_image = ImageReader::new(Cursor::new(include_bytes!("../resources/icon.png"))) .with_guessed_format() .unwrap() .decode() .unwrap(); let settings = Settings { decorations: false, icon: Some(icon::from_rgba(icon_image.as_rgba8().unwrap().to_vec(), icon_image.width(), icon_image.height()).unwrap()), size: Size::new(0.0, 0.0), maximized: false, fullscreen: false, position: window::Position::Centered, max_size: None, min_size: None, visible: true, resizable: false, transparent: false, level: window::Level::Normal, exit_on_close_request: false, ..Settings::default() }; iced::application(Launcher::boot, Launcher::update, Launcher::view) .subscription(Launcher::subscription) .title(Launcher::title) .window(settings) .font(include_bytes!("../resources/segoe-mdl2-assets.ttf")) .font(include_bytes!("../resources/QuodlibetSans-Regular.ttf")) .window_size((1280.0, 720.0)) .run() } #[derive(Debug, PartialEq, Eq, Hash, Clone, EnumIter, Default, Serialize, Deserialize)] enum PossibleGames { #[default] WutheringWaves, HonkaiStarRail, ZenlessZoneZero, GenshinImpact, } impl PossibleGames { fn get_preferred_size(&self) -> (u32, u32) { match self { Self::WutheringWaves => (1280, 760), _ => (1280, 720), } } } #[derive(Debug)] enum Launcher { Loaded(Box), } #[derive(Debug)] struct VideoBackground { video: Option