AppearancePage.xaml.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Diagnostics; 6 using ManagedCommon; 7 using Microsoft.CmdPal.UI.ViewModels; 8 using Microsoft.CmdPal.UI.ViewModels.Services; 9 using Microsoft.Extensions.DependencyInjection; 10 using Microsoft.UI; 11 using Microsoft.UI.Xaml; 12 using Microsoft.UI.Xaml.Controls; 13 using Microsoft.UI.Xaml.Documents; 14 using Microsoft.Windows.Storage.Pickers; 15 16 namespace Microsoft.CmdPal.UI.Settings; 17 18 /// <summary> 19 /// An empty page that can be used on its own or navigated to within a Frame. 20 /// </summary> 21 public sealed partial class AppearancePage : Page 22 { 23 private readonly TaskScheduler _mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 24 25 internal SettingsViewModel ViewModel { get; } 26 27 public AppearancePage() 28 { 29 InitializeComponent(); 30 31 var settings = App.Current.Services.GetService<SettingsModel>()!; 32 var themeService = App.Current.Services.GetRequiredService<IThemeService>(); 33 var topLevelCommandManager = App.Current.Services.GetService<TopLevelCommandManager>()!; 34 ViewModel = new SettingsViewModel(settings, topLevelCommandManager, _mainTaskScheduler, themeService); 35 } 36 37 private async void PickBackgroundImage_Click(object sender, RoutedEventArgs e) 38 { 39 try 40 { 41 if (XamlRoot?.ContentIslandEnvironment is null) 42 { 43 return; 44 } 45 46 var windowId = XamlRoot?.ContentIslandEnvironment?.AppWindowId ?? new WindowId(0); 47 48 var picker = new FileOpenPicker(windowId) 49 { 50 CommitButtonText = ViewModels.Properties.Resources.builtin_settings_appearance_pick_background_image_title!, 51 SuggestedStartLocation = PickerLocationId.PicturesLibrary, 52 ViewMode = PickerViewMode.Thumbnail, 53 }; 54 55 string[] extensions = [".png", ".bmp", ".jpg", ".jpeg", ".jfif", ".gif", ".tiff", ".tif", ".webp", ".jxr"]; 56 foreach (var ext in extensions) 57 { 58 picker.FileTypeFilter!.Add(ext); 59 } 60 61 var file = await picker.PickSingleFileAsync()!; 62 if (file != null) 63 { 64 ViewModel.Appearance.BackgroundImagePath = file.Path ?? string.Empty; 65 } 66 } 67 catch (Exception ex) 68 { 69 Logger.LogError("Failed to pick background image file", ex); 70 } 71 } 72 73 private void OpenWindowsColorsSettings_Click(Hyperlink sender, HyperlinkClickEventArgs args) 74 { 75 // LOAD BEARING (or BEAR LOADING?): Process.Start with UseShellExecute inside a XAML input event can trigger WinUI reentrancy 76 // and cause FailFast crashes. Task.Run moves the call off the UI thread to prevent hard process termination. 77 Task.Run(() => 78 { 79 try 80 { 81 _ = Process.Start(new ProcessStartInfo("ms-settings:colors") { UseShellExecute = true }); 82 } 83 catch (Exception ex) 84 { 85 Logger.LogError("Failed to open Windows Settings", ex); 86 } 87 }); 88 } 89 }