diff --git a/src/Files.App/App.xaml.cs b/src/Files.App/App.xaml.cs index 58fbb26f2cac..1bdeed3773c4 100644 --- a/src/Files.App/App.xaml.cs +++ b/src/Files.App/App.xaml.cs @@ -136,10 +136,10 @@ private IHost ConfigureHost() .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/Files.App/Dialogs/AddBranchDialog.xaml b/src/Files.App/Dialogs/AddBranchDialog.xaml index b79572979456..fcc6f995e379 100644 --- a/src/Files.App/Dialogs/AddBranchDialog.xaml +++ b/src/Files.App/Dialogs/AddBranchDialog.xaml @@ -10,11 +10,12 @@ Title="{helpers:ResourceString Name=CreateNewBranch}" Closing="ContentDialog_Closing" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="Primary" IsPrimaryButtonEnabled="{x:Bind ViewModel.IsBranchValid, Mode=OneWay}" PrimaryButtonStyle="{StaticResource AccentButtonStyle}" PrimaryButtonText="{helpers:ResourceString Name=Create}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonText="{helpers:ResourceString Name=Cancel}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/AddBranchDialog.xaml.cs b/src/Files.App/Dialogs/AddBranchDialog.xaml.cs index 8d4039816398..6794616ecd0a 100644 --- a/src/Files.App/Dialogs/AddBranchDialog.xaml.cs +++ b/src/Files.App/Dialogs/AddBranchDialog.xaml.cs @@ -2,17 +2,19 @@ // Licensed under the MIT License. See the LICENSE. using Files.App.ViewModels.Dialogs; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; namespace Files.App.Dialogs { public sealed partial class AddBranchDialog : ContentDialog, IDialog { - public AddBranchDialogViewModel ViewModel - { - get => (AddBranchDialogViewModel)DataContext; - set => DataContext = value; - } + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public AddBranchDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public AddBranchDialog() { diff --git a/src/Files.App/Dialogs/AddItemDialog.xaml b/src/Files.App/Dialogs/AddItemDialog.xaml index 8f47a4ab9324..345612cc459e 100644 --- a/src/Files.App/Dialogs/AddItemDialog.xaml +++ b/src/Files.App/Dialogs/AddItemDialog.xaml @@ -13,8 +13,9 @@ Grid.RowSpan="4" BorderThickness="0" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" Loaded="AddItemDialog_Loaded" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonText="{helpers:ResourceString Name=Cancel}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/AddItemDialog.xaml.cs b/src/Files.App/Dialogs/AddItemDialog.xaml.cs index 7bc71af5aa55..7b1a1bbdd520 100644 --- a/src/Files.App/Dialogs/AddItemDialog.xaml.cs +++ b/src/Files.App/Dialogs/AddItemDialog.xaml.cs @@ -10,13 +10,13 @@ namespace Files.App.Dialogs { public sealed partial class AddItemDialog : ContentDialog, IDialog { + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); private readonly IAddItemService addItemService = Ioc.Default.GetRequiredService(); - public AddItemDialogViewModel ViewModel - { - get => (AddItemDialogViewModel)DataContext; - set => DataContext = value; - } + public AddItemDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public AddItemDialog() { diff --git a/src/Files.App/Dialogs/CreateArchiveDialog.xaml b/src/Files.App/Dialogs/CreateArchiveDialog.xaml index 4c0f998947de..a4b74c0470be 100644 --- a/src/Files.App/Dialogs/CreateArchiveDialog.xaml +++ b/src/Files.App/Dialogs/CreateArchiveDialog.xaml @@ -17,7 +17,7 @@ IsPrimaryButtonEnabled="{x:Bind ViewModel.IsNameValid, Mode=OneWay}" Loaded="ContentDialog_Loaded" PrimaryButtonText="{helpers:ResourceString Name=Create}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs b/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs index d0b2d1e0506a..41036af83546 100644 --- a/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs +++ b/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs @@ -10,6 +10,11 @@ namespace Files.App.Dialogs { public sealed partial class CreateArchiveDialog : ContentDialog { + private IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; + private bool canCreate = false; public bool CanCreate => canCreate; diff --git a/src/Files.App/Dialogs/CreateShortcutDialog.xaml b/src/Files.App/Dialogs/CreateShortcutDialog.xaml index 0a3752eabfd7..8b820a766b94 100644 --- a/src/Files.App/Dialogs/CreateShortcutDialog.xaml +++ b/src/Files.App/Dialogs/CreateShortcutDialog.xaml @@ -7,11 +7,12 @@ xmlns:helpers="using:Files.App.Helpers" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="{helpers:ResourceString Name=NewShortcutDialogTitle}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="Primary" IsPrimaryButtonEnabled="{x:Bind ViewModel.IsLocationValid, Mode=OneWay}" PrimaryButtonCommand="{x:Bind ViewModel.PrimaryButtonCommand}" PrimaryButtonText="{helpers:ResourceString Name=Create}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonText="{helpers:ResourceString Name=Cancel}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/CreateShortcutDialog.xaml.cs b/src/Files.App/Dialogs/CreateShortcutDialog.xaml.cs index a6b554dd152d..620236d0bc8e 100644 --- a/src/Files.App/Dialogs/CreateShortcutDialog.xaml.cs +++ b/src/Files.App/Dialogs/CreateShortcutDialog.xaml.cs @@ -3,6 +3,7 @@ using Files.App.ViewModels.Dialogs; using Files.Core.ViewModels.Dialogs; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Data; @@ -10,11 +11,12 @@ namespace Files.App.Dialogs { public sealed partial class CreateShortcutDialog : ContentDialog, IDialog { - public CreateShortcutDialogViewModel ViewModel - { - get => (CreateShortcutDialogViewModel)DataContext; - set => DataContext = value; - } + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public CreateShortcutDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public CreateShortcutDialog() { diff --git a/src/Files.App/Dialogs/CredentialDialog.xaml b/src/Files.App/Dialogs/CredentialDialog.xaml index 1194fc4377a8..fcf5eeefa85e 100644 --- a/src/Files.App/Dialogs/CredentialDialog.xaml +++ b/src/Files.App/Dialogs/CredentialDialog.xaml @@ -9,10 +9,11 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="{helpers:ResourceString Name=AskCredentialDialog/Title}" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" PrimaryButtonClick="ContentDialog_PrimaryButtonClick" PrimaryButtonStyle="{StaticResource AccentButtonStyle}" PrimaryButtonText="{helpers:ResourceString Name=OK}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonText="{helpers:ResourceString Name=Cancel}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/CredentialDialog.xaml.cs b/src/Files.App/Dialogs/CredentialDialog.xaml.cs index 31e75fd70236..16fef0f502d8 100644 --- a/src/Files.App/Dialogs/CredentialDialog.xaml.cs +++ b/src/Files.App/Dialogs/CredentialDialog.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using System.Text; @@ -8,11 +9,12 @@ namespace Files.App.Dialogs { public sealed partial class CredentialDialog : ContentDialog, IDialog { - public CredentialDialogViewModel ViewModel - { - get => (CredentialDialogViewModel)DataContext; - set => DataContext = value; - } + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public CredentialDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public CredentialDialog() { diff --git a/src/Files.App/Dialogs/DecompressArchiveDialog.xaml b/src/Files.App/Dialogs/DecompressArchiveDialog.xaml index 0529351e14f5..2b295226884a 100644 --- a/src/Files.App/Dialogs/DecompressArchiveDialog.xaml +++ b/src/Files.App/Dialogs/DecompressArchiveDialog.xaml @@ -8,10 +8,11 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="{helpers:ResourceString Name=ExtractArchive}" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="Primary" PrimaryButtonClick="ContentDialog_PrimaryButtonClick" PrimaryButtonText="{helpers:ResourceString Name=Extract}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonText="{helpers:ResourceString Name=Cancel}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/DecompressArchiveDialog.xaml.cs b/src/Files.App/Dialogs/DecompressArchiveDialog.xaml.cs index bc9ca6f00830..a93888050a76 100644 --- a/src/Files.App/Dialogs/DecompressArchiveDialog.xaml.cs +++ b/src/Files.App/Dialogs/DecompressArchiveDialog.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See the LICENSE. using Files.App.ViewModels.Dialogs; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using System.Text; @@ -9,11 +10,12 @@ namespace Files.App.Dialogs { public sealed partial class DecompressArchiveDialog : ContentDialog { - public DecompressArchiveDialogViewModel ViewModel - { - get => (DecompressArchiveDialogViewModel)DataContext; - set => DataContext = value; - } + private IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public DecompressArchiveDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public DecompressArchiveDialog() { diff --git a/src/Files.App/Dialogs/DynamicDialog.xaml b/src/Files.App/Dialogs/DynamicDialog.xaml index bfa44938d45c..0a300f0a14b3 100644 --- a/src/Files.App/Dialogs/DynamicDialog.xaml +++ b/src/Files.App/Dialogs/DynamicDialog.xaml @@ -12,13 +12,14 @@ CloseButtonClick="ContentDialog_CloseButtonClick" CloseButtonText="{x:Bind ViewModel.CloseButtonText, Mode=OneWay}" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="Primary" IsPrimaryButtonEnabled="{x:Bind ViewModel.IsPrimaryButtonEnabled, Mode=OneWay}" IsSecondaryButtonEnabled="{x:Bind ViewModel.IsSecondaryButtonEnabled, Mode=OneWay}" KeyDown="ContentDialog_KeyDown" PrimaryButtonClick="ContentDialog_PrimaryButtonClick" PrimaryButtonText="{x:Bind ViewModel.PrimaryButtonText, Mode=OneWay}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonClick="ContentDialog_SecondaryButtonClick" SecondaryButtonText="{x:Bind ViewModel.SecondaryButtonText, Mode=OneWay}" Style="{StaticResource DefaultContentDialogStyle}" diff --git a/src/Files.App/Dialogs/DynamicDialog.xaml.cs b/src/Files.App/Dialogs/DynamicDialog.xaml.cs index a14ab38e4ab6..12165867632c 100644 --- a/src/Files.App/Dialogs/DynamicDialog.xaml.cs +++ b/src/Files.App/Dialogs/DynamicDialog.xaml.cs @@ -2,17 +2,19 @@ // Licensed under the MIT License. See the LICENSE. using Files.App.ViewModels.Dialogs; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; namespace Files.App.Dialogs { public sealed partial class DynamicDialog : ContentDialog, IDisposable { - public DynamicDialogViewModel ViewModel - { - get => (DynamicDialogViewModel)DataContext; - private set => DataContext = value; - } + private IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public DynamicDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public DynamicDialogResult DynamicResult { diff --git a/src/Files.App/Dialogs/ElevateConfirmDialog.xaml b/src/Files.App/Dialogs/ElevateConfirmDialog.xaml index 0f06b1d6d44d..8c5bdb672ed5 100644 --- a/src/Files.App/Dialogs/ElevateConfirmDialog.xaml +++ b/src/Files.App/Dialogs/ElevateConfirmDialog.xaml @@ -11,9 +11,10 @@ CloseButtonText="{helpers:ResourceString Name=No}" Content="{helpers:ResourceString Name=ElevateConfirmDialog/Content}" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="None" PrimaryButtonText="{helpers:ResourceString Name=Yes}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/ElevateConfirmDialog.xaml.cs b/src/Files.App/Dialogs/ElevateConfirmDialog.xaml.cs index f7106d65907d..1c4b93c048ed 100644 --- a/src/Files.App/Dialogs/ElevateConfirmDialog.xaml.cs +++ b/src/Files.App/Dialogs/ElevateConfirmDialog.xaml.cs @@ -1,20 +1,19 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using Files.Core.ViewModels.Dialogs; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using System; -using System.Threading.Tasks; namespace Files.App.Dialogs { public sealed partial class ElevateConfirmDialog : ContentDialog, IDialog { - public ElevateConfirmDialogViewModel ViewModel - { - get => (ElevateConfirmDialogViewModel)DataContext; - set => DataContext = value; - } + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public ElevateConfirmDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public ElevateConfirmDialog() { diff --git a/src/Files.App/Dialogs/FileTooLargeDialog.xaml b/src/Files.App/Dialogs/FileTooLargeDialog.xaml index 827187926bee..7b03ac261dde 100644 --- a/src/Files.App/Dialogs/FileTooLargeDialog.xaml +++ b/src/Files.App/Dialogs/FileTooLargeDialog.xaml @@ -8,9 +8,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="{helpers:ResourceString Name=CopyFailureFileToLarge}" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="Primary" PrimaryButtonText="{helpers:ResourceString Name=OK}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/FileTooLargeDialog.xaml.cs b/src/Files.App/Dialogs/FileTooLargeDialog.xaml.cs index 40a659b4b4b7..28e834e1babb 100644 --- a/src/Files.App/Dialogs/FileTooLargeDialog.xaml.cs +++ b/src/Files.App/Dialogs/FileTooLargeDialog.xaml.cs @@ -1,17 +1,19 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; namespace Files.App.Dialogs { public sealed partial class FileTooLargeDialog : ContentDialog, IDialog { - public FileTooLargeDialogViewModel ViewModel - { - get => (FileTooLargeDialogViewModel)DataContext; - set => DataContext = value; - } + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public FileTooLargeDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public FileTooLargeDialog() { diff --git a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml index abae820b5fd1..2f7ccd7db6f2 100644 --- a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml +++ b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml @@ -18,7 +18,7 @@ IsPrimaryButtonEnabled="{x:Bind ViewModel.PrimaryButtonEnabled, Mode=OneWay}" Opened="FilesystemOperationDialog_Opened" PrimaryButtonText="{x:Bind ViewModel.PrimaryButtonText, Mode=OneWay}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonCommand="{x:Bind ViewModel.SecondaryButtonClickCommand, Mode=OneWay}" SecondaryButtonText="{x:Bind ViewModel.SecondaryButtonText, Mode=OneWay}" Style="{StaticResource DefaultContentDialogStyle}" diff --git a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs index 8ab9e952c81e..da990b3c6e7b 100644 --- a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs +++ b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs @@ -4,26 +4,28 @@ using CommunityToolkit.WinUI.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; namespace Files.App.Dialogs { public sealed partial class FilesystemOperationDialog : ContentDialog, IDialog { + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + public FileSystemDialogViewModel ViewModel { get => (FileSystemDialogViewModel)DataContext; set { if (value is not null) - { value.PrimaryButtonEnabled = true; - } DataContext = value; } } + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; + public FilesystemOperationDialog() { InitializeComponent(); diff --git a/src/Files.App/Dialogs/GitHubLoginDialog.xaml b/src/Files.App/Dialogs/GitHubLoginDialog.xaml index 86c1c0716a38..cda857523b42 100644 --- a/src/Files.App/Dialogs/GitHubLoginDialog.xaml +++ b/src/Files.App/Dialogs/GitHubLoginDialog.xaml @@ -14,7 +14,7 @@ CornerRadius="{StaticResource OverlayCornerRadius}" PrimaryButtonClick="ContentDialog_PrimaryButtonClick" PrimaryButtonText="{helpers:ResourceString Name=OK}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/GitHubLoginDialog.xaml.cs b/src/Files.App/Dialogs/GitHubLoginDialog.xaml.cs index a3dbe9cce892..72782087bae9 100644 --- a/src/Files.App/Dialogs/GitHubLoginDialog.xaml.cs +++ b/src/Files.App/Dialogs/GitHubLoginDialog.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Windows.ApplicationModel.DataTransfer; @@ -8,6 +9,8 @@ namespace Files.App.Dialogs { public sealed partial class GitHubLoginDialog : ContentDialog, IDialog { + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + public GitHubLoginDialogViewModel ViewModel { get => (GitHubLoginDialogViewModel)DataContext; @@ -22,6 +25,9 @@ public GitHubLoginDialogViewModel ViewModel } } + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; + public GitHubLoginDialog() { InitializeComponent(); diff --git a/src/Files.App/Dialogs/PropertiesDialog.xaml b/src/Files.App/Dialogs/PropertiesDialog.xaml deleted file mode 100644 index 0967d1475cc0..000000000000 --- a/src/Files.App/Dialogs/PropertiesDialog.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 0 - - - - - \ No newline at end of file diff --git a/src/Files.App/Dialogs/PropertiesDialog.xaml.cs b/src/Files.App/Dialogs/PropertiesDialog.xaml.cs deleted file mode 100644 index f3d2b8c403c3..000000000000 --- a/src/Files.App/Dialogs/PropertiesDialog.xaml.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2023 Files Community -// Licensed under the MIT License. See the LICENSE. - -using Microsoft.UI.Xaml.Controls; - -namespace Files.App.Dialogs -{ - public sealed partial class PropertiesDialog : ContentDialog - { - public PropertiesDialog() - { - InitializeComponent(); - } - } -} diff --git a/src/Files.App/Dialogs/ReleaseNotesDialog.xaml b/src/Files.App/Dialogs/ReleaseNotesDialog.xaml index 610dd2ba35a0..3e0ad0f7bd4d 100644 --- a/src/Files.App/Dialogs/ReleaseNotesDialog.xaml +++ b/src/Files.App/Dialogs/ReleaseNotesDialog.xaml @@ -9,10 +9,12 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Closing="ContentDialog_Closing" CornerRadius="{StaticResource OverlayCornerRadius}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="None" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> + 0 diff --git a/src/Files.App/Dialogs/ReleaseNotesDialog.xaml.cs b/src/Files.App/Dialogs/ReleaseNotesDialog.xaml.cs index 38d23d23d534..8392ac8f4fe3 100644 --- a/src/Files.App/Dialogs/ReleaseNotesDialog.xaml.cs +++ b/src/Files.App/Dialogs/ReleaseNotesDialog.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -8,11 +9,12 @@ namespace Files.App.Dialogs { public sealed partial class ReleaseNotesDialog : ContentDialog, IDialog { - public ReleaseNotesDialogViewModel ViewModel - { - get => (ReleaseNotesDialogViewModel)DataContext; - set => DataContext = value; - } + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public ReleaseNotesDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public ReleaseNotesDialog() { diff --git a/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml b/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml index 41d9dccea3ee..3402e6951347 100644 --- a/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml +++ b/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml @@ -8,11 +8,12 @@ xmlns:helpers="using:Files.App.Helpers" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="{helpers:ResourceString Name=ReorderSidebarItemsDialogText}" + DataContext="{x:Bind ViewModel, Mode=OneWay}" DefaultButton="Primary" IsPrimaryButtonEnabled="True" PrimaryButtonCommand="{x:Bind ViewModel.PrimaryButtonCommand}" PrimaryButtonText="{helpers:ResourceString Name=Save}" - RequestedTheme="{x:Bind helpers:ThemeHelper.RootTheme}" + RequestedTheme="{x:Bind ThemeMode, Mode=OneWay}" SecondaryButtonText="{helpers:ResourceString Name=Cancel}" Style="{StaticResource DefaultContentDialogStyle}" mc:Ignorable="d"> diff --git a/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs b/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs index 4b032415ee6f..050383f315aa 100644 --- a/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs +++ b/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs @@ -2,26 +2,22 @@ // Licensed under the MIT License. See the LICENSE. using CommunityToolkit.WinUI.UI; -using Files.App.Data.Items; -using Files.App.Extensions; using Files.App.ViewModels.Dialogs; -using Files.Core.ViewModels.Dialogs; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; -using System; -using System.Threading.Tasks; using Windows.ApplicationModel.DataTransfer; namespace Files.App.Dialogs { public sealed partial class ReorderSidebarItemsDialog : ContentDialog, IDialog { - public ReorderSidebarItemsDialogViewModel ViewModel - { - get => (ReorderSidebarItemsDialogViewModel)DataContext; - set => DataContext = value; - } + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + + public ReorderSidebarItemsDialogViewModel ViewModel { get; set; } + + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; public ReorderSidebarItemsDialog() { diff --git a/src/Files.App/Dialogs/SettingsDialog.xaml.cs b/src/Files.App/Dialogs/SettingsDialog.xaml.cs index 7d4f6d42cac2..7085729a73b3 100644 --- a/src/Files.App/Dialogs/SettingsDialog.xaml.cs +++ b/src/Files.App/Dialogs/SettingsDialog.xaml.cs @@ -2,18 +2,20 @@ // Licensed under the MIT License. See the LICENSE. using Files.App.Views.Settings; -using Files.Core.ViewModels.Dialogs; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using System; -using System.Threading.Tasks; namespace Files.App.Dialogs { public sealed partial class SettingsDialog : ContentDialog, IDialog { + public IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + public SettingsDialogViewModel ViewModel { get; set; } + private ElementTheme ThemeMode + => (ElementTheme)AppThemeModeService.ThemeMode; + private FrameworkElement RootAppElement => (FrameworkElement)MainWindow.Instance.Content; diff --git a/src/Files.App/Helpers/UI/ThemeHelper.cs b/src/Files.App/Helpers/UI/ThemeHelper.cs deleted file mode 100644 index 646abd68098c..000000000000 --- a/src/Files.App/Helpers/UI/ThemeHelper.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2023 Files Community -// Licensed under the MIT License. See the LICENSE. - -using Microsoft.UI; -using Microsoft.UI.Windowing; -using Microsoft.UI.Xaml; -using Windows.Storage; -using Windows.UI; -using Windows.UI.ViewManagement; - -namespace Files.App.Helpers -{ - /// - /// Class providing functionality around switching and restoring theme settings - /// - public static class ThemeHelper - { - private const string selectedAppThemeKey = "theme"; - private static Window? currentApplicationWindow; - private static AppWindowTitleBar? titleBar; - private static bool isInitialized = false; - - // Keep reference so it does not get optimized/garbage collected - public static UISettings UiSettings; - - /// - /// Gets or sets (with LocalSettings persistence) the RequestedTheme of the root element. - /// - public static ElementTheme RootTheme - { - get - { - var savedTheme = ApplicationData.Current.LocalSettings.Values[selectedAppThemeKey]?.ToString(); - - return !string.IsNullOrEmpty(savedTheme) - ? EnumExtensions.GetEnum(savedTheme) - : ElementTheme.Default; - } - set - { - ApplicationData.Current.LocalSettings.Values[selectedAppThemeKey] = value.ToString(); - ApplyTheme(); - } - } - - public static bool Initialize() - { - if (isInitialized) - return false; - - isInitialized = true; - - // Save reference as this might be null when the user is in another app - currentApplicationWindow = MainWindow.Instance; - - // Set TitleBar background color - if (currentApplicationWindow is not null) - titleBar = MainWindow.Instance.AppWindow.TitleBar; - - // Apply the desired theme based on what is set in the application settings - ApplyTheme(); - - // Registering to color changes, thus we notice when user changes theme system wide - UiSettings = new UISettings(); - UiSettings.ColorValuesChanged += UiSettings_ColorValuesChanged; - - return true; - } - - public static void ApplyResources() - { - // Toggle between the themes to force reload the resource styles - ApplyTheme(ElementTheme.Dark); - ApplyTheme(ElementTheme.Light); - - // Restore the theme to the correct theme - ApplyTheme(); - } - - private static async void UiSettings_ColorValuesChanged(UISettings sender, object args) - { - // Make sure we have a reference to our window so we dispatch a UI change - if (currentApplicationWindow is null) - { - currentApplicationWindow = MainWindow.Instance; - - if (currentApplicationWindow is null) - return; - } - - titleBar ??= MainWindow.Instance.AppWindow.TitleBar; - - // Dispatch on UI thread so that we have a current appbar to access and change - await currentApplicationWindow.DispatcherQueue.EnqueueOrInvokeAsync(ApplyTheme); - } - - private static void ApplyTheme() - { - ApplyTheme(RootTheme); - } - - private static void ApplyTheme(ElementTheme rootTheme) - { - if (MainWindow.Instance.Content is FrameworkElement rootElement) - rootElement.RequestedTheme = rootTheme; - - if (titleBar is not null) - { - titleBar.ButtonBackgroundColor = Colors.Transparent; - titleBar.ButtonInactiveBackgroundColor = Colors.Transparent; - - switch (rootTheme) - { - case ElementTheme.Default: - titleBar.ButtonHoverBackgroundColor = (Color)Application.Current.Resources["SystemBaseLowColor"]; - titleBar.ButtonForegroundColor = (Color)Application.Current.Resources["SystemBaseHighColor"]; - break; - - case ElementTheme.Light: - titleBar.ButtonHoverBackgroundColor = Color.FromArgb(51, 0, 0, 0); - titleBar.ButtonForegroundColor = Colors.Black; - break; - - case ElementTheme.Dark: - titleBar.ButtonHoverBackgroundColor = Color.FromArgb(51, 255, 255, 255); - titleBar.ButtonForegroundColor = Colors.White; - break; - } - } - Ioc.Default.GetRequiredService().UpdateThemeElements.Execute(null); - } - } -} \ No newline at end of file diff --git a/src/Files.App/Services/AppThemeModeService.cs b/src/Files.App/Services/AppThemeModeService.cs new file mode 100644 index 000000000000..4178d70a726f --- /dev/null +++ b/src/Files.App/Services/AppThemeModeService.cs @@ -0,0 +1,109 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Microsoft.UI; +using Microsoft.UI.Windowing; +using Microsoft.UI.Xaml; +using Windows.UI; +using Windows.UI.ViewManagement; + +namespace Files.App.Services +{ + public class AppThemeModeService : IAppThemeModeService + { + // Dependency injections + + private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService(); + + // Fields & Properties + + private readonly UISettings UISettings = new(); + + public AppThemeMode ThemeMode + { + get + { + var theme = UserSettingsService.AppearanceSettingsService.AppThemeMode; + + return EnumExtensions.GetEnum(theme); + } + set + { + UserSettingsService.AppearanceSettingsService.AppThemeMode = value.ToString(); + + SetThemeMode(); + } + } + + // Events + + public event EventHandler? ThemeModeChanged; + + // Constructor + + public AppThemeModeService() + { + // Set the desired theme based on what is set in the application settings + SetThemeMode(); + + // Registering to color changes, so that we can notice when changed system theme mode + UISettings.ColorValuesChanged += UISettings_ColorValuesChanged; + } + + // Methods + + public void RefreshThemeMode() + { + // Toggle between the themes to force reload the resource styles + SetThemeMode(null, null, ElementTheme.Dark); + SetThemeMode(null, null, ElementTheme.Light); + + // Restore the theme to the correct theme + SetThemeMode(); + } + + private void SetThemeMode(Window? window = null, AppWindowTitleBar? titleBar = null, ElementTheme? rootTheme = null, bool callThemeModeChangedEvent = true) + { + window ??= MainWindow.Instance; + titleBar ??= MainWindow.Instance.AppWindow.TitleBar; + rootTheme ??= (ElementTheme)ThemeMode; + + if (window.Content is FrameworkElement rootElement) + rootElement.RequestedTheme = (ElementTheme)rootTheme; + + if (titleBar is not null) + { + titleBar.ButtonBackgroundColor = Colors.Transparent; + titleBar.ButtonInactiveBackgroundColor = Colors.Transparent; + + switch (rootTheme) + { + case ElementTheme.Default: + titleBar.ButtonHoverBackgroundColor = (Color)Application.Current.Resources["SystemBaseLowColor"]; + titleBar.ButtonForegroundColor = (Color)Application.Current.Resources["SystemBaseHighColor"]; + break; + case ElementTheme.Light: + titleBar.ButtonHoverBackgroundColor = Color.FromArgb(51, 0, 0, 0); + titleBar.ButtonForegroundColor = Colors.Black; + break; + case ElementTheme.Dark: + titleBar.ButtonHoverBackgroundColor = Color.FromArgb(51, 255, 255, 255); + titleBar.ButtonForegroundColor = Colors.White; + break; + } + } + + if (callThemeModeChangedEvent) + ThemeModeChanged?.Invoke(null, EventArgs.Empty); + } + + private async void UISettings_ColorValuesChanged(UISettings sender, object args) + { + // Dispatch on UI thread so that we have a current app bar to access and change + await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => + { + SetThemeMode(); + }); + } + } +} diff --git a/src/Files.App/Services/ResourcesService.cs b/src/Files.App/Services/ResourcesService.cs index 83eedca8e3c8..c1839d0bf864 100644 --- a/src/Files.App/Services/ResourcesService.cs +++ b/src/Files.App/Services/ResourcesService.cs @@ -9,6 +9,8 @@ namespace Files.App.Services /// public class ResourcesService : IResourcesService { + private IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + /// public void SetAppThemeBackgroundColor(Color appThemeBackgroundColor) { @@ -55,7 +57,7 @@ public void SetCompactSpacing(bool useCompactSpacing) /// public void ApplyResources() { - ThemeHelper.ApplyResources(); + AppThemeModeService.RefreshThemeMode(); } } } \ No newline at end of file diff --git a/src/Files.App/Services/Settings/AppearanceSettingsService.cs b/src/Files.App/Services/Settings/AppearanceSettingsService.cs index 688f2223bb68..8dd74e10f0f0 100644 --- a/src/Files.App/Services/Settings/AppearanceSettingsService.cs +++ b/src/Files.App/Services/Settings/AppearanceSettingsService.cs @@ -35,6 +35,13 @@ public bool UseCompactStyles set => Set(value); } + /// + public string AppThemeMode + { + get => Get("Default"); + set => Set(value); + } + /// public String AppThemeBackgroundColor { diff --git a/src/Files.App/Services/Settings/GeneralSettingsService.cs b/src/Files.App/Services/Settings/GeneralSettingsService.cs index 500104296415..229c30bcaf27 100644 --- a/src/Files.App/Services/Settings/GeneralSettingsService.cs +++ b/src/Files.App/Services/Settings/GeneralSettingsService.cs @@ -67,6 +67,13 @@ public List LastCrashedTabList set => Set(value); } + /// + public Dictionary SideBarSections + { + get => Get>(null); + set => Set(value); + } + public DateTimeFormats DateTimeFormat { get => Get(DateTimeFormats.Application); diff --git a/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs b/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs index 2dc48a613596..11114b5919e8 100644 --- a/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs +++ b/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs @@ -89,13 +89,14 @@ public static void OpenPropertiesWindow(IShellPage associatedInstance) public static void OpenPropertiesWindow(object item, IShellPage associatedInstance) { var applicationService = Ioc.Default.GetRequiredService(); + var appThemeModeService = Ioc.Default.GetRequiredService(); if (item is null) return; var frame = new Frame { - RequestedTheme = ThemeHelper.RootTheme + RequestedTheme = (ElementTheme)appThemeModeService.ThemeMode }; WinUIEx.WindowEx propertiesWindow; diff --git a/src/Files.App/ViewModels/MainPageViewModel.cs b/src/Files.App/ViewModels/MainPageViewModel.cs index 57eb525122a2..060892ace304 100644 --- a/src/Files.App/ViewModels/MainPageViewModel.cs +++ b/src/Files.App/ViewModels/MainPageViewModel.cs @@ -56,10 +56,6 @@ public async Task OnNavigatedToAsync(NavigationEventArgs e) if (e.NavigationMode == NavigationMode.Back) return; - // Initialize the static theme helper to capture a reference to this window - // to handle theme changes without restarting the app - var isInitialized = ThemeHelper.Initialize(); - var parameter = e.Parameter; var ignoreStartupSettings = false; if (parameter is MainPageNavigationArguments mainPageNavigationArguments) @@ -163,15 +159,12 @@ public async Task OnNavigatedToAsync(NavigationEventArgs e) await NavigationHelpers.AddNewTabByParamAsync(tabArgs.InitialPageType, tabArgs.NavigationParameter); } - if (isInitialized) - { - // Load the app theme resources - ResourcesService.LoadAppResources(AppearanceSettingsService); + // Load the app theme resources + ResourcesService.LoadAppResources(AppearanceSettingsService); - await Task.WhenAll( - DrivesViewModel.UpdateDrivesAsync(), - NetworkDrivesViewModel.UpdateDrivesAsync()); - } + await Task.WhenAll( + DrivesViewModel.UpdateDrivesAsync(), + NetworkDrivesViewModel.UpdateDrivesAsync()); } // Command methods diff --git a/src/Files.App/ViewModels/Settings/AppearanceViewModel.cs b/src/Files.App/ViewModels/Settings/AppearanceViewModel.cs index 980db2d7708b..5f73d17197e1 100644 --- a/src/Files.App/ViewModels/Settings/AppearanceViewModel.cs +++ b/src/Files.App/ViewModels/Settings/AppearanceViewModel.cs @@ -2,27 +2,23 @@ // Licensed under the MIT License. See the LICENSE. using CommunityToolkit.WinUI.Helpers; -using Files.Core.Services; -using Microsoft.UI.Composition.SystemBackdrops; using Microsoft.UI.Xaml; namespace Files.App.ViewModels.Settings { public class AppearanceViewModel : ObservableObject { - private readonly IUserSettingsService UserSettingsService; - private readonly IResourcesService ResourcesService; + private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService(); + private IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + private IResourcesService ResourcesService { get; } = Ioc.Default.GetRequiredService(); public List Themes { get; private set; } public Dictionary BackdropMaterialTypes { get; private set; } = new(); public ObservableCollection AppThemeResources { get; } - public AppearanceViewModel(IUserSettingsService userSettingsService, IResourcesService resourcesService) + public AppearanceViewModel() { - UserSettingsService = userSettingsService; - ResourcesService = resourcesService; - Themes = new List() { "Default".GetLocalizedResource(), @@ -87,15 +83,15 @@ public AppThemeResourceItem SelectedAppThemeResources } } - private int selectedThemeIndex = (int)Enum.Parse(typeof(ElementTheme), ThemeHelper.RootTheme.ToString()); + private int selectedThemeIndex; public int SelectedThemeIndex { - get => selectedThemeIndex; + get => (int)Enum.Parse(typeof(AppThemeMode), AppThemeModeService.ThemeMode.ToString()); set { if (SetProperty(ref selectedThemeIndex, value)) { - ThemeHelper.RootTheme = (ElementTheme)value; + AppThemeModeService.ThemeMode = ((AppThemeMode)value); OnPropertyChanged(nameof(SelectedElementTheme)); } } diff --git a/src/Files.App/ViewModels/SettingsViewModel.cs b/src/Files.App/ViewModels/SettingsViewModel.cs deleted file mode 100644 index cf837503e801..000000000000 --- a/src/Files.App/ViewModels/SettingsViewModel.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2023 Files Community -// Licensed under the MIT License. See the LICENSE. - -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Windows.Input; -using Windows.Storage; - -namespace Files.App.ViewModels -{ - [Obsolete("Do not use this class as Settings store anymore, settings have been merged to IUserSettingsService.")] - public class SettingsViewModel : ObservableObject - { - private readonly ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; - - public SettingsViewModel() - { - UpdateThemeElements = new RelayCommand(() => ThemeModeChanged?.Invoke(this, EventArgs.Empty)); - } - - public event EventHandler ThemeModeChanged; - - public ICommand UpdateThemeElements { get; } - - #region ReadAndSaveSettings - - public bool Set(TValue value, [CallerMemberName] string propertyName = null) - { - propertyName = - propertyName is not null && propertyName.StartsWith("set_", StringComparison.OrdinalIgnoreCase) ? - propertyName.Substring(4) : - propertyName; - - TValue originalValue = default; - - if (localSettings.Values.ContainsKey(propertyName)) - { - originalValue = Get(originalValue, propertyName); - - localSettings.Values[propertyName] = value; - if (!SetProperty(ref originalValue, value, propertyName)) - { - return false; - } - } - else - { - localSettings.Values[propertyName] = value; - } - - return true; - } - - public TValue Get<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TValue>(TValue defaultValue, [CallerMemberName] string propertyName = null) - { - var name = propertyName ?? throw new ArgumentNullException(nameof(propertyName), "Cannot store property of unnamed."); - - name = - name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) ? - propertyName.Substring(4) : - propertyName; - - if (localSettings.Values.ContainsKey(name)) - { - var value = localSettings.Values[name]; - - if (value is not TValue tValue) - { - if (value is IConvertible) - { - tValue = (TValue)Convert.ChangeType(value, typeof(TValue)); - } - else - { - var valueType = value.GetType(); - var tryParse = typeof(TValue).GetMethod("TryParse", BindingFlags.Instance | BindingFlags.Public); - - if (tryParse is null) - { - return default; - } - - var stringValue = value.ToString(); - tValue = default; - - var tryParseDelegate = - (TryParseDelegate)Delegate.CreateDelegate(valueType, tryParse, false); - - tValue = (tryParseDelegate?.Invoke(stringValue, out tValue) ?? false) ? tValue : default; - } - - // Put the corrected value in settings - Set(tValue, propertyName); - - return tValue; - } - return tValue; - } - - localSettings.Values[propertyName] = defaultValue; - - return defaultValue; - } - - private delegate bool TryParseDelegate(string inValue, out TValue parsedValue); - - #endregion ReadAndSaveSettings - } -} diff --git a/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs b/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs index e09e30279717..a5bd184d41aa 100644 --- a/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs +++ b/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs @@ -399,15 +399,28 @@ await lib.CheckDefaultSaveFolderAccess() && } } - section.IsExpanded = Ioc.Default.GetRequiredService().Get(section.Text == "SidebarFavorites".GetLocalizedResource(), $"section:{section.Text.Replace('\\', '_')}"); + var isExpanded = + UserSettingsService.GeneralSettingsService.SideBarSections? + .Select(x => x.Key == $"Section_{section.Text}") + .FirstOrDefault() + ?? true; + + section.IsExpanded = isExpanded; section.PropertyChanged += Section_PropertyChanged; } private void Section_PropertyChanged(object? sender, PropertyChangedEventArgs e) { - if (sender is LocationItem section && e.PropertyName == nameof(section.IsExpanded)) + if (sender is LocationItem section && + e.PropertyName == nameof(section.IsExpanded)) { - Ioc.Default.GetRequiredService().Set(section.IsExpanded, $"section:{section.Text.Replace('\\', '_')}"); + if (UserSettingsService.GeneralSettingsService.SideBarSections is null) + UserSettingsService.GeneralSettingsService.SideBarSections = new(); + + UserSettingsService.GeneralSettingsService.SideBarSections + .Add( + $"Section_{section.Text}", + section.IsExpanded); } } diff --git a/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs b/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs index b8f2233ea386..53c8ef0eac4f 100644 --- a/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs +++ b/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs @@ -15,12 +15,12 @@ namespace Files.App.Views.Properties { public sealed partial class MainPropertiesPage : BasePropertiesPage { + private IAppThemeModeService AppThemeModeService { get; } = Ioc.Default.GetRequiredService(); + private AppWindow AppWindow; private Window Window; - private SettingsViewModel AppSettings { get; set; } - private MainPropertiesViewModel MainPropertiesViewModel { get; set; } public MainPropertiesPage() @@ -45,8 +45,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) private void Page_Loaded(object sender, RoutedEventArgs e) { - AppSettings = Ioc.Default.GetRequiredService(); - AppSettings.ThemeModeChanged += AppSettings_ThemeModeChanged; + AppThemeModeService.ThemeModeChanged += AppSettings_ThemeModeChanged; Window.Closed += Window_Closed; UpdatePageLayout(); @@ -86,9 +85,9 @@ private async void AppSettings_ThemeModeChanged(object? sender, EventArgs e) await DispatcherQueue.EnqueueOrInvokeAsync(() => { - ((Frame)Parent).RequestedTheme = ThemeHelper.RootTheme; + ((Frame)Parent).RequestedTheme = (ElementTheme)AppThemeModeService.ThemeMode; - switch (ThemeHelper.RootTheme) + switch ((ElementTheme)AppThemeModeService.ThemeMode) { case ElementTheme.Default: AppWindow.TitleBar.ButtonHoverBackgroundColor = (Color)Application.Current.Resources["SystemBaseLowColor"]; @@ -108,7 +107,7 @@ await DispatcherQueue.EnqueueOrInvokeAsync(() => private void Window_Closed(object sender, WindowEventArgs args) { - AppSettings.ThemeModeChanged -= AppSettings_ThemeModeChanged; + AppThemeModeService.ThemeModeChanged -= AppSettings_ThemeModeChanged; Window.Closed -= Window_Closed; if (MainPropertiesViewModel.ChangedPropertiesCancellationTokenSource is not null && diff --git a/src/Files.Core/Data/Enums/AppThemeMode.cs b/src/Files.Core/Data/Enums/AppThemeMode.cs new file mode 100644 index 000000000000..a222667cb60e --- /dev/null +++ b/src/Files.Core/Data/Enums/AppThemeMode.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.Core.Data.Enums +{ + public enum AppThemeMode + { + Default, + Light, + Dark + } +} diff --git a/src/Files.Core/Services/IAppThemeModeService.cs b/src/Files.Core/Services/IAppThemeModeService.cs new file mode 100644 index 000000000000..4135de20c5d8 --- /dev/null +++ b/src/Files.Core/Services/IAppThemeModeService.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.Core.Services +{ + public interface IAppThemeModeService + { + public event EventHandler? ThemeModeChanged; + + public AppThemeMode ThemeMode { get; set; } + + public void RefreshThemeMode(); + } +} diff --git a/src/Files.Core/Services/Settings/IAppearanceSettingsService.cs b/src/Files.Core/Services/Settings/IAppearanceSettingsService.cs index 00da16c03643..4d218f99d228 100644 --- a/src/Files.Core/Services/Settings/IAppearanceSettingsService.cs +++ b/src/Files.Core/Services/Settings/IAppearanceSettingsService.cs @@ -24,6 +24,11 @@ public interface IAppearanceSettingsService : IBaseSettingsService, INotifyPrope /// bool UseCompactStyles { get; set; } + /// + /// Gets or sets a value for the app theme mode. + /// + string AppThemeMode { get; set; } + /// /// Gets or sets a value for the app theme background color. /// diff --git a/src/Files.Core/Services/Settings/IGeneralSettingsService.cs b/src/Files.Core/Services/Settings/IGeneralSettingsService.cs index a6e0e5ae626d..40ab67ff9c3c 100644 --- a/src/Files.Core/Services/Settings/IGeneralSettingsService.cs +++ b/src/Files.Core/Services/Settings/IGeneralSettingsService.cs @@ -54,6 +54,11 @@ public interface IGeneralSettingsService : IBaseSettingsService, INotifyProperty /// List LastCrashedTabList { get; set; } + /// + /// A list containing SideBar sections with expanded/collapsed boolean. + /// + public Dictionary SideBarSections { get; set; } + /// /// Gets or sets a value indicating which date and time format to use. /// diff --git a/src/Files.Core/ViewModels/Dialogs/IDialog.cs b/src/Files.Core/ViewModels/Dialogs/IDialog.cs index dfa5d505fb47..13e227a79cdd 100644 --- a/src/Files.Core/ViewModels/Dialogs/IDialog.cs +++ b/src/Files.Core/ViewModels/Dialogs/IDialog.cs @@ -8,6 +8,8 @@ namespace Files.Core.ViewModels.Dialogs public interface IDialog where TViewModel : class, INotifyPropertyChanged { + IAppThemeModeService AppThemeModeService { get; } + TViewModel ViewModel { get; set; } Task ShowAsync();