Skip to content

Surface soju-bouncer networks via an in-console onboarding banner - #26

Merged
buggerman merged 2 commits into
mainfrom
bouncer-onboarding-banner
Apr 25, 2026
Merged

Surface soju-bouncer networks via an in-console onboarding banner#26
buggerman merged 2 commits into
mainfrom
bouncer-onboarding-banner

Conversation

@buggerman

Copy link
Copy Markdown
Owner

Summary

  • Soju-bouncer discovery (Discover soju bouncer networks (Layer 2A, read-only) #14, BOUNCER BIND per-network Servers (Layer 2B) #18) currently surfaces only as a 9-pt chip next to the server name in the sidebar — easy to miss. Users connecting to a soju bouncer for the first time often don't realize they can chat on the upstream networks at all.
  • Add an in-console onboarding banner that shows above the server message buffer when the bouncer has advertised networks and the user hasn't engaged with them yet. Lists each network with the existing "Add as server" button, plus a "Dismiss" button that hides the banner permanently (per server).
  • Banner self-hides when the user adds any advertised network — once they've engaged with the feature, the banner is moot. Pure additive UX; no model changes, no migrations.

Changes

  • Sources/BryggaCore/PreferencesKeys.swift — new bouncerOnboardingDismissedPrefix constant for the per-server dismissal flag (UserDefaults key suffix is server.id).
  • Sources/Brygga/Views/ContentView.swift:
    • Extracted BouncerNetworkRow (file-private) from BouncerNetworksPopover so the popover and banner share row markup. Added an optional onAdd callback so the popover can dismiss itself while the banner stays mounted.
    • New BouncerOnboardingBanner(server:). Visible iff (a) server.bouncerNetworks non-empty, (b) per-server dismissed flag is false, (c) no sibling Server already has bouncerNetID matching one of the advertised networks. Uses @AppStorage with a runtime key built from bouncerOnboardingDismissedPrefix + server.id.
    • ServerMessageList now wraps its MessageBufferView in a VStack and mounts the banner above it.

Test plan

  • swift build — passes
  • swift test — 115 tests pass (no test changes; banner is UI-only and matches the precedent of HistoryHeaderView from Surface CHATHISTORY at the top of the channel buffer #21)
  • swiftformat --lint . — clean
  • Manual:
    • Connect to a soju bouncer that advertises BOUNCER LISTNETWORKS and you haven't bound any networks yet — open the server console (server row in the sidebar). Banner appears with the network list and Add buttons.
    • Click "Add as server" on one network. The new sibling Server appears in the sidebar; the banner self-hides on the parent server (because there's now an added bouncer-bound sibling).
    • Repeat with a fresh bouncer where you press "Dismiss" instead. Banner disappears immediately and stays gone after restarting the app.
    • Connect to a vanilla (non-bouncer) IRC server. No banner appears.
    • Existing sidebar chip-and-popover flow still works unchanged.

Risk / rollback

  • No model, persistence-schema, or networking changes. Only adds: one UserDefaults key prefix, one private SwiftUI view, one extracted-and-renamed private row view.
  • Per-server dismissal lives in UserDefaults under a documented key shape; can be cleared via defaults delete <bundle> for testing or rollback.
  • Revert: this single commit.

@buggerman
buggerman merged commit 617839e into main Apr 25, 2026
1 check passed
@buggerman
buggerman deleted the bouncer-onboarding-banner branch April 25, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant