RouteMain.vue shows the two-step stepper whenever serverData is empty, which is every launch. ServerConnectDialog.vue hardcodes the Hivecom WebSocket URL, serverConnect in stores/irc.ts joins #orbit/testing unconditionally, and stores/user.ts keeps one global nick and account pair in localStorage. The layout that lib/windows.ts mirrors to localStorage includes a numeric server id that meant nothing on the next launch; the servers ticket makes those ids stable. The irc store's init already iterates controller.servers and reads each state, so the load path exists. It has just never had anything to load. Channel messages come back from the database on GetChannelState (core-shared/src/handlers.rs), so once a channel is rejoined its scrollback is already there.
Give each saved server a connection state in the irc store (saved, connecting, connected, failed). On init, connect every server flagged auto-connect, sign in with its saved identity mode, and rejoin its persisted channels. The hardcoded join goes away. A server with no channels opens the chat picker from #72. RouteMain skips the stepper when saved servers exist and goes straight to the window manager. The sidebar lists saved servers with their state and offers connect on the ones that didn't auto-connect. The restored layout resolves against stable ids, so the chat window reopens the same server and channel. The global names in user.ts move into the per-server identity record. A saved server whose identity is a SASL account prompts for the password until #63 provides tokens; it must not silently fall back to anonymous.
Spec
Acceptance criteria
- Reloading with one saved auto-connect server shows no stepper; the app opens the window manager, connects, and rejoins its channels with no input
- A saved server with auto-connect off shows disconnected in the sidebar and connects on click
- A failed startup connect marks that server failed and the others still connect
- The persisted layout reopens the same server and channel after reload
- A saved SASL identity prompts for credentials instead of connecting anonymously
- No hardcoded channel join remains in the irc store
Out of scope
Blocked by the servers store ticket in this epic. #89's remembered-servers path is delivered here, so #89 should take a blocked-by on this ticket and drop that criterion.
RouteMain.vue shows the two-step stepper whenever serverData is empty, which is every launch. ServerConnectDialog.vue hardcodes the Hivecom WebSocket URL, serverConnect in stores/irc.ts joins #orbit/testing unconditionally, and stores/user.ts keeps one global nick and account pair in localStorage. The layout that lib/windows.ts mirrors to localStorage includes a numeric server id that meant nothing on the next launch; the servers ticket makes those ids stable. The irc store's init already iterates controller.servers and reads each state, so the load path exists. It has just never had anything to load. Channel messages come back from the database on GetChannelState (core-shared/src/handlers.rs), so once a channel is rejoined its scrollback is already there.
Give each saved server a connection state in the irc store (saved, connecting, connected, failed). On init, connect every server flagged auto-connect, sign in with its saved identity mode, and rejoin its persisted channels. The hardcoded join goes away. A server with no channels opens the chat picker from #72. RouteMain skips the stepper when saved servers exist and goes straight to the window manager. The sidebar lists saved servers with their state and offers connect on the ones that didn't auto-connect. The restored layout resolves against stable ids, so the chat window reopens the same server and channel. The global names in user.ts move into the per-server identity record. A saved server whose identity is a SASL account prompts for the password until #63 provides tokens; it must not silently fall back to anonymous.
Spec
Acceptance criteria
Out of scope
Blocked by the servers store ticket in this epic. #89's remembered-servers path is delivered here, so #89 should take a blocked-by on this ticket and drop that criterion.