`useBtwPanelState` already subscribes to the composer's own session — it is what the fork link is derived from — so asking `useSession` for the same session and directory a second time in `ChatInput` was a duplicate subscription for a value already in hand. Expose it as `parentSession` and read the promoted flag from there. No behavior change.
58 lines
2.4 KiB
TypeScript
58 lines
2.4 KiB
TypeScript
import React from 'react';
|
|
import type { Session } from '@opencode-ai/sdk/v2';
|
|
import { useSession } from '@/sync/sync-context';
|
|
import { getBtwBoundaryMessageID, getBtwSessionID } from '@/lib/sessionBtwMetadata';
|
|
import { useBtwStore } from '@/stores/useBtwStore';
|
|
|
|
export type BtwPanelState = {
|
|
/** The session the composer is in — the one `/btw` would fork. */
|
|
parentSession: Session | null;
|
|
/** The active fork for this parent, or null when no panel should exist. */
|
|
btwSessionId: string | null;
|
|
btwSession: Session | null;
|
|
/** The fork's directory identity (may be canonicalized by the server). */
|
|
btwDirectory: string | null;
|
|
/** Last message id inherited from the parent; the panel shows what's after it. */
|
|
boundaryMessageID: string | null;
|
|
collapsed: boolean;
|
|
creating: boolean;
|
|
};
|
|
|
|
/**
|
|
* Derive the `/btw` panel identity for one parent session from authoritative
|
|
* session metadata (`openchamber.btwSessionID`), plus the transient UI state
|
|
* kept in `useBtwStore`. The panel exists only while the parent's link AND the
|
|
* fork itself are present in the live stores, so a fork deleted anywhere
|
|
* (sidebar, another client) makes the panel disappear without extra tracking.
|
|
*/
|
|
export function useBtwPanelState(
|
|
parentSessionId: string | null | undefined,
|
|
directory: string | undefined,
|
|
): BtwPanelState {
|
|
const parentSession = useSession(parentSessionId, directory);
|
|
const linkedBtwSessionId = getBtwSessionID(parentSession);
|
|
const btwSession = useSession(linkedBtwSessionId, directory) ?? null;
|
|
const uiState = useBtwStore(
|
|
React.useCallback(
|
|
(s) => (parentSessionId ? s.byParent[parentSessionId] : undefined),
|
|
[parentSessionId],
|
|
),
|
|
);
|
|
|
|
const destroying = Boolean(uiState?.destroying);
|
|
const btwSessionId = btwSession && !destroying ? linkedBtwSessionId : null;
|
|
return {
|
|
parentSession: parentSession ?? null,
|
|
btwSessionId,
|
|
btwSession: btwSessionId ? btwSession : null,
|
|
// SAFETY: the SDK Session type omits the server's `directory` field; this
|
|
// widening only reads it, with the parent's directory as the fallback.
|
|
btwDirectory: btwSessionId
|
|
? ((btwSession as (Session & { directory?: string | null }) | null)?.directory ?? directory ?? null)
|
|
: null,
|
|
boundaryMessageID: btwSessionId ? getBtwBoundaryMessageID(btwSession) : null,
|
|
collapsed: Boolean(uiState?.collapsed),
|
|
creating: Boolean(uiState?.creating),
|
|
};
|
|
}
|