The composer rendered a second StatusRow instance carrying the pending-changes bar and the todos dropdown, so every restyle of the floating assistant-status chip (glass, placement, sizing) silently restyled the composer bar and its dropdown too — for the fourth time. StatusRow is now only the floating chip above the composer; the composer's own bar is a new ComposerStatusBar with the pre-glass layout, its own container name, and its own container-query classes (the anti-overlap rules that hide the long active todo under 38rem and the changed-files label under 30rem moved with it — losing them during the split let the two dropdown triggers overlap on mobile). The two components share no markup and no CSS hooks anymore.
57 lines
2.2 KiB
TypeScript
57 lines
2.2 KiB
TypeScript
import React from 'react';
|
|
|
|
import { useAssistantStatus } from '@/hooks/useAssistantStatus';
|
|
import { useConfigStore } from '@/stores/useConfigStore';
|
|
import { useSessionUIStore } from '@/sync/session-ui-store';
|
|
import { getProviderModelDisplayName } from '@/lib/modelDisplay';
|
|
import { StatusRow } from './StatusRow';
|
|
|
|
/**
|
|
* Status row wrapper.
|
|
* Uses the dedicated assistant status hook so the row keeps accurate live activity
|
|
* labels while still limiting subscriptions to the active assistant message.
|
|
*/
|
|
export const StatusRowContainer: React.FC = React.memo(() => {
|
|
const currentSessionId = useSessionUIStore((state) => state.currentSessionId);
|
|
const abortRecord = useSessionUIStore(
|
|
React.useCallback((state) => {
|
|
if (!currentSessionId) {
|
|
return null;
|
|
}
|
|
return state.sessionAbortFlags?.get(currentSessionId) ?? null;
|
|
}, [currentSessionId]),
|
|
);
|
|
const { activeModel, working } = useAssistantStatus();
|
|
const currentAgentName = useConfigStore((state) => state.currentAgentName);
|
|
const providers = useConfigStore((state) => state.providers);
|
|
|
|
const modelDisplayName = React.useMemo(() => {
|
|
if (!activeModel) {
|
|
return null;
|
|
}
|
|
const provider = providers.length > 0
|
|
? providers.find((candidate) => candidate.id === activeModel.providerId)
|
|
: undefined;
|
|
return getProviderModelDisplayName(provider, activeModel.modelId) || null;
|
|
}, [activeModel, providers]);
|
|
|
|
const wasAborted = Boolean(abortRecord && !abortRecord.acknowledged);
|
|
|
|
return (
|
|
<StatusRow
|
|
isWorking={working.isWorking}
|
|
statusText={working.statusText}
|
|
isGenericStatus={working.isGenericStatus}
|
|
isWaitingForPermission={working.isWaitingForPermission}
|
|
wasAborted={wasAborted || working.wasAborted}
|
|
abortActive={wasAborted || working.abortActive}
|
|
retryInfo={working.retryInfo}
|
|
agentName={currentAgentName}
|
|
modelName={modelDisplayName}
|
|
providerId={activeModel?.providerId ?? null}
|
|
/>
|
|
);
|
|
});
|
|
|
|
StatusRowContainer.displayName = 'StatusRowContainer';
|