MingaEditor.Shell.Board.State (Minga v0.1.0)

Copy Markdown View Source

Presentation state for The Board shell.

Holds the card grid, focus tracking, zoom state, and an ID counter. All operations are pure functions on this struct; the Editor GenServer calls them from Shell.Board callbacks.

Zoom lifecycle

The Board has two modes: grid view (showing all cards) and zoomed view (showing one card's workspace). The zoomed_into field tracks which card is currently expanded. When nil, the grid is showing.

Zooming in: the caller snapshots the current workspace onto the card, then restores the target card's workspace as the live workspace.

Zooming out: the caller snapshots the live workspace back onto the card, then either clears the live workspace or restores a minimal Board workspace.

Summary

Functions

Returns the number of cards on the board.

Creates a new card and adds it to the board.

Returns cards filtered by the current filter text, in display order.

Sets focus to the given card ID.

Returns the currently focused card, or nil.

Returns true when the grid is showing (not zoomed into a card).

Moves focus in the given direction within the grid.

Creates a fresh Board state with an empty card grid.

Removes a card from the board.

Reorders a card to a new position in the display order.

Returns all cards in display order (respecting user reordering).

Updates a card by applying a function to it.

Zooms into a card, storing the given workspace snapshot on it.

Zooms out of the current card, returning {state, workspace_snapshot}.

Returns the currently zoomed-into card, or nil.

Types

t()

@type t() :: %MingaEditor.Shell.Board.State{
  agent: MingaEditor.State.Agent.t(),
  bottom_panel: MingaEditor.BottomPanel.t(),
  card_order: [MingaEditor.Shell.Board.Card.id()],
  cards: %{
    required(MingaEditor.Shell.Board.Card.id()) =>
      MingaEditor.Shell.Board.Card.t()
  },
  dashboard: nil,
  filter_mode: boolean(),
  filter_text: String.t(),
  focused_card: MingaEditor.Shell.Board.Card.id() | nil,
  git_status_panel: nil,
  hover_popup: nil,
  modeline_click_regions: [],
  nav_flash: nil,
  next_id: pos_integer(),
  picker_ui: MingaEditor.State.Picker.t(),
  prompt_ui: MingaEditor.State.Prompt.t(),
  signature_help: nil,
  status_msg: String.t() | nil,
  suppress_tool_prompts: boolean(),
  tab_bar: nil,
  tab_bar_click_regions: [],
  tool_declined: MapSet.t(),
  tool_prompt_queue: [atom()],
  warning_popup_timer: nil,
  whichkey: MingaEditor.State.WhichKey.t(),
  zoomed_into: MingaEditor.Shell.Board.Card.id() | nil
}

Functions

card_count(state)

@spec card_count(t()) :: non_neg_integer()

Returns the number of cards on the board.

create_card(state, attrs \\ [])

@spec create_card(
  t(),
  keyword()
) :: {t(), MingaEditor.Shell.Board.Card.t()}

Creates a new card and adds it to the board.

Returns {updated_state, card}. The card gets a unique monotonic ID. If no card was focused, the new card becomes focused.

filtered_cards(state)

@spec filtered_cards(t()) :: [MingaEditor.Shell.Board.Card.t()]

Returns cards filtered by the current filter text, in display order.

focus_card(state, card_id)

@spec focus_card(t(), MingaEditor.Shell.Board.Card.id()) :: t()

Sets focus to the given card ID.

focused(state)

@spec focused(t()) :: MingaEditor.Shell.Board.Card.t() | nil

Returns the currently focused card, or nil.

grid_view?(state)

@spec grid_view?(t()) :: boolean()

Returns true when the grid is showing (not zoomed into a card).

move_focus(state, direction, cols)

@spec move_focus(t(), :up | :down | :left | :right, pos_integer()) :: t()

Moves focus in the given direction within the grid.

Direction is :up, :down, :left, or :right. The grid is computed from sorted card IDs laid out in rows of cols columns.

new()

@spec new() :: t()

Creates a fresh Board state with an empty card grid.

remove_card(state, card_id)

@spec remove_card(t(), MingaEditor.Shell.Board.Card.id()) :: t()

Removes a card from the board.

If the removed card was focused, focus moves to the next card in ID order, or nil if the board is now empty. If the removed card was zoomed into, zoom is cleared.

reorder_card(state, card_id, new_index)

@spec reorder_card(t(), MingaEditor.Shell.Board.Card.id(), non_neg_integer()) :: t()

Reorders a card to a new position in the display order.

Moves the card with the given ID to the specified index in the card_order list. If the card or index is invalid, returns the state unchanged.

sorted_cards(state)

@spec sorted_cards(t()) :: [MingaEditor.Shell.Board.Card.t()]

Returns all cards in display order (respecting user reordering).

update_card(state, card_id, fun)

Updates a card by applying a function to it.

zoom_into(state, card_id, workspace_snapshot)

@spec zoom_into(t(), MingaEditor.Shell.Board.Card.id(), map()) :: t()

Zooms into a card, storing the given workspace snapshot on it.

The caller is responsible for restoring the card's workspace as the live state.workspace on EditorState.

zoom_out(state)

@spec zoom_out(t()) :: {t(), map() | nil}

Zooms out of the current card, returning {state, workspace_snapshot}.

The returned snapshot is the workspace that was stored on the card when it was zoomed into. Returns {state, nil} if not zoomed.

zoomed(state)

@spec zoomed(t()) :: MingaEditor.Shell.Board.Card.t() | nil

Returns the currently zoomed-into card, or nil.