Reloadable configuration, FontService (WIP)

This commit is contained in:
2023-02-22 16:50:50 +01:00
parent d6022ee02c
commit 3db5945cfd
18 changed files with 166 additions and 41 deletions

View File

@@ -103,28 +103,13 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
{
await (command.PasteMode switch
{
PasteMode.Merge => PasteMerge(),
PasteMode.Overwrite => PasteOverwrite(),
PasteMode.Skip => PasteSkip(),
PasteMode.Merge => Paste(TransportMode.Merge),
PasteMode.Overwrite => Paste(TransportMode.Overwrite),
PasteMode.Skip => Paste(TransportMode.Skip),
_ => throw new ArgumentException($"Unknown {nameof(PasteMode)} value: {command.PasteMode}")
});
}
private async Task PasteMerge()
{
await Paste(TransportMode.Merge);
}
private async Task PasteOverwrite()
{
await Paste(TransportMode.Overwrite);
}
private async Task PasteSkip()
{
await Paste(TransportMode.Skip);
}
private async Task Paste(TransportMode mode)
{
if (_clipboardService.CommandType is null)

View File

@@ -59,6 +59,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.Core.ContentAccess
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.Core.CommandHandlers", "Core\FileTime.Core.CommandHandlers\FileTime.Core.CommandHandlers.csproj", "{9B161766-A672-4D59-B591-C68907905158}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.GuiApp.Font", "GuiApp\Avalonia\FileTime.GuiApp.Font\FileTime.GuiApp.Font.csproj", "{767F3868-11D0-445D-9B86-F81C7FCEB6FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.GuiApp.Font.Abstractions", "GuiApp\Avalonia\FileTime.GuiApp.Font.Abstractions\FileTime.GuiApp.Font.Abstractions.csproj", "{2D07F149-106B-4644-9586-D6218F78D868}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -145,6 +149,14 @@ Global
{9B161766-A672-4D59-B591-C68907905158}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B161766-A672-4D59-B591-C68907905158}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B161766-A672-4D59-B591-C68907905158}.Release|Any CPU.Build.0 = Release|Any CPU
{767F3868-11D0-445D-9B86-F81C7FCEB6FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{767F3868-11D0-445D-9B86-F81C7FCEB6FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{767F3868-11D0-445D-9B86-F81C7FCEB6FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{767F3868-11D0-445D-9B86-F81C7FCEB6FA}.Release|Any CPU.Build.0 = Release|Any CPU
{2D07F149-106B-4644-9586-D6218F78D868}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D07F149-106B-4644-9586-D6218F78D868}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D07F149-106B-4644-9586-D6218F78D868}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D07F149-106B-4644-9586-D6218F78D868}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -171,6 +183,8 @@ Global
{2AC5CAFF-EBDA-4C6E-BCFF-304B651F2906} = {3324D046-1E05-46B5-B1BA-82910D56B332}
{88BBB541-7306-44AE-95B1-0F8765AF1D4E} = {3324D046-1E05-46B5-B1BA-82910D56B332}
{9B161766-A672-4D59-B591-C68907905158} = {3324D046-1E05-46B5-B1BA-82910D56B332}
{767F3868-11D0-445D-9B86-F81C7FCEB6FA} = {01F231DE-4A65-435F-B4BB-77EE5221890C}
{2D07F149-106B-4644-9586-D6218F78D868} = {01F231DE-4A65-435F-B4BB-77EE5221890C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF}

View File

@@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia" Version="11.0.0-preview5" />
<PackageReference Include="PropertyChanged.SourceGenerator" Version="1.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -2,6 +2,7 @@ using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using FileTime.App.DependencyInjection;
using FileTime.GuiApp.Font;
using FileTime.GuiApp.ViewModels;
using FileTime.GuiApp.Views;
using Microsoft.Extensions.DependencyInjection;
@@ -13,9 +14,11 @@ public partial class App : Application
{
static App()
{
DI.ServiceProvider ??= DependencyInjection
var configuration = Startup.CreateConfiguration();
DI.ServiceProvider = DependencyInjection
.RegisterDefaultServices()
.AddConfiguration()
.AddConfiguration(configuration)
.ConfigureFont(configuration)
.RegisterLogging()
.RegisterServices()
.AddViewModels()

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0</TargetFramework>
@@ -25,11 +25,11 @@
<TrimmableAssembly Include="Avalonia.Themes.Default" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia" Version="11.0.0-preview5" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview5" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview4" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview5" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
@@ -42,6 +42,7 @@
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.DependencyInjection\FileTime.App.DependencyInjection.csproj" />
<ProjectReference Include="..\FileTime.GuiApp.CustomImpl\FileTime.GuiApp.CustomImpl.csproj" />
<ProjectReference Include="..\FileTime.GuiApp.Font\FileTime.GuiApp.Font.csproj" />
<ProjectReference Include="..\FileTime.GuiApp\FileTime.GuiApp.csproj" />
</ItemGroup>

View File

@@ -20,6 +20,25 @@ namespace FileTime.GuiApp.App;
public static class Startup
{
internal static IConfigurationRoot CreateConfiguration()
{
var configurationBuilder = new ConfigurationBuilder()
.AddInMemoryCollection(MainConfiguration.Configuration)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true);
var configurationDirectory = new DirectoryInfo(Path.Combine(Program.AppDataRoot, "config"));
if (configurationDirectory.Exists)
{
foreach (var settingsFile in configurationDirectory.GetFiles("*.json"))
{
configurationBuilder.AddJsonFile(settingsFile.FullName, optional: true, reloadOnChange: true);
}
}
return configurationBuilder.Build();
}
internal static IServiceCollection AddViewModels(this IServiceCollection serviceCollection)
{
serviceCollection.TryAddSingleton<MainWindowViewModel>();
@@ -69,14 +88,8 @@ public static class Startup
);
}
internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection)
internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection, IConfigurationRoot configuration)
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(MainConfiguration.Configuration)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true)
.Build();
return serviceCollection
.Configure<ProgramsConfiguration>(configuration.GetSection(SectionNames.ProgramsSectionName))
.Configure<KeyBindingConfiguration>(configuration.GetSection(SectionNames.KeybindingSectionName))

View File

@@ -0,0 +1,9 @@
namespace FileTime.GuiApp.Configuration;
public class FontConfiguration
{
public const string SectionName = "Font";
public List<string> Main { get; set; } = new();
public List<string> DateTime { get; set; } = new();
}

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>FileTime.GuiApp</RootNamespace>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,7 @@
namespace FileTime.GuiApp.Services;
public interface IFontService
{
IObservable<string?> MainFont { get; }
string? GetMainFont();
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>FileTime.GuiApp</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FileTime.GuiApp.Font.Abstractions\FileTime.GuiApp.Font.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview5" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,16 @@
using FileTime.GuiApp.Configuration;
using FileTime.GuiApp.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.GuiApp.Font;
public static class Startup
{
public static IServiceCollection ConfigureFont(this IServiceCollection services, IConfigurationRoot configurationRoot)
{
services.Configure<FontConfiguration>(configurationRoot.GetSection(FontConfiguration.SectionName));
services.AddSingleton<IFontService, FontService>();
return services;
}
}

View File

@@ -0,0 +1,34 @@
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Avalonia.Media;
using FileTime.GuiApp.Configuration;
using Microsoft.Extensions.Options;
namespace FileTime.GuiApp.Services;
public class FontService : IFontService
{
private readonly IOptionsMonitor<FontConfiguration> _fontConfiguration;
private readonly BehaviorSubject<string?> _mainFont = new(null);
public IObservable<string?> MainFont => _mainFont.DistinctUntilChanged();
public FontService(IOptionsMonitor<FontConfiguration> fontConfiguration)
{
_fontConfiguration = fontConfiguration;
fontConfiguration.OnChange(UpdateFonts);
UpdateFonts(fontConfiguration.CurrentValue, null);
}
private void UpdateFonts(FontConfiguration newConfiguration, string? arg2)
{
_mainFont.OnNext(GetMainFont());
}
public string? GetMainFont()
{
var installedFonts = FontManager.Current.GetInstalledFontFamilyNames().ToList();
return _fontConfiguration.CurrentValue.Main.FirstOrDefault(f => installedFonts.Contains(f));
}
}

View File

@@ -19,13 +19,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia" Version="11.0.0-preview5" />
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.0.0-preview5" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview5" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia.Svg.Skia" Version="11.0.0-preview4" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-preview4" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview5" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview5" />
<PackageReference Include="Avalonia.Svg.Skia" Version="11.0.0-preview5" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-preview5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="MvvmGen" Version="1.1.5" />
@@ -40,6 +41,7 @@
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
<ProjectReference Include="..\..\..\Providers\FileTime.Providers.Local.Abstractions\FileTime.Providers.Local.Abstractions.csproj" />
<ProjectReference Include="..\FileTime.GuiApp.Abstractions\FileTime.GuiApp.Abstractions.csproj" />
<ProjectReference Include="..\FileTime.GuiApp.Font.Abstractions\FileTime.GuiApp.Font.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@@ -9,7 +9,7 @@
</ResourceDictionary>
</Styles.Resources>
<FluentTheme Mode="Dark" />
<FluentTheme />
<Style Selector="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource ForegroundBrush}" />

View File

@@ -3,4 +3,5 @@ namespace FileTime.GuiApp.ViewModels;
public interface IMainWindowViewModelBase
{
bool Loading { get; }
IObservable<string?> MainFont { get; }
}

View File

@@ -1,6 +1,9 @@
using System.Reactive.Subjects;
namespace FileTime.GuiApp.ViewModels;
public class MainWindowLoadingViewModel : IMainWindowViewModelBase
{
public bool Loading => true;
public IObservable<string?> MainFont { get; } = new BehaviorSubject<string?>("");
}

View File

@@ -9,6 +9,7 @@ using FileTime.Core.Timeline;
using FileTime.GuiApp.Services;
using FileTime.Providers.Local;
using InitableService;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MvvmGen;
@@ -26,9 +27,11 @@ namespace FileTime.GuiApp.ViewModels;
[Inject(typeof(IItemPreviewService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(IDialogService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(ITimelessContentProvider), PropertyName = "_timelessContentProvider")]
[Inject(typeof(IFontService), "_fontService")]
public partial class MainWindowViewModel : IMainWindowViewModelBase
{
public bool Loading => false;
public IObservable<string?> MainFont => _fontService.MainFont;
public IGuiAppState AppState => _appState;
public string Title { get; private set; }

View File

@@ -20,9 +20,11 @@
Background="Transparent"
Closed="OnWindowClosed"
ExtendClientAreaToDecorationsHint="True"
FontFamily="{Binding MainFont^, Mode=OneWay}"
Icon="/Assets/filetime.ico"
InputElement.KeyDown="OnKeyDown"
KeyDown="OnKeyDown"
Opened="OnWindowOpened"
RequestedThemeVariant="Dark"
TransparencyLevelHint="Blur"
mc:Ignorable="d">
<Window.Resources>