Skip to content

feat(desktop): add time filter to sidebar project tree#4150

Merged
esengine merged 5 commits into
esengine:main-v2from
ttmouse:pr/time-filter
Jun 12, 2026
Merged

feat(desktop): add time filter to sidebar project tree#4150
esengine merged 5 commits into
esengine:main-v2from
ttmouse:pr/time-filter

Conversation

@ttmouse

@ttmouse ttmouse commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Add a clock button in the project tree header that lets users filter sidebar topics by time.

  • All / Latest 10 / Latest 20 / Last 1h / 3h / 5h / 24h
  • Dropdown grouped into three sections (all / count / time)
  • Pure frontend filtering using topicActivityTime()
  • Persistent filter state via localStorage
  • Empty-state message + clear filter button when no results match

Notes

  • Backend (Go) changes for CreatedAt persistence on ProjectNode were already present in upstream, no backend changes needed
  • Only frontend changes (6 files, +290/-10 lines)
  • Filter is purely client-side, no extra API calls

ttmouse added 5 commits June 12, 2026 15:48
Add a clock button in the project tree header that opens a dropdown with time-based filters:
- All / Latest 10 / Last 1h / 3h / 5h / 24h
- Pure frontend filtering using topicActivityTime()
- Persistent filter state via localStorage
- Shows empty-state message + clear filter button when no results
…default styling and adaptive width

- Move time filter clock button to the left of collapse button
- Remove fixed width:22px, use min-width:22px so button expands when label shown
- Share combined selectors with add-project/collapse-all for consistent default styling
@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) labels Jun 12, 2026
@ttmouse

ttmouse commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author
image

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

--topicbar-height: 56px;
--statusbar-height: 0px;
--chrome-toggle-size: 42px;

P2 Badge Keep the filter menu inside the clipped sidebar

The project tree lives inside .sidebar, which has overflow: hidden, and this menu is absolutely positioned from the left edge of a button in the right-aligned header actions. In the default All state the button sits only about the other two action buttons away from the sidebar edge, so an 84px (or wider localized) menu extends past the sidebar and gets clipped, hiding part of the options. Align the menu to the right edge or render it in a portal like other floating UI.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +523 to +532
const times = new Set<number>();
const collect = (nodes: ProjectNode[]) => {
for (const n of nodes) {
if (n.kind === "topic" || n.kind === "global_topic") times.add(topicActivityTime(n));
collect(asArray(n.children));
}
};
collect(tree);
const sorted = [...times].sort((a, b) => b - a);
return sorted.length >= 10 ? sorted[9] : (sorted.length > 0 ? sorted[sorted.length - 1] : null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Count topics instead of distinct timestamps

For Latest 10/Latest 20, this stores activity times in a Set, so topics that share the same timestamp are collapsed before selecting the cutoff. In workspaces with legacy/blank topics where topicActivityTime() returns 0 for many nodes, or when several topics have identical millisecond activity times, the cutoff can become 0 (or a tied timestamp) and topicMatchesTime() then includes every topic at that value, causing the “Latest 10” filter to show far more than 10 topics. Build the cutoff from sorted topic entries rather than unique timestamps, with a deterministic tie-breaker if needed.

Useful? React with 👍 / 👎.

const sorted = [...times].sort((a, b) => b - a);
return sorted.length >= 20 ? sorted[19] : (sorted.length > 0 ? sorted[sorted.length - 1] : null);
})()
: Date.now() - diff;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refresh relative cutoff as time passes

When a duration filter such as Last hour is selected, the cutoff is computed from Date.now() only when this useMemo reruns, but its dependencies are just query, tree, and timeFilter. If the user leaves the sidebar open with no tree refresh, topics that have aged past the selected window remain visible indefinitely until some unrelated state change recomputes the memo, so the time filter can show stale results. Add a timer/tick dependency while a duration filter is active or recompute on render for these filters.

Useful? React with 👍 / 👎.

@esengine esengine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Nicely self-contained — i18n in both locales, theme tokens throughout, persisted filter state, and a real empty state with a clear-filter action. I read through the filter logic (the time + count cutoffs and the folder-visibility handling) and it holds up.

One real thing, which @chatgpt-codex-connector also caught: the dropdown is positioned left: 0 inside the overflow: hidden sidebar, so on a narrow sidebar — and with the longer zh labels — it clips at the right edge. Merging this and right-aligning the menu in a quick follow-up so you don't have to round-trip. Thanks for the contribution!

@esengine esengine merged commit bd30b0a into esengine:main-v2 Jun 12, 2026
14 checks passed
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

esengine added a commit that referenced this pull request Jun 12, 2026
…ip (#4196)

Follow-up to #4150. The dropdown was positioned `left: 0` inside the
`overflow: hidden` sidebar; the trigger sits in the right-aligned header, so on
a narrow sidebar — and with the longer zh labels — the menu ran past the right
edge and got clipped. Right-align it so it opens leftward into the sidebar.

Also fold the duplicated Latest-10 / Latest-20 cutoff IIFEs into one helper;
behavior is identical (same Set-dedup, sort, and short-list fallback).
esengine added a commit that referenced this pull request Jun 12, 2026
Follow-up to #4150. The dropdown is marked up as role=menu/menuitem but was
mouse-only. Add Escape-to-close (focus returns to the trigger), move focus into
the menu on open (the selected option, else the first), and ArrowUp/Down/Home/End
roving between options. The trigger gains aria-haspopup / aria-expanded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

desktop Wails desktop app (desktop/**) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants