FEATURE: Calculator Plugin History

01
5d ago
+741-40

Changes

  • Added History and HistoryItem objects to persist calculator results
  • Added a plugin setting to enable or disable history
  • Implemented a debounce strategy to reduce unnecessary history entries

Debounce Strategy

Currently, the calculator plugin returns results even when the Enter key is not pressed. Because of this behavior, every partial expression can be added to the history while the user is typing.
For example, while the user is building the expression:

1+2+3+4+5

Without a debounce mechanism, each intermediate expression is stored in history, generating multiple unnecessary entries.
With the debounce strategy, the plugin waits for a short delay before saving the result. This ensures that only the final or more complete expression is added to history.

Without debounce

  • 1
  • 1+2
  • 1+2+3
  • 1+2+3+4
  • 1+2+3+4+5

With debounce

  • 1+2+3+4+5

This keeps the history cleaner and improves the overall user experience.


[!NOTE]
I'm not fully satisfied with the result title and subtitles yet, so suggestions are welcome!

Technical Implementation Details

Time-Ago Formatting

We implemented custom, localized relative time strings (e.g., "just now", "5 minutes ago"). This was needed because there is no built-in datetime formatting helper in the Flow Launcher codebase. The implementation uses the plugin's own local translation keys (in en.xaml) to keep everything localized correctly.

Debounce vs Immediate Modes

  • On Query Mode (Debounced): Uses a PendingHistoryItem together with an 800ms debounce timer to prevent saving incomplete expressions while the user is typing.
  • On Enter Mode (Immediate): When execution occurs (e.g., when the user presses Enter), the item is added or updated directly using a standard HistoryItem without any debounce.

Code Quality & Refactorings

  • Constructor Chaining: Chained the constructors in HistoryItem.cs so that the PendingHistoryItem constructor delegates to the primary one, avoiding initialization duplication.
  • Unified Action Delegation: Structured CreateClipboardActionWithHistory in Main.cs to delegate directly to CreateClipboardAction, avoiding duplicated copy and error handling logic.
  • Unified Update Logic: Created AddOrUpdateInternal(HistoryItem) in History.cs to standardize the update path for both modes.
  • Main Thread Execution: Removed unnecessary locks (lock (_syncRoot)) on the normal HistoryItem addition path since it is triggered from the main thread.

Screenshot 2026-07-04 201306

https://github.com/user-attachments/assets/02af3d1f-3156-4692-afa2-c41a541512cf


Summary by cubic

Summary of changes

Adds an optional calculation history to the calculator plugin, showing up to 5 recent calculations beneath the current result, and updates the history badge icon to a clearer design.

  • Changed: Query now returns the main result (formatted as = {result}) plus recent history when EnableHistory is on, excluding the active query. The main result gains a "copy to clipboard" action and subtitle, and clipboard handling is centralized via shared helpers. NaN and incomplete-expression cases now render an error result only when ShowErrorMessage is on. The main result is scored one point above history results, and AddSelectedCount is disabled on both so usage never reorders them while still letting the launcher set topmost. Executing the main result now flushes any pending debounced entry, so a calculation you run is saved even before the debounce elapses.
  • Added: Settings EnableHistory (default off) and HistoryCreationMode (OnQuery with an 800ms debounce, OnEnter). Storage-backed History with a 5-item cap (drops oldest), plus HistoryItem, PendingHistoryItem, and HistoryHelper for pending items and localized time-ago strings. A history icon, English strings, and a settings UI with a mode selector and an OnQuery warning.
  • Removed: Inline copy-to-clipboard logic from Query in favor of the centralized helpers.
  • Memory impact: Low. At most 5 stored items, one pending item, and one debounce timer in settings storage.
  • Security risks: Low. History is local and off by default; OnQuery may capture partial expressions, but the UI warns and nothing is sent externally.
  • Unit tests: Added coverage for history enable/disable behavior, saved data, debounce flush, executing a result before the debounce, and incomplete-query handling, including per-test history reset.

Release Note

You can now enable a calculator history that remembers your 5 most recent calculations, saving them as you type or only when you press Enter.