Skip to content

feat: promote mini mode and Windows-only layout fixes to main - #102

Merged
pountzas merged 46 commits into
mainfrom
dev
Aug 12, 2026
Merged

pountzas merged 46 commits into
mainfrom
dev

Conversation

@pountzas

@pountzas pountzas commented Aug 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

Promote dev to main, including:

  • Mini Mode: full-width bottom keyboard on text focus, 3-button FAB when collapsed, transparent outlined UI, mirror-display eligibility, UIA-based text-focus detection, and layout race fixes
  • Windows-only product hardening (drop macOS / cross-platform stubs)
  • Related layout polish: tool-window centering, touch/mouse layout snapshots, resize-drag pointer capture, DPI-aware collapsed FAB sizing
  • Trackpad touch cursor stability / tap-to-click work already on dev

Commit message

feat: promote mini mode and Windows-only layout fixes to main

Related issue

N/A

Accessibility impact

Mini Mode makes the keyboard appear when typing in other apps and collapse to large FABs when not — better for single-monitor / mirrored accessibility setups. Focus detection now covers modern Windows text fields (Search, browsers, WinUI), not only classic Edit controls.

Test plan

  • Ran npm run tauri dev locally on Windows
  • Mini Mode: keyboard shows on Notepad / Search / browser input; hides to Settings/Dictate/Expand FAB on focus lost
  • Collapse/expand does not leave a squashed keyboard in the FAB corner
  • No crash when rapidly changing focus between apps
  • Confirm Windows-only CI/release targets (nsis/msi) still look correct

Screenshots (if UI changed)

See mini-mode work in #101 if needed; this PR is the dev → main promotion.

Summary by CodeRabbit

  • New Features
    • Added Mini Mode with automatic display detection, compact controls, expandable keyboard, and transparent styling.
    • Added separate touch and mouse layout profiles with improved pointer and trackpad interactions.
    • Added cursor highlighting, focus-aware keyboard visibility, and monitor-aware tool-window placement.
  • Bug Fixes
    • Improved mirrored-monitor handling, window sizing, dragging, and category initialization for existing profiles.
  • Documentation
    • Clarified Windows 10/11-only support and Windows installer availability.
  • Tests
    • Added coverage for Mini Mode, layouts, pointer dragging, and database seeding.

dependabot Bot and others added 27 commits August 3, 2026 18:16
Bumps the npm-minor-and-patch group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/jszip](https://github.com/Stuk/jszip) | `3.4.0` | `3.4.1` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.17` | `19.2.18` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.3` | `19.2.4` |
| [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.4` | `6.0.5` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.1.5` | `8.2.0` |


Updates `@types/jszip` from 3.4.0 to 3.4.1
- [Changelog](https://github.com/Stuk/jszip/blob/main/CHANGES.md)
- [Commits](https://github.com/Stuk/jszip/commits)

Updates `@types/react` from 19.2.17 to 19.2.18
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 19.2.3 to 19.2.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `@vitejs/plugin-react` from 6.0.4 to 6.0.5
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.5/packages/plugin-react)

Updates `vite` from 8.1.5 to 8.2.0
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@8.2.0/packages/vite)

---
updated-dependencies:
- dependency-name: "@types/jszip"
  dependency-version: 3.4.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-and-patch
- dependency-name: "@types/react"
  dependency-version: 19.2.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-and-patch
- dependency-name: "@types/react-dom"
  dependency-version: 19.2.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-and-patch
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-and-patch
- dependency-name: vite
  dependency-version: 8.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
- Refactored SQL queries in the `pack_words` and `predictions` methods to improve execution speed and reduce overhead.
- Removed redundant operations to streamline data retrieval processes.
Drive relative moves from an authoritative position for the gesture so Windows touch absolute cursor placement cannot yank the pointer onto the finger.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Added a new module for cursor highlighting specific to Windows.
- Updated mouse handling functions to utilize absolute cursor positioning, improving gesture responsiveness.
- Enhanced trackpad gesture functions to maintain cursor visibility and state during interactions.
- Refactored mouse event handling to support additional mouse event flags for better compatibility.
Map short stationary taps to left click and a second tap in the double-click window to double-click, matching real trackpad behavior.
fix: stabilize touch trackpad cursor and add tap-to-click
…minor-and-patch-48aa4d6334

chore(deps-dev): bump the npm-minor-and-patch group with 5 updates
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Refactor collapsed sizing with CollapsedFabCount enum and shared
FAB_HOVER_SLACK constant synced between Rust and TS. Window dimensions
now include hover headroom; CollapsedFab uses reduced scale and min sizes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
ReachPanel is Windows-only. Remove stub modules, macOS CI jobs, and
cross-platform fallbacks; add compile_error guard for non-Windows builds.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…nly guardrails

Pass the main window scale factor into compute_window_layout, commit the
windows-only Cursor rule, run CI on PRs targeting dev, and document the
platform policy in CONTRIBUTING.

Co-authored-by: Cursor <cursoragent@cursor.com>
…eyboard

Toolbar button collapses back to the FAB stack (including transparent mode)
and suppresses auto-show until external focus is lost once.

Co-authored-by: Cursor <cursoragent@cursor.com>
feat: mini mode layout fixes and Windows-only platform
@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pountzas, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cf98e68d-8102-4e0a-84f8-54d58461db1b

📥 Commits

Reviewing files that changed from the base of the PR and between 1517b83 and e31e1ee.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • package.json
  • src-tauri/tauri.conf.json
  • src/components/common/SuggestionsBar.tsx
  • src/stores/appStore.ts
📝 Walkthrough

Walkthrough

ReachPanel is now Windows-only. The change adds Mini Mode, monitor-aware layouts, touch and mouse layout profiles, native focus tracking, cursor highlighting, improved trackpad gestures, transparent keyboard controls, and Windows-only release configuration.

Changes

Windows-only platform and release contract

Layer / File(s) Summary
Platform support and release configuration
.cursor/*, .github/workflows/*, CONTRIBUTING.md, README.md, src-tauri/tauri.conf.json
Project rules, documentation, CI, release metadata, and bundles now target Windows only.
Native platform behavior
src-tauri/src/input/*, src-tauri/src/stt/*, src-tauri/src/tts/*, src-tauri/src/icons.rs
Non-Windows stubs and fallbacks were removed. Windows input, speech, icon, and connectivity implementations are used directly.

Mini Mode and input interaction

Layer / File(s) Summary
Monitor-aware layout
src-tauri/src/window/*, src-tauri/src/lib.rs, src/lib/toolWindows.ts
Mirror detection, monitor selection, DPI-aware sizing, collapsed FAB layouts, and Mini Mode window geometry were added.
Mini Mode state and profiles
src/lib/types.ts, src/lib/layoutProfiles.ts, src/stores/appStore.ts, src/App.tsx
The store now manages Mini Mode activation, focus-driven visibility, pointer-specific layouts, settings persistence, and window synchronization.
Pointer and trackpad handling
src/lib/pointerDrag.ts, src/components/layout/*, src/components/mouse/Trackpad.tsx, src-tauri/src/input/mouse.rs
Pointer capture and cancellation use a shared hook. Trackpad input now supports gesture tracking, delayed clicks, double-clicks, and backend gesture lifecycle commands.
Mini Mode interface and validation
src/components/layout/MiniModeShell.tsx, src/components/keyboard/*, src/components/settings/SettingsPanel.tsx, src/i18n/*, src/lib/*test.ts, docs/*
Mini Mode adds collapsed and expanded views, transparent styling, settings, translations, acceptance criteria, implementation planning, and Vitest coverage.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant AppStore
  participant FocusTarget
  participant Tauri
  participant MiniModeShell
  App->>AppStore: initialize and detect Mini Mode
  AppStore->>Tauri: query monitors and apply layout
  FocusTarget-->>AppStore: publish input-focus-changed
  AppStore->>Tauri: animate keyboard visibility
  AppStore->>MiniModeShell: update Mini Mode state
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description includes all required sections and provides clear scope, accessibility impact, and a detailed Windows test plan.
Title check ✅ Passed The title clearly summarizes the main Mini Mode and Windows-only layout changes promoted to main.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch dev
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 16

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (6)
companion/.expo/README.md-11-14 (1)

11-14: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove committed Expo local state.

companion/.expo/README.md states that .expo is machine-specific and must not be shared. Remove both files from Git. Add an ignore rule for companion/.expo/ if one does not already exist.

  • companion/.expo/README.md#L11-L14: remove the committed Expo-generated README.
  • companion/.expo/devices.json#L1-L3: remove the committed development-session state file.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@companion/.expo/README.md` around lines 11 - 14, Remove the committed files
companion/.expo/README.md (lines 11-14) and companion/.expo/devices.json (lines
1-3) from Git, and add the companion/.expo/ ignore rule to the relevant
.gitignore if it is not already present.
src/i18n/it.ts-30-42 (1)

30-42: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Mini Mode feature name uses two capitalizations in the new translations. Both files introduce the feature name in title case in the miniMode key and in lower case in the miniModeCollapse key. The shared root cause is a missing capitalization rule for the feature name across the new Mini Mode strings. Pick one form per language and apply it to every Mini Mode string, including any future keys.

  • src/i18n/it.ts#L30-L42: change miniModeCollapse to use "Modalità Mini", or change miniMode to lower case, so both keys agree.
  • src/i18n/pt.ts#L30-L42: change miniModeCollapse to use "Modo Mini", or change miniMode to lower case, so both keys agree.

Check the remaining locale files in the same way, because they were changed in the same commit.

#!/bin/bash
# Compare Mini Mode string capitalization across all locale files.
fd -t f -e ts . src/i18n --exec rg -n -A2 'miniMode' {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/it.ts` around lines 30 - 42, Standardize the Mini Mode feature-name
capitalization across all new locale strings: in src/i18n/it.ts lines 30-42,
make miniMode and miniModeCollapse consistently use “Modalità Mini”; in
src/i18n/pt.ts lines 30-42, make them consistently use “Modo Mini”. Review the
remaining locale files for the same miniMode and miniModeCollapse inconsistency
and apply each language’s chosen capitalization consistently to all Mini Mode
keys.
src/lib/layoutProfiles.test.ts-25-31 (1)

25-31: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the mouse-layout assertion able to fail.

Line 30 uses ?? 0.28 and then expects 0.28. The assertion passes when mouseLayout is undefined and when it equals 0.28. A regression where persistLayoutForKind(…, "touch") also writes mouseLayout would only be caught if the written value differed from 0.28, and here it would not.

base has no mouseLayout, so assert its absence directly.

💚 Proposed fix
     const stored = persistLayoutForKind(touchApplied, "touch");
     expect(stored.touchLayout?.inputRowRightRatio).toBe(0.4);
-    expect(stored.mouseLayout?.inputRowRightRatio ?? 0.28).toBe(0.28);
+    expect(stored.mouseLayout).toBeUndefined();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/layoutProfiles.test.ts` around lines 25 - 31, Update the mouse-layout
assertion in the test around persistLayoutForKind to assert that
stored.mouseLayout is absent, since base does not define one. Remove the nullish
fallback and preserve the existing touch-layout value assertion.
src/stores/appStore.ts-889-919 (1)

889-919: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Debounce pointer-kind profile switches

The capture-phase window pointerdown listener calls handlePointerInputEvent without debouncing. Rapid touch-to-mouse alternation can start overlapping persistence and layout-sync operations. Add a short debounce before setPointerInputKind.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/stores/appStore.ts` around lines 889 - 919, Debounce pointer-kind changes
initiated by handlePointerInputEvent before invoking setPointerInputKind, so
rapid alternating pointerdown events coalesce into one update and avoid
overlapping persistence/layout synchronization. Keep the existing no-op behavior
for the current kind and preserve setPointerInputKind’s persistence and
window-sync logic.
src/lib/pointerDrag.ts-69-70 (1)

69-70: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Move the optionsRef write out of render.

React can replay or discard a render, which can leave optionsRef.current pointing to callbacks from an uncommitted render. Update the ref in a layout effect. useEffectEvent cannot replace this callback because Effect Events cannot be called from event handlers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/pointerDrag.ts` around lines 69 - 70, Move the optionsRef.current
assignment out of the render path and update it in a layout effect within the
pointer-drag hook, ensuring callbacks come from the committed render before
event handlers use them. Keep optionsRef initialized with options and retain the
existing event-handler access through optionsRef.

Source: Linters/SAST tools

src/stores/appStore.ts-82-126 (1)

82-126: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Drain pendingMiniLayoutSync in toggleCollapsed's finally block. During settings transitions, AppShell can render CollapsedFab before miniModeActive is cleared. A Mini Mode sync can queue during toggleCollapsed, but this finally block does not drain it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/stores/appStore.ts` around lines 82 - 126, Update toggleCollapsed’s
finally block to drain pendingMiniLayoutSync after the transition completes,
handling any queued Mini Mode layout sync using the existing
syncMiniModeWindowLayout flow. Preserve the current cleanup behavior and ensure
the queued request is cleared and executed when appropriate.
🧹 Nitpick comments (11)
src-tauri/src/lib.rs (1)

310-336: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Group the layout flags into a struct.

apply_window_layout and animate_window_layout now take nine positional parameters. Six of them are bool or f32. The call sites pass literal sequences such as false, false, false, height_ratio, false, false, .... A swapped argument compiles without an error and produces wrong window geometry.

Pass a single LayoutOptions struct instead. This also makes the compute_window_layout call site self-documenting.

♻️ Sketch of the struct-based signature
#[derive(Clone, Copy)]
pub struct LayoutOptions {
    pub monitor_id: u32,
    pub collapsed: bool,
    pub collapsed_dictation: bool,
    pub collapsed_settings: bool,
    pub height_ratio: f32,
    pub mini_mode: bool,
    pub mini_keyboard_visible: bool,
    pub mini_keyboard_height_ratio: f32,
}

impl LayoutOptions {
    pub fn expanded(monitor_id: u32, height_ratio: f32) -> Self {
        Self {
            monitor_id,
            collapsed: false,
            collapsed_dictation: false,
            collapsed_settings: false,
            height_ratio,
            mini_mode: false,
            mini_keyboard_visible: false,
            mini_keyboard_height_ratio: window::MINI_KEYBOARD_HEIGHT_RATIO,
        }
    }
}

async fn apply_window_layout(app: &tauri::AppHandle, opts: LayoutOptions) -> Result<(), String> { /* … */ }

The cmd_move_window_to_monitor call site then reads:

apply_window_layout(&app, LayoutOptions::expanded(monitor_id, height_ratio)).await

Also applies to: 469-480, 515-519

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/lib.rs` around lines 310 - 336, Introduce a shared
LayoutOptions struct containing monitor_id and all layout flags and ratios, plus
the expanded constructor shown by the existing conventions. Update
apply_window_layout, animate_window_layout, compute_window_layout, and every
affected call site to accept or pass LayoutOptions instead of positional
parameters, using named fields to make layout intent explicit and preserving
current behavior.
vitest.config.ts (1)

1-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Register Testing Library cleanup. Vitest globals are disabled, and no setup file calls cleanup. Add cleanup() to the existing afterEach so each renderHook unmounts and removes its subscriptions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vitest.config.ts` around lines 1 - 7, Update the Vitest setup referenced by
the test configuration to import Testing Library’s cleanup and invoke cleanup()
from the existing afterEach hook. Ensure the setup runs for every test so
renderHook instances unmount and remove subscriptions, while preserving the
current Node environment configuration.
src-tauri/src/input/focus_target.rs (2)

240-243: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the redundant prefix check.

lower.starts_with("chrome_widgetwin") can never be reached. Every string with that prefix already matches chrome_.

♻️ Proposed simplification
 fn is_chromium_class(class: &str) -> bool {
     let lower = class.to_ascii_lowercase();
-    lower.starts_with("chrome_") || lower.starts_with("chrome_widgetwin")
+    lower.starts_with("chrome_")
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/input/focus_target.rs` around lines 240 - 243, Remove the
redundant lower.starts_with("chrome_widgetwin") condition from
is_chromium_class, leaving only the chrome_ prefix check while preserving the
existing case-insensitive behavior.

418-441: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Use one long-lived worker thread instead of a new thread per burst.

Each burst spawns a thread. The thread initializes COM, creates a CUIAutomation instance in thread-local storage, and never calls CoUninitialize. Focus events are frequent, so this repeats thread creation and COM/UIA object creation, and the cached automation object is discarded at every thread exit.

A single dedicated worker thread with a condition variable keeps the UIA instance alive and removes the busy/dirty handshake.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/input/focus_target.rs` around lines 418 - 441, The
schedule_reevaluate_input_focus flow should use one long-lived dedicated worker
instead of spawning a thread per burst. Move COM initialization and
CUIAutomation creation into that worker’s thread-local setup, keep the UIA
instance alive while waiting on a condition variable, and replace the
REEVAL_DIRTY/REEVAL_WORKER_BUSY handshake with condition-variable signaling so
focus events wake the worker for reevaluation.
src-tauri/src/input/cursor_highlight.rs (1)

146-153: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Skip redundant MoveWindow calls while idle.

The loop calls position_window every 16 ms while the ring is visible, even when last_pos did not change. Each call invalidates the window and queues a repaint. Track the last applied position and move only on change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/input/cursor_highlight.rs` around lines 146 - 153, Update the
visibility loop around position_window to track the last position applied to the
window and call position_window only when the current last_pos differs from it.
Preserve the existing hide behavior and visible-position handling, while
updating the tracked position after each actual move.
src-tauri/src/input/mouse.rs (1)

17-34: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the duplicated default state definition.

The manual Default impl and the static initializer both describe the same initial state. They can diverge when a field is added. The Default impl also appears unused, because the static uses a const initializer.

Derive Default and keep the const initializer, or drop the impl.

♻️ Proposed simplification
+#[derive(Default)]
 struct TrackpadGestureState {
     active: bool,
     last_good: Option<(i32, i32)>,
 }
 
-impl Default for TrackpadGestureState {
-    fn default() -> Self {
-        Self {
-            active: false,
-            last_good: None,
-        }
-    }
-}
-
 static TRACKPAD_GESTURE: Mutex<TrackpadGestureState> = Mutex::new(TrackpadGestureState {
     active: false,
     last_good: None,
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/input/mouse.rs` around lines 17 - 34, Remove the manual Default
implementation for TrackpadGestureState and retain the static TRACKPAD_GESTURE
initializer, or derive Default if a default constructor is needed elsewhere.
Ensure only one authoritative default-state definition remains and preserve the
current active=false and last_good=None values.
src/components/layout/ResizableSplitPane.tsx (1)

109-122: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Set the drag state only after the hook accepts the gesture.

onSplitterPointerDown writes dragStateRef.current before it calls splitterDrag.onPointerDown. usePointerDrag returns early when enabled is false, so no onEnd runs and the ref keeps a stale value.

The splitter renders only when !sizedPaneCollapsed, so the path is unreachable today. The order still couples this component to the hook's internal guard. Add the same guard here.

♻️ Proposed guard
   const onSplitterPointerDown = (event: React.PointerEvent<HTMLDivElement>) => {
+    if (sizedPaneCollapsed) return;
     const container = containerRef.current;
     if (!container) return;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/layout/ResizableSplitPane.tsx` around lines 109 - 122, Update
onSplitterPointerDown to check the same enabled condition used by splitterDrag
before assigning dragStateRef.current, and return without starting the gesture
when disabled. Keep the container and width validation, then invoke
splitterDrag.onPointerDown before or alongside setting drag state only after the
gesture is accepted.
src/lib/pointerDrag.test.ts (1)

28-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the remaining usePointerDrag branches.

The suite covers the move path and the active-state transition. Three behaviors in the hook are untested:

  • enabled: false must skip onPointerDown and must not set the active state.
  • pointercancel must end the drag in the same way as pointerup.
  • onEnd must run once with the terminating event.

These branches guard drag state that can otherwise leak across gestures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/pointerDrag.test.ts` around lines 28 - 78, Extend the usePointerDrag
tests with coverage for the disabled option, asserting enabled: false skips
onPointerDown and leaves pointerDragActive false; add a pointercancel test
verifying it ends the drag like pointerup; and verify onEnd is called exactly
once with the terminating event. Use the existing renderHook setup,
__resetPointerDragActiveForTests, and window event dispatch patterns.
src/lib/layoutProfiles.ts (1)

3-33: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the snapshot functions from LAYOUT_PARTIAL_KEYS.

The three layout fields are listed three times: in LAYOUT_PARTIAL_KEYS, in snapshotFromSettings, and in applyLayoutSnapshot. If a fourth layout field is added later and one list is missed, that field is silently dropped from the touch or mouse profile with no type error.

Drive all three from the single key list.

♻️ Proposed refactor
 const LAYOUT_PARTIAL_KEYS = [
   "sectionStack",
   "inputRowRightRatio",
   "windowHeightRatio",
 ] as const satisfies ReadonlyArray<keyof AppSettings>;
 
 export function snapshotFromSettings(settings: AppSettings): LayoutSnapshot {
-  return {
-    sectionStack: settings.sectionStack,
-    inputRowRightRatio: settings.inputRowRightRatio,
-    windowHeightRatio: settings.windowHeightRatio,
-  };
+  const snap: LayoutSnapshot = {};
+  for (const key of LAYOUT_PARTIAL_KEYS) {
+    if (settings[key] !== undefined) {
+      Object.assign(snap, { [key]: settings[key] });
+    }
+  }
+  return snap;
 }
 
 export function applyLayoutSnapshot(
   settings: AppSettings,
   snap: LayoutSnapshot,
 ): AppSettings {
-  return {
-    ...settings,
-    ...(snap.sectionStack !== undefined
-      ? { sectionStack: snap.sectionStack }
-      : {}),
-    ...(snap.inputRowRightRatio !== undefined
-      ? { inputRowRightRatio: snap.inputRowRightRatio }
-      : {}),
-    ...(snap.windowHeightRatio !== undefined
-      ? { windowHeightRatio: snap.windowHeightRatio }
-      : {}),
-  };
+  const next = { ...settings };
+  for (const key of LAYOUT_PARTIAL_KEYS) {
+    if (snap[key] !== undefined) {
+      Object.assign(next, { [key]: snap[key] });
+    }
+  }
+  return next;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/layoutProfiles.ts` around lines 3 - 33, Refactor snapshotFromSettings
and applyLayoutSnapshot to iterate over LAYOUT_PARTIAL_KEYS instead of
explicitly naming each layout field, preserving undefined-snapshot values and
the existing AppSettings merge behavior. Ensure adding a key to
LAYOUT_PARTIAL_KEYS automatically includes it in both snapshot creation and
application.
src/lib/layoutProfiles.test.ts (1)

58-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add round-trip coverage for sectionStack.

Every test exercises only inputRowRightRatio. sectionStack is the largest snapshot field and the only object-valued one, so a shallow-copy or reference-sharing regression between the touch and mouse profiles would not be caught. Add one switch test that stores different sectionStack values per pointer kind and asserts they stay separate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/layoutProfiles.test.ts` around lines 58 - 83, Extend the
switchPointerInputKindLayout test coverage with distinct object-valued
sectionStack values for mouse and touch profiles, then assert switching to touch
restores its sectionStack and switching back restores the mouse value
independently. Ensure the assertions verify value separation rather than only
inputRowRightRatio.
src-tauri/src/window/mod.rs (1)

283-288: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the DPI effect, not a loose lower bound.

collapsed_window_includes_hover_and_dpi_slack passes with dpi_scale = 1.0 as well, so it does not prove that the DPI slack is applied. Compare the result against the same count at scale 1.0.

💚 Proposed test strengthening
     #[test]
     fn collapsed_window_includes_hover_and_dpi_slack() {
-        let (width, height) = compute_collapsed_dimensions(CollapsedFabCount::Two, 1.5);
-        assert!(width >= 76);
-        assert!(height >= 76);
+        let (base_w, base_h) = compute_collapsed_dimensions(CollapsedFabCount::Two, 1.0);
+        let (width, height) = compute_collapsed_dimensions(CollapsedFabCount::Two, 1.5);
+        let extra = (FAB_HOVER_SLACK as f32 * 1.5).ceil() as u32 - FAB_HOVER_SLACK;
+        assert_eq!(width, base_w + extra);
+        assert_eq!(height, base_h + extra);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/window/mod.rs` around lines 283 - 288, Strengthen
collapsed_window_includes_hover_and_dpi_slack by computing collapsed dimensions
for CollapsedFabCount::Two at both DPI scales 1.5 and 1.0, then assert that the
scaled result is larger than the baseline for the relevant dimensions. Retain
the existing minimum-size checks if needed, but ensure the test directly
verifies the DPI effect.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Around line 35-43: Align the Vite and Vitest dependency versions in
package.json by either upgrading vitest to a published release that supports
Vite 8 or pinning vite to a major supported by vitest 3.2.4. Preserve the
existing `@vitejs/plugin-react` compatibility and ensure the resulting dependency
range has no unsupported peer-version mismatch.

In `@src-tauri/src/icons.rs`:
- Around line 26-31: Update the cache-write flow around fs::rename so that a
rename failure re-checks whether cache_file now exists and returns its path when
valid. Only remove the temporary file and return None if the destination is
still unavailable, preserving the existing success path.

In `@src-tauri/src/input/cursor_highlight.rs`:
- Around line 114-157: Add a Windows message pump inside each iteration of
run_loop, after processing commands or before sleeping, by repeatedly calling
PeekMessageW for the overlay thread’s queue and passing retrieved messages
through TranslateMessage and DispatchMessageW. Preserve the existing command
handling, visibility updates, and shutdown behavior while ensuring all queued
window messages are removed and dispatched.

In `@src-tauri/src/input/focus_target.rs`:
- Around line 73-77: Update init so it no longer calls reevaluate_input_focus
directly on the caller thread; instead, schedule the initial evaluation through
the existing deferred worker mechanism while preserving hook installation and
app-handle setup order.

In `@src-tauri/src/lib.rs`:
- Around line 1028-1032: Update cmd_open_windows_settings to validate the
requested ms-settings page against a strict allowlist of supported settings
URIs, rejecting all other values before launching. Replace the cmd.exe
invocation with the registered tauri_plugin_opener or a Windows-only
ShellExecuteW call, preserving the existing error propagation and success
behavior.

In `@src-tauri/src/stt/mod.rs`:
- Around line 67-86: Update start_dictation to handle an existing
router().active backend before starting the selected engine: either reject the
request while active or stop the current backend first. Ensure the previous
backend cannot remain running when active is replaced, and preserve consistent
router state across the WinRt and Groq branches.

In `@src-tauri/src/window/mod.rs`:
- Around line 86-105: Update collapsed_fab_stack_height and
compute_collapsed_dimensions so COLLAPSED_SIZE, COLLAPSED_PAD, and
COLLAPSED_FAB_GAP are all scaled by dpi_scale before calculating the stack width
and height. Preserve the existing minimum scale behavior and continue including
the separately computed hover slack.

In `@src/components/mouse/Trackpad.tsx`:
- Around line 213-217: Update the movement handling around the dx/dy
calculations to accumulate fractional motion in subPixel.current before
rounding, preserving remainders across pointer events instead of discarding
them. Reset subPixel.current to { x: 0, y: 0 } in both onPointerDown and
endGesture so each gesture starts without stale movement.
- Around line 186-199: Update the cmd_trackpad_gesture_begin failure handler in
Trackpad.tsx to call pollError() after resetting dragging.current and
gestureReady.current for the active generation. Preserve the existing
stale-generation behavior and ensure the backend error is surfaced to the user
like the other trackpad actions.
- Around line 242-290: Use the existing gestureGen in endGesture to associate
flushThenEnd and endBackend with the gesture being ended. Capture the generation
before starting teardown, and abort any retry, cursor flush, backend end, or old
handleTap callback when gestureGen.current no longer matches, allowing a new
onPointerDown gesture to own rafId and backend cleanup.

In `@src/components/settings/SettingsPanel.tsx`:
- Around line 465-474: Update the Mini Mode control around the miniModeOverride
setting to expose all three states: null for Auto, true for forced On, and false
for forced Off. Replace the current boolean-only ToggleRow behavior with an
explicit Off option or tri-state control, ensuring user selection writes false
when disabling and preserves null for Auto.

In `@src/lib/miniMode.ts`:
- Around line 85-88: Update isMiniModeEligible to reject an empty monitors
array, returning true only when there is exactly one monitor or
isMirroredSetup(monitors) is true. Add a regression test asserting
isMiniModeEligible([]) returns false.

In `@src/lib/pointerDrag.ts`:
- Around line 92-105: Update src/lib/pointerDrag.ts lines 92-105 in
onPointerDown to return when activeRef.current is already set, preventing
concurrent pointers from orphaning the active gesture. Add unmount cleanup at
src/lib/pointerDrag.ts lines 107-113 to remove the pointermove, pointerup, and
pointercancel listeners, clear activeRef.current, and call
setPointerDragActive(false) when a drag is active.
- Around line 107-113: Add a useEffect cleanup in usePointerDrag that detects an
in-progress drag during unmount and invokes endDrag with the appropriate
event-free handling, ensuring all window listeners are removed and
activeDragCount is decremented. Import useEffect as needed, while preserving the
existing pointer event handlers.

In `@src/lib/toolWindows.ts`:
- Around line 57-71: Update getMonitors so failures from
invoke("cmd_list_monitors") are caught and return an empty MonitorInfo[] instead
of rejecting. Preserve the existing successful query behavior, allowing
openToolWindow and its positioning fallback to continue when no monitors are
available.

In `@src/stores/appStore.ts`:
- Around line 845-861: Update the miniModeSettingChanged condition in the store
update flow to depend only on miniModeOverride, excluding miniModeTransparent.
Preserve the existing refreshMiniModeState behavior for override changes and
leave transparency updates to the CSS path without triggering window layout
animation.

---

Minor comments:
In `@companion/.expo/README.md`:
- Around line 11-14: Remove the committed files companion/.expo/README.md (lines
11-14) and companion/.expo/devices.json (lines 1-3) from Git, and add the
companion/.expo/ ignore rule to the relevant .gitignore if it is not already
present.

In `@src/i18n/it.ts`:
- Around line 30-42: Standardize the Mini Mode feature-name capitalization
across all new locale strings: in src/i18n/it.ts lines 30-42, make miniMode and
miniModeCollapse consistently use “Modalità Mini”; in src/i18n/pt.ts lines
30-42, make them consistently use “Modo Mini”. Review the remaining locale files
for the same miniMode and miniModeCollapse inconsistency and apply each
language’s chosen capitalization consistently to all Mini Mode keys.

In `@src/lib/layoutProfiles.test.ts`:
- Around line 25-31: Update the mouse-layout assertion in the test around
persistLayoutForKind to assert that stored.mouseLayout is absent, since base
does not define one. Remove the nullish fallback and preserve the existing
touch-layout value assertion.

In `@src/lib/pointerDrag.ts`:
- Around line 69-70: Move the optionsRef.current assignment out of the render
path and update it in a layout effect within the pointer-drag hook, ensuring
callbacks come from the committed render before event handlers use them. Keep
optionsRef initialized with options and retain the existing event-handler access
through optionsRef.

In `@src/stores/appStore.ts`:
- Around line 889-919: Debounce pointer-kind changes initiated by
handlePointerInputEvent before invoking setPointerInputKind, so rapid
alternating pointerdown events coalesce into one update and avoid overlapping
persistence/layout synchronization. Keep the existing no-op behavior for the
current kind and preserve setPointerInputKind’s persistence and window-sync
logic.
- Around line 82-126: Update toggleCollapsed’s finally block to drain
pendingMiniLayoutSync after the transition completes, handling any queued Mini
Mode layout sync using the existing syncMiniModeWindowLayout flow. Preserve the
current cleanup behavior and ensure the queued request is cleared and executed
when appropriate.

---

Nitpick comments:
In `@src-tauri/src/input/cursor_highlight.rs`:
- Around line 146-153: Update the visibility loop around position_window to
track the last position applied to the window and call position_window only when
the current last_pos differs from it. Preserve the existing hide behavior and
visible-position handling, while updating the tracked position after each actual
move.

In `@src-tauri/src/input/focus_target.rs`:
- Around line 240-243: Remove the redundant
lower.starts_with("chrome_widgetwin") condition from is_chromium_class, leaving
only the chrome_ prefix check while preserving the existing case-insensitive
behavior.
- Around line 418-441: The schedule_reevaluate_input_focus flow should use one
long-lived dedicated worker instead of spawning a thread per burst. Move COM
initialization and CUIAutomation creation into that worker’s thread-local setup,
keep the UIA instance alive while waiting on a condition variable, and replace
the REEVAL_DIRTY/REEVAL_WORKER_BUSY handshake with condition-variable signaling
so focus events wake the worker for reevaluation.

In `@src-tauri/src/input/mouse.rs`:
- Around line 17-34: Remove the manual Default implementation for
TrackpadGestureState and retain the static TRACKPAD_GESTURE initializer, or
derive Default if a default constructor is needed elsewhere. Ensure only one
authoritative default-state definition remains and preserve the current
active=false and last_good=None values.

In `@src-tauri/src/lib.rs`:
- Around line 310-336: Introduce a shared LayoutOptions struct containing
monitor_id and all layout flags and ratios, plus the expanded constructor shown
by the existing conventions. Update apply_window_layout, animate_window_layout,
compute_window_layout, and every affected call site to accept or pass
LayoutOptions instead of positional parameters, using named fields to make
layout intent explicit and preserving current behavior.

In `@src-tauri/src/window/mod.rs`:
- Around line 283-288: Strengthen collapsed_window_includes_hover_and_dpi_slack
by computing collapsed dimensions for CollapsedFabCount::Two at both DPI scales
1.5 and 1.0, then assert that the scaled result is larger than the baseline for
the relevant dimensions. Retain the existing minimum-size checks if needed, but
ensure the test directly verifies the DPI effect.

In `@src/components/layout/ResizableSplitPane.tsx`:
- Around line 109-122: Update onSplitterPointerDown to check the same enabled
condition used by splitterDrag before assigning dragStateRef.current, and return
without starting the gesture when disabled. Keep the container and width
validation, then invoke splitterDrag.onPointerDown before or alongside setting
drag state only after the gesture is accepted.

In `@src/lib/layoutProfiles.test.ts`:
- Around line 58-83: Extend the switchPointerInputKindLayout test coverage with
distinct object-valued sectionStack values for mouse and touch profiles, then
assert switching to touch restores its sectionStack and switching back restores
the mouse value independently. Ensure the assertions verify value separation
rather than only inputRowRightRatio.

In `@src/lib/layoutProfiles.ts`:
- Around line 3-33: Refactor snapshotFromSettings and applyLayoutSnapshot to
iterate over LAYOUT_PARTIAL_KEYS instead of explicitly naming each layout field,
preserving undefined-snapshot values and the existing AppSettings merge
behavior. Ensure adding a key to LAYOUT_PARTIAL_KEYS automatically includes it
in both snapshot creation and application.

In `@src/lib/pointerDrag.test.ts`:
- Around line 28-78: Extend the usePointerDrag tests with coverage for the
disabled option, asserting enabled: false skips onPointerDown and leaves
pointerDragActive false; add a pointercancel test verifying it ends the drag
like pointerup; and verify onEnd is called exactly once with the terminating
event. Use the existing renderHook setup, __resetPointerDragActiveForTests, and
window event dispatch patterns.

In `@vitest.config.ts`:
- Around line 1-7: Update the Vitest setup referenced by the test configuration
to import Testing Library’s cleanup and invoke cleanup() from the existing
afterEach hook. Ensure the setup runs for every test so renderHook instances
unmount and remove subscriptions, while preserving the current Node environment
configuration.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5409213e-5508-4c51-a944-ab6452dc83c9

📥 Commits

Reviewing files that changed from the base of the PR and between ae94120 and 06482d5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (63)
  • .cursor/mcp.json
  • .cursor/rules/windows-only.mdc
  • .github/scripts/generate-latest-json.mjs
  • .github/workflows/build.yml
  • .github/workflows/release.yml
  • .gitignore
  • CONTRIBUTING.md
  • README.md
  • companion/.expo/README.md
  • companion/.expo/devices.json
  • docs/accessibility-requirements.md
  • docs/superpowers/plans/2026-08-11-mini-mode-layout-fixes.md
  • package.json
  • src-tauri/src/icons.rs
  • src-tauri/src/input/cursor_highlight.rs
  • src-tauri/src/input/focus_target.rs
  • src-tauri/src/input/mod.rs
  • src-tauri/src/input/mouse.rs
  • src-tauri/src/input/stub.rs
  • src-tauri/src/installed_apps.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/stt/mod.rs
  • src-tauri/src/stt/network.rs
  • src-tauri/src/stt/stub.rs
  • src-tauri/src/tts/mod.rs
  • src-tauri/src/tts/stub.rs
  • src-tauri/src/window/mod.rs
  • src-tauri/src/window/stub.rs
  • src-tauri/src/window/windows.rs
  • src-tauri/tauri.conf.json
  • src/App.tsx
  • src/components/common/ModeToggle.tsx
  • src/components/common/SectionIcons.tsx
  • src/components/common/SuggestionsBar.tsx
  • src/components/keyboard/DictationButton.tsx
  • src/components/keyboard/KeyButton.tsx
  • src/components/keyboard/Keyboard.tsx
  • src/components/keyboard/KeyboardSection.tsx
  • src/components/layout/AppShell.tsx
  • src/components/layout/CollapsedFab.tsx
  • src/components/layout/FloatingSection.tsx
  • src/components/layout/MiniModeShell.tsx
  • src/components/layout/ResizableSplitPane.tsx
  • src/components/layout/SectionCanvas.tsx
  • src/components/mouse/Trackpad.tsx
  • src/components/settings/SettingsPanel.tsx
  • src/i18n/de.ts
  • src/i18n/el.ts
  • src/i18n/en.ts
  • src/i18n/es.ts
  • src/i18n/fr.ts
  • src/i18n/it.ts
  • src/i18n/pt.ts
  • src/lib/layoutProfiles.test.ts
  • src/lib/layoutProfiles.ts
  • src/lib/miniMode.test.ts
  • src/lib/miniMode.ts
  • src/lib/pointerDrag.test.ts
  • src/lib/pointerDrag.ts
  • src/lib/toolWindows.ts
  • src/lib/types.ts
  • src/stores/appStore.ts
  • vitest.config.ts
💤 Files with no reviewable changes (6)
  • src-tauri/src/tts/stub.rs
  • src-tauri/src/window/stub.rs
  • .github/scripts/generate-latest-json.mjs
  • src-tauri/src/stt/stub.rs
  • src-tauri/src/input/stub.rs
  • src-tauri/src/tts/mod.rs

Comment thread package.json Outdated
Comment thread src-tauri/src/icons.rs
Comment thread src-tauri/src/input/cursor_highlight.rs
Comment thread src-tauri/src/input/focus_target.rs
Comment thread src-tauri/src/lib.rs Outdated
Comment thread src/lib/miniMode.ts
Comment thread src/lib/pointerDrag.ts
Comment thread src/lib/pointerDrag.ts
Comment thread src/lib/toolWindows.ts
Comment thread src/stores/appStore.ts Outdated
Co-authored-by: Cursor <cursoragent@cursor.com>
pountzas and others added 17 commits August 12, 2026 18:23
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
fix: address PR review findings across Mini Mode input and tooling

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/db/mod.rs`:
- Around line 1050-1067: Close or otherwise release the database connection
owned by db before calling std::fs::remove_dir_all(dir) in this test cleanup
block. Ensure all SQLite handles, including the connection guarded by db.conn,
are dropped before removal, and handle the cleanup result according to the
existing test conventions instead of ignoring a Windows failure.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2dad0ace-94aa-4e30-8173-1dd19c8b60ed

📥 Commits

Reviewing files that changed from the base of the PR and between 06482d5 and 1517b83.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (31)
  • .gitignore
  • package.json
  • src-tauri/src/db/mod.rs
  • src-tauri/src/icons.rs
  • src-tauri/src/input/cursor_highlight.rs
  • src-tauri/src/input/focus_target.rs
  • src-tauri/src/input/mouse.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/stt/mod.rs
  • src-tauri/src/window/mod.rs
  • src/App.tsx
  • src/components/layout/ResizableSplitPane.tsx
  • src/components/mouse/Trackpad.tsx
  • src/components/settings/SettingsPanel.tsx
  • src/i18n/de.ts
  • src/i18n/el.ts
  • src/i18n/en.ts
  • src/i18n/es.ts
  • src/i18n/fr.ts
  • src/i18n/it.ts
  • src/i18n/pt.ts
  • src/lib/layoutProfiles.test.ts
  • src/lib/layoutProfiles.ts
  • src/lib/miniMode.test.ts
  • src/lib/miniMode.ts
  • src/lib/pointerDrag.test.ts
  • src/lib/pointerDrag.ts
  • src/lib/toolWindows.ts
  • src/stores/appStore.ts
  • vitest.config.ts
  • vitest.setup.ts
💤 Files with no reviewable changes (1)
  • src-tauri/src/input/mouse.rs
🚧 Files skipped from review as they are similar to previous changes (23)
  • src/i18n/en.ts
  • vitest.config.ts
  • src/i18n/el.ts
  • src/i18n/es.ts
  • src/i18n/fr.ts
  • src/App.tsx
  • .gitignore
  • src/lib/layoutProfiles.test.ts
  • src/i18n/pt.ts
  • src/components/layout/ResizableSplitPane.tsx
  • src/i18n/de.ts
  • src/lib/layoutProfiles.ts
  • src/lib/toolWindows.ts
  • src/components/settings/SettingsPanel.tsx
  • src-tauri/src/icons.rs
  • src/i18n/it.ts
  • src-tauri/src/stt/mod.rs
  • src/lib/pointerDrag.ts
  • src/components/mouse/Trackpad.tsx
  • src/lib/miniMode.ts
  • package.json
  • src-tauri/src/input/focus_target.rs
  • src-tauri/src/window/mod.rs

Comment thread src-tauri/src/db/mod.rs
Comment on lines +1050 to +1067
let conn = db.conn.lock().expect("lock");
let cats: i64 = conn
.query_row(
"SELECT COUNT(*) FROM phrase_categories WHERE profile_id = 'orphan'",
[],
|r| r.get(0),
)
.expect("count categories");
assert!(cats >= 2, "expected Basic Needs + Emergency categories");
let phrases: i64 = conn
.query_row(
"SELECT COUNT(*) FROM phrases WHERE profile_id = 'orphan' AND language = 'el'",
[],
|r| r.get(0),
)
.expect("count phrases");
assert!(phrases > 0, "expected locale phrases to be seeded");
let _ = std::fs::remove_dir_all(dir);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Close the database before removing the temporary directory.

db still owns the SQLite connection at Line 1067. Windows keeps reach-panel.db locked, so remove_dir_all(dir) fails. The ignored result leaves a temporary directory after each test run.

Proposed fix
         assert!(phrases > 0, "expected locale phrases to be seeded");
-        let _ = std::fs::remove_dir_all(dir);
+        drop(conn);
+        drop(db);
+        std::fs::remove_dir_all(dir).expect("remove temp db directory");

As per coding guidelines, ReachPanel targets Windows only.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let conn = db.conn.lock().expect("lock");
let cats: i64 = conn
.query_row(
"SELECT COUNT(*) FROM phrase_categories WHERE profile_id = 'orphan'",
[],
|r| r.get(0),
)
.expect("count categories");
assert!(cats >= 2, "expected Basic Needs + Emergency categories");
let phrases: i64 = conn
.query_row(
"SELECT COUNT(*) FROM phrases WHERE profile_id = 'orphan' AND language = 'el'",
[],
|r| r.get(0),
)
.expect("count phrases");
assert!(phrases > 0, "expected locale phrases to be seeded");
let _ = std::fs::remove_dir_all(dir);
let conn = db.conn.lock().expect("lock");
let cats: i64 = conn
.query_row(
"SELECT COUNT(*) FROM phrase_categories WHERE profile_id = 'orphan'",
[],
|r| r.get(0),
)
.expect("count categories");
assert!(cats >= 2, "expected Basic Needs + Emergency categories");
let phrases: i64 = conn
.query_row(
"SELECT COUNT(*) FROM phrases WHERE profile_id = 'orphan' AND language = 'el'",
[],
|r| r.get(0),
)
.expect("count phrases");
assert!(phrases > 0, "expected locale phrases to be seeded");
drop(conn);
drop(db);
std::fs::remove_dir_all(dir).expect("remove temp db directory");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/db/mod.rs` around lines 1050 - 1067, Close or otherwise release
the database connection owned by db before calling std::fs::remove_dir_all(dir)
in this test cleanup block. Ensure all SQLite handles, including the connection
guarded by db.conn, are dropped before removal, and handle the cleanup result
according to the existing test conventions instead of ignoring a Windows
failure.

Sources: Coding guidelines, Learnings

…icts.

Keep Mini Mode toolbar and predictions off/enable UX; apply theme-aware suggestion chip colors from main.

Co-authored-by: Cursor <cursoragent@cursor.com>
@pountzas
pountzas merged commit b1be5eb into main Aug 12, 2026
2 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Aug 20, 2026
Merged
2 of 3 tasks
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.

1 participant