Skip to content

Commit 054aee6

Browse files
committed
Import and export profiles
1 parent 017eb97 commit 054aee6

File tree

7 files changed

+151
-32
lines changed

7 files changed

+151
-32
lines changed

YMouseButtonControl.Core/Services/Profiles/ProfilesCache.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public interface IProfilesCache
2121
IObservable<IChangeSet<ProfileVm, int>> Connect();
2222
void ImportProfileFromPath(string path);
2323
void AddProfile(ProfileVm profileVm);
24-
void AddOrUpdate(ProfileVm profileVm);
2524
}
2625

2726
public class ProfilesCache : ReactiveObject, IProfilesCache, IDisposable
@@ -62,8 +61,6 @@ public bool Dirty
6261
/// </summary>
6362
public ReadOnlyObservableCollection<ProfileVm> Profiles => _profilesObsCol;
6463

65-
public void AddOrUpdate(ProfileVm profile) => _profilesSc.AddOrUpdate(profile);
66-
6764
public IObservable<IChangeSet<ProfileVm, int>> Connect() => _profilesSc.Connect();
6865

6966
public ProfileVm? CurrentProfile
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Linq;
6+
using YMouseButtonControl.Core.Services.Profiles;
7+
8+
namespace YMouseButtonControl.Core.ViewModels.Models;
9+
10+
public class ProfileVmConverter(IProfilesCache profilesCache) : JsonConverter<ProfileVm>
11+
{
12+
public override void WriteJson(JsonWriter writer, ProfileVm? value, JsonSerializer serializer)
13+
{
14+
JObject obj =
15+
new()
16+
{
17+
// Serialize the properties directly.
18+
["IsDefault"] = value!.IsDefault,
19+
["Checked"] = value.Checked,
20+
["Name"] = value.Name,
21+
["Description"] = value.Description,
22+
["WindowCaption"] = value.WindowCaption,
23+
["Process"] = value.Process,
24+
["WindowClass"] = value.WindowClass,
25+
["ParentClass"] = value.ParentClass,
26+
["MatchType"] = value.MatchType,
27+
["DisplayPriority"] = value.DisplayPriority,
28+
};
29+
30+
if (value.ButtonMappings != null)
31+
{
32+
obj["ButtonMappings"] = JToken.FromObject(value.ButtonMappings, serializer);
33+
}
34+
35+
obj.WriteTo(writer);
36+
}
37+
38+
public override ProfileVm ReadJson(
39+
JsonReader reader,
40+
Type objectType,
41+
ProfileVm? existingValue,
42+
bool hasExistingValue,
43+
JsonSerializer serializer
44+
)
45+
{
46+
JObject obj = JObject.Load(reader);
47+
48+
// Deserialize the properties directly.
49+
bool isDefault = obj["IsDefault"]!.ToObject<bool>(serializer);
50+
bool @checked = obj["Checked"]!.ToObject<bool>(serializer);
51+
string name = obj["Name"]!.ToObject<string>(serializer)!;
52+
string description = obj["Description"]?.ToObject<string>(serializer) ?? string.Empty;
53+
string windowCaption = obj["WindowCaption"]?.ToObject<string>(serializer) ?? "N/A";
54+
string process = obj["Process"]?.ToObject<string>(serializer) ?? "N/A";
55+
string windowClass = obj["WindowClass"]?.ToObject<string>(serializer) ?? "N/A";
56+
string parentClass = obj["ParentClass"]?.ToObject<string>(serializer) ?? "N/A";
57+
string matchType = obj["MatchType"]?.ToObject<string>(serializer) ?? "N/A";
58+
int displayPriority = obj["DisplayPriority"]!.ToObject<int>(serializer);
59+
60+
// Deserialize the button mappings.
61+
List<BaseButtonMappingVm> buttonMappings = [];
62+
if (obj["ButtonMappings"] != null)
63+
{
64+
buttonMappings = obj["ButtonMappings"]!.ToObject<List<BaseButtonMappingVm>>(
65+
serializer
66+
)!;
67+
}
68+
var maxBtnMappingIdInCache = profilesCache
69+
.Profiles.SelectMany(x => x.ButtonMappings)
70+
.Max(x => x.Id);
71+
foreach (var bm in buttonMappings)
72+
{
73+
bm.Id = ++maxBtnMappingIdInCache;
74+
}
75+
76+
var idForProfile = profilesCache.Profiles.Max(x => x.Id) + 1;
77+
foreach (var bm in buttonMappings)
78+
{
79+
bm.ProfileId = idForProfile;
80+
}
81+
82+
ProfileVm profileVm =
83+
new(buttonMappings)
84+
{
85+
Id = idForProfile,
86+
IsDefault = isDefault,
87+
Checked = @checked,
88+
Name = name!,
89+
Description = description,
90+
WindowCaption = windowCaption,
91+
Process = process,
92+
WindowClass = windowClass,
93+
ParentClass = parentClass,
94+
MatchType = matchType,
95+
DisplayPriority = displayPriority,
96+
};
97+
98+
return profileVm;
99+
}
100+
}

YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/ExportProfile.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@
22
using System.Linq;
33
using Newtonsoft.Json;
44
using YMouseButtonControl.Core.Services.Profiles;
5+
using YMouseButtonControl.Core.ViewModels.Models;
56

67
namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles;
78

89
public static class ExportProfile
910
{
1011
public sealed record Command(int Id, string Path);
1112

12-
public sealed class Handler(IProfilesCache profilesService)
13+
public sealed class Handler(IProfilesCache profilesCache, ProfileVmConverter profileVmConverter)
1314
{
1415
public void Execute(Command c)
1516
{
16-
var profileToExport = profilesService.Profiles.First(x => x.Id == c.Id);
17-
var jsonString = JsonConvert.SerializeObject(
18-
profileToExport,
19-
new JsonSerializerSettings
20-
{
21-
TypeNameHandling = TypeNameHandling.Auto,
22-
Formatting = Formatting.Indented,
23-
}
24-
);
17+
var profileToExport = profilesCache.Profiles.First(x => x.Id == c.Id);
18+
var settings = new JsonSerializerSettings
19+
{
20+
TypeNameHandling = TypeNameHandling.Auto,
21+
Formatting = Formatting.Indented,
22+
};
23+
settings.Converters.Add(profileVmConverter);
24+
var jsonString = JsonConvert.SerializeObject(profileToExport, settings);
2525
File.WriteAllText(c.Path, jsonString);
2626
}
2727
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.IO;
2+
using DynamicData;
3+
using Newtonsoft.Json;
4+
using YMouseButtonControl.Core.Services.Profiles;
5+
using YMouseButtonControl.Core.ViewModels.Models;
6+
7+
namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles;
8+
9+
public static class ImportProfile
10+
{
11+
public sealed record Command(string Path);
12+
13+
public sealed class Handler(IProfilesCache profilesCache, ProfileVmConverter profileVmConverter)
14+
{
15+
public void Execute(Command c)
16+
{
17+
var f = File.ReadAllText(c.Path);
18+
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
19+
settings.Converters.Add(profileVmConverter);
20+
var deserializedProfile =
21+
JsonConvert.DeserializeObject<ProfileVm>(f, settings)
22+
?? throw new JsonSerializationException("Error deserializing profile");
23+
profilesCache.ProfilesSc.AddOrUpdate(deserializedProfile);
24+
}
25+
}
26+
}

YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListHandlerRegistrations.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public static void RegisterCommon(IServiceCollection services)
1515
.AddScoped<AddProfile.Handler>()
1616
.AddScoped<RemoveProfile.Handler>()
1717
.AddScoped<ExportProfile.Handler>()
18+
.AddScoped<ImportProfile.Handler>()
1819
.AddScoped<CopyProfile.Handler>();
1920
}
2021
}

YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
using System;
22
using System.Collections.ObjectModel;
3-
using System.Diagnostics;
43
using System.Linq;
54
using System.Reactive;
65
using System.Reactive.Linq;
7-
using System.Threading.Tasks;
86
using System.Windows.Input;
97
using ReactiveUI;
10-
using YMouseButtonControl.Core.Services.Profiles;
118
using YMouseButtonControl.Core.ViewModels.Models;
129
using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm;
1310
using YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles;
@@ -20,7 +17,6 @@ public interface IProfilesListViewModel;
2017

2118
public class ProfilesListViewModel : ViewModelBase, IProfilesListViewModel
2219
{
23-
private IProfilesCache _profilesService;
2420
private ProfilesListProfileModel? _currentProfile;
2521

2622
public ICommand AddButtonCommand { get; }
@@ -37,18 +33,17 @@ public Interaction<
3733
> ShowProcessSelectorInteraction { get; }
3834

3935
public ProfilesListViewModel(
40-
IProfilesCache profilesService,
4136
ListProfiles.Handler listCacheProfilesHandler,
4237
GetCurrentProfile.Handler getCurrentProfileHandler,
4338
SetCurrentProfile.Handler setCurrentProfileHandler,
4439
RemoveProfile.Handler removeProfileHandler,
4540
IProcessSelectorDialogVmFactory processSelectorDialogVmFactory,
4641
AddProfile.Handler addProfileHandler,
4742
ExportProfile.Handler exportProfileHandler,
48-
CopyProfile.Handler copyProfileHandler
43+
CopyProfile.Handler copyProfileHandler,
44+
ImportProfile.Handler importProfileHandler
4945
)
5046
{
51-
_profilesService = profilesService;
5247
CurrentProfile = getCurrentProfileHandler.Execute();
5348
Profiles = listCacheProfilesHandler.Execute();
5449
this.WhenAnyValue(x => x.CurrentProfile)
@@ -70,7 +65,16 @@ CopyProfile.Handler copyProfileHandler
7065
});
7166
ShowExportFileDialog = new Interaction<string, string>();
7267
ShowImportFileDialog = new Interaction<Unit, string?>();
73-
ImportCommand = ReactiveCommand.CreateFromTask(OnImportClickedAsync);
68+
ImportCommand = ReactiveCommand.CreateFromTask(async () =>
69+
{
70+
var result = await ShowImportFileDialog.Handle(Unit.Default);
71+
if (string.IsNullOrWhiteSpace(result))
72+
{
73+
return;
74+
}
75+
76+
importProfileHandler.Execute(new ImportProfile.Command(result));
77+
});
7478
var exportCanExecute = this.WhenAnyValue(
7579
x => x.CurrentProfile,
7680
curProf => !curProf?.IsDefault ?? false
@@ -234,15 +238,4 @@ public ProfilesListProfileModel? CurrentProfile
234238
}
235239

236240
public ReadOnlyObservableCollection<ProfilesListProfileModel> Profiles { get; }
237-
238-
private async Task OnImportClickedAsync()
239-
{
240-
var result = await ShowImportFileDialog.Handle(Unit.Default);
241-
if (string.IsNullOrWhiteSpace(result))
242-
{
243-
return;
244-
}
245-
246-
_profilesService.ImportProfileFromPath(result);
247-
}
248241
}

YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using YMouseButtonControl.Core.Services.Theme;
99
using YMouseButtonControl.Core.ViewModels.AppViewModel;
1010
using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog;
11+
using YMouseButtonControl.Core.ViewModels.Models;
1112
using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm;
1213
using YMouseButtonControl.Core.ViewModels.ProfilesList;
1314

@@ -28,6 +29,7 @@ private static void RegisterCommonServices(IServiceCollection services)
2829
ProfilesListHandlerRegistrations.RegisterCommon(services);
2930
GlobalSettingsDialogHandlerRegistrations.RegisterCommon(services);
3031
services
32+
.AddScoped<ProfileVmConverter>()
3133
.AddScoped<IThemeService, ThemeService>()
3234
.AddScoped<IProfilesCache, ProfilesCache>()
3335
.AddScoped<ISettingsService, SettingsService>();

0 commit comments

Comments
 (0)