Avalonia migration#4214
Conversation
Create Flow.Launcher.Avalonia project as foundation for migrating from WPF to Avalonia UI framework. Key components: - MainWindow with query box and results list (matching WPF layout) - ViewModels: MainViewModel, ResultsViewModel, ResultViewModel - Themes/Base.axaml with converted styles from WPF - FluentAvaloniaUI for Windows 11 styling - References existing Core/Infrastructure/Plugin projects The project builds and runs alongside the existing WPF application. This is Phase 1 of the incremental migration approach.
- Load settings from disk via FlowLauncherJsonStorage - Initialize PluginManager and query plugins on text change - Add minimal AvaloniaPublicAPI implementing IPublicAPI - Execute plugin results on Enter key - Add WPF framework reference for IPublicAPI compatibility
…oading - Use DynamicData SourceList with automatic sorting by score descending - Add ReplaceResults() with EditDiff for minimal UI updates (reduces flickering) - Keep previous results visible while typing until new results arrive - Add ImageLoader with Windows Shell API (IShellItemImageFactory) for exe/ico icons - Use AlphaFormat.Unpremul to correctly render transparent icons without white borders - Query all plugins in parallel and merge/sort results globally
- Wrap each plugin query in Task.Run() to ensure synchronous plugin code doesn't block the UI thread - Show results progressively as each plugin completes using ConcurrentBag - Update UI after each plugin returns instead of waiting for all plugins
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Avalonia UI frontend for Flow Launcher as an alternative to the existing WPF implementation. The migration adds a complete new project with UI components, ViewModels, and platform integration while maintaining compatibility with the existing plugin system.
Changes:
- Adds new
Flow.Launcher.Avaloniaproject with complete UI implementation including MainWindow, result list views, and styling - Implements Windows global hotkey support and image loading utilities with native Win32 interop
- Adds console logging output to infrastructure logger for easier debugging
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 50 comments.
Show a summary per file
| File | Description |
|---|---|
| Flow.Launcher.sln | Adds Flow.Launcher.Avalonia project to solution with build configurations |
| Flow.Launcher.Infrastructure/Logger/Log.cs | Adds console output for log messages |
| Flow.Launcher.Avalonia/app.manifest | Defines Windows compatibility and DPI awareness settings |
| Flow.Launcher.Avalonia/Views/ResultListBox.axaml | XAML markup for search results list display |
| Flow.Launcher.Avalonia/Views/ResultListBox.axaml.cs | Code-behind for result list interactions |
| Flow.Launcher.Avalonia/ViewModel/ResultsViewModel.cs | ViewModel managing result collection with sorting and selection |
| Flow.Launcher.Avalonia/ViewModel/ResultViewModel.cs | ViewModel for individual result items |
| Flow.Launcher.Avalonia/ViewModel/MainViewModel.cs | Main application ViewModel coordinating queries and UI state |
| Flow.Launcher.Avalonia/Themes/Resources.axaml | Color and resource definitions for UI theme |
| Flow.Launcher.Avalonia/Themes/Base.axaml | Style definitions for UI components |
| Flow.Launcher.Avalonia/Program.cs | Application entry point |
| Flow.Launcher.Avalonia/MainWindow.axaml | Main window XAML markup |
| Flow.Launcher.Avalonia/MainWindow.axaml.cs | Main window code-behind with event handling |
| Flow.Launcher.Avalonia/Helper/ImageLoader.cs | Image loading utility with caching and Win32 shell integration |
| Flow.Launcher.Avalonia/Helper/HotKeyMapper.cs | Global hotkey registration management |
| Flow.Launcher.Avalonia/Helper/GlobalHotkey.cs | Win32-based global hotkey implementation |
| Flow.Launcher.Avalonia/Flow.Launcher.Avalonia.csproj | Project configuration and dependencies |
| Flow.Launcher.Avalonia/Converters/CommonConverters.cs | Value converters for data binding |
| Flow.Launcher.Avalonia/Converters/BoolToIsVisibleConverter.cs | Boolean to visibility converter |
| Flow.Launcher.Avalonia/AvaloniaPublicAPI.cs | IPublicAPI implementation for plugin compatibility |
| Flow.Launcher.Avalonia/App.axaml | Application XAML with theme configuration |
| Flow.Launcher.Avalonia/App.axaml.cs | Application code-behind with initialization logic |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add ActiveView enum to track Results vs ContextMenu view state - Add ContextMenu ResultsViewModel and view switching logic - Implement LoadContextMenuCommand using PluginManager.GetContextMenusForPlugin - Add keyboard navigation: Shift+Enter/Right to open, Left/Escape to close - Update SelectNextItem/SelectPrevItem to navigate appropriate list - Update EscCommand to return from context menu before hiding
- Create Internationalization service that parses WPF XAML language files - Load translations from main Languages/ folder and all plugin Languages/ folders - Add LocalizeExtension markup extension and Translator helper for XAML/code - Fix IPublicAPI.GetTranslation to use the i18n service for plugin context menus - Update MainWindow to use localized placeholder text
This comment has been minimized.
This comment has been minimized.
- Internationalization.Initialize() called in constructor when DI creates it - Remove InitializeInternationalization() method from App.axaml.cs - Update AvaloniaPublicAPI and LocalizeExtension to use Ioc.Default.GetService - Reorder ConfigureDI before i18n initialization
This comment has been minimized.
This comment has been minimized.
|
Is there any actual benefit to switching to Avalonia or it's just for testing purposes? |
There should be some performance improvement for animation. Besides, I also want to have the chance to make flow cross platform as I am gradually migrating my workflow to mac. |
- MainWindowVisibility starts as false (window hidden) - Window IsVisible bound to MainWindowVisibility - Set MainWindowVisibility = true in OnPluginsReady() after plugins load
This comment has been minimized.
This comment has been minimized.
- Add Glyph and GlyphAvailable properties to ResultViewModel - Set Glyph from plugin Result when creating result items - Add resultGlyph style matching icon size (32x32) - Update ResultListBox to show glyph or image icon based on ShowGlyph property - ShowGlyph = true when UseGlyphIcons is enabled AND glyph is available
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@check-spelling-bot Report🔴 Please reviewSee the 📂 files view, the 📜action log, or 📝 job summary for details.
See ❌ Event descriptions for more information. Forbidden patterns 🙅 (1)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. preexistingIf the flagged items are 🤯 false positivesIf items relate to a ...
|
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Split repository guidance by domain so contributors can find module-specific rules without duplicating repo-wide conventions.
|
@taooceros could you list us what's left to do in this PR please. |
|
I will get a summary soon. |
Bring the Avalonia host closer to WPF parity by wiring the missing settings dialogs, selectors, and public API flows. Also fix the async JSON save path and settings DI so direct-launch validation can get past the earlier runtime failures. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Track the requested local agent metadata in the repo and add a minimal OpenCode project config for editor/schema support. Keep the old .gemini workspace out of the repository state. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Move the new WPF-inspired palette into shared Avalonia theme resources so the main shell can pull consistent brushes and borders from one place. This keeps later styling polish tied to a single resource layer instead of scattered hex values. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Apply the shared theme brushes to the live result list and the theme settings preview so the settings sample matches the actual search window. This makes the new palette visible in the places users judge the UI most quickly. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Replace the rigid footer button rows on the About page with flexible wrapping so longer labels do not clip or disappear. This keeps the action layout stable across different widths and localized text lengths. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Mark the completed dialogs, settings work, and runtime wiring so the migration plan matches the current Avalonia host state. This keeps the remaining work list focused on the gaps that still matter instead of already-finished items. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
GSD-Unit: Q1
There was a problem hiding this comment.
15 issues found across 291 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed. cubic prioritises the most important files to review.
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.Avalonia/Views/SettingPages/ThemeSettingsPage.axaml">
<violation number="1" location="Flow.Launcher.Avalonia/Views/SettingPages/ThemeSettingsPage.axaml:13">
P3: Avoid hardcoding font sizes in XAML; rely on default or shared styles so theme/accessibility updates apply consistently.
(Based on your team's feedback about relying on default UI styles and font sizes.) [FEEDBACK_USED]</violation>
</file>
<file name="Flow.Launcher.Avalonia/Views/SettingPages/HotkeySettingsPage.axaml">
<violation number="1" location="Flow.Launcher.Avalonia/Views/SettingPages/HotkeySettingsPage.axaml:14">
P2: Avoid hardcoding FontSize in XAML; use the default/shared style so global theming and accessibility scaling stay consistent.
(Based on your team's feedback about relying on default UI styles and font sizes.) [FEEDBACK_USED]</violation>
<violation number="2" location="Flow.Launcher.Avalonia/Views/SettingPages/HotkeySettingsPage.axaml:24">
P3: Avoid hardcoding FontSize in XAML; use default/shared styles for consistent appearance across themes.
(Based on your team's feedback about relying on default UI styles and font sizes.) [FEEDBACK_USED]</violation>
</file>
<file name="Flow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml">
<violation number="1" location="Flow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml:17">
P3: Avoid hardcoded `FontSize` here and rely on default/shared text styles for consistent theming and accessibility.
(Based on your team's feedback about relying on default UI styles and avoiding hardcoded font sizes.) [FEEDBACK_USED]</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| WindowStartupLocation="CenterScreen"> | ||
|
|
||
| <Grid RowDefinitions="Auto,Auto,*,Auto" Margin="20"> | ||
| <TextBlock FontSize="20" |
There was a problem hiding this comment.
P3: Avoid hardcoded FontSize here and rely on default/shared text styles for consistent theming and accessibility.
(Based on your team's feedback about relying on default UI styles and avoiding hardcoded font sizes.)
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Flow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml, line 17:
<comment>Avoid hardcoded `FontSize` here and rely on default/shared text styles for consistent theming and accessibility.
(Based on your team's feedback about relying on default UI styles and avoiding hardcoded font sizes.) </comment>
<file context>
@@ -0,0 +1,41 @@
+ WindowStartupLocation="CenterScreen">
+
+ <Grid RowDefinitions="Auto,Auto,*,Auto" Margin="20">
+ <TextBlock FontSize="20"
+ FontWeight="SemiBold"
+ Text="{Binding TitleText}" />
</file context>
There was a problem hiding this comment.
Actionable comments posted: 19
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
♻️ Duplicate comments (2)
Flow.Launcher.Avalonia/App.axaml.cs (1)
142-150:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAttach storage to the fallback
Settingsinstance too.The failure path still creates
_settingswithoutSetStorage, so later saves run against an unconfigured settings object.Suggested fix
catch (Exception e) { Log.Exception(ClassName, "Settings load failed", e); - _settings = new Settings + var storage = new FlowLauncherJsonStorage<Settings>(); + _settings = new Settings { WindowSize = 580, WindowHeightSize = 42, QueryBoxFontSize = 24, ItemHeightSize = 50, ResultItemFontSize = 14, ResultSubItemFontSize = 12, MaxResultsToShow = 6 }; + _settings.SetStorage(storage); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/App.axaml.cs` around lines 142 - 150, The fallback Settings instance created in the catch block is missing its storage attachment, so call SetStorage on the newly created _settings (the same storage used for the normal settings path) before assigning/using it; update the catch to create the Settings object and then invoke _settings.SetStorage(...) with the existing settings storage instance (the same storage reference used elsewhere when loading/saving settings), ensuring the fallback has storage configured.Flow.Launcher.Avalonia/MainWindow.axaml (1)
68-75:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMake the search icon overlay non-hit-testable.
This overlay sits on top of the query box, so clicks on the icon area can stop focusing the
TextBox.Suggested fix
- <Canvas Name="SearchIconCanvas" - Classes="searchIconPosition" - HorizontalAlignment="Right"> + <Canvas Name="SearchIconCanvas" + Classes="searchIconPosition" + HorizontalAlignment="Right" + IsHitTestVisible="False">In Avalonia UI, does an overlaid Canvas receive pointer events by default, and does setting `IsHitTestVisible="False"` allow clicks to pass through to the TextBox underneath?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/MainWindow.axaml` around lines 68 - 75, The overlaid SearchIconCanvas is intercepting pointer events and preventing the underlying TextBox from receiving focus; make the overlay non-hit-testable by setting IsHitTestVisible="False" (on SearchIconCanvas or on the inner SearchIcon Path) so pointer events pass through to the TextBox beneath, ensuring clicks still focus the input while preserving the visual overlay.
🟡 Minor comments (22)
Flow.Launcher.Avalonia/Views/Dialogs/NotificationWindow.axaml.cs-87-94 (1)
87-94:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winHandle icon-load failures explicitly to avoid silent task faults.
LoadIconAsyncis fire-and-forget and currently has no local exception handling. A bad/corrupt image path can fault the task without structured logging.Suggested fix
private async System.Threading.Tasks.Task LoadIconAsync(string iconPath) { - var resolvedPath = File.Exists(iconPath) - ? iconPath - : Path.Combine(Constant.ProgramDirectory, "Images", "app.png"); - - NotificationIcon = await ImageLoader.LoadAsync(resolvedPath); + try + { + var resolvedPath = File.Exists(iconPath) + ? iconPath + : Path.Combine(Constant.ProgramDirectory, "Images", "app.png"); + + NotificationIcon = await ImageLoader.LoadAsync(resolvedPath); + } + catch (Exception ex) + { + Log.Exception(nameof(NotificationWindow), "Failed to load notification icon", ex); + NotificationIcon = null; + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/Dialogs/NotificationWindow.axaml.cs` around lines 87 - 94, LoadIconAsync currently awaits ImageLoader.LoadAsync but has no exception handling, causing silent task faults; wrap the ImageLoader.LoadAsync(resolvedPath) call in a try/catch inside LoadIconAsync (catch Exception) and on failure set a safe fallback for NotificationIcon and log the exception (include resolvedPath and the exception) using the existing logging mechanism so failures are visible and the UI remains stable.AGENTS.md-5-16 (1)
5-16:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRoot AGENTS table needs MD058 spacing fix.
Add blank lines around the
WHERE TO LOOKtable block.Suggested patch
## WHERE TO LOOK + | Task | Location | Notes | |------|----------|-------| | WPF app behavior | `Flow.Launcher/` | Main host, windows, settings shell, WPF-only UI rules | | Avalonia app behavior | `Flow.Launcher.Avalonia/` | Avalonia host, WPF compatibility shim, migrated settings pages | | Plugin lifecycle | `Flow.Launcher.Core/` | `PluginManager`, plugin loading, updates, manifest integration | | Shared infra | `Flow.Launcher.Infrastructure/` | settings, storage, hotkeys, logging, fuzzy matching | | Plugin SDK contract | `Flow.Launcher.Plugin/` | interfaces/models consumed by built-in and external plugins | | Built-in plugins | `Plugins/` | 12 plugin projects, shared `Main.cs` + `plugin.json` structure | | Test project | `Flow.Launcher.Test/` | NUnit 4 tests; some Explorer tests need Windows Search | | CI / release process | `.github/` | workflow automation, release PRs, plugin publishing, issue templates | + ## CHILD AGENTS🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@AGENTS.md` around lines 5 - 16, The WHERE TO LOOK table in AGENTS.md violates MD058 (missing blank lines around a block table); edit AGENTS.md and add a blank line immediately before the "## WHERE TO LOOK" heading block and another blank line immediately after the table (after the final | CI / release process | `.github/` ... | row) so the table is separated from surrounding text, ensuring proper Markdown spacing for the "WHERE TO LOOK" table block.Flow.Launcher.Infrastructure/AGENTS.md-5-14 (1)
5-14:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd blank lines around the table (MD058).
markdownlintexpects a blank line before and after this table block.Suggested patch
## WHERE TO LOOK + | Task | Location | Notes | |------|----------|-------| | User settings | `UserSettings/` | `Settings`, `DataLocation`, app/user data roots | | Storage | `Storage/` | JSON/binary persistence, backup/atomic write behavior | | Search matching | `StringMatcher.cs`, related models | fuzzy/acronym/pinyin behavior | | Logging | `Logger/` | NLog wrapper and diagnostics | | Hotkeys | `Hotkey/` | low-level keyboard integration | | Windows helpers | helper/system wrappers | Win32 and shell integration | + ## LOCAL RULES🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Infrastructure/AGENTS.md` around lines 5 - 14, The Markdown table under the "## WHERE TO LOOK" heading needs blank lines before and after it to satisfy markdownlint rule MD058; edit the AGENTS.md content so there is an empty line between the "## WHERE TO LOOK" heading and the table start, and another empty line after the table end (i.e., ensure a blank line before the first | of the table and one after the final | row) to resolve the lint warning..github/AGENTS.md-5-15 (1)
5-15:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winLint fix needed: blank lines around table (MD058).
Please add a blank line before and after this table.
Suggested patch
## WHERE TO LOOK + | Task | Location | Notes | |------|----------|-------| | CI build and artifacts | `.github/workflows/dotnet.yml` | build/test pipeline, WSearch service, artifact publishing | | Release deploy | `.github/workflows/release_deploy.yml` | website + Chocolatey dispatches, secret-driven | | Release PR body automation | `.github/workflows/release_pr.yml`, `.github/update_release_pr.py` | expects one open release PR and milestone grouping | | Built-in plugin publishing | `.github/workflows/default_plugins.yml` | publishes plugin repos, updates plugin metadata | | Issue/PR automation | `.github/workflows/pr_*.yml`, `stale.yml`, `spelling.yml` | author assignment, milestone, stale, spelling | | Dependency policy | `.github/dependabot.yml` | daily cadence, PR caps, ignored packages | | Intake rules | `.github/ISSUE_TEMPLATE/` | bug report required fields, feature request, code review template | + ## LOCAL RULES🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/AGENTS.md around lines 5 - 15, Add a blank line before and after the Markdown table under the "WHERE TO LOOK" heading so the table is separated from surrounding text (fixes MD058); locate the "WHERE TO LOOK" header and the following table block (the lines starting with "## WHERE TO LOOK" and the table rows like "| Task | Location | Notes |") and insert one empty line immediately above the "## WHERE TO LOOK" table block if not present and one empty line immediately after the table end.Plugins/AGENTS.md-11-18 (1)
11-18:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winResolve markdownlint MD058 for the
WHERE TO LOOKtable.Insert blank lines around this table block.
Suggested patch
## WHERE TO LOOK + | Task | Location | Notes | |------|----------|-------| | Entry/query logic | each plugin `Main.cs` | sync vs async behavior lives here | | Manifest | each plugin `plugin.json` | metadata, action keyword(s), icon, execute file | | Settings model | `Settings.cs` or equivalent | usually loaded through API storage helpers | | Plugin UI/settings | plugin views/viewmodels if present | some have WPF + Avalonia settings paths | + ## LOCAL RULES🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Plugins/AGENTS.md` around lines 11 - 18, The MD058 lint violation is caused by the table not being separated by blank lines; update the Plugins/AGENTS.md by adding a blank line after the "## WHERE TO LOOK" heading and another blank line after the table block (the lines starting with "| Task | Location | Notes |" through the table row with "Plugin UI/settings | plugin views/viewmodels if present | ...") so the table is isolated with an empty line above and below to satisfy markdownlint.Flow.Launcher.Core/AGENTS.md-5-14 (1)
5-14:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix markdownlint MD058 around the table.
Add blank lines before/after the
WHERE TO LOOKtable to satisfy markdownlint.Suggested patch
## WHERE TO LOOK + | Task | Location | Notes | |------|----------|-------| | Plugin lifecycle | `Plugin/PluginManager.cs` | discovery, load, init, query fanout | | Plugin manifest parsing | `Plugin/PluginConfig.cs` | scans `plugin.json`, duplicate/version filtering | | Loader implementation | `Plugin/PluginsLoader.cs` | .NET + external plugin loading | | Community plugins | `ExternalPlugins/` | manifest/store integration | | Updates | updater-related files | Squirrel + release logic | | Resources/i18n | `Resource/`, related services | host/plugin resource merging | + ## LOCAL RULES🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Core/AGENTS.md` around lines 5 - 14, Add a blank line immediately before the "## WHERE TO LOOK" heading/table and another blank line immediately after the table to satisfy markdownlint MD058; edit the AGENTS.md section containing the table that lists Plugin/PluginManager.cs, Plugin/PluginConfig.cs, Plugin/PluginsLoader.cs, ExternalPlugins/, updater-related files, and Resource/ so the table is separated by empty lines above and below.Flow.Launcher.Plugin/AGENTS.md-5-12 (1)
5-12:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTable spacing violates MD058.
Please add blank lines before and after this table.
Suggested patch
## WHERE TO LOOK + | Task | Location | Notes | |------|----------|-------| | Core plugin interfaces | `Interfaces/` | `IPlugin`, `IAsyncPlugin`, capability interfaces | | Public models | root models, `SharedModels/` | `Result`, `Query`, metadata, settings-facing types | | Shared commands/helpers | `SharedCommands/` | reusable SDK-side pieces | | Docs | `README.md` | package/plugin authoring baseline | + ## LOCAL RULES🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Plugin/AGENTS.md` around lines 5 - 12, The Markdown table under the "## WHERE TO LOOK" heading violates MD058 by lacking blank lines around the table; fix it by inserting a single blank line immediately after the "## WHERE TO LOOK" heading and another blank line immediately after the table block (the pipe-delimited rows shown in the diff) so there is one empty line before and after the table.Flow.Launcher/AGENTS.md-5-13 (1)
5-13:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winSurround the “WHERE TO LOOK” table with blank lines.
Line 6 currently triggers markdownlint
MD058. Add a blank line before and after the table block.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher/AGENTS.md` around lines 5 - 13, The "WHERE TO LOOK" markdown table in AGENTS.md triggers MD058 because it is not surrounded by blank lines; update the file to insert a blank line immediately before the "## WHERE TO LOOK" header/table block and another blank line immediately after the table so the table is separated from surrounding content and satisfies markdownlint; target the table block shown (the header "## WHERE TO LOOK" and its pipe-delimited rows) when making the change.Flow.Launcher.Avalonia/AGENTS.md-5-13 (1)
5-13:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd blank lines around the table block.
Line 6 starts a table immediately after a heading, which triggers markdownlint (
MD058). Add one blank line before and after this table for clean rendering/lint pass.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/AGENTS.md` around lines 5 - 13, Add a blank line before and a blank line after the markdown table that starts with the heading "## WHERE TO LOOK" and the pipe-delimited table (the | Task | Location | Notes | ... block) so the table is separated from surrounding content and satisfies MD058; edit the AGENTS.md section containing that table to insert one empty line above the table and one empty line below it.AVALONIA_MIGRATION_CHECKLIST.md-347-384 (1)
347-384:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winInsert blank lines before table blocks in Core Features subsections.
At Line 348/362/372/381, tables start immediately after subsection titles and trigger
MD058. Add a blank line before each table.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@AVALONIA_MIGRATION_CHECKLIST.md` around lines 347 - 384, The markdown linter MD058 is triggered because tables in the "Search & Results", "Window Management", and "System Integration" subsections start immediately after their subsection titles; add a single blank line before each table to separate the heading and the table (i.e., insert a blank line before the table that begins under the "Search & Results" header, the table under "Window Management", and the table under "System Integration") so each subsection title is followed by a blank line then the table.AVALONIA_MIGRATION_CHECKLIST.md-458-528 (1)
458-528:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd language identifiers to fenced code blocks.
The blocks at Line 458 and Line 481 have no language (
MD040). Usetext(orbashwhere appropriate).Suggested patch
-``` +```text Flow.Launcher/ ...-
+text
Flow.Launcher.Avalonia/
...🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@AVALONIA_MIGRATION_CHECKLIST.md` around lines 458 - 528, Update the two fenced code blocks that list the project trees so they include a language identifier; specifically, change the triple-backtick fence before the block starting with "Flow.Launcher/" and the one before the block starting with "Flow.Launcher.Avalonia/" to use ```text (or ```bash for shell-style listing) instead of bare ``` so the MD040 lint warning is resolved.AVALONIA_MIGRATION_CHECKLIST.md-56-166 (1)
56-166:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix single-cell “section header” rows inside 3-column tables.
Rows like Line 58 (
| **Startup Section** |) break table column count (MD056). Keep 3 cells for those separator rows.Suggested patch pattern
-| **Startup Section** | +| **Startup Section** | | | ... -| **Behavior Section** | +| **Behavior Section** | | |🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@AVALONIA_MIGRATION_CHECKLIST.md` around lines 56 - 166, The table contains single-cell section header rows (e.g., "**Startup Section**", "**Behavior Section**", "**Position Section**", etc.) that break the 3-column table structure and trigger MD056; update each of those separator rows so they contain three pipe-separated cells (for example add two empty cells or placeholder text) to maintain the "| col1 | col2 | col3 |" format throughout the file (search for rows starting with "| **" and ensure they become three-cell rows).Flow.Launcher.Avalonia/Views/SettingPages/CustomQueryHotkeyWindow.axaml.cs-81-118 (1)
81-118:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winLocalize the validation messages too.
This dialog already routes button text through
Translate(...), but the error title/messages are still hard-coded English. That leaves part of the settings flow untranslated on non-English installs.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/SettingPages/CustomQueryHotkeyWindow.axaml.cs` around lines 81 - 118, The validation dialog strings in OnDoneClick are hard-coded; update the calls that pass "Custom Query Hotkey", "Both the hotkey and query text are required.", and "That hotkey is already assigned to another custom query." to use the app localization method (Translate) before calling ShowMessageAsync, and modify ShowMessageAsync to accept already-localized title/content or call Translate for any non-localized inputs; reference the OnDoneClick method and ShowMessageAsync to locate and change the message parameters so all dialog title and content use Translate(...) like the CloseButtonText does.Flow.Launcher.Avalonia/Views/Dialogs/PluginUpdateWindow.axaml-40-53 (1)
40-53:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMove the remaining labels through i18n resources.
Restart after updating pluginsandCancelare still hard-coded here, so this dialog won't fully localize with the rest of the Avalonia host.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/Dialogs/PluginUpdateWindow.axaml` around lines 40 - 53, Replace the two hard-coded UI strings with bindings to the i18n resource keys so the dialog localizes; specifically change the CheckBox Content ("Restart after updating plugins") to use the localization resource (e.g., a resource key like RestartAfterUpdatingPlugins) and change the Cancel Button Content ("Cancel") to use the Cancel resource key, keeping the existing bindings/properties (Restart, UpdateButtonText) and event handlers (OnCancelClick, OnUpdateClick) intact so only the Content attributes are switched to resource-based bindings or StaticResource/Loc markup extensions that the project uses for localization.Flow.Launcher.Avalonia/Views/SettingPages/CustomShortcutWindow.axaml.cs-80-100 (1)
80-100:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTrim the shortcut key before validating and saving it.
Right now
"foo"and" foo "are treated as different values, so_doesShortcutExist(...)can be bypassed and the saved shortcut key may not expand the way the user expects.Suggested change
private async void OnDoneClick(object? sender, RoutedEventArgs e) { - if (string.IsNullOrWhiteSpace(ShortcutKey) || string.IsNullOrWhiteSpace(ShortcutValue)) + var normalizedShortcutKey = ShortcutKey.Trim(); + + if (string.IsNullOrWhiteSpace(normalizedShortcutKey) || string.IsNullOrWhiteSpace(ShortcutValue)) { await ShowMessageAsync("Custom Shortcut", "Both the shortcut and expansion text are required."); return; } - if (((_update && _originalShortcutKey != ShortcutKey) || !_update) && _doesShortcutExist(ShortcutKey)) + if (((_update && _originalShortcutKey != normalizedShortcutKey) || !_update) && + _doesShortcutExist(normalizedShortcutKey)) { await ShowMessageAsync("Custom Shortcut", "That shortcut key already exists."); return; } - if (_update && _originalShortcutKey == ShortcutKey && _originalShortcutValue == ShortcutValue) + if (_update && _originalShortcutKey == normalizedShortcutKey && _originalShortcutValue == ShortcutValue) { Close(false); return; } + ShortcutKey = normalizedShortcutKey; Close(true); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/SettingPages/CustomShortcutWindow.axaml.cs` around lines 80 - 100, In OnDoneClick, normalize the ShortcutKey by trimming whitespace before any validation, existence checks, or comparison with _originalShortcutKey/_originalShortcutValue so leading/trailing spaces don't bypass _doesShortcutExist or create mismatched saved keys; i.e., compute a trimmedKey = ShortcutKey?.Trim(), use trimmedKey for the Null/WhiteSpace check, pass trimmedKey into _doesShortcutExist(trimmedKey), compare trimmedKey to _originalShortcutKey when determining no-op updates, and ensure the value used when saving/closing is the trimmed key.Flow.Launcher.Avalonia/ViewModel/MainViewModel.cs-290-295 (1)
290-295:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
LoadHistory()runs the same history query twice.After
QueryText = string.Empty;,OnQueryTextChanged()already invokesQueryAsync(). The extra_ = QueryAsync();immediately below repeats the history load every time this view opens.Suggested change
if (ActiveView == ActiveView.Results) { _queryTextBeforeHistory = QueryText; ActiveView = ActiveView.History; QueryText = string.Empty; - _ = QueryAsync(); if (HistoryView.Results.Count > 0) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/ViewModel/MainViewModel.cs` around lines 290 - 295, The history load is triggered twice because setting QueryText = string.Empty fires OnQueryTextChanged which already calls QueryAsync(), so remove the redundant explicit call to QueryAsync(); in the MainViewModel method that switches views (the block referencing ActiveView, _queryTextBeforeHistory, QueryText and calling QueryAsync()), delete the line "_ = QueryAsync();" so QueryAsync is only invoked via OnQueryTextChanged when QueryText is set to empty.Flow.Launcher.Avalonia/Views/SettingPages/GeneralSettingsPage.axaml-80-100 (1)
80-100:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMove the new search-window labels into localization resources.
Custom screen,Custom position, andSet X and Y when alignment is Customare user-facing English strings in an otherwise localized page. These should usei18n:Localizekeys like the rest of the settings UI.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/SettingPages/GeneralSettingsPage.axaml` around lines 80 - 100, Replace the hardcoded English strings in the SettingsExpanderItem elements with i18n:Localize resource keys: change Content="Custom screen" to Content="{i18n:Localize CustomScreen}" (or your chosen key), Content="Custom position" to Content="{i18n:Localize CustomPosition}", and Description="Set X and Y when alignment is Custom" to Description="{i18n:Localize CustomPositionDescription}"; add corresponding keys to the localization resource file so SearchWindowAlign and other localized entries remain consistent and bind to UI:SettingsExpanderItem and its Footer ComboBox elements unchanged.Flow.Launcher.Avalonia/Views/SettingPages/AboutSettingsPage.axaml-44-46 (1)
44-46:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winLocalize the new section descriptions.
These descriptions are hardcoded English while the rest of the page is localized, so this page will regress into a mixed-language UI for non-English users. Please move them into the i18n resources as well.
Also applies to: 58-60, 72-74
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/SettingPages/AboutSettingsPage.axaml` around lines 44 - 46, The Description attributes in AboutSettingsPage.axaml's SettingsExpander elements (e.g., the one with Header="{i18n:Localize website}" and IconSource="World") are hardcoded English; replace those literal Description strings with i18n resource lookups (use i18n:Localize or the existing localization markup) and add corresponding keys to the i18n resource files; do the same for the other two expanders referenced (the elements around lines 58-60 and 72-74) so all Header and Description text is pulled from localization keys rather than hardcoded English.Flow.Launcher.Avalonia/Views/Dialogs/WelcomeWindow.axaml-50-53 (1)
50-53:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winSwap these Page 3 labels or hotkeys.
HotkeyUpDownDescis currently shown next to left/right arrows, andHotkeyLeftRightDescis shown next to up/down arrows. The onboarding text is backwards.Suggested fix
- <TextBlock Grid.Row="0" Margin="0,0,0,10" Text="{i18n:Localize HotkeyUpDownDesc}" /> + <TextBlock Grid.Row="0" Margin="0,0,0,10" Text="{i18n:Localize HotkeyLeftRightDesc}" /> <controls:HotkeyDisplay Grid.Row="0" Grid.Column="1" Keys="←+→" /> - <TextBlock Grid.Row="1" Margin="0,0,0,10" Text="{i18n:Localize HotkeyLeftRightDesc}" /> + <TextBlock Grid.Row="1" Margin="0,0,0,10" Text="{i18n:Localize HotkeyUpDownDesc}" /> <controls:HotkeyDisplay Grid.Row="1" Grid.Column="1" Keys="↑+↓" />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/Dialogs/WelcomeWindow.axaml` around lines 50 - 53, The two Page 3 items are swapped: the TextBlock using i18n:Localize HotkeyUpDownDesc is paired with Keys="←+→" and HotkeyLeftRightDesc is paired with Keys="↑+↓"; swap them so HotkeyUpDownDesc is paired with Keys="↑+↓" and HotkeyLeftRightDesc is paired with Keys="←+→". Locate the two controls: the TextBlock elements referencing HotkeyUpDownDesc and HotkeyLeftRightDesc and the adjacent controls:HotkeyDisplay elements with Keys="←+→" and Keys="↑+↓", and swap the Keys values or swap the TextBlock positions so each description matches the corresponding HotkeyDisplay.Flow.Launcher.Avalonia/Views/SettingPages/HotkeySettingsPage.axaml-102-114 (1)
102-114:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDifferentiate the fixed
Shift+Enterrow from the editable context-menu hotkey.Both rows render the same label, so users can’t tell which one they can change and which one is hard-coded.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/SettingPages/HotkeySettingsPage.axaml` around lines 102 - 114, The two SettingsExpanderItem rows use the same Content/localization key so users can’t tell the editable hotkey (HotkeyControl bound to OpenContextMenuHotkey) from the fixed one (HotkeyDisplay Keys="Shift+Enter"); update the second SettingsExpanderItem to use a different label (e.g., a new localization key like OpenContextMenuHotkey_Fixed or append "(fixed)" to the content) or a distinct visual cue so the fixed Shift+Enter row is clearly labeled as non-editable while leaving the HotkeyControl row unchanged.Flow.Launcher.Avalonia/Views/SettingPages/ThemeSettingsPage.axaml-28-40 (1)
28-40:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winLocalize the remaining hard-coded labels on this page.
This still exposes English-only UI (
Hello there,Theme resources,Sizing and fonts,Theme Builder,Warning, etc.), so the page bypasses the app’s i18n path in visible settings content.Also applies to: 88-93, 116-116, 201-205, 296-299
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/SettingPages/ThemeSettingsPage.axaml` around lines 28 - 40, Replace all hard-coded TextBlock/Text content on ThemeSettingsPage.axaml (e.g., the Text attributes "Hello there", "Sample result title", "Sample result subtitle" and visible headings like "Theme resources", "Sizing and fonts", "Theme Builder", "Warning") with localized resource lookups or bindings to the app's i18n keys (use the same pattern used elsewhere in the project such as StaticResource/x:Static or a LocalizationManager binding). Create or use descriptive resource keys (e.g., ThemeSettings_Hello, ThemeSettings_ResultTitle, ThemeSettings_ResultSubtitle, ThemeSettings_ThemeResources, ThemeSettings_SizingAndFonts, ThemeSettings_ThemeBuilder, ThemeSettings_Warning) and replace the literal strings with those resource references so the page follows the app’s localization path.Flow.Launcher.Avalonia/ViewModel/SettingPages/GeneralSettingsViewModel.cs-75-86 (1)
75-86:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winHistory-style labels won't refresh after a language switch.
UpdateLabels()mutatesHistoryStyleOption.Display, butHistoryStyleOptiondoes not raise property changes and the view model never re-raisesHistoryStyles/SelectedHistoryStyle. This dropdown will keep the old language until the page is recreated.Also applies to: 407-423, 809-829
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/ViewModel/SettingPages/GeneralSettingsViewModel.cs` around lines 75 - 86, UpdateLabels currently mutates HistoryStyleOption.Display but the UI doesn't refresh because HistoryStyleOption doesn't raise PropertyChanged and the VM doesn't re-raise HistoryStyles/SelectedHistoryStyle; fix by making HistoryStyleOption raise INotifyPropertyChanged for its Display (implement PropertyChanged in UpdateLabel) and/or after calling HistoryStyles.ForEach(x => x.UpdateLabel(_i18n)) call the view model's RaisePropertyChanged(nameof(HistoryStyles)) and RaisePropertyChanged(nameof(SelectedHistoryStyle)) so the dropdown updates when UpdateLabels() runs.
🧹 Nitpick comments (4)
Flow.Launcher.Avalonia/Views/Dialogs/NotificationWindow.axaml.cs (1)
17-18: 🏗️ Heavy liftUse CommunityToolkit MVVM primitives instead of manual code-behind state/handlers.
This dialog currently mixes manual
INotifyPropertyChangedand click handlers in the view class; please move bindable state/commands to anObservableObjectview model and bind commands from AXAML.As per coding guidelines:
Flow.Launcher.Avalonia/**/*.cs: Avalonia UI code should use CommunityToolkit.Mvvm patterns such asObservableObject,[ObservableProperty],[RelayCommand].Also applies to: 48-57, 123-153
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/Dialogs/NotificationWindow.axaml.cs` around lines 17 - 18, The NotificationWindow class currently implements INotifyPropertyChanged and contains click handlers; create a NotificationViewModel that inherits CommunityToolkit.Mvvm.ComponentModel.ObservableObject, convert window state fields to [ObservableProperty]s and handlers to [RelayCommand] methods, then set NotificationWindow.DataContext to an instance of that view model and remove the manual INotifyPropertyChanged implementation and code-behind click handlers from NotificationWindow; update AXAML to bind buttons and properties to the view model commands/properties instead of using code-behind.Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj (1)
68-68: Add explicit separator in OutputPath glob for consistency across all plugins.While MSBuild's normalization makes the current pattern
$(OutputPath)**\*.*work correctly and deterministically, adding an explicit backslash makes the glob pattern clearer:$(OutputPath)\**\*.*. Apply this consistently across all plugin projects where this pattern is used.Files affected
All 12 plugin csproj files use this pattern:
- Flow.Launcher.Plugin.Explorer (line 68)
- Flow.Launcher.Plugin.WindowsSettings (line 78)
- Flow.Launcher.Plugin.Sys (line 75)
- Flow.Launcher.Plugin.Program (line 84)
- Flow.Launcher.Plugin.ProcessKiller (line 78)
- Flow.Launcher.Plugin.WebSearch (line 72)
- Flow.Launcher.Plugin.Url (line 70)
- Flow.Launcher.Plugin.PluginIndicator (line 69)
- Flow.Launcher.Plugin.PluginsManager (line 51)
- Flow.Launcher.Plugin.Shell (line 74)
- Flow.Launcher.Plugin.BrowserBookmark (line 125)
- Flow.Launcher.Plugin.Calculator (line 78)
Proposed fix
- <PluginFiles Include="$(OutputPath)**\*.*" /> + <PluginFiles Include="$(OutputPath)\**\*.*" />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj` at line 68, Update the PluginFiles Include pattern to explicitly add a directory separator after $(OutputPath) so the glob is unambiguous: change the attribute value from "$(OutputPath)**\*.*" to "$(OutputPath)\**\*.*" in this csproj (look for the PluginFiles Include entry and the OutputPath pattern), and apply the same edit to the other plugin csproj files listed to ensure consistency across all plugins.Flow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml (1)
1-14: ⚡ Quick winReorder root AXAML attributes to match repo convention.
x:Classis currently placed after severalxmlns/design attributes; please reorder the root attributes to follow the project’s prescribed order for consistent formatting.As per coding guidelines:
**/*.{xaml,axaml}: In XAML/AXAML attribute order: x:Class → xmlns → key/name → layout → size → margin/padding → rest.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml` around lines 1 - 14, Reorder the root Window attributes in ProgressBoxWindow.axaml so x:Class is the first attribute (x:Class="Flow.Launcher.Avalonia.Views.Dialogs.ProgressBoxWindow"), followed by the xmlns declarations, then key/name attributes, layout attributes, size attributes (Width/Height), margin/padding, and then the remaining attributes (e.g., CanResize, WindowStartupLocation); update the Window tag for the ProgressBoxWindow XAML to follow the project's prescribed attribute ordering convention.Flow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml.cs (1)
11-25: 🏗️ Heavy liftAlign this dialog with the Avalonia MVVM pattern used in the host.
This window currently acts as its own view-model (
INotifyPropertyChanged+ code-behind click handlers). Please move state/commands into anObservableObjectview-model and bind commands from AXAML for consistency with the Avalonia migration pattern.As per coding guidelines:
Flow.Launcher.Avalonia/**/*.cs: Avalonia UI code should use CommunityToolkit.Mvvm patterns such asObservableObject,[ObservableProperty],[RelayCommand].Also applies to: 125-139
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Flow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml.cs` around lines 11 - 25, The ProgressBoxWindow class currently implements view-model responsibilities (implements INotifyPropertyChanged, holds _isIndeterminate, _progressValue, _progressText and click handlers) — refactor by extracting a new ViewModel class that derives from CommunityToolkit.Mvvm.ComponentModel.ObservableObject (e.g., ProgressBoxViewModel) and use [ObservableProperty] for IsIndeterminate, ProgressValue, ProgressText and a [RelayCommand] for the cancel action that invokes the existing _cancelProgress logic; update ProgressBoxWindow to set DataContext = new ProgressBoxViewModel(TitleText, cancelAction) and remove INotifyPropertyChanged implementation and backing fields from the code-behind, then wire the AXAML to bind to the new ViewModel properties and command names instead of relying on code-behind handlers (ensure ProgressBoxWindow constructor still accepts caption and cancelAction and passes them into the ViewModel).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a0986ad8-fa43-42ba-912f-9c97ce418693
📒 Files selected for processing (81)
.github/AGENTS.md.github/workflows/dotnet.yml.gitignore.gsd/quick/1-a-review-about-whether-we-have-touched-a/1-SUMMARY.mdAGENTS.mdAVALONIA_MIGRATION_CHECKLIST.mdFlow.Launcher.Avalonia/.agent/README.mdFlow.Launcher.Avalonia/AGENTS.mdFlow.Launcher.Avalonia/App.axaml.csFlow.Launcher.Avalonia/AvaloniaPublicAPI.csFlow.Launcher.Avalonia/Flow.Launcher.Avalonia.csprojFlow.Launcher.Avalonia/Helper/AutoStartup.csFlow.Launcher.Avalonia/Helper/HotKeyMapper.csFlow.Launcher.Avalonia/Helper/ResultHelper.csFlow.Launcher.Avalonia/MainWindow.axamlFlow.Launcher.Avalonia/MainWindow.axaml.csFlow.Launcher.Avalonia/Storage/History.csFlow.Launcher.Avalonia/Themes/Base.axamlFlow.Launcher.Avalonia/Themes/Resources.axamlFlow.Launcher.Avalonia/ViewModel/MainViewModel.csFlow.Launcher.Avalonia/ViewModel/ResultViewModel.csFlow.Launcher.Avalonia/ViewModel/SettingPages/AboutSettingsViewModel.csFlow.Launcher.Avalonia/ViewModel/SettingPages/GeneralSettingsViewModel.csFlow.Launcher.Avalonia/ViewModel/SettingPages/HotkeySettingsViewModel.csFlow.Launcher.Avalonia/ViewModel/SettingPages/PluginStoreSettingsViewModel.csFlow.Launcher.Avalonia/ViewModel/SettingPages/ThemeSettingsViewModel.csFlow.Launcher.Avalonia/Views/Controls/HotkeyControl.axaml.csFlow.Launcher.Avalonia/Views/Controls/HotkeyDisplay.axamlFlow.Launcher.Avalonia/Views/Controls/HotkeyDisplay.axaml.csFlow.Launcher.Avalonia/Views/Dialogs/NotificationWindow.axamlFlow.Launcher.Avalonia/Views/Dialogs/NotificationWindow.axaml.csFlow.Launcher.Avalonia/Views/Dialogs/PluginUpdateWindow.axamlFlow.Launcher.Avalonia/Views/Dialogs/PluginUpdateWindow.axaml.csFlow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axamlFlow.Launcher.Avalonia/Views/Dialogs/ProgressBoxWindow.axaml.csFlow.Launcher.Avalonia/Views/Dialogs/ReportWindow.axamlFlow.Launcher.Avalonia/Views/Dialogs/ReportWindow.axaml.csFlow.Launcher.Avalonia/Views/Dialogs/WelcomeWindow.axamlFlow.Launcher.Avalonia/Views/Dialogs/WelcomeWindow.axaml.csFlow.Launcher.Avalonia/Views/ResultListBox.axamlFlow.Launcher.Avalonia/Views/SettingPages/AboutSettingsPage.axamlFlow.Launcher.Avalonia/Views/SettingPages/CustomQueryHotkeyWindow.axamlFlow.Launcher.Avalonia/Views/SettingPages/CustomQueryHotkeyWindow.axaml.csFlow.Launcher.Avalonia/Views/SettingPages/CustomShortcutWindow.axamlFlow.Launcher.Avalonia/Views/SettingPages/CustomShortcutWindow.axaml.csFlow.Launcher.Avalonia/Views/SettingPages/GeneralSettingsPage.axamlFlow.Launcher.Avalonia/Views/SettingPages/HotkeySettingsPage.axamlFlow.Launcher.Avalonia/Views/SettingPages/ReleaseNotesWindow.axamlFlow.Launcher.Avalonia/Views/SettingPages/ReleaseNotesWindow.axaml.csFlow.Launcher.Avalonia/Views/SettingPages/SelectBrowserWindow.axamlFlow.Launcher.Avalonia/Views/SettingPages/SelectBrowserWindow.axaml.csFlow.Launcher.Avalonia/Views/SettingPages/SelectFileManagerWindow.axamlFlow.Launcher.Avalonia/Views/SettingPages/SelectFileManagerWindow.axaml.csFlow.Launcher.Avalonia/Views/SettingPages/ThemeSettingsPage.axamlFlow.Launcher.Core/AGENTS.mdFlow.Launcher.Core/packages.lock.jsonFlow.Launcher.Infrastructure/AGENTS.mdFlow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csprojFlow.Launcher.Infrastructure/Storage/JsonStorage.csFlow.Launcher.Infrastructure/packages.lock.jsonFlow.Launcher.Plugin/AGENTS.mdFlow.Launcher.Plugin/Flow.Launcher.Plugin.csprojFlow.Launcher.Plugin/packages.lock.jsonFlow.Launcher.Test/Avalonia/ProgrammaticQueryFocusRequestTest.csFlow.Launcher.Test/Flow.Launcher.Test.csprojFlow.Launcher/AGENTS.mdFlow.Launcher/Languages/en.xamlFlow.Launcher/Storage/History.csFlow.Launcher/packages.lock.jsonPlugins/AGENTS.mdPlugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csprojPlugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csprojPlugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.csPlugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.csPlugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xamlPlugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csprojPlugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xamlPlugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csprojPlugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csprojPlugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csprojopencode.json
✅ Files skipped from review due to trivial changes (7)
- Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
- Flow.Launcher.Avalonia/.agent/README.md
- Flow.Launcher.Avalonia/Flow.Launcher.Avalonia.csproj
- .gitignore
- Flow.Launcher.Avalonia/Themes/Base.axaml
- Flow.Launcher/Languages/en.xaml
- Flow.Launcher.Plugin/packages.lock.json
🚧 Files skipped from review as they are similar to previous changes (7)
- Flow.Launcher.Test/Flow.Launcher.Test.csproj
- Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
- .github/workflows/dotnet.yml
- Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
- Flow.Launcher.Avalonia/ViewModel/SettingPages/HotkeySettingsViewModel.cs
- Flow.Launcher.Avalonia/ViewModel/ResultViewModel.cs
- Flow.Launcher.Avalonia/AvaloniaPublicAPI.cs
|
Amazing work. Always looking for a simple replacement for spotlight after switching from win to mac, since I use flow launcher for such a long time! |
This PR introduces the experimental Avalonia UI host alongside the existing WPF host so the migration can continue incrementally while preserving side-by-side comparison.
The current migration tracker is
AVALONIA_MIGRATION_CHECKLIST.md.Summary
Flow.Launcher.Avalonia, a .NET 9 Avalonia host with its own output directory atOutput/Debug/Avalonia.Flow.Launcher.Plugin,Flow.Launcher.Infrastructure, andFlow.Launcher.Core.What Works
Migration Checklist
Windows & Dialogs — 16/19 complete (84%)
Settings Pages
Core UX / ViewModels
Helpers, Converters, and Controls
Theming and Polish
Build & Run
Notes for Reviewers
AVALONIA_MIGRATION_CHECKLIST.mdas the detailed source of truth for parity status and remaining gaps.