Skip to content

Add strategy and folder pinning#75

Open
njiedev wants to merge 8 commits into
SunkenInTime:mainfrom
njiedev:feature/strategy-pinning
Open

Add strategy and folder pinning#75
njiedev wants to merge 8 commits into
SunkenInTime:mainfrom
njiedev:feature/strategy-pinning

Conversation

@njiedev
Copy link
Copy Markdown

@njiedev njiedev commented May 23, 2026

Summary

Original pinning PR. I attempted to push the manual pinned-order follow-up directly here, but the fork branch njiedev/icarus:feature/strategy-pinning rejected maintainer writes with 403 from my environment.

Manual pinned ordering is available in follow-up PR #77 from SunkenInTime/icarus:devin/manual-pinned-order: new pins enter at the top, pinned items ignore the app’s normal ordering while pinned, and users can reorder pins via Move Pin to Top, Move Pin Up, and Move Pin Down.

Link to Devin session: https://app.devin.ai/sessions/026effa9989f4a9c9d8ef2da902bc575
Requested by: @SunkenInTime

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 23, 2026

Greptile Summary

Adds pin/unpin support for strategy tiles and folder pills, backed by a standalone Hive Box<int> registry (itemId → pinnedTimestamp). Pinned items are hoisted to the top of the root screen in recency order; pinning is suppressed during search, and pins are auto-removed on deletion.

  • PinnedItemsProvider is a clean, self-contained Riverpod Notifier with correct Hive read/write ordering and three unit tests covering toggle, recency sort, and no-op remove.
  • FolderContent adds the root-screen hoisting logic using maps built from the full Hive boxes, correctly implementing the "global pins appear at root regardless of source folder" requirement.
  • A leftover // ... your existing imports development comment remains in folder_content.dart and should be removed.

Confidence Score: 4/5

The change is well-scoped and the core persistence and deletion cleanup paths are correct. The two open items are cosmetic and a minor Riverpod style point — no data-correctness risk.

The provider, Hive wiring, and deletion cleanup are all implemented correctly. The only rough edge is using ref.read to call pinnedIdsByRecency() inside build() when the full state is already available from ref.watch on the line above — a style inconsistency that poses no practical risk but is worth cleaning up. A stale scaffolding comment also remains.

lib/widgets/folder_content.dart — minor ref.read-inside-build pattern and a leftover comment.

Important Files Changed

Filename Overview
lib/providers/pinned_items_provider.dart New Riverpod Notifier backed by a Hive box; state management, ordering, and persistence are all correct. removePin early-exits cleanly, and the box is read once at build time.
lib/widgets/folder_content.dart Pinned-items sorting logic is functionally correct for the stated design (global pins at root). Two minor issues: a leftover // ... your existing imports comment and a ref.read for pinnedIdsByRecency() that could use the already-watched pinned map directly.
lib/providers/strategy_provider.dart Adds a single removePin call before strategy deletion; correct and minimal.
lib/providers/folder_provider.dart Adds removePin(folderID) as the first step in deleteFolder; consistent with the strategy pattern. Direct-child strategy pins are also cleaned up via deleteStrategyremovePin chain.
lib/widgets/folder_pill.dart Pin/unpin menu item added correctly; isDemo guard is in place, and ref.watch drives the label correctly.
lib/widgets/strategy_tile/strategy_tile.dart Pin/unpin menu item added correctly; ref.watch drives the label, and togglePin is the right call from onPressed.
test/pinned_items_provider_test.dart Three unit tests covering toggle round-trip, recency ordering, and no-op remove; Hive is properly initialized and torn down per test.

Sequence Diagram

sequenceDiagram
    participant User
    participant StrategyTile/FolderPill
    participant PinnedItemsProvider
    participant HiveBox
    participant FolderContent

    User->>StrategyTile/FolderPill: Right-click / ⋮ → Pin
    StrategyTile/FolderPill->>PinnedItemsProvider: togglePin(id)
    PinnedItemsProvider->>HiveBox: put(id, nowMs)
    PinnedItemsProvider->>PinnedItemsProvider: "state = {...state, id: nowMs}"
    PinnedItemsProvider-->>FolderContent: rebuild (ref.watch)
    FolderContent->>PinnedItemsProvider: pinnedIdsByRecency()
    FolderContent->>FolderContent: hoist pinned items to front of lists

    User->>StrategyTile/FolderPill: Delete
    StrategyTile/FolderPill->>PinnedItemsProvider: removePin(id)
    PinnedItemsProvider->>HiveBox: delete(id)
    PinnedItemsProvider->>PinnedItemsProvider: "state = {...state}..remove(id)"
Loading

Reviews (1): Last reviewed commit: "Float pinned items to top of grid instea..." | Re-trigger Greptile

Comment on lines +182 to +184
final pinnedIds = ref
.read(pinnedItemsProvider.notifier)
.pinnedIdsByRecency();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 ref.read inside build() for state access

pinnedIdsByRecency() is called via ref.read(pinnedItemsProvider.notifier) on line 183 inside build(). Riverpod's ref.read takes a snapshot at call time and does not subscribe, so in the narrow window between the ref.watch on line 180 and this ref.read, the notifier state could theoretically change (e.g. a concurrent async pin toggle completing). In practice this means pinned (line 180) and the snapshot used by pinnedIdsByRecency() could differ. Since pinned is already the full Map<String, int> state, you can derive the sorted order directly from it — no ref.read needed.

Comment thread lib/widgets/folder_content.dart Outdated
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@SunkenInTime SunkenInTime self-assigned this May 31, 2026
@SunkenInTime SunkenInTime added the enhancement New feature or request label May 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants