Skip to content

Profileの名前を変更可能に#1

Merged
hu-ja-ja merged 5 commits intomasterfrom
dev
Feb 11, 2026
Merged

Profileの名前を変更可能に#1
hu-ja-ja merged 5 commits intomasterfrom
dev

Conversation

@hu-ja-ja
Copy link
Owner

No description provided.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

プロファイルを「名前」ではなく安定した id で識別するように移行し、GUI 上でプロファイル名をリネーム可能にする PR です(既存の profiles.json には起動時に id を自動付与して移行)。

Changes:

  • Profileid を追加し、ロード時に欠損/重複 id を自動補完(移行)する処理を追加
  • 適用/削除/連動グループなどの参照を name ベースから id ベースに変更
  • DataGrid 上でプロファイル名の編集(LostFocus で確定)とリネーム処理、ならびに Core 側のテストを追加

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/WindowController.Core/WindowController.Core.csproj テストから internal を参照できるよう InternalsVisibleTo を追加
src/WindowController.Core/ProfileStore.cs id 移行・FindById/DeleteProfileById/リネームとユニーク名解決を追加
src/WindowController.Core/Models/Profile.cs JSON スキーマに id フィールドを追加
src/WindowController.Core.Tests/ProfileStoreTests.cs id 移行・FindById・削除・リネーム・ユニーク名解決のテストを追加
src/WindowController.App/ViewModels/MainViewModel.cs UI 側を id 参照に切替、DataGrid 名称編集→リネーム連携を追加
src/WindowController.App/SyncManager.cs sync グループのキーを profileId に変更し、ログ用の名前マップを導入
src/WindowController.App/MainWindow.xaml プロファイル名列を編集可能に変更(LostFocus で更新)
README.md id 追加とリネーム操作の説明を追記

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 450 to 456
var newName = pi.Name?.Trim();
if (string.IsNullOrEmpty(newName))
{
// Revert to current stored name
var current = _store.FindById(pi.Id);
if (current != null)
pi.Name = current.Name;
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting pi.Name = current.Name inside the PropertyChanged handler will trigger PropertyChanged again and re-enter OnProfileNameChanged, causing an extra rename/save/timestamp update (and potentially repeated status updates). Consider suppressing re-entrancy (e.g., a guard flag) or temporarily detaching the handler while reverting the value.

Suggested change
var newName = pi.Name?.Trim();
if (string.IsNullOrEmpty(newName))
{
// Revert to current stored name
var current = _store.FindById(pi.Id);
if (current != null)
pi.Name = current.Name;
// 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))
{
return;
}
var newName = pi.Name?.Trim();
if (string.IsNullOrEmpty(newName))
{
// Revert to current stored name
pi.Name = current.Name;

Copilot uses AI. Check for mistakes.
Comment on lines 468 to 473
// If the name was adjusted due to conflict, update the UI
if (finalName != newName)
pi.Name = finalName;

_syncManager.ScheduleRebuild();
StatusText = $"名前を変更しました: {finalName}";
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When finalName != newName, assigning pi.Name = finalName will re-trigger OnProfileNameChanged and call _store.RenameProfile a second time, resulting in duplicate saves and timestamp changes. Add a re-entrancy guard or a check against the store's current name before calling rename/setting the property.

Copilot uses AI. Check for mistakes.
Comment on lines +18 to 22
// profileId -> set of hwnds
private Dictionary<string, HashSet<nint>> _syncGroups = new();
// profileId -> display name (for logging)
private Dictionary<string, string> _profileNames = new();
private Dictionary<nint, int> _lastMinMaxByHwnd = new();
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When sync is disabled in UpdateHooksIfNeeded, _syncGroups and _lastMinMaxByHwnd are cleared but _profileNames is left as-is. This can leave stale name mappings around longer than needed; consider clearing _profileNames alongside _syncGroups for consistency.

Copilot uses AI. Check for mistakes.
Comment on lines 67 to 74
// 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)
Save();
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needsSave detection is based on a raw string json.Contains("\"id\": \"{p.Id}\""), which is sensitive to whitespace/formatting (e.g. older/minified JSON with "id":"..." will cause a save on every startup) and can also be fooled by unrelated occurrences. Consider detecting migration from the parsed object (missing/duplicate Ids) before normalization, or compare pre/post normalization at the object level / via re-serialization with the same options.

Copilot uses AI. Check for mistakes.
Comment on lines 151 to 160
public string? RenameProfile(string profileId, string desiredName)
{
var profile = FindById(profileId);
if (profile == null) return null;

var finalName = ResolveUniqueName(desiredName, profileId);
profile.Name = finalName;
profile.UpdatedAt = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss");
Save();
return finalName;
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RenameProfile updates UpdatedAt and writes to disk even when the resolved name equals the current name. This will unnecessarily touch profiles.json and mutate timestamps (especially since the UI can trigger rename callbacks even for programmatic reverts). Consider early-returning when finalName == profile.Name (after normalization/trim) to avoid redundant saves.

Copilot uses AI. Check for mistakes.
Comment on lines +191 to +199
foreach (var p in root.Profiles)
{
if (string.IsNullOrEmpty(p.Id) || !seenIds.Add(p.Id))
{
// Generate a new unique Id (duplicate Ids are also re-assigned)
p.Id = Guid.NewGuid().ToString("D");
seenIds.Add(p.Id);
}
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.

Copilot uses AI. Check for mistakes.

public void Dispose()
{
try { Directory.Delete(_tempDir, true); } catch { }
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Poor error handling: empty catch block.

Suggested change
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);
}

Copilot uses AI. Check for mistakes.
{
[ObservableProperty] private bool _syncMinMax;
public string Name { get; init; } = "";
[ObservableProperty] private string _name = "";
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Field '_name' can be 'readonly'.

Copilot uses AI. Check for mistakes.
@hu-ja-ja
Copy link
Owner Author

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Contributor

Copilot AI commented Feb 11, 2026

@hu-ja-ja I've opened a new pull request, #2, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 3 commits February 11, 2026 13:26
…, optimize saves

Co-authored-by: hu-ja-ja <107774991+hu-ja-ja@users.noreply.github.com>
Co-authored-by: hu-ja-ja <107774991+hu-ja-ja@users.noreply.github.com>
Fix re-entrancy and redundant saves in profile rename handlers
@hu-ja-ja hu-ja-ja merged commit 1585fb2 into master Feb 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants