-
-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce Dependency Injection for Better Development Experience #3175
base: dev
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughThis pull request introduces a comprehensive refactoring of message display and dependency management across the Flow Launcher application. The primary changes involve replacing direct Changes
Suggested labels
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
This comment has been minimized.
This comment has been minimized.
I was thinking about unifying the access to Very earlier I was thinking about integrating dependency injection in flow, but that seems to be pretty complicated. Maybe we can do that gradually specifically for the PublicAPI? I am not sure. What do others think about global state access? |
@taooceros I agree that dependency injection is the most elegant way to access |
I mean it can serve as a transitional solution for unifying the call of api functions. (here I just do for functions related to |
This comment has been minimized.
This comment has been minimized.
🥷 Code experts: Yusyuriv, jjw24 Yusyuriv, jjw24 have most 🧠 knowledge in the files. See details
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame:
Knowledge based on git-blame: To learn more about /:\ gitStream - Visit our Docs |
Now I implement dependency injection model for this, and can you please take a look of this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🔭 Outside diff range comments (1)
Flow.Launcher.Core/Plugin/PluginsLoader.cs (1)
Line range hint
123-127
: Consider using constructor injection instead of service locator pattern.The use of
Ioc.Default.GetRequiredService
is a service locator anti-pattern that makes the code harder to test and maintain. Consider:
- Making the class non-static
- Injecting IPublicAPI through the constructor
public static class PluginsLoader { + private readonly IPublicAPI _api; + + public PluginsLoader(IPublicAPI api) + { + _api = api; + } public static IEnumerable<PluginPair> DotNetPlugins(...) { // ... - Ioc.Default.GetRequiredService<IPublicAPI>().ShowMsgBox(...); + _api.ShowMsgBox(...);
🧹 Nitpick comments (19)
Flow.Launcher.Core/Resource/Internationalization.cs (2)
128-128
: Consider constructor injection instead of service locator pattern.While the change aligns with the PR's objective to unify API access, using
Ioc.Default
directly is a service locator anti-pattern. Consider injectingIPublicAPI
through the constructor for better testability and maintainability.Example refactor:
public class Internationalization { public Settings Settings { get; set; } + private readonly IPublicAPI _api; private const string Folder = "Languages"; // ... other fields ... - public Internationalization() + public Internationalization(IPublicAPI api) { + _api = api; AddFlowLauncherLanguageDirectory(); } // ... other methods ... public bool PromptShouldUsePinyin(string languageCodeToSet) { // ... existing code ... - if (Ioc.Default.GetRequiredService<IPublicAPI>().ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (_api.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) return false; // ... existing code ... } }
Line range hint
114-131
: Consider separating UI interaction from business logic.The method currently mixes business logic (determining if Pinyin should be used) with UI concerns (showing dialog). Consider extracting the UI interaction to improve testability and maintainability.
Example approach:
+public interface IUserPrompt +{ + bool ConfirmPinyinUsage(Language language); +} public class Internationalization { private readonly IPublicAPI _api; + private readonly IUserPrompt _userPrompt; - public Internationalization(IPublicAPI api) + public Internationalization(IPublicAPI api, IUserPrompt userPrompt) { _api = api; + _userPrompt = userPrompt; } public bool PromptShouldUsePinyin(string languageCodeToSet) { var languageToSet = GetLanguageByLanguageCode(languageCodeToSet); if (Settings.ShouldUsePinyin) return false; if (languageToSet != AvailableLanguages.Chinese && languageToSet != AvailableLanguages.Chinese_TW) return false; - string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?"; - if (_api.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) - return false; - - return true; + return _userPrompt.ConfirmPinyinUsage(languageToSet); } }Flow.Launcher.Infrastructure/UserSettings/Settings.cs (2)
16-26
: Consider constructor injection for better dependency management.While the current implementation works, it adds another initialization requirement that needs to be managed. Given the discussion about unifying API access and potentially moving towards dependency injection, consider:
- Using constructor injection instead of manual initialization
- Making the class immutable where possible
- Using an interface for the storage dependency
This would better align with the goal of improving the development experience and make future DI adoption easier.
Example approach:
- public class Settings : BaseModel, IHotkeySettings + public class Settings : BaseModel, IHotkeySettings, ISettings { - private FlowLauncherJsonStorage<Settings> _storage; + private readonly ISettingsStorage<Settings> _storage; - public void Initialize(FlowLauncherJsonStorage<Settings> storage) - { - _storage = storage; - } + public Settings(ISettingsStorage<Settings> storage) + { + _storage = storage ?? throw new ArgumentNullException(nameof(storage)); + }
Line range hint
1-590
: Consider breaking down the Settings class into smaller, focused components.The Settings class has grown to handle multiple concerns, making it harder to maintain and test. Consider splitting it into smaller, focused classes:
- HotkeySettings (hotkey-related properties)
- UISettings (window size, fonts, themes)
- BrowserSettings (browser configurations)
- ExplorerSettings (explorer configurations)
- PluginSettings (already partially separated)
This would:
- Improve maintainability
- Make the code more testable
- Reduce the cognitive load when making changes
- Make it easier to implement proper dependency injection
Flow.Launcher/ViewModel/MainViewModel.cs (1)
62-68
: Consider future refactoring to constructor injection.While using
Ioc.Default.GetRequiredService
works as a transitional solution, it introduces service location which can make the code harder to test and maintain. Consider gradually moving towards constructor injection in future refactors.A more maintainable approach would be:
-public MainViewModel() +public MainViewModel(Settings settings) { _queryTextBeforeLeaveResults = ""; _queryText = ""; _lastQuery = new Query(); - Settings = Ioc.Default.GetRequiredService<Settings>(); + Settings = settings;Flow.Launcher/App.xaml.cs (6)
89-90
: Avoid using static instances when employing dependency injectionIn lines 89-90, you assign the
StringMatcher.Instance
static property to the instance retrieved from the IoC container:StringMatcher.Instance = stringMatcher;This practice introduces a global state, which undermines the benefits of dependency injection and can lead to harder-to-test code. Consider refactoring the code to inject
StringMatcher
where needed rather than relying on the static instance.
98-98
: Refactor to eliminate the staticApp.API
propertyWhile transitioning to dependency injection, retaining the static
App.API
property may lead to inconsistencies and reduced testability. Instead, injectIPublicAPI
into classes that require it, promoting better modularity and adherence to dependency injection principles.
106-107
: Inject dependencies intoMainWindow
instead of passing_settings
directlyIn lines 106-107,
_settings
is passed directly toMainWindow
's constructor:var window = new MainWindow(_settings, mainVM);To maintain consistency with the dependency injection approach, consider injecting
Settings
intoMainWindow
via the IoC container. This enhances testability and aligns with best practices.
114-114
: RefactorHotKeyMapper
to use dependency injectionCurrently,
HotKeyMapper
is initialized statically:HotKeyMapper.Initialize(mainVM);Consider refactoring
HotKeyMapper
to accept dependencies through constructor injection. This change would improve modularity and make the codebase more maintainable.
163-167
: OptimizeUpdater
by injectingIPublicAPI
In the
AutoUpdates
method,API
is passed explicitly toUpdateAppAsync
:await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync(API);Since
Updater
is registered in the IoC container, consider injectingIPublicAPI
intoUpdater
directly. This reduces dependencies between components and enhances code readability.
210-210
: Avoid overusingIoc.Default
for resolving servicesIn line 210,
MainViewModel
is resolved directly from the service locator:Ioc.Default.GetRequiredService<MainViewModel>().Show();Frequent use of the service locator pattern can lead to code that's harder to maintain and test. Consider injecting
MainViewModel
where needed instead of resolving it directly.Flow.Launcher/ActionKeywords.xaml.cs (1)
47-47
: InjectIPublicAPI
instead of accessingApp.API
directlyIn line 47,
App.API.ShowMsgBox(msg);
is used to display a message box:App.API.ShowMsgBox(msg);To adhere to dependency injection principles and improve testability, consider injecting
IPublicAPI
into theActionKeywords
class. This approach reduces coupling to theApp
class and enhances modularity.Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs (1)
31-31
: LGTM! Consider adding error handling.The change from
MessageBoxEx.Show
toAPI.ShowMsgBox
aligns with the PR objectives. The lambda syntax is appropriate for the callback scenario.Consider wrapping the folder removal in a try-catch block to handle potential IO exceptions:
- FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); + try { + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); + } catch (System.IO.IOException ex) { + API.ShowMsgBox($"Failed to remove folder: {ex.Message}"); + }Flow.Launcher/PriorityChangeWindow.xaml.cs (1)
47-47
: LGTM! Consider extracting the message preparation.The change aligns with the PR objectives.
Consider extracting the message preparation to improve readability:
- string msg = translater.GetTranslation("invalidPriority"); - App.API.ShowMsgBox(msg); + App.API.ShowMsgBox(translater.GetTranslation("invalidPriority"));Flow.Launcher/CustomShortcutSetting.xaml.cs (1)
52-52
: LGTM! Consider consolidating validation logic.The change aligns with the PR objectives.
Consider consolidating the validation logic into a separate method:
+ private bool ValidateShortcut(string key, string value) + { + if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) + { + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("emptyShortcut")); + return false; + } + if (((update && originalKey != key) || !update) && _hotkeyVm.DoesShortcutExist(key)) + { + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); + return false; + } + return true; + }Flow.Launcher/CustomQueryHotkeySetting.xaml.cs (1)
66-66
: LGTM! Error handling is maintained.The change from
MessageBoxEx.Show
toApp.API.ShowMsgBox
maintains the existing error handling while aligning with the PR objectives.Consider adding a descriptive error message that includes the invalid hotkey details:
- App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); + var message = $"{InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")} (Action: {item.ActionKeyword}, Hotkey: {item.Hotkey})"; + App.API.ShowMsgBox(message);Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs (1)
Line range hint
65-72
: LGTM! Consider extracting message strings to constants.The migration from
MessageBoxEx.Show
toApp.API.ShowMsgBox
is implemented correctly. The internationalization and message box parameters are properly maintained.Consider extracting the translation keys to constants at the class level for better maintainability and reusability:
+ private const string ClearLogFolderMessageKey = "clearlogfolderMessage"; + private const string ClearLogFolderTitleKey = "clearlogfolder"; private void AskClearLogFolderConfirmation() { var confirmResult = App.API.ShowMsgBox( - InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"), - InternationalizationManager.Instance.GetTranslation("clearlogfolder"), + InternationalizationManager.Instance.GetTranslation(ClearLogFolderMessageKey), + InternationalizationManager.Instance.GetTranslation(ClearLogFolderTitleKey), MessageBoxButton.YesNo );Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs (2)
45-47
: Extract common message to reduce duplication.The "pleaseSelectAnItem" message is used multiple times. Consider extracting it to a constant or helper method.
+ private const string PleaseSelectItemKey = "pleaseSelectAnItem"; + private void ShowPleaseSelectItemMessage() => + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation(PleaseSelectItemKey)); private void CustomHotkeyDelete() { var item = SelectedCustomPluginHotkey; if (item is null) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + ShowPleaseSelectItemMessage(); return; }Also applies to: 70-72, 91-93, 115-117
Line range hint
49-56
: Consider extracting confirmation dialog pattern.Both delete operations follow the same confirmation pattern. Consider extracting this to a reusable method.
+ private bool ConfirmDeletion<T>(T item, string warningKey, string itemDisplay) + { + var result = App.API.ShowMsgBox( + string.Format( + InternationalizationManager.Instance.GetTranslation(warningKey), + itemDisplay + ), + InternationalizationManager.Instance.GetTranslation("delete"), + MessageBoxButton.YesNo + ); + return result == MessageBoxResult.Yes; + } private void CustomHotkeyDelete() { var item = SelectedCustomPluginHotkey; if (item is null) { ShowPleaseSelectItemMessage(); return; } - var result = App.API.ShowMsgBox(/*...*/); - if (result is MessageBoxResult.Yes) + if (ConfirmDeletion(item, "deleteCustomHotkeyWarning", item.Hotkey)) { Settings.CustomPluginHotkeys.Remove(item); HotKeyMapper.RemoveHotkey(item.Hotkey); } }Also applies to: 95-102
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (30)
Flow.Launcher.Core/Configuration/Portable.cs
(7 hunks)Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
(5 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/Plugin/PluginManager.cs
(1 hunks)Flow.Launcher.Core/Plugin/PluginsLoader.cs
(2 hunks)Flow.Launcher.Core/Resource/Internationalization.cs
(2 hunks)Flow.Launcher.Core/Resource/Theme.cs
(4 hunks)Flow.Launcher.Core/Updater.cs
(4 hunks)Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
(1 hunks)Flow.Launcher.Infrastructure/PinyinAlphabet.cs
(2 hunks)Flow.Launcher.Infrastructure/StringMatcher.cs
(2 hunks)Flow.Launcher.Infrastructure/UserSettings/Settings.cs
(2 hunks)Flow.Launcher/ActionKeywords.xaml.cs
(1 hunks)Flow.Launcher/App.xaml.cs
(5 hunks)Flow.Launcher/CustomQueryHotkeySetting.xaml.cs
(1 hunks)Flow.Launcher/CustomShortcutSetting.xaml.cs
(1 hunks)Flow.Launcher/Flow.Launcher.csproj
(2 hunks)Flow.Launcher/Helper/HotKeyMapper.cs
(1 hunks)Flow.Launcher/MessageBoxEx.xaml
(1 hunks)Flow.Launcher/MessageBoxEx.xaml.cs
(1 hunks)Flow.Launcher/PriorityChangeWindow.xaml.cs
(2 hunks)Flow.Launcher/PublicAPIInstance.cs
(1 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs
(1 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
(4 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs
(1 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
(1 hunks)Flow.Launcher/ViewModel/MainViewModel.cs
(2 hunks)Flow.Launcher/ViewModel/SettingWindowViewModel.cs
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- Flow.Launcher/MessageBoxEx.xaml.cs
🧰 Additional context used
📓 Learnings (1)
Flow.Launcher/Flow.Launcher.csproj (1)
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#2616
File: Flow.Launcher/Flow.Launcher.csproj:7-7
Timestamp: 2024-11-12T03:58:56.325Z
Learning: In the Flow Launcher project, the version number in the `Flow.Launcher.csproj` file is dynamically updated during the CI/CD process.
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: gitStream.cm
- GitHub Check: gitStream.cm
🔇 Additional comments (20)
Flow.Launcher.Core/Resource/Internationalization.cs (1)
14-14
: LGTM! Using CommunityToolkit.Mvvm for dependency injection.The addition of CommunityToolkit.Mvvm's dependency injection aligns well with the PR's objective to improve API access patterns.
Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1)
7-7
: LGTM!The addition of the Storage namespace import is appropriate for the new storage functionality.
Flow.Launcher/PublicAPIInstance.cs (1)
36-36
: Good use of abstraction by changing_alphabet
toIAlphabet
Switching the type from
PinyinAlphabet
to theIAlphabet
interface enhances flexibility and allows for different implementations, promoting a more extensible design.Flow.Launcher/ViewModel/MainViewModel.cs (2)
28-28
: LGTM! Using statement aligns with DI changes.The addition of CommunityToolkit.Mvvm.DependencyInjection enables proper dependency injection support.
68-68
: Verify DI container configuration.Ensure that Settings is properly registered in the DI container before MainViewModel is instantiated.
Run this script to verify the DI setup:
✅ Verification successful
DI container configuration for Settings is properly set up
The Settings class is correctly registered as a singleton in the DI container before MainViewModel is instantiated, ensuring proper dependency management.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for proper DI registration of Settings # Look for container configuration and Settings registration rg -A 5 'AddSingleton<Settings>|services\.Add.*Settings'Length of output: 58
Script:
#!/bin/bash # First, find Settings class definition ast-grep --pattern 'class Settings' # Then look for service collection setup and registration patterns rg -l "IServiceCollection|ServiceCollection|BuildServiceProvider" # Also search for any Settings usage in startup/configuration files rg -l "Settings" "*Program.cs" "*Startup.cs"Length of output: 34619
Script:
#!/bin/bash # Look for DI configuration in App.xaml.cs and service registration patterns rg -A 10 "CreateHost|Host\.CreateDefault|ConfigureServices|AddSingleton|\.Services\." "Flow.Launcher/App.xaml.cs" # Search for service registration using ast-grep to find method calls ast-grep --pattern 'AddSingleton<$_>($_)' # Look for Settings usage in App initialization rg -A 5 "new Settings\(\)|GetService<Settings>|GetRequiredService<Settings>" "Flow.Launcher/App.xaml.cs"Length of output: 1522
Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs (1)
28-28
: Confirmed refactoring to centralized message handlingThe update to use
API.ShowMsgBox(s)
aligns with the project's shift towards centralized message handling viaIPublicAPI
. This enhances consistency across the codebase.Flow.Launcher/PriorityChangeWindow.xaml.cs (1)
27-27
: LGTM! Error handling is maintained.The change from
MessageBoxEx.Show
toApp.API.ShowMsgBox
maintains the existing error handling while aligning with the PR objectives.Flow.Launcher/CustomShortcutSetting.xaml.cs (1)
46-46
: LGTM! Validation is maintained.The change from
MessageBoxEx.Show
toApp.API.ShowMsgBox
maintains the existing validation while aligning with the PR objectives.Flow.Launcher/MessageBoxEx.xaml (1)
2-2
: LGTM! Namespace changes align with project reorganization.The MessageBoxEx class has been correctly moved from Flow.Launcher.Core to Flow.Launcher namespace, aligning with the PR objectives.
Let's verify that all references to MessageBoxEx have been updated:
Also applies to: 6-6
✅ Verification successful
✅ Namespace changes are properly implemented
All references to MessageBoxEx have been updated to use the new
Flow.Launcher
namespace. No remaining references to the oldFlow.Launcher.Core
namespace were found.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for any remaining references to Flow.Launcher.Core.MessageBoxEx rg "Flow\.Launcher\.Core\.MessageBoxEx"Length of output: 41
Script:
#!/bin/bash # Search for MessageBoxEx references in all files rg "MessageBoxEx" -A 2 # Specifically look for XAML references fd -e xaml -x grep -l "MessageBoxEx" {} \;Length of output: 1685
Flow.Launcher.Core/Updater.cs (2)
59-59
: LGTM! Consistent API usage for message boxes.The changes to use API.ShowMsgBox are consistent with the project-wide changes and maintain the same functionality.
Also applies to: 74-76, 89-89
26-26
: Consider thread safety implications of singleton API instance.While using dependency injection is good, retrieving the API instance at field initialization might cause issues if the IoC container isn't set up when the class is instantiated.
Consider injecting IPublicAPI through the constructor instead:
-private readonly IPublicAPI API = Ioc.Default.GetRequiredService<IPublicAPI>(); +private readonly IPublicAPI API; + +public Updater(IPublicAPI api) +{ + API = api; +}Flow.Launcher.Core/Configuration/Portable.cs (1)
19-19
: LGTM! Well-structured dependency injection.The changes properly implement dependency injection by using a private readonly field initialized through the constructor.
Flow.Launcher.Core/Resource/Theme.cs (2)
14-14
: LGTM: Dependency injection setup looks good.The addition of CommunityToolkit.Mvvm.DependencyInjection and initialization of IPublicAPI through dependency injection aligns with the PR objectives of improving the development experience.
Also applies to: 27-27
114-114
: LGTM: Message box calls properly migrated.The MessageBoxEx.Show calls have been consistently replaced with API.ShowMsgBox, maintaining the same functionality while using the new centralized message handling approach.
Also applies to: 124-124
Flow.Launcher.Core/Plugin/PluginManager.cs (1)
522-522
: LGTM: Consistent message handling approach.The change to use API.ShowMsgBox via lambda expression maintains consistency with the PR's objective of centralizing message handling.
Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs (1)
28-28
: LGTM: Consistent message handling approach.The change to use API.ShowMsgBox via lambda expression maintains consistency with the PR's objective of centralizing message handling.
Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs (1)
25-25
: LGTM! Change aligns with unified API access pattern.The replacement of MessageBoxEx.Show with App.API.ShowMsgBox is consistent with the PR objective of unifying API access.
Let's verify error handling in proxy testing scenarios:
✅ Verification successful
Error handling verification successful
The proxy-related error handling is comprehensive and properly maintained:
- Input validation for server and port
- Connection failure handling
- All error messages are properly internationalized
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for other proxy-related error handling patterns rg -A 2 "proxyConnectFailed|serverCantBeEmpty|portCantBeEmpty" --type csLength of output: 1129
Flow.Launcher/Helper/HotKeyMapper.cs (1)
49-49
: LGTM! Consistent error handling pattern.The change to App.API.ShowMsgBox maintains consistent error handling across the application.
Let's verify the consistency of error handling in hotkey-related scenarios:
✅ Verification successful
Verified: Message box usage is consistent across the codebase
The change from MessageBoxEx.Show to App.API.ShowMsgBox in HotKeyMapper.cs aligns with the application-wide pattern where all UI components use the API abstraction for showing message boxes.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for similar hotkey registration error handling patterns rg "registerHotkeyFailed|HotkeyManager.Current" --type cs -A 2Length of output: 1387
Script:
#!/bin/bash # Search for MessageBoxEx.Show and App.API.ShowMsgBox usage rg "MessageBoxEx\.Show|App\.API\.ShowMsgBox" --type cs -A 2Length of output: 5488
Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj (1)
57-57
: LGTM! Addition of MVVM toolkit enhances development experience.The CommunityToolkit.Mvvm package addition supports the MVVM pattern implementation across the project.
Flow.Launcher/Flow.Launcher.csproj (1)
91-92
: Review framework and package version compatibility.The project targets .NET 7 but uses .NET 8 packages (Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Hosting version 8.0.1). This version mismatch might cause compatibility issues.
Consider downgrading to version 7.x.x or upgrading the target framework to .NET 8.
Let's verify the impact:
✅ Verification successful
Version mismatch is safe for current DI usage patterns
The codebase uses only basic DI features (Host builder and singleton registration) that are stable between .NET 7 and 8. While aligning versions with the target framework is recommended, the current implementation doesn't use any .NET 8 specific features that would cause compatibility issues.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for DI usage patterns that might be affected rg "IServiceCollection|IServiceProvider|IHost" --type cs -A 2Length of output: 1080
Script:
#!/bin/bash # Search for DI setup and usage patterns rg "using Microsoft\.Extensions\.(DependencyInjection|Hosting)" --type cs -A 3 # Search for common DI patterns rg "AddSingleton|AddScoped|AddTransient|BuildServiceProvider|CreateDefaultBuilder|ConfigureServices" --type cs -A 3Length of output: 1767
Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
Show resolved
Hide resolved
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Flow.Launcher.Infrastructure/StringMatcher.cs
(3 hunks)
🔇 Additional comments (2)
Flow.Launcher.Infrastructure/StringMatcher.cs (2)
11-11
: LGTM!The use of target-typed
new()
expression improves code conciseness while maintaining readability.
Line range hint
254-268
: LGTM!The implementation of
CalculateClosestSpaceIndex
is correct and the change to static is appropriate as it doesn't use instance state.
This comment has been minimized.
This comment has been minimized.
This reverts commit ff110b3.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
Flow.Launcher.Infrastructure/StringMatcher.cs (2)
17-26
: 🛠️ Refactor suggestionConsider using constructor injection instead of service locator pattern.
The current implementation uses the service locator pattern which is generally considered an anti-pattern. While the test constructor provides a workaround, it would be better to use constructor injection consistently.
-public StringMatcher() -{ - _alphabet = Ioc.Default.GetRequiredService<IAlphabet>(); -} - -// This is a workaround to allow unit tests to set the instance -public StringMatcher(IAlphabet alphabet) -{ - _alphabet = alphabet; -} +public StringMatcher(IAlphabet alphabet) +{ + _alphabet = alphabet ?? throw new ArgumentNullException(nameof(alphabet)); +}
256-257
:⚠️ Potential issueFix numeric character comparison in IsAcronymNumber.
The current implementation incorrectly compares character codes with integers.
-private static bool IsAcronymNumber(string stringToCompare, int compareStringIndex) - => stringToCompare[compareStringIndex] >= 0 && stringToCompare[compareStringIndex] <= 9; +private static bool IsAcronymNumber(string stringToCompare, int compareStringIndex) + => char.IsDigit(stringToCompare[compareStringIndex]);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
Flow.Launcher.Infrastructure/StringMatcher.cs
(3 hunks)Flow.Launcher.Test/FuzzyMatcherTest.cs
(11 hunks)
🔇 Additional comments (2)
Flow.Launcher.Infrastructure/StringMatcher.cs (2)
251-254
: LGTM! Good static method refactoring.The change to make IsAcronymChar static is appropriate as it doesn't depend on instance state.
Line range hint
260-274
: LGTM! Good static method refactoring.The change to make CalculateClosestSpaceIndex static is appropriate as it doesn't depend on instance state.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (8)
Flow.Launcher/ViewModel/SettingWindowViewModel.cs (1)
7-21
: Consider a more gradual transition to proper DI.While the current changes introduce dependency injection, they rely on the service locator pattern which can make the code harder to test and maintain. Consider these steps for a cleaner DI implementation:
- Create an interface for Settings management
- Use constructor injection instead of
Ioc.Default
- Register dependencies at composition root
- Update tests to use mocked dependencies
This will improve testability while maintaining backward compatibility with existing code.
Flow.Launcher/PublicAPIInstance.cs (1)
50-55
: Consider restructuring to avoid circular dependenciesThe need for a separate
Initialize
method to avoid recursive dependency injection suggests a potential architectural issue. Consider:
- Breaking the circular dependency by extracting a common interface
- Using an event-based approach
- Implementing a mediator pattern
This would eliminate the need for the two-phase initialization and make the dependencies more explicit.
Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs (1)
162-164
: Consider adding error handling for the update process.The update process could fail for various reasons (network issues, permissions, etc.). Consider wrapping the async call with try-catch and providing user feedback.
private void UpdateApp() { - _ = _updater.UpdateAppAsync(false); + try + { + _ = _updater.UpdateAppAsync(false); + } + catch (Exception ex) + { + Notification.Show( + InternationalizationManager.Instance.GetTranslation("updateError"), + ex.Message); + } }Flow.Launcher/SettingWindow.xaml.cs (2)
27-35
: Consider using constructor injection for dependenciesCurrently, dependencies are being resolved within the constructor using
Ioc.Default.GetRequiredService<T>()
, which follows the service locator pattern. This can make unit testing and maintenance more challenging. Consider injecting dependencies via constructor parameters to enhance testability and adhere to dependency injection best practices.
169-169
: Allow pages to resolve their own dependenciesPassing
_settings
,_updater
, and_portable
throughPaneData
couplesSettingWindow
tightly with its child pages. To improve modularity and leverage dependency injection fully, consider allowing each page to resolve its own dependencies from the IoC container.Flow.Launcher/CustomQueryHotkeySetting.xaml.cs (2)
18-22
: InjectIPublicAPI
for consistent dependency managementWith the shift towards dependency injection, consider injecting
IPublicAPI
into the constructor alongsideSettings
. This promotes consistency in dependency management and enhances testability by reducing reliance on the staticApp.API
.
63-63
: Avoid direct access toApp.API
for better testabilityAccessing
App.API
directly in theUpdateItem
method increases coupling and hinders unit testing. InjectingIPublicAPI
as a dependency would adhere to dependency injection principles and improve maintainability.Flow.Launcher/App.xaml.cs (1)
209-209
: Reuse the resolvedMainViewModel
instance
MainViewModel
is resolved multiple times usingIoc.Default.GetRequiredService<MainViewModel>()
. Storing the instance in a private field or property after the first resolution can improve performance and code readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
Flow.Launcher.Core/Updater.cs
(5 hunks)Flow.Launcher/App.xaml.cs
(5 hunks)Flow.Launcher/CustomQueryHotkeySetting.xaml.cs
(2 hunks)Flow.Launcher/PublicAPIInstance.cs
(4 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs
(2 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
(1 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
(4 hunks)Flow.Launcher/SettingWindow.xaml.cs
(5 hunks)Flow.Launcher/ViewModel/SettingWindowViewModel.cs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
- Flow.Launcher.Core/Updater.cs
🔇 Additional comments (6)
Flow.Launcher/ViewModel/SettingWindowViewModel.cs (2)
9-9
: Well-designed immutable Settings property!The use of the
init
accessor ensures Settings cannot be modified after initialization, which is a good practice for dependency injection.
20-21
: Clean and focused Save implementation!The simplified Save method properly delegates the responsibility to the Settings object, adhering to the Single Responsibility Principle.
Flow.Launcher/PublicAPIInstance.cs (3)
28-28
: LGTM! Using Microsoft's MVVM Toolkit for DIThe addition of CommunityToolkit.Mvvm.DependencyInjection aligns well with the PR's objective of introducing dependency injection.
42-47
: Consider using constructor injection over service locationUsing
Ioc.Default.GetRequiredService<T>()
within the constructor makes the code harder to test and maintain. Consider using constructor injection instead:-public PublicAPIInstance() +public PublicAPIInstance( + SettingWindowViewModel settingsVM, + MainViewModel mainVM) { - _settingsVM = Ioc.Default.GetRequiredService<SettingWindowViewModel>(); - _mainVM = Ioc.Default.GetRequiredService<MainViewModel>(); + _settingsVM = settingsVM; + _mainVM = mainVM; GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); }
114-117
: LGTM! Simplified window opening logicThe change to use
SingletonWindowOpener
reduces coupling and simplifies the method implementation.Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs (1)
163-163
: LGTM! Good progress on dependency injection.The removal of the direct
App.API
parameter aligns well with the PR's objective of implementing proper dependency injection. This change suggests that theUpdater
class now internally manages its API dependencies.Let's verify that the
Updater
class properly handles the API dependency:✅ Verification successful
Verified: API dependency properly managed through DI
The change to remove the
App.API
parameter fromUpdateAppAsync
is correct and consistent with the codebase. TheUpdater
class is properly managed through dependency injection, as evidenced by:
- All consumers obtain the
Updater
instance through DI- The method signature is consistently used across the codebase
- The IoC container properly manages the Updater registration
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for the Updater class implementation to verify API injection ast-grep --pattern 'class Updater { $$$ UpdateAppAsync($$$) { $$$ } $$$ }'Length of output: 88
Script:
#!/bin/bash # Find files containing Updater fd -t f "Updater" # Search for UpdateAppAsync method implementation rg "UpdateAppAsync" -A 5Length of output: 2645
Flow.Launcher/PublicAPIInstance.cs
Outdated
{ | ||
// We need to initialize Updater not in the constructor because we want to avoid | ||
// recrusive dependency injection | ||
_updater = Ioc.Default.GetRequiredService<Updater>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember this is one of the reason I forfeit DI before. Not elegant but maybe good enough.
@@ -145,7 +151,7 @@ private double WindowLeft() | |||
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); | |||
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); | |||
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); | |||
var left = (dip2.X - this.ActualWidth) / 2 + dip1.X; | |||
var left = (dip2.X - ActualWidth) / 2 + dip1.X; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You sure this is correct? I think it's very instance dependent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this
is only necessary under the occasions as follows:
Disambiguation:
If a local variable or parameter has the same name as a class property or field, you need this. to distinguish the instance member from the local scope.
Accessing the current instance explicitly:
When passing the current object as a parameter to a method or event handler.
So I think I can remove this
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I think I read it wrongly. Somehow when I read it I think I saw somewhere you add a static.
I will recheck later
Will this create conflict with #2774 ? |
@taooceros From my view, it will not cause any conflicts. PublicAPI instance is created before other instances. And messageboxEx api function should work. |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
Flow.Launcher/PublicAPIInstance.cs (2)
40-43
: 🛠️ Refactor suggestionConsider using constructor injection over service location.
Using
Ioc.Default.GetRequiredService<T>()
within the constructor makes the code harder to test and maintain. Consider using constructor injection instead:-public PublicAPIInstance() +public PublicAPIInstance( + SettingWindowViewModel settingsVM, + MainViewModel mainVM) { - _settingsVM = Ioc.Default.GetRequiredService<SettingWindowViewModel>(); - _mainVM = Ioc.Default.GetRequiredService<MainViewModel>(); + _settingsVM = settingsVM; + _mainVM = mainVM; GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); }
80-80
:⚠️ Potential issueImplement proper async/await handling for update checks.
The current implementation discards the Task with
_
, which could hide potential errors. Consider implementing proper error handling:-public void CheckForNewUpdate() => _ = Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync(false); +public async Task CheckForNewUpdate() +{ + try + { + await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync(false); + } + catch (Exception ex) + { + LogException(nameof(PublicAPIInstance), "Failed to check for updates", ex); + ShowMsgError("Update Check Failed", ex.Message); + } +}
🧹 Nitpick comments (2)
Flow.Launcher/App.xaml.cs (2)
58-70
: Consider reviewing service lifetime scopes.While the DI setup is well-structured, registering all services as singletons might not be appropriate for every component. Consider reviewing each service's lifecycle requirements:
- Stateful services might benefit from scoped or transient lifetimes
- Services that manage disposable resources might need special handling
Example services to review:
MainViewModel
- Could be scoped if it maintains window-specific stateStringMatcher
- Could be transient if it's stateful per operation
161-161
: Consider making update check interval configurable.While the DI usage is correct, the 5-hour interval for update checks is hardcoded. Consider moving this to configuration:
-var timer = new PeriodicTimer(TimeSpan.FromHours(5)); +var timer = new PeriodicTimer(TimeSpan.FromHours(_settings.UpdateCheckIntervalHours));Also applies to: 165-165
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
(1 hunks)Flow.Launcher/App.xaml.cs
(5 hunks)Flow.Launcher/PublicAPIInstance.cs
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
🔇 Additional comments (6)
Flow.Launcher/App.xaml.cs (3)
7-7
: LGTM! Good architectural improvement.The transition from concrete
PublicAPIInstance
toIPublicAPI
interface improves testability and follows dependency injection best practices. The necessary DI framework imports have been correctly added.Also applies to: 22-23, 30-30
73-78
: Review API initialization and service ordering.The initialization sequence of services is logical, but there are two concerns:
- The API initialization might involve downcasting to call
Initialize()
, which was flagged in a previous review- Consider making the initialization order explicit through a dedicated initialization service
Consider implementing an
IInitializable
interface:public interface IInitializable { void Initialize(); } public class InitializationService { private readonly IEnumerable<IInitializable> _initializables; public InitializationService(IEnumerable<IInitializable> initializables) { _initializables = initializables; } public void Initialize() { foreach (var initializable in _initializables) { initializable.Initialize(); } } }
104-105
: LGTM! Consistent DI usage.The changes correctly integrate DI for MainWindow creation and second instance handling, maintaining consistency with the new architecture.
Also applies to: 208-208
Flow.Launcher/PublicAPIInstance.cs (3)
28-28
: LGTM: Import added for dependency injection support.The addition of CommunityToolkit.Mvvm.DependencyInjection import aligns with the PR's objective of implementing dependency injection.
107-107
: LGTM: Improved window management.The change to use
SingletonWindowOpener
improves separation of concerns and aligns with the PR's dependency management goals.
87-87
:⚠️ Potential issueAdd proper error handling for image saving.
The current implementation discards the Task with
_
, which could hide potential errors. Consider implementing proper error handling:-_ = ImageLoader.Save(); +try +{ + await ImageLoader.Save(); +} +catch (Exception ex) +{ + LogException(nameof(PublicAPIInstance), "Failed to save images", ex); +}Likely invalid or redundant comment.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this 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
🧹 Nitpick comments (1)
Flow.Launcher/App.xaml.cs (1)
Line range hint
7-57
: Well-structured dependency injection implementation.The overall architectural changes are well-executed:
- Proper use of Microsoft.Extensions.Hosting for DI setup
- Consistent service registration pattern
- Clean transition from static access to DI
- Good separation of concerns
However, consider creating an
IFlowLauncherHost
interface to encapsulate the DI container setup, making it easier to modify the DI configuration in the future:public interface IFlowLauncherHost { void ConfigureServices(IServiceCollection services); IServiceProvider BuildServiceProvider(); } public class DefaultFlowLauncherHost : IFlowLauncherHost { private readonly Settings _settings; public DefaultFlowLauncherHost(Settings settings) { _settings = settings; } public void ConfigureServices(IServiceCollection services) { services .AddSingleton(_ => _settings) .AddSingleton<Updater>() .AddSingleton<Portable>() // ... other services } public IServiceProvider BuildServiceProvider() { var host = Host.CreateDefaultBuilder() .UseContentRoot(AppContext.BaseDirectory) .ConfigureServices(ConfigureServices) .Build(); return host.Services; } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Flow.Launcher/App.xaml.cs
(5 hunks)
🔇 Additional comments (3)
Flow.Launcher/App.xaml.cs (3)
30-34
: LGTM! Good architectural improvement.The change from
PublicAPIInstance
toIPublicAPI
improves the design by programming to an interface rather than an implementation. This change:
- Enhances testability through better abstraction
- Enables dependency injection
- Makes the code more maintainable
35-57
: LGTM! Well-structured dependency injection setup.Good implementation using Microsoft.Extensions.Hosting with proper service registration. The singleton scoping is appropriate for the registered services.
211-211
: LGTM! Proper use of dependency injection.The change correctly uses DI to resolve MainViewModel instance.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
Flow.Launcher.Infrastructure/Http/Http.cs (1)
Line range hint
39-47
: Reconsider the Proxy property's accessibility pattern.The current design with a public setter and private getter is unusual and could lead to confusion:
- Consumers can set the proxy but can't read its current state
- Makes it difficult to validate the proxy's state externally
- Violates encapsulation principles
Consider one of these alternatives:
- Make both getter and setter private and expose methods for proxy configuration:
-public static HttpProxy Proxy +private static HttpProxy Proxy { private get { return proxy; } - set + private set { proxy = value; proxy.PropertyChanged += UpdateProxy; UpdateProxy(ProxyProperty.Enabled); } } + +public static void ConfigureProxy(HttpProxy proxySettings) +{ + Proxy = proxySettings; +}
- Make the getter public but return an immutable copy:
public static HttpProxy Proxy { - private get { return proxy; } + get { return proxy.Clone(); } set { proxy = value; proxy.PropertyChanged += UpdateProxy; UpdateProxy(ProxyProperty.Enabled); } }
🧹 Nitpick comments (2)
Flow.Launcher.Infrastructure/Http/Http.cs (2)
21-21
: Move API initialization to static constructor to handle DI failures gracefully.Initializing the API property directly during declaration could throw if the IoC container isn't ready. Moving it to the static constructor would allow for proper error handling.
-private static IPublicAPI API { get; set; } = Ioc.Default.GetRequiredService<IPublicAPI>(); +private static IPublicAPI API { get; set; } static Http() { + try + { + API = Ioc.Default.GetRequiredService<IPublicAPI>(); + } + catch (Exception ex) + { + Log.Exception("Http", "Failed to initialize API", ex); + throw; + } + // existing constructor code... }
Line range hint
1-199
: Consider breaking down the Http class to improve testability and maintainability.The current static class design has several architectural concerns:
- Global state makes unit testing difficult
- Concurrent access to shared HttpClient instance could cause issues
- Mixing HTTP client operations with UI notifications (via API.ShowMsg)
Consider splitting this into multiple focused classes:
IHttpClientFactory
for managing HttpClient instancesIProxyConfiguration
for proxy managementIHttpService
for the actual HTTP operationsThis would:
- Make dependencies explicit
- Improve testability
- Allow for better separation of concerns
- Enable proper dependency injection
Would you like me to provide a detailed example of this architecture?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
Flow.Launcher.Core/Plugin/PluginManager.cs
(4 hunks)Flow.Launcher.Infrastructure/Http/Http.cs
(2 hunks)Flow.Launcher/App.xaml.cs
(5 hunks)
🔇 Additional comments (6)
Flow.Launcher/App.xaml.cs (3)
7-7
: LGTM: Good architectural improvement using dependency injection.The transition from concrete
PublicAPIInstance
toIPublicAPI
interface improves modularity and testability. The addition of Microsoft.Extensions.DependencyInjection and Hosting packages provides a robust DI framework.Also applies to: 22-23, 30-30
93-95
: Fix potential race condition with StringMatcher.Instance.The current implementation could lead to race conditions in a multi-threaded environment. Consider using thread-safe initialization or removing the static instance entirely.
164-168
: Make update checks cancellable.The update check task should be cancellable when the app exits to prevent potential memory leaks or hanging operations.
Flow.Launcher.Core/Plugin/PluginManager.cs (3)
162-162
: LGTM: Simplified method signature.Removing the
IPublicAPI
parameter and using the static property improves the API design by reducing unnecessary parameters.
522-522
: LGTM: Consistent message handling through API.Good change to use
API.ShowMsgBox
instead of direct message box calls, maintaining consistency with the new dependency injection pattern.
32-32
: Verify thread-safety of API property initialization.The static property initialization using DI could lead to race conditions if accessed from multiple threads during startup.
@check-spelling-bot Report🔴 Please reviewSee the 📂 files view, the 📜action log, or 📝 job summary for details.
See ❌ Event descriptions for more information. If the flagged items are 🤯 false positivesIf items relate to a ...
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
Flow.Launcher.Infrastructure/Http/Http.cs (1)
11-11
: 🛠️ Refactor suggestionConsider using constructor-based dependency injection instead of static IoC resolution.
The current implementation using
Ioc.Default.GetRequiredService<IPublicAPI>()
maintains tight coupling to the IoC container and makes the code harder to test.This was previously highlighted in an earlier review. The recommendation to make the class non-static and use constructor injection still stands:
-public static class Http -{ +public class Http : IHttp +{ + private readonly IPublicAPI _api; + + public Http(IPublicAPI api) + { + _api = api; + }Also applies to: 80-80
🧹 Nitpick comments (2)
Flow.Launcher.Infrastructure/Http/Http.cs (2)
80-82
: Enhance error handling with more specific information.The current error messages could be more helpful:
- The user message "Please try again" doesn't guide the user on what to correct
- The log message "Unable to parse Uri" could include the attempted proxy values
Consider this improvement:
-Ioc.Default.GetRequiredService<IPublicAPI>().ShowMsg("Please try again", "Unable to parse Http Proxy"); -Log.Exception("Flow.Launcher.Infrastructure.Http", "Unable to parse Uri", e); +var errorDetails = $"Invalid proxy configuration - Server: {Proxy.Server}, Port: {Proxy.Port}"; +Ioc.Default.GetRequiredService<IPublicAPI>().ShowMsg( + "Please check your proxy server and port values", + "Invalid Proxy Configuration"); +Log.Exception("Flow.Launcher.Infrastructure.Http", errorDetails, e);
Line range hint
39-39
: Consider making WebProxy property internal or private.The public
WebProxy
property allows external modification of proxy settings, which could lead to inconsistent state. Consider encapsulating this implementation detail.-public static WebProxy WebProxy { get; } = new WebProxy(); +internal static WebProxy WebProxy { get; } = new WebProxy();
Introduce dependency injection for accessing the
API
property in anywhere inside the project.This can improve development experience. E.g. We can put the
MessgaeBoxEx
toFlow.Launcher
project and we can access the design page like this: