Skip to main content

App

Struct App 

Source
pub struct App {
Show 33 fields pub stage: Stage, pub previous_stage: Stage, pub focused_pane: Pane, pub team: TeamSnapshot, pub selected_agent: Option<usize>, pub detail_buffer: Vec<String>, pub version: &'static str, pub capabilities: Capabilities, pub splash_started: Instant, pub last_refresh: Instant, pub running: bool, pub tutorial_completed: bool, pub mailbox_tab: MailboxTab, pub mailbox: MailboxBuffers, pub pending_approvals: Vec<Approval>, pub selected_approval: usize, pub approval_error: Option<String>, pub compose_target: Option<ComposeTarget>, pub compose_editor: Editor, pub compose_error: Option<String>, pub layout: MainLayout, pub wall_scroll: usize, pub selected_channel: Option<usize>, pub detail_splits: Vec<(String, SplitOrientation)>, pub selected_split: usize, pub pending_chord: Option<KeyCode>, pub tutorial_pending_for_team: bool, pub spinner_frame: usize, pub tutorial_step: usize, pub compose_picker_open: bool, pub compose_picker_index: usize, pub compose_attach_input_open: bool, pub compose_attach_buffer: String,
}

Fields§

§stage: Stage§previous_stage: Stage

Tracked so QuitConfirm can return to whichever stage opened it.

§focused_pane: Pane§team: TeamSnapshot§selected_agent: Option<usize>

Index into team.agents of the agent the detail pane is streaming. None when the team is empty or roster navigation hasn’t picked one yet.

§detail_buffer: Vec<String>

Lines from the most recent pane capture. Bounded to the last MAX_DETAIL_LINES so the buffer doesn’t grow unboundedly over a long-running session.

§version: &'static str§capabilities: Capabilities§splash_started: Instant§last_refresh: Instant

Last time the snapshot + pane capture were refreshed. Used by tick() to gate the next refresh.

§running: bool§tutorial_completed: bool

First-launch detection — when the marker file exists, future stacked-PRs (PR-UI-7) skip the tutorial after splash. PR-UI-1 only reads the flag; nothing routes off it yet.

§mailbox_tab: MailboxTab

Active tab inside the mailbox pane (PR-UI-3). Walked with / when focused_pane == Mailbox (T-124 hard-swapped the prior [ / ] chord for arrow keys; T-074 bug 6 is the gating-on-focus invariant). Tab always cycles pane focus, never mailbox tabs — the previous “Tab cycles tabs when mailbox is focused” shape stranded operators inside the mailbox.

§mailbox: MailboxBuffers

Per-tab buffers + cursors for the focused agent’s mailbox view. Reset whenever the focused agent changes — switching agents starts the operator at the head of fresh traffic.

§pending_approvals: Vec<Approval>

Pending approvals snapshot (PR-UI-4). Drives the conditional stripe at the top of Triptych and the modal opened by a.

§selected_approval: usize

Index into pending_approvals of the row the modal is currently showing. Reset to 0 each time the modal opens; j / k (or / ) cycle.

§approval_error: Option<String>

Last error from a CLI-routed Approve/Deny call — surfaced inline in the modal so the operator sees why a decision didn’t take.

§compose_target: Option<ComposeTarget>

Open compose target — Some while Stage::ComposeModal is the active stage, None otherwise. Stored on App so the editor’s contents survive rerenders.

§compose_editor: Editor

Editor backing the compose modal. Reset to default() each time the modal opens so an old draft from a prior invocation can’t leak into a new send.

§compose_error: Option<String>

Last error from a CLI-routed send call — surfaced inline in the modal so the operator sees rate-limit / ACL-block errors without leaving the UI.

§layout: MainLayout

Active main-view layout (PR-UI-6). Triptych is the default; Ctrl+W toggles Wall, Ctrl+M toggles MailboxFirst.

§wall_scroll: usize

Top-of-window agent index for the Wall view’s vertical scroll. SPEC §3 caps visible tiles at 4; this offsets which 4-agent window is shown when the team has more.

§selected_channel: Option<usize>

Selected channel index (into team.channels) for the MailboxFirst layout’s channel list and for the broadcast picker. None until the operator picks one.

§detail_splits: Vec<(String, SplitOrientation)>

Splits within Triptych’s detail pane (PR-UI-6). When non-empty, the detail pane subdivides; each entry pairs an agent id with the per-split orientation (PR-UI-7 lift of the Q1 deferral). selected_split is the vim-window-motion focus.

§selected_split: usize§pending_chord: Option<KeyCode>

Chord-prefix machine for Ctrl+W follow-ups (PR-UI-7 lift of PR-UI-6’s Ctrl+Q alias). When Some(KeyCode::Char('w')), the next key is interpreted as a Ctrl+W follow: q = close split, o = close others. Cleared on any unrelated keypress so a typo doesn’t leave the editor stuck.

§tutorial_pending_for_team: bool

true when the operator’s first launch on this team has not yet completed the tutorial — drives the auto-open after splash. Reset to false on tutorial completion.

§spinner_frame: usize

Brand-spinner frame counter (PR-UI-7). Bumped each refresh tick so the statusline indicator shows the app is alive.

§tutorial_step: usize

Tutorial step cursor (PR-UI-7). Index into onboarding::STEPS; reset to 0 when the tutorial reopens.

§compose_picker_open: bool

Modal substage for the broadcast channel picker (PR-UI-6). When true the compose modal renders a picker over the editor; selecting a channel populates compose_target and drops back to the editor.

§compose_picker_index: usize

Picker selection cursor — index into team.channels.

§compose_attach_input_open: bool

T-32: when true, the compose modal renders a single-line path-input overlay instead of the editor; Enter appends a 📎 attachment: <path> line to the editor body and closes the overlay. Tab inside the editor opens it; Esc inside the overlay cancels back to the editor (matches the picker overlay’s modal-vs-modal symmetry from PR-UI-6).

§compose_attach_buffer: String

Single-line buffer for the path-input overlay. Reset on close so a cancelled draft can’t leak into the next attach attempt.

Implementations§

Source§

impl App

Source

pub fn new() -> Self

Construct an empty App — no team snapshot loaded. Used by tests and as the splash-stage default. Production launch goes through App::launch() which immediately runs an initial refresh() so the splash screen already shows the real team name + agent count.

Source

pub fn enter_help_overlay(&mut self)

Per-tutorial-step cursor (used by Stage::Tutorial). Wraps at the end so t-then-keys walks the full tour.

Source

pub fn close_help_overlay(&mut self)

Source

pub fn enter_tutorial(&mut self)

Source

pub fn close_tutorial(&mut self)

Source

pub fn tutorial_advance(&mut self)

Source

pub fn tutorial_back(&mut self)

Source

pub fn toggle_wall_layout(&mut self)

Source

pub fn toggle_mailbox_first_layout(&mut self)

Source

pub fn wall_scroll_up(&mut self)

Source

pub fn wall_scroll_down(&mut self)

Source

pub fn select_next_channel(&mut self)

Source

pub fn select_prev_channel(&mut self)

Source

pub fn add_detail_split_vertical(&mut self)

Add a split for the focused agent (or current selection) to the detail pane. Cap at 4 splits per the SPEC §3 cap. Add a vertical split (PR-UI-7). Ctrl+| calls this.

Source

pub fn add_detail_split_horizontal(&mut self)

Add a horizontal split (PR-UI-7). Ctrl+- calls this.

Source

pub fn add_detail_split(&mut self)

Back-compat shim — earlier PRs called the unsuffixed name. Defaults to vertical (matching the most-common chord Ctrl+|). Kept so the test surface PR-UI-6 pinned doesn’t drift.

Source

pub fn close_focused_split(&mut self)

Source

pub fn cycle_split_next(&mut self)

Source

pub fn cycle_split_prev(&mut self)

Source

pub fn enter_compose_broadcast_with_picker(&mut self)

Open the broadcast compose flow — picker first when at least one channel is declared, else fall back to the project’s all channel (PR-UI-5 behaviour) on the assumption that all always exists in production composes.

Source

pub fn picker_next(&mut self)

Source

pub fn picker_prev(&mut self)

Source

pub fn picker_confirm(&mut self)

Source

pub fn open_compose_attach_input(&mut self)

T-32: open the path-input overlay. Resets the buffer so a previously-cancelled draft can’t carry over.

Source

pub fn confirm_compose_attach_input(&mut self)

T-32: append a 📎 attachment: <path> line to the compose editor and close the overlay. The line lands as a fresh row at the end of the body so the operator can edit it (or delete it) before sending. Whitespace-only buffers are ignored — Tab followed by Enter shouldn’t insert an empty marker.

Source

pub fn close_compose_attach_input(&mut self)

Source

pub fn cycle_mailbox_tab(&mut self)

Source

pub fn cycle_mailbox_tab_back(&mut self)

Source

pub fn cycle_focus_back(&mut self)

Source

pub fn has_pending_approvals(&self) -> bool

Source

pub fn enter_approvals_modal(&mut self)

Source

pub fn close_approvals_modal(&mut self)

Source

pub fn cycle_approval_next(&mut self)

Source

pub fn cycle_approval_prev(&mut self)

Source

pub fn focused_approval(&self) -> Option<&Approval>

Source

pub fn replace_approvals(&mut self, approvals: Vec<Approval>)

Replace the pending-approvals list. Closes the modal when the queue empties (no row to act on); preserves the modal otherwise but clamps selected_approval into range so an approval resolved out-of-band doesn’t leave us pointing at a stale index.

Source

pub fn apply_decision<D: ApprovalDecider>( &mut self, decider: &D, kind: Decision, note: &str, )

Apply a decision to the focused approval via the injected decider. The decider routes through teamctl approve|deny in production; tests inject a recorder. On success the row gets removed from the local pending_approvals snapshot optimistically — the next refresh_approvals will reconcile against the broker.

Source

pub fn enter_compose_dm_for_focused(&mut self)

Open the compose modal for the focused agent (if any). The @ chord. No-op when no agent is focused.

Source

pub fn enter_compose_broadcast(&mut self)

Open the compose modal targeting the project’s all channel — the broadcast wire. The ! chord. PR-UI-5 ships with channel scoping limited to all (the Wire tab is the only channel context the mailbox pane currently surfaces); PR-UI-6’s mailbox UI work will widen the scope to per-channel targets when individual channels become first-class in the pane.

Source

pub fn close_compose_modal(&mut self)

Source

pub fn apply_send<S: MessageSender, M: MailboxSource>( &mut self, sender: &S, mailbox_source: &M, )

Send the current compose body via the injected message sender. Routes through teamctl send|broadcast in production; tests inject a recorder. Closes the modal + triggers a mailbox refresh on success; surfaces error inline on failure.

Source

pub fn dismiss_splash(&mut self)

Source

pub fn cycle_focus(&mut self)

Source

pub fn select_prev(&mut self)

Move roster selection up by one — wraps at the top. No-op when the team is empty. Does not change focused_pane. Resets mailbox buffers when the resulting agent id differs from the prior selection — switching agents should start the operator at the head of fresh traffic.

Source

pub fn select_next(&mut self)

Move roster selection down by one — wraps at the bottom. No-op when the team is empty.

Source

pub fn selected_agent_id(&self) -> Option<String>

<project>:<agent> of the currently selected agent, if any.

Source

pub fn enter_quit_confirm(&mut self)

Source

pub fn cancel_quit(&mut self)

Source

pub fn confirm_quit(&mut self)

Source

pub fn replace_team(&mut self, team: TeamSnapshot)

Replace the team snapshot. Preserves the current selection when the agent at that index still exists; otherwise resets to the first agent (or None for an empty team). Resets the mailbox buffers when the resulting agent id differs from the prior selection — same agent-changed contract as select_next / select_prev.

Source

pub fn focused_session(&self) -> Option<&str>

Return the focused agent’s tmux session name, if any. Used by the run loop to know which session to capture.

Source

pub fn stream_target_session(&self) -> Option<String>

Tmux session that stream-keys mode should target. Cell 0 of the detail-pane split layout is always the focused agent; cells 1..N are the entries in detail_splits. When the operator has focused a non-zero split, route stream-keys to that split’s agent — that’s the cell visually showing as the focus ring, so it’s the one the operator expects to type into.

Source

pub fn enter_stream_keys(&mut self)

Enter stream-keys mode. No-op unless an agent is selected — without a target session there’s nothing to forward to. Caller is responsible for the focused-pane gate (entry chord only fires from focused_pane == Pane::Detail).

Source

pub fn exit_stream_keys(&mut self)

Exit stream-keys mode and return to whichever stage opened it. Esc is the only exit chord per the issue’s recommendation — every other key (including Ctrl+C) forwards to the agent.

Source

pub fn set_detail_buffer(&mut self, lines: Vec<String>)

Replace the detail buffer, clipped at the recent-line cap.

Trait Implementations§

Source§

impl Default for App

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for App

§

impl RefUnwindSafe for App

§

impl Send for App

§

impl Sync for App

§

impl Unpin for App

§

impl UnsafeUnpin for App

§

impl UnwindSafe for App

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.