Skip to content

Commit a7de0c1

Browse files
committed
[WIP] Use BaseJsonSettingsModel import/export and reload settings
1 parent a483996 commit a7de0c1

File tree

10 files changed

+184
-26
lines changed

10 files changed

+184
-26
lines changed

Common/FileTagsDb.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using LiteDB;
22
using System;
33
using System.Collections.Generic;
4+
using System.Linq;
45

56
namespace Common
67
{
@@ -149,6 +150,18 @@ public void Dispose()
149150
db.Dispose();
150151
}
151152

153+
public void Import(string json)
154+
{
155+
var dataValues = JsonSerializer.DeserializeArray(json);
156+
db.Engine.Delete("taggedfiles", Query.All());
157+
db.Engine.InsertBulk("taggedfiles", dataValues.Select(x => x.AsDocument));
158+
}
159+
160+
public string Export()
161+
{
162+
return JsonSerializer.Serialize(new BsonArray(db.Engine.FindAll("taggedfiles")));
163+
}
164+
152165
public class TaggedFile
153166
{
154167
[BsonId]

Files/Controllers/SidebarPinnedController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ public async Task InitializeAsync()
2929
await LoadAsync();
3030
}
3131

32+
public async Task ReloadAsync()
33+
{
34+
await LoadAsync();
35+
Model.RemoveStaleSidebarItems();
36+
}
37+
3238
private async Task LoadAsync()
3339
{
3440
StorageFolder Folder = await FilesystemTasks.Wrap(() => ApplicationData.Current.LocalFolder.CreateFolderAsync("settings", CreationCollisionOption.OpenIfExists).AsTask());

Files/Services/IBundlesSettingsService.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
using System.Collections.Generic;
1+
using Files.EventArguments;
2+
using System;
3+
using System.Collections.Generic;
24

35
namespace Files.Services
46
{
57
public interface IBundlesSettingsService
68
{
9+
event EventHandler<SettingChangedEventArgs> OnSettingChangedEvent;
10+
711
bool FlushSettings();
812

913
object ExportSettings();
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1-
using Files.Filesystem;
1+
using Files.EventArguments;
2+
using Files.Filesystem;
3+
using System;
24
using System.Collections.Generic;
35

46
namespace Files.Services
57
{
68
public interface IFileTagsSettingsService
79
{
10+
event EventHandler<SettingChangedEventArgs> OnSettingChangedEvent;
11+
812
IList<FileTag> FileTagList { get; set; }
913

1014
FileTag GetTagById(string uid);
1115

1216
IEnumerable<FileTag> GetTagsByName(string tagName);
17+
18+
object ExportSettings();
19+
20+
bool ImportSettings(object import);
1321
}
1422
}

Files/Services/Implementation/BundlesSettingsService.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Files.Models.JsonSettings;
1+
using Files.Extensions;
2+
using Files.Models.JsonSettings;
23
using System.Collections.Generic;
34
using Windows.Storage;
45

@@ -20,19 +21,22 @@ public Dictionary<string, List<string>> SavedBundles
2021

2122
public override bool ImportSettings(object import)
2223
{
23-
try
24+
if (import is string importString)
2425
{
25-
SavedBundles = (Dictionary<string, List<string>>)import;
26-
27-
FlushSettings();
28-
29-
return true;
26+
SavedBundles = jsonSettingsSerializer.DeserializeFromJson<Dictionary<string, List<string>>>(importString);
3027
}
31-
catch
28+
else if (import is Dictionary<string, List<string>> importDict)
3229
{
33-
// TODO: Display the error?
34-
return false;
30+
SavedBundles = importDict;
3531
}
32+
33+
if (SavedBundles != null)
34+
{
35+
FlushSettings();
36+
return true;
37+
}
38+
39+
return false;
3640
}
3741

3842
public override object ExportSettings()

Files/Services/Implementation/FileTagsSettingsService.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,33 @@ public IEnumerable<FileTag> GetTagsByName(string tagName)
5151
{
5252
return FileTagList.Where(x => x.TagName.StartsWith(tagName, StringComparison.OrdinalIgnoreCase));
5353
}
54+
55+
public override bool ImportSettings(object import)
56+
{
57+
if (import is string importString)
58+
{
59+
FileTagList = jsonSettingsSerializer.DeserializeFromJson<List<FileTag>>(importString);
60+
}
61+
else if (import is List<FileTag> importList)
62+
{
63+
FileTagList = importList;
64+
}
65+
66+
FileTagList ??= s_defaultFileTags;
67+
68+
if (FileTagList != null)
69+
{
70+
FlushSettings();
71+
return true;
72+
}
73+
74+
return false;
75+
}
76+
77+
public override object ExportSettings()
78+
{
79+
// Return string in Json format
80+
return jsonSettingsSerializer.SerializeToJson(FileTagList);
81+
}
5482
}
5583
}

Files/Services/Implementation/UserSettingsService.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,15 @@ public override object ExportSettings()
6363

6464
public override bool ImportSettings(object import)
6565
{
66-
var settingsImport = jsonSettingsSerializer.DeserializeFromJson<Dictionary<string, object>>((string)import);
66+
Dictionary<string, object> settingsImport = null;
67+
if (import is string importString)
68+
{
69+
settingsImport = jsonSettingsSerializer.DeserializeFromJson<Dictionary<string, object>>(importString);
70+
}
71+
else if (import is Dictionary<string, object> importDict)
72+
{
73+
settingsImport = importDict;
74+
}
6775

6876
if (!settingsImport.IsEmpty())
6977
{

Files/ViewModels/ItemViewModel.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public class ItemViewModel : ObservableObject, IDisposable
5858
private List<ListedItem> filesAndFolders;
5959

6060
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService<IUserSettingsService>();
61+
private IFileTagsSettingsService FileTagsSettingsService { get; } = Ioc.Default.GetService<IFileTagsSettingsService>();
6162

6263
// only used for Binding and ApplyFilesAndFoldersChangesAsync, don't manipulate on this!
6364
public BulkConcurrentObservableCollection<ListedItem> FilesAndFolders { get; }
@@ -359,9 +360,20 @@ public ItemViewModel(FolderSettingsViewModel folderSettingsViewModel)
359360
shouldDisplayFileExtensions = UserSettingsService.PreferencesSettingsService.ShowFileExtensions;
360361

361362
UserSettingsService.OnSettingChangedEvent += UserSettingsService_OnSettingChangedEvent;
363+
FileTagsSettingsService.OnSettingChangedEvent += FileTagsSettingsService_OnSettingChangedEvent;
362364
AppServiceConnectionHelper.ConnectionChanged += AppServiceConnectionHelper_ConnectionChanged;
363365
}
364366

367+
private void FileTagsSettingsService_OnSettingChangedEvent(object sender, SettingChangedEventArgs e)
368+
{
369+
switch (e.settingName)
370+
{
371+
case nameof(FileTagsSettingsService.FileTagList):
372+
// Reload tags
373+
break;
374+
}
375+
}
376+
365377
private async void UserSettingsService_OnSettingChangedEvent(object sender, SettingChangedEventArgs e)
366378
{
367379
switch (e.settingName)
@@ -2251,6 +2263,7 @@ public void Dispose()
22512263
Connection.RequestReceived -= Connection_RequestReceived;
22522264
}
22532265
UserSettingsService.OnSettingChangedEvent -= UserSettingsService_OnSettingChangedEvent;
2266+
FileTagsSettingsService.OnSettingChangedEvent -= FileTagsSettingsService_OnSettingChangedEvent;
22542267
AppServiceConnectionHelper.ConnectionChanged -= AppServiceConnectionHelper_ConnectionChanged;
22552268
DefaultIcons.Clear();
22562269
}

Files/ViewModels/SettingsViewModels/AboutViewModel.cs

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Files.Extensions;
1+
using Files.Filesystem;
2+
using Files.Filesystem.StorageItems;
23
using Files.Helpers;
34
using Files.Services;
45
using Microsoft.Toolkit.Mvvm.ComponentModel;
@@ -22,6 +23,8 @@ namespace Files.ViewModels.SettingsViewModels
2223
public class AboutViewModel : ObservableObject
2324
{
2425
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetService<IUserSettingsService>();
26+
private IBundlesSettingsService BundlesSettingsService { get; } = Ioc.Default.GetService<IBundlesSettingsService>();
27+
protected IFileTagsSettingsService FileTagsSettingsService { get; } = Ioc.Default.GetService<IFileTagsSettingsService>();
2528

2629
public RelayCommand OpenLogLocationCommand => new RelayCommand(() => SettingsViewModel.OpenLogLocation());
2730
public RelayCommand CopyVersionInfoCommand => new RelayCommand(() => CopyVersionInfo());
@@ -42,31 +45,92 @@ public AboutViewModel()
4245
private async Task ExportSettings()
4346
{
4447
FileSavePicker filePicker = new FileSavePicker();
45-
filePicker.FileTypeChoices.Add("Json File", Path.GetExtension(Constants.LocalSettings.UserSettingsFileName).CreateList());
48+
filePicker.FileTypeChoices.Add("Zip File", new[] { ".zip" });
49+
filePicker.SuggestedFileName = $"Files_{App.AppVersion}";
4650

4751
StorageFile file = await filePicker.PickSaveFileAsync();
4852
if (file != null)
4953
{
50-
string export = (string)UserSettingsService.ExportSettings();
51-
await FileIO.WriteTextAsync(file, export);
54+
try
55+
{
56+
var zipFolder = await ZipStorageFolder.FromStorageFileAsync(file);
57+
if (zipFolder == null)
58+
{
59+
return;
60+
}
61+
var localFolderPath = ApplicationData.Current.LocalFolder.Path;
62+
// Export user settings
63+
var userSettings = await zipFolder.CreateFileAsync(Constants.LocalSettings.UserSettingsFileName, CreationCollisionOption.ReplaceExisting);
64+
string exportSettings = (string)UserSettingsService.ExportSettings();
65+
await userSettings.WriteTextAsync(exportSettings);
66+
// Export bundles
67+
var bundles = await zipFolder.CreateFileAsync(Constants.LocalSettings.BundlesSettingsFileName, CreationCollisionOption.ReplaceExisting);
68+
string exportBundles = (string)BundlesSettingsService.ExportSettings();
69+
await bundles.WriteTextAsync(exportBundles);
70+
// Export pinned items
71+
var pinnedItems = await BaseStorageFile.GetFileFromPathAsync(Path.Combine(localFolderPath, Constants.LocalSettings.SettingsFolderName, App.SidebarPinnedController.JsonFileName));
72+
await pinnedItems.CopyAsync(zipFolder, pinnedItems.Name, NameCollisionOption.ReplaceExisting);
73+
// Export terminals config
74+
var terminals = await BaseStorageFile.GetFileFromPathAsync(Path.Combine(localFolderPath, Constants.LocalSettings.SettingsFolderName, App.TerminalController.JsonFileName));
75+
await terminals.CopyAsync(zipFolder, terminals.Name, NameCollisionOption.ReplaceExisting);
76+
// Export file tags list and DB
77+
var fileTagsList = await zipFolder.CreateFileAsync(Constants.LocalSettings.FileTagSettingsFileName, CreationCollisionOption.ReplaceExisting);
78+
string exportTags = (string)FileTagsSettingsService.ExportSettings();
79+
await fileTagsList.WriteTextAsync(exportTags);
80+
var fileTagsDB = await zipFolder.CreateFileAsync(Path.GetFileName(FileTagsHelper.FileTagsDbPath), CreationCollisionOption.ReplaceExisting);
81+
string exportTagsDB = FileTagsHelper.DbInstance.Export();
82+
await fileTagsDB.WriteTextAsync(exportTagsDB);
83+
}
84+
catch (Exception ex)
85+
{
86+
App.Logger.Warn(ex, "Error exporting settings");
87+
}
5288
}
5389
}
5490

5591
private async Task ImportSettings()
5692
{
5793
FileOpenPicker filePicker = new FileOpenPicker();
58-
filePicker.FileTypeFilter.Add(Path.GetExtension(Constants.LocalSettings.UserSettingsFileName));
94+
filePicker.FileTypeFilter.Add(".zip");
5995

6096
StorageFile file = await filePicker.PickSingleFileAsync();
6197
if (file != null)
6298
{
6399
try
64100
{
65-
string import = await FileIO.ReadTextAsync(file);
66-
UserSettingsService.ImportSettings(import);
101+
var zipFolder = await ZipStorageFolder.FromStorageFileAsync(file);
102+
if (zipFolder == null)
103+
{
104+
return;
105+
}
106+
var localFolderPath = ApplicationData.Current.LocalFolder.Path;
107+
var settingsFolder = await StorageFolder.GetFolderFromPathAsync(Path.Combine(localFolderPath, Constants.LocalSettings.SettingsFolderName));
108+
// Import user settings
109+
var userSettingsFile = await zipFolder.GetFileAsync(Constants.LocalSettings.UserSettingsFileName);
110+
string importSettings = await userSettingsFile.ReadTextAsync();
111+
UserSettingsService.ImportSettings(importSettings);
112+
// Import bundles
113+
var bundles = await zipFolder.GetFileAsync(Constants.LocalSettings.BundlesSettingsFileName);
114+
string importBundles = await bundles.ReadTextAsync();
115+
BundlesSettingsService.ImportSettings(importBundles);
116+
// Import pinned items
117+
var pinnedItems = await zipFolder.GetFileAsync(App.SidebarPinnedController.JsonFileName);
118+
await pinnedItems.CopyAsync(settingsFolder, pinnedItems.Name, NameCollisionOption.ReplaceExisting);
119+
await App.SidebarPinnedController.ReloadAsync();
120+
// Import terminals config
121+
var terminals = await zipFolder.GetFileAsync(App.TerminalController.JsonFileName);
122+
await terminals.CopyAsync(settingsFolder, terminals.Name, NameCollisionOption.ReplaceExisting);
123+
// Import file tags list and DB
124+
var fileTagsList = await zipFolder.GetFileAsync(Constants.LocalSettings.FileTagSettingsFileName);
125+
string importTags = await fileTagsList.ReadTextAsync();
126+
FileTagsSettingsService.ImportSettings(importTags);
127+
var fileTagsDB = await zipFolder.GetFileAsync(Path.GetFileName(FileTagsHelper.FileTagsDbPath));
128+
string importTagsDB = await fileTagsDB.ReadTextAsync();
129+
FileTagsHelper.DbInstance.Import(importTagsDB);
67130
}
68-
catch
131+
catch (Exception ex)
69132
{
133+
App.Logger.Warn(ex, "Error importing settings");
70134
UIHelpers.CloseAllDialogs();
71135
await DialogDisplayHelper.ShowDialogAsync("SettingsImportErrorTitle".GetLocalized(), "SettingsImportErrorDescription".GetLocalized());
72136
}

Files/ViewModels/Widgets/Bundles/BundlesViewModel.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ public BundlesViewModel()
104104
AddBundleCommand = new RelayCommand(() => AddBundle(BundleNameTextInput));
105105
ImportBundlesCommand = new AsyncRelayCommand(ImportBundles);
106106
ExportBundlesCommand = new AsyncRelayCommand(ExportBundles);
107+
108+
BundlesSettingsService.OnSettingChangedEvent += BundlesSettingsService_OnSettingChangedEvent;
107109
}
108110

109111
#endregion Constructor
@@ -228,15 +230,12 @@ private async Task ImportBundles()
228230
filePicker.FileTypeFilter.Add(System.IO.Path.GetExtension(Constants.LocalSettings.BundlesSettingsFileName));
229231

230232
StorageFile file = await filePicker.PickSingleFileAsync();
231-
232233
if (file != null)
233234
{
234235
try
235236
{
236237
string data = NativeFileOperationsHelper.ReadStringFromFile(file.Path);
237-
var deserialized = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(data);
238-
BundlesSettingsService.ImportSettings(JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(data));
239-
await Load(); // Update the collection
238+
BundlesSettingsService.ImportSettings(data);
240239
}
241240
catch // Couldn't deserialize, data is corrupted
242241
{
@@ -250,7 +249,6 @@ private async Task ExportBundles()
250249
filePicker.FileTypeChoices.Add("Json File", new List<string>() { System.IO.Path.GetExtension(Constants.LocalSettings.BundlesSettingsFileName) });
251250

252251
StorageFile file = await filePicker.PickSaveFileAsync();
253-
254252
if (file != null)
255253
{
256254
NativeFileOperationsHelper.WriteStringToFile(file.Path, (string)BundlesSettingsService.ExportSettings());
@@ -261,6 +259,16 @@ private async Task ExportBundles()
261259

262260
#region Handlers
263261

262+
private async void BundlesSettingsService_OnSettingChangedEvent(object sender, EventArguments.SettingChangedEventArgs e)
263+
{
264+
switch (e.settingName)
265+
{
266+
case nameof(BundlesSettingsService.SavedBundles):
267+
await Load();
268+
break;
269+
}
270+
}
271+
264272
private void OpenPathHandle(string path, FilesystemItemType itemType, bool openSilent, bool openViaApplicationPicker, IEnumerable<string> selectItems)
265273
{
266274
OpenPathEvent?.Invoke(this, new BundlesOpenPathEventArgs(path, itemType, openSilent, openViaApplicationPicker, selectItems));
@@ -277,6 +285,8 @@ private void OpenPathInNewPaneHandle(string path)
277285
/// <param name="item"></param>
278286
private void NotifyItemRemovedHandle(BundleContainerViewModel item)
279287
{
288+
BundlesSettingsService.OnSettingChangedEvent -= BundlesSettingsService_OnSettingChangedEvent;
289+
280290
Items.Remove(item);
281291
item?.Dispose();
282292

0 commit comments

Comments
 (0)