diff --git a/src/ui/gui/netplay_create.slint b/src/ui/gui/netplay_create.slint index 14df865..3e61aff 100644 --- a/src/ui/gui/netplay_create.slint +++ b/src/ui/gui/netplay_create.slint @@ -16,6 +16,7 @@ export component NetplayCreate inherits Page { title: @tr("Netplay: Create Session"); callback select_rom(string); callback create_session(string, string, string, string, string, string, bool, bool); + callback resume_session(string); callback close; VerticalBox { @@ -113,6 +114,14 @@ export component NetplayCreate inherits Page { } } + Button { + text: @tr("Resume Session…"); + enabled: !NetplayData.pending_session; + clicked => { + resume_session(SettingsData.rom_dir); + } + } + Button { text: @tr("Cancel"); clicked => { diff --git a/src/ui/gui/netplay_page.slint b/src/ui/gui/netplay_page.slint index 678b2cc..364b876 100644 --- a/src/ui/gui/netplay_page.slint +++ b/src/ui/gui/netplay_page.slint @@ -27,6 +27,7 @@ export global NetplayData { in-out property show_wait_session; in-out property show_create_session; in-out property show_join_session; + in-out property resyncing; } export component Netplay inherits Page { diff --git a/src/ui/gui/netplay_wait.slint b/src/ui/gui/netplay_wait.slint index bb7159e..d7f787b 100644 --- a/src/ui/gui/netplay_wait.slint +++ b/src/ui/gui/netplay_wait.slint @@ -21,12 +21,15 @@ export global NetplayWaitData { in-out property recommended_delay; in-out property game_pal; in-out property connected_peers_count; + in-out property is_host; + in-out property resyncing; } export component NetplayWait inherits Page { title: @tr("Netplay: Waiting Room"); callback send_chat_message(string); callback begin_game(int); + callback save_session; callback close; VerticalBox { alignment: start; @@ -143,6 +146,14 @@ export component NetplayWait inherits Page { } } + if NetplayWaitData.is_host: Button { + text: @tr("Save Session"); + enabled: NetplayWaitData.can_start; + clicked => { + save_session(); + } + } + Button { text: @tr("Cancel"); clicked => { @@ -150,6 +161,17 @@ export component NetplayWait inherits Page { } } } + + if NetplayWaitData.resyncing: Rectangle { + background: #ffaa00; + height: 24px; + Text { + text: @tr("Resyncing…"); + horizontal-alignment: center; + vertical-alignment: center; + color: white; + } + } } } } diff --git a/src/ui/netplay.rs b/src/ui/netplay.rs index 2519c4b..4646fd6 100644 --- a/src/ui/netplay.rs +++ b/src/ui/netplay.rs @@ -271,6 +271,48 @@ fn setup_callbacks( app.on_netplay_feedback_button_clicked(move || { open_uri("https://github.com/gopher64/gopher64/discussions/453"); }); + + // Resume Session: open a file picker for .netplay-state files + let weak_app = app.as_weak(); + app.on_netplay_resume_session(move |rom_dir| { + let weak_app = weak_app.clone(); + tokio::spawn(async move { + if let Some(file) = rfd::AsyncFilePicker::new() + .add_filter("Netplay State", &["netplay-state"]) + .set_directory(rom_dir) + .pick_file() + .await + { + eprintln!("resume session from: {}", file.display()); + // TODO: #3 — load the netplay session state from the file and + // re-establish the connection. For now, just show a message. + weak_app + .upgrade_in_event_loop(|handle| { + ui::video::onscreen_message( + "Resume session not yet implemented (#3)", + ui::video::MESSAGE_LENGTH_MESSAGE_SHORT, + ); + let _ = handle; + }) + .ok(); + } + }); + }); + + // Save Session: host-only, triggers the save flow from #3 + let weak_app = app.as_weak(); + app.on_netplay_save_session(move || { + eprintln!("save session requested"); + weak_app + .upgrade_in_event_loop(|handle| { + ui::video::onscreen_message( + "Save session not yet implemented (#3)", + ui::video::MESSAGE_LENGTH_MESSAGE_SHORT, + ); + let _ = handle; + }) + .ok(); + }); } fn close_connections( @@ -751,6 +793,12 @@ fn setup_wait_window( app.set_netplay_game_name(game_name); app.set_netplay_rom_path(rom_path); app.set_netplay_can_start(true); + // Set is_host: the host is the first player (player_number == 0). + // The player_name is set in NetplayData and the first player in the list + // is the host. This is determined when the session is created. + app.set_netplay_is_host( + app.get_netplay_player_name() == app.get_netplay_players().iter().next().map(|s| s.to_string()).unwrap_or_default().as_str() + ); let request_update = NetplayLobbyMessage { message_type: MessageType::RequestUpdateSession,