Пример #1
0
        /// <summary>
        /// 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().
        /// </summary>
        public App()
        {
            UnhandledException += OnUnhandledException;
            TaskScheduler.UnobservedTaskException += OnUnobservedException;

            var services = new Type[] { typeof(Crashes), typeof(Analytics) };

            AppCenter.Start(AppCenterSecret, services);

            InstanceHandlerMutex = new Mutex(true, App.ApplicationName, out bool isNew);
            if (isNew)
            {
                IsPrimaryInstance = true;
                ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, null);
            }
            else
            {
                InstanceHandlerMutex.Close();
            }

            LoggingService.LogInfo($"[{nameof(App)}] Started: Instance = {Id} IsPrimaryInstance: {IsPrimaryInstance} IsGameBarWidget: {IsGameBarWidget}.");

            ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString());

            InitializeComponent();

            Suspending += OnSuspending;
        }
Пример #2
0
        private static AppInstance GetLastActiveInstance()
        {
            var instances = AppInstance.GetInstances();

            if (instances.Count == 0)
            {
                return(null);
            }
            else if (instances.Count == 1)
            {
                return(instances.FirstOrDefault());
            }

            if (!(ApplicationSettingsStore.Read(SettingsKey.ActiveInstanceIdStr) is string activeInstance))
            {
                return(null);
            }

            foreach (var appInstance in instances)
            {
                if (appInstance.Key == activeInstance)
                {
                    return(appInstance);
                }
            }

            // activeInstance might be closed already, let's return the first instance in this case
            return(instances.FirstOrDefault());
        }
Пример #3
0
        private static AppInstance GetLastActiveInstance()
        {
            var instances = AppInstance.GetInstances();

            if (instances.Count == 0)
            {
                return(null);
            }
            else if (instances.Count == 1)
            {
                return(instances.FirstOrDefault());
            }

            string activeInstance = ApplicationSettingsStore.Read("ActiveInstance") as string;

            if (activeInstance == null)
            {
                return(null);
            }

            foreach (var appInstance in instances)
            {
                if (appInstance.Key == activeInstance)
                {
                    return(appInstance);
                }
            }

            // activeInstance might be closed, let's return the first instance
            return(instances.FirstOrDefault());
        }
Пример #4
0
        public async Task <int> LoadLastSessionAsync()
        {
            if (_loaded)
            {
                return(0); // Already loaded
            }

            if (!(ApplicationSettingsStore.Read(SessionDataKey) is string data))
            {
                return(0); // No session data found
            }

            NotepadsSessionDataV1 sessionData;

            try
            {
                sessionData = JsonConvert.DeserializeObject <NotepadsSessionDataV1>(data, _encodingConverter);
            }
            catch (Exception ex)
            {
                LoggingService.LogError($"Failed to load session metadata: {ex.Message}");
                return(0);
            }

            ITextEditor selectedTextEditor = null;

            foreach (TextEditorSessionData textEditorData in sessionData.TextEditors)
            {
                ITextEditor textEditor;

                try
                {
                    textEditor = await RecoverTextEditorAsync(textEditorData);
                }
                catch
                {
                    continue;
                }

                if (textEditor != null)
                {
                    _sessionData.TryAdd(textEditor.Id, textEditorData);

                    if (textEditor.Id == sessionData.SelectedTextEditor)
                    {
                        selectedTextEditor = textEditor;
                    }
                }
            }

            if (selectedTextEditor != null)
            {
                _notepadsCore.SwitchTo(selectedTextEditor);
            }

            _loaded = true;

            return(_sessionData.Count);
        }
Пример #5
0
        static void Main(string[] args)
        {
            var instances = AppInstance.GetInstances();

            if (instances.Count == 0)
            {
                IsFirstInstance = true;
                ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, null);
            }

            IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs();

            if (activatedArgs is FileActivatedEventArgs)
            {
                RedirectOrCreateNewInstance();
            }
            else if (activatedArgs is CommandLineActivatedEventArgs cmdActivatedArgs)
            {
                RedirectOrCreateNewInstance();
            }
            else if (activatedArgs is ProtocolActivatedEventArgs protocolActivatedEventArgs)
            {
                LoggingService.LogInfo($"[Main] [ProtocolActivated] Protocol: {protocolActivatedEventArgs.Uri}");
                var protocol = NotepadsProtocolService.GetOperationProtocol(protocolActivatedEventArgs.Uri, out var context);
                if (protocol == NotepadsOperationProtocol.OpenNewInstance)
                {
                    OpenNewInstance();
                }
                else
                {
                    RedirectOrCreateNewInstance();
                }
            }
            else if (activatedArgs is LaunchActivatedEventArgs launchActivatedEventArgs)
            {
                bool handled = false;

                if (!string.IsNullOrEmpty(launchActivatedEventArgs.Arguments))
                {
                    var protocol = NotepadsProtocolService.GetOperationProtocol(new Uri(launchActivatedEventArgs.Arguments), out var context);
                    if (protocol == NotepadsOperationProtocol.OpenNewInstance)
                    {
                        handled = true;
                        OpenNewInstance();
                    }
                }

                if (!handled)
                {
                    RedirectOrCreateNewInstance();
                }
            }
            else
            {
                RedirectOrCreateNewInstance();
            }
        }
Пример #6
0
        private void Sets_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
        {
            if (ApplicationSettingsStore.Read(SetDragAndDropActionStatus) is string setDragAndDropActionStatus && setDragAndDropActionStatus == "Handled")
            {
                if (args.Items.FirstOrDefault() is ITextEditor editor)
                {
                    DeleteTextEditor(editor);
                }
            }

            ApplicationSettingsStore.Remove(SetDragAndDropActionStatus);
        }
Пример #7
0
        private void Sets_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
        {
            if (ApplicationSettingsStore.Read(SetDragAndDropActionStatus) is string setDragAndDropActionStatus && setDragAndDropActionStatus == "Handled")
            {
                if (args.Items.FirstOrDefault() is ITextEditor editor)
                {
                    TextEditorMovedToAnotherAppInstance?.Invoke(this, editor);
                }
            }

            ApplicationSettingsStore.Remove(SetDragAndDropActionStatus);
        }
Пример #8
0
        static void Main(string[] args)
        {
            _instances = AppInstance.GetInstances();

            if (_instances.Count == 0)
            {
                IsFirstInstance = true;
                ApplicationSettingsStore.Write("ActiveInstance", null);
            }

            IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs();

            if (activatedArgs is FileActivatedEventArgs fileArgs)
            {
                foreach (var file in fileArgs.Files)
                {
                    if (!(file is StorageFile))
                    {
                        continue;
                    }
                    AssignOrCreateInstanceForFile((file as StorageFile).Path);
                }
            }
            else if (activatedArgs is CommandLineActivatedEventArgs cmdActivatedArgs)
            {
                LoggingService.LogInfo($"[Main] [CommandActivated] CurrentDirectoryPath: {cmdActivatedArgs.Operation.CurrentDirectoryPath} Arguments: {cmdActivatedArgs.Operation.Arguments}");

                var file = FileSystemUtility.GetAbsolutePathFromCommandLine(
                    cmdActivatedArgs.Operation.CurrentDirectoryPath, cmdActivatedArgs.Operation.Arguments, App.ApplicationName);
                if (file != null)
                {
                    AssignOrCreateInstanceForFile(file);
                }
                else
                {
                    OpenNewInstance();
                }
            }
            else if (activatedArgs is ProtocolActivatedEventArgs protocolActivatedEventArgs)
            {
                LoggingService.LogInfo($"[Main] [ProtocolActivated] Protocol: {protocolActivatedEventArgs.Uri}");
                var protocol = NotepadsProtocolService.GetOperationProtocol(protocolActivatedEventArgs.Uri, out var context);
                if (protocol == NotepadsOperationProtocol.OpenNewInstance || protocol == NotepadsOperationProtocol.Unrecognized)
                {
                    OpenNewInstance();
                }
            }
            else
            {
                OpenNewInstance();
            }
        }
Пример #9
0
        private static void RedirectOrCreateNewInstance()
        {
            var instance = (GetLastActiveInstance() ?? AppInstance.FindOrRegisterInstanceForKey(App.Id.ToString()));

            if (instance.IsCurrentInstance)
            {
                Windows.UI.Xaml.Application.Start(p => new App());
            }
            else
            {
                // open new instance if user prefers to
                if (ApplicationSettingsStore.Read(SettingsKey.AlwaysOpenNewWindowBool) is bool alwaysOpenNewWindowBool && alwaysOpenNewWindowBool)
                {
                    OpenNewInstance();
                }
Пример #10
0
        private void Sets_DragItemsStarting(object sender, DragItemsStartingEventArgs args)
        {
            // In Initial Window we need to serialize our tab data.
            var item = args.Items.FirstOrDefault();

            if (!(item is ITextEditor editor))
            {
                return;
            }

            try
            {
                var data = JsonConvert.SerializeObject(editor.GetTextEditorStateMetaData());

                var lastSavedText = editor.LastSavedSnapshot.Content;
                var pendingText   = editor.GetText();

                args.Data.Properties.Add(NotepadsTextEditorLastSavedContent, lastSavedText);

                if (!string.Equals(lastSavedText, pendingText))
                {
                    args.Data.Properties.Add(NotepadsTextEditorPendingContent, pendingText);
                }

                // Add Editing File
                if (editor.EditingFile != null)
                {
                    args.Data.Properties.FileTypes.Add(StandardDataFormats.StorageItems);
                    args.Data.Properties.Add(NotepadsTextEditorEditingFilePath, editor.EditingFilePath);
                    args.Data.SetStorageItems(new List <IStorageItem>()
                    {
                        editor.EditingFile
                    }, readOnly: false);
                }

                args.Data.Properties.Add(NotepadsTextEditorMetaData, data);
                args.Data.Properties.Add(NotepadsTextEditorGuid, editor.Id.ToString());
                args.Data.Properties.Add(NotepadsInstanceId, App.Id.ToString());
                args.Data.Properties.ApplicationName = App.ApplicationName;

                ApplicationSettingsStore.Write(SetDragAndDropActionStatus, "Started");
            }
            catch (Exception ex)
            {
                LoggingService.LogError($"[{nameof(NotepadsCore)}] Failed to prepare editor meta data for drag and drop: {ex.Message}");
            }
        }
Пример #11
0
        /// <summary>
        /// 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().
        /// </summary>
        public App()
        {
            UnhandledException += OnUnhandledException;
            TaskScheduler.UnobservedTaskException += OnUnobservedException;

            var services = new Type[] { typeof(Crashes), typeof(Analytics) };

            AppCenter.Start(AppCenterSecret, services);

            LoggingService.LogInfo($"[{nameof(App)}] Started: Instance = {Id} IsFirstInstance: {IsFirstInstance} IsGameBarWidget: {IsGameBarWidget}.");

            ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, App.Id.ToString());

            InitializeComponent();

            Suspending += OnSuspending;
        }
Пример #12
0
        /// <summary>
        /// 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().
        /// </summary>
        public App()
        {
            //await LoggingService.InitializeAsync();
            LoggingService.LogInfo($"[App Started] Instance = {Id} IsFirstInstance: {IsFirstInstance}");

            if (!IsFirstInstance)
            {
                Analytics.TrackEvent("ShadowInstanceLaunched");
            }

            ApplicationSettingsStore.Write("ActiveInstance", App.Id.ToString());

            UnhandledException += OnUnhandledException;
            TaskScheduler.UnobservedTaskException += OnUnobservedException;

            var services = new Type[] { typeof(Crashes), typeof(Analytics) };

            AppCenter.Start(AppCenterSecret, services);

            InitializeComponent();
            Suspending += OnSuspending;
        }
Пример #13
0
 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);
         ApplicationSettingsStore.Write("ActiveInstance", App.Id.ToString());
         NotepadsCore.GetSelectedTextEditor()?.StartCheckingFileStatusPeriodically();
         if (EditorSettingsService.IsSessionSnapshotEnabled)
         {
             SessionManager.StartSessionBackup();
         }
     }
 }
Пример #14
0
        static void Main(string[] args)
        {
#if DEBUG
            Task.Run(LoggingService.InitializeFileSystemLoggingAsync);
#endif

            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
            //    App.IsGameBarWidget = true;
            //    App.IsFirstInstance = true;
            //    Windows.UI.Xaml.Application.Start(p => new App());
            //}

            var instances = AppInstance.GetInstances();

            if (instances.Count == 0)
            {
                IsFirstInstance = true;
                ApplicationSettingsStore.Write(SettingsKey.ActiveInstanceIdStr, null);
            }

            if (activatedArgs is FileActivatedEventArgs)
            {
                RedirectOrCreateNewInstance();
            }
            else if (activatedArgs is CommandLineActivatedEventArgs)
            {
                RedirectOrCreateNewInstance();
            }
            else if (activatedArgs is ProtocolActivatedEventArgs protocolActivatedEventArgs)
            {
                LoggingService.LogInfo($"[{nameof(Main)}] [ProtocolActivated] Protocol: {protocolActivatedEventArgs.Uri}");
                var protocol = NotepadsProtocolService.GetOperationProtocol(protocolActivatedEventArgs.Uri, out _);
                if (protocol == NotepadsOperationProtocol.OpenNewInstance)
                {
                    OpenNewInstance();
                }
                else
                {
                    RedirectOrCreateNewInstance();
                }
            }
            else if (activatedArgs is LaunchActivatedEventArgs launchActivatedEventArgs)
            {
                bool handled = false;

                if (!string.IsNullOrEmpty(launchActivatedEventArgs.Arguments))
                {
                    var protocol = NotepadsProtocolService.GetOperationProtocol(new Uri(launchActivatedEventArgs.Arguments), out _);
                    if (protocol == NotepadsOperationProtocol.OpenNewInstance)
                    {
                        handled = true;
                        OpenNewInstance();
                    }
                }

                if (!handled)
                {
                    RedirectOrCreateNewInstance();
                }
            }
            else
            {
                RedirectOrCreateNewInstance();
            }
        }
Пример #15
0
        private async void Sets_Drop(object sender, DragEventArgs args)
        {
            if (!(sender is SetsView))
            {
                return;
            }

            var sets = sender as SetsView;

            // Handle non Notepads drop event
            if (string.IsNullOrEmpty(args.DataView?.Properties?.ApplicationName) ||
                !string.Equals(args.DataView?.Properties?.ApplicationName, App.ApplicationName))
            {
                if (args.DataView == null || !args.DataView.Contains(StandardDataFormats.StorageItems))
                {
                    return;
                }
                var fileDropDeferral = args.GetDeferral();
                var storageItems     = await args.DataView.GetStorageItemsAsync();

                StorageItemsDropped?.Invoke(this, storageItems);
                fileDropDeferral.Complete();
                return;
            }

            var deferral = args.GetDeferral();

            try
            {
                args.DataView.Properties.TryGetValue(NotepadsTextEditorMetaData, out object dataObj);

                if (!(dataObj is string data))
                {
                    throw new Exception("Failed to drop editor set: NotepadsTextEditorMetaData is invalid (Not String).");
                }

                TextEditorStateMetaData metaData = JsonConvert.DeserializeObject <TextEditorStateMetaData>(data);

                if (args.DataView.Properties.TryGetValue(NotepadsTextEditorEditingFilePath,
                                                         out object editingFilePathObj) && editingFilePathObj is string editingFilePath)
                {
                    var editor = GetTextEditor(editingFilePath);
                    if (editor != null)
                    {
                        SwitchTo(editor);
                        NotificationCenter.Instance.PostNotification(_resourceLoader.GetString("TextEditor_NotificationMsg_FileAlreadyOpened"), 2500);
                        throw new Exception("Failed to drop editor set: File already opened.");
                    }
                }

                StorageFile editingFile = null;

                if (metaData.HasEditingFile && args.DataView.Contains(StandardDataFormats.StorageItems))
                {
                    var storageItems = await args.DataView.GetStorageItemsAsync();

                    if (storageItems.Count == 1 && storageItems[0] is StorageFile file)
                    {
                        editingFile = file;
                    }
                    else
                    {
                        throw new Exception("Failed to read storage file from dropped set: Expecting only one storage file.");
                    }
                }

                string lastSavedText = null;
                string pendingText   = null;

                if (args.DataView.Properties.TryGetValue(NotepadsTextEditorLastSavedContent, out object lastSavedContentObj) &&
                    lastSavedContentObj is string lastSavedContent)
                {
                    lastSavedText = lastSavedContent;
                }
                else
                {
                    throw new Exception($"Failed to get last saved content from DataView: NotepadsTextEditorLastSavedContent property Is null");
                }

                if (args.DataView.Properties.TryGetValue(NotepadsTextEditorPendingContent, out object pendingContentObj) &&
                    pendingContentObj is string pendingContent)
                {
                    pendingText = pendingContent;
                }

                ApplicationSettingsStore.Write(SetDragAndDropActionStatus, "Handled");

                var index = -1;

                // Determine which items in the list our pointer is in between.
                for (int i = 0; i < sets.Items?.Count; i++)
                {
                    var item = sets.ContainerFromIndex(i) as SetsViewItem;

                    if (args.GetPosition(item).X - item?.ActualWidth < 0)
                    {
                        index = i;
                        break;
                    }
                }

                var atIndex = index == -1 ? sets.Items.Count : index;

                var textFile = new TextFile(lastSavedText,
                                            EncodingUtility.GetEncodingByName(metaData.LastSavedEncoding),
                                            LineEndingUtility.GetLineEndingByName(metaData.LastSavedLineEnding),
                                            metaData.DateModifiedFileTime);

                var newEditor = CreateTextEditor(Guid.NewGuid(), textFile, editingFile, metaData.FileNamePlaceholder, metaData.IsModified);
                OpenTextEditor(newEditor, atIndex);
                newEditor.ResetEditorState(metaData, pendingText);

                if (metaData.IsContentPreviewPanelOpened)
                {
                    newEditor.ShowHideContentPreview();
                }

                if (metaData.IsInDiffPreviewMode)
                {
                    newEditor.OpenSideBySideDiffViewer();
                }

                deferral.Complete();
                Analytics.TrackEvent("OnSetDropped");
            }
            catch (Exception ex)
            {
                LoggingService.LogException(ex);
                deferral.Complete();
            }
        }
Пример #16
0
 public void ClearSessionData()
 {
     ApplicationSettingsStore.Remove(SessionDataKey);
 }
Пример #17
0
        public async Task SaveSessionAsync()
        {
            if (!IsBackupEnabled)
            {
                LoggingService.LogInfo("Session backup is disabled.");
                return;
            }

            // Serialize saves
            await _semaphoreSlim.WaitAsync();

            Stopwatch stopwatch = Stopwatch.StartNew();

            ITextEditor[] textEditors        = _notepadsCore.GetAllTextEditors();
            ITextEditor   selectedTextEditor = _notepadsCore.GetSelectedTextEditor();

            FileSystemUtility.ClearFutureAccessList();

            NotepadsSessionDataV1 sessionData = new NotepadsSessionDataV1();

            foreach (ITextEditor textEditor in textEditors)
            {
                if (textEditor.EditingFile != null)
                {
                    // Add the opened file to FutureAccessList so we can access it next launch
                    await FileSystemUtility.TryAddToFutureAccessList(ToToken(textEditor.Id), textEditor.EditingFile);
                }

                if (!_sessionData.TryGetValue(textEditor.Id, out TextEditorSessionData textEditorData))
                {
                    textEditorData = new TextEditorSessionData {
                        Id = textEditor.Id
                    };

                    if (textEditor.IsModified)
                    {
                        if (textEditor.EditingFile != null)
                        {
                            // Persist the last save known to the app, which might not be up-to-date (if the file was modified outside the app)
                            BackupMetadata lastSaved = await SaveLastSavedChangesAsync(textEditor);

                            if (lastSaved == null)
                            {
                                continue;
                            }

                            textEditorData.LastSaved = lastSaved;
                        }

                        // Persist pending changes relative to the last save
                        BackupMetadata pending = await SavePendingChangesAsync(textEditor);

                        if (pending == null)
                        {
                            continue;
                        }

                        textEditorData.Pending = pending;
                    }

                    // We will not create new backup files for this text editor unless it has changes
                    _sessionData.TryAdd(textEditor.Id, textEditorData);
                }

                sessionData.TextEditors.Add(textEditorData);

                if (textEditor == selectedTextEditor)
                {
                    sessionData.SelectedTextEditor = textEditor.Id;
                }
            }

            bool sessionDataSaved = false;

            try
            {
                string sessionJsonStr = JsonConvert.SerializeObject(sessionData, _encodingConverter);

                if (!(ApplicationSettingsStore.Read(SessionDataKey) is string currentValue) || !string.Equals(currentValue, sessionJsonStr, StringComparison.OrdinalIgnoreCase))
                {
                    ApplicationSettingsStore.Write(SessionDataKey, sessionJsonStr);
                    sessionDataSaved = true;
                }
            }
            catch (Exception ex)
            {
                LoggingService.LogError($"Failed to save session metadata: {ex.Message}");
                return; // Failed to save the session - do not proceed to delete backup files
            }

            if (sessionDataSaved)
            {
                await DeleteOrphanedBackupFilesAsync(sessionData);
            }

            stopwatch.Stop();

            if (sessionDataSaved)
            {
                LoggingService.LogInfo($"Successfully saved the current session. Total time: {stopwatch.Elapsed.TotalMilliseconds} milliseconds.", consoleOnly: true);
            }

            _semaphoreSlim.Release();
        }