Places Linux, refactor

This commit is contained in:
2022-05-28 23:38:56 +02:00
parent fbf36b890b
commit 74a8f66db1
6 changed files with 159 additions and 18 deletions

View File

@@ -0,0 +1,14 @@
namespace FileTime.GuiApp.IconProviders;
public enum SpecialPathType
{
Home,
Downloads,
Music,
Videos,
Desktop,
Documents,
Images,
Templates,
PublicShare
}

View File

@@ -0,0 +1,9 @@
using FileTime.App.Core.Services;
using FileTime.GuiApp.IconProviders;
namespace FileTime.GuiApp.Services;
public interface IPlacesService : IStartupHandler
{
Dictionary<string, SpecialPathType> GetSpecialPaths();
}

View File

@@ -45,16 +45,20 @@ public static class Startup
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
serviceCollection.AddSingleton<IContextMenuProvider, WindowsContextMenuProvider>(); serviceCollection
.AddSingleton<IContextMenuProvider, WindowsContextMenuProvider>()
.AddSingleton<IPlacesService, WindowsPlacesService>();
} }
else else
{ {
serviceCollection.AddSingleton<IContextMenuProvider, LinuxContextMenuProvider>(); serviceCollection
.AddSingleton<IContextMenuProvider, LinuxContextMenuProvider>()
.AddSingleton<IPlacesService, LinuxPlacesService>();
} }
return serviceCollection return serviceCollection
.AddSingleton<IStartupHandler, RootDriveInfoService>() .AddSingleton<IStartupHandler, RootDriveInfoService>()
.AddSingleton<IStartupHandler, PlacesService>(); .AddSingleton<IStartupHandler>(sp => sp.GetRequiredService<IPlacesService>());
} }
internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection) internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection)

View File

@@ -1,8 +1,8 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.GuiApp.Models; using FileTime.GuiApp.Models;
using FileTime.GuiApp.Services;
using FileTime.Providers.Local; using FileTime.Providers.Local;
using Syroot.Windows.IO;
namespace FileTime.GuiApp.IconProviders; namespace FileTime.GuiApp.IconProviders;
@@ -11,7 +11,7 @@ public class MaterialIconProvider : IIconProvider
private static readonly Dictionary<string, string> _iconsByExtension = new(); private static readonly Dictionary<string, string> _iconsByExtension = new();
private static readonly Dictionary<string, string> _iconsByFileName = new(); private static readonly Dictionary<string, string> _iconsByFileName = new();
private readonly List<SpecialPathWithIcon> _specialPaths = new(); private readonly Lazy<List<SpecialPathWithIcon>> _specialPaths;
public bool EnableAdvancedIcons { get; set; } = true; public bool EnableAdvancedIcons { get; set; } = true;
static MaterialIconProvider() static MaterialIconProvider()
@@ -19,17 +19,18 @@ public class MaterialIconProvider : IIconProvider
InitMatches(); InitMatches();
} }
public MaterialIconProvider() public MaterialIconProvider(IPlacesService placesService)
{ {
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return; _specialPaths = new Lazy<List<SpecialPathWithIcon>>(() =>
{
var result = new List<SpecialPathWithIcon>();
foreach (var kvp in placesService.GetSpecialPaths())
{
result.Add(new SpecialPathWithIcon(kvp.Key, GetAssetPath(GetSpecialPathIcon(kvp.Value))));
}
_specialPaths.Add(new SpecialPathWithIcon(KnownFolders.Desktop.Path, GetAssetPath("desktop.svg"))); return result;
_specialPaths.Add(new SpecialPathWithIcon(KnownFolders.Documents.Path, GetAssetPath("folder-resource.svg"))); });
_specialPaths.Add(new SpecialPathWithIcon(KnownFolders.DownloadsLocalized.Path, GetAssetPath("folder-download.svg")));
_specialPaths.Add(new SpecialPathWithIcon(KnownFolders.MusicLocalized.Path, GetAssetPath("folder-music.svg")));
_specialPaths.Add(new SpecialPathWithIcon(KnownFolders.Pictures.Path, GetAssetPath("folder-images.svg")));
_specialPaths.Add(new SpecialPathWithIcon(KnownFolders.Profile.Path, GetAssetPath("folder-home.svg")));
_specialPaths.Add(new SpecialPathWithIcon(KnownFolders.Videos.Path, GetAssetPath("folder-video.svg")));
} }
public ImagePath GetImage(IItem item) public ImagePath GetImage(IItem item)
@@ -40,7 +41,7 @@ public class MaterialIconProvider : IIconProvider
if (!EnableAdvancedIcons) return GetAssetPath(icon); if (!EnableAdvancedIcons) return GetAssetPath(icon);
if (localPath != null && _specialPaths.Find(p => p.Path == localPath) is SpecialPathWithIcon specialPath) if (localPath != null && _specialPaths.Value.Find(p => p.Path == localPath) is SpecialPathWithIcon specialPath)
{ {
return specialPath.IconPath; return specialPath.IconPath;
} }
@@ -67,6 +68,21 @@ public class MaterialIconProvider : IIconProvider
return GetAssetPath(icon); return GetAssetPath(icon);
} }
private string GetSpecialPathIcon(SpecialPathType pathType)
=> pathType switch
{
SpecialPathType.Desktop => "desktop.svg",
SpecialPathType.Documents => "folder-resource.svg",
SpecialPathType.Downloads => "folder-download.svg",
SpecialPathType.Music => "folder-music.svg",
SpecialPathType.Images => "folder-images.svg",
SpecialPathType.Home => "folder-home.svg",
SpecialPathType.Videos => "folder-video.svg",
SpecialPathType.Templates => "folder-resource.svg",
SpecialPathType.PublicShare => "folder-resource.svg",
_ => throw new NotImplementedException()
};
private static ImagePath GetAssetPath(string iconName) private static ImagePath GetAssetPath(string iconName)
{ {
return new ImagePath(ImagePathType.Asset, "/Assets/material/" + iconName); return new ImagePath(ImagePathType.Asset, "/Assets/material/" + iconName);

View File

@@ -0,0 +1,85 @@
using System.Collections;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using FileTime.GuiApp.IconProviders;
using FileTime.GuiApp.ViewModels;
using FileTime.Providers.Local;
namespace FileTime.GuiApp.Services;
public class LinuxPlacesService : IPlacesService
{
private readonly ILocalContentProvider _localContentProvider;
private readonly IGuiAppState _guiAppState;
private readonly Dictionary<string, SpecialPathType> _specialPath = new();
public LinuxPlacesService(
ILocalContentProvider localContentProvider,
IGuiAppState guiAppState)
{
_localContentProvider = localContentProvider;
_guiAppState = guiAppState;
}
public async Task InitAsync()
{
var placeKeys = new Dictionary<string, SpecialPathType>
{
{"XDG_DESKTOP_DIR", SpecialPathType.Desktop},
{"XDG_DOWNLOAD_DIR", SpecialPathType.Downloads},
{"XDG_TEMPLATES_DIR", SpecialPathType.Templates},
{"XDG_PUBLICSHARE_DIR", SpecialPathType.PublicShare},
{"XDG_DOCUMENTS_DIR", SpecialPathType.Documents},
{"XDG_MUSIC_DIR", SpecialPathType.Music},
{"XDG_PICTURES_DIR", SpecialPathType.Images},
{"XDG_VIDEOS_DIR", SpecialPathType.Videos},
};
var homeFolder = Environment.GetEnvironmentVariable("HOME");
if (homeFolder is null) return;
var userDirsLines = await File.ReadAllLinesAsync(Path.Combine(homeFolder, ".config", "user-dirs.dirs"));
var placesStrings = placeKeys
.Select(p => (SpecialPath: p.Value, Line: userDirsLines.FirstOrDefault(l => l.StartsWith(p.Key))))
.Where(l => l.Line is not null)
.Select(l => (l.SpecialPath, Path: l.Line![(l.Line.IndexOf('=') + 1)..].Trim('\"')))
.Select(l => (l.SpecialPath, Path: ReplaceEnvVars(l.Path)))
.Where(l => Directory.Exists(l.Path))
.ToList();
var places = new List<PlaceInfo>();
foreach (var place in placesStrings)
{
var resolvedPlace = await _localContentProvider.GetItemByNativePathAsync(new NativePath(place.Path), PointInTime.Present);
if (resolvedPlace is not IContainer resolvedContainer) continue;
places.Add(new PlaceInfo(resolvedContainer, resolvedContainer.DisplayName));
_specialPath.Add(place.Path, place.SpecialPath);
}
var resolvedHomeItem = await _localContentProvider.GetItemByNativePathAsync(new NativePath(homeFolder), PointInTime.Present);
IEnumerable<PlaceInfo> finalPlaces = places.OrderBy(p => p.DisplayName);
if (resolvedHomeItem is IContainer resolvedHomeFolder)
{
finalPlaces = finalPlaces.Prepend(new PlaceInfo(resolvedHomeFolder, resolvedHomeFolder.DisplayName));
_specialPath.Add(homeFolder, SpecialPathType.Home);
}
_guiAppState.Places = finalPlaces.ToList().AsReadOnly();
}
private string ReplaceEnvVars(string s)
{
return Environment
.GetEnvironmentVariables()
.Cast<DictionaryEntry>()
.Select(d => new KeyValuePair<string, string>(d.Key.ToString()!, d.Value!.ToString()!))
.Aggregate(s, (c, kvp) => c.Replace("$" + kvp.Key, kvp.Value));
}
public Dictionary<string, SpecialPathType> GetSpecialPaths() => _specialPath;
}

View File

@@ -2,18 +2,19 @@ using System.Runtime.InteropServices;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
using FileTime.GuiApp.IconProviders;
using FileTime.GuiApp.ViewModels; using FileTime.GuiApp.ViewModels;
using FileTime.Providers.Local; using FileTime.Providers.Local;
using Syroot.Windows.IO; using Syroot.Windows.IO;
namespace FileTime.GuiApp.Services; namespace FileTime.GuiApp.Services;
public class PlacesService : IStartupHandler public class WindowsPlacesService : IPlacesService
{ {
private readonly ILocalContentProvider _localContentProvider; private readonly ILocalContentProvider _localContentProvider;
private readonly IGuiAppState _guiAppState; private readonly IGuiAppState _guiAppState;
public PlacesService( public WindowsPlacesService(
ILocalContentProvider localContentProvider, ILocalContentProvider localContentProvider,
IGuiAppState guiAppState) IGuiAppState guiAppState)
{ {
@@ -49,4 +50,16 @@ public class PlacesService : IStartupHandler
_guiAppState.Places = places.AsReadOnly(); _guiAppState.Places = places.AsReadOnly();
} }
public Dictionary<string, SpecialPathType> GetSpecialPaths()
=> new Dictionary<string, SpecialPathType>
{
{KnownFolders.Desktop.Path, SpecialPathType.Desktop},
{KnownFolders.Documents.Path, SpecialPathType.Documents},
{KnownFolders.DownloadsLocalized.Path, SpecialPathType.Downloads},
{KnownFolders.MusicLocalized.Path, SpecialPathType.Music},
{KnownFolders.Pictures.Path, SpecialPathType.Images},
{KnownFolders.Profile.Path, SpecialPathType.Home},
{KnownFolders.Videos.Path, SpecialPathType.Videos},
};
} }