-
Notifications
You must be signed in to change notification settings - Fork 45
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
added support for shell icons for files on Windows #63
Conversation
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.
Hey @iksi4prs ! Thanks for your PR. Please see my file specific comments below. Some general comments here:
- Please make sure you follow current code formatting for consistency
- Please add tests where possible/exclude some classes from tests coverage if needed
private readonly IconsSettingsModel _builtin; | ||
private readonly IUnitOfWorkFactory _unitOfWorkFactory; | ||
private readonly Platform _platform; | ||
private IconsSettingsModel _cachedValue = null; |
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.
We don't really need to cache values here because calling DB is rare and doesn't take too much time
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.
every time we draw an icon for a file, we need to check if to use shell-icon or bulit-in, so this value should be kept somewhere, no point in checking db every time
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.
Please see my comment about loading it on startup
|
||
public IconsSettingsModel GetIconsSettings() | ||
{ | ||
if (_platform != Platform.Windows) |
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 would recommend to avoid platform-specific code here. Just allow to read/save as usual. See my comment regarding settings for more info
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 kept this as lower level possible, so implementers of feature for linux/mac, will have less to do.
@@ -30,15 +31,18 @@ public int SelectedIndex | |||
|
|||
public SettingsDialogViewModel( | |||
ISettingsViewModel generalSettingsViewModel, | |||
ISettingsViewModel terminalSettingsViewModel) | |||
ISettingsViewModel terminalSettingsViewModel, | |||
ISettingsViewModel iconsSettingsViewModel) |
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.
Let's simply don't show icon VM for non-windows environments.
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.
As I wrote before, I kept this as lower level possible, so implementers of feature for linux/mac, will have less to do.
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.
ok, if Linux/Mac PRs are incoming I'm ok with keeping it as is
private long _size; | ||
private Bitmap _shellIcon = null; |
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.
= null
is redundant
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.
Habit. used to newer projects with Bitmap?.
|
||
private IconsType GetUserSelectedType() | ||
{ | ||
var model = _iconsSettingsService.GetIconsSettings(); |
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'm ok with settings applying only after restart so I think we can just inject this value from factory (where we can read it once) instead of doing this call every time
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.
As a user, very confusing. I applied the theme, and didn't understand why nothing happens.
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.
True but it's a tradeoff between code complexity and functionality. In the future I'm planning to add automatic restart to avoid that issue. Loading and storing this value on start saves us a lot of effort of loading it during runtime
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 think Avalonia v11 has different way of handling theme, that support it (at least for themes)
|
||
namespace Camelot.Services.AllPlatforms; | ||
|
||
public class ShellIconsCacheService : IShellIconsCacheService |
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 think we should leave "Cache" part of the name for this class out because we don't really want to expose to consumers such details as using cache internally. It seems that we use ShellIconsService
only here so moving all code to the same file sounds fine to me
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.
ShellIconsService is per platform, just asking platform for icon, based on file extension or application.
ShellIconsCacheService is higher level, shared to all platform, that checks if it already has icon for extension.
eg for file1.txt and file2.txt, ShellIconsCacheService will call ShellIconsService only on 1st time.
on 2nd time, it will use cache, as it already has icon for ".txt".
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 got the idea but I don't like the naming, we should not let consumers of this class know that there is some cache being used. I recommend to implement this caching logic as a decorator or put it in some base class and for platforms just add some platform-specific implementation
{ | ||
private readonly IShellLinksService _shellLinksService; | ||
private readonly IShellIconsService _shellIconsService; | ||
private readonly Dictionary<string, Bitmap> _cache = new(); |
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.
What happens if the cache grows too large? Should we enforce some size limits?
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.
Good question. Cache is limited to number of extensions and apps.
I guess for normal user, if he has 30 extensions and some 100 apps, then it will not grow more than 150-200 icons.
But its a good idea to add some limit.
{ | ||
case IShellIconsService.ShellIconType.Extension: | ||
{ | ||
var ext = Path.GetExtension(path); |
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.
Please use IPathService
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.
Will do.
|
||
namespace Camelot.Services.Abstractions; | ||
|
||
public interface IShellIconsService |
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.
These class & interface should be merged with IShellService
with some methods being private
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.
see notes before about IShellIconsService as per platform.
src/Camelot.Images/ConcreteImage.cs
Outdated
|
||
public class ConcreteImage : ImageModel | ||
{ | ||
public Bitmap Bitmap { get; } |
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.
Is there a way to follow one of approaches mentioned here? https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/system-drawing-common-windows-only Current solution looks hacky. Alternative approach would be to get rid of Camelot.Images
and create separate projects for platform specific stuff instead of touching services/abstractions projects that designed for a business logic and not UI stuff
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.
This is the trickiest thing on this PR.
I understand the separation of logic and UI.
But here, I think although its "image", it is part of business logic.
At first I thought as a solution to use Skia, or something like that, but it is actually not necessary.
Avalonia provides all that is necessary, just need some Image class in the abstractions layer.
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 see. My recommendation is:
- Create
Camelot.UI.AllPlatforms
and corresponding platform specific projects if needed - Move this logic there.
Services
was designed for a business logic and not rendering stuff. Feel free to use Avalonia in new projects instead. It's totally ok to have a different logic for rendering on different platforms (surprisingly it didn't happen before). Camelot.Images
can be removed in this case and all casts won't be necessary anymore
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.
a. "Create Camelot.UI.AllPlatforms" - can u send picture when do u want it in solution ?
b. "Move this logic there" - do u mean all the icons services ?
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 will actually try to build and push this change today in the evening
Codecov ReportAttention:
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## master #63 +/- ##
==========================================
- Coverage 97.68% 92.89% -4.79%
==========================================
Files 177 185 +8
Lines 4619 4830 +211
Branches 0 388 +388
==========================================
- Hits 4512 4487 -25
- Misses 107 288 +181
- Partials 0 55 +55
☔ View full report in Codecov by Sentry. |
Pushed some changes to avoid casts, unfortunately tests are still broken. Next step will be to address tests and do refactoring |
Fixed tests in the follow up commit. So just refactoring/addressing PR comments is left |
return true; // icon in indexed resource | ||
|
||
var ext = Path.GetExtension(filename).ToLower(); | ||
var extensionsOfIcoFiles = new List<string>() { ".ico", ".exe", ".dll" , ".cpl", ".appref-ms", ".msc" }; |
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 suspect that this list should be in sync with WindowsShellIconsService
and this code might be refactored to avoid this class creation at all
Thanks, merged! |
Support for shell icons for files on Windows.
See attached images.