1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! Navigation helpers: filter/sort, visible id list, and cursor movement.
use crateIndexRow;
use cratetui_common;
use SearchTuiState;
/// Apply [`SearchTuiState::filter`] and [`SearchTuiState::sort_key`] to the
/// state's indexes, returning the visible subset in display order.
///
/// Why: delegates to the shared [`tui_common::filtered_sorted`] so memory and
/// search apply identical filter / sort rules. Kept as a search-named wrapper
/// for the existing tests and callers.
/// What: thin wrapper over [`tui_common::filtered_sorted`].
/// Test: `test_apply_filter`, `test_apply_sort_*`.
/// Ids of the rows the user can navigate between, in visible display order.
///
/// Why: thin wrapper over the shared [`tui_common::visible_ids`].
/// What: delegates to the shared helper with the search state's fields.
/// Test: `test_visible_index_ids`, `test_navigate_visible`.
/// Move the cursor up one row in the visible (filtered + sorted) list.
///
/// Why: thin wrapper over the shared [`tui_common::navigate_up`].
/// What: delegates and writes back the new cursor.
/// Test: `test_navigate_visible`.
/// Move the cursor down one row in the visible (filtered + sorted) list.
///
/// Why: thin wrapper over the shared [`tui_common::navigate_down`].
/// What: delegates and writes back the new cursor.
/// Test: `test_navigate_visible`.
/// Row index — within the rendered `index_lines` output — that the cursor
/// currently sits on.
///
/// Why: ratatui's `ListState::with_selected` and the viewport scroll math
/// both index into the rendered list, but `state.selected` is an index into
/// the *original* `state.indexes` Vec. After a filter, sort, or grouping
/// reorders rows, the two indices diverge and the highlight + scroll latch
/// onto the wrong on-screen line. This helper bridges them: given the same
/// state the renderer sees, it returns the visible row at which the current
/// selection is drawn so the highlight follows the sorted order.
/// What: returns `0` when "All" is selected; otherwise walks
/// [`index_lines`] looking for the row whose `selected` flag is set and
/// returns its index. Falls back to `0` (the "All" row) when no matching
/// row is found, which mirrors how `clamp_to_visible` collapses a hidden
/// selection back to "All".
/// Test: `test_visible_selected_row_follows_sort`,
/// `test_visible_selected_row_follows_group`.
/// Compute which lines from `new_lines` are genuinely new since `watermark`.
///
/// Why: `GET /logs/tail` returns the last N lines from a ring buffer; on
/// every poll we receive an overlapping window. This helper finds the
/// suffix of `new_lines` that appears after the last-seen watermark line,
/// so only truly new lines get pushed to the activity log.
/// What: if `watermark` is `None`, returns all of `new_lines` (first poll
/// after the initial skip). Otherwise finds the rightmost occurrence of
/// `watermark` in `new_lines` and returns everything after it. If the
/// watermark is not found (ring buffer wrapped), returns all of `new_lines`.
/// Test: `test_new_log_lines_since_watermark`.