diff --git a/Cargo.lock b/Cargo.lock index 795ba1e3..b7c2e232 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2249,7 +2249,6 @@ dependencies = [ "futures", "jni 0.22.4", "mimalloc", - "ndk-context", "open", "postcard", "rand 0.10.1", diff --git a/Cargo.toml b/Cargo.toml index a89ee1e7..35f9ce35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,6 @@ open = { version = "5.3", optional = true } [target.'cfg(target_os = "android")'.dependencies] slint = { version = "1.16", default-features = false, features = ["compat-1-2", "std", "backend-android-activity-06", "accessibility"], optional = true } jni = "0.22" -ndk-context = "0.1" [build-dependencies] winresource = "0.1" diff --git a/src/lib.rs b/src/lib.rs index 78904bda..d3fda223 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -311,13 +311,7 @@ pub async fn run() -> std::io::Result<()> { async fn android_main(app: slint::android::AndroidApp) { slint::android::init(app.clone()).unwrap(); - if let Err(_) = android::DIRS.set(ui::Dirs { - config_dir: app.internal_data_path().unwrap().join("config"), - data_dir: app.external_data_path().unwrap().join("data"), - cache_dir: app.internal_data_path().unwrap().join("cache"), - }) { - println!("Android dirs already set"); - } + *android::ANDROID_APP.lock().unwrap() = Some(app); let dirs = ui::get_dirs(); @@ -327,4 +321,5 @@ async fn android_main(app: slint::android::AndroidApp) { std::fs::create_dir_all(dirs.data_dir.join("states")).unwrap(); ui::gui::app_window(true); + *android::ANDROID_APP.lock().unwrap() = None; } diff --git a/src/ui.rs b/src/ui.rs index d16065a9..70e472c9 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -128,32 +128,29 @@ pub fn sdl_close() { } } -#[cfg(not(target_os = "android"))] pub fn get_dirs() -> Dirs { - let exe_path = std::env::current_exe().unwrap(); - let portable_dir = exe_path.parent(); - let portable = portable_dir.unwrap().join("portable.txt").exists(); - if portable { - Dirs { - config_dir: portable_dir.unwrap().join("portable_data").join("config"), - data_dir: portable_dir.unwrap().join("portable_data").join("data"), - cache_dir: portable_dir.unwrap().join("portable_data").join("cache"), - } - } else { - Dirs { - config_dir: dirs::config_dir().unwrap().join("gopher64"), - data_dir: dirs::data_dir().unwrap().join("gopher64"), - cache_dir: dirs::cache_dir().unwrap().join("gopher64"), + #[cfg(not(target_os = "android"))] + { + let exe_path = std::env::current_exe().unwrap(); + let portable_dir = exe_path.parent(); + let portable = portable_dir.unwrap().join("portable.txt").exists(); + if portable { + Dirs { + config_dir: portable_dir.unwrap().join("portable_data").join("config"), + data_dir: portable_dir.unwrap().join("portable_data").join("data"), + cache_dir: portable_dir.unwrap().join("portable_data").join("cache"), + } + } else { + Dirs { + config_dir: dirs::config_dir().unwrap().join("gopher64"), + data_dir: dirs::data_dir().unwrap().join("gopher64"), + cache_dir: dirs::cache_dir().unwrap().join("gopher64"), + } } } -} - -#[cfg(target_os = "android")] -pub fn get_dirs() -> Dirs { - if let Some(android_dirs) = android::DIRS.get() { - android_dirs.clone() - } else { - panic!("Android app not initialized"); + #[cfg(target_os = "android")] + { + android::get_dirs() } } diff --git a/src/ui/android.rs b/src/ui/android.rs index cd55ba3d..58a525f1 100644 --- a/src/ui/android.rs +++ b/src/ui/android.rs @@ -3,10 +3,12 @@ use jni::refs::Global; use jni::{Env, JavaVM, bind_java_type}; use crate::ui; -pub static DIRS: std::sync::OnceLock = std::sync::OnceLock::new(); + +pub static ANDROID_APP: std::sync::Mutex> = + std::sync::Mutex::new(None); bind_java_type! { - AndroidContext => "android.content.Context", + AndroidActivity => "android.app.Activity", type_map = { AndroidIntent => "android.content.Intent", }, @@ -72,9 +74,14 @@ pub struct ControllerInfo { /// Lists connected gamepads and joysticks using the Android framework. pub fn list_controllers() -> Vec { - let ctx = ndk_context::android_context(); - - let vm = unsafe { JavaVM::from_raw(ctx.vm().cast()) }; + let vm = if let Ok(app) = ANDROID_APP.lock() + && let Some(app) = app.as_ref() + { + unsafe { JavaVM::from_raw(app.vm_as_ptr().cast()) } + } else { + eprintln!("Android app not initialized"); + return Vec::new(); + }; match vm.attach_current_thread(list_controllers_on_jvm) { Ok(controllers) => controllers, @@ -150,35 +157,39 @@ fn list_controllers_on_jvm(env: &mut Env<'_>) -> jni::errors::Result, - context: *mut std::ffi::c_void, - path: &str, -) -> jni::errors::Result<()> { - let context_ptr = context.cast(); - let context = unsafe { env.as_cast_raw::>(&context_ptr)? }; +fn open_uri_on_jvm(env: &mut Env<'_>, path: &str) -> jni::errors::Result<()> { + if let Ok(app) = ANDROID_APP.lock() + && let Some(app) = app.as_ref() + { + let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject; + let activity = unsafe { env.as_cast_raw::>(&raw_activity_global)? }; - let uri_string = JString::from_str(env, path.to_string())?; - let uri = AndroidUri::parse(env, &uri_string)?; + let uri_string = JString::from_str(env, path.to_string())?; + let uri = AndroidUri::parse(env, &uri_string)?; - let action_view = AndroidIntent::ACTION_VIEW(env)?; - let flag = AndroidIntent::FLAG_ACTIVITY_NEW_TASK(env)?; - let intent = AndroidIntent::new(env, &action_view)? - .set_data(env, &uri)? - .add_flags(env, flag)?; + let action_view = AndroidIntent::ACTION_VIEW(env)?; + let intent = AndroidIntent::new(env, &action_view)?.set_data(env, &uri)?; - context.as_ref().start_activity(env, &intent)?; - Ok(()) + activity.as_ref().start_activity(env, &intent)?; + Ok(()) + } else { + Err(jni::errors::Error::UninitializedJavaVM) + } } pub async fn select_rom(_rom_dir: slint::SharedString) -> Option { @@ -192,3 +203,17 @@ pub async fn select_gb_rom(_player: i32) -> Option { pub async fn select_gb_ram(_player: i32) -> Option { None } + +pub fn get_dirs() -> ui::Dirs { + if let Ok(app) = ANDROID_APP.lock() + && let Some(app) = app.as_ref() + { + ui::Dirs { + config_dir: app.internal_data_path().unwrap().join("config"), + data_dir: app.external_data_path().unwrap().join("data"), + cache_dir: app.internal_data_path().unwrap().join("cache"), + } + } else { + panic!("Android app not initialized"); + } +} diff --git a/src/ui/gui/appwindow.slint b/src/ui/gui/appwindow.slint index 0e329504..e7b6ae60 100644 --- a/src/ui/gui/appwindow.slint +++ b/src/ui/gui/appwindow.slint @@ -105,34 +105,34 @@ export component AppWindow inherits Window { portrait: root.is-portrait; title: "Gopher64"; model: [ - { - icon: @image-url("../../../data/ui/icons/local_game.svg"), - label: @tr("Menu" => "Local Game"), - }, - { - icon: @image-url("../../../data/ui/icons/controller.svg"), - label: @tr("Menu" => "Controller Config"), - }, - { - icon: @image-url("../../../data/ui/icons/netplay.svg"), - label: @tr("Menu" => "Netplay"), - }, - { - icon: @image-url("../../../data/ui/icons/cheats.svg"), - label: @tr("Menu" => "Cheats"), - }, - { - icon: @image-url("../../../data/ui/icons/achievements.svg"), - label: @tr("Menu" => "RetroAchievements"), - }, - { - icon: @image-url("../../../data/ui/icons/settings.svg"), - label: @tr("Menu" => "Settings"), - }, - { - icon: @image-url("../../../data/ui/icons/about.svg"), - label: @tr("Menu" => "About"), - }, + { + icon: @image-url("../../../data/ui/icons/local_game.svg"), + label: @tr("Menu" => "Local Game"), + }, + { + icon: @image-url("../../../data/ui/icons/controller.svg"), + label: @tr("Menu" => "Controller Config"), + }, + { + icon: @image-url("../../../data/ui/icons/netplay.svg"), + label: @tr("Menu" => "Netplay"), + }, + { + icon: @image-url("../../../data/ui/icons/cheats.svg"), + label: @tr("Menu" => "Cheats"), + }, + { + icon: @image-url("../../../data/ui/icons/achievements.svg"), + label: @tr("Menu" => "RetroAchievements"), + }, + { + icon: @image-url("../../../data/ui/icons/settings.svg"), + label: @tr("Menu" => "Settings"), + }, + { + icon: @image-url("../../../data/ui/icons/about.svg"), + label: @tr("Menu" => "About"), + }, ]; x: root.safe-left; y: root.is-portrait ? parent.height - root.bar-thickness - root.safe-bottom : root.safe-top; diff --git a/src/ui/gui/input_profile.slint b/src/ui/gui/input_profile.slint index 30703e80..704b6b14 100644 --- a/src/ui/gui/input_profile.slint +++ b/src/ui/gui/input_profile.slint @@ -13,6 +13,10 @@ export component InputProfileDialog inherits Window { in-out property profile_name <=> InputProfileData.profile_name; in-out property deadzone <=> InputProfileData.deadzone; VerticalBox { + padding-left: root.safe-area-insets.left; + padding-top: root.safe-area-insets.top; + padding-right: root.safe-area-insets.right; + padding-bottom: root.safe-area-insets.bottom; alignment: start; HorizontalBox { diff --git a/src/ui/gui/netplay_create.slint b/src/ui/gui/netplay_create.slint index 92dacc0f..185c94ce 100644 --- a/src/ui/gui/netplay_create.slint +++ b/src/ui/gui/netplay_create.slint @@ -1,8 +1,10 @@ -import { LineEdit, HorizontalBox, VerticalBox, Button, ComboBox } from "std-widgets.slint"; +import { LineEdit, HorizontalBox, VerticalBox, Button, ComboBox, ScrollView } from "std-widgets.slint"; import { NetplayData } from "netplay_page.slint"; export component NetplayCreate inherits Window { title: @tr("Netplay: Create Session"); + preferred-width: 425px; + preferred-height: 425px; in-out property server_names <=> NetplayData.server_names; in-out property server_urls <=> NetplayData.server_urls; in-out property custom_server_url <=> NetplayData.custom_server_url; @@ -18,108 +20,121 @@ export component NetplayCreate inherits Window { callback create_session(string, string, string, string, string, string, string); VerticalBox { - HorizontalBox { + vertical-stretch: 1; + padding-left: root.safe-area-insets.left; + padding-top: root.safe-area-insets.top; + padding-right: root.safe-area-insets.right; + padding-bottom: root.safe-area-insets.bottom; + ScrollView { + mouse-drag-pan-enabled: true; + vertical-stretch: 1; VerticalBox { - Text { - text: @tr("Session Name:"); - } + alignment: start; + HorizontalBox { + VerticalBox { + Text { + text: @tr("Session Name:"); + } - LineEdit { - placeholder-text: @tr("Enter session name"); - edited(text) => { - NetplayData.session_name = text; + LineEdit { + placeholder-text: @tr("Enter session name"); + edited(text) => { + NetplayData.session_name = text; + } + } } - } - } - VerticalBox { - Text { - text: @tr("Password (Optional):"); - } + VerticalBox { + Text { + text: @tr("Password (Optional):"); + } - LineEdit { - placeholder-text: @tr("Enter session password"); - edited(text) => { - NetplayData.password = text; - } - } - } - } - - VerticalBox { - Text { - text: @tr("Player Name:"); - } - - LineEdit { - placeholder-text: @tr("Enter player name"); - edited(text) => { - NetplayData.player_name = text; - } - } - } - - VerticalBox { - Text { - text: @tr("Server:"); - } - - HorizontalBox { - server := ComboBox { - model: NetplayData.server_names; - selected => { - if (self.current-index >= 0) { - if (self.current-value == "Custom") { - get_custom_url(); + LineEdit { + placeholder-text: @tr("Enter session password"); + edited(text) => { + NetplayData.password = text; } } } } - } - } - HorizontalBox { - alignment: center; - if NetplayData.game_name == "": Button { - text: @tr("Select ROM"); - clicked => { - select_rom(NetplayData.rom_dir); + VerticalBox { + Text { + text: @tr("Player Name:"); + } + + LineEdit { + placeholder-text: @tr("Enter player name"); + edited(text) => { + NetplayData.player_name = text; + } + } } - } - if NetplayData.game_name != "": Button { - text: NetplayData.game_name; - clicked => { - select_rom(NetplayData.rom_dir); + + VerticalBox { + Text { + text: @tr("Server:"); + } + + HorizontalBox { + server := ComboBox { + model: NetplayData.server_names; + selected => { + if (self.current-index >= 0) { + if (self.current-value == "Custom") { + get_custom_url(); + } + } + } + } + } } - } - } - Rectangle { } - - if NetplayData.game_cheats != "":Text { - text: @tr("This game has cheats enabled. Cheats will be synchronized with other players."); - } - Rectangle { } - - Button { - property server_url; - text: @tr("Create Session"); - enabled: NetplayData.session_name != "" && NetplayData.player_name != "" && NetplayData.game_name != "" && !NetplayData.pending_session; - clicked => { - NetplayData.pending_session = true; - if (server.current-value == "Custom") { - server_url = "ws://" + NetplayData.custom_server_url; - } else { - server_url = NetplayData.server_urls[server.current-index]; + HorizontalBox { + alignment: center; + if NetplayData.game_name == "": Button { + text: @tr("Select ROM"); + clicked => { + select_rom(NetplayData.rom_dir); + } + } + if NetplayData.game_name != "": Button { + text: NetplayData.game_name; + clicked => { + select_rom(NetplayData.rom_dir); + } + } } - create_session( - server_url, - NetplayData.session_name, - NetplayData.player_name, - NetplayData.game_name, - NetplayData.game_hash, - NetplayData.game_cheats, - NetplayData.password); + + Rectangle { } + + if NetplayData.game_cheats != "":Text { + text: @tr("This game has cheats enabled. Cheats will be synchronized with other players."); + } + Rectangle { } + + Button { + property server_url; + text: @tr("Create Session"); + enabled: NetplayData.session_name != "" && NetplayData.player_name != "" && NetplayData.game_name != "" && !NetplayData.pending_session; + clicked => { + NetplayData.pending_session = true; + if (server.current-value == "Custom") { + server_url = "ws://" + NetplayData.custom_server_url; + } else { + server_url = NetplayData.server_urls[server.current-index]; + } + create_session( + server_url, + NetplayData.session_name, + NetplayData.player_name, + NetplayData.game_name, + NetplayData.game_hash, + NetplayData.game_cheats, + NetplayData.password); + } + } + Rectangle { } } } } @@ -127,7 +142,13 @@ export component NetplayCreate inherits Window { export component DispatcherDialog inherits Dialog { title: @tr("Creating Server"); - Text { - text: @tr("Creating server, please wait...This may take about 30 seconds."); + VerticalBox { + padding-left: root.safe-area-insets.left; + padding-top: root.safe-area-insets.top; + padding-right: root.safe-area-insets.right; + padding-bottom: root.safe-area-insets.bottom; + Text { + text: @tr("Creating server, please wait...This may take about 30 seconds."); + } } } diff --git a/src/ui/gui/netplay_join.slint b/src/ui/gui/netplay_join.slint index b73c888f..69226627 100644 --- a/src/ui/gui/netplay_join.slint +++ b/src/ui/gui/netplay_join.slint @@ -1,4 +1,4 @@ -import { VerticalBox, LineEdit, StandardTableView, HorizontalBox, ComboBox, Button } from "std-widgets.slint"; +import { VerticalBox, LineEdit, StandardTableView, HorizontalBox, ComboBox, Button, ScrollView } from "std-widgets.slint"; import { NetplayData } from "netplay_page.slint"; export component NetplayJoin inherits Window { @@ -22,116 +22,129 @@ export component NetplayJoin inherits Window { callback select_rom(string); callback join_session(string, string, string, string, int); preferred-width: 700px; + preferred-height: 450px; VerticalBox { - HorizontalBox { + vertical-stretch: 1; + padding-left: root.safe-area-insets.left; + padding-top: root.safe-area-insets.top; + padding-right: root.safe-area-insets.right; + padding-bottom: root.safe-area-insets.bottom; + ScrollView { + mouse-drag-pan-enabled: true; + vertical-stretch: 1; VerticalBox { - Text { - text: @tr("Player Name (required):"); - } + alignment: start; + HorizontalBox { + VerticalBox { + Text { + text: @tr("Player Name (required):"); + } - LineEdit { - placeholder-text: @tr("Enter player name"); - edited(text) => { - NetplayData.player_name = text; + LineEdit { + placeholder-text: @tr("Enter player name"); + edited(text) => { + NetplayData.player_name = text; + } + } + } + + VerticalBox { + Text { + text: @tr("Custom Server URL (optional):"); + } + + LineEdit { + placeholder-text: "example.com:45000"; + text: NetplayData.custom_server_url; + edited(text) => { + NetplayData.custom_server_url = text; + } + } } } - } - VerticalBox { - Text { - text: @tr("Custom Server URL (optional):"); + if NetplayData.pending_refresh: Text { + text: @tr("Refreshing session list, please wait..."); + horizontal-alignment: center; + vertical-alignment: center; } - - LineEdit { - placeholder-text: "example.com:45000"; - text: NetplayData.custom_server_url; - edited(text) => { - NetplayData.custom_server_url = text; + if !NetplayData.pending_refresh && NetplayData.sessions.length > 0: Text { + text: @tr("Click on a session below to select it"); + horizontal-alignment: center; + vertical-alignment: center; + } + if !NetplayData.pending_refresh && NetplayData.sessions.length == 0: Text { + text: @tr("No sessions available. Please refresh to check again."); + horizontal-alignment: center; + vertical-alignment: center; + } + StandardTableView { + columns: [ + { title: @tr("Server") }, + { title: @tr("Session Name") }, + { title: @tr("Game Name") }, + { title: @tr("Password") }, + { title: @tr("Cheats") } + ]; + rows: NetplayData.sessions; + current-row: NetplayData.current_session; + current-row-changed(current-row) => { + NetplayData.current_session = current-row; } } - } - } - if NetplayData.pending_refresh: Text { - text: @tr("Refreshing session list, please wait..."); - horizontal-alignment: center; - vertical-alignment: center; - } - if !NetplayData.pending_refresh && NetplayData.sessions.length > 0: Text { - text: @tr("Click on a session below to select it"); - horizontal-alignment: center; - vertical-alignment: center; - } - if !NetplayData.pending_refresh && NetplayData.sessions.length == 0: Text { - text: @tr("No sessions available. Please refresh to check again."); - horizontal-alignment: center; - vertical-alignment: center; - } - StandardTableView { - columns: [ - { title: @tr("Server") }, - { title: @tr("Session Name") }, - { title: @tr("Game Name") }, - { title: @tr("Password") }, - { title: @tr("Cheats") } - ]; - rows: NetplayData.sessions; - current-row: NetplayData.current_session; - current-row-changed(current-row) => { - NetplayData.current_session = current-row; - } - } + HorizontalBox { + Rectangle { } - HorizontalBox { - Rectangle { } - - Button { - enabled: !NetplayData.pending_refresh; - text: @tr("Refresh Session List"); - clicked => { - NetplayData.pending_refresh = true; - NetplayData.current_session = -1; - NetplayData.sessions = []; - NetplayData.room_urls = []; - NetplayData.room_ports = []; - refresh_session(); + Button { + enabled: !NetplayData.pending_refresh; + text: @tr("Refresh Session List"); + clicked => { + NetplayData.pending_refresh = true; + NetplayData.current_session = -1; + NetplayData.sessions = []; + NetplayData.room_urls = []; + NetplayData.room_ports = []; + refresh_session(); + } + } } - } - } - HorizontalBox { - LineEdit { - placeholder-text: @tr("Password (if required)"); - edited(text) => { - NetplayData.password = text; - } - } + HorizontalBox { + LineEdit { + placeholder-text: @tr("Password (if required)"); + edited(text) => { + NetplayData.password = text; + } + } - if NetplayData.game_name == "": Button { - text: @tr("Select ROM"); - clicked => { - select_rom(NetplayData.rom_dir); - } - } - if NetplayData.game_name != "": Button { - text: NetplayData.game_name; - clicked => { - select_rom(NetplayData.rom_dir); - } - } + if NetplayData.game_name == "": Button { + text: @tr("Select ROM"); + clicked => { + select_rom(NetplayData.rom_dir); + } + } + if NetplayData.game_name != "": Button { + text: NetplayData.game_name; + clicked => { + select_rom(NetplayData.rom_dir); + } + } - Button { - text: @tr("Join Session"); - enabled: NetplayData.player_name != "" && NetplayData.current_session >= 0 && NetplayData.game_name != "" && !NetplayData.pending_session; - clicked => { - NetplayData.pending_session = true; - join_session( - NetplayData.player_name, - NetplayData.game_hash, - NetplayData.password, - NetplayData.room_urls[NetplayData.current_session], - NetplayData.room_ports[NetplayData.current_session]); + Button { + text: @tr("Join Session"); + enabled: NetplayData.player_name != "" && NetplayData.current_session >= 0 && NetplayData.game_name != "" && !NetplayData.pending_session; + clicked => { + NetplayData.pending_session = true; + join_session( + NetplayData.player_name, + NetplayData.game_hash, + NetplayData.password, + NetplayData.room_urls[NetplayData.current_session], + NetplayData.room_ports[NetplayData.current_session]); + } + } } } } diff --git a/src/ui/gui/netplay_page.slint b/src/ui/gui/netplay_page.slint index fb28dd49..0c337032 100644 --- a/src/ui/gui/netplay_page.slint +++ b/src/ui/gui/netplay_page.slint @@ -82,12 +82,22 @@ export component CustomNetplayServer inherits Dialog { title: @tr("Custom Netplay Server"); preferred-width: 400px; callback ok_clicked(string); - server_url := LineEdit { - text: NetplayData.custom_server_url; - placeholder-text: "example.com:45000"; + VerticalBox { + alignment: start; + vertical-stretch: 1; + padding-left: root.safe-area-insets.left; + padding-top: root.safe-area-insets.top; + padding-right: root.safe-area-insets.right; + padding-bottom: root.safe-area-insets.bottom; + server_url := LineEdit { + vertical-stretch: 0; + text: NetplayData.custom_server_url; + placeholder-text: "example.com:45000"; + } } StandardButton { + vertical-stretch: 0; kind: ok; clicked => { NetplayData.custom_server_url = server_url.text; diff --git a/src/ui/gui/netplay_wait.slint b/src/ui/gui/netplay_wait.slint index a227d50e..a39d7e00 100644 --- a/src/ui/gui/netplay_wait.slint +++ b/src/ui/gui/netplay_wait.slint @@ -1,4 +1,4 @@ -import { VerticalBox, HorizontalBox, TextEdit, LineEdit, Button, GridBox } from "std-widgets.slint"; +import { VerticalBox, HorizontalBox, TextEdit, LineEdit, Button, GridBox, ScrollView } from "std-widgets.slint"; import { NetplayData } from "netplay_page.slint"; export global NetplayWaitData { @@ -12,8 +12,8 @@ export global NetplayWaitData { export component NetplayWait inherits Window { title: @tr("Netplay: Waiting Room"); - preferred-width: 400px; - preferred-height: 400px; + preferred-width: 500px; + preferred-height: 450px; in-out property players <=> NetplayWaitData.players; in-out property session_name <=> NetplayData.session_name; in-out property game_name <=> NetplayData.game_name; @@ -27,83 +27,99 @@ export component NetplayWait inherits Window { callback begin_game; VerticalBox { - Text { - text: @tr("Session Name:") + " " + NetplayData.session_name; - font-size: 15px; - horizontal-alignment: center; - } - - Text { - text: @tr("Game Name:") + " " + NetplayData.game_name; - font-size: 15px; - horizontal-alignment: center; - } - - Text { - text: @tr("Ping:") + " " + NetplayWaitData.ping; - horizontal-alignment: center; - } - - GridBox { - Row { + vertical-stretch: 1; + padding-left: root.safe-area-insets.left; + padding-top: root.safe-area-insets.top; + padding-right: root.safe-area-insets.right; + padding-bottom: root.safe-area-insets.bottom; + ScrollView { + mouse-drag-pan-enabled: true; + vertical-stretch: 1; + VerticalBox { + alignment: start; Text { - text: @tr("Player 1:") + " " + players[0]; + text: @tr("Session Name:") + " " + NetplayData.session_name; + font-size: 15px; + horizontal-alignment: center; } Text { - text: @tr("Player 2:") + " " + players[1]; - } - } - - Row { - Text { - text: @tr("Player 3:") + " " + players[2]; + text: @tr("Game Name:") + " " + NetplayData.game_name; + font-size: 15px; + horizontal-alignment: center; } Text { - text: @tr("Player 4:") + " " + players[3]; + text: @tr("Ping:") + " " + NetplayWaitData.ping; + horizontal-alignment: center; } - } - } - TextEdit { - read-only: true; - text: NetplayWaitData.chat_text; - } + GridBox { + Row { + Text { + text: @tr("Player 1:") + " " + players[0]; + } - HorizontalBox { - chat_message := LineEdit { - placeholder-text: @tr("Enter chat message"); - key-released(event) => { - if (event.text == Key.Return && chat_message.text != "") { - send_chat_message(chat_message.text); - chat_message.text = ""; + Text { + text: @tr("Player 2:") + " " + players[1]; + } + } + + Row { + Text { + text: @tr("Player 3:") + " " + players[2]; + } + + Text { + text: @tr("Player 4:") + " " + players[3]; + } } - accept } - } - Button { - text: @tr("Send Message"); - enabled: chat_message.text != ""; - clicked => { - send_chat_message(chat_message.text); - chat_message.text = ""; + TextEdit { + read-only: true; + min-height: 120px; + text: NetplayWaitData.chat_text; } - } - } - Text { - text: NetplayWaitData.motd; - wrap: word-wrap; - } + HorizontalBox { + chat_message := LineEdit { + placeholder-text: @tr("Enter chat message"); + key-released(event) => { + if (event.text == Key.Return && chat_message.text != "") { + send_chat_message(chat_message.text); + chat_message.text = ""; + } + accept + } + } - Button { - text: @tr("Start Game"); - enabled: NetplayWaitData.can_start; - clicked => { - NetplayWaitData.can_start = false; - begin_game(); + Button { + text: @tr("Send Message"); + enabled: chat_message.text != ""; + clicked => { + send_chat_message(chat_message.text); + chat_message.text = ""; + } + } + } + + Text { + text: NetplayWaitData.motd; + wrap: word-wrap; + } + + Button { + text: @tr("Start Game"); + enabled: NetplayWaitData.can_start; + clicked => { + NetplayWaitData.can_start = false; + begin_game(); + } + } + Rectangle { + vertical-stretch: 0; + } } } } diff --git a/src/ui/gui/retroachievements_page.slint b/src/ui/gui/retroachievements_page.slint index 8ca492c8..37de87df 100644 --- a/src/ui/gui/retroachievements_page.slint +++ b/src/ui/gui/retroachievements_page.slint @@ -108,7 +108,7 @@ export component RetroAchievements inherits Page { edited(text) => { RAData.ra_username = text; } - + } password_widget := LineEdit { enabled: RAData.enabled; diff --git a/src/ui/gui/side_bar.slint b/src/ui/gui/side_bar.slint index cade4540..c2f9887c 100644 --- a/src/ui/gui/side_bar.slint +++ b/src/ui/gui/side_bar.slint @@ -46,20 +46,20 @@ component SideBarButton inherits Rectangle { } states [ - selected when root.selected: { - highlight.opacity: 1; - highlight.background: Palette.accent-background; - icon-display.colorize: Palette.accent-foreground; - } - pressed when touch.pressed && !root.selected: { - highlight.opacity: 0.55; - } - hover when touch.has-hover && !root.selected: { - highlight.opacity: 0.4; - } - focused when root.has-focus && !root.selected: { - highlight.opacity: 0.4; - } + selected when root.selected: { + highlight.opacity: 1; + highlight.background: Palette.accent-background; + icon-display.colorize: Palette.accent-foreground; + } + pressed when touch.pressed && !root.selected: { + highlight.opacity: 0.55; + } + hover when touch.has-hover && !root.selected: { + highlight.opacity: 0.4; + } + focused when root.has-focus && !root.selected: { + highlight.opacity: 0.4; + } ] }