From 960a695c7e4b8aed562f397ee94c8495ca55fbcf Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Wed, 30 Sep 2026 16:18:58 +0900 Subject: [PATCH] =?UTF-8?q?v1.1.0:=20=EC=9B=B9=20=EB=B8=8C=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=EC=A0=80,=20=EC=9E=90=EB=A7=89=20=EB=B2=88=EC=97=AD,?= =?UTF-8?q?=20=EC=9E=91=EC=97=85=20=EB=8C=80=EA=B8=B0=EC=97=B4,=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EB=B6=84=ED=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 앱 안 브라우저 (Edge WebView2): 동영상 페이지 [다운로드], 즐겨찾기 (표시줄 · 폴더 · 실행 취소 · Chrome/Edge/Whale 가져오기), 로그인 쿠키를 cookies.txt 로 내보내 yt-dlp 와 공유 - 자막 번역: 있는 자막을 NLLB 로 번역해 jj_mkv\파일명_언어코드.srt 로 저장하고 MKV 자막에 추가, 인터넷 자막을 받을 때 한국어로 함께 번역 - 작업 대기열: AI 자막 · 자막 번역 · MKV 만들기를 차례대로 실행 - 브라우저 화면 분할 [작업 현황]: 작업 · 편집 목록 · 다운로드 진행 - 다 받은 동영상을 편집 목록에 자동 추가 (설정) - 설정: 시작 화면, 홈 주소, 외부 브라우저 Co-Authored-By: Claude Opus 5.5 --- README.md | 8 +- THIRD_PARTY_NOTICES.txt | 4 + integration_test/browser_real_test.dart | 111 +++ integration_test/translate_split_test.dart | 104 +++ lib/app/app_controller.dart | 209 ++++- lib/app/bookmarks_controller.dart | 124 +++ lib/app/download_manager.dart | 35 + lib/app/settings.dart | 46 +- lib/core/bookmarks.dart | 210 +++++ lib/core/download_detect.dart | 58 +- lib/core/web_address.dart | 26 + lib/main.dart | 23 +- lib/platform/windows/desktop_shell.dart | 9 + lib/platform/windows/shell_integration.dart | 32 + lib/services/app_shell.dart | 10 + lib/services/platform_services.dart | 6 +- lib/ui/browser_page.dart | 859 ++++++++++++++++++ lib/ui/home_page.dart | 59 +- lib/ui/settings_page.dart | 63 +- lib/ui/subtitle_search_dialog.dart | 23 +- lib/ui/translate_dialog.dart | 108 +++ lib/ui/work_panel.dart | 236 +++++ pubspec.lock | 64 ++ pubspec.yaml | 3 +- test/ai_test.dart | 58 ++ test/browser_test.dart | 275 ++++++ .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 28 files changed, 2723 insertions(+), 44 deletions(-) create mode 100644 integration_test/browser_real_test.dart create mode 100644 integration_test/translate_split_test.dart create mode 100644 lib/app/bookmarks_controller.dart create mode 100644 lib/core/bookmarks.dart create mode 100644 lib/core/web_address.dart create mode 100644 lib/ui/browser_page.dart create mode 100644 lib/ui/translate_dialog.dart create mode 100644 lib/ui/work_panel.dart create mode 100644 test/browser_test.dart diff --git a/README.md b/README.md index 3382fa1..9a4d085 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,13 @@ | **자막 편집** | SRT · SMI · ASS · VTT · 내장 자막 편집, 문자셋 변환(UTF-8 · CP949 · Shift-JIS · GBK · UTF-16) | | **싱크 맞추기** | 영상을 보면서 편집, 타임라인에서 끌어서 이동·길이 조절, "선택 줄부터 여기로 맞추기" | | **AI 자막** | Whisper 음성인식 → `파일명_AI.srt`, NLLB 번역 → `파일명_ko.srt` · `_en` · `_ja` … (200개 언어) | +| **자막 번역** | 이미 있는 자막(예: 영어)을 원하는 언어로 번역해 MKV 에 추가. 인터넷에서 받은 자막도 한국어로 함께 번역 | | **인터넷 자막 찾기** | OpenSubtitles.com 검색 (영상 해시로 "이 파일용" 자막 우선) | | **동영상 플레이어** | 재생 목록, 전체 화면, 팝업(항상 위), 원본의 0.5·1·2·4배, 자막·음성 트랙 선택, 속도 | | **탐색기 연결** | 오른쪽 클릭 "JJ_MKVMaker 로 재생" / "JJ_MKVMaker 로 자막 만들기", 끌어다 놓기 | -| **다운로드** | Ctrl+C 로 복사한 YouTube 주소 → yt-dlp, 마그넷 · .torrent → aria2 (백그라운드, 트레이) | +| **다운로드** | Ctrl+C 로 복사한 YouTube 주소 → yt-dlp, 마그넷 · .torrent → aria2 (백그라운드, 트레이). 다 받은 영상은 편집 목록에 자동 추가 | +| **웹 브라우저** | 앱 안 브라우저(Edge WebView2)로 보다가 [다운로드], 즐겨찾기(Chrome · Edge · Whale 에서 가져오기), 로그인 쿠키를 yt-dlp 와 공유 | +| **작업 대기열 · 화면 분할** | AI 자막 · 번역 · MKV 만들기를 차례로 백그라운드 실행, 브라우저 옆 [작업 현황] 에서 진행 확인 | ## 실행 @@ -52,11 +55,12 @@ OpenSubtitles 의 무료 API 키가 필요합니다. |---|---| | 플레이어 | Space 재생/정지 · ←/→ 10초 · Shift+←/→ 1분 · ↑/↓ 음량 · F 전체 화면 · Esc 나가기 · N/P 다음/이전 · M 음소거 · S 자막 · L 재생 목록 | | 자막 편집 | Ctrl+Space 재생/정지 · Alt+←/→ 1초 · Alt+Shift+←/→ 0.1초 · F7 새 줄 · F8 선택 줄 재생 · F9 시작=현재 · F10 끝=현재 | +| 브라우저 | Ctrl+L 주소창 · F5 새로고침 · Alt+←/→ 뒤로/앞으로 · Ctrl+D 즐겨찾기 · Ctrl+Shift+B 즐겨찾기 관리 · Ctrl+Shift+J 작업 현황 | | 어디서나 | Ctrl+Shift+X 창 보이기 (환경 설정에서 변경) | ## 소스에서 빌드 -필요: Flutter 3.47+, Visual Studio 2022 Build Tools (C++ 데스크톱), Windows 개발자 모드 +필요: Flutter 3.47+, Visual Studio 2022 Build Tools (C++ 데스크톱), Windows 개발자 모드, PATH 에 `nuget.exe` (앱 안 브라우저 WebView2 빌드용) ```powershell git clone <이 저장소> diff --git a/THIRD_PARTY_NOTICES.txt b/THIRD_PARTY_NOTICES.txt index ff0dd8b..0940cb7 100644 --- a/THIRD_PARTY_NOTICES.txt +++ b/THIRD_PARTY_NOTICES.txt @@ -23,6 +23,10 @@ JJ_MKVMaker - 포함된 오픈 소스 구성 요소 및 라이선스 고지 - onnxruntime (Dart) MIT https://pub.dev/packages/onnxruntime - window_manager, tray_manager, hotkey_manager, screen_retriever, nativeapi MIT https://github.com/leanflutter +- flutter_inappwebview Apache-2.0 https://pub.dev/packages/flutter_inappwebview +- Microsoft Edge WebView2 SDK (WebView2Loader.dll) + BSD 3-Clause (Microsoft) https://www.nuget.org/packages/Microsoft.Web.WebView2 + 앱 안 브라우저는 Windows 에 설치된 Edge WebView2 런타임을 사용합니다 (Windows 11 기본 포함). - desktop_drop Apache-2.0 https://pub.dev/packages/desktop_drop - file_picker MIT https://pub.dev/packages/file_picker - charset Apache-2.0 https://pub.dev/packages/charset diff --git a/integration_test/browser_real_test.dart b/integration_test/browser_real_test.dart new file mode 100644 index 0000000..69e25ca --- /dev/null +++ b/integration_test/browser_real_test.dart @@ -0,0 +1,111 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:jj_mkvmaker/app/app_controller.dart'; +import 'package:jj_mkvmaker/app/bookmarks_controller.dart'; +import 'package:jj_mkvmaker/app/download_manager.dart'; +import 'package:jj_mkvmaker/core/download_detect.dart'; +import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart'; +import 'package:jj_mkvmaker/platform/windows/process_media_tool.dart'; +import 'package:jj_mkvmaker/platform/windows/ytdlp_backend.dart'; +import 'package:jj_mkvmaker/services/platform_services.dart'; +import 'package:jj_mkvmaker/ui/browser_page.dart'; +import 'package:path/path.dart' as p; + +/// 실제 Edge(WebView2): 페이지 열기 · 동영상 감지 · 쿠키 저장 → yt-dlp 가 같은 쿠키를 읽는지 +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('앱 안 브라우저 → 쿠키 → yt-dlp', (tester) async { + final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0); + server.listen((req) async { + req.response + ..headers.contentType = ContentType.html + ..headers.add('Set-Cookie', 'jjserver=ok; Max-Age=3600; Path=/') + ..write('JJ 테스트' + '' + ''); + await req.response.close(); + }); + final url = 'http://127.0.0.1:${server.port}/'; + final dataDir = Directory.systemTemp.createTempSync('jj_webview_').path; + + final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); + c.settings.webViewDataDir = dataDir; + final bm = BookmarksController(p.join(dataDir, 'bm.json')); + final d = DownloadManager(backends: const [], settings: () => c.settings, readClipboard: () async => null); + + await tester.pumpWidget(MaterialApp(home: BrowserPage(c: c, bookmarks: bm, downloads: d, initialUrl: url))); + + // 페이지가 열리고