File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ ---
2+ " sideshow " : patch
3+ ---
4+
5+ Fix blank page when opening a post permalink (` /p/:id ` ) on a
6+ ` publicRead="session" ` workspace without authentication. The SSE connection
7+ fired before the viewer discovered the post's session ID, hitting ` /api/events `
8+ without the required ` ?session= ` param and getting a 401. The connection is now
9+ deferred until after the initial post fetch resolves.
Original file line number Diff line number Diff line change 66 initialPageTitle ,
77 isReadonly ,
88 layoutMode ,
9+ publicReadMode ,
910 relTime ,
1011 sessionLabel ,
1112 type Post ,
@@ -118,14 +119,35 @@ export default function App() {
118119 // nor a host's loading overlay flips to real content before we know what to
119120 // show. .catch keeps it unblocking — a failed fetch still resolves to the
120121 // (empty) onboarding view, and the host overlay still clears.
121- void bootstrap ( )
122- . catch ( ( ) => { } )
123- . finally ( ( ) => {
124- setInitialLoaded ( true ) ;
125- host ( ) . onReady ?.( ) ;
126- } ) ;
127- const disconnect = connect ( ) ;
128- onCleanup ( disconnect ) ;
122+ // On a session-scoped publicRead workspace, the SSE connection requires a
123+ // ?session= param. For standalone post permalinks (/p/:id) the session ID
124+ // is only discovered during bootstrap (enterStandalone fetches the post).
125+ // Connecting before that resolves sends /api/events without a session and
126+ // the server returns 401. Defer the SSE connection until bootstrap finishes
127+ // so eventsPath() can read the resolved session ID.
128+ let disconnect : ( ( ) => void ) | undefined ;
129+ let unmounted = false ;
130+ if ( isReadonly ( ) && publicReadMode ( ) === "session" ) {
131+ void bootstrap ( )
132+ . catch ( ( ) => { } )
133+ . finally ( ( ) => {
134+ setInitialLoaded ( true ) ;
135+ host ( ) . onReady ?.( ) ;
136+ if ( ! unmounted ) disconnect = connect ( ) ;
137+ } ) ;
138+ } else {
139+ void bootstrap ( )
140+ . catch ( ( ) => { } )
141+ . finally ( ( ) => {
142+ setInitialLoaded ( true ) ;
143+ host ( ) . onReady ?.( ) ;
144+ } ) ;
145+ disconnect = connect ( ) ;
146+ }
147+ onCleanup ( ( ) => {
148+ unmounted = true ;
149+ disconnect ?.( ) ;
150+ } ) ;
129151 checkVersion ( ) ;
130152 void initTheme ( ) ;
131153 const timer = setInterval ( ( ) => {
Original file line number Diff line number Diff line change @@ -478,7 +478,7 @@ const WS_RECONNECT_MS = 1000;
478478
479479function eventsPath ( ) : string {
480480 const route = host ( ) . router . get ( ) ;
481- const sessionId = route . sessionId ?? selected ( ) ;
481+ const sessionId = route . sessionId ?? selected ( ) ?? standalonePost ( ) ?. sessionId ;
482482 return isReadonly ( ) && publicReadMode ( ) === "session" && sessionId
483483 ? `/api/events?session=${ encodeURIComponent ( sessionId ) } `
484484 : "/api/events" ;
You can’t perform that action at this time.
0 commit comments