Skip to content

Context-sensitive preview for Sub/Lnk tabs#55

Merged
textfuel merged 9 commits intotextfuel:mainfrom
seflue:feat/context-sensitive-preview
Apr 18, 2026
Merged

Context-sensitive preview for Sub/Lnk tabs#55
textfuel merged 9 commits intotextfuel:mainfrom
seflue:feat/context-sensitive-preview

Conversation

@seflue
Copy link
Copy Markdown
Contributor

@seflue seflue commented Apr 18, 2026

Closes #54

Moving the cursor to an issue in the Subtasks or Links tab now
previews that issue in the main pane, and contextual actions
(refresh, edit, transition, open in browser, comments, custom
commands) act on it. Entering a Sub/Lnk tab previews its first
entry immediately; leaving the tab resets the preview back to
the main issue.

The effect: the Sub/Lnk tab behaves like any other selection
pane in a lazy*-style layout. You can browse related issues
without losing your place, and key actions always target the
issue the cursor currently points to.

Implementation notes

  • A new jiratest.FakeClient provides handler-level test
    coverage. Writing tests at this level surfaced a pre-existing
    bug where refresh read stale data from the cache before
    dispatching the fetch; it is also fixed in this branch.

  • App.previewKey holds the key of the issue currently shown in
    the right-hand views. Selection, cursor moves in the info
    panel and tab-leave paths all write it; the detail view and
    action handlers read it.

  • Preview fetches debounce for 150 ms and carry a monotonic
    counter. Responses whose counter is stale by the time they
    arrive are dropped, so a slow response for an earlier
    selection cannot overwrite a later one. Bubbletea has no
    native tea.Cmd cancellation, which is why the counter is
    needed. Cache hits bypass the debounce and update the detail
    view synchronously.

  • On task selection, a single JQL batch warms the cache for the
    task's parent, subtasks and linked issues, so entering a Sub
    or Lnk tab usually lands on a cache hit.

To test:

  1. Open an issue with sub-tasks or links. Move the cursor in the
    Sub or Lnk tab: the main pane previews the highlighted
    item. The info panel stays put.
  2. Refresh: the preview re-fetches, not the list item.
  3. Edit, transition, or trigger a custom command: they all
    target the previewed issue.
  4. Leave the Sub/Lnk tab: the preview returns to the main issue.

@seflue seflue requested a review from textfuel as a code owner April 18, 2026 05:56
seflue added 9 commits April 18, 2026 09:19
A new jiratest sub-package provides a fake that implements the
Jira client interface. Every method fails the test on an
unexpected call, so each test opts in explicitly to the traffic
it expects. The first consumer locks in the current refresh
behavior: pressing the refresh action fetches the currently
selected issue.

This opens a path to fast, precise tests for keyboard-driven
actions, which previously only surfaced in slow E2E runs.
Upcoming preview work needs a safety net at this level.
Refresh and the detail view now follow a single preview target
instead of peeking at the list cursor or the detail's own state.
This keeps the right-hand views coherent when the preview
diverges from the list selection. Previewing a sub-issue is the
motivating case.
Switching the info panel to the Subtasks or Links tab previews
the tab's first entry right away, and moving the cursor through
the list updates the preview as you go. The Fields tab stays
quiet: navigation there never changes the preview target, and
empty lists dispatch nothing.
Preview requests debounce for 150 ms before hitting the network,
so scrolling through sub-tasks or links does not trigger a fetch
per row. A monotonic request counter rides along with each
fetch; any response whose counter is stale by the time it
arrives is dropped, so a slow answer for an earlier row cannot
overwrite a later selection. Bubbletea has no native command
cancellation, so the counter acts as the cancel substitute.

Cache hits short-circuit the debounce entirely and update the
detail view synchronously, so revisiting an already-loaded issue
feels instant. Cache misses land on the debounced path.

Non-preview paths (refresh, main-list selection on cache miss,
comment updates) keep the existing direct-fetch behavior.
Deletes the issueCache entry for the previewed key synchronously in the
ActRefresh handler, before the fetch cmd is returned. Any cache read
between the keypress and the fetch response now sees a miss instead of
stale data.

Adds TestActRefresh_InvalidatesCacheBeforeFetch to pin the invariant.
When the user presses Esc (ActFocusLeft) while the InfoPanel has focus
with the Sub or Lnk tab active, previewKey now snaps back to the
current list selection via previewSelectedIssue(). The same reset fires
when switching the InfoPanel tab to Fields via PrevTab or NextTab.

Empty Sub/Lnk lists never dispatch PreviewRequestMsg (confirmed by
test; no production change needed).

Added package-level subKey1 constant and migrated all "SUB-1" literals
in pkg/tui tests to use it (goconst lint fix).
Previewing a sub-issue now only updates the right-side detail
view. The info panel keeps its tab and cursor on the main list
issue, as the user's navigation context should.

Before, a detail response for a previewed sub-issue overwrote
the info panel. Because the panel's SetIssue resets cursor and
active tab when the key changes, the sub/link tab snapped back
to fields and the cursor jumped to the top, making the whole
pane feel like it was flying away from under the user.

The detail view and info panel now have independent guards.
The detail view follows previewKey, which is the source of
truth for what is shown on the right. The info panel follows
the list selection, matching user intent for navigation
context.
Selecting a task in the list, and switching back into the list
view, fires a single JQL batch for the task's parent, subtasks
and linked issues. By the time the user moves into the Sub or
Lnk tab, those issues are already in the cache and the preview
renders without a network round-trip. The parent joins the
batch so future drill-up navigation benefits from the same
warm cache.
Edit, copy URL, open in browser, transition, priority, assignee,
duplicate, create branch, and custom commands all now act on
the issue currently shown in the detail view. Previously they
followed the list cursor, which surprised the user after
drilling into a sub or linked issue via the info panel.

A new currentIssue helper resolves to the cached previewed
issue when one is active, falling back to the list selection
otherwise. The info panel's Fields tab still edits the main
list issue, because that is what the Fields tab shows.
@seflue seflue force-pushed the feat/context-sensitive-preview branch from 60a222a to 22cf077 Compare April 18, 2026 07:19
Copy link
Copy Markdown
Owner

@textfuel textfuel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!
The debounce + epoch approach is a clean solution
Thanks for improving the navigation experience 👍

@textfuel textfuel merged commit 851bfa1 into textfuel:main Apr 18, 2026
2 checks passed
@seflue seflue deleted the feat/context-sensitive-preview branch April 18, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Context-sensitive preview for Sub/Lnk tabs

2 participants