From 52d9fb3f5895215c5cd5723e9acba7b6eccba4a4 Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Wed, 12 Feb 2020 16:45:35 -0800 Subject: [PATCH 01/49] add support for game bar sdk --- src/Notepads/App.xaml.cs | 38 ++++++++++++++++- src/Notepads/Notepads.csproj | 8 +++- src/Notepads/Package.appxmanifest | 69 ++++++++++++++++++++++++++++++- src/Notepads/Program.cs | 37 +++++++++++++---- 4 files changed, 139 insertions(+), 13 deletions(-) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index 63f05688e..e999c0173 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -7,6 +7,7 @@ using Microsoft.AppCenter; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; + using Microsoft.Gaming.XboxGameBar; using Microsoft.Toolkit.Uwp.Helpers; using Notepads.Services; using Notepads.Settings; @@ -27,9 +28,12 @@ sealed partial class App : Application public static Guid Id { get; } = Guid.NewGuid(); public static bool IsFirstInstance; + public static bool IsUiExt = false; private const string AppCenterSecret = null; + private XboxGameBarUIExtension XboxGameBarUIExtension = null; + /// /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). @@ -151,10 +155,38 @@ protected override async void OnFileActivated(FileActivatedEventArgs args) base.OnFileActivated(args); } + //protected override async void OnActivated(IActivatedEventArgs args) + //{ + // await ActivateAsync(args); + // base.OnActivated(args); + //} + protected override async void OnActivated(IActivatedEventArgs args) { + XboxGameBarUIExtensionActivatedEventArgs uiExtArgs = null; + if (args.Kind == ActivationKind.Protocol) + { + var protocolArgs = args as IProtocolActivatedEventArgs; + string protocolString = protocolArgs.Uri.AbsoluteUri; + if (protocolString.StartsWith("ms-gamebaruiextension")) + { + uiExtArgs = args as XboxGameBarUIExtensionActivatedEventArgs; + } + } + + IsUiExt = uiExtArgs != null; + await ActivateAsync(args); base.OnActivated(args); + + if (IsUiExt) + { + IsFirstInstance = true; + XboxGameBarUIExtension = new XboxGameBarUIExtension( + uiExtArgs, + Window.Current.CoreWindow, + Window.Current.Content as Frame); + } } private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) @@ -233,7 +265,11 @@ private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) } Window.Current.Activate(); - ExtendAcrylicIntoTitleBar(); + + if (IsUiExt != true) + { + ExtendAcrylicIntoTitleBar(); + } } private Frame CreateRootFrame(IActivatedEventArgs e) diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index 0b588d8ee..ac1974b18 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -1,4 +1,4 @@ - + @@ -106,6 +106,7 @@ prompt true false + true bin\x64\Release\ @@ -494,6 +495,9 @@ 2.6.4 + + 1.0.200212001-prerelease + 6.2.9 @@ -624,4 +628,4 @@ --> - + \ No newline at end of file diff --git a/src/Notepads/Package.appxmanifest b/src/Notepads/Package.appxmanifest index d5ee9411a..49d86c190 100644 --- a/src/Notepads/Package.appxmanifest +++ b/src/Notepads/Package.appxmanifest @@ -8,7 +8,8 @@ xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4" xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" - IgnorableNamespaces="uap mp uap5 desktop4 iot2 rescap"> + xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" + IgnorableNamespaces="uap mp uap5 desktop4 iot2 rescap uap3"> + + + + + + + + + + + + + + + + + + true + true + true + + + 400 + 400 + 400 + 400 + 1000 + 1000 + + + true + true + + + + + + + + + + + + + Microsoft.Gaming.XboxGameBar.winmd + + + + + + + + + diff --git a/src/Notepads/Program.cs b/src/Notepads/Program.cs index 9a925940d..3126e0ca6 100644 --- a/src/Notepads/Program.cs +++ b/src/Notepads/Program.cs @@ -13,6 +13,15 @@ public static class Program static void Main(string[] args) { + IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs(); + + if (activatedArgs == null) + { + // No activated event args, so this is not an activation via the multi-instance ID + // Just create a new instance and let App OnActivated resolve the launch + OpenNewInstance(false); + } + var instances = AppInstance.GetInstances(); if (instances.Count == 0) @@ -21,8 +30,6 @@ static void Main(string[] args) ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, null); } - IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs(); - if (activatedArgs is FileActivatedEventArgs) { RedirectOrCreateNewInstance(); @@ -37,7 +44,7 @@ static void Main(string[] args) var protocol = NotepadsProtocolService.GetOperationProtocol(protocolActivatedEventArgs.Uri, out var context); if (protocol == NotepadsOperationProtocol.OpenNewInstance) { - OpenNewInstance(); + OpenNewInstance(true); } else { @@ -54,7 +61,7 @@ static void Main(string[] args) if (protocol == NotepadsOperationProtocol.OpenNewInstance) { handled = true; - OpenNewInstance(); + OpenNewInstance(true); } } @@ -69,12 +76,24 @@ static void Main(string[] args) } } - private static void OpenNewInstance() + private static void OpenNewInstance(bool registerInstance) { - AppInstance.FindOrRegisterInstanceForKey(App.Id.ToString()); - App.IsFirstInstance = IsFirstInstance; + if (registerInstance) + { + AppInstance.FindOrRegisterInstanceForKey(App.Id.ToString()); + App.IsFirstInstance = IsFirstInstance; + } + else + { + App.IsFirstInstance = true; + } + Windows.UI.Xaml.Application.Start(p => new App()); - IsFirstInstance = false; + + if (registerInstance) + { + IsFirstInstance = false; + } } private static void RedirectOrCreateNewInstance() @@ -92,7 +111,7 @@ private static void RedirectOrCreateNewInstance() // open new instance if user prefers to if (ApplicationSettingsStore.Read(SettingsKey.AlwaysOpenNewWindowBool) is bool alwaysOpenNewWindowBool && alwaysOpenNewWindowBool) { - OpenNewInstance(); + OpenNewInstance(true); } else { From a9e59dbb018e2a620d610b3225d7ad124825d839 Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Thu, 13 Feb 2020 13:13:27 -0800 Subject: [PATCH 02/49] remove the start menu entry for the UI extension application --- src/Notepads/Package.appxmanifest | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Notepads/Package.appxmanifest b/src/Notepads/Package.appxmanifest index 49d86c190..a4278642f 100644 --- a/src/Notepads/Package.appxmanifest +++ b/src/Notepads/Package.appxmanifest @@ -375,7 +375,8 @@ Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="Notepads for Game Bar" - BackgroundColor="transparent"> + BackgroundColor="transparent" + AppListEntry="none"> From 0ebea98fd21d2d49ba01c40605d8f69418510776 Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Thu, 5 Mar 2020 14:15:01 -0800 Subject: [PATCH 03/49] update to latest sdk - breaking changes fixed for widget rename --- src/Notepads/App.xaml.cs | 10 +++--- src/Notepads/Notepads.csproj | 2 +- src/Notepads/Package.appxmanifest | 53 ++++++++++++++++--------------- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index e999c0173..1ef3d20af 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -32,7 +32,7 @@ sealed partial class App : Application private const string AppCenterSecret = null; - private XboxGameBarUIExtension XboxGameBarUIExtension = null; + private XboxGameBarWidget XboxGameBarWidget = null; /// /// Initializes the singleton application object. This is the first line of authored code @@ -163,14 +163,14 @@ protected override async void OnFileActivated(FileActivatedEventArgs args) protected override async void OnActivated(IActivatedEventArgs args) { - XboxGameBarUIExtensionActivatedEventArgs uiExtArgs = null; + XboxGameBarWidgetActivatedEventArgs uiExtArgs = null; if (args.Kind == ActivationKind.Protocol) { var protocolArgs = args as IProtocolActivatedEventArgs; string protocolString = protocolArgs.Uri.AbsoluteUri; - if (protocolString.StartsWith("ms-gamebaruiextension")) + if (protocolString.StartsWith("ms-gamebarwidget")) { - uiExtArgs = args as XboxGameBarUIExtensionActivatedEventArgs; + uiExtArgs = args as XboxGameBarWidgetActivatedEventArgs; } } @@ -182,7 +182,7 @@ protected override async void OnActivated(IActivatedEventArgs args) if (IsUiExt) { IsFirstInstance = true; - XboxGameBarUIExtension = new XboxGameBarUIExtension( + XboxGameBarWidget = new XboxGameBarWidget( uiExtArgs, Window.Current.CoreWindow, Window.Current.Content as Frame); diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index ac1974b18..d9c6b44bd 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -496,7 +496,7 @@ 2.6.4 - 1.0.200212001-prerelease + 4.1.200305001-prerelease 6.2.9 diff --git a/src/Notepads/Package.appxmanifest b/src/Notepads/Package.appxmanifest index a4278642f..6036c69cf 100644 --- a/src/Notepads/Package.appxmanifest +++ b/src/Notepads/Package.appxmanifest @@ -391,26 +391,28 @@ - true - true - true - - - 400 - 400 - 400 - 400 - 1000 - 1000 - - - true - true - - + + true + true + true + + + 400 + 400 + 400 + 400 + 1000 + 1000 + + + true + true + + + @@ -421,21 +423,22 @@ + is a required element (by VS) and has to point to a binary in the package, but it's not used when the class id is + 00000355-0000-0000-C000-000000000046 (MBM). Due to that we just put the Microsoft.Gaming.XboxGameBar.winmd here. --> Microsoft.Gaming.XboxGameBar.winmd - - - - - + + + + + - + From 4c90fdc2762ff1f31c9187d758436c9d53c908a7 Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Fri, 6 Mar 2020 11:26:55 -0800 Subject: [PATCH 04/49] remove uneeded file menu entries when running as a widget --- src/Notepads/App.xaml.cs | 38 ++++++-------- src/Notepads/NotepadsMainPage.ViewModes.cs | 58 ++++++++++++---------- src/Notepads/NotepadsMainPage.xaml | 4 +- src/Notepads/NotepadsMainPage.xaml.cs | 10 ++++ src/Notepads/Package.appxmanifest | 23 +++++++++ 5 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index 1ef3d20af..0863d27f1 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -28,11 +28,11 @@ sealed partial class App : Application public static Guid Id { get; } = Guid.NewGuid(); public static bool IsFirstInstance; - public static bool IsUiExt = false; + public static bool IsGameBarWidget = false; private const string AppCenterSecret = null; - private XboxGameBarWidget XboxGameBarWidget = null; + private XboxGameBarWidget m_xboxGameBarWidget = null; /// /// Initializes the singleton application object. This is the first line of authored code @@ -155,35 +155,29 @@ protected override async void OnFileActivated(FileActivatedEventArgs args) base.OnFileActivated(args); } - //protected override async void OnActivated(IActivatedEventArgs args) - //{ - // await ActivateAsync(args); - // base.OnActivated(args); - //} - protected override async void OnActivated(IActivatedEventArgs args) { - XboxGameBarWidgetActivatedEventArgs uiExtArgs = null; + XboxGameBarWidgetActivatedEventArgs uiWidgetArgs = null; if (args.Kind == ActivationKind.Protocol) { var protocolArgs = args as IProtocolActivatedEventArgs; string protocolString = protocolArgs.Uri.AbsoluteUri; if (protocolString.StartsWith("ms-gamebarwidget")) { - uiExtArgs = args as XboxGameBarWidgetActivatedEventArgs; + uiWidgetArgs = args as XboxGameBarWidgetActivatedEventArgs; } } - IsUiExt = uiExtArgs != null; + IsGameBarWidget = uiWidgetArgs != null; await ActivateAsync(args); base.OnActivated(args); - if (IsUiExt) + if (IsGameBarWidget) { IsFirstInstance = true; - XboxGameBarWidget = new XboxGameBarWidget( - uiExtArgs, + m_xboxGameBarWidget = new XboxGameBarWidget( + uiWidgetArgs, Window.Current.CoreWindow, Window.Current.Content as Frame); } @@ -266,10 +260,7 @@ private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) Window.Current.Activate(); - if (IsUiExt != true) - { - ExtendAcrylicIntoTitleBar(); - } + ExtendAcrylicIntoTitleBar(); } private Frame CreateRootFrame(IActivatedEventArgs e) @@ -322,10 +313,13 @@ private void OnSuspending(object sender, SuspendingEventArgs e) private void ExtendAcrylicIntoTitleBar() { - CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true; - ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar; - titleBar.ButtonBackgroundColor = Colors.Transparent; - titleBar.ButtonInactiveBackgroundColor = Colors.Transparent; + if (!IsGameBarWidget) + { + CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true; + ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar; + titleBar.ButtonBackgroundColor = Colors.Transparent; + titleBar.ButtonInactiveBackgroundColor = Colors.Transparent; + } } //private static void UpdateAppVersion() diff --git a/src/Notepads/NotepadsMainPage.ViewModes.cs b/src/Notepads/NotepadsMainPage.ViewModes.cs index 1a66bf5c8..a17e6acc3 100644 --- a/src/Notepads/NotepadsMainPage.ViewModes.cs +++ b/src/Notepads/NotepadsMainPage.ViewModes.cs @@ -34,47 +34,53 @@ private void WindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedE private async void EnterExitCompactOverlayMode() { - if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default) + if (!App.IsGameBarWidget) { - var modeSwitched = await ApplicationView.GetForCurrentView() - .TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay); - if (!modeSwitched) + if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default) { - LoggingService.LogError("Failed to enter CompactOverlay view mode."); - Analytics.TrackEvent("FailedToEnterCompactOverlayViewMode"); + var modeSwitched = await ApplicationView.GetForCurrentView() + .TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay); + if (!modeSwitched) + { + LoggingService.LogError("Failed to enter CompactOverlay view mode."); + Analytics.TrackEvent("FailedToEnterCompactOverlayViewMode"); + } } - } - else if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay) - { - var modeSwitched = await ApplicationView.GetForCurrentView() - .TryEnterViewModeAsync(ApplicationViewMode.Default); - if (!modeSwitched) + else if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay) { - LoggingService.LogError("Failed to enter Default view mode."); - Analytics.TrackEvent("FailedToEnterDefaultViewMode"); + var modeSwitched = await ApplicationView.GetForCurrentView() + .TryEnterViewModeAsync(ApplicationViewMode.Default); + if (!modeSwitched) + { + LoggingService.LogError("Failed to enter Default view mode."); + Analytics.TrackEvent("FailedToEnterDefaultViewMode"); + } } } } private void EnterExitFullScreenMode() { - if (ApplicationView.GetForCurrentView().IsFullScreenMode) - { - LoggingService.LogInfo("Existing full screen view mode.", consoleOnly: true); - ApplicationView.GetForCurrentView().ExitFullScreenMode(); - } - else + if(!App.IsGameBarWidget) { - if (ApplicationView.GetForCurrentView().TryEnterFullScreenMode()) + if (ApplicationView.GetForCurrentView().IsFullScreenMode) { - LoggingService.LogInfo("Entered full screen view mode.", consoleOnly: true); - NotificationCenter.Instance.PostNotification( - _resourceLoader.GetString("TextEditor_NotificationMsg_ExitFullScreenHint"), 3000); + LoggingService.LogInfo("Existing full screen view mode.", consoleOnly: true); + ApplicationView.GetForCurrentView().ExitFullScreenMode(); } else { - LoggingService.LogError("Failed to enter full screen view mode."); - Analytics.TrackEvent("FailedToEnterFullScreenViewMode"); + if (ApplicationView.GetForCurrentView().TryEnterFullScreenMode()) + { + LoggingService.LogInfo("Entered full screen view mode.", consoleOnly: true); + NotificationCenter.Instance.PostNotification( + _resourceLoader.GetString("TextEditor_NotificationMsg_ExitFullScreenHint"), 3000); + } + else + { + LoggingService.LogError("Failed to enter full screen view mode."); + Analytics.TrackEvent("FailedToEnterFullScreenViewMode"); + } } } } diff --git a/src/Notepads/NotepadsMainPage.xaml b/src/Notepads/NotepadsMainPage.xaml index 55a6087fc..4f9b478da 100644 --- a/src/Notepads/NotepadsMainPage.xaml +++ b/src/Notepads/NotepadsMainPage.xaml @@ -133,7 +133,7 @@ - + @@ -150,7 +150,7 @@ - + - From a15140df13826210400bcc74344d5a623b47d299 Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Tue, 10 Mar 2020 08:48:02 -0700 Subject: [PATCH 07/49] in progress settings changes --- src/Notepads/App.xaml.cs | 38 +++++++++++++++++++++++++------ src/Notepads/Notepads.csproj | 2 +- src/Notepads/Package.appxmanifest | 16 ++++++------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index fe40a177a..6a0b2e558 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -9,6 +9,7 @@ using Microsoft.AppCenter.Crashes; using Microsoft.Gaming.XboxGameBar; using Microsoft.Toolkit.Uwp.Helpers; + using Notepads.Controls.Settings; using Notepads.Services; using Notepads.Settings; using Notepads.Utilities; @@ -33,6 +34,7 @@ sealed partial class App : Application private const string AppCenterSecret = null; private XboxGameBarWidget m_xboxGameBarWidget = null; + private XboxGameBarWidget m_xboxGameBarSettingsWidget = null; /// /// Initializes the singleton application object. This is the first line of authored code @@ -155,18 +157,18 @@ protected override async void OnFileActivated(FileActivatedEventArgs args) protected override async void OnActivated(IActivatedEventArgs args) { - XboxGameBarWidgetActivatedEventArgs uiWidgetArgs = null; + XboxGameBarWidgetActivatedEventArgs widgetArgs = null; if (args.Kind == ActivationKind.Protocol) { var protocolArgs = args as IProtocolActivatedEventArgs; string protocolString = protocolArgs.Uri.AbsoluteUri; if (protocolString.StartsWith("ms-gamebarwidget")) { - uiWidgetArgs = args as XboxGameBarWidgetActivatedEventArgs; + widgetArgs = args as XboxGameBarWidgetActivatedEventArgs; } } - IsGameBarWidget = uiWidgetArgs != null; + IsGameBarWidget = widgetArgs != null; await ActivateAsync(args); base.OnActivated(args); @@ -174,10 +176,32 @@ protected override async void OnActivated(IActivatedEventArgs args) if (IsGameBarWidget) { IsFirstInstance = true; - m_xboxGameBarWidget = new XboxGameBarWidget( - uiWidgetArgs, - Window.Current.CoreWindow, - Window.Current.Content as Frame); + + if (widgetArgs.AppExtensionId == "Notepads") + { + + m_xboxGameBarWidget = new XboxGameBarWidget( + widgetArgs, + Window.Current.CoreWindow, + Window.Current.Content as Frame); + } + else if(widgetArgs.AppExtensionId == "NotepadsSettings") + { + Frame rootFrame = Window.Current.Content as Frame; + + //m_xboxGameBarSettingsWidget = new XboxGameBarWidget( + // widgetArgs, + // Window.Current.CoreWindow, + // Window.Current.Content as Frame); + + //rootFrame.Navigate(typeof(SettingsPage), widgetArgs.Uri); + //SettingsFrame.Navigate(typeof(SettingsPage), null, new SuppressNavigationTransitionInfo()); + } + else + { + // Unknown - Game Bar should never send an unknown App Extension Id + return; + } } } diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index d8cf4c870..71fc1b5d5 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -561,7 +561,7 @@ 3.0.0 - 4.1.200305001-prerelease + 4.1.200310001-prerelease 6.2.9 diff --git a/src/Notepads/Package.appxmanifest b/src/Notepads/Package.appxmanifest index 793fd7c1b..0fc3a5119 100644 --- a/src/Notepads/Package.appxmanifest +++ b/src/Notepads/Package.appxmanifest @@ -398,6 +398,7 @@ true true true + 400 @@ -416,12 +417,11 @@ - @@ -451,11 +450,12 @@ Microsoft.Gaming.XboxGameBar.winmd - - - - - + + + + + + From d95a13f5e11aad2b33e7743aaafb5f11413bd3df Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Tue, 10 Mar 2020 15:36:57 -0700 Subject: [PATCH 08/49] cleanup activation to match existing patterns, enable settings widget --- src/Notepads/App.xaml.cs | 47 ------------------- .../Controls/Settings/SettingsPage.xaml.cs | 18 +++++++ src/Notepads/NotepadsMainPage.xaml.cs | 26 +++++++++- src/Notepads/Package.appxmanifest | 2 +- src/Notepads/Services/ActivationService.cs | 34 ++++++++++++++ 5 files changed, 78 insertions(+), 49 deletions(-) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index 6a0b2e558..7b2dbce47 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -33,9 +33,6 @@ sealed partial class App : Application private const string AppCenterSecret = null; - private XboxGameBarWidget m_xboxGameBarWidget = null; - private XboxGameBarWidget m_xboxGameBarSettingsWidget = null; - /// /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). @@ -157,52 +154,8 @@ protected override async void OnFileActivated(FileActivatedEventArgs args) protected override async void OnActivated(IActivatedEventArgs args) { - XboxGameBarWidgetActivatedEventArgs widgetArgs = null; - if (args.Kind == ActivationKind.Protocol) - { - var protocolArgs = args as IProtocolActivatedEventArgs; - string protocolString = protocolArgs.Uri.AbsoluteUri; - if (protocolString.StartsWith("ms-gamebarwidget")) - { - widgetArgs = args as XboxGameBarWidgetActivatedEventArgs; - } - } - - IsGameBarWidget = widgetArgs != null; - await ActivateAsync(args); base.OnActivated(args); - - if (IsGameBarWidget) - { - IsFirstInstance = true; - - if (widgetArgs.AppExtensionId == "Notepads") - { - - m_xboxGameBarWidget = new XboxGameBarWidget( - widgetArgs, - Window.Current.CoreWindow, - Window.Current.Content as Frame); - } - else if(widgetArgs.AppExtensionId == "NotepadsSettings") - { - Frame rootFrame = Window.Current.Content as Frame; - - //m_xboxGameBarSettingsWidget = new XboxGameBarWidget( - // widgetArgs, - // Window.Current.CoreWindow, - // Window.Current.Content as Frame); - - //rootFrame.Navigate(typeof(SettingsPage), widgetArgs.Uri); - //SettingsFrame.Navigate(typeof(SettingsPage), null, new SuppressNavigationTransitionInfo()); - } - else - { - // Unknown - Game Bar should never send an unknown App Extension Id - return; - } - } } private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) diff --git a/src/Notepads/Controls/Settings/SettingsPage.xaml.cs b/src/Notepads/Controls/Settings/SettingsPage.xaml.cs index 9fa6952e7..bd09204c0 100644 --- a/src/Notepads/Controls/Settings/SettingsPage.xaml.cs +++ b/src/Notepads/Controls/Settings/SettingsPage.xaml.cs @@ -1,11 +1,15 @@ namespace Notepads.Controls.Settings { + using Microsoft.Gaming.XboxGameBar; using System.Linq; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; + using Windows.UI.Xaml.Navigation; public sealed partial class SettingsPage : Page { + private XboxGameBarWidget _widget; // maintain throughout the lifetime of the settings widget + public SettingsPage() { InitializeComponent(); @@ -17,6 +21,20 @@ private void SettingsPage_Loaded(object sender, RoutedEventArgs e) ((NavigationViewItem)SettingsNavigationView.MenuItems.First()).IsSelected = true; } + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + + switch (e.Parameter) + { + case null: + return; + case XboxGameBarWidget widget: + _widget = widget; + break; + } + } + private void SettingsPanel_OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) { SettingsPanel.Show((args.InvokedItem as string), (args.InvokedItemContainer as NavigationViewItem)?.Tag as string); diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index f27ba4165..acaaef739 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -27,8 +27,9 @@ using Windows.UI.Xaml.Media.Animation; using Windows.UI.Xaml.Navigation; using Microsoft.AppCenter.Analytics; + using Microsoft.Gaming.XboxGameBar; using Windows.Graphics.Printing; - + public sealed partial class NotepadsMainPage : Page, INotificationDelegate { private IReadOnlyList _appLaunchFiles; @@ -51,6 +52,9 @@ public sealed partial class NotepadsMainPage : Page, INotificationDelegate private INotepadsCore _notepadsCore; + private XboxGameBarWidget _widget; // maintain throughout the lifetime of the notepads widget + private XboxGameBarWidgetControl _widgetControl; + private INotepadsCore NotepadsCore { get @@ -373,6 +377,17 @@ protected override void OnNavigatedTo(NavigationEventArgs e) case ProtocolActivatedEventArgs protocol: _appLaunchUri = protocol.Uri; break; + case XboxGameBarWidget widget: + _widget = widget; + _widgetControl = new XboxGameBarWidgetControl(_widget); + _widget.SettingsClicked += Widget_SettingsClicked; + //_widget.PinnedChanged += Widget_PinnedChanged; + //_widget.FavoritedChanged += Widget_FavoritedChanged; + //_widget.RequestedThemeChanged += Widget_RequestedThemeChanged; + //_widget.VisibleChanged += Widget_VisibleChanged; + //_widget.WindowStateChanged += Widget_WindowStateChanged; + //_widget.GameBarDisplayModeChanged += Widget_GameBarDisplayModeChanged; + break; } } @@ -577,6 +592,15 @@ private async void MainPage_CloseRequested(object sender, Windows.UI.Core.Previe #endregion + #region XboxGameBar + + private async void Widget_SettingsClicked(XboxGameBarWidget sender, object args) + { + await _widget.ActivateSettingsAsync(); + } + + #endregion + #region InAppNotification public void PostNotification(string message, int duration) diff --git a/src/Notepads/Package.appxmanifest b/src/Notepads/Package.appxmanifest index 0fc3a5119..1d88e6b4c 100644 --- a/src/Notepads/Package.appxmanifest +++ b/src/Notepads/Package.appxmanifest @@ -428,7 +428,7 @@ 400 - 200 + 300 false diff --git a/src/Notepads/Services/ActivationService.cs b/src/Notepads/Services/ActivationService.cs index aa2c538c9..f90fb79f5 100644 --- a/src/Notepads/Services/ActivationService.cs +++ b/src/Notepads/Services/ActivationService.cs @@ -1,8 +1,11 @@ namespace Notepads.Services { using System.Threading.Tasks; + using Microsoft.Gaming.XboxGameBar; + using Notepads.Controls.Settings; using Notepads.Utilities; using Windows.ApplicationModel.Activation; + using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; public static class ActivationService @@ -25,6 +28,10 @@ public static async Task ActivateAsync(Frame rootFrame, IActivatedEventArgs e) { LaunchActivated(rootFrame, launchActivatedEventArgs); } + else if (e is XboxGameBarWidgetActivatedEventArgs xboxGameBarWidgetActivatedEventArgs) + { + GameBarActivated(rootFrame, xboxGameBarWidgetActivatedEventArgs); + } else // For other types of activated events { if (rootFrame.Content == null) @@ -34,6 +41,33 @@ public static async Task ActivateAsync(Frame rootFrame, IActivatedEventArgs e) } } + public static void GameBarActivated(Frame rootFrame, XboxGameBarWidgetActivatedEventArgs xboxGameBarWidgetActivatedEventArgs) + { + LoggingService.LogInfo($"[XboxGameBarWidgetActivated] AppExtensionId: {xboxGameBarWidgetActivatedEventArgs.AppExtensionId}"); + + if (xboxGameBarWidgetActivatedEventArgs != null) + { + if (xboxGameBarWidgetActivatedEventArgs.IsLaunchActivation) + { + App.IsFirstInstance = true; + + var xboxGameBarWidget = new XboxGameBarWidget( + xboxGameBarWidgetActivatedEventArgs, + Window.Current.CoreWindow, + rootFrame); + + if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "Notepads") + { + rootFrame.Navigate(typeof(NotepadsMainPage), xboxGameBarWidget); + } + else if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "NotepadsSettings") + { + rootFrame.Navigate(typeof(SettingsPage), xboxGameBarWidget); + } + } + } + } + private static void ProtocolActivated(Frame rootFrame, ProtocolActivatedEventArgs protocolActivatedEventArgs) { LoggingService.LogInfo($"[ProtocolActivated] Protocol: {protocolActivatedEventArgs.Uri}"); From a9aa7df21f7a86ca10b033b303dd13ba49c5e475 Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Wed, 11 Mar 2020 16:01:05 -0700 Subject: [PATCH 09/49] update most settings to be thread safe when running in game bar, theme not yet supported --- .../Controls/TextEditor/TextEditor.xaml.cs | 56 ++++++++++++------- .../Controls/TextEditor/TextEditorCore.cs | 39 +++++++++---- src/Notepads/Notepads.csproj | 2 +- src/Notepads/NotepadsMainPage.xaml.cs | 30 ++++++---- src/Notepads/Services/ActivationService.cs | 1 + 5 files changed, 84 insertions(+), 44 deletions(-) diff --git a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs index 49e7f4866..37154e223 100644 --- a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs +++ b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs @@ -977,42 +977,60 @@ private void DrawLineHighlighter() } } - private void LineHighlighter_OnViewStateChanged(object sender, bool enabled) + private async void LineHighlighter_OnViewStateChanged(object sender, bool enabled) { - if (enabled) + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { - LineHighlighter.Visibility = Visibility.Visible; - DrawLineHighlighter(); - } - else - { - LineHighlighter.Visibility = Visibility.Collapsed; - } + if (enabled) + { + LineHighlighter.Visibility = Visibility.Visible; + DrawLineHighlighter(); + } + else + { + LineHighlighter.Visibility = Visibility.Collapsed; + } + }); } - private void LineHighlighter_OnSelectionChanged(object sender, RoutedEventArgs e) + private async void LineHighlighter_OnSelectionChanged(object sender, RoutedEventArgs e) { - if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + }); } - private void LineHighlighter_OnTextWrappingChanged(object sender, TextWrapping e) + private async void LineHighlighter_OnTextWrappingChanged(object sender, TextWrapping e) { - if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + }); } - private void LineHighlighter_OnFontSizeChanged(object sender, double e) + private async void LineHighlighter_OnFontSizeChanged(object sender, double e) { - if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + }); } - private void LineHighlighter_WindowSizeChanged(object sender, SizeChangedEventArgs e) + private async void LineHighlighter_WindowSizeChanged(object sender, SizeChangedEventArgs e) { - if (EditorSettingsService.EditorDefaultTextWrapping == TextWrapping.Wrap && EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + if (EditorSettingsService.EditorDefaultTextWrapping == TextWrapping.Wrap && EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + }); } - private void LineHighlighter_OnScrolled(object sender, ScrollViewerViewChangedEventArgs e) + private async void LineHighlighter_OnScrolled(object sender, ScrollViewerViewChangedEventArgs e) { - if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); + }); } } } \ No newline at end of file diff --git a/src/Notepads/Controls/TextEditor/TextEditorCore.cs b/src/Notepads/Controls/TextEditor/TextEditorCore.cs index 594bd8c0d..d1e7af914 100644 --- a/src/Notepads/Controls/TextEditor/TextEditorCore.cs +++ b/src/Notepads/Controls/TextEditor/TextEditorCore.cs @@ -149,31 +149,46 @@ public void Dispose() _contentLinesCache = null; } - private void EditorSettingsService_OnFontFamilyChanged(object sender, string fontFamily) + private async void EditorSettingsService_OnFontFamilyChanged(object sender, string fontFamily) { - FontFamily = new FontFamily(fontFamily); - SetDefaultTabStopAndLineSpacing(FontFamily, FontSize); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + FontFamily = new FontFamily(fontFamily); + SetDefaultTabStopAndLineSpacing(FontFamily, FontSize); + }); } - private void EditorSettingsService_OnFontSizeChanged(object sender, int fontSize) + private async void EditorSettingsService_OnFontSizeChanged(object sender, int fontSize) { - FontSize = fontSize; + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + FontSize = fontSize; + }); } - private void EditorSettingsService_OnDefaultTextWrappingChanged(object sender, TextWrapping textWrapping) + private async void EditorSettingsService_OnDefaultTextWrappingChanged(object sender, TextWrapping textWrapping) { - TextWrapping = textWrapping; + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + TextWrapping = textWrapping; + }); } - private void EditorSettingsService_OnHighlightMisspelledWordsChanged(object sender, bool isSpellCheckEnabled) + private async void EditorSettingsService_OnHighlightMisspelledWordsChanged(object sender, bool isSpellCheckEnabled) { - IsSpellCheckEnabled = isSpellCheckEnabled; + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + IsSpellCheckEnabled = isSpellCheckEnabled; + }); } - private void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color color) + private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color color) { - SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; - SelectionHighlightColorWhenNotFocused = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + SelectionHighlightColorWhenNotFocused = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + }); } private KeyboardCommandHandler GetKeyboardCommandHandler() diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index 71fc1b5d5..5dd7f3ee0 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -561,7 +561,7 @@ 3.0.0 - 4.1.200310001-prerelease + 4.1.200311001-prerelease 6.2.9 diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index acaaef739..fb15bbbed 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -128,25 +128,31 @@ public NotepadsMainPage() // Setup status bar ShowHideStatusBar(EditorSettingsService.ShowStatusBar); - EditorSettingsService.OnStatusBarVisibilityChanged += (sender, visibility) => + EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => { - if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, ()=> + { + if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); + }); }; // Session backup and restore toggle EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => { - if (isSessionBackupAndRestoreEnabled) - { - SessionManager.IsBackupEnabled = true; - SessionManager.StartSessionBackup(startImmediately: true); - } - else + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => { - SessionManager.IsBackupEnabled = false; - SessionManager.StopSessionBackup(); - await SessionManager.ClearSessionDataAsync(); - } + if (isSessionBackupAndRestoreEnabled) + { + SessionManager.IsBackupEnabled = true; + SessionManager.StartSessionBackup(startImmediately: true); + } + else + { + SessionManager.IsBackupEnabled = false; + SessionManager.StopSessionBackup(); + await SessionManager.ClearSessionDataAsync(); + } + }); }; // Sharing diff --git a/src/Notepads/Services/ActivationService.cs b/src/Notepads/Services/ActivationService.cs index f90fb79f5..d93fc607e 100644 --- a/src/Notepads/Services/ActivationService.cs +++ b/src/Notepads/Services/ActivationService.cs @@ -50,6 +50,7 @@ public static void GameBarActivated(Frame rootFrame, XboxGameBarWidgetActivatedE if (xboxGameBarWidgetActivatedEventArgs.IsLaunchActivation) { App.IsFirstInstance = true; + App.IsGameBarWidget = true; var xboxGameBarWidget = new XboxGameBarWidget( xboxGameBarWidgetActivatedEventArgs, From 0fc5d9e12651ba920fe137f8e7e25c76cb92110f Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Thu, 12 Mar 2020 12:49:16 -0700 Subject: [PATCH 10/49] disable unused features in settings background opacity and the ability to start multiple instances are not supported in game bar scenario, hide these settings --- src/Notepads/Controls/Settings/AdvancedSettings.xaml | 3 ++- src/Notepads/Controls/Settings/AdvancedSettings.xaml.cs | 7 +++++++ .../Controls/Settings/PersonalizationSettings.xaml | 4 ++-- .../Controls/Settings/PersonalizationSettings.xaml.cs | 7 +++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Notepads/Controls/Settings/AdvancedSettings.xaml b/src/Notepads/Controls/Settings/AdvancedSettings.xaml index 6dcfbc7e6..aecd4fcda 100644 --- a/src/Notepads/Controls/Settings/AdvancedSettings.xaml +++ b/src/Notepads/Controls/Settings/AdvancedSettings.xaml @@ -49,11 +49,12 @@ - + - - + Date: Thu, 12 Mar 2020 14:06:28 -0700 Subject: [PATCH 11/49] fix issues with settings page not being on the main page UI thread --- .../FindAndReplaceControl.xaml.cs | 8 +++- .../Controls/GoTo/GoToControl.xaml.cs | 8 +++- .../Controls/Settings/SettingsPage.xaml.cs | 28 ++++++++++++ .../Controls/TextEditor/ITextEditor.cs | 2 + .../Controls/TextEditor/TextEditor.xaml.cs | 13 ++++++ src/Notepads/Core/NotepadsCore.cs | 5 ++- .../DiffViewer/SideBySideDiffViewer.xaml.cs | 9 ++-- src/Notepads/NotepadsMainPage.xaml.cs | 30 ++++++++++++- src/Notepads/Services/ThemeSettingsService.cs | 43 +++++++++++-------- 9 files changed, 117 insertions(+), 29 deletions(-) diff --git a/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs b/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs index bac909f77..d8fe31a07 100644 --- a/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs +++ b/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs @@ -3,6 +3,7 @@ using System; using Notepads.Services; using Windows.System; + using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; @@ -39,9 +40,12 @@ private void FindAndReplaceControl_Unloaded(object sender, RoutedEventArgs e) ThemeSettingsService.OnAccentColorChanged -= ThemeSettingsService_OnAccentColorChanged; } - private void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color e) + private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color e) { - SetSelectionHighlightColor(); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + SetSelectionHighlightColor(); + }); } public double GetHeight(bool showReplaceBar) diff --git a/src/Notepads/Controls/GoTo/GoToControl.xaml.cs b/src/Notepads/Controls/GoTo/GoToControl.xaml.cs index abf282a21..ae84dc6bd 100644 --- a/src/Notepads/Controls/GoTo/GoToControl.xaml.cs +++ b/src/Notepads/Controls/GoTo/GoToControl.xaml.cs @@ -4,6 +4,7 @@ using Notepads.Services; using Windows.ApplicationModel.Resources; using Windows.System; + using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; @@ -53,9 +54,12 @@ private void GoToControl_Unloaded(object sender, RoutedEventArgs e) ThemeSettingsService.OnAccentColorChanged -= ThemeSettingsService_OnAccentColorChanged; } - private void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color e) + private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color e) { - SetSelectionHighlightColor(); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + SetSelectionHighlightColor(); + }); } public double GetHeight() diff --git a/src/Notepads/Controls/Settings/SettingsPage.xaml.cs b/src/Notepads/Controls/Settings/SettingsPage.xaml.cs index bd09204c0..5d32b6342 100644 --- a/src/Notepads/Controls/Settings/SettingsPage.xaml.cs +++ b/src/Notepads/Controls/Settings/SettingsPage.xaml.cs @@ -1,9 +1,13 @@ namespace Notepads.Controls.Settings { using Microsoft.Gaming.XboxGameBar; + using Notepads.Services; + using System; using System.Linq; + using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; + using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; public sealed partial class SettingsPage : Page @@ -14,6 +18,30 @@ public SettingsPage() { InitializeComponent(); Loaded += SettingsPage_Loaded; + + if (App.IsGameBarWidget) + { + ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; + ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; + + ThemeSettingsService.SetRequestedTheme(null, Window.Current.Content, null); + } + } + + private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedAccentColor(); + }); + } + + private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedTheme(null, Window.Current.Content, null); + }); } private void SettingsPage_Loaded(object sender, RoutedEventArgs e) diff --git a/src/Notepads/Controls/TextEditor/ITextEditor.cs b/src/Notepads/Controls/TextEditor/ITextEditor.cs index e0553cbb7..6c3843c52 100644 --- a/src/Notepads/Controls/TextEditor/ITextEditor.cs +++ b/src/Notepads/Controls/TextEditor/ITextEditor.cs @@ -6,6 +6,7 @@ using Notepads.Models; using Notepads.Utilities; using Windows.Storage; + using Windows.UI; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; @@ -27,6 +28,7 @@ public interface ITextEditor event EventHandler ChangeReverted; event EventHandler FileSaved; event EventHandler FileReloaded; + event EventHandler AccentColorChanged; Guid Id { get; set; } diff --git a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs index 37154e223..2650e2f3e 100644 --- a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs +++ b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs @@ -19,6 +19,7 @@ using Windows.ApplicationModel.Resources; using Windows.Storage; using Windows.System; + using Windows.UI; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -71,6 +72,8 @@ public sealed partial class TextEditor : UserControl, ITextEditor public event EventHandler FileReloaded; + public event EventHandler AccentColorChanged; + private const char RichEditBoxDefaultLineEnding = '\r'; public string FileNamePlaceholder { get; set; } = string.Empty; @@ -187,6 +190,7 @@ public TextEditor() _keyboardCommandHandler = GetKeyboardCommandHandler(); ThemeSettingsService.OnThemeChanged += ThemeSettingsService_OnThemeChanged; + ThemeSettingsService.OnAccentColorChanged += ThemeSettingsService_OnAccentColorChanged; base.Loaded += TextEditor_Loaded; base.Unloaded += TextEditor_Unloaded; @@ -223,6 +227,7 @@ public void Dispose() } ThemeSettingsService.OnThemeChanged -= ThemeSettingsService_OnThemeChanged; + ThemeSettingsService.OnAccentColorChanged -= ThemeSettingsService_OnAccentColorChanged; Unloaded?.Invoke(this, new RoutedEventArgs()); @@ -285,6 +290,14 @@ private void ThemeSettingsService_OnThemeChanged(object sender, ElementTheme the } } + private void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color color) + { + Dispatcher.RunAsync(() => + { + AccentColorChanged?.Invoke(this, color); + }); + } + public string GetText() { return TextEditorCore.GetText(); diff --git a/src/Notepads/Core/NotepadsCore.cs b/src/Notepads/Core/NotepadsCore.cs index 423576884..274fdf093 100644 --- a/src/Notepads/Core/NotepadsCore.cs +++ b/src/Notepads/Core/NotepadsCore.cs @@ -86,7 +86,6 @@ public NotepadsCore(SetsView sets, Sets.DragItemsCompleted += Sets_DragItemsCompleted; _extensionProvider = extensionProvider; - ThemeSettingsService.OnAccentColorChanged += OnAppAccentColorChanged; } public void OpenNewTextEditor(string fileNamePlaceholder) @@ -134,6 +133,8 @@ public void OpenTextEditor(ITextEditor textEditor, int atIndex = -1) Sets.ScrollToLastSet(); } } + + textEditor.AccentColorChanged += TextEditor_AccentColorChanged; } public void OpenTextEditors(ITextEditor[] editors, Guid? selectedEditorId = null) @@ -543,7 +544,7 @@ private void TextEditor_OnLineEndingChanged(object sender, EventArgs e) TextEditorLineEndingChanged?.Invoke(this, textEditor); } - private void OnAppAccentColorChanged(object sender, Color color) + private void TextEditor_AccentColorChanged(object sender, Color e) { if (Sets.Items == null) return; foreach (SetsViewItem item in Sets.Items) diff --git a/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs b/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs index cf31a31d9..70428f460 100644 --- a/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs +++ b/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs @@ -65,10 +65,13 @@ private void SideBySideDiffViewer_Loaded(object sender, RoutedEventArgs e) Focus(); } - private void ThemeSettingsService_OnAccentColorChanged(object sender, Color color) + private async void ThemeSettingsService_OnAccentColorChanged(object sender, Color color) { - LeftBox.SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; - RightBox.SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + LeftBox.SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + RightBox.SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + }); } private KeyboardCommandHandler GetKeyboardCommandHandler() diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index fb15bbbed..7ece11c60 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -120,8 +120,10 @@ public NotepadsMainPage() NotificationCenter.Instance.SetNotificationDelegate(this); // Setup theme - ThemeSettingsService.AppBackground = RootGrid; - ThemeSettingsService.SetRequestedTheme(); + ThemeSettingsService.OnBackgroundChanged += ThemeSettingsService_OnBackgroundChanged; + ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; + ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; + ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); // Setup custom Title Bar Window.Current.SetTitleBar(AppTitleBar); @@ -180,6 +182,30 @@ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async ( } } + private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedAccentColor(); + }); + } + + private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); + }); + } + + private async void ThemeSettingsService_OnBackgroundChanged(object sender, Brush backgroundBrush) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + RootGrid.Background = backgroundBrush; + }); + } + private void InitControls() { ToolTipService.SetToolTip(ExitCompactOverlayButton, _resourceLoader.GetString("App_ExitCompactOverlayMode_Text")); diff --git a/src/Notepads/Services/ThemeSettingsService.cs b/src/Notepads/Services/ThemeSettingsService.cs index f2bc868fb..001859d8b 100644 --- a/src/Notepads/Services/ThemeSettingsService.cs +++ b/src/Notepads/Services/ThemeSettingsService.cs @@ -21,8 +21,12 @@ public static class ThemeSettingsService private static UISettings _uiSettings; public static event EventHandler OnThemeChanged; + public static event EventHandler OnRequestThemeUpdate; + + public static event EventHandler OnBackgroundChanged; public static event EventHandler OnAccentColorChanged; + public static event EventHandler OnRequestAccentColorUpdate; public static ElementTheme ThemeMode { get; set; } @@ -39,7 +43,7 @@ public static bool UseWindowsTheme if (value) { ThemeMode = ApplicationThemeToElementTheme(Application.Current.RequestedTheme); - SetRequestedTheme(); + OnRequestThemeUpdate?.Invoke(null, null); } ApplicationSettingsStore.Write(SettingsKey.UseWindowsThemeBool, _useWindowsTheme, true); } @@ -62,8 +66,6 @@ public static bool UseWindowsAccentColor } } - public static Panel AppBackground { get; set; } - private static double _appBackgroundPanelTintOpacity; public static double AppBackgroundPanelTintOpacity @@ -72,11 +74,9 @@ public static double AppBackgroundPanelTintOpacity set { _appBackgroundPanelTintOpacity = value; - if (AppBackground != null) - { - AppBackground.Background = GetBackgroundBrush(ThemeMode, changingOpacityOnly: true); - ApplicationSettingsStore.Write(SettingsKey.AppBackgroundTintOpacityDouble, value, true); - } + + OnBackgroundChanged?.Invoke(null, GetBackgroundBrush(ThemeMode, changingOpacityOnly: true)); + ApplicationSettingsStore.Write(SettingsKey.AppBackgroundTintOpacityDouble, value, true); } } @@ -88,7 +88,7 @@ public static Color AppAccentColor set { _appAccentColor = value; - UpdateSystemAccentColorAndBrushes(value); + OnRequestAccentColorUpdate?.Invoke(null, EventArgs.Empty); ApplicationSettingsStore.Write(SettingsKey.AppAccentColorHexStr, value.ToHex(), true); OnAccentColorChanged?.Invoke(null, value); } @@ -188,6 +188,7 @@ private static void ThemeListener_ThemeChanged(ThemeListener sender) SetTheme(sender.CurrentTheme); } }); + } public static void SetTheme(ApplicationTheme theme) @@ -198,25 +199,28 @@ public static void SetTheme(ApplicationTheme theme) public static void SetTheme(ElementTheme theme) { ThemeMode = theme; - SetRequestedTheme(); + OnRequestThemeUpdate?.Invoke(null, EventArgs.Empty); ApplicationSettingsStore.Write(SettingsKey.RequestedThemeStr, ThemeMode.ToString(), true); } - public static void SetRequestedTheme() + public static void SetRequestedTheme(Panel backgroundPanel, UIElement currentContent, ApplicationViewTitleBar titleBar) { // Set requested theme for app background - if (AppBackground != null) + if (backgroundPanel != null) { - ApplyAcrylicBrush(ThemeMode, AppBackground); + ApplyAcrylicBrush(ThemeMode, backgroundPanel); } - if (Window.Current.Content is FrameworkElement frameworkElement) + if (currentContent is FrameworkElement frameworkElement) { frameworkElement.RequestedTheme = ThemeMode; } // Set requested theme for app title bar - ApplyThemeForTitleBarButtons(ThemeMode); + if (titleBar != null) + { + ApplyThemeForTitleBarButtons(titleBar, ThemeMode); + } // Set ContentDialog background dimming color ((SolidColorBrush)Application.Current.Resources["SystemControlPageBackgroundMediumAltMediumBrush"]).Color = ThemeMode == ElementTheme.Dark ? Color.FromArgb(153, 0, 0, 0) : Color.FromArgb(153, 255, 255, 255); @@ -227,6 +231,11 @@ public static void SetRequestedTheme() OnThemeChanged?.Invoke(null, ThemeMode); } + public static void SetRequestedAccentColor() + { + UpdateSystemAccentColorAndBrushes(AppAccentColor); + } + private static ElementTheme ApplicationThemeToElementTheme(ApplicationTheme theme) { switch (theme) @@ -322,10 +331,8 @@ public static void ApplyAcrylicBrush(ElementTheme theme, Panel panel) panel.Background = GetBackgroundBrush(theme); } - public static void ApplyThemeForTitleBarButtons(ElementTheme theme) + public static void ApplyThemeForTitleBarButtons(ApplicationViewTitleBar titleBar, ElementTheme theme) { - var titleBar = ApplicationView.GetForCurrentView().TitleBar; - if (theme == ElementTheme.Dark) { // Set active window colors From 1b768b70edebacdd63714b99a26d18a53e789c4c Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Tue, 17 Mar 2020 10:34:56 -0700 Subject: [PATCH 12/49] update to 5.1.200317001-prerelease game bar sdk --- src/Notepads/Notepads.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index 6831a0c59..5223c73ac 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -562,7 +562,7 @@ 3.0.0 - 4.1.200311001-prerelease + 5.1.200317001-prerelease 6.2.9 From afe8a60654ec10f9da3daa11498e2ac9ecc11f7f Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Wed, 1 Apr 2020 10:43:26 -0700 Subject: [PATCH 13/49] Update to the release version of Game Bar SDK [5.1.200401003] --- src/Notepads/Notepads.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index 5223c73ac..bc029b936 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -562,7 +562,7 @@ 3.0.0 - 5.1.200317001-prerelease + 5.1.200401003 6.2.9 From bb59241801ed38ad391787397c2140a309073aa0 Mon Sep 17 00:00:00 2001 From: Eric Hamilton Date: Wed, 1 Apr 2020 12:25:53 -0700 Subject: [PATCH 14/49] fix hang on shutdown when opening settings widget --- src/Notepads/NotepadsMainPage.xaml.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index 088067615..9e4b658c9 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -503,8 +503,18 @@ private async void Sets_Loaded(object sender, RoutedEventArgs e) Window.Current.CoreWindow.Activated -= CoreWindow_Activated; Window.Current.CoreWindow.Activated += CoreWindow_Activated; - Application.Current.EnteredBackground -= App_EnteredBackground; - Application.Current.EnteredBackground += App_EnteredBackground; + + if (!App.IsGameBarWidget) + { + // An issue with the Game Bar extension model and Windows platform prevents the Notepads process from exiting cleanly + // when more than one CoreWindow has been created, and NotepadsMainPage is the last to close. The common case for this + // is to open Notepads in Game Bar, then open its settings, then close the settings and finally close Notepads. + // This puts the process in a bad state where it will no longer open in Game Bar and the Notepads process is orphaned. + // To work around this do not use the EnteredBackground event when running as a widget. + // Microsoft is tracking this issue as VSO#25735260 + Application.Current.EnteredBackground -= App_EnteredBackground; + Application.Current.EnteredBackground += App_EnteredBackground; + } } private async void App_EnteredBackground(object sender, Windows.ApplicationModel.EnteredBackgroundEventArgs e) From a87f7a40f279a91d14009fcc903f6864225bd999 Mon Sep 17 00:00:00 2001 From: Ben McGregor Date: Thu, 2 Apr 2020 14:25:00 -0700 Subject: [PATCH 15/49] Cleanup Game Bar launch path and fix some exceptions --- src/Notepads/App.xaml.cs | 161 +- .../Controls/TextEditor/TextEditor.xaml.cs | 2 +- src/Notepads/Notepads.csproj | 1432 ++++++++--------- src/Notepads/NotepadsMainPage.xaml.cs | 108 +- src/Notepads/Program.cs | 30 +- src/Notepads/Services/ActivationService.cs | 9 +- 6 files changed, 842 insertions(+), 900 deletions(-) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index 69a89c91a..c961a31c2 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -15,20 +15,23 @@ using Notepads.Utilities; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; - using Windows.ApplicationModel.Core; + using Windows.ApplicationModel.Core; + using Windows.System.UserProfile; using Windows.UI; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; - using Windows.UI.Xaml.Navigation; - + using Windows.UI.Xaml.Navigation; + using System.Runtime.InteropServices; + using Windows.UI.Core; + sealed partial class App : Application { public static string ApplicationName = "Notepads"; public static Guid Id { get; } = Guid.NewGuid(); - public static bool IsFirstInstance; + public static bool IsFirstInstance = false; public static bool IsGameBarWidget = false; private const string AppCenterSecret = null; @@ -47,7 +50,7 @@ public App() //await LoggingService.InitializeAsync(); LoggingService.LogInfo($"[App Started] Instance = {Id} IsFirstInstance: {IsFirstInstance}"); - + ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString()); InitializeComponent(); @@ -63,51 +66,21 @@ private static void OnUnhandledException(object sender, Windows.UI.Xaml.Unhandle var diagnosticInfo = new Dictionary() { - { - "Message", e.Message - }, - { - "Exception", e.Exception.ToString() - }, - { - "Culture", SystemInformation.Culture.EnglishName - }, - { - "AvailableMemory", SystemInformation.AvailableMemory.ToString("F0") - }, - { - "IsFirstRun", SystemInformation.IsFirstRun.ToString() - }, - { - "IsFirstRunAfterUpdate", SystemInformation.IsAppUpdated.ToString() - }, - { - "FirstVersionInstalled", $"{SystemInformation.ApplicationVersion.Major}.{SystemInformation.ApplicationVersion.Minor}.{SystemInformation.ApplicationVersion.Build}.{SystemInformation.ApplicationVersion.Revision}" - }, - { - "FirstUseTimeUTC", SystemInformation.FirstUseTime.ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss") - }, - { - "LastLaunchTimeUTC", SystemInformation.LastLaunchTime.ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss") - }, - { - "LaunchTimeUTC", SystemInformation.LaunchTime.ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss") - }, - { - "CurrentLaunchCount", SystemInformation.LaunchCount.ToString() - }, - { - "TotalLaunchCount", SystemInformation.TotalLaunchCount.ToString() - }, - { - "AppUptime", SystemInformation.AppUptime.ToString() - }, - { - "OSArchitecture", SystemInformation.OperatingSystemArchitecture.ToString() - }, - { - "OSVersion", SystemInformation.OperatingSystemVersion.ToString() - } + { "Message", e.Message }, + { "Exception", e.Exception.ToString() }, + { "Culture", SystemInformation.Culture.EnglishName }, + { "AvailableMemory", SystemInformation.AvailableMemory.ToString("F0") }, + { "IsFirstRun", SystemInformation.IsFirstRun.ToString() }, + { "IsFirstRunAfterUpdate", SystemInformation.IsAppUpdated.ToString() }, + { "FirstVersionInstalled", $"{SystemInformation.ApplicationVersion.Major}.{SystemInformation.ApplicationVersion.Minor}.{SystemInformation.ApplicationVersion.Build}.{SystemInformation.ApplicationVersion.Revision}" }, + { "FirstUseTimeUTC", SystemInformation.FirstUseTime.ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss") }, + { "LastLaunchTimeUTC", SystemInformation.LastLaunchTime.ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss") }, + { "LaunchTimeUTC", SystemInformation.LaunchTime.ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss") }, + { "CurrentLaunchCount", SystemInformation.LaunchCount.ToString() }, + { "TotalLaunchCount", SystemInformation.TotalLaunchCount.ToString() }, + { "AppUptime", SystemInformation.AppUptime.ToString() }, + { "OSArchitecture", SystemInformation.OperatingSystemArchitecture.ToString() }, + { "OSVersion", SystemInformation.OperatingSystemVersion.ToString() } }; Analytics.TrackEvent("OnUnhandledException", diagnosticInfo); @@ -160,71 +133,37 @@ protected override async void OnActivated(IActivatedEventArgs args) private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) { + bool rootFrameCreated = false; if (!(Window.Current.Content is Frame rootFrame)) { rootFrame = CreateRootFrame(e); Window.Current.Content = rootFrame; - } + rootFrameCreated = true; - ThemeSettingsService.Initialize(); - EditorSettingsService.Initialize(); + ThemeSettingsService.Initialize(); + EditorSettingsService.Initialize(); + } var appLaunchSettings = new Dictionary() { - { - "OSArchitecture", SystemInformation.OperatingSystemArchitecture.ToString() - }, - { - "UseWindowsTheme", ThemeSettingsService.UseWindowsTheme.ToString() - }, - { - "ThemeMode", ThemeSettingsService.ThemeMode.ToString() - }, - { - "UseWindowsAccentColor", ThemeSettingsService.UseWindowsAccentColor.ToString() - }, - { - "AppBackgroundTintOpacity", $"{(int) (ThemeSettingsService.AppBackgroundPanelTintOpacity * 100.0)}" - }, - { - "ShowStatusBar", EditorSettingsService.ShowStatusBar.ToString() - }, - { - "EditorDefaultLineEnding", EditorSettingsService.EditorDefaultLineEnding.ToString() - }, - { - "EditorDefaultEncoding", EncodingUtility.GetEncodingName(EditorSettingsService.EditorDefaultEncoding) - }, - { - "EditorDefaultTabIndents", EditorSettingsService.EditorDefaultTabIndents.ToString() - }, - { - "EditorDefaultDecoding", EditorSettingsService.EditorDefaultDecoding == null ? "Auto" : EncodingUtility.GetEncodingName(EditorSettingsService.EditorDefaultDecoding) - }, - { - "EditorFontFamily", EditorSettingsService.EditorFontFamily - }, - { - "EditorFontSize", EditorSettingsService.EditorFontSize.ToString() - }, - { - "IsSessionSnapshotEnabled", EditorSettingsService.IsSessionSnapshotEnabled.ToString() - }, - { - "IsShadowWindow", (!IsFirstInstance).ToString() - }, - { - "AlwaysOpenNewWindow", EditorSettingsService.AlwaysOpenNewWindow.ToString() - }, - { - "IsHighlightMisspelledWordsEnabled", EditorSettingsService.IsHighlightMisspelledWordsEnabled.ToString() - }, - { - "IsLineHighlighterEnabled", EditorSettingsService.IsLineHighlighterEnabled.ToString() - }, - { - "EditorDefaultSearchEngine", EditorSettingsService.EditorDefaultSearchEngine.ToString() - } + { "OSArchitecture", SystemInformation.OperatingSystemArchitecture.ToString() }, + { "UseWindowsTheme", ThemeSettingsService.UseWindowsTheme.ToString() }, + {"ThemeMode", ThemeSettingsService.ThemeMode.ToString() }, + { "UseWindowsAccentColor", ThemeSettingsService.UseWindowsAccentColor.ToString() }, + { "AppBackgroundTintOpacity", $"{(int) (ThemeSettingsService.AppBackgroundPanelTintOpacity * 100.0)}" }, + { "ShowStatusBar", EditorSettingsService.ShowStatusBar.ToString() }, + { "EditorDefaultLineEnding", EditorSettingsService.EditorDefaultLineEnding.ToString() }, + { "EditorDefaultEncoding", EncodingUtility.GetEncodingName(EditorSettingsService.EditorDefaultEncoding) }, + { "EditorDefaultTabIndents", EditorSettingsService.EditorDefaultTabIndents.ToString() }, + { "EditorDefaultDecoding", EditorSettingsService.EditorDefaultDecoding == null ? "Auto" : EncodingUtility.GetEncodingName(EditorSettingsService.EditorDefaultDecoding) }, + { "EditorFontFamily", EditorSettingsService.EditorFontFamily }, + { "EditorFontSize", EditorSettingsService.EditorFontSize.ToString() }, + { "IsSessionSnapshotEnabled", EditorSettingsService.IsSessionSnapshotEnabled.ToString() }, + { "IsShadowWindow", (!IsFirstInstance).ToString() }, + { "AlwaysOpenNewWindow", EditorSettingsService.AlwaysOpenNewWindow.ToString() }, + { "IsHighlightMisspelledWordsEnabled", EditorSettingsService.IsHighlightMisspelledWordsEnabled.ToString() }, + { "IsLineHighlighterEnabled", EditorSettingsService.IsLineHighlighterEnabled.ToString() }, + { "EditorDefaultSearchEngine", EditorSettingsService.EditorDefaultSearchEngine.ToString() } }; LoggingService.LogInfo($"AppLaunchSettings: {string.Join(";", appLaunchSettings.Select(x => x.Key + "=" + x.Value).ToArray())}"); @@ -239,9 +178,11 @@ private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) throw new Exception("AppFailedToActivate", ex); } - Window.Current.Activate(); - - ExtendAcrylicIntoTitleBar(); + if (rootFrameCreated) + { + Window.Current.Activate(); + ExtendAcrylicIntoTitleBar(); + } } private Frame CreateRootFrame(IActivatedEventArgs e) diff --git a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs index fa144a10b..55f278c88 100644 --- a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs +++ b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs @@ -411,7 +411,7 @@ private async Task CheckAndUpdateFileStatus() FileModificationState.Untouched; } - await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { FileModificationState = newState.Value; }); diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index 5223c73ac..98b2ff567 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -1,717 +1,717 @@ - - - - - Debug - x86 - {99274932-9E86-480C-8142-38525F80007D} - AppContainerExe - Properties - Notepads - Notepads - en-US - UAP - 10.0.18362.0 - 10.0.17763.0 - 14 - 512 - {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - true - False - Always - 1 - OnApplicationRun - False - True - x86|x64|arm - - - true - bin\x86\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - ;2008 - full - x86 - false - prompt - true - - - bin\x86\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - true - ;2008 - pdbonly - x86 - false - prompt - true - true - - - true - bin\ARM\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - ;2008 - full - ARM - false - prompt - true - - - bin\ARM\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - true - ;2008 - pdbonly - ARM - false - prompt - true - true - - - true - bin\ARM64\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - ;2008 - full - ARM64 - false - prompt - true - true - - - bin\ARM64\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - true - ;2008 - pdbonly - ARM64 - false - prompt - true - true - - - true - bin\x64\Debug\ - TRACE;DEBUG;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;DISABLE_XAML_GENERATED_MAIN - ;2008 - full - x64 - false - prompt - true - false - true - - - bin\x64\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - true - ;2008 - pdbonly - x64 - false - prompt - true - true - - - PackageReference - - - - - - - - FindAndReplaceControl.xaml - - - GoToControl.xaml - - - - ContinuationPageFormat.xaml - - - - PrintPageFormat.xaml - - - AboutPage.xaml - - - AdvancedSettings.xaml - - - SettingsPage.xaml - - - SettingsPanel.xaml - - - PersonalizationSettings.xaml - - - TextAndEditorSettings.xaml - - - - TextEditor.xaml - - - - - - - - - - - - - - - - SideBySideDiffViewer.xaml - - - - - - - - - - - - - - - - - - - - - MarkdownExtensionView.xaml - - - - - - - - - - - - - - - - - - - - - - App.xaml - - - NotepadsMainPage.xaml - - - - - - - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - - - 1.5.0 - - - 3.0.0 - - - 3.0.0 - - - 5.1.200317001-prerelease - - - 6.2.9 - - - 6.0.0 - - - 2.0.1 - - - 12.0.3 - - - 4.1.1 - - - 2.3.0 - - - - - {7aa5e631-b663-420e-a08f-002cd81df855} - SetsView - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 14.0 - - - + + + + + Debug + x86 + {99274932-9E86-480C-8142-38525F80007D} + AppContainerExe + Properties + Notepads + Notepads + en-US + UAP + 10.0.18362.0 + 10.0.17763.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + False + Always + 1 + OnApplicationRun + False + True + x86|x64|arm + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN + true + ;2008 + pdbonly + x86 + false + prompt + true + true + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN + true + ;2008 + pdbonly + ARM + false + prompt + true + true + + + true + bin\ARM64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN + ;2008 + full + ARM64 + false + prompt + true + true + + + bin\ARM64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN + true + ;2008 + pdbonly + ARM64 + false + prompt + true + true + + + true + bin\x64\Debug\ + TRACE;DEBUG;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;DISABLE_XAML_GENERATED_MAIN + ;2008 + full + x64 + false + prompt + true + false + true + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN + true + ;2008 + pdbonly + x64 + false + prompt + true + true + + + PackageReference + + + + + + + + FindAndReplaceControl.xaml + + + GoToControl.xaml + + + + ContinuationPageFormat.xaml + + + + PrintPageFormat.xaml + + + AboutPage.xaml + + + AdvancedSettings.xaml + + + SettingsPage.xaml + + + SettingsPanel.xaml + + + PersonalizationSettings.xaml + + + TextAndEditorSettings.xaml + + + + TextEditor.xaml + + + + + + + + + + + + + + + + SideBySideDiffViewer.xaml + + + + + + + + + + + + + + + + + + + + + MarkdownExtensionView.xaml + + + + + + + + + + + + + + + + + + + + + + App.xaml + + + NotepadsMainPage.xaml + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + + + 1.5.0 + + + 3.0.0 + + + 3.0.0 + + + 5.1.200401003 + + + 6.2.9 + + + 6.0.0 + + + 2.0.1 + + + 12.0.3 + + + 4.1.1 + + + 2.3.0 + + + + + {7aa5e631-b663-420e-a08f-002cd81df855} + SetsView + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 14.0 + + + \ No newline at end of file diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index 088067615..dad21f256 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -28,8 +28,8 @@ using Windows.UI.Xaml.Navigation; using Microsoft.AppCenter.Analytics; using Microsoft.Gaming.XboxGameBar; - using Windows.Graphics.Printing; - + using Windows.Graphics.Printing; + public sealed partial class NotepadsMainPage : Page, INotificationDelegate { private IReadOnlyList _appLaunchFiles; @@ -113,30 +113,33 @@ private INotepadsCore NotepadsCore public NotepadsMainPage() { - InitializeComponent(); - - _defaultNewFileName = _resourceLoader.GetString("TextEditor_DefaultNewFileName"); - - NotificationCenter.Instance.SetNotificationDelegate(this); - - // Setup theme - ThemeSettingsService.OnBackgroundChanged += ThemeSettingsService_OnBackgroundChanged; - ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; - ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; - ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); - - // Setup custom Title Bar - Window.Current.SetTitleBar(AppTitleBar); - - // Setup status bar - ShowHideStatusBar(EditorSettingsService.ShowStatusBar); - EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, ()=> - { - if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); - }); - }; + InitializeComponent(); + + _defaultNewFileName = _resourceLoader.GetString("TextEditor_DefaultNewFileName"); + + NotificationCenter.Instance.SetNotificationDelegate(this); + + // Setup theme + ThemeSettingsService.OnBackgroundChanged += ThemeSettingsService_OnBackgroundChanged; + ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; + ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; + ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); + + // Setup custom Title Bar + Window.Current.SetTitleBar(AppTitleBar); + + // Setup status bar + ShowHideStatusBar(EditorSettingsService.ShowStatusBar); + EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); + }); + }; + + // Ensure we cleanup the widget object when our window is closed + Window.Current.Closed += WidgetMainWindowClosed; // Session backup and restore toggle EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => @@ -180,8 +183,8 @@ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async ( { PrintArgs.RegisterForPrinting(this); } - } - + } + private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => @@ -432,10 +435,10 @@ protected override void OnNavigatedTo(NavigationEventArgs e) //_widget.GameBarDisplayModeChanged += Widget_GameBarDisplayModeChanged; break; } - } - - // App should wait for Sets fully loaded before opening files requested by user (by click or from cmd) - // Open files from external links or cmd args on Sets Loaded + } + + // App should wait for Sets fully loaded before opening files requested by user (by click or from cmd) + // Open files from external links or cmd args on Sets Loaded private async void Sets_Loaded(object sender, RoutedEventArgs e) { int loadedCount = 0; @@ -502,21 +505,32 @@ private async void Sets_Loaded(object sender, RoutedEventArgs e) await BuildOpenRecentButtonSubItems(); Window.Current.CoreWindow.Activated -= CoreWindow_Activated; - Window.Current.CoreWindow.Activated += CoreWindow_Activated; - Application.Current.EnteredBackground -= App_EnteredBackground; + Window.Current.CoreWindow.Activated += CoreWindow_Activated; + Application.Current.EnteredBackground -= App_EnteredBackground; Application.Current.EnteredBackground += App_EnteredBackground; - } - - private async void App_EnteredBackground(object sender, Windows.ApplicationModel.EnteredBackgroundEventArgs e) - { - var deferral = e.GetDeferral(); - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - await SessionManager.SaveSessionAsync(); - } - - deferral.Complete(); + } + + private async void App_EnteredBackground(object sender, Windows.ApplicationModel.EnteredBackgroundEventArgs e) + { + var deferral = e.GetDeferral(); + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + await SessionManager.SaveSessionAsync(); + } + + deferral.Complete(); + } + + private void WidgetMainWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) + { + // Unregister events + _widget.SettingsClicked -= Widget_SettingsClicked; + Window.Current.Closed -= WidgetMainWindowClosed; + + // Cleanup game bar objects + _widget = null; + _widgetControl = null; } public void ExecuteProtocol(Uri uri) @@ -538,7 +552,7 @@ private void CoreWindow_Activated(Windows.UI.Core.CoreWindow sender, Windows.UI. args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.CodeActivated) { LoggingService.LogInfo("CoreWindow Activated.", consoleOnly: true); - ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString()); + Task.Run(() => ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString())); NotepadsCore.GetSelectedTextEditor()?.StartCheckingFileStatusPeriodically(); if (EditorSettingsService.IsSessionSnapshotEnabled) { diff --git a/src/Notepads/Program.cs b/src/Notepads/Program.cs index 07d53667e..c922447d5 100644 --- a/src/Notepads/Program.cs +++ b/src/Notepads/Program.cs @@ -19,7 +19,9 @@ static void Main(string[] args) { // No activated event args, so this is not an activation via the multi-instance ID // Just create a new instance and let App OnActivated resolve the launch - OpenNewInstance(false); + App.IsGameBarWidget = true; + App.IsFirstInstance = true; + Windows.UI.Xaml.Application.Start(p => new App()); } var instances = AppInstance.GetInstances(); @@ -44,7 +46,7 @@ static void Main(string[] args) var protocol = NotepadsProtocolService.GetOperationProtocol(protocolActivatedEventArgs.Uri, out _); if (protocol == NotepadsOperationProtocol.OpenNewInstance) { - OpenNewInstance(true); + OpenNewInstance(); } else { @@ -61,7 +63,7 @@ static void Main(string[] args) if (protocol == NotepadsOperationProtocol.OpenNewInstance) { handled = true; - OpenNewInstance(true); + OpenNewInstance(); } } @@ -76,24 +78,12 @@ static void Main(string[] args) } } - private static void OpenNewInstance(bool registerInstance) + private static void OpenNewInstance() { - if (registerInstance) - { - AppInstance.FindOrRegisterInstanceForKey(App.Id.ToString()); - App.IsFirstInstance = IsFirstInstance; - } - else - { - App.IsFirstInstance = true; - } - + AppInstance.FindOrRegisterInstanceForKey(App.Id.ToString()); + App.IsFirstInstance = IsFirstInstance; Windows.UI.Xaml.Application.Start(p => new App()); - - if (registerInstance) - { - IsFirstInstance = false; - } + IsFirstInstance = false; } private static void RedirectOrCreateNewInstance() @@ -111,7 +101,7 @@ private static void RedirectOrCreateNewInstance() // open new instance if user prefers to if (ApplicationSettingsStore.Read(SettingsKey.AlwaysOpenNewWindowBool) is bool alwaysOpenNewWindowBool && alwaysOpenNewWindowBool) { - OpenNewInstance(true); + OpenNewInstance(); } else { diff --git a/src/Notepads/Services/ActivationService.cs b/src/Notepads/Services/ActivationService.cs index d93fc607e..95ebfd108 100644 --- a/src/Notepads/Services/ActivationService.cs +++ b/src/Notepads/Services/ActivationService.cs @@ -49,18 +49,15 @@ public static void GameBarActivated(Frame rootFrame, XboxGameBarWidgetActivatedE { if (xboxGameBarWidgetActivatedEventArgs.IsLaunchActivation) { - App.IsFirstInstance = true; - App.IsGameBarWidget = true; - var xboxGameBarWidget = new XboxGameBarWidget( xboxGameBarWidgetActivatedEventArgs, Window.Current.CoreWindow, - rootFrame); - + rootFrame); + if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "Notepads") { rootFrame.Navigate(typeof(NotepadsMainPage), xboxGameBarWidget); - } + } else if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "NotepadsSettings") { rootFrame.Navigate(typeof(SettingsPage), xboxGameBarWidget); From 658b18778928c56d93bb8d8bc027c6eac3267bd3 Mon Sep 17 00:00:00 2001 From: Ben McGregor Date: Thu, 2 Apr 2020 14:42:10 -0700 Subject: [PATCH 16/49] Remove unnecessary using statements --- src/Notepads/App.xaml.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index 684cce25b..884387631 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -7,7 +7,6 @@ using Microsoft.AppCenter; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; - using Microsoft.Gaming.XboxGameBar; using Microsoft.Toolkit.Uwp.Helpers; using Notepads.Controls.Settings; using Notepads.Services; @@ -22,8 +21,6 @@ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; - using System.Runtime.InteropServices; - using Windows.UI.Core; sealed partial class App : Application { From ee8c16e1ad088ca9b9b2e3c0ae3b4b4254f29e91 Mon Sep 17 00:00:00 2001 From: Ben McGregor Date: Thu, 2 Apr 2020 16:41:52 -0700 Subject: [PATCH 17/49] More adjustments to widget cleanup --- src/Notepads/Controls/Settings/SettingsPage.xaml.cs | 10 ++++++++++ src/Notepads/NotepadsMainPage.xaml.cs | 10 ++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Notepads/Controls/Settings/SettingsPage.xaml.cs b/src/Notepads/Controls/Settings/SettingsPage.xaml.cs index 5d32b6342..1d8fb82ed 100644 --- a/src/Notepads/Controls/Settings/SettingsPage.xaml.cs +++ b/src/Notepads/Controls/Settings/SettingsPage.xaml.cs @@ -59,10 +59,20 @@ protected override void OnNavigatedTo(NavigationEventArgs e) return; case XboxGameBarWidget widget: _widget = widget; + Window.Current.Closed += WidgetSettingsWindowClosed; break; } } + private void WidgetSettingsWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) + { + // Unregister events + Window.Current.Closed -= WidgetSettingsWindowClosed; + + // Cleanup game bar objects + _widget = null; + } + private void SettingsPanel_OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) { SettingsPanel.Show((args.InvokedItem as string), (args.InvokedItemContainer as NavigationViewItem)?.Tag as string); diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index a7ec15629..63ff594f0 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -138,9 +138,6 @@ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => }); }; - // Ensure we cleanup the widget object when our window is closed - Window.Current.Closed += WidgetMainWindowClosed; - // Session backup and restore toggle EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => { @@ -430,7 +427,8 @@ protected override void OnNavigatedTo(NavigationEventArgs e) //_widget.RequestedThemeChanged += Widget_RequestedThemeChanged; //_widget.VisibleChanged += Widget_VisibleChanged; //_widget.WindowStateChanged += Widget_WindowStateChanged; - //_widget.GameBarDisplayModeChanged += Widget_GameBarDisplayModeChanged; + //_widget.GameBarDisplayModeChanged += Widget_GameBarDisplayModeChanged; + Window.Current.Closed += WidgetMainWindowClosed; break; } } @@ -531,9 +529,9 @@ private async void App_EnteredBackground(object sender, Windows.ApplicationModel private void WidgetMainWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) { - // Unregister events + // Unregister events + Window.Current.Closed -= WidgetMainWindowClosed; _widget.SettingsClicked -= Widget_SettingsClicked; - Window.Current.Closed -= WidgetMainWindowClosed; // Cleanup game bar objects _widget = null; From 43e6a5f539e184eb48da68e223af8d99f7a2a8a9 Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Tue, 7 Apr 2020 10:26:54 -0700 Subject: [PATCH 18/49] Drop ARM support and keep ARM64 only Drop ARM support and keep ARM64 only --- src/Notepads.sln | 44 ++++++++++-------------------------- src/Notepads/Notepads.csproj | 25 +------------------- 2 files changed, 13 insertions(+), 56 deletions(-) diff --git a/src/Notepads.sln b/src/Notepads.sln index 71cfd2414..fc0ad2f0b 100644 --- a/src/Notepads.sln +++ b/src/Notepads.sln @@ -12,64 +12,44 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetsView", "SetsView\SetsVi EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM - Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM - Release|ARM64 = Release|ARM64 + Debug|ARM64 = Debug|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 + Release|ARM64 = Release|ARM64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {99274932-9E86-480C-8142-38525F80007D}.Debug|Any CPU.ActiveCfg = Debug|x86 - {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM.ActiveCfg = Debug|ARM - {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM.Build.0 = Debug|ARM - {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM.Deploy.0 = Debug|ARM - {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM64.Build.0 = Debug|ARM64 - {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM64.Deploy.0 = Debug|ARM64 {99274932-9E86-480C-8142-38525F80007D}.Debug|x64.ActiveCfg = Debug|x64 {99274932-9E86-480C-8142-38525F80007D}.Debug|x64.Build.0 = Debug|x64 {99274932-9E86-480C-8142-38525F80007D}.Debug|x64.Deploy.0 = Debug|x64 {99274932-9E86-480C-8142-38525F80007D}.Debug|x86.ActiveCfg = Debug|x86 {99274932-9E86-480C-8142-38525F80007D}.Debug|x86.Build.0 = Debug|x86 {99274932-9E86-480C-8142-38525F80007D}.Debug|x86.Deploy.0 = Debug|x86 - {99274932-9E86-480C-8142-38525F80007D}.Release|Any CPU.ActiveCfg = Release|x86 - {99274932-9E86-480C-8142-38525F80007D}.Release|ARM.ActiveCfg = Release|ARM - {99274932-9E86-480C-8142-38525F80007D}.Release|ARM.Build.0 = Release|ARM - {99274932-9E86-480C-8142-38525F80007D}.Release|ARM.Deploy.0 = Release|ARM - {99274932-9E86-480C-8142-38525F80007D}.Release|ARM64.ActiveCfg = Release|ARM64 - {99274932-9E86-480C-8142-38525F80007D}.Release|ARM64.Build.0 = Release|ARM64 - {99274932-9E86-480C-8142-38525F80007D}.Release|ARM64.Deploy.0 = Release|ARM64 + {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM64.Build.0 = Debug|ARM64 + {99274932-9E86-480C-8142-38525F80007D}.Debug|ARM64.Deploy.0 = Debug|ARM64 {99274932-9E86-480C-8142-38525F80007D}.Release|x64.ActiveCfg = Release|x64 {99274932-9E86-480C-8142-38525F80007D}.Release|x64.Build.0 = Release|x64 {99274932-9E86-480C-8142-38525F80007D}.Release|x64.Deploy.0 = Release|x64 {99274932-9E86-480C-8142-38525F80007D}.Release|x86.ActiveCfg = Release|x86 {99274932-9E86-480C-8142-38525F80007D}.Release|x86.Build.0 = Release|x86 {99274932-9E86-480C-8142-38525F80007D}.Release|x86.Deploy.0 = Release|x86 - {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|ARM.ActiveCfg = Debug|ARM - {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|ARM.Build.0 = Debug|ARM - {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|ARM64.Build.0 = Debug|ARM64 + {99274932-9E86-480C-8142-38525F80007D}.Release|ARM64.ActiveCfg = Release|ARM64 + {99274932-9E86-480C-8142-38525F80007D}.Release|ARM64.Build.0 = Release|ARM64 + {99274932-9E86-480C-8142-38525F80007D}.Release|ARM64.Deploy.0 = Release|ARM64 {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|x64.ActiveCfg = Debug|x64 {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|x64.Build.0 = Debug|x64 {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|x86.ActiveCfg = Debug|x86 {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|x86.Build.0 = Debug|x86 - {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|Any CPU.Build.0 = Release|Any CPU - {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|ARM.ActiveCfg = Release|ARM - {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|ARM.Build.0 = Release|ARM - {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|ARM64.ActiveCfg = Release|ARM64 - {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|ARM64.Build.0 = Release|ARM64 + {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {7AA5E631-B663-420E-A08F-002CD81DF855}.Debug|ARM64.Build.0 = Debug|ARM64 {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|x64.ActiveCfg = Release|x64 {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|x64.Build.0 = Release|x64 {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|x86.ActiveCfg = Release|x86 {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|x86.Build.0 = Release|x86 + {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|ARM64.ActiveCfg = Release|ARM64 + {7AA5E631-B663-420E-A08F-002CD81DF855}.Release|ARM64.Build.0 = Release|ARM64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index 7ec636cda..435c56069 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -23,7 +23,7 @@ OnApplicationRun False True - x86|x64|arm|arm64 + x86|x64|arm64 true @@ -48,29 +48,6 @@ true true - - true - bin\ARM\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - ;2008 - full - ARM - false - prompt - true - - - bin\ARM\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP;DISABLE_XAML_GENERATED_MAIN - true - ;2008 - pdbonly - ARM - false - prompt - true - true - true bin\ARM64\Debug\ From bb59a38d35bdcf26921ea980ab6a3632979835cd Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Tue, 7 Apr 2020 10:36:18 -0700 Subject: [PATCH 19/49] Update azure-pipelines.yml --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 64f33b491..3dff8b94c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -8,7 +8,7 @@ pool: variables: solution: '**/*.sln' - buildPlatform: 'x86|x64|ARM' + buildPlatform: 'x86|x64|ARM64' buildConfiguration: 'Debug' appxPackageDir: '$(build.artifactStagingDirectory)\AppxPackages\\' From 01b06f01f325b90a142b515b58e2471cdcc99e6a Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Tue, 7 Apr 2020 15:25:26 -0700 Subject: [PATCH 20/49] Update NotepadsMainPage.xaml.cs --- src/Notepads/NotepadsMainPage.xaml.cs | 1587 +++++++++++++------------ 1 file changed, 795 insertions(+), 792 deletions(-) diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index 5cf688d31..6cb441d2a 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -1,796 +1,799 @@ -namespace Notepads -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - using Notepads.Commands; - using Notepads.Controls.Print; - using Notepads.Controls.Settings; - using Notepads.Controls.TextEditor; - using Notepads.Core; - using Notepads.Extensions; - using Notepads.Services; - using Notepads.Settings; - using Notepads.Utilities; - using Windows.ApplicationModel.Activation; - using Windows.ApplicationModel.DataTransfer; - using Windows.ApplicationModel.Resources; - using Windows.Storage; - using Windows.System; - using Windows.UI.ViewManagement; - using Windows.UI.Xaml; - using Windows.UI.Xaml.Controls; - using Windows.UI.Xaml.Controls.Primitives; - using Windows.UI.Xaml.Input; - using Windows.UI.Xaml.Media; - using Windows.UI.Xaml.Media.Animation; - using Windows.UI.Xaml.Navigation; - using Microsoft.AppCenter.Analytics; - using Microsoft.Gaming.XboxGameBar; - using Windows.Graphics.Printing; - - public sealed partial class NotepadsMainPage : Page, INotificationDelegate - { - private IReadOnlyList _appLaunchFiles; - - private string _appLaunchCmdDir; - private string _appLaunchCmdArgs; - private Uri _appLaunchUri; - - private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView(); - - private bool _loaded = false; - private bool _appShouldExitAfterLastEditorClosed = false; - - private const int TitleBarReservedAreaDefaultWidth = 180; - private const int TitleBarReservedAreaCompactOverlayWidth = 100; - - private INotepadsCore _notepadsCore; - - private XboxGameBarWidget _widget; // maintain throughout the lifetime of the notepads widget - private XboxGameBarWidgetControl _widgetControl; - - private INotepadsCore NotepadsCore - { - get - { - if (_notepadsCore == null) - { - _notepadsCore = new NotepadsCore(Sets, new NotepadsExtensionProvider()); - _notepadsCore.StorageItemsDropped += OnStorageItemsDropped; - _notepadsCore.TextEditorLoaded += OnTextEditorLoaded; - _notepadsCore.TextEditorUnloaded += OnTextEditorUnloaded; - _notepadsCore.TextEditorKeyDown += OnTextEditor_KeyDown; - _notepadsCore.TextEditorClosing += OnTextEditorClosing; - _notepadsCore.TextEditorMovedToAnotherAppInstance += OnTextEditorMovedToAnotherAppInstance; - _notepadsCore.TextEditorSelectionChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateLineColumnIndicator(editor); }; - _notepadsCore.TextEditorFontZoomFactorChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateFontZoomIndicator(editor); }; - _notepadsCore.TextEditorEncodingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateEncodingIndicator(editor.GetEncoding()); }; - _notepadsCore.TextEditorLineEndingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) { UpdateLineEndingIndicator(editor.GetLineEnding()); UpdateLineColumnIndicator(editor); } }; - _notepadsCore.TextEditorEditorModificationStateChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) SetupStatusBar(editor); }; - _notepadsCore.TextEditorFileModificationStateChanged += (sender, editor) => - { - if (NotepadsCore.GetSelectedTextEditor() == editor) - { - if (editor.FileModificationState == FileModificationState.Modified) - { - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileModifiedOutsideIndicator_ToolTip"), 3500); - } - else if (editor.FileModificationState == FileModificationState.RenamedMovedOrDeleted) - { - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileRenamedMovedOrDeletedIndicator_ToolTip"), 3500); - } - UpdateFileModificationStateIndicator(editor); - UpdatePathIndicator(editor); - } - }; - _notepadsCore.TextEditorSaved += (sender, editor) => - { - if (NotepadsCore.GetSelectedTextEditor() == editor) - { - SetupStatusBar(editor); - } - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_NotificationMsg_FileSaved"), 1500); - }; - } - - return _notepadsCore; - } - } - - private readonly ICommandHandler _keyboardCommandHandler; - - private ISessionManager _sessionManager; - - private ISessionManager SessionManager => _sessionManager ?? (_sessionManager = SessionUtility.GetSessionManager(NotepadsCore)); - - private readonly string _defaultNewFileName; - - public NotepadsMainPage() - { - InitializeComponent(); - - _defaultNewFileName = _resourceLoader.GetString("TextEditor_DefaultNewFileName"); - - NotificationCenter.Instance.SetNotificationDelegate(this); - - // Setup theme - ThemeSettingsService.OnBackgroundChanged += ThemeSettingsService_OnBackgroundChanged; - ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; - ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; - ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); - - // Setup custom Title Bar - Window.Current.SetTitleBar(AppTitleBar); - - // Setup status bar - ShowHideStatusBar(EditorSettingsService.ShowStatusBar); - EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); - }); - }; - - // Session backup and restore toggle - EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => - { - if (isSessionBackupAndRestoreEnabled) - { - SessionManager.IsBackupEnabled = true; - SessionManager.StartSessionBackup(startImmediately: true); - } - else - { - SessionManager.IsBackupEnabled = false; - SessionManager.StopSessionBackup(); - await SessionManager.ClearSessionDataAsync(); - } - }); - }; - - // Sharing - Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView().DataRequested += MainPage_DataRequested; - Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += MainPage_CloseRequested; - - Window.Current.VisibilityChanged += WindowVisibilityChangedEventHandler; - Window.Current.SizeChanged += WindowSizeChanged; - - InitControls(); - - // Init shortcuts - _keyboardCommandHandler = GetKeyboardCommandHandler(); - - //Register for printing - if (!PrintManager.IsSupported()) - { - MenuPrintButton.Visibility = Visibility.Collapsed; - MenuPrintAllButton.Visibility = Visibility.Collapsed; - PrintSettingsSeparator.Visibility = Visibility.Collapsed; - } - else - { - PrintArgs.RegisterForPrinting(this); - } - } - - private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - ThemeSettingsService.SetRequestedAccentColor(); - }); - } - - private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); - }); - } - - private async void ThemeSettingsService_OnBackgroundChanged(object sender, Brush backgroundBrush) - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - RootGrid.Background = backgroundBrush; - }); - } - - private void InitControls() - { - ToolTipService.SetToolTip(ExitCompactOverlayButton, _resourceLoader.GetString("App_ExitCompactOverlayMode_Text")); - RootSplitView.PaneOpening += delegate { SettingsFrame.Navigate(typeof(SettingsPage), null, new SuppressNavigationTransitionInfo()); }; - RootSplitView.PaneClosed += delegate { NotepadsCore.FocusOnSelectedTextEditor(); }; - NewSetButton.Click += delegate { NotepadsCore.OpenNewTextEditor(_defaultNewFileName); }; - MainMenuButton.Click += (sender, args) => FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender); - MenuCreateNewButton.Click += (sender, args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName); - MenuCreateNewWindowButton.Click += async (sender, args) => await OpenNewAppInstance(); - MenuOpenFileButton.Click += async (sender, args) => await OpenNewFiles(); - MenuSaveButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false); - MenuSaveAsButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true); - MenuSaveAllButton.Click += async (sender, args) => - { - var success = false; - foreach (var textEditor in NotepadsCore.GetAllTextEditors()) - { - if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) success = true; - } - if (success) - { - await BuildOpenRecentButtonSubItems(); - } - }; - MenuFindButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: false); - MenuReplaceButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: true); - MenuFullScreenButton.Click += (sender, args) => EnterExitFullScreenMode(); - MenuCompactOverlayButton.Click += (sender, args) => EnterExitCompactOverlayMode(); - MenuPrintButton.Click += async (sender, args) => await Print(NotepadsCore.GetSelectedTextEditor()); - MenuPrintAllButton.Click += async (sender, args) => await PrintAll(NotepadsCore.GetAllTextEditors()); - MenuSettingsButton.Click += (sender, args) => RootSplitView.IsPaneOpen = true; - - MainMenuButtonFlyout.Opening += (sender, o) => - { - var selectedTextEditor = NotepadsCore.GetSelectedTextEditor(); - if (selectedTextEditor == null) - { - MenuSaveButton.IsEnabled = false; - MenuSaveAsButton.IsEnabled = false; - MenuFindButton.IsEnabled = false; - MenuReplaceButton.IsEnabled = false; - MenuPrintButton.IsEnabled = false; - MenuPrintAllButton.IsEnabled = false; - } - else if (selectedTextEditor.IsEditorEnabled() == false) - { - MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; - MenuSaveAsButton.IsEnabled = true; - MenuFindButton.IsEnabled = false; - MenuReplaceButton.IsEnabled = false; - } - else - { - MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; - MenuSaveAsButton.IsEnabled = true; - MenuFindButton.IsEnabled = true; - MenuReplaceButton.IsEnabled = true; - - if (PrintManager.IsSupported()) - { - MenuPrintButton.IsEnabled = !string.IsNullOrEmpty(selectedTextEditor.GetText()); - MenuPrintAllButton.IsEnabled = NotepadsCore.HaveNonemptyTextEditor(); - } - } - - MenuFullScreenButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().IsFullScreenMode ? - "App_ExitFullScreenMode_Text" : "App_EnterFullScreenMode_Text"); - MenuCompactOverlayButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay ? - "App_ExitCompactOverlayMode_Text" : "App_EnterCompactOverlayMode_Text"); - MenuSaveAllButton.IsEnabled = NotepadsCore.HaveUnsavedTextEditor(); - }; - - if (!App.IsFirstInstance) - { - MainMenuButton.Foreground = new SolidColorBrush(ThemeSettingsService.AppAccentColor); - MenuSettingsButton.IsEnabled = false; - } - - if (App.IsGameBarWidget) - { - MenuFullScreenSeparator.Visibility = Visibility.Collapsed; - PrintSettingsSeparator.Visibility = Visibility.Collapsed; - - MenuCompactOverlayButton.Visibility = Visibility.Collapsed; - MenuFullScreenButton.Visibility = Visibility.Collapsed; - MenuSettingsButton.Visibility = Visibility.Collapsed; - } - } - - private async Task BuildOpenRecentButtonSubItems() - { - var openRecentSubItem = new MenuFlyoutSubItem - { - Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent/Text"), - Icon = new FontIcon { Glyph = "\xE81C" }, - Name = "MenuOpenRecentlyUsedFileButton", - }; - - var MRUFileList = new HashSet(); - - foreach (var item in await MRUService.Get(top: 10)) - { - if (item is StorageFile file) - { - if (MRUFileList.Contains(file.Path)) - { - // MRU might contains files with same path (User opens a recently used file after renaming it) - // So we need to do the decouple here - continue; - } - var newItem = new MenuFlyoutItem() - { - Text = file.Path - }; - ToolTipService.SetToolTip(newItem, file.Path); - newItem.Click += async (sender, args) => { await OpenFile(file); }; - openRecentSubItem.Items?.Add(newItem); - MRUFileList.Add(file.Path); - } - } - - var oldOpenRecentSubItem = MainMenuButtonFlyout.Items?.FirstOrDefault(i => i.Name == openRecentSubItem.Name); - if (oldOpenRecentSubItem != null) - { - MainMenuButtonFlyout.Items.Remove(oldOpenRecentSubItem); - } - - openRecentSubItem.IsEnabled = false; - if (openRecentSubItem.Items?.Count > 0) - { - openRecentSubItem.Items?.Add(new MenuFlyoutSeparator()); - - var clearRecentlyOpenedSubItem = - new MenuFlyoutItem() - { - Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent_ClearRecentlyOpenedSubItem_Text") - }; - clearRecentlyOpenedSubItem.Click += async (sender, args) => - { - MRUService.ClearAll(); - await BuildOpenRecentButtonSubItems(); - }; - openRecentSubItem.Items?.Add(clearRecentlyOpenedSubItem); - openRecentSubItem.IsEnabled = true; - } - - if (MainMenuButtonFlyout.Items != null) - { - var indexToInsert = MainMenuButtonFlyout.Items.IndexOf(MenuOpenFileButton) + 1; - MainMenuButtonFlyout.Items.Insert(indexToInsert, openRecentSubItem); - } - } - - private KeyboardCommandHandler GetKeyboardCommandHandler() - { - return new KeyboardCommandHandler(new List>() - { - new KeyboardCommand(true, false, false, VirtualKey.W, (args) => NotepadsCore.CloseTextEditor(NotepadsCore.GetSelectedTextEditor())), - new KeyboardCommand(true, false, false, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(true)), - new KeyboardCommand(true, false, true, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(false)), - new KeyboardCommand(true, false, false, VirtualKey.N, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), - new KeyboardCommand(true, false, false, VirtualKey.T, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), - new KeyboardCommand(true, false, false, VirtualKey.O, async (args) => await OpenNewFiles()), - new KeyboardCommand(true, false, false, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false, ignoreUnmodifiedDocument: true)), - new KeyboardCommand(true, false, true, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true)), - new KeyboardCommand(true, false, false, VirtualKey.P, async (args) => await Print(NotepadsCore.GetSelectedTextEditor())), - new KeyboardCommand(true, false, true, VirtualKey.P, async (args) => await PrintAll(NotepadsCore.GetAllTextEditors())), - new KeyboardCommand(true, false, true, VirtualKey.R, (args) => { ReloadFileFromDisk(this, new RoutedEventArgs()); }), - new KeyboardCommand(true, false, true, VirtualKey.N, async (args) => await OpenNewAppInstance()), - new KeyboardCommand(true, false, false, VirtualKey.Number1, (args) => NotepadsCore.SwitchTo(0)), - new KeyboardCommand(true, false, false, VirtualKey.Number2, (args) => NotepadsCore.SwitchTo(1)), - new KeyboardCommand(true, false, false, VirtualKey.Number3, (args) => NotepadsCore.SwitchTo(2)), - new KeyboardCommand(true, false, false, VirtualKey.Number4, (args) => NotepadsCore.SwitchTo(3)), - new KeyboardCommand(true, false, false, VirtualKey.Number5, (args) => NotepadsCore.SwitchTo(4)), - new KeyboardCommand(true, false, false, VirtualKey.Number6, (args) => NotepadsCore.SwitchTo(5)), - new KeyboardCommand(true, false, false, VirtualKey.Number7, (args) => NotepadsCore.SwitchTo(6)), - new KeyboardCommand(true, false, false, VirtualKey.Number8, (args) => NotepadsCore.SwitchTo(7)), - new KeyboardCommand(true, false, false, VirtualKey.Number9, (args) => NotepadsCore.SwitchTo(8)), - new KeyboardCommand(VirtualKey.F11, (args) => { EnterExitFullScreenMode(); }), - new KeyboardCommand(VirtualKey.F12, (args) => { EnterExitCompactOverlayMode(); }), - new KeyboardCommand(VirtualKey.Escape, (args) => { if (RootSplitView.IsPaneOpen) RootSplitView.IsPaneOpen = false; }), - }); - } - - private async Task OpenNewAppInstance() - { - if (!await NotepadsProtocolService.LaunchProtocolAsync(NotepadsOperationProtocol.OpenNewInstance)) - { - Analytics.TrackEvent("FailedToOpenNewAppInstance"); - } - } - - #region Application Life Cycle & Window management - - // Handles external links or cmd args activation before Sets loaded - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - - switch (e.Parameter) - { - case null: - return; - case FileActivatedEventArgs fileActivatedEventArgs: - _appLaunchFiles = fileActivatedEventArgs.Files; - break; - case CommandLineActivatedEventArgs commandLineActivatedEventArgs: - _appLaunchCmdDir = commandLineActivatedEventArgs.Operation.CurrentDirectoryPath; - _appLaunchCmdArgs = commandLineActivatedEventArgs.Operation.Arguments; - break; - case ProtocolActivatedEventArgs protocol: - _appLaunchUri = protocol.Uri; - break; - case XboxGameBarWidget widget: - _widget = widget; - _widgetControl = new XboxGameBarWidgetControl(_widget); - _widget.SettingsClicked += Widget_SettingsClicked; - //_widget.PinnedChanged += Widget_PinnedChanged; - //_widget.FavoritedChanged += Widget_FavoritedChanged; - //_widget.RequestedThemeChanged += Widget_RequestedThemeChanged; - //_widget.VisibleChanged += Widget_VisibleChanged; - //_widget.WindowStateChanged += Widget_WindowStateChanged; +namespace Notepads +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Notepads.Commands; + using Notepads.Controls.Print; + using Notepads.Controls.Settings; + using Notepads.Controls.TextEditor; + using Notepads.Core; + using Notepads.Extensions; + using Notepads.Services; + using Notepads.Settings; + using Notepads.Utilities; + using Windows.ApplicationModel.Activation; + using Windows.ApplicationModel.DataTransfer; + using Windows.ApplicationModel.Resources; + using Windows.Storage; + using Windows.System; + using Windows.UI.ViewManagement; + using Windows.UI.Xaml; + using Windows.UI.Xaml.Controls; + using Windows.UI.Xaml.Controls.Primitives; + using Windows.UI.Xaml.Input; + using Windows.UI.Xaml.Media; + using Windows.UI.Xaml.Media.Animation; + using Windows.UI.Xaml.Navigation; + using Microsoft.AppCenter.Analytics; + using Microsoft.Gaming.XboxGameBar; + using Windows.Graphics.Printing; + + public sealed partial class NotepadsMainPage : Page, INotificationDelegate + { + private IReadOnlyList _appLaunchFiles; + + private string _appLaunchCmdDir; + private string _appLaunchCmdArgs; + private Uri _appLaunchUri; + + private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView(); + + private bool _loaded = false; + private bool _appShouldExitAfterLastEditorClosed = false; + + private const int TitleBarReservedAreaDefaultWidth = 180; + private const int TitleBarReservedAreaCompactOverlayWidth = 100; + + private INotepadsCore _notepadsCore; + + private XboxGameBarWidget _widget; // maintain throughout the lifetime of the notepads widget + private XboxGameBarWidgetControl _widgetControl; + + private INotepadsCore NotepadsCore + { + get + { + if (_notepadsCore == null) + { + _notepadsCore = new NotepadsCore(Sets, new NotepadsExtensionProvider()); + _notepadsCore.StorageItemsDropped += OnStorageItemsDropped; + _notepadsCore.TextEditorLoaded += OnTextEditorLoaded; + _notepadsCore.TextEditorUnloaded += OnTextEditorUnloaded; + _notepadsCore.TextEditorKeyDown += OnTextEditor_KeyDown; + _notepadsCore.TextEditorClosing += OnTextEditorClosing; + _notepadsCore.TextEditorMovedToAnotherAppInstance += OnTextEditorMovedToAnotherAppInstance; + _notepadsCore.TextEditorSelectionChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateLineColumnIndicator(editor); }; + _notepadsCore.TextEditorFontZoomFactorChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateFontZoomIndicator(editor); }; + _notepadsCore.TextEditorEncodingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateEncodingIndicator(editor.GetEncoding()); }; + _notepadsCore.TextEditorLineEndingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) { UpdateLineEndingIndicator(editor.GetLineEnding()); UpdateLineColumnIndicator(editor); } }; + _notepadsCore.TextEditorEditorModificationStateChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) SetupStatusBar(editor); }; + _notepadsCore.TextEditorFileModificationStateChanged += (sender, editor) => + { + if (NotepadsCore.GetSelectedTextEditor() == editor) + { + if (editor.FileModificationState == FileModificationState.Modified) + { + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileModifiedOutsideIndicator_ToolTip"), 3500); + } + else if (editor.FileModificationState == FileModificationState.RenamedMovedOrDeleted) + { + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileRenamedMovedOrDeletedIndicator_ToolTip"), 3500); + } + UpdateFileModificationStateIndicator(editor); + UpdatePathIndicator(editor); + } + }; + _notepadsCore.TextEditorSaved += (sender, editor) => + { + if (NotepadsCore.GetSelectedTextEditor() == editor) + { + SetupStatusBar(editor); + } + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_NotificationMsg_FileSaved"), 1500); + }; + } + + return _notepadsCore; + } + } + + private readonly ICommandHandler _keyboardCommandHandler; + + private ISessionManager _sessionManager; + + private ISessionManager SessionManager => _sessionManager ?? (_sessionManager = SessionUtility.GetSessionManager(NotepadsCore)); + + private readonly string _defaultNewFileName; + + public NotepadsMainPage() + { + InitializeComponent(); + + _defaultNewFileName = _resourceLoader.GetString("TextEditor_DefaultNewFileName"); + + NotificationCenter.Instance.SetNotificationDelegate(this); + + // Setup theme + ThemeSettingsService.OnBackgroundChanged += ThemeSettingsService_OnBackgroundChanged; + ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; + ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; + ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); + + // Setup custom Title Bar + Window.Current.SetTitleBar(AppTitleBar); + + // Setup status bar + ShowHideStatusBar(EditorSettingsService.ShowStatusBar); + EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); + }); + }; + + // Session backup and restore toggle + EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => + { + if (isSessionBackupAndRestoreEnabled) + { + SessionManager.IsBackupEnabled = true; + SessionManager.StartSessionBackup(startImmediately: true); + } + else + { + SessionManager.IsBackupEnabled = false; + SessionManager.StopSessionBackup(); + await SessionManager.ClearSessionDataAsync(); + } + }); + }; + + // Sharing + Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView().DataRequested += MainPage_DataRequested; + Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += MainPage_CloseRequested; + + Window.Current.VisibilityChanged += WindowVisibilityChangedEventHandler; + Window.Current.SizeChanged += WindowSizeChanged; + + InitControls(); + + // Init shortcuts + _keyboardCommandHandler = GetKeyboardCommandHandler(); + + //Register for printing + if (!PrintManager.IsSupported()) + { + MenuPrintButton.Visibility = Visibility.Collapsed; + MenuPrintAllButton.Visibility = Visibility.Collapsed; + PrintSettingsSeparator.Visibility = Visibility.Collapsed; + } + else + { + PrintArgs.RegisterForPrinting(this); + } + } + + private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedAccentColor(); + }); + } + + private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); + }); + } + + private async void ThemeSettingsService_OnBackgroundChanged(object sender, Brush backgroundBrush) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + RootGrid.Background = backgroundBrush; + }); + } + + private void InitControls() + { + ToolTipService.SetToolTip(ExitCompactOverlayButton, _resourceLoader.GetString("App_ExitCompactOverlayMode_Text")); + RootSplitView.PaneOpening += delegate { SettingsFrame.Navigate(typeof(SettingsPage), null, new SuppressNavigationTransitionInfo()); }; + RootSplitView.PaneClosed += delegate { NotepadsCore.FocusOnSelectedTextEditor(); }; + NewSetButton.Click += delegate { NotepadsCore.OpenNewTextEditor(_defaultNewFileName); }; + MainMenuButton.Click += (sender, args) => FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender); + MenuCreateNewButton.Click += (sender, args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName); + MenuCreateNewWindowButton.Click += async (sender, args) => await OpenNewAppInstance(); + MenuOpenFileButton.Click += async (sender, args) => await OpenNewFiles(); + MenuSaveButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false); + MenuSaveAsButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true); + MenuSaveAllButton.Click += async (sender, args) => + { + var success = false; + foreach (var textEditor in NotepadsCore.GetAllTextEditors()) + { + if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) success = true; + } + if (success) + { + await BuildOpenRecentButtonSubItems(); + } + }; + MenuFindButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: false); + MenuReplaceButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: true); + MenuFullScreenButton.Click += (sender, args) => EnterExitFullScreenMode(); + MenuCompactOverlayButton.Click += (sender, args) => EnterExitCompactOverlayMode(); + MenuPrintButton.Click += async (sender, args) => await Print(NotepadsCore.GetSelectedTextEditor()); + MenuPrintAllButton.Click += async (sender, args) => await PrintAll(NotepadsCore.GetAllTextEditors()); + MenuSettingsButton.Click += (sender, args) => RootSplitView.IsPaneOpen = true; + + MainMenuButtonFlyout.Opening += (sender, o) => + { + var selectedTextEditor = NotepadsCore.GetSelectedTextEditor(); + if (selectedTextEditor == null) + { + MenuSaveButton.IsEnabled = false; + MenuSaveAsButton.IsEnabled = false; + MenuFindButton.IsEnabled = false; + MenuReplaceButton.IsEnabled = false; + MenuPrintButton.IsEnabled = false; + MenuPrintAllButton.IsEnabled = false; + } + else if (selectedTextEditor.IsEditorEnabled() == false) + { + MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; + MenuSaveAsButton.IsEnabled = true; + MenuFindButton.IsEnabled = false; + MenuReplaceButton.IsEnabled = false; + } + else + { + MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; + MenuSaveAsButton.IsEnabled = true; + MenuFindButton.IsEnabled = true; + MenuReplaceButton.IsEnabled = true; + + if (PrintManager.IsSupported()) + { + MenuPrintButton.IsEnabled = !string.IsNullOrEmpty(selectedTextEditor.GetText()); + MenuPrintAllButton.IsEnabled = NotepadsCore.HaveNonemptyTextEditor(); + } + } + + MenuFullScreenButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().IsFullScreenMode ? + "App_ExitFullScreenMode_Text" : "App_EnterFullScreenMode_Text"); + MenuCompactOverlayButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay ? + "App_ExitCompactOverlayMode_Text" : "App_EnterCompactOverlayMode_Text"); + MenuSaveAllButton.IsEnabled = NotepadsCore.HaveUnsavedTextEditor(); + }; + + if (!App.IsFirstInstance) + { + MainMenuButton.Foreground = new SolidColorBrush(ThemeSettingsService.AppAccentColor); + MenuSettingsButton.IsEnabled = false; + } + + if (App.IsGameBarWidget) + { + MenuFullScreenSeparator.Visibility = Visibility.Collapsed; + PrintSettingsSeparator.Visibility = Visibility.Collapsed; + + MenuCompactOverlayButton.Visibility = Visibility.Collapsed; + MenuFullScreenButton.Visibility = Visibility.Collapsed; + MenuSettingsButton.Visibility = Visibility.Collapsed; + } + } + + private async Task BuildOpenRecentButtonSubItems() + { + var openRecentSubItem = new MenuFlyoutSubItem + { + Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent/Text"), + Icon = new FontIcon { Glyph = "\xE81C" }, + Name = "MenuOpenRecentlyUsedFileButton", + }; + + var MRUFileList = new HashSet(); + + foreach (var item in await MRUService.Get(top: 10)) + { + if (item is StorageFile file) + { + if (MRUFileList.Contains(file.Path)) + { + // MRU might contains files with same path (User opens a recently used file after renaming it) + // So we need to do the decouple here + continue; + } + var newItem = new MenuFlyoutItem() + { + Text = file.Path + }; + ToolTipService.SetToolTip(newItem, file.Path); + newItem.Click += async (sender, args) => { await OpenFile(file); }; + openRecentSubItem.Items?.Add(newItem); + MRUFileList.Add(file.Path); + } + } + + var oldOpenRecentSubItem = MainMenuButtonFlyout.Items?.FirstOrDefault(i => i.Name == openRecentSubItem.Name); + if (oldOpenRecentSubItem != null) + { + MainMenuButtonFlyout.Items.Remove(oldOpenRecentSubItem); + } + + openRecentSubItem.IsEnabled = false; + if (openRecentSubItem.Items?.Count > 0) + { + openRecentSubItem.Items?.Add(new MenuFlyoutSeparator()); + + var clearRecentlyOpenedSubItem = + new MenuFlyoutItem() + { + Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent_ClearRecentlyOpenedSubItem_Text") + }; + clearRecentlyOpenedSubItem.Click += async (sender, args) => + { + MRUService.ClearAll(); + await BuildOpenRecentButtonSubItems(); + }; + openRecentSubItem.Items?.Add(clearRecentlyOpenedSubItem); + openRecentSubItem.IsEnabled = true; + } + + if (MainMenuButtonFlyout.Items != null) + { + var indexToInsert = MainMenuButtonFlyout.Items.IndexOf(MenuOpenFileButton) + 1; + MainMenuButtonFlyout.Items.Insert(indexToInsert, openRecentSubItem); + } + } + + private KeyboardCommandHandler GetKeyboardCommandHandler() + { + return new KeyboardCommandHandler(new List>() + { + new KeyboardCommand(true, false, false, VirtualKey.W, (args) => NotepadsCore.CloseTextEditor(NotepadsCore.GetSelectedTextEditor())), + new KeyboardCommand(true, false, false, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(true)), + new KeyboardCommand(true, false, true, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(false)), + new KeyboardCommand(true, false, false, VirtualKey.N, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), + new KeyboardCommand(true, false, false, VirtualKey.T, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), + new KeyboardCommand(true, false, false, VirtualKey.O, async (args) => await OpenNewFiles()), + new KeyboardCommand(true, false, false, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false, ignoreUnmodifiedDocument: true)), + new KeyboardCommand(true, false, true, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true)), + new KeyboardCommand(true, false, false, VirtualKey.P, async (args) => await Print(NotepadsCore.GetSelectedTextEditor())), + new KeyboardCommand(true, false, true, VirtualKey.P, async (args) => await PrintAll(NotepadsCore.GetAllTextEditors())), + new KeyboardCommand(true, false, true, VirtualKey.R, (args) => { ReloadFileFromDisk(this, new RoutedEventArgs()); }), + new KeyboardCommand(true, false, true, VirtualKey.N, async (args) => await OpenNewAppInstance()), + new KeyboardCommand(true, false, false, VirtualKey.Number1, (args) => NotepadsCore.SwitchTo(0)), + new KeyboardCommand(true, false, false, VirtualKey.Number2, (args) => NotepadsCore.SwitchTo(1)), + new KeyboardCommand(true, false, false, VirtualKey.Number3, (args) => NotepadsCore.SwitchTo(2)), + new KeyboardCommand(true, false, false, VirtualKey.Number4, (args) => NotepadsCore.SwitchTo(3)), + new KeyboardCommand(true, false, false, VirtualKey.Number5, (args) => NotepadsCore.SwitchTo(4)), + new KeyboardCommand(true, false, false, VirtualKey.Number6, (args) => NotepadsCore.SwitchTo(5)), + new KeyboardCommand(true, false, false, VirtualKey.Number7, (args) => NotepadsCore.SwitchTo(6)), + new KeyboardCommand(true, false, false, VirtualKey.Number8, (args) => NotepadsCore.SwitchTo(7)), + new KeyboardCommand(true, false, false, VirtualKey.Number9, (args) => NotepadsCore.SwitchTo(8)), + new KeyboardCommand(VirtualKey.F11, (args) => { EnterExitFullScreenMode(); }), + new KeyboardCommand(VirtualKey.F12, (args) => { EnterExitCompactOverlayMode(); }), + new KeyboardCommand(VirtualKey.Escape, (args) => { if (RootSplitView.IsPaneOpen) RootSplitView.IsPaneOpen = false; }), + }); + } + + private async Task OpenNewAppInstance() + { + if (!await NotepadsProtocolService.LaunchProtocolAsync(NotepadsOperationProtocol.OpenNewInstance)) + { + Analytics.TrackEvent("FailedToOpenNewAppInstance"); + } + } + + #region Application Life Cycle & Window management + + // Handles external links or cmd args activation before Sets loaded + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + + switch (e.Parameter) + { + case null: + return; + case FileActivatedEventArgs fileActivatedEventArgs: + _appLaunchFiles = fileActivatedEventArgs.Files; + break; + case CommandLineActivatedEventArgs commandLineActivatedEventArgs: + _appLaunchCmdDir = commandLineActivatedEventArgs.Operation.CurrentDirectoryPath; + _appLaunchCmdArgs = commandLineActivatedEventArgs.Operation.Arguments; + break; + case ProtocolActivatedEventArgs protocol: + _appLaunchUri = protocol.Uri; + break; + case XboxGameBarWidget widget: + _widget = widget; + _widgetControl = new XboxGameBarWidgetControl(_widget); + _widget.SettingsClicked += Widget_SettingsClicked; + //_widget.PinnedChanged += Widget_PinnedChanged; + //_widget.FavoritedChanged += Widget_FavoritedChanged; + //_widget.RequestedThemeChanged += Widget_RequestedThemeChanged; + //_widget.VisibleChanged += Widget_VisibleChanged; + //_widget.WindowStateChanged += Widget_WindowStateChanged; //_widget.GameBarDisplayModeChanged += Widget_GameBarDisplayModeChanged; - Window.Current.Closed += WidgetMainWindowClosed; - break; - } - } - - // App should wait for Sets fully loaded before opening files requested by user (by click or from cmd) - // Open files from external links or cmd args on Sets Loaded - private async void Sets_Loaded(object sender, RoutedEventArgs e) - { - int loadedCount = 0; - - if (!_loaded && EditorSettingsService.IsSessionSnapshotEnabled) - { - try - { - loadedCount = await SessionManager.LoadLastSessionAsync(); - } - catch (Exception ex) - { - LoggingService.LogError($"[SessionManager] Failed to LoadLastSessionAsync: {ex}"); - Analytics.TrackEvent("FailedToLoadLastSession", new Dictionary { { "Exception", ex.ToString() } }); - } - } - - if (_appLaunchFiles != null && _appLaunchFiles.Count > 0) - { - loadedCount += await OpenFiles(_appLaunchFiles); - _appLaunchFiles = null; - } - else if (_appLaunchCmdDir != null) - { - var file = await FileSystemUtility.OpenFileFromCommandLine(_appLaunchCmdDir, _appLaunchCmdArgs); - if (file != null && await OpenFile(file)) - { - loadedCount++; - } - _appLaunchCmdDir = null; - _appLaunchCmdArgs = null; - } - else if (_appLaunchUri != null) - { - var operation = NotepadsProtocolService.GetOperationProtocol(_appLaunchUri, out var context); - if (operation == NotepadsOperationProtocol.OpenNewInstance || operation == NotepadsOperationProtocol.Unrecognized) - { - // Do nothing - } - _appLaunchUri = null; - } - - if (!_loaded) - { - if (loadedCount == 0) - { - NotepadsCore.OpenNewTextEditor(_defaultNewFileName); - } - - if (!App.IsFirstInstance) - { - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("App_ShadowWindowIndicator_Description"), 4000); - } - _loaded = true; - } - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - SessionManager.IsBackupEnabled = true; - SessionManager.StartSessionBackup(); - } - - await BuildOpenRecentButtonSubItems(); - - Window.Current.CoreWindow.Activated -= CoreWindow_Activated; - Window.Current.CoreWindow.Activated += CoreWindow_Activated; - - if (!App.IsGameBarWidget) - { - // An issue with the Game Bar extension model and Windows platform prevents the Notepads process from exiting cleanly - // when more than one CoreWindow has been created, and NotepadsMainPage is the last to close. The common case for this - // is to open Notepads in Game Bar, then open its settings, then close the settings and finally close Notepads. - // This puts the process in a bad state where it will no longer open in Game Bar and the Notepads process is orphaned. - // To work around this do not use the EnteredBackground event when running as a widget. - // Microsoft is tracking this issue as VSO#25735260 - Application.Current.EnteredBackground -= App_EnteredBackground; - Application.Current.EnteredBackground += App_EnteredBackground; - } - } - - private async void App_EnteredBackground(object sender, Windows.ApplicationModel.EnteredBackgroundEventArgs e) - { - var deferral = e.GetDeferral(); - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - await SessionManager.SaveSessionAsync(); - } - - deferral.Complete(); - } - - private void WidgetMainWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) - { + Window.Current.Closed += WidgetMainWindowClosed; + break; + } + } + + // App should wait for Sets fully loaded before opening files requested by user (by click or from cmd) + // Open files from external links or cmd args on Sets Loaded + private async void Sets_Loaded(object sender, RoutedEventArgs e) + { + int loadedCount = 0; + + if (!_loaded && EditorSettingsService.IsSessionSnapshotEnabled) + { + try + { + loadedCount = await SessionManager.LoadLastSessionAsync(); + } + catch (Exception ex) + { + LoggingService.LogError($"[SessionManager] Failed to LoadLastSessionAsync: {ex}"); + Analytics.TrackEvent("FailedToLoadLastSession", new Dictionary { { "Exception", ex.ToString() } }); + } + } + + if (_appLaunchFiles != null && _appLaunchFiles.Count > 0) + { + loadedCount += await OpenFiles(_appLaunchFiles); + _appLaunchFiles = null; + } + else if (_appLaunchCmdDir != null) + { + var file = await FileSystemUtility.OpenFileFromCommandLine(_appLaunchCmdDir, _appLaunchCmdArgs); + if (file != null && await OpenFile(file)) + { + loadedCount++; + } + _appLaunchCmdDir = null; + _appLaunchCmdArgs = null; + } + else if (_appLaunchUri != null) + { + var operation = NotepadsProtocolService.GetOperationProtocol(_appLaunchUri, out var context); + if (operation == NotepadsOperationProtocol.OpenNewInstance || operation == NotepadsOperationProtocol.Unrecognized) + { + // Do nothing + } + _appLaunchUri = null; + } + + if (!_loaded) + { + if (loadedCount == 0) + { + NotepadsCore.OpenNewTextEditor(_defaultNewFileName); + } + + if (!App.IsFirstInstance) + { + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("App_ShadowWindowIndicator_Description"), 4000); + } + _loaded = true; + } + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + SessionManager.IsBackupEnabled = true; + SessionManager.StartSessionBackup(); + } + + await BuildOpenRecentButtonSubItems(); + + Window.Current.CoreWindow.Activated -= CoreWindow_Activated; + Window.Current.CoreWindow.Activated += CoreWindow_Activated; + + if (!App.IsGameBarWidget) + { + // An issue with the Game Bar extension model and Windows platform prevents the Notepads process from exiting cleanly + // when more than one CoreWindow has been created, and NotepadsMainPage is the last to close. The common case for this + // is to open Notepads in Game Bar, then open its settings, then close the settings and finally close Notepads. + // This puts the process in a bad state where it will no longer open in Game Bar and the Notepads process is orphaned. + // To work around this do not use the EnteredBackground event when running as a widget. + // Microsoft is tracking this issue as VSO#25735260 + Application.Current.EnteredBackground -= App_EnteredBackground; + Application.Current.EnteredBackground += App_EnteredBackground; + } + } + + private async void App_EnteredBackground(object sender, Windows.ApplicationModel.EnteredBackgroundEventArgs e) + { + var deferral = e.GetDeferral(); + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + await SessionManager.SaveSessionAsync(); + } + + deferral.Complete(); + } + + private void WidgetMainWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) + { // Unregister events Window.Current.Closed -= WidgetMainWindowClosed; - _widget.SettingsClicked -= Widget_SettingsClicked; - - // Cleanup game bar objects - _widget = null; - _widgetControl = null; - } - - public void ExecuteProtocol(Uri uri) - { - } - - private void CoreWindow_Activated(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.WindowActivatedEventArgs args) - { - if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated) - { - LoggingService.LogInfo("CoreWindow Deactivated.", consoleOnly: true); - NotepadsCore.GetSelectedTextEditor()?.StopCheckingFileStatus(); - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - SessionManager.StopSessionBackup(); - } - } - else if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.PointerActivated || - args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.CodeActivated) - { - LoggingService.LogInfo("CoreWindow Activated.", consoleOnly: true); - Task.Run(() => ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString())); - NotepadsCore.GetSelectedTextEditor()?.StartCheckingFileStatusPeriodically(); - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - SessionManager.StartSessionBackup(); - } - } - } - - void WindowVisibilityChangedEventHandler(System.Object sender, Windows.UI.Core.VisibilityChangedEventArgs e) - { - LoggingService.LogInfo($"Window Visibility Changed, Visible = {e.Visible}.", consoleOnly: true); - // Perform operations that should take place when the application becomes visible rather than - // when it is prelaunched, such as building a what's new feed - } - - // Content sharing - private void MainPage_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) - { - var textEditor = NotepadsCore.GetSelectedTextEditor(); - if (textEditor == null) return; - - if (NotepadsCore.TryGetSharingContent(textEditor, out var title, out var content)) - { - args.Request.Data.Properties.Title = title; - args.Request.Data.SetText(content); - } - else - { - args.Request.FailWithDisplayText(_resourceLoader.GetString("ContentSharing_FailureDisplayText")); - } - } - - private async void MainPage_CloseRequested(object sender, Windows.UI.Core.Preview.SystemNavigationCloseRequestedPreviewEventArgs e) - { - var deferral = e.GetDeferral(); - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - // Save session before app exit - await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); - deferral.Complete(); - return; - } - - if (!NotepadsCore.HaveUnsavedTextEditor()) - { - deferral.Complete(); - return; - } - - var appCloseSaveReminderDialog = NotepadsDialogFactory.GetAppCloseSaveReminderDialog( - async () => - { - var count = NotepadsCore.GetNumberOfOpenedTextEditors(); - - foreach (var textEditor in NotepadsCore.GetAllTextEditors()) - { - if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) - { - if (count == 1) - { - _appShouldExitAfterLastEditorClosed = true; - } - NotepadsCore.DeleteTextEditor(textEditor); - count--; - } - } - - // Prevent app from closing if there is any tab still opens - if (count > 0) - { - e.Handled = true; - await BuildOpenRecentButtonSubItems(); - } - - deferral.Complete(); - }, - discardAndExitAction: () => - { - deferral.Complete(); - }, - cancelAction: () => - { - e.Handled = true; - deferral.Complete(); - }); - - await DialogManager.OpenDialogAsync(appCloseSaveReminderDialog, awaitPreviousDialog: false); - - if (e.Handled && !appCloseSaveReminderDialog.IsAborted) - { - NotepadsCore.FocusOnSelectedTextEditor(); - } - } - - private void UpdateApplicationTitle(ITextEditor activeTextEditor) - { - ApplicationView.GetForCurrentView().Title = activeTextEditor.EditingFileName ?? activeTextEditor.FileNamePlaceholder; - } - - #endregion - - #region XboxGameBar - - private async void Widget_SettingsClicked(XboxGameBarWidget sender, object args) - { - await _widget.ActivateSettingsAsync(); - } - - #endregion - - #region InAppNotification - - public void PostNotification(string message, int duration) - { - if (StatusNotification == null) { FindName("StatusNotification"); } // Lazy loading - var textSize = FontUtility.GetTextSize(StatusNotification.FontFamily, StatusNotification.FontSize, message); - StatusNotification.Width = textSize.Width + 100; // actual width + padding - StatusNotification.Height = textSize.Height + 50; // actual height + padding - StatusNotification.Show(message, duration); - } - - #endregion - - #region NotepadsCore Events - - private void OnTextEditorLoaded(object sender, ITextEditor textEditor) - { - if (NotepadsCore.GetSelectedTextEditor() == textEditor) - { - SetupStatusBar(textEditor); - UpdateApplicationTitle(textEditor); - NotepadsCore.FocusOnSelectedTextEditor(); - } - } - - private void OnTextEditorUnloaded(object sender, ITextEditor textEditor) - { - if (NotepadsCore.GetNumberOfOpenedTextEditors() == 0 && !_appShouldExitAfterLastEditorClosed) - { - NotepadsCore.OpenNewTextEditor(_defaultNewFileName); - } - } - - private async void OnTextEditorMovedToAnotherAppInstance(object sender, ITextEditor textEditor) - { - // Notepads should exit if last tab was dragged to another app instance - if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1) - { - _appShouldExitAfterLastEditorClosed = true; - - NotepadsCore.DeleteTextEditor(textEditor); - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); - } - - Application.Current.Exit(); - } - else - { - NotepadsCore.DeleteTextEditor(textEditor); - } - } - - private async void OnTextEditorClosing(object sender, ITextEditor textEditor) - { - if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1 && textEditor.IsModified == false && textEditor.EditingFile == null) - { - // Do nothing - // Take no action if user is trying to close the last tab and the last tab is a new empty document - } - else if (!textEditor.IsModified) - { - NotepadsCore.DeleteTextEditor(textEditor); - } - else // Remind user to save uncommitted changes - { - var file = textEditor.EditingFilePath ?? textEditor.FileNamePlaceholder; - - var setCloseSaveReminderDialog = NotepadsDialogFactory.GetSetCloseSaveReminderDialog(file, async () => - { - if (NotepadsCore.GetAllTextEditors().Contains(textEditor) && await Save(textEditor, saveAs: false)) - { - NotepadsCore.DeleteTextEditor(textEditor); - } - }, () => - { - if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) - { - NotepadsCore.DeleteTextEditor(textEditor); - } - }); - - setCloseSaveReminderDialog.Opened += (s, a) => - { - if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) - { - NotepadsCore.SwitchTo(textEditor); - } - }; - - await DialogManager.OpenDialogAsync(setCloseSaveReminderDialog, awaitPreviousDialog: true); - - if (!setCloseSaveReminderDialog.IsAborted) - { - NotepadsCore.FocusOnSelectedTextEditor(); - } - } - } - - private void OnTextEditor_KeyDown(object sender, KeyRoutedEventArgs e) - { - if (!(sender is ITextEditor textEditor)) return; - // ignoring key events coming from inactive text editors - if (NotepadsCore.GetSelectedTextEditor() != textEditor) return; - var result = _keyboardCommandHandler.Handle(e); - if (result.ShouldHandle) - { - e.Handled = true; - } - } - - private async void OnStorageItemsDropped(object sender, IReadOnlyList storageItems) - { - foreach (var storageItem in storageItems) - { - if (storageItem is StorageFile file) - { - await OpenFile(file); - Analytics.TrackEvent("OnStorageFileDropped"); - } - } - } - - #endregion - } + _widget.SettingsClicked -= Widget_SettingsClicked; + + // Cleanup game bar objects + _widget = null; + _widgetControl = null; + } + + public void ExecuteProtocol(Uri uri) + { + } + + private void CoreWindow_Activated(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.WindowActivatedEventArgs args) + { + if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated) + { + LoggingService.LogInfo("CoreWindow Deactivated.", consoleOnly: true); + NotepadsCore.GetSelectedTextEditor()?.StopCheckingFileStatus(); + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + SessionManager.StopSessionBackup(); + } + } + else if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.PointerActivated || + args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.CodeActivated) + { + LoggingService.LogInfo("CoreWindow Activated.", consoleOnly: true); + Task.Run(() => ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString())); + NotepadsCore.GetSelectedTextEditor()?.StartCheckingFileStatusPeriodically(); + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + SessionManager.StartSessionBackup(); + } + } + } + + void WindowVisibilityChangedEventHandler(System.Object sender, Windows.UI.Core.VisibilityChangedEventArgs e) + { + LoggingService.LogInfo($"Window Visibility Changed, Visible = {e.Visible}.", consoleOnly: true); + // Perform operations that should take place when the application becomes visible rather than + // when it is prelaunched, such as building a what's new feed + } + + // Content sharing + private void MainPage_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) + { + var textEditor = NotepadsCore.GetSelectedTextEditor(); + if (textEditor == null) return; + + if (NotepadsCore.TryGetSharingContent(textEditor, out var title, out var content)) + { + args.Request.Data.Properties.Title = title; + args.Request.Data.SetText(content); + } + else + { + args.Request.FailWithDisplayText(_resourceLoader.GetString("ContentSharing_FailureDisplayText")); + } + } + + private async void MainPage_CloseRequested(object sender, Windows.UI.Core.Preview.SystemNavigationCloseRequestedPreviewEventArgs e) + { + var deferral = e.GetDeferral(); + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + // Save session before app exit + await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); + deferral.Complete(); + return; + } + + if (!NotepadsCore.HaveUnsavedTextEditor()) + { + deferral.Complete(); + return; + } + + var appCloseSaveReminderDialog = NotepadsDialogFactory.GetAppCloseSaveReminderDialog( + async () => + { + var count = NotepadsCore.GetNumberOfOpenedTextEditors(); + + foreach (var textEditor in NotepadsCore.GetAllTextEditors()) + { + if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) + { + if (count == 1) + { + _appShouldExitAfterLastEditorClosed = true; + } + NotepadsCore.DeleteTextEditor(textEditor); + count--; + } + } + + // Prevent app from closing if there is any tab still opens + if (count > 0) + { + e.Handled = true; + await BuildOpenRecentButtonSubItems(); + } + + deferral.Complete(); + }, + discardAndExitAction: () => + { + deferral.Complete(); + }, + cancelAction: () => + { + e.Handled = true; + deferral.Complete(); + }); + + await DialogManager.OpenDialogAsync(appCloseSaveReminderDialog, awaitPreviousDialog: false); + + if (e.Handled && !appCloseSaveReminderDialog.IsAborted) + { + NotepadsCore.FocusOnSelectedTextEditor(); + } + } + + private void UpdateApplicationTitle(ITextEditor activeTextEditor) + { + if (!App.IsGameBarWidget) + { + ApplicationView.GetForCurrentView().Title = activeTextEditor.EditingFileName ?? activeTextEditor.FileNamePlaceholder; + } + } + + #endregion + + #region XboxGameBar + + private async void Widget_SettingsClicked(XboxGameBarWidget sender, object args) + { + await _widget.ActivateSettingsAsync(); + } + + #endregion + + #region InAppNotification + + public void PostNotification(string message, int duration) + { + if (StatusNotification == null) { FindName("StatusNotification"); } // Lazy loading + var textSize = FontUtility.GetTextSize(StatusNotification.FontFamily, StatusNotification.FontSize, message); + StatusNotification.Width = textSize.Width + 100; // actual width + padding + StatusNotification.Height = textSize.Height + 50; // actual height + padding + StatusNotification.Show(message, duration); + } + + #endregion + + #region NotepadsCore Events + + private void OnTextEditorLoaded(object sender, ITextEditor textEditor) + { + if (NotepadsCore.GetSelectedTextEditor() == textEditor) + { + SetupStatusBar(textEditor); + UpdateApplicationTitle(textEditor); + NotepadsCore.FocusOnSelectedTextEditor(); + } + } + + private void OnTextEditorUnloaded(object sender, ITextEditor textEditor) + { + if (NotepadsCore.GetNumberOfOpenedTextEditors() == 0 && !_appShouldExitAfterLastEditorClosed) + { + NotepadsCore.OpenNewTextEditor(_defaultNewFileName); + } + } + + private async void OnTextEditorMovedToAnotherAppInstance(object sender, ITextEditor textEditor) + { + // Notepads should exit if last tab was dragged to another app instance + if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1) + { + _appShouldExitAfterLastEditorClosed = true; + + NotepadsCore.DeleteTextEditor(textEditor); + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); + } + + Application.Current.Exit(); + } + else + { + NotepadsCore.DeleteTextEditor(textEditor); + } + } + + private async void OnTextEditorClosing(object sender, ITextEditor textEditor) + { + if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1 && textEditor.IsModified == false && textEditor.EditingFile == null) + { + // Do nothing + // Take no action if user is trying to close the last tab and the last tab is a new empty document + } + else if (!textEditor.IsModified) + { + NotepadsCore.DeleteTextEditor(textEditor); + } + else // Remind user to save uncommitted changes + { + var file = textEditor.EditingFilePath ?? textEditor.FileNamePlaceholder; + + var setCloseSaveReminderDialog = NotepadsDialogFactory.GetSetCloseSaveReminderDialog(file, async () => + { + if (NotepadsCore.GetAllTextEditors().Contains(textEditor) && await Save(textEditor, saveAs: false)) + { + NotepadsCore.DeleteTextEditor(textEditor); + } + }, () => + { + if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) + { + NotepadsCore.DeleteTextEditor(textEditor); + } + }); + + setCloseSaveReminderDialog.Opened += (s, a) => + { + if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) + { + NotepadsCore.SwitchTo(textEditor); + } + }; + + await DialogManager.OpenDialogAsync(setCloseSaveReminderDialog, awaitPreviousDialog: true); + + if (!setCloseSaveReminderDialog.IsAborted) + { + NotepadsCore.FocusOnSelectedTextEditor(); + } + } + } + + private void OnTextEditor_KeyDown(object sender, KeyRoutedEventArgs e) + { + if (!(sender is ITextEditor textEditor)) return; + // ignoring key events coming from inactive text editors + if (NotepadsCore.GetSelectedTextEditor() != textEditor) return; + var result = _keyboardCommandHandler.Handle(e); + if (result.ShouldHandle) + { + e.Handled = true; + } + } + + private async void OnStorageItemsDropped(object sender, IReadOnlyList storageItems) + { + foreach (var storageItem in storageItems) + { + if (storageItem is StorageFile file) + { + await OpenFile(file); + Analytics.TrackEvent("OnStorageFileDropped"); + } + } + } + + #endregion + } } \ No newline at end of file From a4934e1bea481bb3a4b46848225e860b36487d99 Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Tue, 7 Apr 2020 15:44:50 -0700 Subject: [PATCH 21/49] Revert "Update NotepadsMainPage.xaml.cs" This reverts commit 01b06f01f325b90a142b515b58e2471cdcc99e6a. --- src/Notepads/NotepadsMainPage.xaml.cs | 1587 ++++++++++++------------- 1 file changed, 792 insertions(+), 795 deletions(-) diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index 6cb441d2a..5cf688d31 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -1,799 +1,796 @@ -namespace Notepads -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - using Notepads.Commands; - using Notepads.Controls.Print; - using Notepads.Controls.Settings; - using Notepads.Controls.TextEditor; - using Notepads.Core; - using Notepads.Extensions; - using Notepads.Services; - using Notepads.Settings; - using Notepads.Utilities; - using Windows.ApplicationModel.Activation; - using Windows.ApplicationModel.DataTransfer; - using Windows.ApplicationModel.Resources; - using Windows.Storage; - using Windows.System; - using Windows.UI.ViewManagement; - using Windows.UI.Xaml; - using Windows.UI.Xaml.Controls; - using Windows.UI.Xaml.Controls.Primitives; - using Windows.UI.Xaml.Input; - using Windows.UI.Xaml.Media; - using Windows.UI.Xaml.Media.Animation; - using Windows.UI.Xaml.Navigation; - using Microsoft.AppCenter.Analytics; - using Microsoft.Gaming.XboxGameBar; - using Windows.Graphics.Printing; - - public sealed partial class NotepadsMainPage : Page, INotificationDelegate - { - private IReadOnlyList _appLaunchFiles; - - private string _appLaunchCmdDir; - private string _appLaunchCmdArgs; - private Uri _appLaunchUri; - - private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView(); - - private bool _loaded = false; - private bool _appShouldExitAfterLastEditorClosed = false; - - private const int TitleBarReservedAreaDefaultWidth = 180; - private const int TitleBarReservedAreaCompactOverlayWidth = 100; - - private INotepadsCore _notepadsCore; - - private XboxGameBarWidget _widget; // maintain throughout the lifetime of the notepads widget - private XboxGameBarWidgetControl _widgetControl; - - private INotepadsCore NotepadsCore - { - get - { - if (_notepadsCore == null) - { - _notepadsCore = new NotepadsCore(Sets, new NotepadsExtensionProvider()); - _notepadsCore.StorageItemsDropped += OnStorageItemsDropped; - _notepadsCore.TextEditorLoaded += OnTextEditorLoaded; - _notepadsCore.TextEditorUnloaded += OnTextEditorUnloaded; - _notepadsCore.TextEditorKeyDown += OnTextEditor_KeyDown; - _notepadsCore.TextEditorClosing += OnTextEditorClosing; - _notepadsCore.TextEditorMovedToAnotherAppInstance += OnTextEditorMovedToAnotherAppInstance; - _notepadsCore.TextEditorSelectionChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateLineColumnIndicator(editor); }; - _notepadsCore.TextEditorFontZoomFactorChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateFontZoomIndicator(editor); }; - _notepadsCore.TextEditorEncodingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateEncodingIndicator(editor.GetEncoding()); }; - _notepadsCore.TextEditorLineEndingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) { UpdateLineEndingIndicator(editor.GetLineEnding()); UpdateLineColumnIndicator(editor); } }; - _notepadsCore.TextEditorEditorModificationStateChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) SetupStatusBar(editor); }; - _notepadsCore.TextEditorFileModificationStateChanged += (sender, editor) => - { - if (NotepadsCore.GetSelectedTextEditor() == editor) - { - if (editor.FileModificationState == FileModificationState.Modified) - { - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileModifiedOutsideIndicator_ToolTip"), 3500); - } - else if (editor.FileModificationState == FileModificationState.RenamedMovedOrDeleted) - { - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileRenamedMovedOrDeletedIndicator_ToolTip"), 3500); - } - UpdateFileModificationStateIndicator(editor); - UpdatePathIndicator(editor); - } - }; - _notepadsCore.TextEditorSaved += (sender, editor) => - { - if (NotepadsCore.GetSelectedTextEditor() == editor) - { - SetupStatusBar(editor); - } - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_NotificationMsg_FileSaved"), 1500); - }; - } - - return _notepadsCore; - } - } - - private readonly ICommandHandler _keyboardCommandHandler; - - private ISessionManager _sessionManager; - - private ISessionManager SessionManager => _sessionManager ?? (_sessionManager = SessionUtility.GetSessionManager(NotepadsCore)); - - private readonly string _defaultNewFileName; - - public NotepadsMainPage() - { - InitializeComponent(); - - _defaultNewFileName = _resourceLoader.GetString("TextEditor_DefaultNewFileName"); - - NotificationCenter.Instance.SetNotificationDelegate(this); - - // Setup theme - ThemeSettingsService.OnBackgroundChanged += ThemeSettingsService_OnBackgroundChanged; - ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; - ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; - ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); - - // Setup custom Title Bar - Window.Current.SetTitleBar(AppTitleBar); - - // Setup status bar - ShowHideStatusBar(EditorSettingsService.ShowStatusBar); - EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); - }); - }; - - // Session backup and restore toggle - EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => - { - if (isSessionBackupAndRestoreEnabled) - { - SessionManager.IsBackupEnabled = true; - SessionManager.StartSessionBackup(startImmediately: true); - } - else - { - SessionManager.IsBackupEnabled = false; - SessionManager.StopSessionBackup(); - await SessionManager.ClearSessionDataAsync(); - } - }); - }; - - // Sharing - Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView().DataRequested += MainPage_DataRequested; - Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += MainPage_CloseRequested; - - Window.Current.VisibilityChanged += WindowVisibilityChangedEventHandler; - Window.Current.SizeChanged += WindowSizeChanged; - - InitControls(); - - // Init shortcuts - _keyboardCommandHandler = GetKeyboardCommandHandler(); - - //Register for printing - if (!PrintManager.IsSupported()) - { - MenuPrintButton.Visibility = Visibility.Collapsed; - MenuPrintAllButton.Visibility = Visibility.Collapsed; - PrintSettingsSeparator.Visibility = Visibility.Collapsed; - } - else - { - PrintArgs.RegisterForPrinting(this); - } - } - - private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - ThemeSettingsService.SetRequestedAccentColor(); - }); - } - - private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); - }); - } - - private async void ThemeSettingsService_OnBackgroundChanged(object sender, Brush backgroundBrush) - { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - RootGrid.Background = backgroundBrush; - }); - } - - private void InitControls() - { - ToolTipService.SetToolTip(ExitCompactOverlayButton, _resourceLoader.GetString("App_ExitCompactOverlayMode_Text")); - RootSplitView.PaneOpening += delegate { SettingsFrame.Navigate(typeof(SettingsPage), null, new SuppressNavigationTransitionInfo()); }; - RootSplitView.PaneClosed += delegate { NotepadsCore.FocusOnSelectedTextEditor(); }; - NewSetButton.Click += delegate { NotepadsCore.OpenNewTextEditor(_defaultNewFileName); }; - MainMenuButton.Click += (sender, args) => FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender); - MenuCreateNewButton.Click += (sender, args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName); - MenuCreateNewWindowButton.Click += async (sender, args) => await OpenNewAppInstance(); - MenuOpenFileButton.Click += async (sender, args) => await OpenNewFiles(); - MenuSaveButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false); - MenuSaveAsButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true); - MenuSaveAllButton.Click += async (sender, args) => - { - var success = false; - foreach (var textEditor in NotepadsCore.GetAllTextEditors()) - { - if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) success = true; - } - if (success) - { - await BuildOpenRecentButtonSubItems(); - } - }; - MenuFindButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: false); - MenuReplaceButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: true); - MenuFullScreenButton.Click += (sender, args) => EnterExitFullScreenMode(); - MenuCompactOverlayButton.Click += (sender, args) => EnterExitCompactOverlayMode(); - MenuPrintButton.Click += async (sender, args) => await Print(NotepadsCore.GetSelectedTextEditor()); - MenuPrintAllButton.Click += async (sender, args) => await PrintAll(NotepadsCore.GetAllTextEditors()); - MenuSettingsButton.Click += (sender, args) => RootSplitView.IsPaneOpen = true; - - MainMenuButtonFlyout.Opening += (sender, o) => - { - var selectedTextEditor = NotepadsCore.GetSelectedTextEditor(); - if (selectedTextEditor == null) - { - MenuSaveButton.IsEnabled = false; - MenuSaveAsButton.IsEnabled = false; - MenuFindButton.IsEnabled = false; - MenuReplaceButton.IsEnabled = false; - MenuPrintButton.IsEnabled = false; - MenuPrintAllButton.IsEnabled = false; - } - else if (selectedTextEditor.IsEditorEnabled() == false) - { - MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; - MenuSaveAsButton.IsEnabled = true; - MenuFindButton.IsEnabled = false; - MenuReplaceButton.IsEnabled = false; - } - else - { - MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; - MenuSaveAsButton.IsEnabled = true; - MenuFindButton.IsEnabled = true; - MenuReplaceButton.IsEnabled = true; - - if (PrintManager.IsSupported()) - { - MenuPrintButton.IsEnabled = !string.IsNullOrEmpty(selectedTextEditor.GetText()); - MenuPrintAllButton.IsEnabled = NotepadsCore.HaveNonemptyTextEditor(); - } - } - - MenuFullScreenButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().IsFullScreenMode ? - "App_ExitFullScreenMode_Text" : "App_EnterFullScreenMode_Text"); - MenuCompactOverlayButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay ? - "App_ExitCompactOverlayMode_Text" : "App_EnterCompactOverlayMode_Text"); - MenuSaveAllButton.IsEnabled = NotepadsCore.HaveUnsavedTextEditor(); - }; - - if (!App.IsFirstInstance) - { - MainMenuButton.Foreground = new SolidColorBrush(ThemeSettingsService.AppAccentColor); - MenuSettingsButton.IsEnabled = false; - } - - if (App.IsGameBarWidget) - { - MenuFullScreenSeparator.Visibility = Visibility.Collapsed; - PrintSettingsSeparator.Visibility = Visibility.Collapsed; - - MenuCompactOverlayButton.Visibility = Visibility.Collapsed; - MenuFullScreenButton.Visibility = Visibility.Collapsed; - MenuSettingsButton.Visibility = Visibility.Collapsed; - } - } - - private async Task BuildOpenRecentButtonSubItems() - { - var openRecentSubItem = new MenuFlyoutSubItem - { - Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent/Text"), - Icon = new FontIcon { Glyph = "\xE81C" }, - Name = "MenuOpenRecentlyUsedFileButton", - }; - - var MRUFileList = new HashSet(); - - foreach (var item in await MRUService.Get(top: 10)) - { - if (item is StorageFile file) - { - if (MRUFileList.Contains(file.Path)) - { - // MRU might contains files with same path (User opens a recently used file after renaming it) - // So we need to do the decouple here - continue; - } - var newItem = new MenuFlyoutItem() - { - Text = file.Path - }; - ToolTipService.SetToolTip(newItem, file.Path); - newItem.Click += async (sender, args) => { await OpenFile(file); }; - openRecentSubItem.Items?.Add(newItem); - MRUFileList.Add(file.Path); - } - } - - var oldOpenRecentSubItem = MainMenuButtonFlyout.Items?.FirstOrDefault(i => i.Name == openRecentSubItem.Name); - if (oldOpenRecentSubItem != null) - { - MainMenuButtonFlyout.Items.Remove(oldOpenRecentSubItem); - } - - openRecentSubItem.IsEnabled = false; - if (openRecentSubItem.Items?.Count > 0) - { - openRecentSubItem.Items?.Add(new MenuFlyoutSeparator()); - - var clearRecentlyOpenedSubItem = - new MenuFlyoutItem() - { - Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent_ClearRecentlyOpenedSubItem_Text") - }; - clearRecentlyOpenedSubItem.Click += async (sender, args) => - { - MRUService.ClearAll(); - await BuildOpenRecentButtonSubItems(); - }; - openRecentSubItem.Items?.Add(clearRecentlyOpenedSubItem); - openRecentSubItem.IsEnabled = true; - } - - if (MainMenuButtonFlyout.Items != null) - { - var indexToInsert = MainMenuButtonFlyout.Items.IndexOf(MenuOpenFileButton) + 1; - MainMenuButtonFlyout.Items.Insert(indexToInsert, openRecentSubItem); - } - } - - private KeyboardCommandHandler GetKeyboardCommandHandler() - { - return new KeyboardCommandHandler(new List>() - { - new KeyboardCommand(true, false, false, VirtualKey.W, (args) => NotepadsCore.CloseTextEditor(NotepadsCore.GetSelectedTextEditor())), - new KeyboardCommand(true, false, false, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(true)), - new KeyboardCommand(true, false, true, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(false)), - new KeyboardCommand(true, false, false, VirtualKey.N, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), - new KeyboardCommand(true, false, false, VirtualKey.T, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), - new KeyboardCommand(true, false, false, VirtualKey.O, async (args) => await OpenNewFiles()), - new KeyboardCommand(true, false, false, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false, ignoreUnmodifiedDocument: true)), - new KeyboardCommand(true, false, true, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true)), - new KeyboardCommand(true, false, false, VirtualKey.P, async (args) => await Print(NotepadsCore.GetSelectedTextEditor())), - new KeyboardCommand(true, false, true, VirtualKey.P, async (args) => await PrintAll(NotepadsCore.GetAllTextEditors())), - new KeyboardCommand(true, false, true, VirtualKey.R, (args) => { ReloadFileFromDisk(this, new RoutedEventArgs()); }), - new KeyboardCommand(true, false, true, VirtualKey.N, async (args) => await OpenNewAppInstance()), - new KeyboardCommand(true, false, false, VirtualKey.Number1, (args) => NotepadsCore.SwitchTo(0)), - new KeyboardCommand(true, false, false, VirtualKey.Number2, (args) => NotepadsCore.SwitchTo(1)), - new KeyboardCommand(true, false, false, VirtualKey.Number3, (args) => NotepadsCore.SwitchTo(2)), - new KeyboardCommand(true, false, false, VirtualKey.Number4, (args) => NotepadsCore.SwitchTo(3)), - new KeyboardCommand(true, false, false, VirtualKey.Number5, (args) => NotepadsCore.SwitchTo(4)), - new KeyboardCommand(true, false, false, VirtualKey.Number6, (args) => NotepadsCore.SwitchTo(5)), - new KeyboardCommand(true, false, false, VirtualKey.Number7, (args) => NotepadsCore.SwitchTo(6)), - new KeyboardCommand(true, false, false, VirtualKey.Number8, (args) => NotepadsCore.SwitchTo(7)), - new KeyboardCommand(true, false, false, VirtualKey.Number9, (args) => NotepadsCore.SwitchTo(8)), - new KeyboardCommand(VirtualKey.F11, (args) => { EnterExitFullScreenMode(); }), - new KeyboardCommand(VirtualKey.F12, (args) => { EnterExitCompactOverlayMode(); }), - new KeyboardCommand(VirtualKey.Escape, (args) => { if (RootSplitView.IsPaneOpen) RootSplitView.IsPaneOpen = false; }), - }); - } - - private async Task OpenNewAppInstance() - { - if (!await NotepadsProtocolService.LaunchProtocolAsync(NotepadsOperationProtocol.OpenNewInstance)) - { - Analytics.TrackEvent("FailedToOpenNewAppInstance"); - } - } - - #region Application Life Cycle & Window management - - // Handles external links or cmd args activation before Sets loaded - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - - switch (e.Parameter) - { - case null: - return; - case FileActivatedEventArgs fileActivatedEventArgs: - _appLaunchFiles = fileActivatedEventArgs.Files; - break; - case CommandLineActivatedEventArgs commandLineActivatedEventArgs: - _appLaunchCmdDir = commandLineActivatedEventArgs.Operation.CurrentDirectoryPath; - _appLaunchCmdArgs = commandLineActivatedEventArgs.Operation.Arguments; - break; - case ProtocolActivatedEventArgs protocol: - _appLaunchUri = protocol.Uri; - break; - case XboxGameBarWidget widget: - _widget = widget; - _widgetControl = new XboxGameBarWidgetControl(_widget); - _widget.SettingsClicked += Widget_SettingsClicked; - //_widget.PinnedChanged += Widget_PinnedChanged; - //_widget.FavoritedChanged += Widget_FavoritedChanged; - //_widget.RequestedThemeChanged += Widget_RequestedThemeChanged; - //_widget.VisibleChanged += Widget_VisibleChanged; - //_widget.WindowStateChanged += Widget_WindowStateChanged; +namespace Notepads +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Notepads.Commands; + using Notepads.Controls.Print; + using Notepads.Controls.Settings; + using Notepads.Controls.TextEditor; + using Notepads.Core; + using Notepads.Extensions; + using Notepads.Services; + using Notepads.Settings; + using Notepads.Utilities; + using Windows.ApplicationModel.Activation; + using Windows.ApplicationModel.DataTransfer; + using Windows.ApplicationModel.Resources; + using Windows.Storage; + using Windows.System; + using Windows.UI.ViewManagement; + using Windows.UI.Xaml; + using Windows.UI.Xaml.Controls; + using Windows.UI.Xaml.Controls.Primitives; + using Windows.UI.Xaml.Input; + using Windows.UI.Xaml.Media; + using Windows.UI.Xaml.Media.Animation; + using Windows.UI.Xaml.Navigation; + using Microsoft.AppCenter.Analytics; + using Microsoft.Gaming.XboxGameBar; + using Windows.Graphics.Printing; + + public sealed partial class NotepadsMainPage : Page, INotificationDelegate + { + private IReadOnlyList _appLaunchFiles; + + private string _appLaunchCmdDir; + private string _appLaunchCmdArgs; + private Uri _appLaunchUri; + + private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView(); + + private bool _loaded = false; + private bool _appShouldExitAfterLastEditorClosed = false; + + private const int TitleBarReservedAreaDefaultWidth = 180; + private const int TitleBarReservedAreaCompactOverlayWidth = 100; + + private INotepadsCore _notepadsCore; + + private XboxGameBarWidget _widget; // maintain throughout the lifetime of the notepads widget + private XboxGameBarWidgetControl _widgetControl; + + private INotepadsCore NotepadsCore + { + get + { + if (_notepadsCore == null) + { + _notepadsCore = new NotepadsCore(Sets, new NotepadsExtensionProvider()); + _notepadsCore.StorageItemsDropped += OnStorageItemsDropped; + _notepadsCore.TextEditorLoaded += OnTextEditorLoaded; + _notepadsCore.TextEditorUnloaded += OnTextEditorUnloaded; + _notepadsCore.TextEditorKeyDown += OnTextEditor_KeyDown; + _notepadsCore.TextEditorClosing += OnTextEditorClosing; + _notepadsCore.TextEditorMovedToAnotherAppInstance += OnTextEditorMovedToAnotherAppInstance; + _notepadsCore.TextEditorSelectionChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateLineColumnIndicator(editor); }; + _notepadsCore.TextEditorFontZoomFactorChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateFontZoomIndicator(editor); }; + _notepadsCore.TextEditorEncodingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) UpdateEncodingIndicator(editor.GetEncoding()); }; + _notepadsCore.TextEditorLineEndingChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) { UpdateLineEndingIndicator(editor.GetLineEnding()); UpdateLineColumnIndicator(editor); } }; + _notepadsCore.TextEditorEditorModificationStateChanged += (sender, editor) => { if (NotepadsCore.GetSelectedTextEditor() == editor) SetupStatusBar(editor); }; + _notepadsCore.TextEditorFileModificationStateChanged += (sender, editor) => + { + if (NotepadsCore.GetSelectedTextEditor() == editor) + { + if (editor.FileModificationState == FileModificationState.Modified) + { + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileModifiedOutsideIndicator_ToolTip"), 3500); + } + else if (editor.FileModificationState == FileModificationState.RenamedMovedOrDeleted) + { + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_FileRenamedMovedOrDeletedIndicator_ToolTip"), 3500); + } + UpdateFileModificationStateIndicator(editor); + UpdatePathIndicator(editor); + } + }; + _notepadsCore.TextEditorSaved += (sender, editor) => + { + if (NotepadsCore.GetSelectedTextEditor() == editor) + { + SetupStatusBar(editor); + } + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_NotificationMsg_FileSaved"), 1500); + }; + } + + return _notepadsCore; + } + } + + private readonly ICommandHandler _keyboardCommandHandler; + + private ISessionManager _sessionManager; + + private ISessionManager SessionManager => _sessionManager ?? (_sessionManager = SessionUtility.GetSessionManager(NotepadsCore)); + + private readonly string _defaultNewFileName; + + public NotepadsMainPage() + { + InitializeComponent(); + + _defaultNewFileName = _resourceLoader.GetString("TextEditor_DefaultNewFileName"); + + NotificationCenter.Instance.SetNotificationDelegate(this); + + // Setup theme + ThemeSettingsService.OnBackgroundChanged += ThemeSettingsService_OnBackgroundChanged; + ThemeSettingsService.OnRequestThemeUpdate += ThemeSettingsService_OnRequestThemeUpdate; + ThemeSettingsService.OnRequestAccentColorUpdate += ThemeSettingsService_OnRequestAccentColorUpdate; + ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); + + // Setup custom Title Bar + Window.Current.SetTitleBar(AppTitleBar); + + // Setup status bar + ShowHideStatusBar(EditorSettingsService.ShowStatusBar); + EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); + }); + }; + + // Session backup and restore toggle + EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => + { + if (isSessionBackupAndRestoreEnabled) + { + SessionManager.IsBackupEnabled = true; + SessionManager.StartSessionBackup(startImmediately: true); + } + else + { + SessionManager.IsBackupEnabled = false; + SessionManager.StopSessionBackup(); + await SessionManager.ClearSessionDataAsync(); + } + }); + }; + + // Sharing + Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView().DataRequested += MainPage_DataRequested; + Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += MainPage_CloseRequested; + + Window.Current.VisibilityChanged += WindowVisibilityChangedEventHandler; + Window.Current.SizeChanged += WindowSizeChanged; + + InitControls(); + + // Init shortcuts + _keyboardCommandHandler = GetKeyboardCommandHandler(); + + //Register for printing + if (!PrintManager.IsSupported()) + { + MenuPrintButton.Visibility = Visibility.Collapsed; + MenuPrintAllButton.Visibility = Visibility.Collapsed; + PrintSettingsSeparator.Visibility = Visibility.Collapsed; + } + else + { + PrintArgs.RegisterForPrinting(this); + } + } + + private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedAccentColor(); + }); + } + + private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); + }); + } + + private async void ThemeSettingsService_OnBackgroundChanged(object sender, Brush backgroundBrush) + { + await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + { + RootGrid.Background = backgroundBrush; + }); + } + + private void InitControls() + { + ToolTipService.SetToolTip(ExitCompactOverlayButton, _resourceLoader.GetString("App_ExitCompactOverlayMode_Text")); + RootSplitView.PaneOpening += delegate { SettingsFrame.Navigate(typeof(SettingsPage), null, new SuppressNavigationTransitionInfo()); }; + RootSplitView.PaneClosed += delegate { NotepadsCore.FocusOnSelectedTextEditor(); }; + NewSetButton.Click += delegate { NotepadsCore.OpenNewTextEditor(_defaultNewFileName); }; + MainMenuButton.Click += (sender, args) => FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender); + MenuCreateNewButton.Click += (sender, args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName); + MenuCreateNewWindowButton.Click += async (sender, args) => await OpenNewAppInstance(); + MenuOpenFileButton.Click += async (sender, args) => await OpenNewFiles(); + MenuSaveButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false); + MenuSaveAsButton.Click += async (sender, args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true); + MenuSaveAllButton.Click += async (sender, args) => + { + var success = false; + foreach (var textEditor in NotepadsCore.GetAllTextEditors()) + { + if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) success = true; + } + if (success) + { + await BuildOpenRecentButtonSubItems(); + } + }; + MenuFindButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: false); + MenuReplaceButton.Click += (sender, args) => NotepadsCore.GetSelectedTextEditor()?.ShowFindAndReplaceControl(showReplaceBar: true); + MenuFullScreenButton.Click += (sender, args) => EnterExitFullScreenMode(); + MenuCompactOverlayButton.Click += (sender, args) => EnterExitCompactOverlayMode(); + MenuPrintButton.Click += async (sender, args) => await Print(NotepadsCore.GetSelectedTextEditor()); + MenuPrintAllButton.Click += async (sender, args) => await PrintAll(NotepadsCore.GetAllTextEditors()); + MenuSettingsButton.Click += (sender, args) => RootSplitView.IsPaneOpen = true; + + MainMenuButtonFlyout.Opening += (sender, o) => + { + var selectedTextEditor = NotepadsCore.GetSelectedTextEditor(); + if (selectedTextEditor == null) + { + MenuSaveButton.IsEnabled = false; + MenuSaveAsButton.IsEnabled = false; + MenuFindButton.IsEnabled = false; + MenuReplaceButton.IsEnabled = false; + MenuPrintButton.IsEnabled = false; + MenuPrintAllButton.IsEnabled = false; + } + else if (selectedTextEditor.IsEditorEnabled() == false) + { + MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; + MenuSaveAsButton.IsEnabled = true; + MenuFindButton.IsEnabled = false; + MenuReplaceButton.IsEnabled = false; + } + else + { + MenuSaveButton.IsEnabled = selectedTextEditor.IsModified; + MenuSaveAsButton.IsEnabled = true; + MenuFindButton.IsEnabled = true; + MenuReplaceButton.IsEnabled = true; + + if (PrintManager.IsSupported()) + { + MenuPrintButton.IsEnabled = !string.IsNullOrEmpty(selectedTextEditor.GetText()); + MenuPrintAllButton.IsEnabled = NotepadsCore.HaveNonemptyTextEditor(); + } + } + + MenuFullScreenButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().IsFullScreenMode ? + "App_ExitFullScreenMode_Text" : "App_EnterFullScreenMode_Text"); + MenuCompactOverlayButton.Text = _resourceLoader.GetString(ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay ? + "App_ExitCompactOverlayMode_Text" : "App_EnterCompactOverlayMode_Text"); + MenuSaveAllButton.IsEnabled = NotepadsCore.HaveUnsavedTextEditor(); + }; + + if (!App.IsFirstInstance) + { + MainMenuButton.Foreground = new SolidColorBrush(ThemeSettingsService.AppAccentColor); + MenuSettingsButton.IsEnabled = false; + } + + if (App.IsGameBarWidget) + { + MenuFullScreenSeparator.Visibility = Visibility.Collapsed; + PrintSettingsSeparator.Visibility = Visibility.Collapsed; + + MenuCompactOverlayButton.Visibility = Visibility.Collapsed; + MenuFullScreenButton.Visibility = Visibility.Collapsed; + MenuSettingsButton.Visibility = Visibility.Collapsed; + } + } + + private async Task BuildOpenRecentButtonSubItems() + { + var openRecentSubItem = new MenuFlyoutSubItem + { + Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent/Text"), + Icon = new FontIcon { Glyph = "\xE81C" }, + Name = "MenuOpenRecentlyUsedFileButton", + }; + + var MRUFileList = new HashSet(); + + foreach (var item in await MRUService.Get(top: 10)) + { + if (item is StorageFile file) + { + if (MRUFileList.Contains(file.Path)) + { + // MRU might contains files with same path (User opens a recently used file after renaming it) + // So we need to do the decouple here + continue; + } + var newItem = new MenuFlyoutItem() + { + Text = file.Path + }; + ToolTipService.SetToolTip(newItem, file.Path); + newItem.Click += async (sender, args) => { await OpenFile(file); }; + openRecentSubItem.Items?.Add(newItem); + MRUFileList.Add(file.Path); + } + } + + var oldOpenRecentSubItem = MainMenuButtonFlyout.Items?.FirstOrDefault(i => i.Name == openRecentSubItem.Name); + if (oldOpenRecentSubItem != null) + { + MainMenuButtonFlyout.Items.Remove(oldOpenRecentSubItem); + } + + openRecentSubItem.IsEnabled = false; + if (openRecentSubItem.Items?.Count > 0) + { + openRecentSubItem.Items?.Add(new MenuFlyoutSeparator()); + + var clearRecentlyOpenedSubItem = + new MenuFlyoutItem() + { + Text = _resourceLoader.GetString("MainMenu_Button_Open_Recent_ClearRecentlyOpenedSubItem_Text") + }; + clearRecentlyOpenedSubItem.Click += async (sender, args) => + { + MRUService.ClearAll(); + await BuildOpenRecentButtonSubItems(); + }; + openRecentSubItem.Items?.Add(clearRecentlyOpenedSubItem); + openRecentSubItem.IsEnabled = true; + } + + if (MainMenuButtonFlyout.Items != null) + { + var indexToInsert = MainMenuButtonFlyout.Items.IndexOf(MenuOpenFileButton) + 1; + MainMenuButtonFlyout.Items.Insert(indexToInsert, openRecentSubItem); + } + } + + private KeyboardCommandHandler GetKeyboardCommandHandler() + { + return new KeyboardCommandHandler(new List>() + { + new KeyboardCommand(true, false, false, VirtualKey.W, (args) => NotepadsCore.CloseTextEditor(NotepadsCore.GetSelectedTextEditor())), + new KeyboardCommand(true, false, false, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(true)), + new KeyboardCommand(true, false, true, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(false)), + new KeyboardCommand(true, false, false, VirtualKey.N, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), + new KeyboardCommand(true, false, false, VirtualKey.T, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), + new KeyboardCommand(true, false, false, VirtualKey.O, async (args) => await OpenNewFiles()), + new KeyboardCommand(true, false, false, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false, ignoreUnmodifiedDocument: true)), + new KeyboardCommand(true, false, true, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true)), + new KeyboardCommand(true, false, false, VirtualKey.P, async (args) => await Print(NotepadsCore.GetSelectedTextEditor())), + new KeyboardCommand(true, false, true, VirtualKey.P, async (args) => await PrintAll(NotepadsCore.GetAllTextEditors())), + new KeyboardCommand(true, false, true, VirtualKey.R, (args) => { ReloadFileFromDisk(this, new RoutedEventArgs()); }), + new KeyboardCommand(true, false, true, VirtualKey.N, async (args) => await OpenNewAppInstance()), + new KeyboardCommand(true, false, false, VirtualKey.Number1, (args) => NotepadsCore.SwitchTo(0)), + new KeyboardCommand(true, false, false, VirtualKey.Number2, (args) => NotepadsCore.SwitchTo(1)), + new KeyboardCommand(true, false, false, VirtualKey.Number3, (args) => NotepadsCore.SwitchTo(2)), + new KeyboardCommand(true, false, false, VirtualKey.Number4, (args) => NotepadsCore.SwitchTo(3)), + new KeyboardCommand(true, false, false, VirtualKey.Number5, (args) => NotepadsCore.SwitchTo(4)), + new KeyboardCommand(true, false, false, VirtualKey.Number6, (args) => NotepadsCore.SwitchTo(5)), + new KeyboardCommand(true, false, false, VirtualKey.Number7, (args) => NotepadsCore.SwitchTo(6)), + new KeyboardCommand(true, false, false, VirtualKey.Number8, (args) => NotepadsCore.SwitchTo(7)), + new KeyboardCommand(true, false, false, VirtualKey.Number9, (args) => NotepadsCore.SwitchTo(8)), + new KeyboardCommand(VirtualKey.F11, (args) => { EnterExitFullScreenMode(); }), + new KeyboardCommand(VirtualKey.F12, (args) => { EnterExitCompactOverlayMode(); }), + new KeyboardCommand(VirtualKey.Escape, (args) => { if (RootSplitView.IsPaneOpen) RootSplitView.IsPaneOpen = false; }), + }); + } + + private async Task OpenNewAppInstance() + { + if (!await NotepadsProtocolService.LaunchProtocolAsync(NotepadsOperationProtocol.OpenNewInstance)) + { + Analytics.TrackEvent("FailedToOpenNewAppInstance"); + } + } + + #region Application Life Cycle & Window management + + // Handles external links or cmd args activation before Sets loaded + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + + switch (e.Parameter) + { + case null: + return; + case FileActivatedEventArgs fileActivatedEventArgs: + _appLaunchFiles = fileActivatedEventArgs.Files; + break; + case CommandLineActivatedEventArgs commandLineActivatedEventArgs: + _appLaunchCmdDir = commandLineActivatedEventArgs.Operation.CurrentDirectoryPath; + _appLaunchCmdArgs = commandLineActivatedEventArgs.Operation.Arguments; + break; + case ProtocolActivatedEventArgs protocol: + _appLaunchUri = protocol.Uri; + break; + case XboxGameBarWidget widget: + _widget = widget; + _widgetControl = new XboxGameBarWidgetControl(_widget); + _widget.SettingsClicked += Widget_SettingsClicked; + //_widget.PinnedChanged += Widget_PinnedChanged; + //_widget.FavoritedChanged += Widget_FavoritedChanged; + //_widget.RequestedThemeChanged += Widget_RequestedThemeChanged; + //_widget.VisibleChanged += Widget_VisibleChanged; + //_widget.WindowStateChanged += Widget_WindowStateChanged; //_widget.GameBarDisplayModeChanged += Widget_GameBarDisplayModeChanged; - Window.Current.Closed += WidgetMainWindowClosed; - break; - } - } - - // App should wait for Sets fully loaded before opening files requested by user (by click or from cmd) - // Open files from external links or cmd args on Sets Loaded - private async void Sets_Loaded(object sender, RoutedEventArgs e) - { - int loadedCount = 0; - - if (!_loaded && EditorSettingsService.IsSessionSnapshotEnabled) - { - try - { - loadedCount = await SessionManager.LoadLastSessionAsync(); - } - catch (Exception ex) - { - LoggingService.LogError($"[SessionManager] Failed to LoadLastSessionAsync: {ex}"); - Analytics.TrackEvent("FailedToLoadLastSession", new Dictionary { { "Exception", ex.ToString() } }); - } - } - - if (_appLaunchFiles != null && _appLaunchFiles.Count > 0) - { - loadedCount += await OpenFiles(_appLaunchFiles); - _appLaunchFiles = null; - } - else if (_appLaunchCmdDir != null) - { - var file = await FileSystemUtility.OpenFileFromCommandLine(_appLaunchCmdDir, _appLaunchCmdArgs); - if (file != null && await OpenFile(file)) - { - loadedCount++; - } - _appLaunchCmdDir = null; - _appLaunchCmdArgs = null; - } - else if (_appLaunchUri != null) - { - var operation = NotepadsProtocolService.GetOperationProtocol(_appLaunchUri, out var context); - if (operation == NotepadsOperationProtocol.OpenNewInstance || operation == NotepadsOperationProtocol.Unrecognized) - { - // Do nothing - } - _appLaunchUri = null; - } - - if (!_loaded) - { - if (loadedCount == 0) - { - NotepadsCore.OpenNewTextEditor(_defaultNewFileName); - } - - if (!App.IsFirstInstance) - { - NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("App_ShadowWindowIndicator_Description"), 4000); - } - _loaded = true; - } - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - SessionManager.IsBackupEnabled = true; - SessionManager.StartSessionBackup(); - } - - await BuildOpenRecentButtonSubItems(); - - Window.Current.CoreWindow.Activated -= CoreWindow_Activated; - Window.Current.CoreWindow.Activated += CoreWindow_Activated; - - if (!App.IsGameBarWidget) - { - // An issue with the Game Bar extension model and Windows platform prevents the Notepads process from exiting cleanly - // when more than one CoreWindow has been created, and NotepadsMainPage is the last to close. The common case for this - // is to open Notepads in Game Bar, then open its settings, then close the settings and finally close Notepads. - // This puts the process in a bad state where it will no longer open in Game Bar and the Notepads process is orphaned. - // To work around this do not use the EnteredBackground event when running as a widget. - // Microsoft is tracking this issue as VSO#25735260 - Application.Current.EnteredBackground -= App_EnteredBackground; - Application.Current.EnteredBackground += App_EnteredBackground; - } - } - - private async void App_EnteredBackground(object sender, Windows.ApplicationModel.EnteredBackgroundEventArgs e) - { - var deferral = e.GetDeferral(); - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - await SessionManager.SaveSessionAsync(); - } - - deferral.Complete(); - } - - private void WidgetMainWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) - { + Window.Current.Closed += WidgetMainWindowClosed; + break; + } + } + + // App should wait for Sets fully loaded before opening files requested by user (by click or from cmd) + // Open files from external links or cmd args on Sets Loaded + private async void Sets_Loaded(object sender, RoutedEventArgs e) + { + int loadedCount = 0; + + if (!_loaded && EditorSettingsService.IsSessionSnapshotEnabled) + { + try + { + loadedCount = await SessionManager.LoadLastSessionAsync(); + } + catch (Exception ex) + { + LoggingService.LogError($"[SessionManager] Failed to LoadLastSessionAsync: {ex}"); + Analytics.TrackEvent("FailedToLoadLastSession", new Dictionary { { "Exception", ex.ToString() } }); + } + } + + if (_appLaunchFiles != null && _appLaunchFiles.Count > 0) + { + loadedCount += await OpenFiles(_appLaunchFiles); + _appLaunchFiles = null; + } + else if (_appLaunchCmdDir != null) + { + var file = await FileSystemUtility.OpenFileFromCommandLine(_appLaunchCmdDir, _appLaunchCmdArgs); + if (file != null && await OpenFile(file)) + { + loadedCount++; + } + _appLaunchCmdDir = null; + _appLaunchCmdArgs = null; + } + else if (_appLaunchUri != null) + { + var operation = NotepadsProtocolService.GetOperationProtocol(_appLaunchUri, out var context); + if (operation == NotepadsOperationProtocol.OpenNewInstance || operation == NotepadsOperationProtocol.Unrecognized) + { + // Do nothing + } + _appLaunchUri = null; + } + + if (!_loaded) + { + if (loadedCount == 0) + { + NotepadsCore.OpenNewTextEditor(_defaultNewFileName); + } + + if (!App.IsFirstInstance) + { + NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("App_ShadowWindowIndicator_Description"), 4000); + } + _loaded = true; + } + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + SessionManager.IsBackupEnabled = true; + SessionManager.StartSessionBackup(); + } + + await BuildOpenRecentButtonSubItems(); + + Window.Current.CoreWindow.Activated -= CoreWindow_Activated; + Window.Current.CoreWindow.Activated += CoreWindow_Activated; + + if (!App.IsGameBarWidget) + { + // An issue with the Game Bar extension model and Windows platform prevents the Notepads process from exiting cleanly + // when more than one CoreWindow has been created, and NotepadsMainPage is the last to close. The common case for this + // is to open Notepads in Game Bar, then open its settings, then close the settings and finally close Notepads. + // This puts the process in a bad state where it will no longer open in Game Bar and the Notepads process is orphaned. + // To work around this do not use the EnteredBackground event when running as a widget. + // Microsoft is tracking this issue as VSO#25735260 + Application.Current.EnteredBackground -= App_EnteredBackground; + Application.Current.EnteredBackground += App_EnteredBackground; + } + } + + private async void App_EnteredBackground(object sender, Windows.ApplicationModel.EnteredBackgroundEventArgs e) + { + var deferral = e.GetDeferral(); + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + await SessionManager.SaveSessionAsync(); + } + + deferral.Complete(); + } + + private void WidgetMainWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) + { // Unregister events Window.Current.Closed -= WidgetMainWindowClosed; - _widget.SettingsClicked -= Widget_SettingsClicked; - - // Cleanup game bar objects - _widget = null; - _widgetControl = null; - } - - public void ExecuteProtocol(Uri uri) - { - } - - private void CoreWindow_Activated(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.WindowActivatedEventArgs args) - { - if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated) - { - LoggingService.LogInfo("CoreWindow Deactivated.", consoleOnly: true); - NotepadsCore.GetSelectedTextEditor()?.StopCheckingFileStatus(); - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - SessionManager.StopSessionBackup(); - } - } - else if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.PointerActivated || - args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.CodeActivated) - { - LoggingService.LogInfo("CoreWindow Activated.", consoleOnly: true); - Task.Run(() => ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString())); - NotepadsCore.GetSelectedTextEditor()?.StartCheckingFileStatusPeriodically(); - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - SessionManager.StartSessionBackup(); - } - } - } - - void WindowVisibilityChangedEventHandler(System.Object sender, Windows.UI.Core.VisibilityChangedEventArgs e) - { - LoggingService.LogInfo($"Window Visibility Changed, Visible = {e.Visible}.", consoleOnly: true); - // Perform operations that should take place when the application becomes visible rather than - // when it is prelaunched, such as building a what's new feed - } - - // Content sharing - private void MainPage_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) - { - var textEditor = NotepadsCore.GetSelectedTextEditor(); - if (textEditor == null) return; - - if (NotepadsCore.TryGetSharingContent(textEditor, out var title, out var content)) - { - args.Request.Data.Properties.Title = title; - args.Request.Data.SetText(content); - } - else - { - args.Request.FailWithDisplayText(_resourceLoader.GetString("ContentSharing_FailureDisplayText")); - } - } - - private async void MainPage_CloseRequested(object sender, Windows.UI.Core.Preview.SystemNavigationCloseRequestedPreviewEventArgs e) - { - var deferral = e.GetDeferral(); - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - // Save session before app exit - await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); - deferral.Complete(); - return; - } - - if (!NotepadsCore.HaveUnsavedTextEditor()) - { - deferral.Complete(); - return; - } - - var appCloseSaveReminderDialog = NotepadsDialogFactory.GetAppCloseSaveReminderDialog( - async () => - { - var count = NotepadsCore.GetNumberOfOpenedTextEditors(); - - foreach (var textEditor in NotepadsCore.GetAllTextEditors()) - { - if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) - { - if (count == 1) - { - _appShouldExitAfterLastEditorClosed = true; - } - NotepadsCore.DeleteTextEditor(textEditor); - count--; - } - } - - // Prevent app from closing if there is any tab still opens - if (count > 0) - { - e.Handled = true; - await BuildOpenRecentButtonSubItems(); - } - - deferral.Complete(); - }, - discardAndExitAction: () => - { - deferral.Complete(); - }, - cancelAction: () => - { - e.Handled = true; - deferral.Complete(); - }); - - await DialogManager.OpenDialogAsync(appCloseSaveReminderDialog, awaitPreviousDialog: false); - - if (e.Handled && !appCloseSaveReminderDialog.IsAborted) - { - NotepadsCore.FocusOnSelectedTextEditor(); - } - } - - private void UpdateApplicationTitle(ITextEditor activeTextEditor) - { - if (!App.IsGameBarWidget) - { - ApplicationView.GetForCurrentView().Title = activeTextEditor.EditingFileName ?? activeTextEditor.FileNamePlaceholder; - } - } - - #endregion - - #region XboxGameBar - - private async void Widget_SettingsClicked(XboxGameBarWidget sender, object args) - { - await _widget.ActivateSettingsAsync(); - } - - #endregion - - #region InAppNotification - - public void PostNotification(string message, int duration) - { - if (StatusNotification == null) { FindName("StatusNotification"); } // Lazy loading - var textSize = FontUtility.GetTextSize(StatusNotification.FontFamily, StatusNotification.FontSize, message); - StatusNotification.Width = textSize.Width + 100; // actual width + padding - StatusNotification.Height = textSize.Height + 50; // actual height + padding - StatusNotification.Show(message, duration); - } - - #endregion - - #region NotepadsCore Events - - private void OnTextEditorLoaded(object sender, ITextEditor textEditor) - { - if (NotepadsCore.GetSelectedTextEditor() == textEditor) - { - SetupStatusBar(textEditor); - UpdateApplicationTitle(textEditor); - NotepadsCore.FocusOnSelectedTextEditor(); - } - } - - private void OnTextEditorUnloaded(object sender, ITextEditor textEditor) - { - if (NotepadsCore.GetNumberOfOpenedTextEditors() == 0 && !_appShouldExitAfterLastEditorClosed) - { - NotepadsCore.OpenNewTextEditor(_defaultNewFileName); - } - } - - private async void OnTextEditorMovedToAnotherAppInstance(object sender, ITextEditor textEditor) - { - // Notepads should exit if last tab was dragged to another app instance - if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1) - { - _appShouldExitAfterLastEditorClosed = true; - - NotepadsCore.DeleteTextEditor(textEditor); - - if (EditorSettingsService.IsSessionSnapshotEnabled) - { - await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); - } - - Application.Current.Exit(); - } - else - { - NotepadsCore.DeleteTextEditor(textEditor); - } - } - - private async void OnTextEditorClosing(object sender, ITextEditor textEditor) - { - if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1 && textEditor.IsModified == false && textEditor.EditingFile == null) - { - // Do nothing - // Take no action if user is trying to close the last tab and the last tab is a new empty document - } - else if (!textEditor.IsModified) - { - NotepadsCore.DeleteTextEditor(textEditor); - } - else // Remind user to save uncommitted changes - { - var file = textEditor.EditingFilePath ?? textEditor.FileNamePlaceholder; - - var setCloseSaveReminderDialog = NotepadsDialogFactory.GetSetCloseSaveReminderDialog(file, async () => - { - if (NotepadsCore.GetAllTextEditors().Contains(textEditor) && await Save(textEditor, saveAs: false)) - { - NotepadsCore.DeleteTextEditor(textEditor); - } - }, () => - { - if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) - { - NotepadsCore.DeleteTextEditor(textEditor); - } - }); - - setCloseSaveReminderDialog.Opened += (s, a) => - { - if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) - { - NotepadsCore.SwitchTo(textEditor); - } - }; - - await DialogManager.OpenDialogAsync(setCloseSaveReminderDialog, awaitPreviousDialog: true); - - if (!setCloseSaveReminderDialog.IsAborted) - { - NotepadsCore.FocusOnSelectedTextEditor(); - } - } - } - - private void OnTextEditor_KeyDown(object sender, KeyRoutedEventArgs e) - { - if (!(sender is ITextEditor textEditor)) return; - // ignoring key events coming from inactive text editors - if (NotepadsCore.GetSelectedTextEditor() != textEditor) return; - var result = _keyboardCommandHandler.Handle(e); - if (result.ShouldHandle) - { - e.Handled = true; - } - } - - private async void OnStorageItemsDropped(object sender, IReadOnlyList storageItems) - { - foreach (var storageItem in storageItems) - { - if (storageItem is StorageFile file) - { - await OpenFile(file); - Analytics.TrackEvent("OnStorageFileDropped"); - } - } - } - - #endregion - } + _widget.SettingsClicked -= Widget_SettingsClicked; + + // Cleanup game bar objects + _widget = null; + _widgetControl = null; + } + + public void ExecuteProtocol(Uri uri) + { + } + + private void CoreWindow_Activated(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.WindowActivatedEventArgs args) + { + if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated) + { + LoggingService.LogInfo("CoreWindow Deactivated.", consoleOnly: true); + NotepadsCore.GetSelectedTextEditor()?.StopCheckingFileStatus(); + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + SessionManager.StopSessionBackup(); + } + } + else if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.PointerActivated || + args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.CodeActivated) + { + LoggingService.LogInfo("CoreWindow Activated.", consoleOnly: true); + Task.Run(() => ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString())); + NotepadsCore.GetSelectedTextEditor()?.StartCheckingFileStatusPeriodically(); + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + SessionManager.StartSessionBackup(); + } + } + } + + void WindowVisibilityChangedEventHandler(System.Object sender, Windows.UI.Core.VisibilityChangedEventArgs e) + { + LoggingService.LogInfo($"Window Visibility Changed, Visible = {e.Visible}.", consoleOnly: true); + // Perform operations that should take place when the application becomes visible rather than + // when it is prelaunched, such as building a what's new feed + } + + // Content sharing + private void MainPage_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) + { + var textEditor = NotepadsCore.GetSelectedTextEditor(); + if (textEditor == null) return; + + if (NotepadsCore.TryGetSharingContent(textEditor, out var title, out var content)) + { + args.Request.Data.Properties.Title = title; + args.Request.Data.SetText(content); + } + else + { + args.Request.FailWithDisplayText(_resourceLoader.GetString("ContentSharing_FailureDisplayText")); + } + } + + private async void MainPage_CloseRequested(object sender, Windows.UI.Core.Preview.SystemNavigationCloseRequestedPreviewEventArgs e) + { + var deferral = e.GetDeferral(); + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + // Save session before app exit + await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); + deferral.Complete(); + return; + } + + if (!NotepadsCore.HaveUnsavedTextEditor()) + { + deferral.Complete(); + return; + } + + var appCloseSaveReminderDialog = NotepadsDialogFactory.GetAppCloseSaveReminderDialog( + async () => + { + var count = NotepadsCore.GetNumberOfOpenedTextEditors(); + + foreach (var textEditor in NotepadsCore.GetAllTextEditors()) + { + if (await Save(textEditor, saveAs: false, ignoreUnmodifiedDocument: true, rebuildOpenRecentItems: false)) + { + if (count == 1) + { + _appShouldExitAfterLastEditorClosed = true; + } + NotepadsCore.DeleteTextEditor(textEditor); + count--; + } + } + + // Prevent app from closing if there is any tab still opens + if (count > 0) + { + e.Handled = true; + await BuildOpenRecentButtonSubItems(); + } + + deferral.Complete(); + }, + discardAndExitAction: () => + { + deferral.Complete(); + }, + cancelAction: () => + { + e.Handled = true; + deferral.Complete(); + }); + + await DialogManager.OpenDialogAsync(appCloseSaveReminderDialog, awaitPreviousDialog: false); + + if (e.Handled && !appCloseSaveReminderDialog.IsAborted) + { + NotepadsCore.FocusOnSelectedTextEditor(); + } + } + + private void UpdateApplicationTitle(ITextEditor activeTextEditor) + { + ApplicationView.GetForCurrentView().Title = activeTextEditor.EditingFileName ?? activeTextEditor.FileNamePlaceholder; + } + + #endregion + + #region XboxGameBar + + private async void Widget_SettingsClicked(XboxGameBarWidget sender, object args) + { + await _widget.ActivateSettingsAsync(); + } + + #endregion + + #region InAppNotification + + public void PostNotification(string message, int duration) + { + if (StatusNotification == null) { FindName("StatusNotification"); } // Lazy loading + var textSize = FontUtility.GetTextSize(StatusNotification.FontFamily, StatusNotification.FontSize, message); + StatusNotification.Width = textSize.Width + 100; // actual width + padding + StatusNotification.Height = textSize.Height + 50; // actual height + padding + StatusNotification.Show(message, duration); + } + + #endregion + + #region NotepadsCore Events + + private void OnTextEditorLoaded(object sender, ITextEditor textEditor) + { + if (NotepadsCore.GetSelectedTextEditor() == textEditor) + { + SetupStatusBar(textEditor); + UpdateApplicationTitle(textEditor); + NotepadsCore.FocusOnSelectedTextEditor(); + } + } + + private void OnTextEditorUnloaded(object sender, ITextEditor textEditor) + { + if (NotepadsCore.GetNumberOfOpenedTextEditors() == 0 && !_appShouldExitAfterLastEditorClosed) + { + NotepadsCore.OpenNewTextEditor(_defaultNewFileName); + } + } + + private async void OnTextEditorMovedToAnotherAppInstance(object sender, ITextEditor textEditor) + { + // Notepads should exit if last tab was dragged to another app instance + if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1) + { + _appShouldExitAfterLastEditorClosed = true; + + NotepadsCore.DeleteTextEditor(textEditor); + + if (EditorSettingsService.IsSessionSnapshotEnabled) + { + await SessionManager.SaveSessionAsync(() => { SessionManager.IsBackupEnabled = false; }); + } + + Application.Current.Exit(); + } + else + { + NotepadsCore.DeleteTextEditor(textEditor); + } + } + + private async void OnTextEditorClosing(object sender, ITextEditor textEditor) + { + if (NotepadsCore.GetNumberOfOpenedTextEditors() == 1 && textEditor.IsModified == false && textEditor.EditingFile == null) + { + // Do nothing + // Take no action if user is trying to close the last tab and the last tab is a new empty document + } + else if (!textEditor.IsModified) + { + NotepadsCore.DeleteTextEditor(textEditor); + } + else // Remind user to save uncommitted changes + { + var file = textEditor.EditingFilePath ?? textEditor.FileNamePlaceholder; + + var setCloseSaveReminderDialog = NotepadsDialogFactory.GetSetCloseSaveReminderDialog(file, async () => + { + if (NotepadsCore.GetAllTextEditors().Contains(textEditor) && await Save(textEditor, saveAs: false)) + { + NotepadsCore.DeleteTextEditor(textEditor); + } + }, () => + { + if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) + { + NotepadsCore.DeleteTextEditor(textEditor); + } + }); + + setCloseSaveReminderDialog.Opened += (s, a) => + { + if (NotepadsCore.GetAllTextEditors().Contains(textEditor)) + { + NotepadsCore.SwitchTo(textEditor); + } + }; + + await DialogManager.OpenDialogAsync(setCloseSaveReminderDialog, awaitPreviousDialog: true); + + if (!setCloseSaveReminderDialog.IsAborted) + { + NotepadsCore.FocusOnSelectedTextEditor(); + } + } + } + + private void OnTextEditor_KeyDown(object sender, KeyRoutedEventArgs e) + { + if (!(sender is ITextEditor textEditor)) return; + // ignoring key events coming from inactive text editors + if (NotepadsCore.GetSelectedTextEditor() != textEditor) return; + var result = _keyboardCommandHandler.Handle(e); + if (result.ShouldHandle) + { + e.Handled = true; + } + } + + private async void OnStorageItemsDropped(object sender, IReadOnlyList storageItems) + { + foreach (var storageItem in storageItems) + { + if (storageItem is StorageFile file) + { + await OpenFile(file); + Analytics.TrackEvent("OnStorageFileDropped"); + } + } + } + + #endregion + } } \ No newline at end of file From 278cfb919e4d7dc95a54695a9f7fbd5084d3eb10 Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Tue, 7 Apr 2020 15:46:49 -0700 Subject: [PATCH 22/49] Disable title change in game bar widget mode Disable title change in game bar widget mode --- src/Notepads/NotepadsMainPage.xaml.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index 5cf688d31..2cc7826c3 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -652,7 +652,10 @@ private async void MainPage_CloseRequested(object sender, Windows.UI.Core.Previe private void UpdateApplicationTitle(ITextEditor activeTextEditor) { - ApplicationView.GetForCurrentView().Title = activeTextEditor.EditingFileName ?? activeTextEditor.FileNamePlaceholder; + if (!App.IsGameBarWidget) + { + ApplicationView.GetForCurrentView().Title = activeTextEditor.EditingFileName ?? activeTextEditor.FileNamePlaceholder; + } } #endregion From c698d2aeb10577a2d2508df7d263d6dd43a4beb6 Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Wed, 8 Apr 2020 15:01:12 -0700 Subject: [PATCH 23/49] Code refactoring Code refactoring --- src/Notepads/App.xaml.cs | 6 +- .../Icons/icon.light.targetsize-16.png | Bin .../Icons/icon.light.targetsize-20.png | Bin .../Icons/icon.light.targetsize-24.png | Bin .../Icons/icon.light.targetsize-256.png | Bin .../Icons/icon.light.targetsize-32.png | Bin .../Icons/icon.light.targetsize-44.png | Bin .../GameBar}/Icons/icon.targetsize-16.png | Bin .../GameBar}/Icons/icon.targetsize-20.png | Bin .../GameBar}/Icons/icon.targetsize-24.png | Bin .../GameBar}/Icons/icon.targetsize-256.png | Bin .../GameBar}/Icons/icon.targetsize-32.png | Bin .../GameBar}/Icons/icon.targetsize-44.png | Bin .../FindAndReplaceControl.xaml.cs | 6 +- .../Controls/GoTo/GoToControl.xaml.cs | 9 +- .../Controls/Settings/AdvancedSettings.xaml | 3 +- .../Settings/AdvancedSettings.xaml.cs | 8 +- .../Settings/PersonalizationSettings.xaml | 4 +- .../Settings/PersonalizationSettings.xaml.cs | 10 +-- .../Controls/Settings/SettingsPage.xaml.cs | 35 ++++---- .../Controls/TextEditor/ITextEditor.cs | 2 - .../Controls/TextEditor/TextEditor.xaml.cs | 13 --- .../Controls/TextEditor/TextEditorCore.cs | 84 +++++++++--------- src/Notepads/Core/NotepadsCore.cs | 27 +++--- .../DiffViewer/SideBySideDiffViewer.xaml.cs | 3 +- src/Notepads/Notepads.csproj | 25 +++--- src/Notepads/NotepadsMainPage.ViewModes.cs | 62 +++++++------ src/Notepads/NotepadsMainPage.xaml.cs | 17 ++-- src/Notepads/Package.appxmanifest | 2 +- src/Notepads/Services/ActivationService.cs | 47 +++++----- src/Notepads/Services/ThemeSettingsService.cs | 9 +- 31 files changed, 177 insertions(+), 195 deletions(-) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.light.targetsize-16.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.light.targetsize-20.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.light.targetsize-24.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.light.targetsize-256.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.light.targetsize-32.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.light.targetsize-44.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.targetsize-16.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.targetsize-20.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.targetsize-24.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.targetsize-256.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.targetsize-32.png (100%) rename src/Notepads/{GameBar/Notepads => Assets/GameBar}/Icons/icon.targetsize-44.png (100%) diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index 4c4d9e58c..74f0c2f49 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -8,14 +8,12 @@ using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; using Microsoft.Toolkit.Uwp.Helpers; - using Notepads.Controls.Settings; using Notepads.Services; using Notepads.Settings; using Notepads.Utilities; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Core; - using Windows.System.UserProfile; using Windows.UI; using Windows.UI.ViewManagement; using Windows.UI.Xaml; @@ -128,6 +126,7 @@ protected override async void OnActivated(IActivatedEventArgs args) private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) { bool rootFrameCreated = false; + if (!(Window.Current.Content is Frame rootFrame)) { rootFrame = CreateRootFrame(e); @@ -153,7 +152,8 @@ private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) { "EditorFontFamily", EditorSettingsService.EditorFontFamily }, { "EditorFontSize", EditorSettingsService.EditorFontSize.ToString() }, { "IsSessionSnapshotEnabled", EditorSettingsService.IsSessionSnapshotEnabled.ToString() }, - { "IsShadowWindow", (!IsFirstInstance).ToString() }, + { "IsShadowWindow", (!IsFirstInstance && !IsGameBarWidget).ToString() }, + { "IsGameBarWidget", IsGameBarWidget.ToString() }, { "AlwaysOpenNewWindow", EditorSettingsService.AlwaysOpenNewWindow.ToString() }, { "IsHighlightMisspelledWordsEnabled", EditorSettingsService.IsHighlightMisspelledWordsEnabled.ToString() }, { "IsLineHighlighterEnabled", EditorSettingsService.IsLineHighlighterEnabled.ToString() }, diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-16.png b/src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-16.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-16.png rename to src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-16.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-20.png b/src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-20.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-20.png rename to src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-20.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-24.png b/src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-24.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-24.png rename to src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-24.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-256.png b/src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-256.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-256.png rename to src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-256.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-32.png b/src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-32.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-32.png rename to src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-32.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-44.png b/src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-44.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.light.targetsize-44.png rename to src/Notepads/Assets/GameBar/Icons/icon.light.targetsize-44.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.targetsize-16.png b/src/Notepads/Assets/GameBar/Icons/icon.targetsize-16.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.targetsize-16.png rename to src/Notepads/Assets/GameBar/Icons/icon.targetsize-16.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.targetsize-20.png b/src/Notepads/Assets/GameBar/Icons/icon.targetsize-20.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.targetsize-20.png rename to src/Notepads/Assets/GameBar/Icons/icon.targetsize-20.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.targetsize-24.png b/src/Notepads/Assets/GameBar/Icons/icon.targetsize-24.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.targetsize-24.png rename to src/Notepads/Assets/GameBar/Icons/icon.targetsize-24.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.targetsize-256.png b/src/Notepads/Assets/GameBar/Icons/icon.targetsize-256.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.targetsize-256.png rename to src/Notepads/Assets/GameBar/Icons/icon.targetsize-256.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.targetsize-32.png b/src/Notepads/Assets/GameBar/Icons/icon.targetsize-32.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.targetsize-32.png rename to src/Notepads/Assets/GameBar/Icons/icon.targetsize-32.png diff --git a/src/Notepads/GameBar/Notepads/Icons/icon.targetsize-44.png b/src/Notepads/Assets/GameBar/Icons/icon.targetsize-44.png similarity index 100% rename from src/Notepads/GameBar/Notepads/Icons/icon.targetsize-44.png rename to src/Notepads/Assets/GameBar/Icons/icon.targetsize-44.png diff --git a/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs b/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs index a6d28d344..d61e26c1c 100644 --- a/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs +++ b/src/Notepads/Controls/FindAndReplace/FindAndReplaceControl.xaml.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using Notepads.Commands; using Notepads.Services; + using Notepads.Utilities; using Windows.System; using Windows.UI.Core; using Windows.UI.Xaml; @@ -66,10 +67,7 @@ private void FindAndReplaceControl_Unloaded(object sender, RoutedEventArgs e) private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color e) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => - { - SetSelectionHighlightColor(); - }); + await ThreadUtility.CallOnMainViewUIThreadAsync(SetSelectionHighlightColor); } public double GetHeight(bool showReplaceBar) diff --git a/src/Notepads/Controls/GoTo/GoToControl.xaml.cs b/src/Notepads/Controls/GoTo/GoToControl.xaml.cs index 3cfe6f7cb..0fd8af631 100644 --- a/src/Notepads/Controls/GoTo/GoToControl.xaml.cs +++ b/src/Notepads/Controls/GoTo/GoToControl.xaml.cs @@ -2,9 +2,9 @@ { using System; using Notepads.Services; + using Notepads.Utilities; using Windows.ApplicationModel.Resources; using Windows.System; - using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; @@ -55,10 +55,7 @@ private void GoToControl_Unloaded(object sender, RoutedEventArgs e) private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color e) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => - { - SetSelectionHighlightColor(); - }); + await ThreadUtility.CallOnMainViewUIThreadAsync(SetSelectionHighlightColor); } public double GetHeight() @@ -145,4 +142,4 @@ private void GoToRootGrid_KeyDown(object sender, KeyRoutedEventArgs e) } } } -} +} \ No newline at end of file diff --git a/src/Notepads/Controls/Settings/AdvancedSettings.xaml b/src/Notepads/Controls/Settings/AdvancedSettings.xaml index aecd4fcda..e339961d5 100644 --- a/src/Notepads/Controls/Settings/AdvancedSettings.xaml +++ b/src/Notepads/Controls/Settings/AdvancedSettings.xaml @@ -37,11 +37,12 @@ Margin="0,0,0,0"/> - + - - + + if (App.IsGameBarWidget) { - ThemeSettingsService.SetRequestedAccentColor(); - }); + ThemeSettingsService.OnRequestThemeUpdate -= ThemeSettingsService_OnRequestThemeUpdate; + ThemeSettingsService.OnRequestAccentColorUpdate -= ThemeSettingsService_OnRequestAccentColorUpdate; + } + } + + private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) + { + await ThreadUtility.CallOnMainViewUIThreadAsync(ThemeSettingsService.SetRequestedAccentColor); } private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { ThemeSettingsService.SetRequestedTheme(null, Window.Current.Content, null); }); } - private void SettingsPage_Loaded(object sender, RoutedEventArgs e) - { - ((NavigationViewItem)SettingsNavigationView.MenuItems.First()).IsSelected = true; - } - protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); @@ -66,9 +70,8 @@ protected override void OnNavigatedTo(NavigationEventArgs e) private void WidgetSettingsWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) { - // Unregister events + // Un-registering events Window.Current.Closed -= WidgetSettingsWindowClosed; - // Cleanup game bar objects _widget = null; } diff --git a/src/Notepads/Controls/TextEditor/ITextEditor.cs b/src/Notepads/Controls/TextEditor/ITextEditor.cs index 5efe91ab5..079f1003c 100644 --- a/src/Notepads/Controls/TextEditor/ITextEditor.cs +++ b/src/Notepads/Controls/TextEditor/ITextEditor.cs @@ -6,7 +6,6 @@ using Notepads.Models; using Notepads.Utilities; using Windows.Storage; - using Windows.UI; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; @@ -28,7 +27,6 @@ public interface ITextEditor event EventHandler ChangeReverted; event EventHandler FileSaved; event EventHandler FileReloaded; - event EventHandler AccentColorChanged; Guid Id { get; set; } diff --git a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs index 22aa8b10e..8ac621d4b 100644 --- a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs +++ b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs @@ -13,12 +13,10 @@ using Notepads.Models; using Notepads.Services; using Notepads.Utilities; - using Windows.ApplicationModel.Core; using Windows.ApplicationModel.DataTransfer; using Windows.ApplicationModel.Resources; using Windows.Storage; using Windows.System; - using Windows.UI; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -53,7 +51,6 @@ public sealed partial class TextEditor : ITextEditor public event EventHandler FontZoomFactorChanged; public event EventHandler FileSaved; public event EventHandler FileReloaded; - public event EventHandler AccentColorChanged; public Guid Id { get; set; } @@ -175,7 +172,6 @@ public TextEditor() _keyboardCommandHandler = GetKeyboardCommandHandler(); ThemeSettingsService.OnThemeChanged += ThemeSettingsService_OnThemeChanged; - ThemeSettingsService.OnAccentColorChanged += ThemeSettingsService_OnAccentColorChanged; base.Loaded += TextEditor_Loaded; base.Unloaded += TextEditor_Unloaded; @@ -212,7 +208,6 @@ public void Dispose() } ThemeSettingsService.OnThemeChanged -= ThemeSettingsService_OnThemeChanged; - ThemeSettingsService.OnAccentColorChanged -= ThemeSettingsService_OnAccentColorChanged; Unloaded?.Invoke(this, new RoutedEventArgs()); @@ -275,14 +270,6 @@ private void ThemeSettingsService_OnThemeChanged(object sender, ElementTheme the } } - private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color color) - { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => - { - AccentColorChanged?.Invoke(this, color); - }); - } - public string GetText() { return TextEditorCore.GetText(); diff --git a/src/Notepads/Controls/TextEditor/TextEditorCore.cs b/src/Notepads/Controls/TextEditor/TextEditorCore.cs index 826be56f3..debfac5c3 100644 --- a/src/Notepads/Controls/TextEditor/TextEditorCore.cs +++ b/src/Notepads/Controls/TextEditor/TextEditorCore.cs @@ -166,48 +166,6 @@ public void Dispose() _contentLinesCache = null; } - private async void EditorSettingsService_OnFontFamilyChanged(object sender, string fontFamily) - { - await ThreadUtility.CallOnMainViewUIThreadAsync(() => - { - FontFamily = new FontFamily(fontFamily); - SetDefaultTabStopAndLineSpacing(FontFamily, FontSize); - }); - } - - private async void EditorSettingsService_OnFontSizeChanged(object sender, int fontSize) - { - await ThreadUtility.CallOnMainViewUIThreadAsync(() => - { - FontSize = fontSize; - }); - } - - private async void EditorSettingsService_OnDefaultTextWrappingChanged(object sender, TextWrapping textWrapping) - { - await ThreadUtility.CallOnMainViewUIThreadAsync(() => - { - TextWrapping = textWrapping; - }); - } - - private async void EditorSettingsService_OnHighlightMisspelledWordsChanged(object sender, bool isSpellCheckEnabled) - { - await ThreadUtility.CallOnMainViewUIThreadAsync(() => - { - IsSpellCheckEnabled = isSpellCheckEnabled; - }); - } - - private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color color) - { - await ThreadUtility.CallOnMainViewUIThreadAsync(() => - { - SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; - SelectionHighlightColorWhenNotFocused = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; - }); - } - private KeyboardCommandHandler GetKeyboardCommandHandler() { var swallowedKeys = new List() @@ -264,6 +222,48 @@ private ICommandHandler GetMouseCommandHandler() }, this); } + private async void EditorSettingsService_OnFontFamilyChanged(object sender, string fontFamily) + { + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + FontFamily = new FontFamily(fontFamily); + SetDefaultTabStopAndLineSpacing(FontFamily, FontSize); + }); + } + + private async void EditorSettingsService_OnFontSizeChanged(object sender, int fontSize) + { + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + FontSize = fontSize; + }); + } + + private async void EditorSettingsService_OnDefaultTextWrappingChanged(object sender, TextWrapping textWrapping) + { + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + TextWrapping = textWrapping; + }); + } + + private async void EditorSettingsService_OnHighlightMisspelledWordsChanged(object sender, bool isSpellCheckEnabled) + { + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + IsSpellCheckEnabled = isSpellCheckEnabled; + }); + } + + private async void ThemeSettingsService_OnAccentColorChanged(object sender, Windows.UI.Color color) + { + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + SelectionHighlightColorWhenNotFocused = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + }); + } + private void OnCoreWindowActivated(CoreWindow sender, WindowActivatedEventArgs args) { if (args.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.CodeActivated || diff --git a/src/Notepads/Core/NotepadsCore.cs b/src/Notepads/Core/NotepadsCore.cs index eca5615cd..e1bd7dbb9 100644 --- a/src/Notepads/Core/NotepadsCore.cs +++ b/src/Notepads/Core/NotepadsCore.cs @@ -75,6 +75,21 @@ public NotepadsCore(SetsView sets, Sets.DragItemsCompleted += Sets_DragItemsCompleted; _extensionProvider = extensionProvider; + + ThemeSettingsService.OnAccentColorChanged += ThemeSettingsService_OnAccentColorChanged; + } + + private async void ThemeSettingsService_OnAccentColorChanged(object sender, Color e) + { + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + if (Sets.Items == null) return; + foreach (SetsViewItem item in Sets.Items) + { + item.Icon.Foreground = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + item.SelectionIndicatorForeground = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; + } + }); } public void OpenNewTextEditor(string fileNamePlaceholder) @@ -122,8 +137,6 @@ public void OpenTextEditor(ITextEditor textEditor, int atIndex = -1) Sets.ScrollToLastSet(); } } - - textEditor.AccentColorChanged += TextEditor_AccentColorChanged; } public void OpenTextEditors(ITextEditor[] editors, Guid? selectedEditorId = null) @@ -530,16 +543,6 @@ private void TextEditor_OnLineEndingChanged(object sender, EventArgs e) TextEditorLineEndingChanged?.Invoke(this, textEditor); } - private void TextEditor_AccentColorChanged(object sender, Color e) - { - if (Sets.Items == null) return; - foreach (SetsViewItem item in Sets.Items) - { - item.Icon.Foreground = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; - item.SelectionIndicatorForeground = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; - } - } - #region DragAndDrop private async void Sets_DragOver(object sender, DragEventArgs args) diff --git a/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs b/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs index fb8276c0c..8845d916b 100644 --- a/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs +++ b/src/Notepads/Extensions/DiffViewer/SideBySideDiffViewer.xaml.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Notepads.Commands; using Notepads.Services; + using Notepads.Utilities; using Windows.System; using Windows.UI; using Windows.UI.Core; @@ -67,7 +68,7 @@ private void SideBySideDiffViewer_Loaded(object sender, RoutedEventArgs e) private async void ThemeSettingsService_OnAccentColorChanged(object sender, Color color) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { LeftBox.SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; RightBox.SelectionHighlightColor = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; diff --git a/src/Notepads/Notepads.csproj b/src/Notepads/Notepads.csproj index 435c56069..527117ab1 100644 --- a/src/Notepads/Notepads.csproj +++ b/src/Notepads/Notepads.csproj @@ -35,6 +35,7 @@ false prompt true + true bin\x86\Release\ @@ -409,18 +410,6 @@ - - - - - - - - - - - - @@ -468,6 +457,18 @@ + + + + + + + + + + + + diff --git a/src/Notepads/NotepadsMainPage.ViewModes.cs b/src/Notepads/NotepadsMainPage.ViewModes.cs index a17e6acc3..52ea9fdaa 100644 --- a/src/Notepads/NotepadsMainPage.ViewModes.cs +++ b/src/Notepads/NotepadsMainPage.ViewModes.cs @@ -34,53 +34,51 @@ private void WindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedE private async void EnterExitCompactOverlayMode() { - if (!App.IsGameBarWidget) + if (App.IsGameBarWidget) return; + + if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default) { - if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default) + var modeSwitched = await ApplicationView.GetForCurrentView() + .TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay); + if (!modeSwitched) { - var modeSwitched = await ApplicationView.GetForCurrentView() - .TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay); - if (!modeSwitched) - { - LoggingService.LogError("Failed to enter CompactOverlay view mode."); - Analytics.TrackEvent("FailedToEnterCompactOverlayViewMode"); - } + LoggingService.LogError("Failed to enter CompactOverlay view mode."); + Analytics.TrackEvent("FailedToEnterCompactOverlayViewMode"); } - else if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay) + } + else if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay) + { + var modeSwitched = await ApplicationView.GetForCurrentView() + .TryEnterViewModeAsync(ApplicationViewMode.Default); + if (!modeSwitched) { - var modeSwitched = await ApplicationView.GetForCurrentView() - .TryEnterViewModeAsync(ApplicationViewMode.Default); - if (!modeSwitched) - { - LoggingService.LogError("Failed to enter Default view mode."); - Analytics.TrackEvent("FailedToEnterDefaultViewMode"); - } + LoggingService.LogError("Failed to enter Default view mode."); + Analytics.TrackEvent("FailedToEnterDefaultViewMode"); } } } private void EnterExitFullScreenMode() { - if(!App.IsGameBarWidget) + if(App.IsGameBarWidget) return; + + if (ApplicationView.GetForCurrentView().IsFullScreenMode) + { + LoggingService.LogInfo("Existing full screen view mode.", consoleOnly: true); + ApplicationView.GetForCurrentView().ExitFullScreenMode(); + } + else { - if (ApplicationView.GetForCurrentView().IsFullScreenMode) + if (ApplicationView.GetForCurrentView().TryEnterFullScreenMode()) { - LoggingService.LogInfo("Existing full screen view mode.", consoleOnly: true); - ApplicationView.GetForCurrentView().ExitFullScreenMode(); + LoggingService.LogInfo("Entered full screen view mode.", consoleOnly: true); + NotificationCenter.Instance.PostNotification( + _resourceLoader.GetString("TextEditor_NotificationMsg_ExitFullScreenHint"), 3000); } else { - if (ApplicationView.GetForCurrentView().TryEnterFullScreenMode()) - { - LoggingService.LogInfo("Entered full screen view mode.", consoleOnly: true); - NotificationCenter.Instance.PostNotification( - _resourceLoader.GetString("TextEditor_NotificationMsg_ExitFullScreenHint"), 3000); - } - else - { - LoggingService.LogError("Failed to enter full screen view mode."); - Analytics.TrackEvent("FailedToEnterFullScreenViewMode"); - } + LoggingService.LogError("Failed to enter full screen view mode."); + Analytics.TrackEvent("FailedToEnterFullScreenViewMode"); } } } diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index 2cc7826c3..9b44f5324 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -48,7 +48,7 @@ public sealed partial class NotepadsMainPage : Page, INotificationDelegate private INotepadsCore _notepadsCore; - private XboxGameBarWidget _widget; // maintain throughout the lifetime of the notepads widget + private XboxGameBarWidget _widget; // maintain throughout the lifetime of the notepads game bar widget private XboxGameBarWidgetControl _widgetControl; private INotepadsCore NotepadsCore @@ -128,7 +128,7 @@ public NotepadsMainPage() ShowHideStatusBar(EditorSettingsService.ShowStatusBar); EditorSettingsService.OnStatusBarVisibilityChanged += async (sender, visibility) => { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) ShowHideStatusBar(visibility); }); @@ -137,7 +137,7 @@ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => // Session backup and restore toggle EditorSettingsService.OnSessionBackupAndRestoreOptionChanged += async (sender, isSessionBackupAndRestoreEnabled) => { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => + await ThreadUtility.CallOnMainViewUIThreadAsync(async () => { if (isSessionBackupAndRestoreEnabled) { @@ -180,15 +180,12 @@ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async ( private async void ThemeSettingsService_OnRequestAccentColorUpdate(object sender, EventArgs e) { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => - { - ThemeSettingsService.SetRequestedAccentColor(); - }); + await ThreadUtility.CallOnMainViewUIThreadAsync(ThemeSettingsService.SetRequestedAccentColor); } private async void ThemeSettingsService_OnRequestThemeUpdate(object sender, EventArgs e) { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { ThemeSettingsService.SetRequestedTheme(RootGrid, Window.Current.Content, ApplicationView.GetForCurrentView().TitleBar); }); @@ -196,7 +193,7 @@ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => private async void ThemeSettingsService_OnBackgroundChanged(object sender, Brush backgroundBrush) { - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { RootGrid.Background = backgroundBrush; }); @@ -526,7 +523,7 @@ private async void App_EnteredBackground(object sender, Windows.ApplicationModel private void WidgetMainWindowClosed(object sender, Windows.UI.Core.CoreWindowEventArgs e) { - // Unregister events + // Un-registering events Window.Current.Closed -= WidgetMainWindowClosed; _widget.SettingsClicked -= Widget_SettingsClicked; diff --git a/src/Notepads/Package.appxmanifest b/src/Notepads/Package.appxmanifest index 29eadd00d..31f6371c8 100644 --- a/src/Notepads/Package.appxmanifest +++ b/src/Notepads/Package.appxmanifest @@ -632,6 +632,6 @@ - + diff --git a/src/Notepads/Services/ActivationService.cs b/src/Notepads/Services/ActivationService.cs index 95ebfd108..ac9846697 100644 --- a/src/Notepads/Services/ActivationService.cs +++ b/src/Notepads/Services/ActivationService.cs @@ -41,31 +41,6 @@ public static async Task ActivateAsync(Frame rootFrame, IActivatedEventArgs e) } } - public static void GameBarActivated(Frame rootFrame, XboxGameBarWidgetActivatedEventArgs xboxGameBarWidgetActivatedEventArgs) - { - LoggingService.LogInfo($"[XboxGameBarWidgetActivated] AppExtensionId: {xboxGameBarWidgetActivatedEventArgs.AppExtensionId}"); - - if (xboxGameBarWidgetActivatedEventArgs != null) - { - if (xboxGameBarWidgetActivatedEventArgs.IsLaunchActivation) - { - var xboxGameBarWidget = new XboxGameBarWidget( - xboxGameBarWidgetActivatedEventArgs, - Window.Current.CoreWindow, - rootFrame); - - if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "Notepads") - { - rootFrame.Navigate(typeof(NotepadsMainPage), xboxGameBarWidget); - } - else if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "NotepadsSettings") - { - rootFrame.Navigate(typeof(SettingsPage), xboxGameBarWidget); - } - } - } - } - private static void ProtocolActivated(Frame rootFrame, ProtocolActivatedEventArgs protocolActivatedEventArgs) { LoggingService.LogInfo($"[ProtocolActivated] Protocol: {protocolActivatedEventArgs.Uri}"); @@ -127,5 +102,27 @@ private static async Task CommandActivated(Frame rootFrame, CommandLineActivated } } } + + public static void GameBarActivated(Frame rootFrame, XboxGameBarWidgetActivatedEventArgs xboxGameBarWidgetActivatedEventArgs) + { + LoggingService.LogInfo($"[XboxGameBarWidgetActivated] AppExtensionId: {xboxGameBarWidgetActivatedEventArgs.AppExtensionId}"); + + if (xboxGameBarWidgetActivatedEventArgs.IsLaunchActivation) + { + var xboxGameBarWidget = new XboxGameBarWidget( + xboxGameBarWidgetActivatedEventArgs, + Window.Current.CoreWindow, + rootFrame); + + if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "Notepads") + { + rootFrame.Navigate(typeof(NotepadsMainPage), xboxGameBarWidget); + } + else if (xboxGameBarWidgetActivatedEventArgs.AppExtensionId == "NotepadsSettings") + { + rootFrame.Navigate(typeof(SettingsPage), xboxGameBarWidget); + } + } + } } } \ No newline at end of file diff --git a/src/Notepads/Services/ThemeSettingsService.cs b/src/Notepads/Services/ThemeSettingsService.cs index c71ed7116..57136ca35 100644 --- a/src/Notepads/Services/ThemeSettingsService.cs +++ b/src/Notepads/Services/ThemeSettingsService.cs @@ -16,13 +16,12 @@ public static class ThemeSettingsService { - public static event EventHandler OnThemeChanged; public static event EventHandler OnRequestThemeUpdate; + public static event EventHandler OnRequestAccentColorUpdate; + public static event EventHandler OnThemeChanged; public static event EventHandler OnBackgroundChanged; - public static event EventHandler OnAccentColorChanged; - public static event EventHandler OnRequestAccentColorUpdate; public static ElementTheme ThemeMode { get; set; } @@ -214,7 +213,6 @@ private static void ThemeListener_ThemeChanged(ThemeListener sender) SetTheme(sender.CurrentTheme); } }); - } public static void SetTheme(ApplicationTheme theme) @@ -249,7 +247,8 @@ public static void SetRequestedTheme(Panel backgroundPanel, UIElement currentCon } // Set ContentDialog background dimming color - ((SolidColorBrush)Application.Current.Resources["SystemControlPageBackgroundMediumAltMediumBrush"]).Color = ThemeMode == ElementTheme.Dark ? Color.FromArgb(153, 0, 0, 0) : Color.FromArgb(153, 255, 255, 255); + ((SolidColorBrush)Application.Current.Resources["SystemControlPageBackgroundMediumAltMediumBrush"]).Color = + ThemeMode == ElementTheme.Dark ? Color.FromArgb(153, 0, 0, 0) : Color.FromArgb(153, 255, 255, 255); // Set accent color UpdateSystemAccentColorAndBrushes(AppAccentColor); From 7768a821f9dd30843846507ea08962b7f40095a0 Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Wed, 8 Apr 2020 15:18:07 -0700 Subject: [PATCH 24/49] More code refactorings More code refactorings --- .../Controls/TextEditor/TextEditor.xaml.cs | 19 ++++++----- src/Notepads/Services/ThemeSettingsService.cs | 34 +++++++++---------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs index 8ac621d4b..bd2f04230 100644 --- a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs +++ b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs @@ -264,9 +264,10 @@ private void ThemeSettingsService_OnThemeChanged(object sender, ElementTheme the if (Mode == TextEditorMode.DiffPreview) { SideBySideDiffViewer.RenderDiff(LastSavedSnapshot.Content, TextEditorCore.GetText()); - Task.Factory.StartNew( - () => Dispatcher.RunAsync(CoreDispatcherPriority.Low, - () => SideBySideDiffViewer.Focus())); + Task.Factory.StartNew(async () => + { + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { SideBySideDiffViewer.Focus(); }); + }); } } @@ -1052,7 +1053,7 @@ private void DrawLineHighlighter() private async void LineHighlighter_OnViewStateChanged(object sender, bool enabled) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { if (enabled) { @@ -1068,7 +1069,7 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => private async void LineHighlighter_OnSelectionChanged(object sender, RoutedEventArgs e) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); }); @@ -1076,7 +1077,7 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => private async void LineHighlighter_OnTextWrappingChanged(object sender, TextWrapping e) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { if (EditorSettingsService.IsLineHighlighterEnabled) { @@ -1089,7 +1090,7 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => private async void LineHighlighter_OnFontSizeChanged(object sender, double e) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); }); @@ -1097,7 +1098,7 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => private async void LineHighlighter_OnSizeChanged(object sender, SizeChangedEventArgs e) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); }); @@ -1105,7 +1106,7 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => private async void LineHighlighter_OnScrollViewerViewChanging(object sender, ScrollViewerViewChangingEventArgs e) { - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + await ThreadUtility.CallOnMainViewUIThreadAsync(() => { if (EditorSettingsService.IsLineHighlighterEnabled) DrawLineHighlighter(); }); diff --git a/src/Notepads/Services/ThemeSettingsService.cs b/src/Notepads/Services/ThemeSettingsService.cs index 57136ca35..bac0e788c 100644 --- a/src/Notepads/Services/ThemeSettingsService.cs +++ b/src/Notepads/Services/ThemeSettingsService.cs @@ -6,9 +6,7 @@ using Notepads.Brushes; using Notepads.Settings; using Notepads.Utilities; - using Windows.ApplicationModel.Core; using Windows.UI; - using Windows.UI.Core; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -153,15 +151,15 @@ private static void InitializeCustomAccentColor() } } - private static void UiSettings_ColorValuesChanged(UISettings sender, object args) + private static async void UiSettings_ColorValuesChanged(UISettings sender, object args) { - _ = CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => - { - if (UseWindowsAccentColor) - { - AppAccentColor = sender.GetColorValue(UIColorType.Accent); - } - }); + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + if (UseWindowsAccentColor) + { + AppAccentColor = sender.GetColorValue(UIColorType.Accent); + } + }); } private static void InitializeAppBackgroundPanelTintOpacity() @@ -204,15 +202,15 @@ private static void InitializeThemeMode() } } - private static void ThemeListener_ThemeChanged(ThemeListener sender) + private static async void ThemeListener_ThemeChanged(ThemeListener sender) { - _ = CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => - { - if (UseWindowsTheme) - { - SetTheme(sender.CurrentTheme); - } - }); + await ThreadUtility.CallOnMainViewUIThreadAsync(() => + { + if (UseWindowsTheme) + { + SetTheme(sender.CurrentTheme); + } + }); } public static void SetTheme(ApplicationTheme theme) From ceb4fad0520bce0f3ef47bd503bab131602b3a5e Mon Sep 17 00:00:00 2001 From: Jiaqi Liu Date: Wed, 8 Apr 2020 17:50:19 -0700 Subject: [PATCH 25/49] Fix icon path for game bar app Fix icon path for game bar app --- src/Notepads/NotepadsMainPage.IO.cs | 2 ++ src/Notepads/NotepadsMainPage.xaml | 4 ++-- src/Notepads/NotepadsMainPage.xaml.cs | 18 ++++++++++++++---- src/Notepads/Package.appxmanifest | 8 ++++---- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/Notepads/NotepadsMainPage.IO.cs b/src/Notepads/NotepadsMainPage.IO.cs index 506bde5f1..131e8ad36 100644 --- a/src/Notepads/NotepadsMainPage.IO.cs +++ b/src/Notepads/NotepadsMainPage.IO.cs @@ -156,12 +156,14 @@ private async Task Save(ITextEditor textEditor, bool saveAs, bool ignoreUn public async Task Print(ITextEditor textEditor) { + if (App.IsGameBarWidget) return; if (textEditor == null) return; await PrintAll(new[] { textEditor }); } public async Task PrintAll(ITextEditor[] textEditors) { + if (App.IsGameBarWidget) return; if (textEditors == null || textEditors.Length == 0) return; // Initialize print content diff --git a/src/Notepads/NotepadsMainPage.xaml b/src/Notepads/NotepadsMainPage.xaml index 1d54dc820..cbc6c1114 100644 --- a/src/Notepads/NotepadsMainPage.xaml +++ b/src/Notepads/NotepadsMainPage.xaml @@ -152,7 +152,7 @@ - + @@ -166,7 +166,7 @@ - +