Skip to content

Fluent Window #3271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 119 commits into from
Mar 20, 2025
Merged

Fluent Window #3271

merged 119 commits into from
Mar 20, 2025

Conversation

onesounds
Copy link
Contributor

@onesounds onesounds commented Feb 24, 2025

What's the PR

Details

  • Blur-enabled themes allow users to select mica/arcrylic effect.
  • Changed translucency effects to work only since Windows 11
    • It no longer works on Windows 10.
  • The themes that do not use the blur method render shadows and borders in the same way as before. (Legacy)
    • This method is retained for cases where user want to remove the shadow.
  • There are two types of translucency effects: light/dark. The skin designer can set two background colors to match, or set it to work with one.
  • Window border curve effect has changed to three different types.
  • Changed shadow effects to be handled using DWM for win10 and above, and legacy for below.
  • Added properties for handling background colors and borders. Removed the existing windowborderstyle-related properties to make them obsolete. Blur theme can't use Corner radius.

Todo List

  • Add relevant properties to themes.
    • Corner
    • LightBG, DarkBG,
    • BGmode : auto, light, dark.
  • Remove old DWM codes.
  • Adjust animation effect for blur-themes.
  • Remove hide delay.
  • Fix Blink situation when Startup
  • Remove Comment & Code simplification
  • OS conditional rendering (windows 10)
  • Fix Clock Animation when non typing and startup
  • Add None/Mica/Acrylic option
  • Check Sys plugin theme change codes.
  • Use PInvoke to replace DllImport.
  • Update docs

Test Cases

  • works well with empty last query mode
  • Blur effects should not be available on Windows 10, and the blur theme should behave the same as the non-blur theme.
  • If the hidestartup setting is enabled, the window should not be displayed on the first launch.
  • When changing the theme, the preview should be displayed correctly.
  • There should be no color issues when switching between themes.
  • When changing the colorscheme, it should adapt properly to the selected theme.
  • There should be no errors when loading a legacy theme.
  • Check if BUG: FL Open with Flickering & Constant CPU usage even when doing nothing #3319 is resolved.

This comment has been minimized.

Copy link

gitstream-cm bot commented Feb 24, 2025

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

Copy link
Contributor

coderabbitai bot commented Feb 24, 2025

📝 Walkthrough

Walkthrough

The pull request introduces enhancements to the Theme class and related components, focusing on theme management and visual effects. New asynchronous methods are added for changing themes, applying blur effects, and refreshing UI elements. The Win32Helper class is updated with methods for managing window attributes, including support for Mica and dark mode. Theme resources are modified across various XAML files to support new properties and improve visual consistency. Additionally, UI responsiveness is enhanced through updates to the MainWindow and view models.

Changes

Files Change Summary
Flow.Launcher.Core/Resource/Theme.cs Added properties and methods for theme management, including CurrentTheme, BlurEnabled, ChangeTheme, LoadAvailableThemes, RefreshFrameAsync, and SetBlurForWindowAsync.
Flow.Launcher.Infrastructure/Win32Helper.cs Introduced methods for window management: IsBackdropSupported, DWMSetCloakForWindow, DWMSetBackdropForWindow, DWMSetDarkModeForWindow, and DWMSetCornerPreferenceForWindow.
Flow.Launcher/MainWindow.xaml Reintroduced SourceInitialized event handler and made minor formatting adjustments.
Flow.Launcher/MainWindow.xaml.cs Updated _settings and _viewModel to readonly, modified OnLoaded to be asynchronous, added event handlers for UI visibility, and introduced new methods for style properties and animation handling.
Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs Added properties for backdrop and drop shadow management, updated SelectedTheme setter logic, and introduced a new BackdropType property.
Flow.Launcher/Themes/BlurBlack.xaml Removed ThemeBlurEnabled, added SystemBG, LightBG, and DarkBG resources, and modified SearchIconStyle dimensions.
Flow.Launcher/Themes/Win11Light.xaml Updated HasBlur to True, added ThemeBlurEnabled, SystemBG, LightBG, and DarkBG resources.
Flow.Launcher/ViewModel/MainViewModel.cs Modified Hide and Show methods for improved UI visibility handling and responsiveness.
Flow.Launcher.Infrastructure/NativeMethods.txt Added entries for DwmSetWindowAttribute, DWM_SYSTEMBACKDROP_TYPE, and DWM_WINDOW_CORNER_PREFERENCE.
Flow.Launcher.Infrastructure/UserSettings/Settings.cs Added BackdropType property and BackdropTypes enum.
Flow.Launcher/Languages/en.xaml Added string resources related to backdrop types.
Flow.Launcher/Resources/Dark.xaml Updated color values for several UI elements to enhance transparency.
Flow.Launcher/Resources/Light.xaml Modified color values for various UI elements to achieve a consistent visual design.
Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml Updated property bindings for color scheme selection and restructured UI components.
Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs Removed unused directive and deleted an unused method.
Flow.Launcher/Themes/Base.xaml Added PreviewWindowBorderStyle, modified BasePendingLineStyle, and removed visibility triggers from BaseClockPanel.
Flow.Launcher/Themes/BlurBlack Darker.xaml Added resources and modified SearchIconStyle dimensions.
Flow.Launcher/Themes/BlurWhite.xaml Introduced new resources, updated styles, and modified existing properties for visual refinement.
Flow.Launcher/Themes/Circle System.xaml Enabled blur effects and updated several color resources.
Flow.Launcher/Themes/Darker.xaml Updated WindowBorderStyle background and modified SeparatorStyle syntax.
Flow.Launcher/Themes/Pink.xaml Significant updates to visual styles and properties of UI elements.
Flow.Launcher/Themes/Ubuntu.xaml Modified padding and margin properties to a space-separated format and simplified background property.
Flow.Launcher/Themes/Win10System.xaml Added new resources and modified existing styles for text elements.
Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs Changed SelectedTheme property to public and updated its setter logic for theme management.

Assessment against linked issues

Objective Addressed Explanation
Ensure blur effect respects window corners for rounded themes. (#2387)
Enable Mica support in the Win11System theme. (#2658)

Possibly related PRs

  • Add Flow Launcher Theme Selector to Sys plugin #2448: The changes in the main PR, particularly in the Theme class, are directly related to the modifications in the ThemeSelector class from the retrieved PR, as both involve theme management and selection functionalities.
  • Fix main window resize border thickness issue #3232: The changes in the main PR regarding the Theme class's management of themes and the introduction of asynchronous operations are related to the modifications in the retrieved PR, which also involves updates to the Theme class, specifically in handling the drop shadow effect and window resizing.

Suggested reviewers

  • onesounds
  • taooceros

Poem

I'm a hopping rabbit in a digital warren,
Blurring windows with style and grace,
Themes transform like a gentle spring rain,
Each code hop brings a brighter interface,
Bugs vanish as my ASCII ears cheer,
🐇 Onward we hop, in a pixel race!

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
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: 0

🧹 Nitpick comments (4)
Flow.Launcher.Infrastructure/Win32Helper.cs (1)

24-31: Consider adding error handling for DWM API calls.

The SetMicaForWindow method should handle potential DWM API failures:

 public static void SetMicaForWindow(Window window, bool enableMica)
 {
     var windowHelper = new WindowInteropHelper(window);
     windowHelper.EnsureHandle();

     DwmSystemBackdropType backdropType = enableMica ? DwmSystemBackdropType.DWMSBT_MICA : DwmSystemBackdropType.DWMSBT_NONE;
-    DwmSetWindowAttribute(windowHelper.Handle, DWMWA_SYSTEMBACKDROP_TYPE, ref backdropType, sizeof(int));
+    var result = DwmSetWindowAttribute(windowHelper.Handle, DWMWA_SYSTEMBACKDROP_TYPE, ref backdropType, sizeof(int));
+    if (result != 0)
+    {
+        Log.Error($"Failed to set window backdrop type. Error code: {result}");
+    }
 }
Flow.Launcher/ViewModel/MainViewModel.cs (1)

412-413: Translate Korean comments to English.

The comment "텍스트 초기화 즉시 적용" should be in English for consistency.

-// 텍스트 초기화 즉시 적용
+// Immediately apply text initialization
Flow.Launcher.Core/Resource/Theme.cs (2)

230-246: Remove commented-out code.

The BGColor method is commented out and should be removed if no longer needed.

-//public SolidColorBrush BGColor(string colorBgKey)
-//{
-//    var defaultBG = Application.Current.TryFindResource("DefaultBG");
-//    var darkBG = Application.Current.TryFindResource("DarkBG");
-//
-//    if (colorBgKey == "")
-//    {
-//        var resource = Application.Current.TryFindResource("BlurMode");
-//
-//        if (resource is string)
-//            return (SolidColorBrush)resource;
-//
-//        return new SolidColorBrush(Colors.DarkGray);
-//    }
-//
-//    return null;
-//}

139-169: Consider adding version check for Windows 11 features.

The SetBlurForWindow method should verify Windows version before using Windows 11-specific features.

 public void SetBlurForWindow()
 {
+    // Check for Windows 11 (build 22000 or higher)
+    if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000))
+    {
+        Log.Debug("Skipping blur effect - requires Windows 11");
+        return;
+    }
+
     var dict = GetThemeResourceDictionary(Settings.Theme);
     if (dict == null)
         return;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3573580 and db5036a.

📒 Files selected for processing (8)
  • Flow.Launcher.Core/Resource/Theme.cs (3 hunks)
  • Flow.Launcher.Infrastructure/Win32Helper.cs (1 hunks)
  • Flow.Launcher/MainWindow.xaml (2 hunks)
  • Flow.Launcher/MainWindow.xaml.cs (2 hunks)
  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs (1 hunks)
  • Flow.Launcher/Themes/BlurBlack.xaml (1 hunks)
  • Flow.Launcher/Themes/Win11Light.xaml (2 hunks)
  • Flow.Launcher/ViewModel/MainViewModel.cs (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: gitStream.cm
🔇 Additional comments (14)
Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs (2)

46-68: LGTM! Good handling of shadow effects.

The property correctly prevents combining drop shadow with blur effects, which could cause visual artifacts. The user feedback through message box is appropriate.


40-42:

❓ Verification inconclusive

LGTM! Verify theme changes are applied correctly.

The addition of ThemeManager.Instance.RefreshFrame() ensures window effects are updated when themes change. This is essential for the new blur and translucency features.

Run this script to verify theme changes are handled correctly:


🏁 Script executed:

#!/bin/bash
# Description: Check theme change handling in ThemeManager
ast-grep --pattern $'class ThemeManager {
  $$$
  public void ChangeTheme($_) {
    $$$
  }
  $$$
  public void RefreshFrame() {
    $$$
  }
  $$$
}'

Length of output: 150


LGTM! However, the automated ast-grep check didn't yield any output, so please manually verify that ThemeManager.Instance.RefreshFrame() correctly updates the window frame after theme changes (and hence applies the new blur/translucency effects).

Flow.Launcher/Themes/BlurBlack.xaml (1)

13-14: LGTM! Good implementation of blur mode.

The addition of BlurMode with "Auto" value allows for flexible blur effects while maintaining compatibility. This aligns well with the PR's objective of enhancing window translucency.

Flow.Launcher/Themes/Win11Light.xaml (1)

4-4: LGTM! Consistent blur implementation.

The changes properly enable blur effects for the Windows 11 light theme, maintaining consistency with other blur-enabled themes.

Also applies to: 15-16

Flow.Launcher/MainWindow.xaml.cs (2)

184-187: LGTM! Good use of async theme refresh.

The asynchronous theme frame refresh with background priority is a good practice for maintaining UI responsiveness while applying theme changes.


63-63:

❓ Verification inconclusive

Verify impact of removing paste handler.

The removal of the paste handler could affect how pasted content is processed in the QueryTextBox. Please ensure this doesn't impact user experience.

Run this script to check for other paste handling mechanisms:


🏁 Script executed:

#!/bin/bash
# Description: Check for paste handling in the codebase
rg -A 5 "OnPaste|DataObject.AddPastingHandler|Paste"

Length of output: 3901


Confirm Paste Handling Remains Intentional

The code in Flow.Launcher/MainWindow.xaml.cs still attaches the paste handler via

DataObject.AddPastingHandler(QueryTextBox, OnPaste);

and the corresponding OnPaste method is present. Please verify that this behavior is intentional and that paste operations continue to work as expected. If modifications to the paste handling logic were expected, please update the implementation accordingly.

Flow.Launcher/MainWindow.xaml (2)

18-19: LGTM! The window property changes enable DWM-based blur effects.

The changes to AllowsTransparency and Background are necessary for implementing DWM-based blur effects:

  • Setting AllowsTransparency="False" is required as DWM handles the transparency
  • The semi-transparent background color #E12E2E2E provides a good base for the blur effect

33-33: LGTM! The window initialization changes support proper window chrome.

The addition of SourceInitialized event handler and SingleBorderWindow style:

  • Enables proper initialization of DWM effects
  • Provides standard window chrome with proper borders

Also applies to: 37-37

Flow.Launcher.Infrastructure/Win32Helper.cs (2)

10-17: LGTM! Well-defined DWM backdrop type enumeration.

The DwmSystemBackdropType enum properly defines all available backdrop types for Windows 11, including Mica and Acrylic effects.


21-22: LGTM! Correct P/Invoke declaration for DWM API.

The DwmSetWindowAttribute P/Invoke declaration:

  • Uses correct parameter types
  • Properly imports from "dwmapi.dll"
Flow.Launcher/ViewModel/MainViewModel.cs (2)

412-417: LGTM! Improved responsiveness for empty query mode.

The immediate query text clearing with Task.Yield() ensures responsive UI updates.


419-436: LGTM! Simplified query mode handling.

The switch statement for LastQueryMode has been streamlined:

  • Removed unnecessary delay
  • Consolidated action keyword cases
  • Cleaner state management
Flow.Launcher.Core/Resource/Theme.cs (2)

71-77: LGTM! Well-structured DWM window attribute enumeration.

The DWMWINDOWATTRIBUTE enum properly defines the required attributes for window effects.


89-104: LGTM! Clean implementation of DWM API methods.

The Methods class provides a clean wrapper around DWM API calls with proper parameter handling.

This comment has been minimized.

Copy link
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: 0

🧹 Nitpick comments (2)
Flow.Launcher.Infrastructure/NativeMethods.txt (2)

19-20: Consistency Check for EnumWindows Entry

The EnumWindows entry is marked with a change (~) which suggests that a formatting (newline) adjustment may have been applied. Please verify that this formatting change is intentional and does not affect any downstream parsing or processing that depends on the file's structure.


21-22: Addition of Native Methods for Translucency Effects

The new entries DwmSetWindowAttribute and DWM_SYSTEMBACKDROP_TYPE have been added, which are essential for enabling the blur-enabled themes on Windows 11. Ensure that these native method names exactly match their usage in the corresponding implementation files (for example, in Theme.cs and Win32Helper.cs). Additionally, consider adding a brief comment or documentation reference here to indicate their role in the new translucency effects.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db5036a and 41b05b3.

📒 Files selected for processing (2)
  • Flow.Launcher.Infrastructure/NativeMethods.txt (1 hunks)
  • Flow.Launcher.Infrastructure/Win32Helper.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Flow.Launcher.Infrastructure/Win32Helper.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: gitStream.cm

@Jack251970
Copy link
Contributor

It looks so nice on Windows 11.👍And I improve code quality for it with PInvoke. (But it seems that you did not use SetMicaForWindow function?)

@taooceros
Copy link
Member

I remember previously we have a lot of issue with fluent window? Things changed?

@onesounds onesounds marked this pull request as draft February 24, 2025 12:20

This comment has been minimized.

This comment has been minimized.

This comment has been minimized.

Copy link
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

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

1073-1204: 🛠️ Refactor suggestion

Consider isolating concurrency logic in QueryResultsAsync.
The method coordinates multiple asynchronous plugin queries with cancellation tokens and progress bar management. This is correct in principle but quite involved. Splitting the gathering, rendering, and cancellation segments may reduce complexity. You might wrap the token logic in a helper or aim for more granular tasks with ConfigureAwait(false).

🧹 Nitpick comments (6)
Flow.Launcher/MainWindow.xaml.cs (5)

34-59: Ensure clarity on new private fields initialization.
The addition of read-only fields for _settings, _theme, _viewModel, and other resources is consistent with dependency injection and code style. However, double-check that each field’s lifecycle aligns with the application’s lifetime. If any field might need reinitialization or disposal later, relaxing read-only or adding explicit teardown may be necessary.


85-92: Validate window procedure hook usage.
Connecting WndProc in OnSourceInitialized is a valid approach for advanced resizing or alt-tab–hiding logic. Ensure that the hook is removed or accounted for on window re-creation or disposal if the application flow changes in the future.


250-272: Beware of potential flicker in OnDeactivated.
Using await Task.Delay(100) before hiding the window can introduce flicker if quickly activated-deactivated. You might prefer a more robust approach (like setting a flag to throttle frequent calls).


740-857: Consider extracting WindowAnimation logic into a separate utility or behavior.
With numerous storyboards and animations, the method is growing large. Moving animation logic into its own class or behavior could simplify maintenance and testing, and allow more customizing of transitions.


859-937: Manage race conditions for concurrent ClockPanel fade in/out.
The fade logic relies on _isClockPanelAnimating to prevent overlap. Rapid updates to ContextMenu.Visibility or typed characters could theoretically introduce race conditions if asynchronous tasks overlap. You can keep using the _isClockPanelAnimating flag, but you may also consider Storyboard completion callbacks or a specialized animation library to finalize transitions safely.

Would you like assistance refining this fade logic to handle quick consecutive events more gracefully?

Flow.Launcher/ViewModel/MainViewModel.cs (1)

1269-1306: Minor readability improvement for topmost logic.
ContextMenuTopMost toggles topmost on or off, with separate AddOrUpdate or Remove calls. If you have more topmost states or conditions in the future, consider a single “toggleTopMost(Result)” method for clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 711865d and bfa7622.

📒 Files selected for processing (3)
  • Flow.Launcher/MainWindow.xaml.cs (9 hunks)
  • Flow.Launcher/SettingWindow.xaml.cs (3 hunks)
  • Flow.Launcher/ViewModel/MainViewModel.cs (19 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Flow.Launcher/SettingWindow.xaml.cs
🔇 Additional comments (6)
Flow.Launcher/MainWindow.xaml.cs (4)

63-77: Constructor DI looks good.
Switching to IoC-based construction is typically beneficial for testability and maintainability. Good job ensuring fields _settings, _theme, and _viewModel are all injected. Please verify that exceptions are handled if the services are unavailable.


229-237: [Duplicate] Potential resource leak in OnClosing.
This reproduces a previously raised concern. Bypassing normal close with Environment.Exit(0) may lead to leaked resources and incomplete cleanup.


1011-1014: PreviewDragOver event looks fine.
Explicitly marking e.Handled = true prevents dropping onto the QueryTextBox. This is consistent with disallowing invalid drag-and-drop.


94-227:

✅ Verification successful

Unsubscribe or manage event handlers in OnLoaded for safety.
The code eagerly subscribes to multiple property descriptors (ContextMenu, History) and sets up QueryTextBox.TextChanged. If the window could be reloaded, consider unsubscribing or using a short-lived scope to prevent potential memory leaks or repeated event calls.

Would you like to verify that OnLoaded is called only once per app lifetime? If not, unsubscribing is advisable. You can confirm by searching for subsequent calls of InitializeComponent() or navigation events:


🏁 Script executed:

#!/bin/bash
# Searching for additional calls to InitializeComponent or OnLoaded
rg -A 5 "InitializeComponent|OnLoaded"

Length of output: 28780


MainWindow OnLoaded is triggered only once at startup.
Our search confirms that the MainWindow’s Loaded event is set only in MainWindow.xaml (via Loaded="OnLoaded") and that there are no subsequent triggers (e.g., from navigation or re-calling InitializeComponent()) that would cause OnLoaded to execute again. Given that the event subscriptions (such as those on _viewModel, _settings, and UI element changes) are registered only once, the current setup does not risk multiple registrations or memory leaks under normal circumstances. If you are confident that the MainWindow will not be unloaded and reloaded during the app’s lifetime, then it is safe to leave the subscriptions as-is.

Flow.Launcher/ViewModel/MainViewModel.cs (2)

243-251: ReloadPluginDataAsync notification approach is acceptable.
Using Notification.Show(...) to give feedback aligns well with a user-friendly experience. The method also properly hides the main view, reloading data, and then notifies success. No immediate concerns here.


386-394:

❓ Verification inconclusive

Verify concurrency in OpenResultAsync.
The method awaits an ExecuteAsync(...) call that might do I/O or plugin logic. Ensure the UI remains responsive and consider try-catch for plugin exceptions. Also verify that multiple calls to OpenResultAsync won't introduce race conditions if the user quickly selects multiple results.


🏁 Script executed:

#!/bin/bash
# Searching for all references to OpenResultAsync to see if multiple calls are triggered quickly:
rg -A 5 "OpenResultAsync"

Length of output: 488


Action Required: Review Concurrency and Exception Handling in OpenResultAsync

Please verify the following in the Flow.Launcher/ViewModel/MainViewModel.cs file (around the current asynchronous snippet):

  • UI Responsiveness: The asynchronous call to result.ExecuteAsync(...) is awaited with .ConfigureAwait(false), which prevents resuming on the UI thread. Confirm that this behavior is intentional and that any subsequent UI updates are marshaled back correctly.
  • Exception Handling: There is no try-catch block around the ExecuteAsync call. Consider wrapping the call in a try-catch to gracefully handle any I/O or plugin-related exceptions.
  • Race Conditions: Since OpenResultAsync can be triggered rapidly (as seen with the check for a non-null index), ensure that multiple concurrent calls do not lead to unsafe modifications of shared state (for example, updating results.SelectedIndex without proper synchronization).

Please review these areas to ensure that rapid, consecutive invocations don’t introduce race conditions or unhandled exceptions that could impact the UI stability.

@fiso64
Copy link

fiso64 commented Mar 17, 2025

Getting the following exception in version 1.19.5.10163 when opening the Hotkeys section in the settings window:

Flow Launcher version: 1.19.5
OS Version: 19044.5487
IntPtr Length: 8
x64: True

Python Path: C:\Users\fiso\AppData\Local\Programs\Python\Python311\pythonw.exe
Node Path: 

Date: 03/17/2025 14:01:04
Exception:
System.Windows.Markup.XamlParseException: The invocation of the constructor on type 'Flow.Launcher.HotkeyControl' that matches the specified binding constraints threw an exception.
 ---> System.NotImplementedException: Hotkey type not set
   at Flow.Launcher.HotkeyControl.get_Hotkey() in C:\projects\flow-launcher\Flow.Launcher\HotkeyControl.xaml.cs:line 146
   at Flow.Launcher.HotkeyControl..ctor() in C:\projects\flow-launcher\Flow.Launcher\HotkeyControl.xaml.cs:line 217
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   --- End of inner exception stack trace ---
   at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at Flow.Launcher.SettingPages.Views.SettingsPaneHotkey.InitializeComponent() in C:\projects\flow-launcher\Flow.Launcher\SettingPages\Views\SettingsPaneHotkey.xaml:line 1
   at Flow.Launcher.SettingPages.Views.SettingsPaneHotkey.OnNavigatedTo(NavigationEventArgs e) in C:\projects\flow-launcher\Flow.Launcher\SettingPages\Views\SettingsPaneHotkey.xaml.cs:line 19
   at ModernWpf.Controls.Page.InternalOnNavigatedTo(NavigationEventArgs e)
   at ModernWpf.Controls.Frame.OnNavigated(Object sender, NavigationEventArgs e)
   at System.Windows.Navigation.NavigationService.FireNavigated(Object navState)
   at System.Windows.Navigation.NavigationService.HandleNavigated(Object navState, Boolean navigatedToNewContent)
   at System.Windows.Navigation.NavigationService.DoNavigate(Object bp, NavigationMode navFlags, Object navState)
   at System.Windows.Navigation.NavigateQueueItem.Dispatch(Object obj)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Log: 2025-03-17.txt

@Jack251970
Copy link
Contributor

Jack251970 commented Mar 17, 2025

Getting the following exception in version 1.19.5.10163 when opening the Hotkeys section in the settings window:

Flow Launcher version: 1.19.5
OS Version: 19044.5487
IntPtr Length: 8
x64: True

Python Path: C:\Users\fiso\AppData\Local\Programs\Python\Python311\pythonw.exe
Node Path: 

Date: 03/17/2025 14:01:04
Exception:
System.Windows.Markup.XamlParseException: The invocation of the constructor on type 'Flow.Launcher.HotkeyControl' that matches the specified binding constraints threw an exception.
 ---> System.NotImplementedException: Hotkey type not set
   at Flow.Launcher.HotkeyControl.get_Hotkey() in C:\projects\flow-launcher\Flow.Launcher\HotkeyControl.xaml.cs:line 146
   at Flow.Launcher.HotkeyControl..ctor() in C:\projects\flow-launcher\Flow.Launcher\HotkeyControl.xaml.cs:line 217
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   --- End of inner exception stack trace ---
   at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at Flow.Launcher.SettingPages.Views.SettingsPaneHotkey.InitializeComponent() in C:\projects\flow-launcher\Flow.Launcher\SettingPages\Views\SettingsPaneHotkey.xaml:line 1
   at Flow.Launcher.SettingPages.Views.SettingsPaneHotkey.OnNavigatedTo(NavigationEventArgs e) in C:\projects\flow-launcher\Flow.Launcher\SettingPages\Views\SettingsPaneHotkey.xaml.cs:line 19
   at ModernWpf.Controls.Page.InternalOnNavigatedTo(NavigationEventArgs e)
   at ModernWpf.Controls.Frame.OnNavigated(Object sender, NavigationEventArgs e)
   at System.Windows.Navigation.NavigationService.FireNavigated(Object navState)
   at System.Windows.Navigation.NavigationService.HandleNavigated(Object navState, Boolean navigatedToNewContent)
   at System.Windows.Navigation.NavigationService.DoNavigate(Object bp, NavigationMode navFlags, Object navState)
   at System.Windows.Navigation.NavigateQueueItem.Dispatch(Object obj)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Log: 2025-03-17.txt

Many thanks for you report! This is already fixed in #3354 and #3357.

This comment has been minimized.

@Jack251970
Copy link
Contributor

Jack251970 commented Mar 17, 2025

@fiso64 You can download the installer from here once the continuous-integration is completed and this issue should be fixed in this version.🫡

image

This comment has been minimized.

This comment has been minimized.

This comment has been minimized.

Copy link
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: 0

♻️ Duplicate comments (1)
Flow.Launcher/MainWindow.xaml.cs (1)

229-237: ⚠️ Potential issue

Potential memory leak in application closing.

The OnClosing method cancels the close event and then forcefully exits the application using Environment.Exit(0). This approach bypasses normal cleanup routines, which might lead to resource leaks.

private async void OnClosing(object sender, CancelEventArgs e)
{
    _notifyIcon.Visible = false;
    App.API.SaveAppAllSettings();
-   e.Cancel = true;
    await PluginManager.DisposePluginsAsync();
    Notification.Uninstall();
-   Environment.Exit(0);
+   // Allow normal closing process to continue
}

Alternatively, if direct application termination is required:

private async void OnClosing(object sender, CancelEventArgs e)
{
+   // Cancel the event to handle cleanup properly
+   e.Cancel = true;
+   
    _notifyIcon.Visible = false;
    App.API.SaveAppAllSettings();
-   e.Cancel = true;
    await PluginManager.DisposePluginsAsync();
    Notification.Uninstall();
+   
+   // Use Application.Current.Shutdown() instead of Environment.Exit
+   Application.Current.Shutdown();
-   Environment.Exit(0);
}
🧹 Nitpick comments (3)
Flow.Launcher/MainWindow.xaml.cs (3)

59-59: Translate non-English comments to English.

There's a Korean comment that should be translated to English for consistency and better collaboration with international contributors.

- private bool _isClockPanelAnimating = false; // 애니메이션 실행 중인지 여부
+ private bool _isClockPanelAnimating = false; // Indicates whether animation is in progress

848-852: Consider extracting condition to a well-named method.

The clock visibility condition check is well-structured but could be extracted into a separate method for improved readability and maintainability.

+ private bool ShouldShowClock()
+ {
+     return QueryTextBox.Text.Length == 0 &&
+            ContextMenu.Visibility != Visibility.Visible &&
+            History.Visibility != Visibility.Visible;
+ }

private void UpdateClockPanelVisibility()
{
    // ...

-   bool shouldShowClock = QueryTextBox.Text.Length == 0 &&
-       ContextMenu.Visibility != Visibility.Visible &&
-       History.Visibility != Visibility.Visible;
+   bool shouldShowClock = ShouldShowClock();

    // ...
}

846-846: Extract magic number as a named constant.

The animation duration calculation uses a magic number that should be extracted as a named constant for better maintainability.

+ private const double FADE_ANIMATION_DURATION_FACTOR = 2.0 / 3.0;

private void UpdateClockPanelVisibility()
{
    // ...
-   var animationDuration = TimeSpan.FromMilliseconds(animationLength * 2 / 3);
+   var animationDuration = TimeSpan.FromMilliseconds(animationLength * FADE_ANIMATION_DURATION_FACTOR);
    // ...
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3322fc and 4731d88.

📒 Files selected for processing (1)
  • Flow.Launcher/MainWindow.xaml.cs (9 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
Flow.Launcher/MainWindow.xaml.cs (3)
Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1) (1)
  • Settings (16:391)
Flow.Launcher/ViewModel/MainViewModel.cs (10) (10)
  • MainViewModel (30:1566)
  • MainViewModel (56:173)
  • Show (1370:1391)
  • Hide (1395:1473)
  • ResetPreview (909:926)
  • Task (535:546)
  • Task (1073:1204)
  • SelectedIsFromQueryResults (1336:1340)
  • Result (1268:1306)
  • Result (1308:1334)
Flow.Launcher/SettingWindow.xaml.cs (4) (4)
  • OnLoaded (34:44)
  • WindowLeft (143:150)
  • WindowTop (152:159)
  • InitializePosition (110:126)
🔇 Additional comments (6)
Flow.Launcher/MainWindow.xaml.cs (6)

65-70: Nice improvement with dependency injection.

The constructor has been refactored to use proper dependency injection, with fields marked as readonly. This is a good practice that improves maintainability and testability.


94-139: Improved window initialization with async handling.

The OnLoaded method now properly uses async/await pattern to handle the frame refresh, which will prevent UI blocking during initialization. The method also better organizes the startup sequence with clearer conditional blocks.


740-831: Improved animation properties for better visual effects.

The animation configuration has been enhanced with appropriate FillBehavior.HoldEnd settings and better initialization of animation properties. The code now correctly uses styling information to determine visual elements' properties.


833-911: Well-implemented clock panel visibility management.

The new UpdateClockPanelVisibility method provides a robust way to control the clock panel's visibility based on multiple conditions. The implementation correctly uses animations for smooth transitions and properly handles edge cases.

However, consider replacing the direct Dispatcher invocation with a more efficient approach:

- Application.Current.Dispatcher.Invoke(() =>
+ Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
  {
      ClockPanel.Visibility = Visibility.Visible;
      // Other code...
      ClockPanel.BeginAnimation(OpacityProperty, fadeIn);
- }, DispatcherPriority.Render);
+ }));

913-943: Good utility methods for style property extraction.

The GetOpacityFromStyle and GetThicknessFromStyle methods are well-implemented utilities that safely extract values from styles with proper fallbacks. This prevents potential null reference issues and improves code robustness.


574-581: Method properly updated to return Task.

The PositionResetAsync method now correctly returns a Task, which is a better practice for async methods than using void returns. This change improves error handling and allows callers to await the operation.

This comment has been minimized.

Copy link
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: 0

♻️ Duplicate comments (2)
Flow.Launcher/ViewModel/MainViewModel.cs (1)

1393-1394: 🛠️ Refactor suggestion

Consider converting async void Hide() to async Task HideAsync().

Using async void can obscure exceptions and hamper chaining. Changing the signature to public async Task HideAsync() and adjusting call sites is recommended so callers can properly await or handle errors.

Apply the following diff as a starting point:

-public async void Hide()
+public async Task HideAsync()
 {
     lastHistoryIndex = 1;

     if (ExternalPreviewVisible)
     {
         CloseExternalPreview();
     }
     // ... rest of method ...
 }
Flow.Launcher/MainWindow.xaml.cs (1)

229-237: ⚠️ Potential issue

Potential memory leak in application closing.

The OnClosing method cancels the close event and then forcefully exits the application using Environment.Exit(0). This approach bypasses normal cleanup routines, which might lead to resource leaks.

Consider allowing the normal window closing process:

private async void OnClosing(object sender, CancelEventArgs e)
{
    _notifyIcon.Visible = false;
    App.API.SaveAppAllSettings();
-   e.Cancel = true;
    await PluginManager.DisposePluginsAsync();
    Notification.Uninstall();
-   Environment.Exit(0);
+   // Allow normal closing process to continue
}

Or if direct application termination is required:

private async void OnClosing(object sender, CancelEventArgs e)
{
+   // Cancel the event to handle cleanup properly
+   e.Cancel = true;
+   
    _notifyIcon.Visible = false;
    App.API.SaveAppAllSettings();
-   e.Cancel = true;
    await PluginManager.DisposePluginsAsync();
    Notification.Uninstall();
+   
+   // Use Application.Current.Shutdown() instead of Environment.Exit
+   Application.Current.Shutdown();
-   Environment.Exit(0);
}
🧹 Nitpick comments (1)
Flow.Launcher/ViewModel/MainViewModel.cs (1)

1459-1459: Consider explaining the purpose of the delay.

The 50ms delay before updating window visibility properties isn't clearly explained. Consider adding a comment to clarify its purpose.

-await Task.Delay(50); 
+// Allow time for visual transitions to complete before changing window visibility
+await Task.Delay(50);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4731d88 and aaca0c0.

📒 Files selected for processing (2)
  • Flow.Launcher/MainWindow.xaml.cs (9 hunks)
  • Flow.Launcher/ViewModel/MainViewModel.cs (19 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
Flow.Launcher/MainWindow.xaml.cs (2)
Flow.Launcher/ViewModel/MainViewModel.cs (6) (6)
  • MainViewModel (30:1559)
  • MainViewModel (56:173)
  • Show (1370:1391)
  • Hide (1395:1465)
  • Task (535:546)
  • Task (1073:1204)
Flow.Launcher/WelcomeWindow.xaml.cs (2) (2)
  • WelcomeWindow (13:102)
  • WelcomeWindow (26:31)
Flow.Launcher/ViewModel/MainViewModel.cs (2)
Flow.Launcher/Msg.xaml.cs (1) (1)
  • Show (63:91)
Flow.Launcher/PublicAPIInstance.cs (8) (8)
  • Task (94:94)
  • Task (165:165)
  • Task (167:168)
  • Task (170:171)
  • Task (347:347)
  • GetTranslation (158:158)
  • ShowMsg (99:100)
  • ShowMsg (102:105)
🔇 Additional comments (42)
Flow.Launcher/ViewModel/MainViewModel.cs (25)

179-180: Improved error handling and task management.

The change to use TaskScheduler.Default for the continuation is a good practice that helps ensure tasks run on the thread pool, avoiding UI thread blocking.


182-182: Good refactoring to use async/await pattern.

Renaming updateAction to UpdateActionAsync follows the naming convention for asynchronous methods, improving code readability and maintainability.


210-211: Ensure consistent error handling approach.

This error handling code in continueAction logs the exception in release mode but re-schedules the same task without addressing the root cause, which could lead to repeated failures.

Consider implementing a more robust error recovery mechanism like retries with exponential backoff or a circuit breaker pattern:

Log.Error($"Error happen in task dealing with viewupdate for results. {t.Exception}");
-_resultsViewUpdateTask =
-    Task.Run(UpdateActionAsync).ContinueWith(continueAction, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
+// Implement retry with delay or circuit breaker
+_resultsViewUpdateTask = Task.Delay(TimeSpan.FromSeconds(5))
+    .ContinueWith(_ => Task.Run(UpdateActionAsync)
+        .ContinueWith(continueAction, CancellationToken.None, 
+            TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default));

249-250: Consider removing the translator comments.

The code now uses App.API.GetTranslation instead of the removed _translator field, making the code cleaner and more consistent.


267-273: Improved async method calls by using Task return types.

The change from calling QueryResults directly to awaiting QueryResultsAsync with discard operator allows for better error propagation and asynchronous operation.


279-279: Consistent use of async/await pattern.

The change from calling QueryResults directly to awaiting QueryResultsAsync with discard operator allows for better error propagation and asynchronous operation.


893-893: Method visibility adjusted appropriately.

Changing SwitchExternalPreview to static makes sense since it doesn't use any instance members, improving code clarity.


1070-1073: Improved method signature from void to Task.

Changing QueryResults to QueryResultsAsync with a Task return type allows for proper error propagation and better asynchronous operation chaining.


1093-1093: Consistent token usage.

Using _updateSource.Token consistently for cancellation improves code reliability and helps prevent race conditions.


1101-1101: Consistent cancellation token checking.

Using _updateSource.Token instead of a local variable makes the code more consistent and easier to maintain.


1131-1133: Improved cancellation handling.

The code now properly checks for cancellation after the delay, which is important for responsive UI and resource management.


1136-1143: Enhanced progress bar visibility logic.

The improvement in handling the progress bar visibility with proper cancellation token checking makes the UI more responsive.


1149-1149: Consistent async method naming.

Renaming QueryTask to QueryTaskAsync follows the naming convention for asynchronous methods, improving code readability.


1163-1164: Consistent cancellation token checking.

The code now properly checks for cancellation before proceeding, which is important for responsive UI and resource management.


1169-1169: Consistent cancellation token checking.

Using _updateSource.Token consistently throughout the code improves reliability and prevents race conditions.


1176-1176: Consistent async method naming.

Renaming QueryTask to QueryTaskAsync follows the naming convention for asynchronous methods, improving code readability.


1183-1183: Consistent token usage.

Using _updateSource.Token consistently for cancellation improves code reliability and helps prevent race conditions.


1185-1185: Proper cancellation token checking.

Using _updateSource.Token.ThrowIfCancellationRequested() is the correct way to handle cancellation in asynchronous operations.


1199-1199: Consistent token usage in TryWrite call.

Using _updateSource.Token consistently throughout the code improves reliability.


1371-1391: Improved window visibility management.

The Show method has been enhanced with better handling of DWM window cloak and UI element visibility, providing a smoother user experience.


1409-1418: Improved LastQueryMode handling.

The code now more directly handles the LastQueryMode.Empty case, with explicit UI updates and a frame delay to ensure changes take effect.


1420-1426: Simplified LastQueryMode logic.

Consolidating the logic for LastQueryMode.Preserved and LastQueryMode.Selected improves code readability and maintainability.


1437-1457: Enhanced window hiding with DWM cloaking.

The implementation of DWM cloaking for window visibility provides a more seamless user experience. The careful handling of UI element opacity and visibility states helps ensure smooth transitions.


1467-1468: Good use of pragma to suppress compiler warnings.

The pragmas to suppress compiler warnings are appropriately scoped and only applied where necessary.


1475-1475: Improved GameMode integration.

The code now properly considers GameModeStatus for hotkey ignoring, which enhances the user experience.

Flow.Launcher/MainWindow.xaml.cs (17)

35-37: Good use of dependency injection.

Converting to readonly fields and using dependency injection improves code maintainability and testability.


38-44: Improved code organization with clear comments.

The addition of comments that group related fields enhances code readability and maintainability.


67-69: Robust dependency injection implementation.

Using Ioc.Default.GetRequiredService ensures that required dependencies are properly injected and will throw appropriate exceptions if missing.


85-91: Proper window initialization.

The OnSourceInitialized handler correctly sets up window hooks and applies necessary window styles.


94-102: Improved first launch experience.

The code now properly handles the first launch scenario by setting _settings.FirstLaunch to false and displaying the welcome window.


105-114: Enhanced startup behavior.

The code now consistently handles window visibility based on the HideOnStartup setting, providing a better user experience.


135-136: Async theme refreshing.

Using await with the async RefreshFrameAsync method ensures that the operation completes before continuing, preventing race conditions.


150-173: Improved MainWindow visibility handling.

The code now properly manages the window's visual state including sound effects, position updates, and animations, enhancing the user experience.


215-226: Enhanced UI element visibility coordination.

Adding event handlers for TextChanged, ContextMenu visibility, and History visibility ensures consistent UI updates.


250-272: Improved window deactivation handling.

The code now properly saves window position and handles animations with appropriate delays, preventing UI flicker.


371-382: Good use of pragma directives.

The pragmas to suppress compiler warnings are appropriately scoped and only applied where necessary.


574-574: Improved method signature.

Changing PositionReset to PositionResetAsync with Task return type follows async naming conventions and allows for proper error handling.


740-831: Enhanced window animation.

The animation code now properly calculates opacity and margin values from styles, making the animations more consistent with the theme.


833-911: Well-implemented ClockPanel visibility management.

The UpdateClockPanelVisibility method implements smooth fade-in and fade-out animations based on application state, providing a better user experience.


914-928: Useful utility method for style properties.

The GetOpacityFromStyle method cleanly extracts opacity values from styles, improving code reusability and reducing duplication.


930-944: Useful utility method for thickness properties.

The GetThicknessFromStyle method cleanly extracts margin values from styles, improving code reusability and reducing duplication.


986-989: Proper drag handling.

Setting e.Handled = true in the drag event ensures that the textbox properly handles drag operations.

Copy link

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

❌ Errors Count
❌ check-file-path 1
❌ forbidden-pattern 25
⚠️ ignored-expect-variant 1
⚠️ non-alpha-in-dictionary 19

See ❌ Event descriptions for more information.

Forbidden patterns 🙅 (2)

In order to address this, you could change the content to not match the forbidden patterns (comments before forbidden patterns may help explain why they're forbidden), add patterns for acceptable instances, or adjust the forbidden patterns themselves.

These forbidden patterns matched content:

s.b. workaround(s)

\bwork[- ]arounds?\b

Reject duplicate words

\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Copy link
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: 0

♻️ Duplicate comments (1)
Flow.Launcher/MainWindow.xaml.cs (1)

230-238: ⚠️ Potential issue

Potential memory leak in application closing.

The OnClosing method cancels the close event and then forcefully exits the application using Environment.Exit(0). This approach bypasses normal cleanup routines, which might lead to resource leaks.

private async void OnClosing(object sender, CancelEventArgs e)
{
    _notifyIcon.Visible = false;
    App.API.SaveAppAllSettings();
-   e.Cancel = true;
    await PluginManager.DisposePluginsAsync();
    Notification.Uninstall();
-   Environment.Exit(0);
+   // Allow normal closing process to continue
}

Alternatively, if direct application termination is required:

private async void OnClosing(object sender, CancelEventArgs e)
{
+   // Cancel the event to handle cleanup properly
+   e.Cancel = true;
+   
    _notifyIcon.Visible = false;
    App.API.SaveAppAllSettings();
-   e.Cancel = true;
    await PluginManager.DisposePluginsAsync();
    Notification.Uninstall();
+   
+   // Use Application.Current.Shutdown() instead of Environment.Exit
+   Application.Current.Shutdown();
-   Environment.Exit(0);
}
🧹 Nitpick comments (6)
Flow.Launcher.Infrastructure/Win32Helper.cs (3)

65-87: Complete XML documentation needed for DWMSetCornerPreferenceForWindow.

The method has incomplete XML documentation. While the parameter descriptions are present, a method description is missing.

 /// <summary>
-/// 
+/// Sets the corner preference (roundness) for the specified window.
 /// </summary>
 /// <param name="window"></param>
 /// <param name="cornerType">DoNotRound, Round, RoundSmall, Default</param>
 /// <returns></returns>

281-296: Robust DPI conversion with fallback handling.

The method properly handles the case when no presentation source is available by creating a temporary HwndSource. Consider adding a comment explaining the fallback case.

 else
 {
+    // Create a temporary source when no presentation source is available
     using var src = new HwndSource(new HwndSourceParameters());
     matrix = src.CompositionTarget.TransformFromDevice;
 }

302-304: Consider using constants for all window message codes.

The code defines constants for WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE but not for other window messages that might be used elsewhere. Consider a more systematic approach to defining message constants.

Consider creating a separate internal class or enum for window messages to centralize these definitions:

public static class WindowMessages
{
    public const int WM_ENTERSIZEMOVE = (int)PInvoke.WM_ENTERSIZEMOVE;
    public const int WM_EXITSIZEMOVE = (int)PInvoke.WM_EXITSIZEMOVE;
    // Add other window messages as needed
}

This would make it easier to maintain and extend window message handling.

Flow.Launcher/MainWindow.xaml.cs (3)

59-59: Translate comment to English for code consistency.

There's a Korean comment that should be translated to English for better maintainability across international contributors.

-    private bool _isClockPanelAnimating = false; // 애니메이션 실행 중인지 여부
+    private bool _isClockPanelAnimating = false; // Whether animation is currently running

402-407: Consider using constants for shadow margin values.

The hardcoded shadow margin value (32) should be defined as a constant at the class level for better maintainability.

+    private const int ShadowMargin = 32;
...
-                        shadowMargin = 32;
+                        shadowMargin = ShadowMargin;

834-912: Well-structured clock panel visibility management with smooth animations.

The new UpdateClockPanelVisibility method effectively manages the clock panel's visibility state with fade animations. The code correctly handles various conditions and edge cases.

However, the booleans for visibility checks would benefit from better naming.

-    bool shouldShowClock = QueryTextBox.Text.Length == 0 &&
-                ContextMenu.Visibility != Visibility.Visible &&
-                History.Visibility != Visibility.Visible;
+    bool isQueryEmpty = QueryTextBox.Text.Length == 0;
+    bool isContextMenuHidden = ContextMenu.Visibility != Visibility.Visible;
+    bool isHistoryHidden = History.Visibility != Visibility.Visible;
+    bool shouldShowClock = isQueryEmpty && isContextMenuHidden && isHistoryHidden;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aaca0c0 and 944393c.

📒 Files selected for processing (3)
  • Flow.Launcher.Infrastructure/Win32Helper.cs (1 hunks)
  • Flow.Launcher/MainWindow.xaml.cs (9 hunks)
  • Flow.Launcher/ViewModel/MainViewModel.cs (22 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Flow.Launcher/ViewModel/MainViewModel.cs
🧰 Additional context used
🧬 Code Definitions (1)
Flow.Launcher/MainWindow.xaml.cs (4)
Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1) (1)
  • Settings (16-391)
Flow.Launcher/ViewModel/MainViewModel.cs (7) (7)
  • MainViewModel (30-1545)
  • MainViewModel (56-173)
  • Show (1356-1377)
  • Hide (1381-1452)
  • ResetPreview (895-912)
  • Result (1254-1292)
  • Result (1294-1320)
Flow.Launcher/SettingWindow.xaml.cs (4) (4)
  • OnLoaded (34-44)
  • WindowLeft (143-150)
  • WindowTop (152-159)
  • InitializePosition (110-126)
Flow.Launcher/App.xaml.cs (2) (2)
  • App (28-253)
  • App (35-88)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Report (PR)
🔇 Additional comments (24)
Flow.Launcher.Infrastructure/Win32Helper.cs (12)

19-24: Good implementation of OS version checking.

The method properly checks both the OS platform and build number to ensure compatibility with Windows 11 (build 22000+) for backdrop effects.


26-35: Effective use of PInvoke for window cloaking.

The implementation correctly uses unsafe code and marshal sizing for proper interop. The boolean parameter provides a clean API for toggling the cloak state.


37-52: Good implementation of backdrop management.

The method effectively converts the application-specific backdrop types to the appropriate DWM constants with a clean switch expression.


54-63: Proper implementation of dark mode toggle.

The implementation correctly converts the boolean parameter to the integer value expected by the Windows API.


93-102: Efficient implementation of wallpaper path retrieval.

The method efficiently uses stack allocation with stackalloc and MemoryMarshal to avoid unnecessary heap allocations while retrieving the wallpaper path.


108-121: Good window foreground management functions.

The overloaded methods provide flexibility for both Window objects and raw handles, which will improve code reusability.


131-141: Effective implementation of Alt+Tab hiding.

The method correctly manipulates window style flags to hide the window from Alt+Tab without affecting its normal visibility.


147-157: Proper implementation of Alt+Tab showing.

The implementation correctly removes the TOOLWINDOW style and adds the APPWINDOW style to ensure the window appears in Alt+Tab.


163-172: Good implementation of control box disabling.

The implementation properly modifies the window style to remove the system menu while keeping other style elements intact.


174-195: Improved error handling in window style methods.

Both methods properly check for PInvoke errors and throw exceptions with detailed error information when necessary.


201-268: Comprehensive fullscreen detection logic.

The implementation handles various edge cases for different window classes and performs proper bounds checking against monitor information. The code is well-structured with early returns for quick resolution of common cases.


309-317: Good implementation of window handle retrieval.

The method provides flexibility with the ensure parameter to optionally create a handle if one doesn't exist.

Flow.Launcher/MainWindow.xaml.cs (12)

34-43: Good improvement for code organization and dependency injection patterns.

The code has been restructured to use dependency injection and clearly organize fields by category. Making fields like _settings, _theme, and _viewModel readonly is a good practice that prevents accidental modification.


65-77: Good use of dependency injection for better testability and maintainability.

The constructor now properly uses dependency injection to obtain services, which is a significant improvement over direct instantiation. This approach makes the class more testable and decouples it from concrete implementations.


94-142: Async window loading with proper initialization sequence.

The OnLoaded event handler has been properly converted to async to support awaiting the theme refresh operation. The initialization sequence is well-structured, with clear comments indicating each step.


216-227: Good implementation of dynamic UI element visibility management.

Adding event handlers to monitor text changes and control visibility provides a more responsive user experience. The use of DependencyPropertyDescriptor for tracking visibility changes is an elegant approach.


251-273: Improved window deactivation handling with animation delay.

Adding a delay before hiding the window when deactivated prevents flickering and provides a smoother user experience. Using Task.Delay with an async method is the correct approach for this scenario.


575-582: Proper async method signature for PositionReset.

Changing PositionReset from async void to async Task is a good practice. This allows callers to await the completion of the method and handle exceptions properly.


915-929: Good utility method for extracting style properties.

The GetOpacityFromStyle method is a clean implementation that safely extracts style properties with fallback values.


931-945: Good utility method for extracting thickness from styles.

The GetThicknessFromStyle method follows the same pattern as GetOpacityFromStyle, providing a consistent approach to style property extraction.


783-795: Good use of new style property extraction methods.

The code now properly extracts opacity and thickness values from styles, making it more robust when dealing with different themes.


741-832: Enhanced window animation with proper property values.

The WindowAnimation method now properly manages animation properties including FillBehavior settings. Using the new utility methods to extract style properties makes the code more resilient to theme changes.


987-991: Prevent default drag behavior for better user experience.

Adding the PreviewDragOver handler ensures that the QueryTextBox handles drag operations consistently with the application's expected behavior.


694-739:

❓ Verification inconclusive

Verify the animation completion event handlers for potential memory leaks.

The InitProgressbarAnimation method creates animations and wires up event handlers but doesn't handle cleanup. This could potentially lead to memory leaks if the window is recreated multiple times without removing old event handlers.


🏁 Script executed:

#!/bin/bash
# Look for other event handler cleanup in the codebase
rg -A 5 -B 5 "\.Completed \+=" --type cs

Length of output: 3158


Action: Confirm Proper Cleanup of ProgressBar Animation Resources

After reviewing the code, no explicit Completed event handlers are wired up in the InitProgressbarAnimation method. Instead, the animation is set up using style triggers with a BeginStoryboard/StopStoryboard mechanism, and the animations are frozen with da.Freeze() and da1.Freeze(). This pattern is in line with similar animations elsewhere in the code (e.g., fade-in/fade-out animations in other parts of the file) where explicit cleanup isn’t needed.

However, please verify that the storyboard’s registered name (i.e., "ProgressBarAnimation", registered via progressStyle.RegisterName) is either unregistered or managed appropriately when the ProgressBar control or its container is disposed. This precaution will ensure that if the window is recreated multiple times, no stale references remain causing memory retention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request kind/ui related to UI, icons, themes, etc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The theme , Win11System, can't support mica. BUG: Theme blur exceeds window with rounded corners.
5 participants