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
+
+
+