pub struct App {Show 51 fields
pub mode: Mode,
pub top_mode: TopMode,
pub nav_display: NavDisplay,
pub milestone_mode: bool,
pub board: BoardState,
pub theme: Theme,
pub detail: Option<DetailState>,
pub form: Option<FormState>,
pub confirm_delete_target: Option<String>,
pub store: Store,
pub status_msg: Option<String>,
pub action_feedback: Option<ActionFeedback>,
pub quit: bool,
pub bindings: EffectiveBindings,
pub active_config: usize,
pub tabs: BoardTabs,
pub show_archived: bool,
pub show_children: bool,
pub filter_modal: Option<FilterModal>,
pub settings: Option<SettingsModal>,
pub planning: Option<PlanningModal>,
pub planning_form: Option<PlanningForm>,
pub date_picker: Option<DatePicker>,
pub action_menu: Option<ActionMenu>,
pub bulk: Option<BulkModal>,
pub bulk_action_targets: Option<Vec<u32>>,
pub views: Option<ViewsModal>,
pub triage: Option<TriageState>,
pub cycle_state: Option<CycleState>,
pub repos_cursor: usize,
pub recurring_warning: Option<RecurringWarning>,
pub mentions: Option<MentionsView>,
pub mentions_view: Option<MentionsView>,
pub unread_mentions: usize,
pub mention_candidates: Vec<String>,
pub wip: WipSnapshot,
pub wip_override: Option<WipOverridePrompt>,
pub health_form: Option<HealthForm>,
pub stats_tab: StatsTab,
pub stats_time: Option<StatsTimeState>,
pub stats_burndown: Option<BurndownState>,
pub time_form: Option<TimeForm>,
pub time_filter_form: Option<TimeFilterForm>,
pub stats_cursor: usize,
pub health: Option<PortableHealth>,
pub schedule: Option<ScheduleState>,
pub library: Option<LibraryState>,
pub portfolio: Option<PortfolioState>,
pub roadmap_filter: RoadmapFilter,
pub portfolio_roadmap_overlay: Option<RoadmapOverlay>,
pub tips: Option<TipsState>,
/* private fields */
}Expand description
Independent toggles are what a TUI session’s state is — the mode lives in Mode,
and the flags beside it (archived shown, help line open, one-shot exit) are not
states a machine would model, they are switches the user throws. Four is not a
design smell here; a struct with a mode enum and a handful of toggles is the shape.
Fields§
§mode: Mode§top_mode: TopModeThe active top-level mode of the shell (tui-mode-navigation). Session-only:
it is derived from the current Mode by App::sync_top_mode and never
persisted.
How the vertical mode navigation is displayed (Off/Small/Default).
Session-only, cycled by toggle_navigation; never persisted.
milestone_mode: boolWhether the Config surface is currently standing in for the F5
Milestones mode. The Milestones mode reuses the Config surface pinned
to ConfigSection::Milestones rather than growing a second view; this
flag is what makes the rail highlight Milestones (not Config), gives the
mode its own InputContext::Milestones keys, and hides the Config
section rail. Session-only, never persisted.
board: BoardState§theme: ThemeResolved tag/type/milestone colors for this session (tix #1530). Built once at startup from the tag store and the config; the board and detail renderers read it.
detail: Option<DetailState>§form: Option<FormState>§confirm_delete_target: Option<String>§store: Store§status_msg: Option<String>§action_feedback: Option<ActionFeedback>The last advertised action this mode refused, with the remedy that would make it possible. Cleared when the next key is accepted, so a refusal is visible on the frame that produced it and never leaks into a later mode.
quit: bool§bindings: EffectiveBindings§active_config: usizeThe active named board configuration index into Config::configs()
(session state only — never persisted). rebuild_board/apply_filter
must not reset it.
tabs: BoardTabsPersistent tabs bar of all named boards (DM-01M2MH8J01DZHV3JMT76XX38KX).
show_archived: boolWhether the board is showing archived issues too (tix #1492).
Off by default, and that default is the point: the board and the corpus are
built from crate::storage::Store::list, which drops a dot-prefixed file
from the directory entry without opening it, so a repository with thousands of
archived issues costs nothing to open. Toggling this on is the “reload them on
demand” half — refresh_corpus re-reads the issue set with the archived files
included and rebuilds the board around it.
show_children: boolWhether the board draws each issue’s sub-issues beneath it (tix #1399).
On by default. Session-only, like App::show_archived — it is a view
preference, not a setting written back to tix.toml. The u toggle flips it
and rebuilds the board, which reorders each column so a sub-issue follows its
parent offset one ASCII column (see BoardState::build_with); no store
re-read is needed because the children are already in the issue set.
filter_modal: Option<FilterModal>§settings: Option<SettingsModal>Config mode state (F12, s, b): the active section and the dashboards
row cursor. Some exactly while Mode::Settings (and its planning
sub-forms) is active.
planning: Option<PlanningModal>Planning cursor: the m management surface’s list state, and the same
cursor the Config mode’s cycles/milestones sections drive (one state, not
two).
planning_form: Option<PlanningForm>Create/edit form for a planning item.
date_picker: Option<DatePicker>Open calendar date picker (overlaid on the form that opened it).
The issue action menu: Some exactly while mode is
Mode::ActionMenu.
bulk: Option<BulkModal>The batch modal (WP07), Some exactly while mode is
Mode::BulkModal.
bulk_action_targets: Option<Vec<u32>>The marked set a content action (comment, health, parent) covers, or
None when the action is about the detail pane’s single issue. Set when
the action menu opens on a card that is part of a multi-selection, and
cleared when the prompt submits or cancels.
views: Option<ViewsModal>The saved-views modal (WP05), Some exactly while mode is
Mode::Views. Its rows mirror the registry; its cursor, prompt, and
feedback are its own.
triage: Option<TriageState>The triage inbox (WP06), Some exactly while mode is
Mode::TriageInbox. Its cursor and selection are its own — see the
note on that mode.
cycle_state: Option<CycleState>The F3 Cycle mode’s cursor (tui-cycle-mode), Some exactly while mode
is Mode::Cycle. Its selection is its own, like the triage inbox’s.
repos_cursor: usizeThe F6 Repos mode’s row cursor (tix #1529). Session-only; reset when the mode is entered.
recurring_warning: Option<RecurringWarning>The due-warning overlay (WP07), Some exactly while mode is
Mode::RecurringWarning.
mentions: Option<MentionsView>The per-issue mention notice, Some exactly while it is open.
mentions_view: Option<MentionsView>The all-issues mentions view, Some exactly while it is open.
unread_mentions: usizeHow many unread mentions the local user holds — the indicator row’s figure.
Cached because counting reads the mention store, and a render pass must not
touch the disk. Recomputed by App::refresh_mentions, which runs at
startup, on every refresh, and after every mention action, so the indicator
cannot disagree with the rows a notice is showing.
mention_candidates: Vec<String>The mention bodies that address the local user, from git (design D6), cached
beside App::unread_mentions so the two are always the same snapshot.
wip: WipSnapshotThe board’s WIP state, derived once per refresh (WP05 T025). Empty for a board with no limits, and rebuilt from the corpus rather than re-read: the figures a header shows are the ones the policy judged the move against.
wip_override: Option<WipOverridePrompt>The override prompt (WP05 T026), Some exactly while mode is
Mode::WipOverride.
health_form: Option<HealthForm>The health form being filled in, when one is open.
stats_tab: StatsTabThe F7 Stats page’s active tab (WP05 T026). A tab on a page that already
ships — not a mode — exactly as crate::ui::roadmap documents for the F10
Portfolio page.
stats_time: Option<StatsTimeState>The Time tab’s one read and its session state, Some exactly while the tab has
been opened. Rebuilt on entering the tab and after every mutation, so a render
never reads the disk.
stats_burndown: Option<BurndownState>The Burndown tab’s selections and its one read (WP06 T029–T032), Some exactly
while the tab has been opened.
The document inside it is the shared crate::analytics::chart::ChartExport the
CLI’s verbs read, rebuilt when the tab is opened and after every control — never
during a render, and never from a second fold of its own.
time_form: Option<TimeForm>The time-entry form being filled in, when one is open.
time_filter_form: Option<TimeFilterForm>The Time tab’s filter editor, when it is open.
stats_cursor: usizeThe F7 Stats page’s row cursor.
health: Option<PortableHealth>The health document for the whole repository (mission
project-issue-health-status-01M3C8HX, WP06): the same DTO the CLI renders,
so the card badge, the detail block and the F7 page cannot describe a
different snapshot from tix health (C-007).
Refreshed wherever the board is rebuilt, and never computed per keystroke: the document is one pass over the issues, and a render must not read the disk.
schedule: Option<ScheduleState>The F8 Schedule page’s state: the active tab, its cursor and any reason
prompt (tix #1593/#181), Some exactly while mode is Mode::Schedule.
library: Option<LibraryState>The F11 Library page’s state (tix #1593), Some exactly while mode is
Mode::Library: the active tab and its row cursor. Session-only, reset
when the mode is entered.
portfolio: Option<PortfolioState>The F10 Portfolio page’s state (WP06), Some exactly while mode is
Mode::Portfolio: the active tab and its row cursor. Session-only, reset
when the mode is entered.
roadmap_filter: RoadmapFilterThe Roadmap tab’s normalized filter (WP05), the one DTO the CLI builds too. Session-only: reset when the page is entered, and never persisted.
portfolio_roadmap_overlay: Option<RoadmapOverlay>The Roadmap tab’s open overlay (WP05): the filter editor or an initiative
action, Some exactly while one is open. Cleared with the page’s other state
and on a tab change, so its text never leaks onto another tab.
tips: Option<TipsState>The startup tips modal (tix #1632), Some exactly while mode is
Mode::Tips. Its index is into the embedded crate::tips::all slice.
Implementations§
Source§impl App
impl App
Sourcepub fn refresh_mentions(&mut self)
pub fn refresh_mentions(&mut self)
Recompute the local user’s mention candidates and unread count.
Read-only, and cheap by construction: the candidates are one git config
read and the count is the unread records in the one or two files those
candidates name — never a scan of the issue tree (design D7).
Source§impl App
impl App
Sourcepub fn apply_triage_action(&mut self, action: Action) -> Result<Action>
pub fn apply_triage_action(&mut self, action: Action) -> Result<Action>
Run a Triage-mode pointer action recorded during the draw. Public so the hit-region tests drive the same path the run loop does.
Source§impl App
impl App
Sourcepub fn active_cycle_name(&self) -> Option<String>
pub fn active_cycle_name(&self) -> Option<String>
The name of the cycle the rail should mark active: the F3 Cycle mode’s
cursor target, or None when that mode is not the shell’s top mode.
Read from the rendered flat order (crate::ui::cycle::flat_entries)
— the same order the listing highlights and the issue table lists — so
the bold limb names the cycle the mode is actually showing. Gated on the
top mode so a cycle does not stay bold after the user has moved to
another surface, and bounds-guarded so a stale cursor past the last entry
names no cycle rather than panicking.
Sourcepub fn active_milestone_name(&self) -> Option<String>
pub fn active_milestone_name(&self) -> Option<String>
The name of the milestone the rail should mark active: the F5 Milestones
mode’s cursor target, or None otherwise.
Gated on milestone_mode and the top mode, so the Config mode’s own
milestones section never bolds a row through this path (its cursor is the
same planning.selected, but the F12 surface is not the F5 mode).
Sourcepub fn select_cycle_row(&mut self, index: usize)
pub fn select_cycle_row(&mut self, index: usize)
Select the cycle row a click landed on — mouse parity with j/k.
Source§impl App
impl App
Sourcepub fn apply_filter_modal_action(&mut self, action: Action) -> Result<Action>
pub fn apply_filter_modal_action(&mut self, action: Action) -> Result<Action>
Run a filter-modal pointer action recorded during the draw. Public so the hit-region tests drive the same path the run loop does.
Source§impl App
impl App
Sourcepub fn library_entries(&self, tab: LibraryTab) -> Vec<LibraryEntry>
pub fn library_entries(&self, tab: LibraryTab) -> Vec<LibraryEntry>
One row per record in tab, in registry order.
The Views tab reads the same Self::view_rows the v modal does — one
interpretation of a view, so the page cannot disagree with the modal about
a name, a scope or the active marker.
Sourcepub fn library_detail(
&self,
tab: LibraryTab,
index: usize,
) -> Option<LibraryDetail>
pub fn library_detail( &self, tab: LibraryTab, index: usize, ) -> Option<LibraryDetail>
The selected record’s detail pane: the facts the record actually holds, read from the registry rather than re-derived from a rendering.
Source§impl App
impl App
Sourcepub fn handle_mouse(&mut self, mouse: MouseEvent) -> Result<Action>
pub fn handle_mouse(&mut self, mouse: MouseEvent) -> Result<Action>
Route a MouseEvent into the active mode’s pointer handler (D2),
mirroring App::handle_key: one dispatch trunk per mode, so mouse and
keyboard share the same single-mode mental model. Modes that declare no
mouse behavior fall through to a no-op. Per-mode handlers land with the
click/hover/dialog tasks.
Sourcepub fn record_region(&self, rect: Rect, action: Action)
pub fn record_region(&self, rect: Rect, action: Action)
Record a click target bounding rect for the current draw (D3).
Widgets call this while rendering; handle_mouse resolves the region
under a pointer via App::resolve_region. Regions are cleared at the
start of every frame, so stale targets from previous frames never fire.
Sourcepub fn is_hovered(&self, action: &Action) -> bool
pub fn is_hovered(&self, action: &Action) -> bool
Whether action’s hit region is the one the pointer is currently over.
Widgets use this to style themselves on hover without owning any pointer
state; the value is refreshed by each Moved event (see handle_mouse).
Source§impl App
impl App
The navigation tree: each trunk mode with the limbs drawn under it (tui-mode-navigation).
Built from the live config and registry, so the rail cannot disagree with
the surfaces a branch activates. Boards, cycles and templates come from
Config; only the milestone names touch the filesystem (a directory
listing of tiny records), and an empty group renders no rows.
Sourcepub fn repo_entries(&self) -> Vec<(String, PathBuf, bool)>
pub fn repo_entries(&self) -> Vec<(String, PathBuf, bool)>
The repositories the F6 Repos mode lists, in display order: the
configured children ([repos], in declaration order) followed by the
parent when one is known (tix #1529).
One level deep by construction: the children come from this config and
the parent from parent_repo (or the TIX_PARENT_REPO the parent set
when spawning us). A child’s own children are reached by running tix
there, never by walking from here.
The column width the rail needs for its current content.
Grown past NavDisplay::width so the widest trunk or branch line is
drawn whole (one space of separation from the content area) rather than
clipped — that is what lets Default show a full branch name.
Sourcepub fn mode_label(&self, mode: TopMode) -> &'static str
pub fn mode_label(&self, mode: TopMode) -> &'static str
The trunk label for mode: the singular name, or the plural when the
mode owns more than one record — boards by configured count, cycles
by Planner::cycle_names, milestones by Planner::list_milestones.
The chord is never affected; only the noun moves.
The rail’s rows in draw order — each trunk followed by its limbs, exactly
as crate::ui::nav::render paints them. The keyboard cursor indexes
this list; the pointer’s hit regions come from the same tree.
The index of the rail row holding the keyboard cursor, None when the
mode content owns the keyboard.
Whether rail row index holds the keyboard cursor. The rail draws such a
row exactly like a hovered one.
Source§impl App
impl App
Sourcepub fn library_state(&self) -> LibraryState
pub fn library_state(&self) -> LibraryState
The Library page’s state (tix #1593), or a fresh default when the page is
not open. The renderer and the key handler both read it, and mode already
says whether the page is live, so a missing state is never an error.
Sourcepub fn portfolio_state(&self) -> PortfolioState
pub fn portfolio_state(&self) -> PortfolioState
The Portfolio page’s state (WP06), or a fresh default when the page is not
open. The renderer and the key handler both read it, and mode already says
whether the page is live, so a missing state is never an error.
Sourcepub fn projects_snapshot(&self) -> Vec<Project>
pub fn projects_snapshot(&self) -> Vec<Project>
The service’s project list as the CLI reads it (WP06).
Built from store.list_all() — archived issues included — because that
is the set tix project list and tix project show count over: the page’s
figures and the CLI’s are the same figures, and neither moves when the board’s
archive toggle does. The result is cached (Self::refresh_portfolio_projects)
and dropped when the page is left, so drawing the page per frame does not
re-read the issue tree (NFR-001).
Nothing is derived here: member_count comes from
crate::projects::list_projects, which owns the membership rule (C-006).
Sourcepub fn portfolio_reports(&self) -> BTreeMap<ProjectId, ProjectHealthReport>
pub fn portfolio_reports(&self) -> BTreeMap<ProjectId, ProjectHealthReport>
The Portfolio page’s typed project health, as the CLI reads it (WP09).
Cached beside Self::projects_snapshot from the same snapshot, so the
page’s progress and health figures are the values tix project show prints
and no surface derives a second one (C-006). Empty when the page is not open
or the read failed; the detail pane then renders the record alone.
Sourcepub fn portfolio_epics(&self) -> &[EpicViewEntry]
pub fn portfolio_epics(&self) -> &[EpicViewEntry]
The Portfolio page’s Epics tab rows, as the CLI reads them (WP06 T032).
The same crate::commands::view::epic_view value the epic view renders, so
the tab and the CLI cannot disagree about a figure (C-008). Empty when the
page is not open or the read failed; the tab then draws its explicit empty
state rather than a fabricated row.
Sourcepub fn portfolio_roadmap(&self) -> Option<&RoadmapProjection>
pub fn portfolio_roadmap(&self) -> Option<&RoadmapProjection>
The Portfolio page’s Roadmap tab projection (WP05), or None while the
page has not built one.
The same crate::roadmap::projection::project value tix roadmap list
renders, so the tab’s rows, summaries and diagnostics are the CLI’s (C-004,
C-007).
Sourcepub fn roadmap_filter(&self) -> &RoadmapFilter
pub fn roadmap_filter(&self) -> &RoadmapFilter
The Roadmap tab’s normalized filter (WP05).
Sourcepub fn roadmap_overlay(&self) -> Option<&RoadmapOverlay>
pub fn roadmap_overlay(&self) -> Option<&RoadmapOverlay>
The Roadmap tab’s open overlay (WP05), if any.
Sourcepub fn roadmap_registry_is_empty(&self) -> bool
pub fn roadmap_registry_is_empty(&self) -> bool
Whether the initiative registry is empty (for the tab’s explicit empty state).
Source§impl App
impl App
Sourcepub fn cycle_schedule_evaluation(&self) -> Option<&CycleEvaluation>
pub fn cycle_schedule_evaluation(&self) -> Option<&CycleEvaluation>
The last evaluation, or None before the first pass.
Sourcepub fn schedule_help_tab(&self) -> Option<ScheduleTab>
pub fn schedule_help_tab(&self) -> Option<ScheduleTab>
The F8 Schedule page’s active tab, and None in every other mode.
The ? overlay is the one surface that has to know it: the page’s two tabs
act on different keys, and an overlay that advertised the Series keys while the
Cycle schedules tab is showing would name two keys that do nothing there
(WP07 review). The overlay is drawn while mode is Mode::Help, so the page
the help was opened from is what counts — its state is still held, and the
top mode is still Schedule.
Sourcepub fn cycle_schedule_entries(&self) -> Vec<CycleScheduleEntry>
pub fn cycle_schedule_entries(&self) -> Vec<CycleScheduleEntry>
One row per cycle schedule, in declaration order, flagged when the last evaluation reported a warning for it.
The row’s tail is the same set of values tix cycle schedule list prints
(its columns minus the ones the detail pane spells out in full), taken from
the one read model rather than re-derived (C-008/NFR-003).
Sourcepub fn cycle_schedule_detail(
&self,
selected: usize,
) -> Option<CycleScheduleDetail>
pub fn cycle_schedule_detail( &self, selected: usize, ) -> Option<CycleScheduleDetail>
The selected schedule’s detail: its record, its generated cycles, its closed snapshots, its identity findings and its evaluated warnings (T036/T038).
Every value is the one the CLI’s show prints or the one detect evaluated —
nothing is recomputed here, so a generated cycle’s state is the stored
record’s rather than this surface’s opinion about its dates (C-007).
Sourcepub fn cycle_schedule_unattached_findings(&self) -> Vec<String>
pub fn cycle_schedule_unattached_findings(&self) -> Vec<String>
Findings that belong to no listed schedule: a record naming a schedule that is not in the registry (a dangling identity), or one the index could not attribute at all.
They get their own block on the tab rather than being folded into a schedule’s detail, because no schedule’s detail is theirs.
Sourcepub fn schedule_state(&self) -> ScheduleState
pub fn schedule_state(&self) -> ScheduleState
The Schedule page's state, or a fresh default when the page is not open.
Sourcepub fn schedule_entries(&self) -> Vec<ScheduleEntry>
pub fn schedule_entries(&self) -> Vec<ScheduleEntry>
One row per series, in id order, with the due flag the detector reports.
Sourcepub fn schedule_detail(&self, selected: usize) -> Option<ScheduleDetail>
pub fn schedule_detail(&self, selected: usize) -> Option<ScheduleDetail>
The selected series' detail: identity, rule, state, cursor, skipped dates
and the due candidate — everything the CLI's show prints, from the same
values (T036, C-008).
Source§impl App
impl App
Sourcepub fn capacity_rows(&self) -> &[CapacityRow]
pub fn capacity_rows(&self) -> &[CapacityRow]
The capacity rows the Capacity tab lists (WP06).
Sourcepub fn capacity_read(&self) -> bool
pub fn capacity_read(&self) -> bool
Whether the last capacity read succeeded.
false makes the tab state that the snapshot could not be read, rather than
drawing its “nothing is configured” sentence over a read that failed.
Sourcepub fn capacity_nothing_committed(&self) -> bool
pub fn capacity_nothing_committed(&self) -> bool
Whether every configured scope’s calculation was counted and came to zero, so
the tab can say so explicitly instead of leaving a row of - to be read two
ways. false when any scope has no answer at all.
Sourcepub fn capacity_detail(&self, selected: usize) -> Option<&CapacityDetail>
pub fn capacity_detail(&self, selected: usize) -> Option<&CapacityDetail>
The selected scope’s detail pane (WP06 T030/T033).
Sourcepub fn capacity_summaries(&self) -> Option<&CapacitySummaries>
pub fn capacity_summaries(&self) -> Option<&CapacitySummaries>
The compact per-cycle cells the board’s [cycle]-grouped headers append (WP06
T032), or None before the first read.
Source§impl App
impl App
pub fn handle_key(&mut self, key: KeyEvent) -> Result<Action>
Sourcepub fn switch_top_mode(&mut self, target: TopMode) -> Result<Action>
pub fn switch_top_mode(&mut self, target: TopMode) -> Result<Action>
Switch the shell to target, reusing each mode’s existing open path.
The sibling top-level state is dropped first so a switch does not leave a stale modal behind to reappear when the mode is left again; the openers are the same methods the letter keys call.
Source§impl App
impl App
Sourcepub fn stats_help_tab(&self) -> Option<StatsTab>
pub fn stats_help_tab(&self) -> Option<StatsTab>
The F7 Stats page’s active tab, and None in every other mode (WP05).
The same reason Self::schedule_help_tab exists, and the same shape: the
page’s two tabs act on different keys — the Health tab has no mutation key at
all, and the Time tab’s six commands act on nothing on Health — so an overlay
generated from the binding context alone would advertise keys that do nothing.
The page the help was opened from is what counts, because the overlay is
drawn while mode is Mode::Help and the tab is still held.
Source§impl App
impl App
Sourcepub fn active_view_id(&self) -> Option<&ViewId>
pub fn active_view_id(&self) -> Option<&ViewId>
The stable id of the active saved view (WP05, T024), or None when no
view is associated with the live board.
Public because the identity is what a surface or a test asserts (C-002): the name is a label and renaming a view must not change what is active.
Sourcepub fn live_plan(&self) -> ViewPlan
pub fn live_plan(&self) -> ViewPlan
The live normalized plan (C-006): the criteria in force, the text query (which carries the sort/group control tokens), and the visibility actually applied to the board.
Visibility is set only when a view’s snapshot is overlaid, which mirrors
what the plan of a view that leaves visibility alone means (“inherit the
live board”) — so applying such a view reports in sync rather than a
difference that is not one.
Sourcepub fn capture_plan(&self) -> ViewPlan
pub fn capture_plan(&self) -> ViewPlan
The plan a create/update from live saves: Self::live_plan plus the
visibility the user is actually looking at.
Unlike divergence (which asks “does the plan still describe the board?”),
saving asks “what is on screen?”, so an absent snapshot is captured as a
real one: hidden_columns and show_mismatch as configured right now.
Sourcepub fn view_divergence(&self) -> Option<ViewDivergence>
pub fn view_divergence(&self) -> Option<ViewDivergence>
The divergence of the live board from the saved definition of the
active view, or None when no view is marked (T026).
The three cases are the ones ViewService::divergence decides — a deleted
view and an uninterpretable plan are explicit diagnostics, never a silent
in_sync — derived here from the registry because rendering borrows
&App. tests/tui_state.rs pins this report against the service’s own
for the same inputs, so the two cannot drift.
Sourcepub fn view_indicator(&self) -> Option<String>
pub fn view_indicator(&self) -> Option<String>
The board’s active-view indicator row (T024), or None when no view is
marked. The same string the filter modal and the views modal show, so the
three surfaces cannot describe one state three ways.
Sourcepub fn active_view_feedback(&self) -> Option<ViewFeedback>
pub fn active_view_feedback(&self) -> Option<ViewFeedback>
The rendered feedback for the active view (T026): its scope, its plan, the live-vs-saved divergence, and every diagnostic the registry reports for it.
Source§impl App
impl App
Sourcepub fn activate_branch(&mut self, action: &Action) -> Result<Action>
pub fn activate_branch(&mut self, action: &Action) -> Result<Action>
Activate a rail branch: switch the shell to the branch’s target, resolved by the same paths the mode’s own controls use.
One method per Action arm, so a branch click and a branch-only
keyboard activation (there is none today; branches are pointer-only per
the open-question-3 decision) share a single transition.
Source§impl App
impl App
Sourcepub fn open_issue_by_filename(&mut self, filename: &str) -> Result<()>
pub fn open_issue_by_filename(&mut self, filename: &str) -> Result<()>
Open the detail pane on the issue a shared issue-table row names
(Action::OpenIssue).
The row’s filename is store-relative, exactly what
IssueSelector::Filename takes; a file that has vanished since the
draw surfaces as an Err the caller reports through the status line
rather than opening an empty detail.
Source§impl App
impl App
Sourcepub fn open_editor_round_trip(&mut self, filename: &str) -> Result<()>
pub fn open_editor_round_trip(&mut self, filename: &str) -> Result<()>
Launch the editor on a temp copy of filename and settle the result
(tix #1510).
The issue file’s raw bytes are snapshotted before the child runs, and
the edited temp copy is compared against that snapshot after it exits
by App::after_editor — the one place the conflict decision is made.
Splitting the round trip this way is what lets the live
Action::OpenEditor shell-out and the programmatic entry point be the same
code path: the only difference between them is who suspends the terminal
around the child.
Sourcepub fn after_editor(&mut self, filename: &str)
pub fn after_editor(&mut self, filename: &str)
Finish an editor round trip: commit the edit, or refuse to because the file changed underneath it (tix #1510).
Both entry points arrive here — App::open_editor_round_trip for the live
shell-out, and direct callers that write the file themselves before calling
this. A round trip that recorded a pending edit is compared against its
pre-edit snapshot and may enter Mode::EditConflict writing nothing;
one with no pending edit has no pre-edit bytes to compare against, so it
keeps the pre-#1510 behaviour of persisting the file it is asked to read.
Source§impl App
impl App
Sourcepub fn apply_new_issue_action(&mut self, action: Action) -> Result<Action>
pub fn apply_new_issue_action(&mut self, action: Action) -> Result<Action>
Run a New Issue-mode pointer action recorded during the draw. Public so the hit-region tests drive the same path the run loop does.
Sourcepub fn open_new_issue_form(&mut self)
pub fn open_new_issue_form(&mut self)
Open the F4 New Issue mode — n on the board, the F4 shell chord, and
where tix new starts the session (#1398, tui-new-issue-mode).
Seeds the default target’s status and the git identity (FR-028, best effort: empty when git is absent, never an error). One method rather than copies, because the key, the shell switch, and the command must produce the same form — entry points into one mode that default differently is how a bug is born.
Source§impl App
impl App
Sourcepub fn open_tips(&mut self)
pub fn open_tips(&mut self)
Open the startup tips modal over whatever the session opened on (tix #1632), starting at a random tip so the same advice does not wear out.
A no-op when the embedded list is empty, so a build whose embedded tips failed to parse simply has no dialog rather than an empty one.
Source§impl App
impl App
Sourcepub fn refresh_from_disk(&mut self, delta: &FsDelta) -> Result<()>
pub fn refresh_from_disk(&mut self, delta: &FsDelta) -> Result<()>
Apply an external change to the in-memory corpus and rebuild the board, without re-reading the issues tree (issue #10 follow-up).
delta comes from crate::watcher::FsWatcher::poll with paths
relative to the issues directory; Corpus::apply re-reads only those
files and drops the removed ones. A read error (e.g. a partially written
file) leaves the current corpus and board in place.
The delta is narrowed to the current view first: with the archived
toggle off, an archived path is dropped rather than read, so an issue
archived outside tix leaves the active board instead of appearing on
it (the archived-inclusive App::ensure_search_corpus snapshot is
dropped and rebuilt from disk on the next search, as after any refresh).
Source§impl App
impl App
Sourcepub fn compare_conflicting_edit(&mut self) -> Result<()>
pub fn compare_conflicting_edit(&mut self) -> Result<()>
Re-open the editor on the conflict prompt’s temp copy so the user can compare the two versions (#1510), then land back on the prompt.
The disk file’s bytes are read before and after the second editor
run, so a change made while the user compares is detected too — that is the
“re-reading the disk state” the prompt promises. It needs the child and the
child needs the terminal, which is why the keypress returns
Action::CompareEdit instead of doing this where the key is handled.
Nothing is written either way: the editor opens the temp copy, never the
issue file.
Sourcepub fn reedit_repair(&mut self) -> Result<()>
pub fn reedit_repair(&mut self) -> Result<()>
Re-open the editor on the repair prompt’s retained copy (#1506).
Called from the event loop because the child needs the terminal, exactly
as App::compare_conflicting_edit is. The edited copy is re-parsed when
it comes back: a valid file is committed (with the previous version backed
up), an invalid one re-enters the same prompt with fresh problems, and
either way the copy survives.
Source§impl App
impl App
Sourcepub fn note_disclosure(&mut self, disclosure: String)
pub fn note_disclosure(&mut self, disclosure: String)
Record a disclosure raised by a write, alongside whatever confirmation the action already produced.
Cycle-4 F4. The event loop drains at the top of the loop body, so a
disclosure raised by handle_key at the bottom would overwrite that
action’s confirmation message before any frame ever drew it — the user
moved an issue and never saw “Moved #1 to in progress”. Composing is the
fix: both facts are true, and both are worth showing.
The disclosure is appended rather than prepended so the confirmation reads first, which is the order the user caused them in. The existing message is left untouched, so this cannot swallow anything either.
pub fn new(config: &Config) -> Result<Self>
Auto Trait Implementations§
impl !Freeze for App
impl !RefUnwindSafe for App
impl !Sync for App
impl Send for App
impl Unpin for App
impl UnsafeUnpin for App
impl UnwindSafe for App
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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