feat: bind public vestibules to domain login gates
This commit is contained in:
parent
2c50b28557
commit
b24d5b5452
6 changed files with 147 additions and 22 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect, useMemo, useState, type CSSProperties, type PointerEvent as ReactPointerEvent } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties, type PointerEvent as ReactPointerEvent } from 'react';
|
||||
import { api, DocTreeNode, DocContent, type ChannelState, type ModuleManifest } from './api';
|
||||
import { DocTree } from './components/DocTree';
|
||||
import { Editor } from './components/Editor';
|
||||
|
|
@ -13,6 +13,7 @@ import { ModuleLibrarySheet } from './components/ModuleLibrarySheet';
|
|||
import { cleanDisplayText } from './presentation';
|
||||
import { WorldEntry } from './components/WorldEntry';
|
||||
import { DomainConnectionSheet } from './components/DomainConnectionSheet';
|
||||
import { createDomainEntryTarget, type DomainEntryTarget, type DomainNodeType } from './domain-entry-state';
|
||||
import type { DomainRouteId } from './public-domain-directory';
|
||||
|
||||
type View = 'editor' | 'history';
|
||||
|
|
@ -84,6 +85,7 @@ export default function App() {
|
|||
const [activeModule, setActiveModule] = useState<ModuleId>('knowledge');
|
||||
const [storageSheetOpen, setStorageSheetOpen] = useState(false);
|
||||
const [domainConnectionOpen, setDomainConnectionOpen] = useState(false);
|
||||
const [domainEntryTarget, setDomainEntryTarget] = useState<DomainEntryTarget | null>(null);
|
||||
const [storageSheetInitialMode, setStorageSheetInitialMode] = useState<'local' | 'server' | undefined>();
|
||||
const [serverSession, setServerSession] = useState<ServerSession>({ authenticated: false, nodeId: '' });
|
||||
const [serverProfiles, setServerProfiles] = useState<ServerProfile[]>([]);
|
||||
|
|
@ -101,6 +103,7 @@ export default function App() {
|
|||
const [lastChannelReceipt, setLastChannelReceipt] = useState('');
|
||||
const [worldEntered, setWorldEntered] = useState(false);
|
||||
const [domainAccess, setDomainAccess] = useState<DomainAccessStatus>({ blockers: [], runtimeReady: false, stage: 'checking' });
|
||||
const domainAccessRequest = useRef(0);
|
||||
|
||||
const storageMode = repositoryStatus?.remote ? 'server' : 'local';
|
||||
const storageLabel = storageMode === 'server' ? '服务器已托管' : '仅本机';
|
||||
|
|
@ -176,19 +179,35 @@ export default function App() {
|
|||
}
|
||||
}, []);
|
||||
|
||||
const refreshDomainAccess = useCallback(async () => {
|
||||
const refreshDomainAccess = useCallback(async (domainId = 'DOM-FIFTH-0001') => {
|
||||
const request = ++domainAccessRequest.current;
|
||||
const server = (window as any).hololake?.server;
|
||||
if (!server?.domainAccess) {
|
||||
setDomainAccess({ blockers: ['desktop_runtime_required'], runtimeReady: false, stage: 'login-required' });
|
||||
if (request === domainAccessRequest.current) setDomainAccess({ blockers: ['desktop_runtime_required'], domainId, runtimeReady: false, stage: 'login-required' });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setDomainAccess(await server.domainAccess('DOM-FIFTH-0001'));
|
||||
const result = await server.domainAccess(domainId);
|
||||
if (request === domainAccessRequest.current) setDomainAccess(result);
|
||||
} catch {
|
||||
setDomainAccess({ blockers: ['domain_access_probe_failed'], runtimeReady: false, stage: 'login-required' });
|
||||
if (request === domainAccessRequest.current) setDomainAccess({ blockers: ['domain_access_probe_failed'], domainId, runtimeReady: false, stage: 'login-required' });
|
||||
}
|
||||
}, []);
|
||||
|
||||
const openDomainConnection = useCallback((routeId: DomainRouteId | null) => {
|
||||
const target = routeId ? createDomainEntryTarget(routeId) : null;
|
||||
setDomainEntryTarget(target);
|
||||
setDomainConnectionOpen(true);
|
||||
if (target) {
|
||||
setDomainAccess({ blockers: [], domainId: target.domain.stableDomainId, runtimeReady: false, stage: 'checking' });
|
||||
void refreshDomainAccess(target.domain.stableDomainId);
|
||||
}
|
||||
}, [refreshDomainAccess]);
|
||||
|
||||
const selectDomainNodeType = useCallback((nodeType: DomainNodeType) => {
|
||||
setDomainEntryTarget(current => current ? createDomainEntryTarget(current.domain.routeId, nodeType) : null);
|
||||
}, []);
|
||||
|
||||
const refreshChannel = useCallback(async () => {
|
||||
try {
|
||||
const [channel, registry] = await Promise.all([api.getChannel(), api.getModules()]);
|
||||
|
|
@ -393,9 +412,7 @@ export default function App() {
|
|||
setActiveModule('knowledge');
|
||||
setWorldEntered(true);
|
||||
}}
|
||||
onOpenConnection={() => {
|
||||
setDomainConnectionOpen(true);
|
||||
}}
|
||||
onOpenConnection={openDomainConnection}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
|
|
@ -581,10 +598,13 @@ export default function App() {
|
|||
/>
|
||||
<DomainConnectionSheet
|
||||
access={domainAccess}
|
||||
target={domainEntryTarget}
|
||||
open={domainConnectionOpen}
|
||||
onClose={() => setDomainConnectionOpen(false)}
|
||||
onSelectTarget={routeId => openDomainConnection(routeId)}
|
||||
onSelectNodeType={selectDomainNodeType}
|
||||
onEnterRuntime={() => {
|
||||
if (!domainAccess.runtimeReady) return;
|
||||
if (!domainEntryTarget || domainEntryTarget.domain.routeId !== 'fifth' || !domainAccess.runtimeReady || domainAccess.domainId !== domainEntryTarget.domain.stableDomainId) return;
|
||||
setActiveRoute('fifth');
|
||||
setActiveModule('knowledge');
|
||||
setWorldEntered(true);
|
||||
|
|
|
|||
Loading…
Reference in a new issue