feat(dashboard): highlight proposals pane + bell on new proposal #50
@@ -1356,6 +1356,11 @@ def _main_loop(stdscr: "curses._CursesWindow") -> None:
|
|||||||
# pre-existing queue entries on its first poll; those
|
# pre-existing queue entries on its first poll; those
|
||||||
# shouldn't ring the bell as if they just arrived.
|
# shouldn't ring the bell as if they just arrived.
|
||||||
saw_first_tick = False
|
saw_first_tick = False
|
||||||
|
# The dashboard's own tmux pane id (tmux sets `$TMUX_PANE`
|
||||||
|
# per-pane). Captured at startup so a new-proposal arrival
|
||||||
|
# can `tmux select-pane` back to the dashboard from
|
||||||
|
# whatever pane the operator is currently in.
|
||||||
|
dashboard_pane_id = os.environ.get("TMUX_PANE", "")
|
||||||
while True:
|
while True:
|
||||||
pending = discover_pending()
|
pending = discover_pending()
|
||||||
if selected >= len(pending):
|
if selected >= len(pending):
|
||||||
@@ -1367,16 +1372,29 @@ def _main_loop(stdscr: "curses._CursesWindow") -> None:
|
|||||||
|
|
||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
live_ids = {qp.proposal.id for qp in pending}
|
live_ids = {qp.proposal.id for qp in pending}
|
||||||
# Detect proposals we've never seen before — used to ring
|
# Detect proposals we've never seen before. Triggers:
|
||||||
# the terminal bell (so tmux's monitor-bell or the
|
# - terminal bell (`curses.beep` → tmux's monitor-bell)
|
||||||
# terminal's own bell-on-activity surface a notice when
|
# - tmux focus jump to the dashboard pane (so the
|
||||||
# the operator isn't looking at the dashboard pane).
|
# operator notices even if they were typing at claude)
|
||||||
|
# - dashboard's internal focus flip to the proposals
|
||||||
|
# pane (so j/k navigates the queued items immediately)
|
||||||
newly_arrived = live_ids - first_seen.keys()
|
newly_arrived = live_ids - first_seen.keys()
|
||||||
if saw_first_tick and newly_arrived:
|
if saw_first_tick and newly_arrived:
|
||||||
try:
|
try:
|
||||||
curses.beep()
|
curses.beep()
|
||||||
except curses.error:
|
except curses.error:
|
||||||
pass
|
pass
|
||||||
|
if dashboard_pane_id and _in_tmux():
|
||||||
|
_tmux_select_pane(dashboard_pane_id)
|
||||||
|
focus = PANE_PROPOSALS
|
||||||
|
# Land the cursor on the first new proposal so the
|
||||||
|
# operator can act immediately. Proposals are sorted
|
||||||
|
# by arrival_timestamp ascending; find the lowest
|
||||||
|
# index whose id is in `newly_arrived`.
|
||||||
|
for i, qp in enumerate(pending):
|
||||||
|
if qp.proposal.id in newly_arrived:
|
||||||
|
selected = i
|
||||||
|
break
|
||||||
for proposal_id in live_ids:
|
for proposal_id in live_ids:
|
||||||
first_seen.setdefault(proposal_id, now)
|
first_seen.setdefault(proposal_id, now)
|
||||||
for stale_id in list(first_seen.keys() - live_ids):
|
for stale_id in list(first_seen.keys() - live_ids):
|
||||||
|
|||||||
Reference in New Issue
Block a user