Skip to content

Refactor UI thread invocation with DispatcherHelper#4335

Open
Jack251970 wants to merge 7 commits intodevfrom
DispatcherHelper
Open

Refactor UI thread invocation with DispatcherHelper#4335
Jack251970 wants to merge 7 commits intodevfrom
DispatcherHelper

Conversation

@Jack251970
Copy link
Copy Markdown
Member

@Jack251970 Jack251970 commented Mar 10, 2026

No logic changes. Added DispatcherHelper and replace all UI thread invocation with it.


Summary by cubic

Centralized UI-thread invocation behind DispatcherHelper to make cross-thread UI updates safer and reduce boilerplate. Async delegates are fully awaited to avoid premature continuation.

  • Summary of changes
    • Changed: Replaced direct Dispatcher.Invoke/InvokeAsync and CheckAccess with DispatcherHelper.Invoke/InvokeAsync across windows, view models, dialogs, notifications, settings, plugin update prompts, theme/wallpaper helpers, and public API methods for opening settings and plugin settings windows. Used explicit DispatcherPriority where needed and consolidated nested dispatcher calls (e.g., fade-out storyboard). Renamed private helpers to *Core for clarity (ShowCore, ChangeQueryTextCore/ChangeQueryTextCoreAsync, ReportProgressCore, GetWallpaperBrushCore).
    • Added: New Flow.Launcher.Core/Resource/DispatcherHelper with sync/async overloads for Action, Func<T>, and Func<Task>, optional Dispatcher parameter, DispatcherPriority support, CheckAccess short-circuiting, and null-safe handling when Application.Current or a Dispatcher is unavailable. Async delegates use double-await so callers wait for completion.
    • Removed: Redundant CheckAccess branches, nested dispatcher invocations, and scattered Application.Current.Dispatcher calls.
    • Memory: No meaningful change; DispatcherHelper is static with minimal allocations.
    • Security: No new risks; safer cross-thread UI access and graceful no-op when dispatcher is unavailable.
    • Unit tests: No new unit tests; verified via existing UI flows.

Written for commit 66e9e6f. Summary will update on new commits.

Introduce DispatcherHelper for safe UI thread access and replace direct Dispatcher.Invoke calls across the codebase. This centralizes thread invocation logic, reduces boilerplate, and improves maintainability. Some methods are refactored for clarity and UI thread safety.
Copilot AI review requested due to automatic review settings March 10, 2026 03:49
@prlabeler prlabeler bot added Code Refactor enhancement New feature or request labels Mar 10, 2026
@github-actions github-actions bot added this to the 2.2.0 milestone Mar 10, 2026
@Jack251970 Jack251970 removed the enhancement New feature or request label Mar 10, 2026
@prlabeler prlabeler bot added the enhancement New feature or request label Mar 10, 2026
@gitstream-cm
Copy link
Copy Markdown

gitstream-cm bot commented Mar 10, 2026

🥷 Code experts: no user but you matched threshold 10

Jack251970 has most 👩‍💻 activity in the files.
Jack251970 has most 🧠 knowledge in the files.

See details

Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher.Core/Resource/Theme.cs

Activity based on git-commit:

Jack251970
MAR 64 additions & 79 deletions
FEB
JAN
DEC
NOV
OCT 12 additions & 2 deletions

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/App.xaml.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN 1 additions & 0 deletions
DEC
NOV
OCT 4 additions & 0 deletions

Knowledge based on git-blame:
Jack251970: 99%

Flow.Launcher/Helper/SingleInstance.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/Helper/WallpaperPathRetrieval.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/MainWindow.xaml.cs

Activity based on git-commit:

Jack251970
MAR 5 additions & 3 deletions
FEB
JAN
DEC
NOV 1 additions & 1 deletions
OCT 8 additions & 7 deletions

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/MessageBoxEx.xaml.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/Msg.xaml.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/MsgWithButton.xaml.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/Notification.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/ProgressBoxEx.xaml.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/PublicAPIInstance.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT 4 additions & 1 deletions

Knowledge based on git-blame:
Jack251970: 98%

Flow.Launcher/ReleaseNotesWindow.xaml.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT 6 additions & 7 deletions

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs

Activity based on git-commit:

Jack251970
MAR
FEB
JAN
DEC
NOV
OCT

Knowledge based on git-blame:
Jack251970: 100%

Flow.Launcher/ViewModel/MainViewModel.cs

Activity based on git-commit:

Jack251970
MAR
FEB 11 additions & 6 deletions
JAN 50 additions & 35 deletions
DEC
NOV 106 additions & 94 deletions
OCT 125 additions & 88 deletions

Knowledge based on git-blame:
Jack251970: 96%

✨ Comment /gs review for LinearB AI review. Learn how to automate it here.

@gitstream-cm
Copy link
Copy Markdown

gitstream-cm bot commented Mar 10, 2026

Be a legend 🏆 by adding a before and after screenshot of the changes you made, especially if they are around UI/UX.

@coderabbitai coderabbitai bot removed the enhancement New feature or request label Mar 10, 2026
@Flow-Launcher Flow-Launcher deleted a comment from gitstream-cm bot Mar 10, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new DispatcherHelper static class in Flow.Launcher.Core/Resource/ that centralizes UI thread dispatching logic — checking thread access and calling the action directly if already on the UI thread, or marshalling to the dispatcher otherwise. It replaces all the scattered, boilerplate Dispatcher.CheckAccess() guard patterns across the codebase.

Changes:

  • New DispatcherHelper class added to Flow.Launcher.Core/Resource/ with Invoke and InvokeAsync overloads handling both Action/Func<T> and Func<Task> delegates.
  • All UI thread invocations throughout Flow.Launcher and Flow.Launcher.Core replaced to use DispatcherHelper, removing repetitive thread-check patterns.
  • Several methods are split into a public dispatcher-aware wrapper (e.g., ChangeQueryText) and a private implementation (e.g., ChangeQueryText1) to align with the new helper's design.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Flow.Launcher.Core/Resource/DispatcherHelper.cs New helper class centralizing dispatcher thread-safety logic
Flow.Launcher.Core/Resource/Theme.cs Replace Dispatcher.InvokeAsync calls with DispatcherHelper.InvokeAsync
Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs Replace element-dispatcher calls with DispatcherHelper.Invoke
Flow.Launcher/ViewModel/MainViewModel.cs Replace all dispatcher invocations; extract ChangeQueryText1/ChangeQueryText1Async helpers
Flow.Launcher/App.xaml.cs Replace Current.Dispatcher.Invoke calls with DispatcherHelper
Flow.Launcher/MainWindow.xaml.cs Replace all Dispatcher.Invoke calls with DispatcherHelper.Invoke
Flow.Launcher/MessageBoxEx.xaml.cs Extract Show1 helper method; use DispatcherHelper.Invoke
Flow.Launcher/ProgressBoxEx.xaml.cs Simplify thread-check pattern; extract ReportProgress1 helper
Flow.Launcher/Msg.xaml.cs Replace Dispatcher.InvokeAsync with DispatcherHelper.InvokeAsync
Flow.Launcher/MsgWithButton.xaml.cs Replace Dispatcher.InvokeAsync with DispatcherHelper.InvokeAsync
Flow.Launcher/Notification.cs Replace Application.Current.Dispatcher.Invoke with DispatcherHelper.Invoke
Flow.Launcher/PublicAPIInstance.cs Replace dispatcher call with DispatcherHelper.Invoke
Flow.Launcher/ReleaseNotesWindow.xaml.cs Replace dispatcher calls with DispatcherHelper.Invoke
Flow.Launcher/Helper/WallpaperPathRetrieval.cs Extract GetWallpaperBrush1 helper; use DispatcherHelper.Invoke
Flow.Launcher/Helper/SingleInstance.cs Replace Application.Current?.Dispatcher.Invoke with DispatcherHelper.Invoke
Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs Replace dispatcher call with DispatcherHelper.Invoke

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Refactored private methods previously suffixed with "1" to use the "Core" suffix instead (e.g., GetWallpaperBrush1 → GetWallpaperBrushCore). Updated all corresponding invocations. This improves naming consistency and aligns with common conventions for core logic methods.
@prlabeler prlabeler bot added bug Something isn't working enhancement New feature or request labels Mar 10, 2026
@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 16 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Flow.Launcher.Core/Resource/DispatcherHelper.cs">

<violation number="1" location="Flow.Launcher.Core/Resource/DispatcherHelper.cs:98">
P2: Awaiting Dispatcher.InvokeAsync(func) only waits for the delegate to return a Task, not for that Task to complete. This makes InvokeAsync(Func<Task>) return early (and miss exceptions) when called from a non-UI thread. Await the returned Task as well to make behavior consistent with the CheckAccess branch.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Ensure that async functions invoked via dispatcher are awaited until completion, not just until scheduled, by using double await on InvokeAsync. This prevents premature continuation when the delegate itself is asynchronous.
@github-actions

This comment has been minimized.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0927fb1f-c59f-4dd5-a439-e82ec1eb9856

📥 Commits

Reviewing files that changed from the base of the PR and between d23129f and 66e9e6f.

📒 Files selected for processing (1)
  • Flow.Launcher/PublicAPIInstance.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • Flow.Launcher/PublicAPIInstance.cs

📝 Walkthrough

Walkthrough

Introduces a centralized WPF dispatcher utility (DispatcherHelper) and replaces direct Dispatcher/CheckAccess usages across many UI and helper files, routing synchronous and asynchronous UI work through DispatcherHelper and extracting small core methods where appropriate.

Changes

Cohort / File(s) Summary
Core Dispatcher Abstraction
Flow.Launcher.Core/Resource/DispatcherHelper.cs
New static helper providing synchronous and asynchronous Invoke/InvokeAsync overloads; resolves dispatcher, handles null and CheckAccess, and marshals to Dispatcher.Invoke / InvokeAsync.
Theme & Core Plugin
Flow.Launcher.Core/Resource/Theme.cs, Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs
Switched Theme and plugin UI-thread calls to use DispatcherHelper; added using Flow.Launcher.Core.Resource where required.
App & Main Window
Flow.Launcher/App.xaml.cs, Flow.Launcher/MainWindow.xaml.cs, Flow.Launcher/ReleaseNotesWindow.xaml.cs
Replaced Application.Current.Dispatcher invocations with DispatcherHelper calls in startup, lifecycle, event handlers, and theme refresh paths.
ViewModels & Public API
Flow.Launcher/ViewModel/MainViewModel.cs, Flow.Launcher/PublicAPIInstance.cs, Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs
Standardized dispatcher usage to DispatcherHelper; introduced small core wrapper methods and added VSTHRD suppression where needed.
Dialogs, Notifications & Progress
Flow.Launcher/MessageBoxEx.xaml.cs, Flow.Launcher/Msg.xaml.cs, Flow.Launcher/MsgWithButton.xaml.cs, Flow.Launcher/Notification.cs, Flow.Launcher/ProgressBoxEx.xaml.cs
Replaced CheckAccess / Dispatcher.InvokeAsync patterns with DispatcherHelper calls; extracted private core helpers and adjusted storyboard await/call patterns.
Helpers & Utilities
Flow.Launcher/Helper/SingleInstance.cs, Flow.Launcher/Helper/WallpaperPathRetrieval.cs
SingleInstance and WallpaperPathRetrieval now invoke UI work via DispatcherHelper (added VSTHRD suppression where needed); moved wallpaper logic to GetWallpaperBrushCore.
Minor / Usings
multiple files
Added using Flow.Launcher.Core.Resource imports where DispatcherHelper is used; small refactors to centralize UI-thread execution.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Caller (View / ViewModel / Helper)
    participant Helper as DispatcherHelper
    participant Disp as Dispatcher (Application.Current.Dispatcher)
    participant UI as UI Control / Window

    Caller->>Helper: Invoke(...) / InvokeAsync(...)
    Helper->>Disp: Resolve dispatcher (implicit or explicit)
    alt Disp is null or Disp.CheckAccess == true
        Helper->>UI: Execute action directly
    else
        Helper->>Disp: Dispatcher.Invoke / InvokeAsync (marshal to UI thread)
        Disp->>UI: Execute action on UI thread
    end
    UI-->>Caller: result / completion
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • jjw24
  • onesounds
  • taooceros
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Refactor UI thread invocation with DispatcherHelper' accurately and specifically describes the main change: a refactoring that centralizes UI thread invocations through a new DispatcherHelper utility.
Description check ✅ Passed The description clearly explains the changes: adding DispatcherHelper and replacing all UI thread invocations throughout the codebase, with specific details about the scope and benefits.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DispatcherHelper

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Flow.Launcher/MainWindow.xaml.cs (1)

267-273: ⚠️ Potential issue | 🟡 Minor

Keep the low-priority caret move.

Line 272 uses DispatcherHelper.Invoke() without specifying a priority, which defaults to DispatcherPriority.Normal. However, the adjacent comment explicitly states this work must wait until the TextBox catches up with the bound query text by using a lower priority like ContextIdle. Since DispatcherHelper.Invoke supports a DispatcherPriority parameter (with default Normal), the call should pass DispatcherPriority.ContextIdle to honor the documented requirement.

🛠️ Proposed fix
-                            DispatcherHelper.Invoke(() => QueryTextBox.CaretIndex = QueryTextBox.Text.Length);
+                            DispatcherHelper.Invoke(
+                                () => QueryTextBox.CaretIndex = QueryTextBox.Text.Length,
+                                DispatcherPriority.ContextIdle);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Flow.Launcher/MainWindow.xaml.cs` around lines 267 - 273, The caret move is
currently dispatched with the default (Normal) priority, but the comment
requires a lower priority so the TextBox binding can update first; update the
call in MainWindow.xaml.cs where you handle
MainViewModel.QueryTextCursorMovedToEnd to call DispatcherHelper.Invoke with
DispatcherPriority.ContextIdle when setting QueryTextBox.CaretIndex =
QueryTextBox.Text.Length (referencing QueryTextBox and
_viewModel.QueryTextCursorMovedToEnd) so the dispatch honors the ContextIdle
scheduling requirement.
🧹 Nitpick comments (2)
Flow.Launcher/MsgWithButton.xaml.cs (1)

86-93: Unnecessary async keyword on the lambda.

The lambda passed to DispatcherHelper.InvokeAsync is marked async but contains no await expressions. Since fadeOutStoryboard.Begin() is synchronous, the async keyword can be removed.

♻️ Suggested fix
-            await DispatcherHelper.InvokeAsync(async () =>
+            await DispatcherHelper.InvokeAsync(() =>
             {
                 if (!closing)
                 {
                     closing = true;
                     fadeOutStoryboard.Begin();
                 }
             });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Flow.Launcher/MsgWithButton.xaml.cs` around lines 86 - 93, The lambda passed
to DispatcherHelper.InvokeAsync is marked async but contains no awaits; remove
the unnecessary async modifier so the delegate is synchronous (e.g., replace
"async () => { ... }" with "() => { ... }") in the call that checks the closing
flag and calls fadeOutStoryboard.Begin(), updating the closure around the
closing variable and fadeOutStoryboard.Begin() accordingly.
Flow.Launcher/Msg.xaml.cs (1)

84-91: Unnecessary async keyword on the lambda.

Same as in MsgWithButton.xaml.cs - the lambda is marked async but contains no await expressions since fadeOutStoryboard.Begin() is synchronous.

♻️ Suggested fix
-            await DispatcherHelper.InvokeAsync(async () =>
+            await DispatcherHelper.InvokeAsync(() =>
             {
                 if (!closing)
                 {
                     closing = true;
                     fadeOutStoryboard.Begin();
                 }
             });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Flow.Launcher/Msg.xaml.cs` around lines 84 - 91, The lambda passed to
DispatcherHelper.InvokeAsync in Msg.xaml.cs is marked async but contains no
await; remove the unnecessary async modifier from the lambda (the block that
checks and sets the closing flag and calls fadeOutStoryboard.Begin()) so the
delegate is a synchronous Action/Func<Task> appropriate for InvokeAsync and
avoid the redundant async state machine.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Flow.Launcher.Core/Resource/DispatcherHelper.cs`:
- Around line 63-85: The fast-path CheckAccess() in the Dispatcher helper
methods causes callers on the UI thread to run immediately and ignore the
requested DispatcherPriority; update both InvokeAsync(Dispatcher, Action,
DispatcherPriority) and InvokeAsync<T>(Dispatcher, Func<T>, DispatcherPriority)
to keep the null dispatcher guard but remove the CheckAccess() branch and
unconditionally call and await dispatcher.InvokeAsync(..., priority) so the
dispatcher always enqueues the delegate with the requested priority (i.e., await
dispatcher.InvokeAsync(action, priority) and return await
dispatcher.InvokeAsync(func, priority) respectively).

---

Outside diff comments:
In `@Flow.Launcher/MainWindow.xaml.cs`:
- Around line 267-273: The caret move is currently dispatched with the default
(Normal) priority, but the comment requires a lower priority so the TextBox
binding can update first; update the call in MainWindow.xaml.cs where you handle
MainViewModel.QueryTextCursorMovedToEnd to call DispatcherHelper.Invoke with
DispatcherPriority.ContextIdle when setting QueryTextBox.CaretIndex =
QueryTextBox.Text.Length (referencing QueryTextBox and
_viewModel.QueryTextCursorMovedToEnd) so the dispatch honors the ContextIdle
scheduling requirement.

---

Nitpick comments:
In `@Flow.Launcher/Msg.xaml.cs`:
- Around line 84-91: The lambda passed to DispatcherHelper.InvokeAsync in
Msg.xaml.cs is marked async but contains no await; remove the unnecessary async
modifier from the lambda (the block that checks and sets the closing flag and
calls fadeOutStoryboard.Begin()) so the delegate is a synchronous
Action/Func<Task> appropriate for InvokeAsync and avoid the redundant async
state machine.

In `@Flow.Launcher/MsgWithButton.xaml.cs`:
- Around line 86-93: The lambda passed to DispatcherHelper.InvokeAsync is marked
async but contains no awaits; remove the unnecessary async modifier so the
delegate is synchronous (e.g., replace "async () => { ... }" with "() => { ...
}") in the call that checks the closing flag and calls
fadeOutStoryboard.Begin(), updating the closure around the closing variable and
fadeOutStoryboard.Begin() accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ea6d1961-6a5e-4a51-8628-416173c8a2f4

📥 Commits

Reviewing files that changed from the base of the PR and between 916b4ff and 036713c.

📒 Files selected for processing (16)
  • Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs
  • Flow.Launcher.Core/Resource/DispatcherHelper.cs
  • Flow.Launcher.Core/Resource/Theme.cs
  • Flow.Launcher/App.xaml.cs
  • Flow.Launcher/Helper/SingleInstance.cs
  • Flow.Launcher/Helper/WallpaperPathRetrieval.cs
  • Flow.Launcher/MainWindow.xaml.cs
  • Flow.Launcher/MessageBoxEx.xaml.cs
  • Flow.Launcher/Msg.xaml.cs
  • Flow.Launcher/MsgWithButton.xaml.cs
  • Flow.Launcher/Notification.cs
  • Flow.Launcher/ProgressBoxEx.xaml.cs
  • Flow.Launcher/PublicAPIInstance.cs
  • Flow.Launcher/ReleaseNotesWindow.xaml.cs
  • Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs
  • Flow.Launcher/ViewModel/MainViewModel.cs

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Refactored method name for clarity and consistency. Updated all internal references to use the new method name. No functional changes were made.
@github-actions

This comment has been minimized.

@coderabbitai coderabbitai bot removed the bug Something isn't working label Mar 10, 2026
@coderabbitai coderabbitai bot removed the enhancement New feature or request label Mar 10, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@Flow.Launcher.Core/Resource/DispatcherHelper.cs`:
- Around line 89-100: The CI flags the "await await" pattern in InvokeAsync;
replace the single "await await dispatcher.InvokeAsync(func, priority);" with
two statements to avoid the repeated-word pattern: call
dispatcher.InvokeAsync(func, priority), await that DispatcherOperation<Task> to
get the inner Task (e.g. "var innerTask = await dispatcher.InvokeAsync(func,
priority);"), then await the innerTask with a second await (e.g. "await
innerTask;") inside the InvokeAsync method to preserve behavior while satisfying
the forbidden-pattern rule.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5fbff59f-5a9b-4347-a3ef-88d72bb59709

📥 Commits

Reviewing files that changed from the base of the PR and between 036713c and a12645d.

📒 Files selected for processing (5)
  • Flow.Launcher.Core/Resource/DispatcherHelper.cs
  • Flow.Launcher/Helper/WallpaperPathRetrieval.cs
  • Flow.Launcher/MessageBoxEx.xaml.cs
  • Flow.Launcher/ProgressBoxEx.xaml.cs
  • Flow.Launcher/ViewModel/MainViewModel.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • Flow.Launcher/Helper/WallpaperPathRetrieval.cs

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@prlabeler prlabeler bot added the enhancement New feature or request label Mar 10, 2026
@Jack251970 Jack251970 removed the enhancement New feature or request label Mar 10, 2026
@prlabeler prlabeler bot added the enhancement New feature or request label Apr 4, 2026
Replaced Application.Current.Dispatcher.Invoke with DispatcherHelper.Invoke when opening the plugin settings window to centralize and abstract dispatcher invocation logic.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Flow.Launcher/ViewModel/MainViewModel.cs (1)

2144-2168: ⚠️ Potential issue | 🟠 Major

Use native Dispatcher.Invoke instead of DispatcherHelper.Invoke to preserve Render priority scheduling for DWM cloak operations.

DispatcherHelper.Invoke executes the action inline when CheckAccess() is true, bypassing the priority queue entirely. Native Dispatcher.Invoke(..., DispatcherPriority.Render) queues the work at Render priority even on the UI thread, respecting the dispatch pipeline. For DWM cloak/uncloak and UpdateLayout() calls, this timing difference can reintroduce the flicker and visibility glitches the code guards against. Replace with direct Dispatcher.Invoke or extend DispatcherHelper with a force-dispatch parameter.

Applies to both locations: lines 2144–2168 and 2226–2247.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Flow.Launcher/ViewModel/MainViewModel.cs` around lines 2144 - 2168, The
current use of DispatcherHelper.Invoke in MainViewModel allows inline execution
when CheckAccess() is true and bypasses the Dispatcher priority queue, which can
break Render-priority timing for DWMSetCloakForWindow and related UI updates;
replace those calls with the native Dispatcher.Invoke(...,
DispatcherPriority.Render) (e.g., Application.Current?.Dispatcher.Invoke(action,
DispatcherPriority.Render)) in both places where DispatcherHelper.Invoke is used
so the work is queued at Render priority even on the UI thread, or alternatively
modify DispatcherHelper.Invoke to accept a “force dispatch” flag and call
Dispatcher.Invoke when true; ensure you update both the block that calls
Win32Helper.DWMSetCloakForWindow and the symmetric second occurrence in
MainViewModel so DWM cloak/uncloak and layout updates run at Render priority.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@Flow.Launcher/ViewModel/MainViewModel.cs`:
- Around line 2144-2168: The current use of DispatcherHelper.Invoke in
MainViewModel allows inline execution when CheckAccess() is true and bypasses
the Dispatcher priority queue, which can break Render-priority timing for
DWMSetCloakForWindow and related UI updates; replace those calls with the native
Dispatcher.Invoke(..., DispatcherPriority.Render) (e.g.,
Application.Current?.Dispatcher.Invoke(action, DispatcherPriority.Render)) in
both places where DispatcherHelper.Invoke is used so the work is queued at
Render priority even on the UI thread, or alternatively modify
DispatcherHelper.Invoke to accept a “force dispatch” flag and call
Dispatcher.Invoke when true; ensure you update both the block that calls
Win32Helper.DWMSetCloakForWindow and the symmetric second occurrence in
MainViewModel so DWM cloak/uncloak and layout updates run at Render priority.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b1f29370-138b-4195-8caa-4ea1db730cdd

📥 Commits

Reviewing files that changed from the base of the PR and between 95fc3eb and d23129f.

📒 Files selected for processing (4)
  • Flow.Launcher.Core/Resource/Theme.cs
  • Flow.Launcher/PublicAPIInstance.cs
  • Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs
  • Flow.Launcher/ViewModel/MainViewModel.cs
🚧 Files skipped from review as they are similar to previous changes (2)
  • Flow.Launcher/PublicAPIInstance.cs
  • Flow.Launcher.Core/Resource/Theme.cs

@coderabbitai coderabbitai bot removed the enhancement New feature or request label Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants