mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Organize ChatPanelSession method order
This commit is contained in:
parent
6b7bf4546f
commit
0de3db212e
1 changed files with 319 additions and 319 deletions
|
|
@ -185,6 +185,325 @@ export class ChatPanelSession implements ChatSurfaceHandle {
|
|||
this.parts = this.createSessionParts();
|
||||
}
|
||||
|
||||
displayTitle(): string {
|
||||
return codexPanelDisplayTitle(this.state.activeThread.id, this.state.threadList.listedThreads, this.restoredThreadTitle());
|
||||
}
|
||||
|
||||
persistedState(): Record<string, unknown> {
|
||||
const threadId = this.state.activeThread.id;
|
||||
if (!threadId) return { version: 1 };
|
||||
|
||||
const threadTitle = this.restoredThreadTitle() ?? this.activeThreadTitle();
|
||||
return {
|
||||
version: 1,
|
||||
threadId,
|
||||
...(threadTitle ? { threadTitle } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
applyViewState(state: unknown): void {
|
||||
const restoredThread = parseRestoredThreadState(state);
|
||||
if (restoredThread) {
|
||||
this.parts.thread.restoration.restore(restoredThread);
|
||||
this.scheduleRestoredThreadHydration();
|
||||
return;
|
||||
}
|
||||
|
||||
this.invalidateResumeWork();
|
||||
this.parts.thread.restoration.clear();
|
||||
this.parts.thread.restoration.clearHydration();
|
||||
this.scheduleWarmup();
|
||||
}
|
||||
|
||||
refreshSettings(): void {
|
||||
const nextContext = this.currentAppServerContext();
|
||||
if (!appServerQueryContextRawEquals(this.observedAppServerContext, nextContext)) {
|
||||
this.observedAppServerContext = nextContext;
|
||||
this.connectionWork.invalidate();
|
||||
this.invalidateResumeWork();
|
||||
this.parts.connection.manager.resetConnection();
|
||||
this.applyCachedAppServerState();
|
||||
}
|
||||
this.mountOrRepairShell();
|
||||
}
|
||||
|
||||
refreshSharedThreadList(): Promise<void> {
|
||||
return this.loadSharedThreadList();
|
||||
}
|
||||
|
||||
async runWithAppServerClient<T>(operation: (client: AppServerClient) => Promise<T>): Promise<T> {
|
||||
const client = this.parts.connection.manager.currentClient();
|
||||
if (!client) throw new Error("Codex app-server is not connected.");
|
||||
const result = await operation(client);
|
||||
if (this.parts.connection.manager.currentClient() !== client) {
|
||||
throw new Error("Codex app-server connection changed while loading shared data.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
openPanelSnapshot(): ChatPanelSnapshot {
|
||||
return {
|
||||
viewId: this.environment.obsidian.viewId,
|
||||
threadId: this.closing ? null : this.state.activeThread.id,
|
||||
turnLifecycle: openPanelTurnLifecycle(this.state.turn.lifecycle),
|
||||
pendingApprovals: this.state.requests.approvals.length,
|
||||
pendingUserInputs: this.state.requests.pendingUserInputs.length,
|
||||
hasComposerDraft: this.state.composer.draft.trim().length > 0,
|
||||
connected: this.parts.connection.manager.isConnected(),
|
||||
};
|
||||
}
|
||||
|
||||
async openThread(threadId: string): Promise<void> {
|
||||
await this.parts.thread.resume.resumeThread(threadId);
|
||||
this.focusComposer();
|
||||
}
|
||||
|
||||
async focusThread(threadId: string | null = null): Promise<void> {
|
||||
if (threadId && this.parts.thread.restoration.isPending(threadId)) {
|
||||
await this.ensureRestoredThreadLoaded();
|
||||
}
|
||||
this.focusComposer();
|
||||
}
|
||||
|
||||
focusComposer(): void {
|
||||
this.parts.composer.controller.focus();
|
||||
}
|
||||
|
||||
applyThreadArchived(threadId: string): void {
|
||||
this.parts.thread.identity.applyThreadArchived(threadId);
|
||||
}
|
||||
|
||||
applyThreadRenamed(threadId: string, name: string | null): void {
|
||||
this.parts.thread.identity.applyThreadRenamed(threadId, name);
|
||||
}
|
||||
|
||||
open(): void {
|
||||
this.opened = true;
|
||||
this.closing = false;
|
||||
this.parts.composer.controller.registerNoteIndexInvalidation((eventRef) => {
|
||||
this.environment.obsidian.registerEvent(eventRef);
|
||||
});
|
||||
this.environment.obsidian.registerPointerDown((event) => {
|
||||
this.closeToolbarPanelOnOutsidePointer(event);
|
||||
});
|
||||
this.subscribeAppServerState();
|
||||
this.mountOrRepairShell();
|
||||
this.scheduleWarmup();
|
||||
this.scheduleRestoredThreadHydration();
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.opened = false;
|
||||
this.closing = true;
|
||||
this.connectionWork.invalidate();
|
||||
this.invalidateResumeWork();
|
||||
this.deferredTasks.clearAll();
|
||||
this.unsubscribeAppServerState();
|
||||
const panelRoot = this.environment.view.panelRoot();
|
||||
this.parts.render.messageStreamPresenter.dispose();
|
||||
this.parts.composer.controller.dispose();
|
||||
unmountChatPanelShell(panelRoot);
|
||||
this.parts.connection.manager.disconnect();
|
||||
this.refreshLiveState();
|
||||
this.deferLiveStateRefresh();
|
||||
}
|
||||
|
||||
setComposerText(text: string): void {
|
||||
this.parts.composer.controller.setDraft(text, { focus: true });
|
||||
}
|
||||
|
||||
async connect(): Promise<void> {
|
||||
await this.parts.connection.controller.ensureConnected();
|
||||
}
|
||||
|
||||
async startNewThread(): Promise<void> {
|
||||
if (chatTurnBusy(this.state)) return;
|
||||
|
||||
this.parts.thread.identity.clearActiveThreadContext();
|
||||
this.dispatch({ type: "ui/panel-set", panel: null });
|
||||
this.dispatch({ type: "connection/status-set", statusText: "New chat." });
|
||||
this.focusComposer();
|
||||
}
|
||||
|
||||
private get state(): ChatState {
|
||||
return this.stateStore.getState();
|
||||
}
|
||||
|
||||
private dispatch(action: ChatAction): void {
|
||||
this.stateStore.dispatch(action);
|
||||
}
|
||||
|
||||
private receiveObservedThreads(threads: readonly Thread[]): void {
|
||||
this.parts.serverActions.threads.applyThreadList(threads);
|
||||
this.refreshTabHeader();
|
||||
}
|
||||
|
||||
private receiveObservedThreadResult(result: AppServerObservedQueryResult<readonly Thread[]>): void {
|
||||
if (result.data) this.receiveObservedThreads(result.data);
|
||||
}
|
||||
|
||||
private receiveObservedAppServerMetadata(metadata: SharedServerMetadata): void {
|
||||
this.parts.serverActions.metadata.applyAppServerMetadata(metadata);
|
||||
}
|
||||
|
||||
private receiveObservedAppServerMetadataResult(result: AppServerObservedQueryResult<SharedServerMetadata>): void {
|
||||
if (result.data) this.receiveObservedAppServerMetadata(result.data);
|
||||
}
|
||||
|
||||
private receiveObservedModels(models: readonly ModelMetadata[]): void {
|
||||
this.dispatch({ type: "connection/metadata-applied", availableModels: models });
|
||||
}
|
||||
|
||||
private receiveObservedModelsResult(result: AppServerObservedQueryResult<readonly ModelMetadata[]>): void {
|
||||
if (result.data) this.receiveObservedModels(result.data);
|
||||
}
|
||||
|
||||
private applyCachedAppServerState(): void {
|
||||
const threads = this.environment.plugin.threadCatalog.activeThreadsSnapshot();
|
||||
if (threads) this.parts.serverActions.threads.applyThreadList(threads);
|
||||
const metadata = this.environment.plugin.appServerData.appServerMetadataSnapshot();
|
||||
if (metadata) this.parts.serverActions.metadata.applyAppServerMetadata(metadata);
|
||||
const models = this.environment.plugin.appServerData.modelsSnapshot();
|
||||
if (models) this.receiveObservedModels(models);
|
||||
}
|
||||
|
||||
private subscribeAppServerState(): void {
|
||||
this.unsubscribeAppServerState();
|
||||
this.applyCachedAppServerState();
|
||||
this.appServerStateUnsubscribers.push(
|
||||
this.environment.plugin.threadCatalog.observeActiveThreadsResult(
|
||||
(result) => {
|
||||
this.receiveObservedThreadResult(result);
|
||||
},
|
||||
{ emitCurrent: false },
|
||||
),
|
||||
this.environment.plugin.appServerData.observeAppServerMetadataResult(
|
||||
(result) => {
|
||||
this.receiveObservedAppServerMetadataResult(result);
|
||||
},
|
||||
{ emitCurrent: false },
|
||||
),
|
||||
this.environment.plugin.appServerData.observeModelsResult(
|
||||
(result) => {
|
||||
this.receiveObservedModelsResult(result);
|
||||
},
|
||||
{ emitCurrent: false },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private unsubscribeAppServerState(): void {
|
||||
while (this.appServerStateUnsubscribers.length > 0) {
|
||||
this.appServerStateUnsubscribers.pop()?.();
|
||||
}
|
||||
}
|
||||
|
||||
private mountOrRepairShell(): void {
|
||||
const root = this.environment.view.panelRoot();
|
||||
if (!root) return;
|
||||
renderChatPanelShell(root, {
|
||||
stateStore: this.stateStore,
|
||||
showToolbar: this.environment.plugin.settingsRef.settings.showToolbar,
|
||||
parts: {
|
||||
toolbar: {
|
||||
surface: this.parts.surface.toolbar,
|
||||
actions: this.parts.toolbar.actions,
|
||||
},
|
||||
goal: this.parts.surface.goal,
|
||||
messageStream: this.parts.render.messageStreamPresenter,
|
||||
composer: {
|
||||
controller: this.parts.composer.controller,
|
||||
actions: {
|
||||
submit: () => void this.parts.composer.submission.submit(),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private scheduleWarmup(): void {
|
||||
const shouldWarmup = (): boolean => this.opened && !this.parts.connection.manager.isConnected();
|
||||
if (!shouldWarmup()) return;
|
||||
|
||||
this.deferredTasks.scheduleAppServerWarmup(() => {
|
||||
if (!shouldWarmup() || this.closing) return;
|
||||
void this.parts.connection.controller.ensureConnected();
|
||||
});
|
||||
}
|
||||
|
||||
private invalidateResumeWork(): void {
|
||||
this.resumeWork.invalidate();
|
||||
this.parts.thread.history.invalidate();
|
||||
}
|
||||
|
||||
private async loadSharedThreadList(): Promise<void> {
|
||||
try {
|
||||
const threads = await this.environment.plugin.threadCatalog.refreshActiveThreads();
|
||||
this.parts.serverActions.threads.applyThreadList(threads);
|
||||
} catch (error) {
|
||||
if (isStaleAppServerSharedQueryContextError(error)) return;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private notifyActiveThreadIdentityChanged(): void {
|
||||
this.refreshTabHeader();
|
||||
this.environment.obsidian.requestWorkspaceLayoutSave();
|
||||
}
|
||||
|
||||
private refreshTabHeader(): void {
|
||||
this.environment.view.refreshTabHeader();
|
||||
}
|
||||
|
||||
private refreshLiveState(): void {
|
||||
this.environment.plugin.threadCatalog.refreshThreadsViewLiveState();
|
||||
}
|
||||
|
||||
private deferLiveStateRefresh(): void {
|
||||
this.viewWindow().setTimeout(() => {
|
||||
this.refreshLiveState();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private viewWindow(): Window {
|
||||
return this.environment.view.viewWindow() ?? window;
|
||||
}
|
||||
|
||||
private currentAppServerContext(): AppServerQueryContext {
|
||||
return {
|
||||
codexPath: this.environment.plugin.settingsRef.settings.codexPath,
|
||||
vaultPath: this.environment.plugin.settingsRef.vaultPath,
|
||||
};
|
||||
}
|
||||
|
||||
private closeToolbarPanelOnOutsidePointer(event: PointerEvent): void {
|
||||
this.parts.toolbar.panels.closeOnOutsidePointer({
|
||||
target: event.target,
|
||||
viewWindow: this.environment.view.viewWindow() as (Window & { Element: typeof Element }) | null,
|
||||
contains: (element) => this.environment.view.containsElement(element),
|
||||
renameEditing: this.parts.thread.rename.isEditing(),
|
||||
});
|
||||
}
|
||||
|
||||
private activeThreadTitle(): string | null {
|
||||
const threadId = this.state.activeThread.id;
|
||||
if (!threadId) return null;
|
||||
const thread = this.state.threadList.listedThreads.find((item) => item.id === threadId);
|
||||
return thread ? getThreadTitle(thread) : null;
|
||||
}
|
||||
|
||||
private restoredThreadTitle(): string | null {
|
||||
return this.parts.thread.restoration.title();
|
||||
}
|
||||
|
||||
private ensureRestoredThreadLoaded(): Promise<boolean> {
|
||||
return this.parts.thread.restoration.ensureLoaded((threadId) => this.parts.thread.resume.resumeThread(threadId));
|
||||
}
|
||||
|
||||
private scheduleRestoredThreadHydration(): void {
|
||||
this.parts.thread.restoration.scheduleHydration((threadId) => this.parts.thread.resume.resumeThread(threadId));
|
||||
}
|
||||
|
||||
private createSessionParts(): ChatPanelSessionParts {
|
||||
const status = this.createSessionStatus();
|
||||
const connection = this.createConnectionManager();
|
||||
|
|
@ -963,325 +1282,6 @@ export class ChatPanelSession implements ChatSurfaceHandle {
|
|||
};
|
||||
}
|
||||
|
||||
private get state(): ChatState {
|
||||
return this.stateStore.getState();
|
||||
}
|
||||
|
||||
private dispatch(action: ChatAction): void {
|
||||
this.stateStore.dispatch(action);
|
||||
}
|
||||
|
||||
displayTitle(): string {
|
||||
return codexPanelDisplayTitle(this.state.activeThread.id, this.state.threadList.listedThreads, this.restoredThreadTitle());
|
||||
}
|
||||
|
||||
persistedState(): Record<string, unknown> {
|
||||
const threadId = this.state.activeThread.id;
|
||||
if (!threadId) return { version: 1 };
|
||||
|
||||
const threadTitle = this.restoredThreadTitle() ?? this.activeThreadTitle();
|
||||
return {
|
||||
version: 1,
|
||||
threadId,
|
||||
...(threadTitle ? { threadTitle } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
applyViewState(state: unknown): void {
|
||||
const restoredThread = parseRestoredThreadState(state);
|
||||
if (restoredThread) {
|
||||
this.parts.thread.restoration.restore(restoredThread);
|
||||
this.scheduleRestoredThreadHydration();
|
||||
return;
|
||||
}
|
||||
|
||||
this.invalidateResumeWork();
|
||||
this.parts.thread.restoration.clear();
|
||||
this.parts.thread.restoration.clearHydration();
|
||||
this.scheduleWarmup();
|
||||
}
|
||||
|
||||
refreshSettings(): void {
|
||||
const nextContext = this.currentAppServerContext();
|
||||
if (!appServerQueryContextRawEquals(this.observedAppServerContext, nextContext)) {
|
||||
this.observedAppServerContext = nextContext;
|
||||
this.connectionWork.invalidate();
|
||||
this.invalidateResumeWork();
|
||||
this.parts.connection.manager.resetConnection();
|
||||
this.applyCachedAppServerState();
|
||||
}
|
||||
this.mountOrRepairShell();
|
||||
}
|
||||
|
||||
refreshSharedThreadList(): Promise<void> {
|
||||
return this.loadSharedThreadList();
|
||||
}
|
||||
|
||||
async runWithAppServerClient<T>(operation: (client: AppServerClient) => Promise<T>): Promise<T> {
|
||||
const client = this.parts.connection.manager.currentClient();
|
||||
if (!client) throw new Error("Codex app-server is not connected.");
|
||||
const result = await operation(client);
|
||||
if (this.parts.connection.manager.currentClient() !== client) {
|
||||
throw new Error("Codex app-server connection changed while loading shared data.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private receiveObservedThreads(threads: readonly Thread[]): void {
|
||||
this.parts.serverActions.threads.applyThreadList(threads);
|
||||
this.refreshTabHeader();
|
||||
}
|
||||
|
||||
private receiveObservedThreadResult(result: AppServerObservedQueryResult<readonly Thread[]>): void {
|
||||
if (result.data) this.receiveObservedThreads(result.data);
|
||||
}
|
||||
|
||||
private receiveObservedAppServerMetadata(metadata: SharedServerMetadata): void {
|
||||
this.parts.serverActions.metadata.applyAppServerMetadata(metadata);
|
||||
}
|
||||
|
||||
private receiveObservedAppServerMetadataResult(result: AppServerObservedQueryResult<SharedServerMetadata>): void {
|
||||
if (result.data) this.receiveObservedAppServerMetadata(result.data);
|
||||
}
|
||||
|
||||
private receiveObservedModels(models: readonly ModelMetadata[]): void {
|
||||
this.dispatch({ type: "connection/metadata-applied", availableModels: models });
|
||||
}
|
||||
|
||||
private receiveObservedModelsResult(result: AppServerObservedQueryResult<readonly ModelMetadata[]>): void {
|
||||
if (result.data) this.receiveObservedModels(result.data);
|
||||
}
|
||||
|
||||
openPanelSnapshot(): ChatPanelSnapshot {
|
||||
return {
|
||||
viewId: this.environment.obsidian.viewId,
|
||||
threadId: this.closing ? null : this.state.activeThread.id,
|
||||
turnLifecycle: openPanelTurnLifecycle(this.state.turn.lifecycle),
|
||||
pendingApprovals: this.state.requests.approvals.length,
|
||||
pendingUserInputs: this.state.requests.pendingUserInputs.length,
|
||||
hasComposerDraft: this.state.composer.draft.trim().length > 0,
|
||||
connected: this.parts.connection.manager.isConnected(),
|
||||
};
|
||||
}
|
||||
|
||||
async openThread(threadId: string): Promise<void> {
|
||||
await this.parts.thread.resume.resumeThread(threadId);
|
||||
this.focusComposer();
|
||||
}
|
||||
|
||||
async focusThread(threadId: string | null = null): Promise<void> {
|
||||
if (threadId && this.parts.thread.restoration.isPending(threadId)) {
|
||||
await this.ensureRestoredThreadLoaded();
|
||||
}
|
||||
this.focusComposer();
|
||||
}
|
||||
|
||||
focusComposer(): void {
|
||||
this.parts.composer.controller.focus();
|
||||
}
|
||||
|
||||
applyThreadArchived(threadId: string): void {
|
||||
this.parts.thread.identity.applyThreadArchived(threadId);
|
||||
}
|
||||
|
||||
applyThreadRenamed(threadId: string, name: string | null): void {
|
||||
this.parts.thread.identity.applyThreadRenamed(threadId, name);
|
||||
}
|
||||
|
||||
open(): void {
|
||||
this.opened = true;
|
||||
this.closing = false;
|
||||
this.parts.composer.controller.registerNoteIndexInvalidation((eventRef) => {
|
||||
this.environment.obsidian.registerEvent(eventRef);
|
||||
});
|
||||
this.environment.obsidian.registerPointerDown((event) => {
|
||||
this.closeToolbarPanelOnOutsidePointer(event);
|
||||
});
|
||||
this.subscribeAppServerState();
|
||||
this.mountOrRepairShell();
|
||||
this.scheduleWarmup();
|
||||
this.scheduleRestoredThreadHydration();
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.opened = false;
|
||||
this.closing = true;
|
||||
this.connectionWork.invalidate();
|
||||
this.invalidateResumeWork();
|
||||
this.deferredTasks.clearAll();
|
||||
this.unsubscribeAppServerState();
|
||||
const panelRoot = this.environment.view.panelRoot();
|
||||
this.parts.render.messageStreamPresenter.dispose();
|
||||
this.parts.composer.controller.dispose();
|
||||
unmountChatPanelShell(panelRoot);
|
||||
this.parts.connection.manager.disconnect();
|
||||
this.refreshLiveState();
|
||||
this.deferLiveStateRefresh();
|
||||
}
|
||||
|
||||
setComposerText(text: string): void {
|
||||
this.parts.composer.controller.setDraft(text, { focus: true });
|
||||
}
|
||||
|
||||
async connect(): Promise<void> {
|
||||
await this.parts.connection.controller.ensureConnected();
|
||||
}
|
||||
|
||||
async startNewThread(): Promise<void> {
|
||||
if (chatTurnBusy(this.state)) return;
|
||||
|
||||
this.parts.thread.identity.clearActiveThreadContext();
|
||||
this.dispatch({ type: "ui/panel-set", panel: null });
|
||||
this.dispatch({ type: "connection/status-set", statusText: "New chat." });
|
||||
this.focusComposer();
|
||||
}
|
||||
|
||||
private applyCachedAppServerState(): void {
|
||||
const threads = this.environment.plugin.threadCatalog.activeThreadsSnapshot();
|
||||
if (threads) this.parts.serverActions.threads.applyThreadList(threads);
|
||||
const metadata = this.environment.plugin.appServerData.appServerMetadataSnapshot();
|
||||
if (metadata) this.parts.serverActions.metadata.applyAppServerMetadata(metadata);
|
||||
const models = this.environment.plugin.appServerData.modelsSnapshot();
|
||||
if (models) this.receiveObservedModels(models);
|
||||
}
|
||||
|
||||
private subscribeAppServerState(): void {
|
||||
this.unsubscribeAppServerState();
|
||||
this.applyCachedAppServerState();
|
||||
this.appServerStateUnsubscribers.push(
|
||||
this.environment.plugin.threadCatalog.observeActiveThreadsResult(
|
||||
(result) => {
|
||||
this.receiveObservedThreadResult(result);
|
||||
},
|
||||
{ emitCurrent: false },
|
||||
),
|
||||
this.environment.plugin.appServerData.observeAppServerMetadataResult(
|
||||
(result) => {
|
||||
this.receiveObservedAppServerMetadataResult(result);
|
||||
},
|
||||
{ emitCurrent: false },
|
||||
),
|
||||
this.environment.plugin.appServerData.observeModelsResult(
|
||||
(result) => {
|
||||
this.receiveObservedModelsResult(result);
|
||||
},
|
||||
{ emitCurrent: false },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private unsubscribeAppServerState(): void {
|
||||
while (this.appServerStateUnsubscribers.length > 0) {
|
||||
this.appServerStateUnsubscribers.pop()?.();
|
||||
}
|
||||
}
|
||||
|
||||
private mountOrRepairShell(): void {
|
||||
const root = this.environment.view.panelRoot();
|
||||
if (!root) return;
|
||||
renderChatPanelShell(root, {
|
||||
stateStore: this.stateStore,
|
||||
showToolbar: this.environment.plugin.settingsRef.settings.showToolbar,
|
||||
parts: {
|
||||
toolbar: {
|
||||
surface: this.parts.surface.toolbar,
|
||||
actions: this.parts.toolbar.actions,
|
||||
},
|
||||
goal: this.parts.surface.goal,
|
||||
messageStream: this.parts.render.messageStreamPresenter,
|
||||
composer: {
|
||||
controller: this.parts.composer.controller,
|
||||
actions: {
|
||||
submit: () => void this.parts.composer.submission.submit(),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private scheduleWarmup(): void {
|
||||
const shouldWarmup = (): boolean => this.opened && !this.parts.connection.manager.isConnected();
|
||||
if (!shouldWarmup()) return;
|
||||
|
||||
this.deferredTasks.scheduleAppServerWarmup(() => {
|
||||
if (!shouldWarmup() || this.closing) return;
|
||||
void this.parts.connection.controller.ensureConnected();
|
||||
});
|
||||
}
|
||||
|
||||
private invalidateResumeWork(): void {
|
||||
this.resumeWork.invalidate();
|
||||
this.parts.thread.history.invalidate();
|
||||
}
|
||||
|
||||
private async loadSharedThreadList(): Promise<void> {
|
||||
try {
|
||||
const threads = await this.environment.plugin.threadCatalog.refreshActiveThreads();
|
||||
this.parts.serverActions.threads.applyThreadList(threads);
|
||||
} catch (error) {
|
||||
if (isStaleAppServerSharedQueryContextError(error)) return;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private notifyActiveThreadIdentityChanged(): void {
|
||||
this.refreshTabHeader();
|
||||
this.environment.obsidian.requestWorkspaceLayoutSave();
|
||||
}
|
||||
|
||||
private refreshTabHeader(): void {
|
||||
this.environment.view.refreshTabHeader();
|
||||
}
|
||||
|
||||
private refreshLiveState(): void {
|
||||
this.environment.plugin.threadCatalog.refreshThreadsViewLiveState();
|
||||
}
|
||||
|
||||
private deferLiveStateRefresh(): void {
|
||||
this.viewWindow().setTimeout(() => {
|
||||
this.refreshLiveState();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private viewWindow(): Window {
|
||||
return this.environment.view.viewWindow() ?? window;
|
||||
}
|
||||
|
||||
private currentAppServerContext(): AppServerQueryContext {
|
||||
return {
|
||||
codexPath: this.environment.plugin.settingsRef.settings.codexPath,
|
||||
vaultPath: this.environment.plugin.settingsRef.vaultPath,
|
||||
};
|
||||
}
|
||||
|
||||
private closeToolbarPanelOnOutsidePointer(event: PointerEvent): void {
|
||||
this.parts.toolbar.panels.closeOnOutsidePointer({
|
||||
target: event.target,
|
||||
viewWindow: this.environment.view.viewWindow() as (Window & { Element: typeof Element }) | null,
|
||||
contains: (element) => this.environment.view.containsElement(element),
|
||||
renameEditing: this.parts.thread.rename.isEditing(),
|
||||
});
|
||||
}
|
||||
|
||||
private activeThreadTitle(): string | null {
|
||||
const threadId = this.state.activeThread.id;
|
||||
if (!threadId) return null;
|
||||
const thread = this.state.threadList.listedThreads.find((item) => item.id === threadId);
|
||||
return thread ? getThreadTitle(thread) : null;
|
||||
}
|
||||
|
||||
private restoredThreadTitle(): string | null {
|
||||
return this.parts.thread.restoration.title();
|
||||
}
|
||||
|
||||
private ensureRestoredThreadLoaded(): Promise<boolean> {
|
||||
return this.parts.thread.restoration.ensureLoaded((threadId) => this.parts.thread.resume.resumeThread(threadId));
|
||||
}
|
||||
|
||||
private scheduleRestoredThreadHydration(): void {
|
||||
this.parts.thread.restoration.scheduleHydration((threadId) => this.parts.thread.resume.resumeThread(threadId));
|
||||
}
|
||||
|
||||
private statusSummaryLines(): string[] {
|
||||
return buildStatusSummaryLines({
|
||||
activeThreadId: this.state.activeThread.id,
|
||||
|
|
|
|||
Loading…
Reference in a new issue