From f380518919ee0f8305c8f0ccb8d5986913913d9c Mon Sep 17 00:00:00 2001 From: Yun Chan Date: Sun, 16 Aug 2026 08:46:54 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8D=B0=EC=8A=A4=ED=81=AC=ED=86=B1=20T3=20?= =?UTF-8?q?=EC=9E=94=EC=97=AC=20=EC=99=84=EC=84=B1=20+=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=ED=8F=B4=EB=A6=AC=EC=8B=9C:=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=9D=BC=EC=9A=B0=ED=8C=85(WorkspaceRouti?= =?UTF-8?q?ngRules=20=EC=9E=90=EB=8F=99=20=EC=9B=8C=ED=81=AC=EC=8A=A4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=84=ED=99=98),=20=ED=83=AD?= =?UTF-8?q?=20=EC=95=84=EC=B9=B4=EC=9D=B4=EB=B8=8C(TabArchive=20=EC=98=81?= =?UTF-8?q?=EC=86=8D=C2=B7=ED=8C=94=EB=A0=88=ED=8A=B8=20=EB=B3=B5=EA=B5=AC?= =?UTF-8?q?),=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=95=A1=EC=85=98(=ED=9D=91?= =?UTF-8?q?=EB=B0=B1/=EC=84=B8=ED=94=BC=EC=95=84=20=ED=95=84=ED=84=B0),=20?= =?UTF-8?q?=EB=85=B8=ED=8A=B8=20=ED=8C=A8=EB=84=90(NotesStore+=ED=94=8C?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EC=95=84=EC=9B=83),=20=EC=BB=B4=ED=8C=A9?= =?UTF-8?q?=ED=8A=B8=20=EB=AA=A8=EB=93=9C(=ED=81=AC=EB=A1=AC=20=EC=88=A8?= =?UTF-8?q?=EA=B9=80+=EC=97=A3=EC=A7=80=20=ED=98=B8=EB=B2=84).=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC:=20=ED=95=9C=EA=B5=AD=EC=96=B4=20=ED=8F=B0?= =?UTF-8?q?=ED=8A=B8=20=ED=8F=B4=EB=B0=B1,=20=EC=95=94=EC=8B=9C=20?= =?UTF-8?q?=ED=8F=B0=ED=8A=B8=20=ED=86=B5=EC=9D=BC,=20=EB=8B=A4=ED=81=AC?= =?UTF-8?q?=20=ED=88=B4=ED=8C=81,=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=8C=80=EB=B9=84=20=EC=83=81=ED=96=A5.=20UpdateNavState=20dis?= =?UTF-8?q?pose=20=EA=B0=80=EB=93=9C.=20164/164=20GREEN=20+=20=EC=8B=A4?= =?UTF-8?q?=EC=B0=BD=20=EC=8A=A4=ED=81=AC=EB=A6=B0=EC=83=B7=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IMPLEMENTATION_AUDIT.md | 14 +- .../Browser/Features/CommandPalette.cs | 21 ++- VideoDownloader.App/MainWindow.xaml | 24 ++- VideoDownloader.App/MainWindow.xaml.cs | 159 +++++++++++++++++- VideoDownloader.App/Themes/Dark.xaml | 6 +- VideoDownloader.App/Themes/Light.xaml | 4 +- VideoDownloader.App/Themes/Shared.xaml | 17 +- VideoDownloader.Browser/NotesStore.cs | 63 +++++++ VideoDownloader.Browser/TabArchive.cs | 63 +++++++ .../WorkspaceRoutingRules.cs | 65 +++++++ .../Browser/DesktopRemainderTests.cs | 130 ++++++++++++++ .../E2E/MainWindowSmokeE2ETests.cs | 52 +++++- 12 files changed, 594 insertions(+), 24 deletions(-) create mode 100644 VideoDownloader.Browser/NotesStore.cs create mode 100644 VideoDownloader.Browser/TabArchive.cs create mode 100644 VideoDownloader.Browser/WorkspaceRoutingRules.cs create mode 100644 VideoDownloader.Tests/Browser/DesktopRemainderTests.cs diff --git a/IMPLEMENTATION_AUDIT.md b/IMPLEMENTATION_AUDIT.md index c077b3f..3025a27 100644 --- a/IMPLEMENTATION_AUDIT.md +++ b/IMPLEMENTATION_AUDIT.md @@ -58,7 +58,7 @@ | 항목 | 구현 | 증거 | |---|---|---| | T2-10 미디어 재생목록 | ✅ 감지 미디어 자동 적재, 플라이아웃, 플레이어 창(native+hls.js+dash.js), 자동 다음, JSON 영속 | `MediaPlaylist.cs` · `PlayerWindow.cs` + 테스트 | -| T3-1 워크스페이스 | ✅ 저장/전환 | `TabManagerWorkspaceExtensions` + 테스트 | +| T3-1 워크스페이스 + 도메인 라우팅 | ✅ 저장/전환 + WorkspaceRoutingRules(도메인→워크스페이스, 주소창 이동 시 자동 전환, 팔레트로 규칙 등록) | `TabManagerWorkspaceExtensions` + `DesktopRemainderTests` 라우팅 2건(www/서브도메인 매칭·영속) | | T3-3 컨테이너/InPrivate | ✅ IsInPrivateModeEnabled 탭 | `OpenInPrivateTab` | | T3-4 빠른 찾기 `/` | ✅ | `MainWindow` 단축키 | | T3-5 컨텍스트 메뉴 전면 커스터마이징 | ✅ WPF 메뉴 + SelectedCommandId | `TabViewService` | @@ -75,11 +75,15 @@ | T3-14 추적 방지 카운터 | ✅ TrackerBlocklist(20개 도메인, 서브도메인 매칭) + WebResourceRequested 차단(204) + TrackerCounter + 실드 배지·도메인 팝업 | `TrackerBlockTests` 8건 + E2E(실제 WebView2 에서 2개 스크립트 차단·집계, 정상 도메인 통과) | | T3-15 주소창 진행 바 + 파라미터 제거 복사 | ✅ NavProgressTracker(전 탭 집계 INPC) → 주소창 하단 인디케이터 + 주소창 우클릭 "파라미터 제거 후 복사"(UrlCleaner) | `UrlCleanerTests`/`NavProgressTrackerTests` 13건 | -### T3 중 명시적 미구현 (계획 내 후순위/선택) +### 3차 완성 (T3 잔여 + 스타일) -- T3-2 Auto-Archive 캐던스 — 닫힘 스택(25개)+복원이 커버(아카이브 자동화는 미차용) -- T3-12 노트 패널 — 계획 자체가 "후순위" 명시 -- T3-13 컴팩트 모드 — F11 전체화면이 동등 커버 +| 항목 | 구현 | 증거 | +|---|---|---| +| T3-2 탭 아카이브 | ✅ TabArchive(닫힘 이력 JSON 영속, 500 상한, 연속 중복 제목 갱신, 검색) + 탭 닫힘 배선 + 팔레트 "아카이브에서 열기" | `DesktopRemainderTests` 3건 + 스모크 E2E(URL 탭 닫음 → 아카이브 기록 실증) | +| T3-6 페이지 액션 | ✅ BoostSettings.PageFilter(흑백/세피아) → CSS 필터 주입, 팔레트 명령 | `DesktopRemainderTests` 3건(RED→GREEN) + 스모크 E2E(로컬 HTTP 문서에서 적용→부스트 저장 실증) | +| T3-12 노트 패널 | ✅ NotesStore(추가·검색·삭제·영속) + 노트 플라이아웃(Ctrl+Alt+N) + "현재 페이지 추가" | `DesktopRemainderTests` 2건 + 스모크 E2E + 실창 스크린샷 | +| T3-13 컴팩트 모드 | ✅ Ctrl+Shift+M 크롬 자동 숨김 + 상단 엣지(4px) 호버 복원 | 스모크 E2E(행 높이 0→복원) + 실창 스크린샷 | +| 스타일 폴리시 | ✅ 폰트 폴백(한국어 맑은 고딕 포함) + 암시 TextBlock 폰트 통일 + 다크 ToolTip + 텍스트 계층 대비 상향(Secondary/Muted/Border) + 상태바 가독성 + 다이얼 페이지 타이포 | 실창 스크린샷 검증(다이얼/노트/컴팩트) | ### 재구성 (사용자 지시 "근원부터 뜯어고쳐") diff --git a/VideoDownloader.App/Browser/Features/CommandPalette.cs b/VideoDownloader.App/Browser/Features/CommandPalette.cs index 5e44e7c..18a46de 100644 --- a/VideoDownloader.App/Browser/Features/CommandPalette.cs +++ b/VideoDownloader.App/Browser/Features/CommandPalette.cs @@ -48,8 +48,11 @@ public sealed class CommandPalette public void Execute(PaletteCommand command) => command.Execute(); } -/// 사이트별 부스트 설정(T2-7, Zen/Arc Boosts 패턴). -public sealed record BoostSettings(bool ForceDark, string CustomCss); +/// 페이지 액션 필터(T3-6, Vivaldi Page Actions — Boost 통합). +public enum PageFilter { None, Grayscale, Sepia } + +/// 사이트별 부스트 설정(T2-7, Zen/Arc Boosts 패턴) + 페이지 액션 필터(T3-6). +public sealed record BoostSettings(bool ForceDark, string CustomCss, PageFilter Filter = PageFilter.None); /// 도메인별 부스트 영속 저장. public sealed class BoostStore @@ -77,11 +80,11 @@ public sealed class BoostStore return host != null && _map.TryGetValue(host, out var v) ? v : new BoostSettings(false, ""); } - public void Set(string? url, bool forceDark, string css) + public void Set(string? url, bool forceDark, string css, PageFilter filter = PageFilter.None) { var host = Normalize(url); if (host == null) return; - _map[host] = new BoostSettings(forceDark, css); + _map[host] = new BoostSettings(forceDark, css, filter); try { Directory.CreateDirectory(Path.GetDirectoryName(_path)!); @@ -110,7 +113,7 @@ public static class BoostCssBuilder { public static string BuildScript(string? url, BoostSettings settings) { - if (!settings.ForceDark && string.IsNullOrWhiteSpace(settings.CustomCss)) return ""; + if (!settings.ForceDark && settings.Filter == PageFilter.None && string.IsNullOrWhiteSpace(settings.CustomCss)) return ""; var css = ""; if (settings.ForceDark) { @@ -119,6 +122,14 @@ html { filter: invert(1) hue-rotate(180deg); background: #fff; } img, video, picture, canvas, svg, iframe, embed, object { filter: invert(1) hue-rotate(180deg); } """; } + else if (settings.Filter == PageFilter.Grayscale) // T3-6 페이지 액션 + { + css += "html { filter: grayscale(1); }"; + } + else if (settings.Filter == PageFilter.Sepia) + { + css += "html { filter: sepia(0.7); }"; + } if (!string.IsNullOrWhiteSpace(settings.CustomCss)) css += settings.CustomCss + "\n"; var js = $$""" (function(){ try { var s = document.createElement('style'); s.id = 'vd-boost'; s.textContent = {{JsonSerializer.Serialize(css)}}; (document.head || document.documentElement).appendChild(s); } catch(e){} })(); diff --git a/VideoDownloader.App/MainWindow.xaml b/VideoDownloader.App/MainWindow.xaml index c4bfb60..71dd1fb 100644 --- a/VideoDownloader.App/MainWindow.xaml +++ b/VideoDownloader.App/MainWindow.xaml @@ -153,7 +153,7 @@ - + @@ -459,7 +459,7 @@ - @@ -550,6 +550,26 @@ + + + + + + + +