From 91f9f3d6fb2dd15076511487089b5829a405fdd2 Mon Sep 17 00:00:00 2001 From: lincube Date: Sat, 14 Mar 2026 16:38:56 +0800 Subject: [PATCH] settings_re7 --- LanMountainDesktop/Controls/IconText.axaml | 2 +- LanMountainDesktop/Localization/zh-CN.json | 11 +- .../Models/AppSettingsSnapshot.cs | 4 + .../Services/Settings/SettingsContracts.cs | 2 +- .../Settings/SettingsDomainServices.cs | 10 +- .../ViewModels/SettingsViewModels.cs | 24 ++++ .../WallpaperSettingsPageViewModel.cs | 130 +++++++++++++++--- .../Views/MainWindow.SettingsHardCut.Stubs.cs | 82 ++++++++++- LanMountainDesktop/Views/MainWindow.axaml | 6 + LanMountainDesktop/Views/MainWindow.axaml.cs | 7 +- .../AppearanceSettingsPage.axaml | 4 +- .../ComponentsSettingsPage.axaml | 36 +++-- .../SettingsPages/WallpaperSettingsPage.axaml | 110 +++++++++++++-- LanMountainDesktop/Views/SettingsWindow.axaml | 2 +- 14 files changed, 370 insertions(+), 60 deletions(-) diff --git a/LanMountainDesktop/Controls/IconText.axaml b/LanMountainDesktop/Controls/IconText.axaml index da69f8e..0b40a7e 100644 --- a/LanMountainDesktop/Controls/IconText.axaml +++ b/LanMountainDesktop/Controls/IconText.axaml @@ -13,7 +13,7 @@ diff --git a/LanMountainDesktop/Localization/zh-CN.json b/LanMountainDesktop/Localization/zh-CN.json index f037590..d51ec38 100644 --- a/LanMountainDesktop/Localization/zh-CN.json +++ b/LanMountainDesktop/Localization/zh-CN.json @@ -32,9 +32,14 @@ "settings.wallpaper.title": "壁纸", "settings.wallpaper.description": "选择图片或视频后可立即设为应用窗口壁纸。", "settings.wallpaper.current_label": "当前壁纸", + "settings.wallpaper.type_label": "壁纸类型", + "settings.wallpaper.type.image": "图片", + "settings.wallpaper.type.video": "视频", + "settings.wallpaper.type.solid_color": "纯色", + "settings.wallpaper.color_label": "壁纸颜色", "settings.wallpaper.placement_label": "显示方式", "settings.wallpaper.placement_desc": "调整图像在桌面上的填充方式。", - "settings.wallpaper.pick_button": "浏览文件", + "settings.wallpaper.pick_button": "选择文件", "settings.wallpaper.clear_button": "恢复纯色", "settings.wallpaper.no_selection": "未选择壁纸。", "settings.wallpaper.storage_unavailable": "存储提供器不可用。", @@ -245,8 +250,8 @@ "settings.status_bar.clock_format_label": "时钟格式", "settings.status_bar.clock_format.hm": "时:分", "settings.status_bar.clock_format.hms": "时:分:秒", - "settings.components.title": "组件", - "settings.components.description": "调整桌面网格与组件摆放密度。", + "settings.components.title": "网格", + "settings.components.description": "调整桌面网格与布局。", "settings.components.grid_header": "网格布局", "settings.update.title": "更新", "settings.update.current_version_label": "当前版本", diff --git a/LanMountainDesktop/Models/AppSettingsSnapshot.cs b/LanMountainDesktop/Models/AppSettingsSnapshot.cs index f100d9b..1751a4a 100644 --- a/LanMountainDesktop/Models/AppSettingsSnapshot.cs +++ b/LanMountainDesktop/Models/AppSettingsSnapshot.cs @@ -18,6 +18,10 @@ public sealed class AppSettingsSnapshot public string? WallpaperPath { get; set; } + public string WallpaperType { get; set; } = "Image"; + + public string? WallpaperColor { get; set; } + public string WallpaperPlacement { get; set; } = "Fill"; public int SettingsTabIndex { get; set; } = 0; diff --git a/LanMountainDesktop/Services/Settings/SettingsContracts.cs b/LanMountainDesktop/Services/Settings/SettingsContracts.cs index a2598eb..882790c 100644 --- a/LanMountainDesktop/Services/Settings/SettingsContracts.cs +++ b/LanMountainDesktop/Services/Settings/SettingsContracts.cs @@ -15,7 +15,7 @@ public enum WallpaperMediaType } public sealed record GridSettingsState(int ShortSideCells, string SpacingPreset, int EdgeInsetPercent); -public sealed record WallpaperSettingsState(string? WallpaperPath, string Placement); +public sealed record WallpaperSettingsState(string? WallpaperPath, string Type, string? Color, string Placement); public sealed record ThemeAppearanceSettingsState(bool IsNightMode, string? ThemeColor, bool UseSystemChrome); public sealed record StatusBarSettingsState( IReadOnlyList TopStatusComponentIds, diff --git a/LanMountainDesktop/Services/Settings/SettingsDomainServices.cs b/LanMountainDesktop/Services/Settings/SettingsDomainServices.cs index 3ddf259..0337cfe 100644 --- a/LanMountainDesktop/Services/Settings/SettingsDomainServices.cs +++ b/LanMountainDesktop/Services/Settings/SettingsDomainServices.cs @@ -91,13 +91,19 @@ internal sealed class WallpaperSettingsService : IWallpaperSettingsService public WallpaperSettingsState Get() { var snapshot = _settingsService.Load(); - return new WallpaperSettingsState(snapshot.WallpaperPath, snapshot.WallpaperPlacement); + return new WallpaperSettingsState( + snapshot.WallpaperPath, + snapshot.WallpaperType ?? "Image", + snapshot.WallpaperColor, + snapshot.WallpaperPlacement); } public void Save(WallpaperSettingsState state) { var snapshot = _settingsService.Load(); snapshot.WallpaperPath = state.WallpaperPath; + snapshot.WallpaperType = state.Type; + snapshot.WallpaperColor = state.Color; snapshot.WallpaperPlacement = string.IsNullOrWhiteSpace(state.Placement) ? "Fill" : state.Placement.Trim(); @@ -107,6 +113,8 @@ internal sealed class WallpaperSettingsService : IWallpaperSettingsService changedKeys: [ nameof(AppSettingsSnapshot.WallpaperPath), + nameof(AppSettingsSnapshot.WallpaperType), + nameof(AppSettingsSnapshot.WallpaperColor), nameof(AppSettingsSnapshot.WallpaperPlacement) ]); } diff --git a/LanMountainDesktop/ViewModels/SettingsViewModels.cs b/LanMountainDesktop/ViewModels/SettingsViewModels.cs index d80c552..3203e42 100644 --- a/LanMountainDesktop/ViewModels/SettingsViewModels.cs +++ b/LanMountainDesktop/ViewModels/SettingsViewModels.cs @@ -412,6 +412,19 @@ public sealed partial class AppearanceSettingsPageViewModel : ViewModelBase [ObservableProperty] private string _themeColor = string.Empty; + [ObservableProperty] + private Color _themeColorPickerValue; + + partial void OnThemeColorPickerValueChanged(Color value) + { + if (_isInitializing) + { + return; + } + + ThemeColor = value.ToString(); + } + [ObservableProperty] private bool _useSystemChrome; @@ -474,6 +487,14 @@ public sealed partial class AppearanceSettingsPageViewModel : ViewModelBase var theme = _settingsFacade.Theme.Get(); IsNightMode = theme.IsNightMode; ThemeColor = theme.ThemeColor ?? string.Empty; + if (Color.TryParse(ThemeColor, out var color)) + { + ThemeColorPickerValue = color; + } + else + { + ThemeColorPickerValue = Color.Parse("#FF3B82F6"); + } UseSystemChrome = theme.UseSystemChrome; var wallpaper = _settingsFacade.Wallpaper.Get(); @@ -588,8 +609,11 @@ public sealed partial class AppearanceSettingsPageViewModel : ViewModelBase private void SaveWallpaper() { + var current = _settingsFacade.Wallpaper.Get(); _settingsFacade.Wallpaper.Save(new WallpaperSettingsState( string.IsNullOrWhiteSpace(WallpaperPath) ? null : WallpaperPath, + current.Type, + current.Color, SelectedWallpaperPlacement.Value)); } diff --git a/LanMountainDesktop/ViewModels/WallpaperSettingsPageViewModel.cs b/LanMountainDesktop/ViewModels/WallpaperSettingsPageViewModel.cs index c7696b4..27566f7 100644 --- a/LanMountainDesktop/ViewModels/WallpaperSettingsPageViewModel.cs +++ b/LanMountainDesktop/ViewModels/WallpaperSettingsPageViewModel.cs @@ -1,7 +1,12 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; +using Avalonia.Media; +using Avalonia.Media.Imaging; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; using LanMountainDesktop.Services; using LanMountainDesktop.Services.Settings; @@ -19,6 +24,8 @@ public sealed partial class WallpaperSettingsPageViewModel : ViewModelBase _settingsFacade = settingsFacade; _languageCode = _localizationService.NormalizeLanguageCode(_settingsFacade.Region.Get().LanguageCode); WallpaperPlacements = CreateWallpaperPlacements(); + WallpaperTypes = CreateWallpaperTypes(); + PresetColors = CreatePresetColors(); RefreshLocalizedText(); _isInitializing = true; @@ -27,41 +34,90 @@ public sealed partial class WallpaperSettingsPageViewModel : ViewModelBase } public IReadOnlyList WallpaperPlacements { get; } + public IReadOnlyList WallpaperTypes { get; } + public IReadOnlyList PresetColors { get; } - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] + [ObservableProperty] private string _wallpaperPath = string.Empty; - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] - private SelectionOption _selectedWallpaperPlacement = new("Fill", "Fill"); + [ObservableProperty] + private SelectionOption _selectedWallpaperType = null!; - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] + [ObservableProperty] + private string? _selectedColor; + + [ObservableProperty] + private SelectionOption _selectedWallpaperPlacement = null!; + + [ObservableProperty] private string _wallpaperHeader = string.Empty; - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] + [ObservableProperty] + private string _wallpaperTypeLabel = string.Empty; + + [ObservableProperty] private string _wallpaperPathLabel = string.Empty; - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] + [ObservableProperty] + private string _wallpaperColorLabel = string.Empty; + + [ObservableProperty] private string _wallpaperPlacementLabel = string.Empty; - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] + [ObservableProperty] private string _wallpaperPlacementDescription = string.Empty; - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] + [ObservableProperty] private string _importWallpaperButtonText = string.Empty; - [CommunityToolkit.Mvvm.ComponentModel.ObservableProperty] + [ObservableProperty] private string _filePickerTitle = string.Empty; + [ObservableProperty] + private bool _isImageOrVideo; + + [ObservableProperty] + private bool _isSolidColor; + + [ObservableProperty] + private Bitmap? _previewImage; + public void Load() { var wallpaper = _settingsFacade.Wallpaper.Get(); WallpaperPath = wallpaper.WallpaperPath ?? string.Empty; + + SelectedWallpaperType = WallpaperTypes.FirstOrDefault(t => t.Value == wallpaper.Type) ?? WallpaperTypes[0]; + SelectedColor = wallpaper.Color ?? PresetColors[0]; + var wallpaperPlacement = string.IsNullOrWhiteSpace(wallpaper.Placement) ? "Fill" : wallpaper.Placement; SelectedWallpaperPlacement = WallpaperPlacements.FirstOrDefault(option => string.Equals(option.Value, wallpaperPlacement, StringComparison.OrdinalIgnoreCase)) ?? WallpaperPlacements[0]; + + UpdateVisibility(); + UpdatePreviewImage(WallpaperPath); + } + + partial void OnSelectedWallpaperTypeChanged(SelectionOption value) + { + UpdateVisibility(); + if (_isInitializing) return; + SaveWallpaper(); + } + + private void UpdateVisibility() + { + IsImageOrVideo = SelectedWallpaperType?.Value is "Image" or "Video"; + IsSolidColor = SelectedWallpaperType?.Value == "SolidColor"; + } + + partial void OnSelectedColorChanged(string? value) + { + if (_isInitializing) return; + SaveWallpaper(); } public async Task ImportWallpaperAsync(string sourcePath) @@ -75,28 +131,48 @@ public sealed partial class WallpaperSettingsPageViewModel : ViewModelBase partial void OnWallpaperPathChanged(string value) { - if (_isInitializing) + UpdatePreviewImage(value); + if (_isInitializing) return; + SaveWallpaper(); + } + + private void UpdatePreviewImage(string path) + { + if (string.IsNullOrWhiteSpace(path) || !System.IO.File.Exists(path)) { + PreviewImage = null; return; } - SaveWallpaper(); + try + { + using var stream = System.IO.File.OpenRead(path); + PreviewImage = new Bitmap(stream); + } + catch + { + PreviewImage = null; + } } partial void OnSelectedWallpaperPlacementChanged(SelectionOption value) { - if (_isInitializing || value is null) - { - return; - } - + if (_isInitializing || value is null) return; SaveWallpaper(); } + [RelayCommand] + private void SelectColor(string color) + { + SelectedColor = color; + } + private void SaveWallpaper() { _settingsFacade.Wallpaper.Save(new WallpaperSettingsState( string.IsNullOrWhiteSpace(WallpaperPath) ? null : WallpaperPath, + SelectedWallpaperType.Value, + SelectedColor, SelectedWallpaperPlacement.Value)); } @@ -112,10 +188,32 @@ public sealed partial class WallpaperSettingsPageViewModel : ViewModelBase ]; } + private IReadOnlyList CreateWallpaperTypes() + { + return + [ + new SelectionOption("Image", L("settings.wallpaper.type.image", "Image")), + new SelectionOption("Video", L("settings.wallpaper.type.video", "Video")), + new SelectionOption("SolidColor", L("settings.wallpaper.type.solid_color", "Solid Color")) + ]; + } + + private IReadOnlyList CreatePresetColors() + { + return + [ + "#D8A7B1", "#B6C9BB", "#A2B5BB", "#E6E2D3", + "#B5A397", "#C5C1C0", "#D4BE8D", "#C08261", + "#8E9775", "#9FBAD3", "#E5BAA2", "#4E596F" + ]; + } + private void RefreshLocalizedText() { WallpaperHeader = L("settings.wallpaper.title", "Wallpaper"); + WallpaperTypeLabel = L("settings.wallpaper.type_label", "Wallpaper Type"); WallpaperPathLabel = L("settings.wallpaper.current_label", "Current Wallpaper"); + WallpaperColorLabel = L("settings.wallpaper.color_label", "Wallpaper Color"); WallpaperPlacementLabel = L("settings.wallpaper.placement_label", "Placement"); WallpaperPlacementDescription = L("settings.wallpaper.placement_desc", "Adjust how the image fills the desktop."); ImportWallpaperButtonText = L("settings.wallpaper.pick_button", "Import Wallpaper"); diff --git a/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs b/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs index d237dbe..f27c9f7 100644 --- a/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs +++ b/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs @@ -15,6 +15,8 @@ using LanMountainDesktop.PluginSdk; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; using LanMountainDesktop.Views.Components; +using LibVLCSharp.Shared; +using LibVLCSharp.Avalonia; namespace LanMountainDesktop.Views; @@ -218,13 +220,24 @@ public partial class MainWindow _defaultDesktopBackground = GetThemeBrush("AdaptiveSurfaceBaseBrush"); } - private void TryRestoreWallpaper(string? savedWallpaperPath) + private void TryRestoreWallpaper(string? savedWallpaperPath, string? type = null, string? color = null) { _wallpaperPath = string.IsNullOrWhiteSpace(savedWallpaperPath) ? null : savedWallpaperPath; + _wallpaperType = type ?? "Image"; + if (TryParseColor(color, out var parsedColor)) + { + _wallpaperSolidColor = parsedColor; + } _wallpaperBitmap?.Dispose(); _wallpaperBitmap = null; + if (_wallpaperType == "SolidColor") + { + _wallpaperMediaType = WallpaperMediaType.SolidColor; + return; + } + if (string.IsNullOrWhiteSpace(_wallpaperPath) || !File.Exists(_wallpaperPath)) { _wallpaperMediaType = WallpaperMediaType.None; @@ -232,7 +245,7 @@ public partial class MainWindow } var extension = Path.GetExtension(_wallpaperPath); - if (SupportedVideoExtensions.Contains(extension)) + if (SupportedVideoExtensions.Contains(extension) || _wallpaperType == "Video") { _wallpaperMediaType = WallpaperMediaType.Video; _wallpaperVideoPath = _wallpaperPath; @@ -263,6 +276,12 @@ public partial class MainWindow private void ApplyWallpaperBrush() { + if (_wallpaperMediaType == WallpaperMediaType.SolidColor && _wallpaperSolidColor.HasValue) + { + DesktopWallpaperLayer.Background = new SolidColorBrush(_wallpaperSolidColor.Value); + return; + } + if (_wallpaperMediaType == WallpaperMediaType.Image && _wallpaperBitmap is not null) { DesktopWallpaperLayer.Background = new ImageBrush(_wallpaperBitmap) @@ -277,16 +296,65 @@ public partial class MainWindow private void UpdateWallpaperDisplay() { + if (_wallpaperMediaType == WallpaperMediaType.Video) + { + if (!string.IsNullOrWhiteSpace(_wallpaperVideoPath)) + { + StartVideoWallpaper(_wallpaperVideoPath); + } + } + else + { + StopVideoWallpaper(); + } + ApplyWallpaperBrush(); } + private void StartVideoWallpaper(string videoPath) + { + if (string.IsNullOrWhiteSpace(videoPath) || !File.Exists(videoPath)) + { + return; + } + + try + { + _libVlc ??= new LibVLC(); + _videoWallpaperPlayer ??= new MediaPlayer(_libVlc); + + if (_videoWallpaperMedia?.Mrl != videoPath) + { + _videoWallpaperMedia?.Dispose(); + _videoWallpaperMedia = new Media(_libVlc, new Uri(videoPath)); + _videoWallpaperPlayer.Media = _videoWallpaperMedia; + } + + if (DesktopVideoWallpaperView is { } videoView) + { + videoView.MediaPlayer = _videoWallpaperPlayer; + videoView.IsVisible = true; + } + + if (!_videoWallpaperPlayer.IsPlaying) + { + _videoWallpaperPlayer.Play(); + } + } + catch + { + } + } + private void StopVideoWallpaper() { - _wallpaperVideoPath = null; - if (_wallpaperMediaType == WallpaperMediaType.Video) + if (DesktopVideoWallpaperView is { } videoView) { - _wallpaperMediaType = WallpaperMediaType.None; + videoView.IsVisible = false; } + + _videoWallpaperPlayer?.Stop(); + _wallpaperVideoPath = null; } private double CalculateCurrentBackgroundLuminance() @@ -398,7 +466,7 @@ public partial class MainWindow InitializeDesktopSurfaceState(layoutSnapshot); InitializeLauncherVisibilitySettings(launcherSnapshot); InitializeDesktopComponentPlacements(layoutSnapshot); - TryRestoreWallpaper(snapshot.WallpaperPath); + TryRestoreWallpaper(snapshot.WallpaperPath, snapshot.WallpaperType, snapshot.WallpaperColor); if (TryParseColor(snapshot.ThemeColor, out var savedThemeColor)) { _selectedThemeColor = savedThemeColor; @@ -428,6 +496,8 @@ public partial class MainWindow IsNightMode = _isNightMode, ThemeColor = _selectedThemeColor.ToString(), WallpaperPath = _wallpaperPath, + WallpaperType = _wallpaperType, + WallpaperColor = _wallpaperSolidColor?.ToString(), LanguageCode = _languageCode, TimeZoneId = _timeZoneService.CurrentTimeZone.Id, WeatherLocationMode = _weatherLocationMode.ToString(), diff --git a/LanMountainDesktop/Views/MainWindow.axaml b/LanMountainDesktop/Views/MainWindow.axaml index f75eed1..29fde44 100644 --- a/LanMountainDesktop/Views/MainWindow.axaml +++ b/LanMountainDesktop/Views/MainWindow.axaml @@ -47,6 +47,12 @@ VerticalAlignment="Stretch" Background="{DynamicResource AdaptiveSurfaceBaseBrush}" /> + + - + diff --git a/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml index 83c29dd..cae0fc8 100644 --- a/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml +++ b/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml @@ -20,25 +20,37 @@ - + - + + - + - + + diff --git a/LanMountainDesktop/Views/SettingsPages/WallpaperSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/WallpaperSettingsPage.axaml index dc6023b..6058248 100644 --- a/LanMountainDesktop/Views/SettingsPages/WallpaperSettingsPage.axaml +++ b/LanMountainDesktop/Views/SettingsPages/WallpaperSettingsPage.axaml @@ -9,34 +9,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Margin="0,0,0,8" /> - + + - + - - -