From a5ea79739783682c46983d5b67b2b4b7b5338ccb Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 1 Nov 2026 21:24:48 +0100 Subject: v4.2.1: plain-language game copy and a balance fetch on login The lobby and every game screen now speak to a player, not an operator: each game has one how-to sentence, and the table headers, limits, RTP, paytable and server-timing notes are gone. The account and balance are fetched whenever a session signs in, including stored-credential auto-login, so the header is filled before the lobby appears. --- gui/src/app.rs | 79 ++++++++++++++++++++++------------------------------------ 1 file changed, 30 insertions(+), 49 deletions(-) (limited to 'gui/src/app.rs') diff --git a/gui/src/app.rs b/gui/src/app.rs index f0efd3e..af64e5e 100644 --- a/gui/src/app.rs +++ b/gui/src/app.rs @@ -49,6 +49,7 @@ pub struct ZaganApp { notices: VecDeque, awaiting: Option, need_info: bool, + was_logged_in: bool, pending_login: Option<(String, String)>, /// Displayed balance while a result animation runs: stake deducted, no /// winnings yet. The view already knows the outcome; the player must not. @@ -62,7 +63,6 @@ struct Session { host: String, fingerprint: Option, ping_ms: f32, - server_version: String, latest: String, url: String, user: Option, @@ -186,6 +186,7 @@ impl ZaganApp { notices: VecDeque::new(), awaiting: None, need_info: false, + was_logged_in: false, pending_login: None, balance_hold: None, balance: None, @@ -348,7 +349,7 @@ impl ZaganApp { reply, }); } - Event::Connected(connected) => self.connected(ctx, connected), + Event::Connected(connected) => self.connected(connected), Event::Failed { addr, failure, @@ -376,7 +377,7 @@ impl ZaganApp { } } - fn connected(&mut self, ctx: &Context, connected: Connected) { + fn connected(&mut self, connected: Connected) { self.connect.pending = false; self.connect.error = None; self.core.set_connected(true); @@ -393,19 +394,14 @@ impl ZaganApp { host: connected.addr, fingerprint: connected.fingerprint, ping_ms: connected.elapsed_ms, - server_version: connected.server_version, latest: connected.latest, url: connected.url, user: connected.user, }); - self.need_info = self.session.as_ref().is_some_and(|s| s.user.is_some()); + self.need_info = false; + self.was_logged_in = false; self.account = None; - if self.need_info { - let effects = self.core.command(Command::Info); - self.apply(ctx, effects); - self.need_info = false; - } } fn failed(&mut self, addr: String, failure: Failure, message: String) { @@ -511,7 +507,6 @@ impl ZaganApp { let command = if registering { Command::Register { user, credential } } else { - self.need_info = true; if self.login.remember { self.pending_login = Some((user.clone(), credential.clone())); } @@ -522,19 +517,26 @@ impl ZaganApp { } fn tick(&mut self, ctx: &Context) { - // Request deadline, mirroring the terminal's socket timeout. - if self.need_info - && self - .session - .as_ref() - .is_some_and(|session| session.user.is_some()) - && self.account.is_none() - { + // Fetch the account and balance once each time a session signs in. + let signed_in = self + .core + .view() + .as_ref() + .is_some_and(|view| matches!(view, View::Lobby(lobby) if lobby.user.is_some())); + if signed_in != self.was_logged_in { + self.was_logged_in = signed_in; + if signed_in { + self.need_info = true; + } + } + if self.need_info && signed_in { let effects = self.core.command(Command::Info); self.apply(ctx, effects); self.need_info = false; } + // Request deadline, mirroring the terminal's socket timeout. + if let Some(sent) = self.awaiting { if sent.elapsed() > REQUEST_TIMEOUT { self.awaiting = None; @@ -1351,13 +1353,7 @@ fn lobby_screen(ui: &mut Ui, app: &mut ZaganApp, lobby: &LobbyView) { ui.add_space(theme::SPACE_2); ui.horizontal(|ui| { if let Some(session) = &app.session { - widgets::note( - ui, - &format!( - "Signed in to {} · server v{}", - session.host, session.server_version - ), - ); + widgets::note(ui, &format!("Signed in to {}", session.host)); } ui.with_layout(Layout::right_to_left(Align::Center), |ui| { if widgets::ghost(ui, "Forget saved login") { @@ -1396,15 +1392,9 @@ fn game_card(ui: &mut Ui, app: &mut ZaganApp, key: &str, name: &str) { .font(theme::sans(22.0)) .color(theme::TEXT), ); - ui.add_space(2.0); - widgets::note(ui, tagline(key)); ui.add_space(theme::SPACE_1); - ui.label( - RichText::new(meta(key)) - .font(theme::mono(10.0)) - .color(theme::TEXT_FAINT), - ); - ui.add_space(theme::SPACE_3); + widgets::note(ui, how_to(key)); + ui.add_space(theme::SPACE_4); if widgets::primary(ui, "PLAY", true, 110.0, 36.0) { let effects = app.core.command(Command::Play { game: key.to_string(), @@ -1415,22 +1405,13 @@ fn game_card(ui: &mut Ui, app: &mut ZaganApp, key: &str, name: &str) { }); } -fn tagline(game: &str) -> &'static str { - match game { - "slots" => "Five reels, five paylines, one lever.", - "roulette" => "The European wheel, thirty-seven pockets.", - "blackjack" => "Six decks, dealer stands on seventeen. Pays 3:2.", - "crash" => "The multiplier rises. Cash out before it busts.", - _ => "", - } -} - -fn meta(game: &str) -> &'static str { +/// One plain sentence: how to play, not the house's rules sheet. +fn how_to(game: &str) -> &'static str { match game { - "slots" => "MIN 10 KR · RTP 96%", - "roulette" => "MIN 10 KR · SINGLE ZERO", - "blackjack" => "MIN 10 KR · S17 · 3:2", - "crash" => "MIN 10 KR · 1% EDGE", + "slots" => "Spin the reels. Three or more matching symbols from the left win.", + "roulette" => "Put chips on the table, then spin. Straight numbers pay the most.", + "blackjack" => "Get closer to 21 than the dealer without going over.", + "crash" => "Start the round, then cash out before the multiplier crashes.", _ => "", } } -- cgit v1.2.3