11import { useEffect , useState } from "react" ;
22
33import { readChannelRecovery , rememberChannel } from "./channel-recovery" ;
4- import { newestDocument } from "./document-actions" ;
54import { documentRouteIdentity } from "./document-route-swap" ;
6- import { useNavigationDocument } from "./navigation-shell" ;
75
8- import type { ComponentType } from "react" ;
96import type * as Api from "./api" ;
107import type { DocumentRouteIdentity } from "./document-route-swap" ;
11- import type {
12- ChannelSource ,
13- DocumentRouteResolution ,
14- HostedFailure ,
15- HostedLoading ,
16- HostedWorkspaceProps ,
17- } from "./hosted" ;
8+ import type { ChannelSource , HostedFailure , HostedLoading } from "./hosted" ;
189
10+ // A channel URL resolves to its document path before any workspace mounts, so the document
11+ // host mounts once under its own route identity instead of replacing a channel-keyed room.
1912export default function ChannelWorkspace (
20- { agent, Failure, Loading, onReady, retryable, source, user } : {
21- agent : boolean ;
13+ { Failure, Loading, onReady, onResolved, retryable, source, user } : {
2214 Failure : typeof HostedFailure ;
2315 Loading : typeof HostedLoading ;
24- onReady ?: ( key : DocumentRouteIdentity , resolution ?: DocumentRouteResolution ) => void ;
16+ onReady : ( key : DocumentRouteIdentity ) => void ;
17+ onResolved : ( key : DocumentRouteIdentity , pathname : string ) => void ;
2518 retryable : ( error : unknown ) => boolean ;
2619 source : ChannelSource ;
2720 user : Api . User ;
2821 } ,
2922) {
30- type LoadedWorkspace = {
31- detail : Api . ChannelDetail ;
32- Workspace : ComponentType < HostedWorkspaceProps > ;
33- } ;
34- let [ loaded , setLoaded ] = useState < LoadedWorkspace > ( ) ;
3523 let [ error , setError ] = useState < unknown > ( ) ;
3624 let [ retry , setRetry ] = useState ( 0 ) ;
37- let { channel : navigationChannel } = useNavigationDocument ( ) ;
3825 let routeKey = documentRouteIdentity ( source ) ;
39- let recovery = readChannelRecovery ( user . id , source . id ) ;
26+ let id = source . id ;
4027
4128 useEffect ( ( ) => {
4229 let active = true ;
4330 let controller = new AbortController ( ) ;
44- setLoaded ( undefined ) ;
4531 setError ( undefined ) ;
46- let prepared = import ( "./document-loader" ) . then ( module =>
47- module . prepareDocumentLoad ( { id : source . id } , controller . signal )
48- ) . then ( ( { detail, pathname } ) => ( { canonicalPath : pathname , detail } ) ) ;
49- prepared = prepared . then ( resolved => {
50- if ( active ) {
51- rememberChannel ( user . id , resolved . detail . channel , resolved . detail . repository ) ;
52- }
53- return resolved ;
54- } ) ;
55- let workspace = import ( "./room-workspace" ) . then ( module => ( {
56- Workspace : module . RoomWorkspace ,
57- } ) ) ;
58- Promise . all ( [ prepared , workspace ] ) . then ( ( [ resolved , selected ] ) => {
59- if ( active ) {
60- setLoaded ( { detail : resolved . detail , ...selected } ) ;
61- onReady ?.( routeKey , {
62- canonicalPath : resolved . canonicalPath ,
63- channel : resolved . detail . channel ,
64- routeKey,
65- } ) ;
66- }
32+ import ( "./document-loader" ) . then ( module =>
33+ module . prepareDocumentLoad ( { id } , controller . signal )
34+ ) . then ( ( { detail, pathname } ) => {
35+ if ( ! active ) return ;
36+ rememberChannel ( user . id , detail . channel , detail . repository ) ;
37+ onResolved ( routeKey , pathname ) ;
6738 } , reason => {
68- if ( active ) {
69- setError ( reason ) ;
70- onReady ?.( routeKey ) ;
71- }
39+ if ( ! active ) return ;
40+ setError ( reason ) ;
41+ onReady ( routeKey ) ;
7242 } ) ;
7343 return ( ) => {
7444 active = false ;
7545 controller . abort ( ) ;
7646 } ;
77- } , [ onReady , retry , routeKey , source , user . id ] ) ;
47+ } , [ id , onReady , onResolved , retry , routeKey , user . id ] ) ;
7848 if ( error ) {
49+ let recovery = readChannelRecovery ( user . id , id ) ;
7950 return (
8051 < Failure
8152 channel = { recovery ?. channel }
@@ -90,27 +61,5 @@ export default function ChannelWorkspace(
9061 />
9162 ) ;
9263 }
93- if ( ! loaded ) return < Loading label = "Opening document…" /> ;
94- let { detail } = loaded ;
95- let channel = navigationChannel ?. id === detail . channel . id
96- ? newestDocument ( detail . channel , navigationChannel )
97- : detail . channel ;
98- let props : HostedWorkspaceProps = {
99- agent,
100- archivedAt : channel . archivedAt ,
101- canEdit : ! channel . archivedAt && ( detail . canEdit || detail . canManage ) ,
102- canManage : detail . canManage ,
103- description : channel . description ,
104- descriptionRevision : channel . descriptionRevision ,
105- handle : user . login ,
106- label : channel . title ,
107- presentation : { type : "document" } ,
108- slug : channel . slug ,
109- updatedAt : channel . updatedAt ,
110- repository : detail . repository ,
111- room : detail . channel . id ,
112- userId : user . id ,
113- } ;
114- let Document = loaded . Workspace ;
115- return < Document { ...props } /> ;
64+ return < Loading label = "Opening document…" /> ;
11665}
0 commit comments