Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/WindowController.App/SyncManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ public void UpdateHooksIfNeeded(bool skipRebuild = false)
{
_hookManager.Uninstall();
_syncGroups.Clear();
_profileNames.Clear();
_lastMinMaxByHwnd.Clear();
}
}
Expand Down
40 changes: 37 additions & 3 deletions src/WindowController.App/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public partial class MainViewModel : ObservableObject
private readonly SyncManager _syncManager;
private readonly AppSettingsStore _appSettings;
private readonly ILogger _log;
private bool _isUpdatingProfileName;

[ObservableProperty] private string _statusText = "";
[ObservableProperty] private string _profileName = "";
Expand Down Expand Up @@ -447,13 +448,36 @@ public void ReloadProfiles()

private void OnProfileNameChanged(ProfileItem pi)
{
// Prevent re-entrancy when we programmatically update pi.Name
if (_isUpdatingProfileName)
return;

// Get the current profile from the store
var current = _store.FindById(pi.Id);
if (current == null)
{
StatusText = "プロファイルが見つかりません。";
return;
}

// If the name has not actually changed compared to the store, ignore.
if (string.Equals(current.Name, pi.Name, StringComparison.Ordinal))
return;


var newName = pi.Name?.Trim();
if (string.IsNullOrEmpty(newName))
{
// Revert to current stored name
var current = _store.FindById(pi.Id);
if (current != null)
_isUpdatingProfileName = true;
try
{
pi.Name = current.Name;
}
finally
{
_isUpdatingProfileName = false;
}
StatusText = "プロファイル名を空にすることはできません。";
return;
}
Expand All @@ -467,7 +491,17 @@ private void OnProfileNameChanged(ProfileItem pi)

// If the name was adjusted due to conflict, update the UI
if (finalName != newName)
pi.Name = finalName;
{
_isUpdatingProfileName = true;
try
{
pi.Name = finalName;
}
finally
{
_isUpdatingProfileName = false;
}
}

_syncManager.ScheduleRebuild();
StatusText = $"名前を変更しました: {finalName}";
Expand Down
9 changes: 8 additions & 1 deletion src/WindowController.Core.Tests/ProfileStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ public ProfileStoreTests()

public void Dispose()
{
try { Directory.Delete(_tempDir, true); } catch { }
try
{
Directory.Delete(_tempDir, true);
}
catch (Exception ex)
{
_log.Warning(ex, "Failed to delete temporary test directory {TempDir}", _tempDir);
}
}

private string TempFile() => Path.Combine(_tempDir, "profiles.json");
Expand Down
21 changes: 14 additions & 7 deletions src/WindowController.Core/ProfileStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,16 @@ public void Load()
{
var json = File.ReadAllText(_filePath);
var parsed = JsonSerializer.Deserialize<ProfilesRoot>(json, JsonOptions);

// Detect migration need before normalization
bool needsMigration = parsed != null && parsed.Profiles.Any(p =>
string.IsNullOrEmpty(p.Id) ||
parsed.Profiles.Count(x => x.Id == p.Id) > 1);

var normalized = NormalizeData(parsed ?? new ProfilesRoot());

// Check if any profile received a new Id during normalization (migration)
bool needsSave = json != null && normalized.Profiles.Any(p =>
!json.Contains($"\"id\": \"{p.Id}\"", StringComparison.Ordinal));

Data = normalized;

if (needsSave)
if (needsMigration)
Save();
}
catch (Exception ex)
Expand Down Expand Up @@ -153,7 +154,13 @@ public bool DeleteProfileById(string id)
var profile = FindById(profileId);
if (profile == null) return null;

var finalName = ResolveUniqueName(desiredName, profileId);
var trimmed = desiredName.Trim();
var finalName = ResolveUniqueName(trimmed, profileId);

// Skip save if the name hasn't actually changed
if (finalName == profile.Name)
return finalName;

profile.Name = finalName;
profile.UpdatedAt = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss");
Save();
Expand Down