-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKeybindingManager.cs
More file actions
211 lines (178 loc) · 6.37 KB
/
Copy pathKeybindingManager.cs
File metadata and controls
211 lines (178 loc) · 6.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright (c) 2023-2026 ktsu-dev contributors
namespace ktsu.Keybinding.Core;
using ktsu.Keybinding.Core.Contracts;
using ktsu.Keybinding.Core.Helpers;
using ktsu.Keybinding.Core.Models;
using ktsu.Keybinding.Core.Services;
/// <summary>
/// Main facade class for managing keybindings, commands, and profiles
/// </summary>
public sealed class KeybindingManager : IDisposable
{
private bool _disposed;
/// <summary>
/// Initializes a new instance of the <see cref="KeybindingManager"/> class with default services
/// </summary>
/// <param name="dataDirectory">Directory to store keybinding data</param>
public KeybindingManager(string dataDirectory)
: this(
new CommandRegistry(),
new ProfileManager(),
new JsonKeybindingRepository(dataDirectory))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="KeybindingManager"/> class with custom services
/// </summary>
/// <param name="commandRegistry">The command registry service</param>
/// <param name="profileManager">The profile manager service</param>
/// <param name="repository">The keybinding repository</param>
public KeybindingManager(
ICommandRegistry commandRegistry,
IProfileManager profileManager,
IKeybindingRepository repository)
{
Commands = Ensure.NotNull(commandRegistry);
Profiles = Ensure.NotNull(profileManager);
Repository = Ensure.NotNull(repository);
Keybindings = new KeybindingService(Commands, Profiles);
}
/// <summary>
/// Gets the command registry for managing commands
/// </summary>
public ICommandRegistry Commands { get; }
/// <summary>
/// Gets the profile manager for managing profiles
/// </summary>
public IProfileManager Profiles { get; }
/// <summary>
/// Gets the keybinding service for managing keybindings
/// </summary>
public IKeybindingService Keybindings { get; }
/// <summary>
/// Gets the repository for persistence operations
/// </summary>
public IKeybindingRepository Repository { get; }
/// <summary>
/// Initializes the keybinding manager and loads persisted data
/// </summary>
/// <returns>Task representing the async operation</returns>
public async Task InitializeAsync()
{
DisposalHelper.ThrowIfDisposed(_disposed, this);
await Repository.InitializeAsync().ConfigureAwait(false);
// Load commands
IReadOnlyCollection<Command> commands = await Repository.LoadCommandsAsync().ConfigureAwait(false);
foreach (Command command in commands)
{
Commands.RegisterCommand(command);
}
// Load profiles
IReadOnlyCollection<Profile> profiles = await Repository.LoadAllProfilesAsync().ConfigureAwait(false);
foreach (Profile profile in profiles)
{
Profiles.CreateProfile(profile);
}
// Load active profile
string? activeProfileId = await Repository.LoadActiveProfileAsync().ConfigureAwait(false);
if (!string.IsNullOrEmpty(activeProfileId) && Profiles.ProfileExists(activeProfileId))
{
Profiles.SetActiveProfile(activeProfileId);
}
}
/// <summary>
/// Saves all data to persistent storage
/// </summary>
/// <returns>Task representing the async operation</returns>
public async Task SaveAsync()
{
DisposalHelper.ThrowIfDisposed(_disposed, this);
// Save commands
IReadOnlyCollection<Command> commands = Commands.GetAllCommands();
await Repository.SaveCommandsAsync(commands).ConfigureAwait(false);
// Save profiles using batch helper
IReadOnlyCollection<Profile> profiles = Profiles.GetAllProfiles();
await AsyncBatchHelper.ForEachAsync(profiles, Repository.SaveProfileAsync).ConfigureAwait(false);
// Save active profile
Profile? activeProfile = Profiles.GetActiveProfile();
await Repository.SaveActiveProfileAsync(activeProfile?.Id).ConfigureAwait(false);
}
/// <summary>
/// Creates a default profile if none exist
/// </summary>
/// <param name="profileId">The ID for the default profile</param>
/// <param name="profileName">The name for the default profile</param>
/// <param name="activation">Whether to set as the active profile</param>
/// <returns>The created profile, or null if a profile already exists with the given ID</returns>
public Profile? CreateDefaultProfile(string profileId = "default", string profileName = "Default", ProfileActivation activation = ProfileActivation.Activate)
{
DisposalHelper.ThrowIfDisposed(_disposed, this);
if (Profiles.ProfileExists(profileId))
{
return null;
}
Profile profile = new(profileId, profileName, "Default keybinding profile");
if (Profiles.CreateProfile(profile))
{
if (activation == ProfileActivation.Activate)
{
Profiles.SetActiveProfile(profileId);
}
return profile;
}
return null;
}
/// <summary>
/// Registers a batch of commands
/// </summary>
/// <param name="commands">The commands to register</param>
/// <returns>Number of commands successfully registered</returns>
public int RegisterCommands(IEnumerable<Command> commands)
{
DisposalHelper.ThrowIfDisposed(_disposed, this);
Ensure.NotNull(commands);
return OperationHelper.ExecuteWithCount(commands, Commands.RegisterCommand, shouldContinueOnError: false);
}
/// <summary>
/// Sets multiple chord bindings for the active profile
/// </summary>
/// <param name="chords">Dictionary of command ID to chord mappings</param>
/// <returns>Number of chord bindings successfully set</returns>
public int SetChords(IReadOnlyDictionary<string, Chord> chords)
{
DisposalHelper.ThrowIfDisposed(_disposed, this);
Ensure.NotNull(chords);
Profile activeProfile = Profiles.GetActiveProfile() ?? throw new InvalidOperationException("No active profile is set");
return OperationHelper.ExecuteWithCount(chords, Keybindings.BindChord);
}
/// <summary>
/// Gets a summary of the current keybinding state
/// </summary>
/// <returns>Summary information</returns>
public KeybindingSummary GetSummary()
{
DisposalHelper.ThrowIfDisposed(_disposed, this);
Profile? activeProfile = Profiles.GetActiveProfile();
int totalCommands = Commands.GetAllCommands().Count;
int totalProfiles = Profiles.GetAllProfiles().Count;
int activeKeybindings = activeProfile?.Chords.Count ?? 0;
return new KeybindingSummary
{
TotalCommands = totalCommands,
TotalProfiles = totalProfiles,
ActiveProfileId = activeProfile?.Id,
ActiveProfileName = activeProfile?.Name,
ActiveKeybindings = activeKeybindings
};
}
/// <summary>
/// Disposes the keybinding manager
/// </summary>
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
}
}
}