diff --git a/src/Notepads/App.xaml.cs b/src/Notepads/App.xaml.cs index 34a1478c7..83425a158 100644 --- a/src/Notepads/App.xaml.cs +++ b/src/Notepads/App.xaml.cs @@ -169,6 +169,7 @@ private async System.Threading.Tasks.Task ActivateAsync(IActivatedEventArgs e) }; LoggingService.LogInfo($"AppLaunchSettings: {string.Join(";", appLaunchSettings.Select(x => x.Key + "=" + x.Value).ToArray())}"); + Analytics.TrackEvent("AppLaunch_Settings", appLaunchSettings); await ActivationService.ActivateAsync(rootFrame, e); diff --git a/src/Notepads/Controls/TextEditor/ITextEditor.cs b/src/Notepads/Controls/TextEditor/ITextEditor.cs index 1c18fe12f..b53572237 100644 --- a/src/Notepads/Controls/TextEditor/ITextEditor.cs +++ b/src/Notepads/Controls/TextEditor/ITextEditor.cs @@ -30,6 +30,8 @@ public interface ITextEditor Encoding RequestedEncoding { get; } + string FileNamePlaceholder { get; set; } + string EditingFileName { get; } string EditingFilePath { get; } diff --git a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs index 239c20d39..169ffe366 100644 --- a/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs +++ b/src/Notepads/Controls/TextEditor/TextEditor.xaml.cs @@ -60,6 +60,8 @@ public sealed partial class TextEditor : UserControl, ITextEditor public event EventHandler FileReloaded; + public string FileNamePlaceholder { get; set; } = string.Empty; + public FileType FileType { get; private set; } public TextFile LastSavedSnapshot { get; private set; } @@ -198,6 +200,7 @@ public TextEditorStateMetaData GetTextEditorStateMetaData() var metaData = new TextEditorStateMetaData { + FileNamePlaceholder = FileNamePlaceholder, LastSavedEncoding = EncodingUtility.GetEncodingName(LastSavedSnapshot.Encoding), LastSavedLineEnding = LineEndingUtility.GetLineEndingName(LastSavedSnapshot.LineEnding), DateModifiedFileTime = LastSavedSnapshot.DateModifiedFileTime, diff --git a/src/Notepads/Controls/TextEditor/TextEditorStateMetaData.cs b/src/Notepads/Controls/TextEditor/TextEditorStateMetaData.cs index e57c915ff..8fb105955 100644 --- a/src/Notepads/Controls/TextEditor/TextEditorStateMetaData.cs +++ b/src/Notepads/Controls/TextEditor/TextEditorStateMetaData.cs @@ -2,6 +2,8 @@ { public class TextEditorStateMetaData { + public string FileNamePlaceholder { get; set; } + public string LastSavedEncoding { get; set; } public string LastSavedLineEnding { get; set; } diff --git a/src/Notepads/Core/INotepadsCore.cs b/src/Notepads/Core/INotepadsCore.cs index 39aa40c50..2ded06333 100644 --- a/src/Notepads/Core/INotepadsCore.cs +++ b/src/Notepads/Core/INotepadsCore.cs @@ -46,9 +46,10 @@ ITextEditor CreateTextEditor( Guid id, TextFile textFile, StorageFile editingFile, - bool isModified); + string fileNamePlaceHolder, + bool isModified = false); - void OpenNewTextEditor(); + void OpenNewTextEditor(string fileNamePlaceholder); void OpenTextEditor(ITextEditor editor, int atIndex = -1); diff --git a/src/Notepads/Core/NotepadsCore.cs b/src/Notepads/Core/NotepadsCore.cs index a912d9e79..4cbd0d48c 100644 --- a/src/Notepads/Core/NotepadsCore.cs +++ b/src/Notepads/Core/NotepadsCore.cs @@ -27,8 +27,6 @@ public class NotepadsCore : INotepadsCore { public SetsView Sets; - public readonly string DefaultNewFileName; - public event EventHandler TextEditorLoaded; public event EventHandler TextEditorUnloaded; @@ -70,7 +68,6 @@ public class NotepadsCore : INotepadsCore private const string NotepadsTextEditorEditingFilePath = "NotepadsTextEditorEditingFilePath"; public NotepadsCore(SetsView sets, - string defaultNewFileName, INotepadsExtensionProvider extensionProvider) { Sets = sets; @@ -85,16 +82,19 @@ public NotepadsCore(SetsView sets, Sets.DragItemsCompleted += Sets_DragItemsCompleted; _extensionProvider = extensionProvider; - DefaultNewFileName = defaultNewFileName; ThemeSettingsService.OnAccentColorChanged += OnAppAccentColorChanged; } - public void OpenNewTextEditor() + public void OpenNewTextEditor(string fileNamePlaceholder) { var textFile = new TextFile(string.Empty, EditorSettingsService.EditorDefaultEncoding, EditorSettingsService.EditorDefaultLineEnding); - var newEditor = CreateTextEditor(Guid.NewGuid(), textFile, null); + var newEditor = CreateTextEditor( + Guid.NewGuid(), + textFile, + null, + fileNamePlaceholder); OpenTextEditor(newEditor); } @@ -160,18 +160,21 @@ public async Task CreateTextEditor( bool ignoreFileSizeLimit = false) { var textFile = await FileSystemUtility.ReadFile(file, ignoreFileSizeLimit); - return CreateTextEditor(id, textFile, file); + return CreateTextEditor(id, textFile, file, file.Name); } - public ITextEditor CreateTextEditor(Guid id, + public ITextEditor CreateTextEditor( + Guid id, TextFile textFile, StorageFile editingFile, + string fileNamePlaceholder, bool isModified = false) { TextEditor textEditor = new TextEditor { Id = id, - ExtensionProvider = _extensionProvider + ExtensionProvider = _extensionProvider, + FileNamePlaceholder = fileNamePlaceholder }; textEditor.Init(textFile, editingFile, isModified: isModified); @@ -216,7 +219,7 @@ public int GetNumberOfOpenedTextEditors() public bool TryGetSharingContent(ITextEditor textEditor, out string title, out string content) { - title = textEditor.EditingFileName ?? DefaultNewFileName; + title = textEditor.EditingFileName ?? textEditor.FileNamePlaceholder; content = textEditor.GetContentForSharing(); return !string.IsNullOrEmpty(content); } @@ -348,7 +351,7 @@ private SetsViewItem CreateTextEditorSetsViewItem(ITextEditor textEditor) { var textEditorSetsViewItem = new SetsViewItem { - Header = textEditor.EditingFileName ?? DefaultNewFileName, + Header = textEditor.EditingFileName ?? textEditor.FileNamePlaceholder, Content = textEditor, SelectionIndicatorForeground = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush, @@ -696,7 +699,7 @@ private async void Sets_Drop(object sender, DragEventArgs args) LineEndingUtility.GetLineEndingByName(metaData.LastSavedLineEnding), metaData.DateModifiedFileTime); - var newEditor = CreateTextEditor(Guid.NewGuid(), textFile, editingFile, metaData.IsModified); + var newEditor = CreateTextEditor(Guid.NewGuid(), textFile, editingFile, metaData.FileNamePlaceholder, metaData.IsModified); OpenTextEditor(newEditor, atIndex); newEditor.ResetEditorState(metaData, pendingText); diff --git a/src/Notepads/Core/SessionManager.cs b/src/Notepads/Core/SessionManager.cs index 15a66e1f9..11db78d02 100644 --- a/src/Notepads/Core/SessionManager.cs +++ b/src/Notepads/Core/SessionManager.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; + using Microsoft.AppCenter.Analytics; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Notepads.Controls.TextEditor; @@ -82,6 +83,7 @@ public async Task LoadLastSessionAsync() catch (Exception ex) { LoggingService.LogError($"[SessionManager] Failed to load last session metadata: {ex.Message}"); + Analytics.TrackEvent("SessionManager_FailedToLoadLastSession", new Dictionary() {{ "Exception", ex.Message }}); await ClearSessionDataAsync(); return 0; } @@ -99,6 +101,7 @@ public async Task LoadLastSessionAsync() catch (Exception ex) { LoggingService.LogError($"[SessionManager] Failed to recover TextEditor: {ex.Message}"); + Analytics.TrackEvent("SessionManager_FailedToRecoverTextEditor", new Dictionary() {{ "Exception", ex.Message }}); continue; } @@ -192,6 +195,7 @@ public async Task SaveSessionAsync(Action actionAfterSaving = null) catch (Exception ex) { LoggingService.LogError($"[SessionManager] Failed to save session metadata: {ex.Message}"); + Analytics.TrackEvent("SessionManager_FailedToSaveSessionMetaData", new Dictionary() {{ "Exception", ex.Message }}); actionAfterSaving?.Invoke(); _semaphoreSlim.Release(); return; // Failed to save the session - do not proceed to delete backup files @@ -225,7 +229,11 @@ private async Task BuildTextEditorSessionData(ITextEdit { // Add the opened file to FutureAccessList so we can access it next launch var futureAccessToken = ToToken(textEditor.Id); - await FileSystemUtility.TryAddOrReplaceTokenInFutureAccessList(futureAccessToken, textEditor.EditingFile); + if (!await FileSystemUtility.TryAddOrReplaceTokenInFutureAccessList(futureAccessToken, textEditor.EditingFile)) + { + Analytics.TrackEvent("SessionManager_FailedToAddTokenInFutureAccessList", + new Dictionary() {{ "ItemCount", FileSystemUtility.GetFutureAccessListItemCount().ToString() }}); + } textEditorData.EditingFileFutureAccessToken = futureAccessToken; textEditorData.EditingFileName = textEditor.EditingFileName; textEditorData.EditingFilePath = textEditor.EditingFilePath; @@ -323,6 +331,7 @@ public async Task ClearSessionDataAsync() catch (Exception ex) { LoggingService.LogError($"[SessionManager] Failed to delete session meta data: {ex.Message}"); + Analytics.TrackEvent("SessionManager_FailedToDeleteSessionMetaData", new Dictionary() {{ "Exception", ex.Message }}); } } @@ -388,6 +397,7 @@ private async Task RecoverTextEditorAsync(TextEditorSessionDataV1 e editorSessionData.Id, textFile, editingFile, + editorSessionData.StateMetaData.FileNamePlaceholder, editorSessionData.StateMetaData.IsModified); if (pendingFile != null) @@ -469,6 +479,7 @@ private void DeleteOrphanedTokensInFutureAccessList(NotepadsSessionDataV1 sessio catch (Exception ex) { LoggingService.LogError($"[SessionManager] Failed to delete orphaned token in FutureAccessList: {ex.Message}"); + Analytics.TrackEvent("SessionManager_FailedToDeleteOrphanedTokenInFutureAccessList", new Dictionary() {{ "Exception", ex.Message }}); } } } diff --git a/src/Notepads/NotepadsMainPage.IO.cs b/src/Notepads/NotepadsMainPage.IO.cs index 1682c3866..e8d732c08 100644 --- a/src/Notepads/NotepadsMainPage.IO.cs +++ b/src/Notepads/NotepadsMainPage.IO.cs @@ -100,7 +100,7 @@ private async Task Save(ITextEditor textEditor, bool saveAs, bool ignoreUn !await FileSystemUtility.FileIsWritable(textEditor.EditingFile)) { NotepadsCore.SwitchTo(textEditor); - file = await FilePickerFactory.GetFileSavePicker(textEditor, _defaultNewFileName, saveAs) + file = await FilePickerFactory.GetFileSavePicker(textEditor, saveAs) .PickSaveFileAsync(); NotepadsCore.FocusOnTextEditor(textEditor); if (file == null) diff --git a/src/Notepads/NotepadsMainPage.StatusBar.cs b/src/Notepads/NotepadsMainPage.StatusBar.cs index ca8437f0d..e13a278c4 100644 --- a/src/Notepads/NotepadsMainPage.StatusBar.cs +++ b/src/Notepads/NotepadsMainPage.StatusBar.cs @@ -72,7 +72,7 @@ private void UpdateFileModificationStateIndicator(ITextEditor textEditor) private void UpdatePathIndicator(ITextEditor textEditor) { if (StatusBar == null) return; - PathIndicator.Text = textEditor.EditingFilePath ?? _defaultNewFileName; + PathIndicator.Text = textEditor.EditingFilePath ?? textEditor.FileNamePlaceholder; if (textEditor.FileModificationState == FileModificationState.Untouched) { @@ -158,7 +158,7 @@ private async void ModificationFlyoutSelection_OnClick(object sender, RoutedEven NotepadsCore.GetSelectedTextEditor().OpenSideBySideDiffViewer(); break; case "RevertAllChanges": - var fileName = selectedTextEditor.EditingFileName ?? _defaultNewFileName; + var fileName = selectedTextEditor.EditingFileName ?? selectedTextEditor.FileNamePlaceholder; var setCloseSaveReminderDialog = ContentDialogFactory.GetRevertAllChangesConfirmationDialog( fileName, () => { diff --git a/src/Notepads/NotepadsMainPage.xaml.cs b/src/Notepads/NotepadsMainPage.xaml.cs index e07a0628c..9d32495a5 100644 --- a/src/Notepads/NotepadsMainPage.xaml.cs +++ b/src/Notepads/NotepadsMainPage.xaml.cs @@ -26,8 +26,6 @@ public sealed partial class NotepadsMainPage : Page, INotificationDelegate { - private readonly string _defaultNewFileName; - private IReadOnlyList _appLaunchFiles; private string _appLaunchCmdDir; @@ -52,7 +50,7 @@ private INotepadsCore NotepadsCore { if (_notepadsCore == null) { - _notepadsCore = new NotepadsCore(Sets, _resourceLoader.GetString("TextEditor_DefaultNewFileName"), new NotepadsExtensionProvider()); + _notepadsCore = new NotepadsCore(Sets, new NotepadsExtensionProvider()); _notepadsCore.StorageItemsDropped += OnStorageItemsDropped; _notepadsCore.TextEditorLoaded += OnTextEditorLoaded; _notepadsCore.TextEditorUnloaded += OnTextEditorUnloaded; @@ -98,6 +96,8 @@ private INotepadsCore NotepadsCore private ISessionManager SessionManager => _sessionManager ?? (_sessionManager = SessionUtility.GetSessionManager(NotepadsCore)); + private readonly string _defaultNewFileName; + public NotepadsMainPage() { InitializeComponent(); @@ -154,9 +154,9 @@ 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(); }; + NewSetButton.Click += delegate { NotepadsCore.OpenNewTextEditor(_defaultNewFileName); }; MainMenuButton.Click += (sender, args) => FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender); - MenuCreateNewButton.Click += (sender, args) => NotepadsCore.OpenNewTextEditor(); + MenuCreateNewButton.Click += (sender, args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName); 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); @@ -216,8 +216,8 @@ private KeyboardCommandHandler GetKeyboardCommandHandler() new KeyboardShortcut(true, false, false, VirtualKey.W, (args) => NotepadsCore.CloseTextEditor(NotepadsCore.GetSelectedTextEditor())), new KeyboardShortcut(true, false, false, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(true)), new KeyboardShortcut(true, false, true, VirtualKey.Tab, (args) => NotepadsCore.SwitchTo(false)), - new KeyboardShortcut(true, false, false, VirtualKey.N, (args) => NotepadsCore.OpenNewTextEditor()), - new KeyboardShortcut(true, false, false, VirtualKey.T, (args) => NotepadsCore.OpenNewTextEditor()), + new KeyboardShortcut(true, false, false, VirtualKey.N, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), + new KeyboardShortcut(true, false, false, VirtualKey.T, (args) => NotepadsCore.OpenNewTextEditor(_defaultNewFileName)), new KeyboardShortcut(true, false, false, VirtualKey.O, async (args) => await OpenNewFiles()), new KeyboardShortcut(true, false, false, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: false, ignoreUnmodifiedDocument: true)), new KeyboardShortcut(true, false, true, VirtualKey.S, async (args) => await Save(NotepadsCore.GetSelectedTextEditor(), saveAs: true)), @@ -293,7 +293,7 @@ private async void Sets_Loaded(object sender, RoutedEventArgs e) { if (loadedCount == 0) { - NotepadsCore.OpenNewTextEditor(); + NotepadsCore.OpenNewTextEditor(_defaultNewFileName); } if (!App.IsFirstInstance) @@ -460,7 +460,7 @@ private async void OnTextEditorUnloaded(object sender, ITextEditor textEditor) private async void OnTextEditorClosingWithUnsavedContent(object sender, ITextEditor textEditor) { - var file = textEditor.EditingFilePath ?? _defaultNewFileName; + var file = textEditor.EditingFilePath ?? textEditor.FileNamePlaceholder; var setCloseSaveReminderDialog = ContentDialogFactory.GetSetCloseSaveReminderDialog(file, async () => { diff --git a/src/Notepads/Services/FilePickerFactory.cs b/src/Notepads/Services/FilePickerFactory.cs index ebb24dc1f..bd8c6c273 100644 --- a/src/Notepads/Services/FilePickerFactory.cs +++ b/src/Notepads/Services/FilePickerFactory.cs @@ -16,7 +16,7 @@ public static FileOpenPicker GetFileOpenPicker() return fileOpenPicker; } - public static FileSavePicker GetFileSavePicker(ITextEditor textEditor, string defaultFileName, bool saveAs) + public static FileSavePicker GetFileSavePicker(ITextEditor textEditor, bool saveAs) { FileSavePicker savePicker = new FileSavePicker { @@ -44,7 +44,7 @@ public static FileSavePicker GetFileSavePicker(ITextEditor textEditor, string de ".js", ".ts", ".lua", }); savePicker.FileTypeChoices.Add("Unknown", new List() { "." }); - savePicker.SuggestedFileName = textEditor.EditingFileName ?? defaultFileName; + savePicker.SuggestedFileName = textEditor.EditingFileName ?? textEditor.FileNamePlaceholder; return savePicker; } } diff --git a/src/Notepads/Utilities/FileSystemUtility.cs b/src/Notepads/Utilities/FileSystemUtility.cs index 1ed9b6ec7..f3bcc3e15 100644 --- a/src/Notepads/Utilities/FileSystemUtility.cs +++ b/src/Notepads/Utilities/FileSystemUtility.cs @@ -364,5 +364,17 @@ public static async Task TryAddOrReplaceTokenInFutureAccessList(string tok } return false; } + + public static int GetFutureAccessListItemCount() + { + try + { + return StorageApplicationPermissions.FutureAccessList.Entries.Count; + } + catch + { + return -1; + } + } } } \ No newline at end of file