diff --git a/src/ui/gui/appwindow.slint b/src/ui/gui/appwindow.slint index 7c24360..6718b99 100644 --- a/src/ui/gui/appwindow.slint +++ b/src/ui/gui/appwindow.slint @@ -14,6 +14,7 @@ export { VruDialog } from "vru_dialog.slint"; export { NetplayCreate } from "netplay_create.slint"; export { NetplayJoin } from "netplay_join.slint"; export { NetplayWait } from "netplay_wait.slint"; +export { CustomNetplayServer } from "netplay_page.slint"; export component AppWindow inherits Window { callback wiki_button_clicked; diff --git a/src/ui/gui/netplay_create.slint b/src/ui/gui/netplay_create.slint index 7bea0a2..7fa4a64 100644 --- a/src/ui/gui/netplay_create.slint +++ b/src/ui/gui/netplay_create.slint @@ -5,6 +5,7 @@ export component NetplayCreate inherits Window { title: @tr("Netplay: Create Session"); 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; in-out property ping <=> NetplayData.ping; in-out property game_name <=> NetplayData.game_name; in-out property game_hash <=> NetplayData.game_hash; @@ -14,6 +15,7 @@ export component NetplayCreate inherits Window { in-out property peer_addr <=> NetplayData.peer_addr; in-out property rom_dir <=> NetplayData.rom_dir; callback get_ping(string); + callback get_custom_url(); callback select_rom(string); callback create_session(string, string, string, string, string, string, string); @@ -69,7 +71,11 @@ export component NetplayCreate inherits Window { model: NetplayData.server_names; selected => { if (self.current-index >= 0) { - get_ping(NetplayData.server_urls[self.current-index]); + if (self.current-value == "Custom") { + get_custom_url(); + } else { + get_ping(NetplayData.server_urls[self.current-index]); + } } } } @@ -102,12 +108,18 @@ export component NetplayCreate inherits Window { 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( - NetplayData.server_urls[server.current-index], + server_url, NetplayData.session_name, NetplayData.player_name, NetplayData.game_name, diff --git a/src/ui/gui/netplay_join.slint b/src/ui/gui/netplay_join.slint index c372416..d7fd8a4 100644 --- a/src/ui/gui/netplay_join.slint +++ b/src/ui/gui/netplay_join.slint @@ -5,6 +5,7 @@ export component NetplayJoin inherits Window { title: @tr("Netplay: Join Session"); 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; in-out property ping <=> NetplayData.ping; in-out property sessions <=> NetplayData.sessions; in-out property current_session <=> NetplayData.current_session; @@ -17,6 +18,7 @@ export component NetplayJoin inherits Window { in-out property rom_path <=> NetplayData.rom_path; in-out property rom_dir <=> NetplayData.rom_dir; callback get_ping(string); + callback get_custom_url(); callback refresh_session(string); callback select_rom(string); callback join_session(string, string, string, int); @@ -46,7 +48,11 @@ export component NetplayJoin inherits Window { model: NetplayData.server_names; selected => { if (self.current-index >= 0) { - get_ping(NetplayData.server_urls[self.current-index]); + if (self.current-value == "Custom") { + get_custom_url(); + } else { + get_ping(NetplayData.server_urls[self.current-index]); + } } } } @@ -89,7 +95,11 @@ export component NetplayJoin inherits Window { Button { text: @tr("Refresh Session List"); clicked => { - refresh_session(NetplayData.server_urls[server.current-index]); + if (server.current-value == "Custom") { + refresh_session("ws://" + NetplayData.custom_server_url); + } else { + refresh_session(NetplayData.server_urls[server.current-index]); + } } } } diff --git a/src/ui/gui/netplay_page.slint b/src/ui/gui/netplay_page.slint index 32ae732..b742a25 100644 --- a/src/ui/gui/netplay_page.slint +++ b/src/ui/gui/netplay_page.slint @@ -1,7 +1,7 @@ // Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT -import { VerticalBox, HorizontalBox, Button } from "std-widgets.slint"; +import { StandardButton, VerticalBox, HorizontalBox, Button, LineEdit } from "std-widgets.slint"; import { Page } from "page.slint"; export global NetplayData { @@ -21,6 +21,7 @@ export global NetplayData { in-out property <[int]> ports; in-out property current_session: -1; in-out property rom_dir; + in-out property custom_server_url; } export component Netplay inherits Page { @@ -74,3 +75,22 @@ export component Netplay inherits Page { } } } + +export component CustomNetplayServer inherits Dialog { + in-out property custom_server_url <=> NetplayData.custom_server_url; + 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"; + } + + StandardButton { + kind: ok; + clicked => { + NetplayData.custom_server_url = server_url.text; + ok_clicked(NetplayData.custom_server_url); + } + } +} diff --git a/src/ui/netplay.rs b/src/ui/netplay.rs index 0b67bc7..d9ad9f9 100644 --- a/src/ui/netplay.rs +++ b/src/ui/netplay.rs @@ -1,8 +1,8 @@ use crate::device; use crate::ui; use crate::ui::gui::{ - AppWindow, ErrorDialog, GameSettings, GbPaths, NetplayCreate, NetplayDevice, NetplayJoin, - NetplayWait, VruChannel, run_rom, save_settings, + AppWindow, CustomNetplayServer, ErrorDialog, GameSettings, GbPaths, NetplayCreate, + NetplayDevice, NetplayJoin, NetplayWait, VruChannel, run_rom, save_settings, }; use futures::{SinkExt, StreamExt}; use sha2::{Digest, Sha256}; @@ -56,6 +56,8 @@ trait NetplayPages { fn refresh_sessions(&self, _server: slint::SharedString) { // Default implementation does nothing } + fn invoke_get_ping(&self, server_url: slint::SharedString); + fn set_custom_server_url(&self, server_url: slint::SharedString); } impl NetplayPages for NetplayCreate { @@ -83,6 +85,12 @@ impl NetplayPages for NetplayCreate { fn set_peer_addr(&self, peer_addr: slint::SharedString) { self.set_peer_addr(peer_addr); } + fn invoke_get_ping(&self, server_url: slint::SharedString) { + self.invoke_get_ping(server_url); + } + fn set_custom_server_url(&self, server_url: slint::SharedString) { + self.set_custom_server_url(server_url); + } } impl NetplayPages for NetplayJoin { @@ -113,6 +121,12 @@ impl NetplayPages for NetplayJoin { fn set_peer_addr(&self, peer_addr: slint::SharedString) { self.set_peer_addr(peer_addr); } + fn invoke_get_ping(&self, server_url: slint::SharedString) { + self.invoke_get_ping(server_url); + } + fn set_custom_server_url(&self, server_url: slint::SharedString) { + self.set_custom_server_url(server_url); + } } fn populate_server_names(weak: slint::Weak) { @@ -159,6 +173,7 @@ fn populate_server_names(weak: slin server_names.push(server.0.into()); server_urls.push(server.1.into()); } + server_names.push("Custom".into()); update_ping(weak2, server_urls.row_data(0).unwrap().into()); handle.refresh_sessions(server_urls.row_data(0).unwrap()); let server_names_model: std::rc::Rc> = @@ -260,6 +275,25 @@ fn update_ping( }); } +fn show_custom_url_dialog( + weak: slint::Weak, + server_url: slint::SharedString, +) { + let url_dialog = CustomNetplayServer::new().unwrap(); + url_dialog.set_custom_server_url(server_url); + let weak_dialog = url_dialog.as_weak(); + url_dialog.on_ok_clicked(move |server_url| { + weak.upgrade_in_event_loop(move |handle| { + handle.set_custom_server_url(server_url.clone()); + let prefix: slint::SharedString = "ws://".into(); + handle.invoke_get_ping(prefix + &server_url); + }) + .unwrap(); + weak_dialog.unwrap().window().hide().unwrap(); + }); + url_dialog.show().unwrap(); +} + pub fn setup_create_window( create_window: &NetplayCreate, game_settings: GameSettings, @@ -283,6 +317,15 @@ pub fn setup_create_window( update_ping(weak.clone(), server_url.to_string()); }); let weak = create_window.as_weak(); + create_window.on_get_custom_url(move || { + let weak2 = weak.clone(); + weak.upgrade_in_event_loop(move |handle| { + handle.set_ping("Ping: Unknown".into()); + show_custom_url_dialog(weak2, handle.get_custom_server_url()); + }) + .unwrap(); + }); + let weak = create_window.as_weak(); create_window.on_select_rom(move |rom_dir| { select_rom(weak.clone(), rom_dir); }); @@ -974,6 +1017,15 @@ pub fn setup_join_window( .unwrap(); }); let weak = join_window.as_weak(); + join_window.on_get_custom_url(move || { + let weak2 = weak.clone(); + weak.upgrade_in_event_loop(move |handle| { + handle.set_ping("Ping: Unknown".into()); + show_custom_url_dialog(weak2, handle.get_custom_server_url()); + }) + .unwrap(); + }); + let weak = join_window.as_weak(); join_window.on_select_rom(move |rom_dir| { select_rom(weak.clone(), rom_dir); });