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:
parent
0caa1111e7
commit
406957088f
14 changed files with 3496 additions and 7 deletions
|
|
@ -38,6 +38,12 @@ public sealed class TabItem : INotifyPropertyChanged
|
|||
private bool _isLoading;
|
||||
public bool IsLoading { get => _isLoading; set => Set(ref _isLoading, value); }
|
||||
|
||||
private string? _groupName; // T2-11 탭 그룹
|
||||
public string? GroupName { get => _groupName; set => Set(ref _groupName, value); }
|
||||
|
||||
private string? _groupColor;
|
||||
public string? GroupColor { get => _groupColor; set => Set(ref _groupColor, value); }
|
||||
|
||||
/// <summary>마지막 활성 시각(탭 절전 판정용)</summary>
|
||||
public DateTime LastActivated { get; set; } = DateTime.UtcNow;
|
||||
|
||||
|
|
@ -52,6 +58,13 @@ public sealed class TabItem : INotifyPropertyChanged
|
|||
/// <summary>탭별 페이지 내 검색 세션 (CoreWebView2 바인딩).</summary>
|
||||
public FindSession? FindSession { get; set; }
|
||||
|
||||
/// <summary>T2-4 리더 모드 진입 여부.</summary>
|
||||
public bool IsReader { get; set; }
|
||||
/// <summary>T3-3 InPrivate(사생활 보호) 탭 여부.</summary>
|
||||
public bool IsPrivate { get; set; }
|
||||
/// <summary>리더 진입 전 원본 URL(복귀용).</summary>
|
||||
public string? ReaderOriginalUrl { get; set; }
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
private void Set<T>(ref T field, T value, [CallerMemberName] string? name = null)
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue