Phase C (T2-1..T3-10): command palette, reader mode (real Readability.js, E2E), boost force-dark, screenshot, split view, vertical tabs, Glance (Alt+click), tab groups (6 colors), workspaces, speed dial, InPrivate tabs, quick find, source view, print, PiP, TTS (94 tests GREEN)

This commit is contained in:
Yun Chan 2026-08-15 15:22:44 +09:00
parent 0caa1111e7
commit 406957088f
14 changed files with 3496 additions and 7 deletions

View file

@ -162,3 +162,44 @@ public sealed class TabManager
ActivateAt(Math.Clamp(snap.ActiveIndex, 0, Math.Max(0, Tabs.Count - 1)));
}
}
// ── T2-11 탭 그룹 확장 ──
public static class TabManagerGroupExtensions
{
/// <summary>그룹 지정(null 이면 해제). 같은 그룹 탭은 인접하도록 이동.</summary>
public static void SetGroup(this TabManager m, TabItem tab, string? name, string? color)
{
if (!m.Tabs.Contains(tab)) return;
tab.GroupName = name;
tab.GroupColor = color;
if (name == null) return;
// 같은 그룹 마지막 탭 뒤로 이동
var lastIdx = -1;
for (var i = 0; i < m.Tabs.Count; i++)
if (string.Equals(m.Tabs[i].GroupName, name, StringComparison.Ordinal) && !ReferenceEquals(m.Tabs[i], tab))
lastIdx = i;
if (lastIdx >= 0) m.Move(tab, lastIdx + 1);
}
/// <summary>그룹 전체 닫기. 반환: 닫은 탭 수.</summary>
public static int CloseGroup(this TabManager m, string groupName)
{
var group = m.Tabs.Where(t => string.Equals(t.GroupName, groupName, StringComparison.Ordinal)).ToList();
foreach (var t in group) m.CloseTab(t);
return group.Count;
}
}
/// <summary>워크스페이스 스냅샷(T3-1, Zen Workspaces 패턴).</summary>
public sealed record WorkspaceSnapshot(string Name, List<string> Urls);
public static class TabManagerWorkspaceExtensions
{
/// <summary>현재 탭 세트를 워크스페이스로 캡처(현재 상태는 유지).</summary>
public static WorkspaceSnapshot CaptureWorkspace(this TabManager m, string name)
=> new(name, m.Tabs.Select(t => t.Url).ToList());
/// <summary>워크스페이스로 전환: 기존 탭 제거 후 스냅샷 복원.</summary>
public static void SwitchWorkspace(this TabManager m, WorkspaceSnapshot ws)
=> m.RestoreSession(new SessionSnapshot(ws.Urls, 0, Enumerable.Repeat(false, ws.Urls.Count).ToList()));
}