Skip to content

Conversation

Jack251970
Copy link
Member

CHANGES

  • Use Localize for string resource
  • Use PublicApi.Instance instead of private one

@github-actions github-actions bot added this to the 2.1.0 milestone Sep 23, 2025
Copy link

gitstream-cm bot commented Sep 23, 2025

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

This comment has been minimized.

@coderabbitai coderabbitai bot added the enhancement New feature or request label Sep 23, 2025
Copy link
Contributor

coderabbitai bot commented Sep 23, 2025

Warning

Rate limit exceeded

@Jack251970 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 4 minutes and 48 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 54622d6 and ac62eba.

📒 Files selected for processing (4)
  • Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs (1 hunks)
  • Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs (1 hunks)
  • Flow.Launcher/MainWindow.xaml.cs (5 hunks)
  • Flow.Launcher/ViewModel/PluginViewModel.cs (2 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Replace DI-based IPublicAPI and API.GetTranslation usages with a centralized PublicApi.Instance and Localize.* across Core, Infrastructure, and App; add Flow.Launcher.Localization package, suppress FLSG0007 in Release builds, enable DI flag, update en.xaml resources, and minor synchronization/timer tweaks.

Changes

Cohort / File(s) Summary
Core: PublicApi & Localize migration
Flow.Launcher.Core/Configuration/Portable.cs, Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs, Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs, Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs, Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs, Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs, Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs, Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs, Flow.Launcher.Core/Plugin/PluginConfig.cs, Flow.Launcher.Core/Plugin/PluginInstaller.cs, Flow.Launcher.Core/Plugin/PluginManager.cs, Flow.Launcher.Core/Plugin/PluginsLoader.cs, Flow.Launcher.Core/Resource/Internationalization.cs, Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs, Flow.Launcher.Core/Resource/Theme.cs, Flow.Launcher.Core/Updater.cs
Remove DI/lazy IPublicAPI fields and related usings; replace API.* and API.GetTranslation(...) calls with PublicApi.Instance.* and Localize.* equivalents for logging, prompts, and translations. Preserve public signatures and control flow.
Infrastructure: API → PublicApi/Localize; misc runtime tweaks
Flow.Launcher.Infrastructure/Http/Http.cs, Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs, Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs, Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs, Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs
Remove DI-based API access; route messages via PublicApi.Instance/Localize; remove DI usings; change several lock objects to Lock; initialize collections with literals; modernize timer null checks.
App/UI: Localize for user-facing text & small logic tweak
Flow.Launcher/ActionKeywords.xaml.cs, Flow.Launcher/App.xaml.cs, Flow.Launcher/CustomQueryHotkeySetting.xaml.cs, Flow.Launcher/CustomShortcutSetting.xaml.cs, Flow.Launcher/Helper/HotKeyMapper.cs, Flow.Launcher/HotkeyControl*.xaml.cs, Flow.Launcher/HotkeyControlDialog.xaml.cs, Flow.Launcher/MainWindow.xaml.cs, Flow.Launcher/PluginUpdateWindow.xaml.cs, Flow.Launcher/PublicAPIInstance.cs, Flow.Launcher/ReleaseNotesWindow.xaml.cs, Flow.Launcher/ReportWindow.xaml.cs, Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs, Flow.Launcher/SettingPages/ViewModels/SettingsPane*.cs, Flow.Launcher/ViewModel/*.cs, Flow.Launcher/ViewModel/SelectBrowserViewModel.cs, Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs
Replace App.API.GetTranslation(...) with Localize.* calls for titles, messages, tooltips, and labels. Minor behavioral change: PluginUpdateWindow now always removes unchecked plugin from list.
Project files: localization package, warnings, DI flag, en.xaml link
Flow.Launcher.Core/Flow.Launcher.Core.csproj, Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj, Flow.Launcher/Flow.Launcher.csproj
Add PackageReference Flow.Launcher.Localization v0.0.6; add Release NoWarn FLSG0007; add property FLLUseDependencyInjection=true; link Languages\en.xaml from Flow.Launcher into Core/Infrastructure projects.
Package locks: add Flow.Launcher.Localization
Flow.Launcher.Core/packages.lock.json, Flow.Launcher.Infrastructure/packages.lock.json, Flow.Launcher/packages.lock.json
Introduce Flow.Launcher.Localization@0.0.6 as a direct dependency in lockfiles and project dependency graphs.
Language resources
Flow.Launcher/Languages/en.xaml
Add plugin_default_search_delay_time and plugin_search_delay_time entries; modify folderOpenError to remove the placeholder.

Sequence Diagram(s)

(Skipped — changes are a widespread API/localization refactor without new control-flow interactions requiring diagrams.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • jjw24
  • onesounds
  • VictoriousRaptor

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title concisely identifies the primary change—adopting Flow.Launcher.Localization—and conveys the intent to improve code quality; it is relevant to the changeset. It does not mention the secondary change (switching private API usage to PublicApi.Instance) but still accurately represents the main focus of the PR.
Description Check ✅ Passed The description directly lists the two principal changes—using Localize for string resources and replacing the private API instance with PublicApi.Instance—which aligns with the file-level summaries and PR objectives and is therefore on-topic and sufficient for this lenient check.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

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

❤️ Share

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

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

Caution

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

⚠️ Outside diff range comments (6)
Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs (1)

39-64: Revert setting on failure to avoid inconsistent state

If enabling/disabling auto-startup throws, Settings.StartFlowLauncherOnSystemStartup remains set to the requested value even though the system change failed. This desynchronizes UI/config from reality. Capture the previous value and revert it in the catch.

Apply this diff:

 private void ChangeAutoStartup(bool value)
 {
-    Settings.StartFlowLauncherOnSystemStartup = value;
+    var previous = Settings.StartFlowLauncherOnSystemStartup;
+    Settings.StartFlowLauncherOnSystemStartup = value;
     try
     {
         if (value)
         {
             if (Settings.UseLogonTaskForStartup)
             {
                 AutoStartup.ChangeToViaLogonTask();
             }
             else
             {
                 AutoStartup.ChangeToViaRegistry();
             }
         }
         else
         {
             AutoStartup.DisableViaLogonTaskAndRegistry();
         }
     }
     catch (Exception e)
     {
-        App.API.ShowMsgError(Localize.setAutoStartFailed(), e.Message);
+        // Revert UI/setting to reflect actual state
+        Settings.StartFlowLauncherOnSystemStartup = previous;
+        App.API.ShowMsgError(Localize.setAutoStartFailed(), e.Message);
     }
 }
Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs (1)

52-58: Possible NullReference when JSON deserializes to null.

If ReadFromJsonAsync returns null, logging plugins.Count will NRE. Guard and default to an empty list.

Apply this patch:

-                    plugins = await response.Content
-                        .ReadFromJsonAsync<List<UserPlugin>>(PluginStoreItemSerializationOption, cancellationToken: token)
-                        .ConfigureAwait(false);
+                    var deserialized = await response.Content
+                        .ReadFromJsonAsync<List<UserPlugin>>(PluginStoreItemSerializationOption, cancellationToken: token)
+                        .ConfigureAwait(false) ?? new List<UserPlugin>();
+                    plugins = deserialized;
Flow.Launcher.Core/Resource/Internationalization.cs (1)

52-66: SystemLanguageCode is always reset to English (logic bug)

The final assignment unconditionally sets SystemLanguageCode to "en", overriding any detected match. Break after a match or only set default when no match is found.

Apply this diff:

-            // Try to find a match in the available languages list
+            // Default to English, then try to find a match in the available languages list
+            SystemLanguageCode = DefaultLanguageCode;
             foreach (var language in availableLanguages)
             {
                 var languageCode = language.LanguageCode;
 
                 if (string.Equals(languageCode, twoLetterCode, StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(languageCode, threeLetterCode, StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(languageCode, fullName, StringComparison.OrdinalIgnoreCase))
                 {
                     SystemLanguageCode = languageCode;
-                }
+                    break;
+                }
             }
-
-            SystemLanguageCode = DefaultLanguageCode;
Flow.Launcher/MainWindow.xaml.cs (1)

821-821: Fix spelling check failure: use “workaround”

CI fails on “work around”. Replace with “workaround”.

-            // Initialize call twice to work around multi-display alignment issue- https://github.com/Flow-Launcher/Flow.Launcher/issues/2910
+            // Initialize call twice to workaround multi-display alignment issue - https://github.com/Flow-Launcher/Flow.Launcher/issues/2910
...
-            // Initialize call twice to work around multi-display alignment issue- https://github.com/Flow-Launcher/Flow.Launcher/issues/2910
+            // Initialize call twice to workaround multi-display alignment issue - https://github.com/Flow-Launcher/Flow.Launcher/issues/2910

Also applies to: 845-845

Flow.Launcher.Core/Plugin/PluginInstaller.cs (2)

82-86: Don't fail install if temp file deletion throws

Deleting the downloaded zip inside the main try means a deletion failure will be reported as “Failed to install plugin” even though install succeeded.

Apply this diff to isolate deletion errors:

-            if (!newPlugin.IsFromLocalInstallPath)
-            {
-                File.Delete(filePath);
-            }
+            if (!newPlugin.IsFromLocalInstallPath)
+            {
+                try
+                {
+                    File.Delete(filePath);
+                }
+                catch (Exception ex)
+                {
+                    PublicApi.Instance.LogException(ClassName, "Failed to delete temp plugin file after install", ex);
+                }
+            }

120-124: Handle invalid/empty plugin.json and be case-insensitive

Deserialization can return null (invalid/empty JSON) and default casing may not match plugin.json. Prevent NRE and improve robustness.

-            using Stream stream = pluginJsonEntry.Open();
-            plugin = JsonSerializer.Deserialize<UserPlugin>(stream);
+            using Stream stream = pluginJsonEntry.Open();
+            var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
+            plugin = JsonSerializer.Deserialize<UserPlugin>(stream, jsonOptions)
+                     ?? throw new InvalidDataException("Invalid plugin.json.");
             plugin.IcoPath = "Images\\zipfolder.png";
             plugin.LocalInstallPath = filePath;
🧹 Nitpick comments (29)
Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs (1)

62-62: Localization change looks good; consider PublicApi.Instance for consistency

Using Localize.setAutoStartFailed() is aligned with the PR. For consistency with the “use PublicApi.Instance” direction, consider swapping App.API for PublicApi.Instance here.

-        App.API.ShowMsgError(Localize.setAutoStartFailed(), e.Message);
+        PublicApi.Instance.ShowMsgError(Localize.setAutoStartFailed(), e.Message);

Can you confirm whether the project is standardizing on PublicApi.Instance in pages as well?

Flow.Launcher/ReportWindow.xaml.cs (1)

52-52: Optional: shorten displayed path for readability.

Long absolute paths can wrap awkwardly. Consider showing just the filename (or a shortened path) if the localized string doesn’t rely on the full path.

-            paragraph.Inlines.Add(Localize.reportWindow_upload_log(log.FullName));
+            paragraph.Inlines.Add(Localize.reportWindow_upload_log(Path.GetFileName(log.FullName)));
Flow.Launcher/CustomShortcutSetting.xaml.cs (1)

50-52: Prefer PublicApi.Instance over App.API for consistency with the PR direction.

Align this call (and others in this file) with the new pattern.

Apply this change here:

-                App.API.ShowMsgBox(Localize.duplicateShortcut());
+                PublicApi.Instance.ShowMsgBox(Localize.duplicateShortcut());

Also update the other usages for consistency (add the appropriate using if needed):

// Line 43
// App.API.ShowMsgBox(Localize.emptyShortcut());
PublicApi.Instance.ShowMsgBox(Localize.emptyShortcut());

// Lines 66-69
// App.API.ChangeQuery(tbExpand.Text);
PublicApi.Instance.ChangeQuery(tbExpand.Text);
// App.API.ShowMainWindow();
PublicApi.Instance.ShowMainWindow();
Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs (1)

53-53: Prefer PublicApi.Instance over App.API for consistency with PR objective

Use PublicApi.Instance.ShowMsgBox(...) to align with the migration away from private API access.

-            App.API.ShowMsgBox(Localize.pleaseSelectAnItem());
+            PublicApi.Instance.ShowMsgBox(Localize.pleaseSelectAnItem());

Apply similarly at other occurrences in this file.

Also applies to: 76-76, 115-115, 137-137

Flow.Launcher/ReleaseNotesWindow.xaml.cs (1)

134-136: Optional: Align message API usage with PublicApi.Instance

For consistency with the PR’s broader shift, consider calling PublicApi.Instance directly.

Apply within this block:

-                    App.API.ShowMsgError(
+                    Flow.Launcher.Plugin.PublicApi.Instance.ShowMsgError(
                         Localize.checkNetworkConnectionTitle(),
                         Localize.checkNetworkConnectionSubTitle());
Flow.Launcher/ViewModel/PluginViewModel.cs (3)

167-172: Use string interpolation; consider localizing the “ms” unit

  • Interpolation improves readability and avoids concat noise.
  • If feasible, move the “ms” unit inside the localized format (some locales may prefer different spacing/order).
-        public string Version => Localize.plugin_query_version()+ " " + PluginPair.Metadata.Version;
+        public string Version => $"{Localize.plugin_query_version()} {PluginPair.Metadata.Version}";

-        public string InitAndQueryTime =>
-            Localize.plugin_init_time()+ " " +
-            PluginPair.Metadata.InitTime + "ms, " +
-            Localize.plugin_query_time()+ " " +
-            PluginPair.Metadata.AvgQueryTime + "ms";
+        public string InitAndQueryTime =>
+            $"{Localize.plugin_init_time()} {PluginPair.Metadata.InitTime}ms, " +
+            $"{Localize.plugin_query_time()} {PluginPair.Metadata.AvgQueryTime}ms";

If the localization package provides formatters that include units, prefer those (e.g., plugin_init_time_ms(int ms)). Please confirm whether such keys exist before changing.


174-176: Avoid nullable type ambiguity by pattern matching; cleaner and safer

Passing a nullable int to a localized formatter can cause overload ambiguity. Pattern matching also improves readability.

-        public string SearchDelayTimeText => PluginPair.Metadata.SearchDelayTime == null ?
-            Localize.plugin_default_search_delay_time() :
-            Localize.plugin_search_delay_time(PluginPair.Metadata.SearchDelayTime);
+        public string SearchDelayTimeText =>
+            PluginPair.Metadata.SearchDelayTime is int delay
+                ? Localize.plugin_search_delay_time(delay)
+                : Localize.plugin_default_search_delay_time();

Double-check the signature of Localize.plugin_search_delay_time(...) to ensure it expects a non-nullable int (or adjust accordingly).


158-160: Localize placeholders OK; avoid surfacing raw exception text in UI

  • Verified: errorCreatingSettingPanel in Flow.Launcher/Languages/*.xaml = "Error creating setting panel for plugin {0}:{1}{2}" (3 placeholders) — call passes (pair.Metadata.Name, Environment.NewLine, e.Message) and matches.
  • Localize is accessible project-wide (no missing import detected).
  • Optional: stop showing e.Message to end users — keep App.API.LogException(e) and show a friendly message (or expose details only in DEBUG).

Location: Flow.Launcher/ViewModel/PluginViewModel.cs:158-160

Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs (1)

54-56: Confirm desired ShowMsgError overload and address spelling warning

  • If you intend a title + message UX (as used elsewhere), consider using the 2‑param overload for consistency.
  • Pipeline warning: “JTF” flagged by the spell checker. Add “JTF” to the allowlist for the Check Spelling action.

Would you confirm whether a subtitle is desired here and add “JTF” to the spelling dictionary used by the workflow?

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

105-108: Use a file‑manager‑specific or neutral localization key for the "new profile" label

Localize.defaultBrowser_new_profile() is used in SelectBrowserViewModel.cs:53 and SelectFileManagerViewModel.cs:107 — change the File Manager usage to a dedicated key (e.g., Localize.defaultFileManager_new_profile()) or a neutral key (e.g., Localize.defaultNewProfile()) and update the resource entry accordingly.

Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs (1)

10-10: Null-safe, culture-agnostic comparison for DisplayName

Use Ordinal equality and a null-safe fallback to avoid culture issues and potential null propagation to bindings.

-        public string DisplayName => Name == "Default" ? Localize.defaultBrowser_default(): Name;
+        public string DisplayName =>
+            string.Equals(Name, "Default", System.StringComparison.Ordinal)
+                ? Localize.defaultBrowser_default()
+                : Name ?? string.Empty;
Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs (1)

86-87: Use Warn level for version-exclusion log

Excluding a plugin due to version mismatch is more a warning than info.

-            PublicApi.Instance.LogInfo(ClassName, $"Plugin {plugin.Name} requires minimum Flow Launcher version {plugin.MinimumAppVersion}, "
+            PublicApi.Instance.LogWarn(ClassName, $"Plugin {plugin.Name} requires minimum Flow Launcher version {plugin.MinimumAppVersion}, "
                 + $"but current version is {Constant.Version}. Plugin excluded from manifest.");
Flow.Launcher/Flow.Launcher.csproj (1)

166-168: Introduce FLLUseDependencyInjection: OK; consider centralizing.

Looks fine. Consider moving this to Directory.Build.props to keep it consistent across projects.

Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs (2)

65-69: Preserve last-known plugins on unexpected status.

Returning null clears callers’ data. Prefer returning the cached list to keep UX stable.

Apply this patch:

-                    PublicApi.Instance.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
-                    return null;
+                    PublicApi.Instance.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
+                    return plugins;

41-45: Dispose HttpRequestMessage.

Minor resource hygiene improvement.

Apply this patch:

-            var request = new HttpRequestMessage(HttpMethod.Get, ManifestFileUrl);
+            using var request = new HttpRequestMessage(HttpMethod.Get, ManifestFileUrl);
Flow.Launcher.Core/Flow.Launcher.Core.csproj (1)

68-71: Set FLLUseDependencyInjection: LGTM; consider centralizing.

Consider moving to Directory.Build.props to prevent drift.

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

1757-1761: Remove unused locals in Plugin Info menu.

author is used; website and version are not. Also the local translator variable above is now unused. Drop unused variables.

Apply this patch:

-            var author = Localize.author();
-            var website = Localize.website();
-            var version = Localize.version();
-            var plugin = Localize.plugin();
+            var author = Localize.author();
+            var plugin = Localize.plugin();

Outside this hunk: remove the now-unused var translator = App.API;.

Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs (1)

49-51: Include the exception message as subtitle for user context (consistent with App.xaml.cs).

Improves troubleshooting parity with other flows using ShowMsgError(title, e.Message).

Apply:

-                    API.ShowMsgError(Localize.failToInstallTypeScriptEnv());
+                    API.ShowMsgError(Localize.failToInstallTypeScriptEnv(), e.Message);
Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs (1)

49-51: Also include exception message as subtitle here for consistency.

-                    API.ShowMsgError(Localize.failToInstallTypeScriptEnv());
+                    API.ShowMsgError(Localize.failToInstallTypeScriptEnv(), e.Message);
Flow.Launcher.Core/Plugin/PluginConfig.cs (1)

133-135: Fix typo and missing delimiter in error message.

Spelling and missing '>' in the config path delimiter.

-                PublicApi.Instance.LogError(ClassName, $"Execute file path didn't exist <{metadata.ExecuteFilePath}> for conifg <{configPath}");
+                PublicApi.Instance.LogError(ClassName, $"Execute file path didn't exist <{metadata.ExecuteFilePath}> for config <{configPath}>");
Flow.Launcher/CustomQueryHotkeySetting.xaml.cs (1)

44-45: LGTM: Localize empty-hotkey message.

Optional: for consistency with other dialogs, consider adding a title via Localize.MessageBoxTitle().

-                App.API.ShowMsgBox(Localize.emptyPluginHotkey());
+                App.API.ShowMsgBox(Localize.emptyPluginHotkey(), Localize.MessageBoxTitle());
Flow.Launcher.Core/Resource/Internationalization.cs (1)

309-320: Fix incorrect path in default English missing log

The log for missing default English language uses {path} (the requested language), should log {english}.

-                        PublicApi.Instance.LogError(ClassName, $"Default English Language path can't be found <{path}>");
+                        PublicApi.Instance.LogError(ClassName, $"Default English Language path can't be found <{english}>");
Flow.Launcher/HotkeyControlDialog.xaml.cs (1)

142-146: Consider migrating translation to PublicApi.Instance.GetTranslation

To align with the broader refactor, prefer PublicApi.Instance.GetTranslation over App.API.GetTranslation when resolving resources dynamically.

-            var description = string.Format(
-                App.API.GetTranslation(registeredHotkeyData.DescriptionResourceKey),
+            var description = string.Format(
+                PublicApi.Instance.GetTranslation(registeredHotkeyData.DescriptionResourceKey),
                 registeredHotkeyData.DescriptionFormatVariables
             );
Flow.Launcher.Core/Configuration/Portable.cs (1)

37-41: Spelling warnings for “uninstaller”

CI flagged unrecognized spelling; consider adding to dictionary or adjusting copy if enforced.

Flow.Launcher.Core/Plugin/PluginManager.cs (1)

321-323: Avoid PublicApi in core PluginManager for modified check

Call the internal PluginModified(...) directly within PluginManager to prevent unnecessary API indirection and align with maintainers’ guidance.

-            if (PublicApi.Instance.PluginModified(plugin.Metadata.ID))
+            if (PluginModified(plugin.Metadata.ID))
                 return Array.Empty<PluginPair>();
Flow.Launcher.Core/Plugin/PluginInstaller.cs (4)

186-187: Typo in comment

“don not” → “do not”.

-            return; // don not restart on failure
+            return; // do not restart on failure

296-310: Redundant modified-plugins check

You already filter out modified plugins when building results. The All(PluginModified) guard will never be true (and is covered by the Count == 0 check anyway).

-        // If all plugins are modified, just return
-        if (resultsForUpdate.All(x => PublicApi.Instance.PluginModified(x.ID)))
-        {
-            return;
-        }

330-361: Data race on anyPluginSuccess across parallel tasks; also clean up temp zips

The bool is written by multiple tasks without synchronization, which is racy. Also delete per-plugin temp zip after a successful update.

-        var anyPluginSuccess = false;
+        var successCount = 0;
         await Task.WhenAll(resultsForUpdate.Select(async plugin =>
         {
             var downloadToFilePath = Path.Combine(Path.GetTempPath(), $"{plugin.Name}-{plugin.NewVersion}.zip");
 
             try
             {
                 using var cts = new CancellationTokenSource();
 
                 await DownloadFileAsync(
                     $"{Localize.DownloadingPlugin()} {plugin.PluginNewUserPlugin.Name}",
                     plugin.PluginNewUserPlugin.UrlDownload, downloadToFilePath, cts);
 
                 // check if user cancelled download before installing plugin
                 if (cts.IsCancellationRequested)
                 {
                     return;
                 }
 
                 if (!await PublicApi.Instance.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, downloadToFilePath))
                 {
                     return;
                 }
 
-                anyPluginSuccess = true;
+                System.Threading.Interlocked.Increment(ref successCount);
+                try
+                {
+                    if (File.Exists(downloadToFilePath))
+                        File.Delete(downloadToFilePath);
+                }
+                catch (Exception ex)
+                {
+                    PublicApi.Instance.LogException(ClassName, "Failed to delete temp plugin file after update (update all)", ex);
+                }
             }
             catch (Exception e)
             {
                 PublicApi.Instance.LogException(ClassName, "Failed to update plugin", e);
                 PublicApi.Instance.ShowMsgError(Localize.ErrorUpdatingPlugin());
             }
         }));
 
-        if (!anyPluginSuccess) return;
+        if (successCount == 0) return;

445-448: Case-insensitive host URL match

Use OrdinalIgnoreCase for StartsWith to avoid false negatives due to casing.

-        return PublicApi.Instance.GetAllPlugins().Any(x =>
+        return PublicApi.Instance.GetAllPlugins().Any(x =>
             !string.IsNullOrEmpty(x.Metadata.Website) &&
-            x.Metadata.Website.StartsWith(constructedUrlPart)
+            x.Metadata.Website.StartsWith(constructedUrlPart, StringComparison.OrdinalIgnoreCase)
         );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e8819a and 0e366a6.

📒 Files selected for processing (50)
  • Flow.Launcher.Core/Configuration/Portable.cs (6 hunks)
  • Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs (3 hunks)
  • Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs (4 hunks)
  • Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs (1 hunks)
  • Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs (1 hunks)
  • Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs (1 hunks)
  • Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs (2 hunks)
  • Flow.Launcher.Core/Flow.Launcher.Core.csproj (3 hunks)
  • Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs (1 hunks)
  • Flow.Launcher.Core/Plugin/PluginConfig.cs (4 hunks)
  • Flow.Launcher.Core/Plugin/PluginInstaller.cs (18 hunks)
  • Flow.Launcher.Core/Plugin/PluginManager.cs (23 hunks)
  • Flow.Launcher.Core/Plugin/PluginsLoader.cs (3 hunks)
  • Flow.Launcher.Core/Resource/Internationalization.cs (7 hunks)
  • Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs (1 hunks)
  • Flow.Launcher.Core/Resource/Theme.cs (2 hunks)
  • Flow.Launcher.Core/Updater.cs (6 hunks)
  • Flow.Launcher.Core/packages.lock.json (2 hunks)
  • Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs (8 hunks)
  • Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj (3 hunks)
  • Flow.Launcher.Infrastructure/Http/Http.cs (1 hunks)
  • Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs (1 hunks)
  • Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs (1 hunks)
  • Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs (1 hunks)
  • Flow.Launcher.Infrastructure/packages.lock.json (1 hunks)
  • Flow.Launcher/ActionKeywords.xaml.cs (2 hunks)
  • Flow.Launcher/App.xaml.cs (1 hunks)
  • Flow.Launcher/CustomQueryHotkeySetting.xaml.cs (1 hunks)
  • Flow.Launcher/CustomShortcutSetting.xaml.cs (1 hunks)
  • Flow.Launcher/Flow.Launcher.csproj (3 hunks)
  • Flow.Launcher/Helper/HotKeyMapper.cs (3 hunks)
  • Flow.Launcher/HotkeyControl.xaml.cs (2 hunks)
  • Flow.Launcher/HotkeyControlDialog.xaml.cs (4 hunks)
  • Flow.Launcher/Languages/en.xaml (2 hunks)
  • Flow.Launcher/MainWindow.xaml.cs (5 hunks)
  • Flow.Launcher/PluginUpdateWindow.xaml.cs (3 hunks)
  • Flow.Launcher/PublicAPIInstance.cs (6 hunks)
  • Flow.Launcher/ReleaseNotesWindow.xaml.cs (1 hunks)
  • Flow.Launcher/ReportWindow.xaml.cs (1 hunks)
  • Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs (1 hunks)
  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs (5 hunks)
  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs (6 hunks)
  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs (4 hunks)
  • Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs (2 hunks)
  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs (3 hunks)
  • Flow.Launcher/ViewModel/MainViewModel.cs (6 hunks)
  • Flow.Launcher/ViewModel/PluginViewModel.cs (2 hunks)
  • Flow.Launcher/ViewModel/SelectBrowserViewModel.cs (1 hunks)
  • Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs (2 hunks)
  • Flow.Launcher/packages.lock.json (3 hunks)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3593
File: Flow.Launcher/HotkeyControlDialog.xaml:6-6
Timestamp: 2025-09-05T11:56:27.267Z
Learning: In Flow.Launcher's migration to iNKORE.UI.WPF.Modern UI framework, dialog resource keys like PopuBGColor, PopupButtonAreaBGColor, PopupButtonAreaBorderColor, and PopupTextColor are provided by the iNKORE.UI.WPF.Modern framework itself, not defined locally in the codebase theme files.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3850
File: Flow.Launcher.Core/Resource/Internationalization.cs:0-0
Timestamp: 2025-07-20T07:28:28.092Z
Learning: In Flow Launcher's Internationalization class, when the Flow Launcher language directory or default language file is missing, the only viable approach is to log an error and return early - there are no fallback mechanisms or alternative recovery strategies available due to architectural constraints.
📚 Learning: 2024-10-08T15:52:58.573Z
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#2616
File: Flow.Launcher/Flow.Launcher.csproj:7-7
Timestamp: 2024-10-08T15:52:58.573Z
Learning: In the Flow Launcher project, the version number in the `Flow.Launcher.csproj` file is dynamically updated during the CI/CD process.

Applied to files:

  • Flow.Launcher.Infrastructure/packages.lock.json
  • Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
  • Flow.Launcher.Core/packages.lock.json
  • Flow.Launcher/packages.lock.json
  • Flow.Launcher.Core/Flow.Launcher.Core.csproj
  • Flow.Launcher/Flow.Launcher.csproj
📚 Learning: 2025-07-06T12:21:37.947Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3572
File: Flow.Launcher/App.xaml.cs:214-216
Timestamp: 2025-07-06T12:21:37.947Z
Learning: In Flow Launcher, the UpdatePluginManifestAsync method in PluginsManifest.cs already has comprehensive internal try-catch handling that logs exceptions and returns false on failure rather than throwing, making external try-catch wrappers unnecessary.

Applied to files:

  • Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs
  • Flow.Launcher.Core/Plugin/PluginsLoader.cs
  • Flow.Launcher.Core/Plugin/PluginManager.cs
  • Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
  • Flow.Launcher.Core/Plugin/PluginConfig.cs
  • Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
  • Flow.Launcher.Core/Plugin/PluginInstaller.cs
  • Flow.Launcher/PluginUpdateWindow.xaml.cs
📚 Learning: 2025-07-01T05:46:13.251Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3791
File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295
Timestamp: 2025-07-01T05:46:13.251Z
Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.

Applied to files:

  • Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs
  • Flow.Launcher.Core/Plugin/PluginsLoader.cs
  • Flow.Launcher.Core/Plugin/PluginManager.cs
  • Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
  • Flow.Launcher.Core/Plugin/PluginConfig.cs
  • Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
  • Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs
  • Flow.Launcher.Core/Plugin/PluginInstaller.cs
  • Flow.Launcher/ViewModel/PluginViewModel.cs
  • Flow.Launcher/PluginUpdateWindow.xaml.cs
📚 Learning: 2025-09-04T11:52:29.096Z
Learnt from: jjw24
PR: Flow-Launcher/Flow.Launcher#3932
File: Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs:48-55
Timestamp: 2025-09-04T11:52:29.096Z
Learning: In Flow Launcher's PluginsManifest.cs, when dealing with version parsing for the MinimumAppVersion feature, maintainer jjw24 prefers to keep the solution simple rather than implementing comprehensive helper methods for SemVer parsing normalization.

Applied to files:

  • Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs
  • Flow.Launcher.Core/packages.lock.json
  • Flow.Launcher/packages.lock.json
  • Flow.Launcher.Core/Plugin/PluginInstaller.cs
📚 Learning: 2025-07-21T09:19:49.684Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3854
File: Flow.Launcher/App.xaml.cs:246-262
Timestamp: 2025-07-21T09:19:49.684Z
Learning: In Flow Launcher's App.xaml.cs, the asynchronous plugin initialization task (containing AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate, PluginManager.LoadPlugins, PluginManager.InitializePluginsAsync, and AutoPluginUpdates) does not require additional try-catch error handling according to maintainer Jack251970, as these operations are designed to handle exceptions internally.

Applied to files:

  • Flow.Launcher.Core/Plugin/PluginsLoader.cs
  • Flow.Launcher.Core/Plugin/PluginManager.cs
  • Flow.Launcher.Core/Plugin/PluginConfig.cs
  • Flow.Launcher/App.xaml.cs
  • Flow.Launcher.Core/Resource/Internationalization.cs
📚 Learning: 2025-07-21T09:19:19.012Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3854
File: Flow.Launcher.Core/Plugin/PluginManager.cs:280-292
Timestamp: 2025-07-21T09:19:19.012Z
Learning: In Flow Launcher's PluginManager.cs, the post-initialization operations (RegisterResultsUpdatedEvent, UpdatePluginMetadataTranslation, RegisterPluginActionKeywords, DialogJump.InitializeDialogJumpPlugin, and AddPluginToLists) are designed to be exception-safe and do not require additional try-catch error handling according to the maintainer Jack251970.

Applied to files:

  • Flow.Launcher.Core/Plugin/PluginConfig.cs
📚 Learning: 2025-07-20T07:28:28.092Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3850
File: Flow.Launcher.Core/Resource/Internationalization.cs:0-0
Timestamp: 2025-07-20T07:28:28.092Z
Learning: In Flow Launcher's Internationalization class, when the Flow Launcher language directory or default language file is missing, the only viable approach is to log an error and return early - there are no fallback mechanisms or alternative recovery strategies available due to architectural constraints.

Applied to files:

  • Flow.Launcher/App.xaml.cs
  • Flow.Launcher.Core/Resource/Internationalization.cs
  • Flow.Launcher/PublicAPIInstance.cs
📚 Learning: 2025-09-05T11:56:27.267Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3593
File: Flow.Launcher/HotkeyControlDialog.xaml:6-6
Timestamp: 2025-09-05T11:56:27.267Z
Learning: In Flow.Launcher's migration to iNKORE.UI.WPF.Modern UI framework, dialog resource keys like PopuBGColor, PopupButtonAreaBGColor, PopupButtonAreaBorderColor, and PopupTextColor are provided by the iNKORE.UI.WPF.Modern framework itself, not defined locally in the codebase theme files.

Applied to files:

  • Flow.Launcher/App.xaml.cs
  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
  • Flow.Launcher/MainWindow.xaml.cs
  • Flow.Launcher.Core/Resource/Theme.cs
  • Flow.Launcher/HotkeyControlDialog.xaml.cs
📚 Learning: 2025-06-24T19:06:48.344Z
Learnt from: Koisu-unavailable
PR: Flow-Launcher/Flow.Launcher#3770
File: Flow.Launcher/ViewModel/MainViewModel.cs:0-0
Timestamp: 2025-06-24T19:06:48.344Z
Learning: In Flow.Launcher's Explorer plugin results, the SubTitle property always contains the directory containing the file. For file results, Title contains the filename and SubTitle contains the parent directory. For directory results, SubTitle contains the directory path itself.

Applied to files:

  • Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
📚 Learning: 2025-06-08T14:12:21.348Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.

Applied to files:

  • Flow.Launcher/MainWindow.xaml.cs
📚 Learning: 2025-03-28T21:12:13.386Z
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.

Applied to files:

  • Flow.Launcher/HotkeyControlDialog.xaml.cs
🧬 Code graph analysis (28)
Flow.Launcher/CustomQueryHotkeySetting.xaml.cs (1)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/HotkeyControl.xaml.cs (2)
Flow.Launcher/PublicAPIInstance.cs (1)
  • System (159-222)
Flow.Launcher/ReleaseNotesWindow.xaml.cs (1)
  • System (122-145)
Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs (1)
Flow.Launcher.Core/Resource/Internationalization.cs (1)
  • GetTranslation (343-355)
Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs (1)
Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs (1)
  • LogException (479-482)
Flow.Launcher.Core/Plugin/PluginsLoader.cs (1)
Flow.Launcher.Infrastructure/Logger/Log.cs (1)
  • Exception (93-103)
Flow.Launcher.Core/Plugin/PluginManager.cs (4)
Flow.Launcher/PublicAPIInstance.cs (10)
  • LogException (285-286)
  • SavePluginSettings (304-310)
  • SavePluginCaches (552-558)
  • LogWarn (279-280)
  • LogInfo (276-277)
  • LogDebug (273-274)
  • ShowMsg (127-128)
  • ShowMsg (130-133)
  • PluginModified (586-586)
  • ShowMsgError (121-122)
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs (10)
  • LogException (311-311)
  • SavePluginSettings (65-65)
  • SavePluginCaches (465-465)
  • LogWarn (300-300)
  • LogInfo (295-295)
  • LogDebug (290-290)
  • ShowMsg (128-128)
  • ShowMsg (137-137)
  • PluginModified (539-539)
  • ShowMsgError (85-85)
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs (2)
  • FilesFolders (14-377)
  • CopyAll (25-72)
Flow.Launcher.Plugin/AllowedLanguage.cs (2)
  • AllowedLanguage (8-118)
  • IsDotNet (65-69)
Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs (2)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1)
  • Settings (15-615)
Flow.Launcher/CustomShortcutSetting.xaml.cs (2)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs (1)
  • DoesShortcutExist (167-171)
Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs (4)
Flow.Launcher.Core/Plugin/PluginConfig.cs (2)
  • List (20-60)
  • List (62-98)
Flow.Launcher.Core/Plugin/PluginManager.cs (1)
  • List (480-507)
Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs (1)
  • List (19-78)
Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs (1)
  • UserPlugin (62-78)
Flow.Launcher.Core/Plugin/PluginConfig.cs (2)
Flow.Launcher.Plugin/AllowedLanguage.cs (2)
  • AllowedLanguage (8-118)
  • IsAllowed (111-117)
Flow.Launcher.Core/Resource/Internationalization.cs (1)
  • Language (167-180)
Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs (2)
Flow.Launcher.Core/Resource/Internationalization.cs (1)
  • Language (167-180)
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs (2)
  • FilesFolders (14-377)
  • RemoveFolderIfExists (115-131)
Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs (2)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/PublicAPIInstance.cs (1)
  • ShowMsgError (121-122)
Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs (3)
Flow.Launcher.Core/Resource/Internationalization.cs (1)
  • GetTranslation (343-355)
Flow.Launcher/PublicAPIInstance.cs (1)
  • GetTranslation (249-249)
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs (1)
  • GetTranslation (171-171)
Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs (2)
Flow.Launcher/PublicAPIInstance.cs (1)
  • MessageBoxResult (522-525)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs (2)
Flow.Launcher/PublicAPIInstance.cs (1)
  • System (159-222)
Flow.Launcher/ReleaseNotesWindow.xaml.cs (1)
  • System (122-145)
Flow.Launcher/App.xaml.cs (2)
Flow.Launcher/PublicAPIInstance.cs (1)
  • ShowMsgError (121-122)
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs (1)
  • ShowMsgError (85-85)
Flow.Launcher.Core/Updater.cs (1)
Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs (1)
  • DataLocation (6-44)
Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs (2)
Flow.Launcher.Infrastructure/Win32Helper.cs (2)
  • Win32Helper (31-921)
  • IsBackdropSupported (35-40)
Flow.Launcher.Infrastructure/Constant.cs (1)
  • Constant (7-59)
Flow.Launcher.Core/Resource/Internationalization.cs (2)
Flow.Launcher/PublicAPIInstance.cs (3)
  • LogError (282-283)
  • LogException (285-286)
  • MessageBoxResult (522-525)
Flow.Launcher/MessageBoxEx.xaml.cs (1)
  • MessageBoxResult (25-64)
Flow.Launcher/ActionKeywords.xaml.cs (1)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs (2)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/PublicAPIInstance.cs (1)
  • ShowMsgError (121-122)
Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs (1)
Flow.Launcher.Core/Plugin/PluginManager.cs (1)
  • PluginModified (622-625)
Flow.Launcher/MainWindow.xaml.cs (3)
Flow.Launcher/PublicAPIInstance.cs (1)
  • System (159-222)
Flow.Launcher/ReleaseNotesWindow.xaml.cs (1)
  • System (122-145)
Flow.Launcher.Infrastructure/Constant.cs (1)
  • Constant (7-59)
Flow.Launcher.Core/Plugin/PluginInstaller.cs (2)
Flow.Launcher/PublicAPIInstance.cs (10)
  • PluginModified (586-586)
  • ShowMsgError (121-122)
  • InstallPlugin (591-592)
  • LogException (285-286)
  • RestartApp (77-90)
  • ShowMsg (127-128)
  • ShowMsg (130-133)
  • MessageBoxResult (522-525)
  • ShowMsgWithButton (135-136)
  • ShowMsgWithButton (138-141)
Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs (1)
  • InstallSourceKnown (656-675)
Flow.Launcher.Core/Configuration/Portable.cs (3)
Flow.Launcher.Infrastructure/Constant.cs (1)
  • Constant (7-59)
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs (5)
  • FilesFolders (14-377)
  • CopyAll (25-72)
  • VerifyBothFolderFilesEqual (82-108)
  • RemoveFolderIfExists (115-131)
  • OpenPath (168-190)
Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs (1)
  • DataLocation (6-44)
Flow.Launcher/ViewModel/MainViewModel.cs (2)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/PublicAPIInstance.cs (2)
  • ShowMsg (127-128)
  • ShowMsg (130-133)
Flow.Launcher/PluginUpdateWindow.xaml.cs (1)
Flow.Launcher/App.xaml.cs (2)
  • App (31-450)
  • App (57-118)
Flow.Launcher/PublicAPIInstance.cs (3)
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs (2)
  • LogException (311-311)
  • ShowMsgError (85-85)
Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs (1)
  • ShowMsgError (62-65)
Flow.Launcher.Infrastructure/Logger/Log.cs (1)
  • Exception (93-103)
🪛 GitHub Actions: Check Spelling
Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs

[warning] 36-40: Unrecognized spelling: 'JTF'. (unrecognized-spelling)

Flow.Launcher/MainWindow.xaml.cs

[error] 821-821: Forbidden pattern: 'work around' matches line_forbidden.patterns. (pattern: \bwork[- ]arounds?\b)

Flow.Launcher.Core/Configuration/Portable.cs

[warning] 37-52: Unrecognized spelling: 'uninstaller'. (unrecognized-spelling)


[warning] 40-34: Unrecognized spelling: 'Uninstaller'. (unrecognized-spelling)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: gitStream workflow automation
  • GitHub Check: gitStream.cm
  • GitHub Check: build

This comment has been minimized.

@Jack251970 Jack251970 requested a review from Copilot September 23, 2025 09:54
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.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs (4)

17-17: Prefer property over captured singleton to avoid stale/early reference

Capturing the singleton at field-init can race with initialization and makes test swapping harder. Use a property that always reads the current instance.

-protected readonly IPublicAPI API = PublicApi.Instance;
+protected IPublicAPI API => PublicApi.Instance;

74-90: Optional: break condition UX

Current loop re-prompts indefinitely if the user keeps choosing “Yes” then canceling the file dialog. Consider adding a “Cancel” option or max attempts to improve UX.


112-116: Optional: include caption/icon for error clarity

Consider using an overload that sets a caption and/or error icon for clearer context, e.g., caption = EnvName or a localized title.


237-244: Guard against missing anchor in path slicing (avoid out-of-range)

If DataLocation.PluginEnvironments is not found (unexpected, but possible), the range slice will throw. Also prefer case-insensitive search on Windows paths.

-        private static string GetUpdatedEnvironmentPath(string filePath)
-        {
-            var index = filePath.IndexOf(DataLocation.PluginEnvironments);
-
-            // get the substring after "Environments" because we can not determine it dynamically
-            var executablePathSubstring = filePath[(index + DataLocation.PluginEnvironments.Length)..];
-            return $"{DataLocation.PluginEnvironmentsPath}{executablePathSubstring}";
-        }
+        private static string GetUpdatedEnvironmentPath(string filePath)
+        {
+            var index = filePath.IndexOf(DataLocation.PluginEnvironments, StringComparison.OrdinalIgnoreCase);
+            if (index < 0)
+            {
+                PublicApi.Instance.LogError(nameof(AbstractPluginEnvironment),
+                    $"'{DataLocation.PluginEnvironments}' not found in path: {filePath}",
+                    nameof(GetUpdatedEnvironmentPath));
+                return filePath;
+            }
+
+            // get the substring after "Environments" because we can not determine it dynamically
+            var executablePathSubstring = filePath[(index + DataLocation.PluginEnvironments.Length)..];
+            return $"{DataLocation.PluginEnvironmentsPath}{executablePathSubstring}";
+        }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e366a6 and 54622d6.

📒 Files selected for processing (4)
  • Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs (5 hunks)
  • Flow.Launcher.Core/packages.lock.json (2 hunks)
  • Flow.Launcher.Infrastructure/packages.lock.json (1 hunks)
  • Flow.Launcher/packages.lock.json (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • Flow.Launcher.Infrastructure/packages.lock.json
  • Flow.Launcher.Core/packages.lock.json
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3593
File: Flow.Launcher/HotkeyControlDialog.xaml:6-6
Timestamp: 2025-09-05T11:56:27.267Z
Learning: In Flow.Launcher's migration to iNKORE.UI.WPF.Modern UI framework, dialog resource keys like PopuBGColor, PopupButtonAreaBGColor, PopupButtonAreaBorderColor, and PopupTextColor are provided by the iNKORE.UI.WPF.Modern framework itself, not defined locally in the codebase theme files.
📚 Learning: 2024-10-08T15:52:58.573Z
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#2616
File: Flow.Launcher/Flow.Launcher.csproj:7-7
Timestamp: 2024-10-08T15:52:58.573Z
Learning: In the Flow Launcher project, the version number in the `Flow.Launcher.csproj` file is dynamically updated during the CI/CD process.

Applied to files:

  • Flow.Launcher/packages.lock.json
📚 Learning: 2025-09-04T11:52:29.096Z
Learnt from: jjw24
PR: Flow-Launcher/Flow.Launcher#3932
File: Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs:48-55
Timestamp: 2025-09-04T11:52:29.096Z
Learning: In Flow Launcher's PluginsManifest.cs, when dealing with version parsing for the MinimumAppVersion feature, maintainer jjw24 prefers to keep the solution simple rather than implementing comprehensive helper methods for SemVer parsing normalization.

Applied to files:

  • Flow.Launcher/packages.lock.json
📚 Learning: 2025-07-01T05:46:13.251Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3791
File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295
Timestamp: 2025-07-01T05:46:13.251Z
Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.

Applied to files:

  • Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
🧬 Code graph analysis (1)
Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs (1)
Flow.Launcher.Core/Resource/Internationalization.cs (1)
  • Language (167-180)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: gitStream.cm
  • GitHub Check: gitStream.cm
  • GitHub Check: build
🔇 Additional comments (5)
Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs (2)

60-61: LGTM: Localize + centralized API usage

Good switch to Localize and PublicApi.Instance. Please confirm the new Localize keys exist in all shipped locales or have fallbacks.


63-66: LGTM: Localized dialog title

Title for the file dialog is localized and passed through consistently.

Flow.Launcher/packages.lock.json (3)

849-856: Core now depends on Localization — confirm csproj wiring

Flow.Launcher.Core already references Flow.Launcher.Localization (Flow.Launcher.Core/Flow.Launcher.Core.csproj). The package is also referenced in: Flow.Launcher/Flow.Launcher.csproj; Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj; Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj; Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj; Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj. Confirm each reference is intentional and remove any unintended PackageReference entries.


17-22: Confirmed: Flow.Launcher.Localization 0.0.6 exists on NuGet — metadata verified

Nuspec shows id=Flow.Launcher.Localization, version=0.0.6, authors=Flow-Launcher, license=MIT (https://licenses.nuget.org/MIT), repository=https://github.com/Flow-Launcher/Flow.Launcher.Localization (commit 456bdc7a986487d691a3ae8d36f8bce7b88b9bc7). OK to add.


864-875: Infrastructure now depends on Flow.Launcher.Localization — verify restore & CI

Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj contains and Flow.Launcher.Infrastructure/packages.lock.json records it resolved to 0.0.6; run dotnet restore and confirm the lockfile/CI build succeed.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR modernizes the codebase by migrating from the old App.API.GetTranslation() pattern to the new Flow.Launcher.Localization package, improving code quality and localization consistency.

  • Adds Flow.Launcher.Localization package dependency to multiple projects
  • Replaces string formatting with App.API.GetTranslation() calls with direct Localize.*() method calls
  • Updates dependency injection usage to use PublicApi.Instance instead of private API instances

Reviewed Changes

Copilot reviewed 50 out of 50 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
Flow.Launcher/packages.lock.json Added Flow.Launcher.Localization package dependency
Flow.Launcher/ViewModel/*.cs Migrated translation calls from App.API pattern to Localize methods
Flow.Launcher/SettingPages/ViewModels/*.cs Updated localization calls and removed string formatting
Flow.Launcher/Resources/Pages/*.cs Updated translation method calls
Flow.Launcher/*.cs Updated main application files to use new localization
Flow.Launcher.Infrastructure/*.cs Updated infrastructure classes to use PublicApi.Instance
Flow.Launcher.Core/*.cs Updated core classes with new localization pattern

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

This comment has been minimized.

This comment has been minimized.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 50 out of 50 changed files in this pull request and generated no new comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

This comment has been minimized.

This comment has been minimized.

@Jack251970 Jack251970 force-pushed the flow_launcher_localization1 branch from 9c518e9 to 54622d6 Compare September 23, 2025 10:07

This comment has been minimized.

Copy link

@check-spelling-bot Report

🔴 Please review

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

❌ Errors and Warnings Count
❌ forbidden-pattern 2
⚠️ noisy-file 3
⚠️ non-alpha-in-dictionary 2

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. workaround(s)

\bwork[- ]arounds?\b
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.

@Jack251970 Jack251970 merged commit 2d00ab1 into dev Sep 27, 2025
6 checks passed
@Jack251970 Jack251970 deleted the flow_launcher_localization1 branch September 27, 2025 16:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Code Quality enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants