File size: 2,437 Bytes
abcf568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import { useMemo, useState } from 'react'
import { useStudioSession } from '../../hooks/use-studio-session'
import { areSameIds, computeMaxHistorySlots, orderWorkSummaries } from '../utils/work-order'

export function usePlotStudioShell() {
  const studio = useStudioSession({
    studioKind: 'plot',
    title: 'Plot Studio'
  })
  const [selectedWorkId, setSelectedWorkId] = useState<string | null>(null)
  const [orderedWorkIds, setOrderedWorkIds] = useState<string[]>([])
  const [confirmExitOpen, setConfirmExitOpen] = useState(false)
  const [interruptArmedUntil, setInterruptArmedUntil] = useState<number | null>(null)

  const orderedWorkSummaries = useMemo(
    () => orderWorkSummaries(studio.workSummaries, orderedWorkIds),
    [orderedWorkIds, studio.workSummaries]
  )

  const effectiveSelectedWorkId =
    selectedWorkId && orderedWorkSummaries.some((entry) => entry.work.id === selectedWorkId)
      ? selectedWorkId
      : orderedWorkSummaries[0]?.work.id ?? null

  const selected = studio.selectWork(effectiveSelectedWorkId)
  const historyCount = orderedWorkSummaries.length
  const historyCountLabel = String(historyCount).padStart(2, '0')
  const maxHistorySlots = computeMaxHistorySlots(historyCount)
  const interruptHintActive = interruptArmedUntil !== null && interruptArmedUntil > Date.now()

  const handleReorderWorks = (nextWorkIds: string[]) => {
    setOrderedWorkIds((current) => (areSameIds(current, nextWorkIds) ? current : nextWorkIds))
  }

  const handleEscapePress = () => {
    const activeRun = studio.latestRun
    const runIsInterruptible = activeRun && (activeRun.status === 'pending' || activeRun.status === 'running')
    if (!runIsInterruptible) {
      setInterruptArmedUntil(null)
      return
    }

    const now = Date.now()
    if (interruptArmedUntil && interruptArmedUntil > now) {
      setInterruptArmedUntil(null)
      void studio.cancelCurrentRun('Cancelled by double-escape in Plot Studio')
      return
    }

    setInterruptArmedUntil(now + 3000)
    window.setTimeout(() => {
      setInterruptArmedUntil((current) => (current && current <= Date.now() ? null : current))
    }, 3100)
  }

  return {
    studio,
    selected,
    orderedWorkSummaries,
    effectiveSelectedWorkId,
    historyCountLabel,
    maxHistorySlots,
    confirmExitOpen,
    setConfirmExitOpen,
    interruptHintActive,
    setSelectedWorkId,
    handleReorderWorks,
    handleEscapePress,
  }
}