From 7d341eb11fa0914db2694df908824125c6717be1 Mon Sep 17 00:00:00 2001 From: azakhi Date: Thu, 28 Feb 2019 00:29:22 +0300 Subject: [PATCH] Add simple auto-save feature --- .../Converters/AutosaveIntervalConverter.cs | 20 ++++++++++ Filtration/Enums/AutosaveInterval.cs | 20 ++++++++++ Filtration/Filtration.csproj | 2 + Filtration/Properties/Settings.Designer.cs | 15 +++++++ .../DesignTimeSettingsPageViewModel.cs | 3 ++ .../ViewModels/ItemFilterScriptViewModel.cs | 40 +++++++++++++++++-- Filtration/ViewModels/MainWindowViewModel.cs | 18 +++++++++ .../ViewModels/SettingsPageViewModel.cs | 34 ++++++++++++++++ Filtration/Views/SettingsPageView.xaml | 25 ++++++++---- 9 files changed, 166 insertions(+), 11 deletions(-) create mode 100644 Filtration/Converters/AutosaveIntervalConverter.cs create mode 100644 Filtration/Enums/AutosaveInterval.cs diff --git a/Filtration/Converters/AutosaveIntervalConverter.cs b/Filtration/Converters/AutosaveIntervalConverter.cs new file mode 100644 index 0000000..6b400f7 --- /dev/null +++ b/Filtration/Converters/AutosaveIntervalConverter.cs @@ -0,0 +1,20 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using Filtration.Enums; + +namespace Filtration.Converters +{ + public class IntToAutosaveIntervalConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (AutosaveInterval)(int)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return (int)(AutosaveInterval)value; + } + } +} diff --git a/Filtration/Enums/AutosaveInterval.cs b/Filtration/Enums/AutosaveInterval.cs new file mode 100644 index 0000000..e15db8c --- /dev/null +++ b/Filtration/Enums/AutosaveInterval.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace Filtration.Enums +{ + internal enum AutosaveInterval + { + [Description("Never")] + Never = -1, + [Description("5 sec")] + FiveSec = 5 * 1000, + [Description("10 sec")] + TenSec = 10 * 1000, + [Description("30 sec")] + ThirtySec = 30 * 1000, + [Description("1 min")] + OneMin = 60 * 1000, + [Description("5 min")] + FiveMin = 5 * 60 * 1000 + } +} diff --git a/Filtration/Filtration.csproj b/Filtration/Filtration.csproj index cd85216..f09eef1 100644 --- a/Filtration/Filtration.csproj +++ b/Filtration/Filtration.csproj @@ -212,10 +212,12 @@ + + diff --git a/Filtration/Properties/Settings.Designer.cs b/Filtration/Properties/Settings.Designer.cs index 6f2df82..c92c390 100644 --- a/Filtration/Properties/Settings.Designer.cs +++ b/Filtration/Properties/Settings.Designer.cs @@ -166,5 +166,20 @@ namespace Filtration.Properties { this["BlocksExpandedOnOpen"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("60000")] + public int AutosaveInterval + { + get + { + return ((int)(this["AutosaveInterval"])); + } + set + { + this["AutosaveInterval"] = value; + } + } } } diff --git a/Filtration/ViewModels/DesignTime/DesignTimeSettingsPageViewModel.cs b/Filtration/ViewModels/DesignTime/DesignTimeSettingsPageViewModel.cs index ac18848..b134ed0 100644 --- a/Filtration/ViewModels/DesignTime/DesignTimeSettingsPageViewModel.cs +++ b/Filtration/ViewModels/DesignTime/DesignTimeSettingsPageViewModel.cs @@ -21,5 +21,8 @@ namespace Filtration.ViewModels.DesignTime } public bool DownloadPrereleaseUpdates { get; set; } + public int AutosaveInterval { get; set; } + + public void SetAutosaveTimer (System.Timers.Timer timer) { } } } diff --git a/Filtration/ViewModels/ItemFilterScriptViewModel.cs b/Filtration/ViewModels/ItemFilterScriptViewModel.cs index c78a95c..fab5a7c 100644 --- a/Filtration/ViewModels/ItemFilterScriptViewModel.cs +++ b/Filtration/ViewModels/ItemFilterScriptViewModel.cs @@ -43,6 +43,8 @@ namespace Filtration.ViewModels bool ShowAdvanced { get; } string Description { get; set; } string DisplayName { get; } + bool IsFilenameFake { get; } + bool Autosave { get; } void Initialise(IItemFilterScript itemFilterScript, bool newScript); void RemoveDirtyFlag(); @@ -118,6 +120,9 @@ namespace Filtration.ViewModels private List _subscriptions; private ObservableCollection _customSoundsAvailable; private readonly List _lastAddedBlocks; + private List _promptedThemeComponents; + + public bool Autosave { get; private set; } public ItemFilterScriptViewModel(IItemFilterBlockBaseViewModelFactory itemFilterBlockBaseViewModelFactory, IItemFilterBlockTranslator blockTranslator, @@ -138,6 +143,8 @@ namespace Filtration.ViewModels _subscriptions = new List(); ItemFilterBlockViewModels = new ObservableCollection(); SelectedBlockViewModels = new ObservableCollection(); + _promptedThemeComponents = new List(); + Autosave = true; _subscriptions.Add( SelectedBlockViewModels.ToObservableChangeSet() @@ -218,7 +225,7 @@ namespace Filtration.ViewModels Script.ItemFilterBlocks.CollectionChanged += ItemFilterBlocksOnCollectionChanged; - _filenameIsFake = newScript; + IsFilenameFake = newScript; if (newScript) { @@ -653,7 +660,7 @@ namespace Filtration.ViewModels public string Filepath => Script.FilePath; - private bool _filenameIsFake; + public bool IsFilenameFake { get; private set; } private bool _showAdvanced; public async Task SaveAsync() @@ -661,7 +668,7 @@ namespace Filtration.ViewModels if (!ValidateScript()) return; if (!CheckForUnusedThemeComponents()) return; - if (_filenameIsFake) + if (IsFilenameFake) { await SaveAsAsync(); return; @@ -672,6 +679,8 @@ namespace Filtration.ViewModels { await _persistenceService.SaveItemFilterScriptAsync(Script); RemoveDirtyFlag(); + // Restore Autosave only when user successfully saves + Autosave = true; } catch (Exception e) { @@ -712,9 +721,11 @@ namespace Filtration.ViewModels { Script.FilePath = saveDialog.FileName; await _persistenceService.SaveItemFilterScriptAsync(Script); - _filenameIsFake = false; + IsFilenameFake = false; Title = Filename; RemoveDirtyFlag(); + // Restore Autosave only when user successfully saves + Autosave = true; } catch (Exception e) { @@ -741,16 +752,37 @@ namespace Filtration.ViewModels Script.ItemFilterBlocks.OfType().Count( b => b.BlockItems.OfType().Count(i => i.ThemeComponent == t) > 0) == 0).ToList(); + // Do not prompt same components again + for (var i = _promptedThemeComponents.Count - 1; i >= 0; i--) + { + if (unusedThemeComponents.Contains(_promptedThemeComponents[i])) + { + unusedThemeComponents.Remove(_promptedThemeComponents[i]); + } + else + { + _promptedThemeComponents.RemoveAt(i); + } + } + if (unusedThemeComponents.Count <= 0) return true; var themeComponents = unusedThemeComponents.Aggregate(string.Empty, (current, themeComponent) => current + themeComponent.ComponentName + Environment.NewLine); + // Do not auto-save while user is prompted + Autosave = false; + var ignoreUnusedThemeComponents = _messageBoxService.Show("Unused Theme Components", "The following theme components are unused, they will be lost when this script is reopened. Save anyway?" + Environment.NewLine + Environment.NewLine + themeComponents, MessageBoxButton.YesNo, MessageBoxImage.Exclamation); + if (ignoreUnusedThemeComponents == MessageBoxResult.Yes) + { + _promptedThemeComponents.AddRange(unusedThemeComponents); + } + return ignoreUnusedThemeComponents != MessageBoxResult.No; } diff --git a/Filtration/ViewModels/MainWindowViewModel.cs b/Filtration/ViewModels/MainWindowViewModel.cs index 50f31c3..f4376ca 100644 --- a/Filtration/ViewModels/MainWindowViewModel.cs +++ b/Filtration/ViewModels/MainWindowViewModel.cs @@ -210,6 +210,24 @@ namespace Filtration.ViewModels } }); + System.Timers.Timer timer = new System.Timers.Timer(); + timer.Elapsed += (sender, e) => OnTimedEvent(sender, e, this); + timer.Interval = Settings.Default.AutosaveInterval > 0 ? Settings.Default.AutosaveInterval : double.MaxValue; + timer.Enabled = Settings.Default.AutosaveInterval > 0; + settingsPageViewModel.SetAutosaveTimer(timer); + } + + private static void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e, MainWindowViewModel mainWindowViewModel) + { + mainWindowViewModel.AutoSave(); + } + + public void AutoSave() + { + foreach (var doc in _avalonDockWorkspaceViewModel.OpenDocuments.OfType().Where(doc => doc.IsDirty && doc.IsScript && !doc.IsFilenameFake && doc.Autosave)) + { + doc.SaveAsync(); + } } public RelayCommand OpenScriptCommand { get; } diff --git a/Filtration/ViewModels/SettingsPageViewModel.cs b/Filtration/ViewModels/SettingsPageViewModel.cs index 6779915..d88ee0b 100644 --- a/Filtration/ViewModels/SettingsPageViewModel.cs +++ b/Filtration/ViewModels/SettingsPageViewModel.cs @@ -13,11 +13,15 @@ namespace Filtration.ViewModels bool BlocksExpandedOnOpen { get; set; } bool DownloadPrereleaseUpdates { get; set; } bool ExtraLineBetweenBlocks { get; set; } + int AutosaveInterval { get; set; } + + void SetAutosaveTimer(System.Timers.Timer timer); } internal class SettingsPageViewModel : ViewModelBase, ISettingsPageViewModel { private readonly IItemFilterScriptDirectoryService _itemFilterScriptDirectoryService; + private System.Timers.Timer _autosaveTimer; public SettingsPageViewModel(IItemFilterScriptDirectoryService itemFilterScriptDirectoryService) { @@ -47,6 +51,36 @@ namespace Filtration.ViewModels set => Settings.Default.ExtraLineBetweenBlocks = value; } + public int AutosaveInterval + { + get => Settings.Default.AutosaveInterval; + set + { + Settings.Default.AutosaveInterval = value; + if (_autosaveTimer != null) + { + if (value < 0) + { + _autosaveTimer.Stop(); + } + else if (_autosaveTimer.Interval != value) + { + _autosaveTimer.Stop(); + _autosaveTimer.Interval = value; + _autosaveTimer.Start(); + } + } + } + } + + public void SetAutosaveTimer(System.Timers.Timer timer) + { + if (_autosaveTimer == null) + { + _autosaveTimer = timer; + } + } + private void OnSetItemFilterScriptDirectoryCommand() { _itemFilterScriptDirectoryService.SetItemFilterScriptDirectory(); diff --git a/Filtration/Views/SettingsPageView.xaml b/Filtration/Views/SettingsPageView.xaml index 83ba1a5..4d857f2 100644 --- a/Filtration/Views/SettingsPageView.xaml +++ b/Filtration/Views/SettingsPageView.xaml @@ -1,11 +1,17 @@ - + d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type={x:Type designTime:DesignTimeSettingsPageViewModel}}"> + + + @@ -27,7 +33,7 @@ - Default Filter Directory: + @@ -35,15 +41,20 @@ - Add blank line between blocks when saving + - Download pre-release updates (use with caution) + - Auto-expand all sections when opening scripts + + +