cleanup and add toggle for sidebar

This commit is contained in:
Arjun Patel
2026-06-12 10:52:04 -07:00
parent 22ba0410a5
commit 91c973d862
5 changed files with 36 additions and 26 deletions
@@ -48,8 +48,7 @@ export type ComposeStep =
type RecordingSource = 'media' | 'screen'; type RecordingSource = 'media' | 'screen';
type PendingArtifact = type PendingArtifact = { type: 'task'; properties: TaskProperties };
| { type: 'task'; properties: TaskProperties };
interface ComposeOverlayProps { interface ComposeOverlayProps {
networkId: string; networkId: string;
@@ -466,7 +465,7 @@ export function ComposeOverlay({
// --- Compose intent handlers --- // --- Compose intent handlers ---
// Single source of truth for the step transitions triggered by the user. // Single source of truth for the step transitions triggered by the user.
// Both the keyboard handler and the intent store dispatch into these so // Both the keyboard handler and the intent store dispatch into these so
// guards (disabled, quota) and screen-vs-media branching live in one place. // guards (quota) and screen-vs-media branching live in one place.
const guardIdle = useCallback((): boolean => { const guardIdle = useCallback((): boolean => {
if (stepRef.current !== 'idle') return false; if (stepRef.current !== 'idle') return false;
@@ -497,7 +496,6 @@ export function ComposeOverlay({
setStepSync('task'); setStepSync('task');
}, [guardIdle, setStepSync]); }, [guardIdle, setStepSync]);
// Artifact submit: capture the artifact, then reuse the standard flow — // Artifact submit: capture the artifact, then reuse the standard flow —
// reply mode creates it under targetPath, root mode configures a stream // reply mode creates it under targetPath, root mode configures a stream
// that will hold it as its first child. // that will hold it as its first child.
@@ -1,4 +1,11 @@
import { Fragment, useMemo, useRef, useEffect, memo, createElement } from 'react'; import {
Fragment,
useMemo,
useRef,
useEffect,
memo,
createElement,
} from 'react';
import { Headphones, Radio, FolderIcon } from 'lucide-react'; import { Headphones, Radio, FolderIcon } from 'lucide-react';
import { cn, getInitials } from '@/lib/utils'; import { cn, getInitials } from '@/lib/utils';
import { useLiveLatestChild } from '@/hooks/use-particle'; import { useLiveLatestChild } from '@/hooks/use-particle';
@@ -1,18 +1,12 @@
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { import { CircleCheck, FileText, Image, List, Mic, Video } from 'lucide-react';
CircleCheck,
FileText,
Image,
List,
Mic,
Video,
} from 'lucide-react';
import { isParticleDeleted, type Human, type Particle } from '@/api/types'; import { isParticleDeleted, type Human, type Particle } from '@/api/types';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { useNetwork } from '@/hooks/use-networks'; import { useNetwork } from '@/hooks/use-networks';
import { resolveHumanDisplay } from '@/lib/humans'; import { resolveHumanDisplay } from '@/lib/humans';
import { RelativeTimestamp } from '@/components/relative-timestamp'; import { RelativeTimestamp } from '@/components/relative-timestamp';
import { HumanAvatar } from '@/components/human-avatar'; import { HumanAvatar } from '@/components/human-avatar';
import { KeyHint } from '@/components/key-hint';
import { ScrollArea } from '@/components/ui/scroll-area'; import { ScrollArea } from '@/components/ui/scroll-area';
interface StreamListSidebarProps { interface StreamListSidebarProps {
@@ -21,6 +15,7 @@ interface StreamListSidebarProps {
networkId: string; networkId: string;
currentIndex: number; currentIndex: number;
onSelect: (index: number) => void; onSelect: (index: number) => void;
onToggle: () => void;
} }
/** /**
@@ -34,6 +29,7 @@ export function StreamListSidebar({
networkId, networkId,
currentIndex, currentIndex,
onSelect, onSelect,
onToggle,
}: StreamListSidebarProps) { }: StreamListSidebarProps) {
const network = useNetwork(networkId); const network = useNetwork(networkId);
const rowRefs = useRef<Array<HTMLDivElement | null>>([]); const rowRefs = useRef<Array<HTMLDivElement | null>>([]);
@@ -52,6 +48,14 @@ export function StreamListSidebar({
{streamName} {streamName}
</span> </span>
<span className="ml-auto text-xs text-white/40">{items.length}</span> <span className="ml-auto text-xs text-white/40">{items.length}</span>
<KeyHint
keys="L"
onClick={onToggle}
title="Hide list (or press L)"
className="text-xs text-white/40"
>
to close
</KeyHint>
</div> </div>
<ScrollArea className="min-h-0 flex-1"> <ScrollArea className="min-h-0 flex-1">
<div className="flex flex-col gap-0.5 px-2 py-2"> <div className="flex flex-col gap-0.5 px-2 py-2">
@@ -68,6 +68,18 @@ import { requireDesktop } from '@/lib/platform/desktop-only';
const noop = () => {}; const noop = () => {};
// Compose step → the composing-presence mode broadcast to other viewers.
const STEP_TO_COMPOSING_MODE: Record<ComposeStep, ComposingMode | null> = {
idle: null,
submitting: null,
recording: 'recording',
typing: 'typing',
task: 'typing',
reviewing: 'typing',
configuring: 'typing',
picking: 'screen',
};
function getReactions( function getReactions(
particle: Particle, particle: Particle,
): Record<string, string[]> | undefined { ): Record<string, string[]> | undefined {
@@ -321,18 +333,7 @@ function StreamViewInner({ path, streamParticle }: StreamViewProps) {
// Broadcast composing state to other viewers // Broadcast composing state to other viewers
useEffect(() => { useEffect(() => {
const stepToMode: Record<string, ComposingMode | null> = { const mode = STEP_TO_COMPOSING_MODE[composeStep] ?? null;
idle: null,
submitting: null,
recording: 'recording',
typing: 'typing',
task: 'typing',
event: 'typing',
reviewing: 'typing',
configuring: 'typing',
picking: 'screen',
};
const mode = stepToMode[composeStep] ?? null;
if (mode) { if (mode) {
startComposing(mode); startComposing(mode);
} else { } else {
@@ -575,6 +576,7 @@ function StreamViewInner({ path, streamParticle }: StreamViewProps) {
networkId={networkId} networkId={networkId}
currentIndex={currentIndex} currentIndex={currentIndex}
onSelect={goTo} onSelect={goTo}
onToggle={toggleViewMode}
/> />
)} )}
</div> </div>
-1
View File
@@ -89,4 +89,3 @@ export function getParticleDisplayName(particle: Particle): string {
return 'Unsupported particle'; return 'Unsupported particle';
} }
} }