diff --git a/Keybinding.Test/DefaultProfileReactivationTests.cs b/Keybinding.Test/DefaultProfileReactivationTests.cs
new file mode 100644
index 0000000..e56adc2
--- /dev/null
+++ b/Keybinding.Test/DefaultProfileReactivationTests.cs
@@ -0,0 +1,76 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+
+namespace ktsu.Keybinding.Test;
+
+using ktsu.Keybinding.Core;
+using ktsu.Keybinding.Core.Models;
+
+[TestClass]
+public class DefaultProfileReactivationTests
+{
+ private string _testDataDirectory = null!;
+
+ [TestInitialize]
+ public void Setup()
+ {
+ _testDataDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
+ Directory.CreateDirectory(_testDataDirectory);
+ }
+
+ [TestCleanup]
+ public void Cleanup()
+ {
+ if (Directory.Exists(_testDataDirectory))
+ {
+ Directory.Delete(_testDataDirectory, recursive: true);
+ }
+ }
+
+ [TestMethod]
+ public async Task CreateDefaultProfile_AfterActiveProfileWasDeleted_ActivatesExistingDefaultOnNextLaunch()
+ {
+ {
+ using KeybindingManager manager = new(_testDataDirectory);
+ await manager.InitializeAsync().ConfigureAwait(false);
+ manager.CreateDefaultProfile();
+ manager.Profiles.CreateProfile("vim", "Vim");
+ Assert.IsTrue(manager.Profiles.SetActiveProfile("vim"));
+ Assert.IsTrue(manager.Profiles.DeleteProfile("vim"));
+ await manager.SaveAsync().ConfigureAwait(false);
+ }
+
+ {
+ using KeybindingManager manager = new(_testDataDirectory);
+ await manager.InitializeAsync().ConfigureAwait(false);
+ manager.CreateDefaultProfile();
+ manager.RegisterCommands([new Command("file.save", "Save")]);
+
+ Assert.AreEqual("default", manager.Profiles.GetActiveProfile()?.Id);
+ Assert.IsTrue(manager.Keybindings.BindChord("file.save", Chord.Parse("Ctrl+S")));
+ Assert.AreEqual("file.save", manager.Keybindings.ExecuteChord(Chord.Parse("Ctrl+S")));
+ }
+ }
+
+ [TestMethod]
+ public void CreateDefaultProfile_ExistingDefaultWhileAnotherIsActive_LeavesActiveProfileAlone()
+ {
+ using KeybindingManager manager = new(_testDataDirectory);
+ manager.CreateDefaultProfile();
+ manager.Profiles.CreateProfile("vim", "Vim");
+ Assert.IsTrue(manager.Profiles.SetActiveProfile("vim"));
+
+ Assert.IsNull(manager.CreateDefaultProfile());
+ Assert.AreEqual("vim", manager.Profiles.GetActiveProfile()?.Id);
+ }
+
+ [TestMethod]
+ public void CreateDefaultProfile_ExistingDefaultWithDoNotActivate_LeavesNoActiveProfile()
+ {
+ using KeybindingManager manager = new(_testDataDirectory);
+ manager.CreateDefaultProfile();
+ manager.Profiles.ClearActiveProfile();
+
+ Assert.IsNull(manager.CreateDefaultProfile(activation: ProfileActivation.DoNotActivate));
+ Assert.IsNull(manager.Profiles.GetActiveProfile());
+ }
+}
diff --git a/Keybinding/KeybindingManager.cs b/Keybinding/KeybindingManager.cs
index b73c08d..e1b2a6a 100644
--- a/Keybinding/KeybindingManager.cs
+++ b/Keybinding/KeybindingManager.cs
@@ -150,7 +150,11 @@ public async Task SaveAsync()
///
/// The ID for the default profile
/// The name for the default profile
- /// Whether to set as the active profile
+ ///
+ /// Whether to set as the active profile. When the profile already exists, it is activated only if no
+ /// profile is active, so a startup call recovers from a deleted or unset active profile without
+ /// overriding the one the user chose.
+ ///
/// The created profile, or null if a profile already exists with the given ID
public Profile? CreateDefaultProfile(string profileId = "default", string profileName = "Default", ProfileActivation activation = ProfileActivation.Activate)
{
@@ -158,6 +162,11 @@ public async Task SaveAsync()
if (Profiles.ProfileExists(profileId))
{
+ if (activation == ProfileActivation.Activate && Profiles.GetActiveProfile() is null)
+ {
+ Profiles.SetActiveProfile(profileId);
+ }
+
return null;
}