From 433f5b187a3f3fc6ef8ad08f7132edb6590bef57 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Mon, 12 Oct 2026 06:01:35 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B0=90=EC=A7=80=ED=95=9C=20=EC=96=B8?= =?UTF-8?q?=EC=96=B4=20=EC=95=8C=EB=A6=BC=EC=9D=80=20=EB=8B=AB=EC=9D=84=20?= =?UTF-8?q?=EB=95=8C=EA=B9=8C=EC=A7=80=20=C2=B7=20MKV=20=EC=84=B8=EB=B6=80?= =?UTF-8?q?=20=EC=A0=95=EB=B3=B4=EC=97=90=EB=8F=84=20[=EB=8B=A4=EB=A5=B8?= =?UTF-8?q?=20=EC=96=B8=EC=96=B4=EB=A1=9C=20=EB=8B=A4=EC=8B=9C]=20(198=20?= =?UTF-8?q?=EB=B3=B4=EC=B6=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 관리자 지시: 248 과 같게 버튼이 있는 안내는 닫을 때까지, 알림을 놓쳐도 세부 정보에서 다시 할 수 있게 Co-Authored-By: Claude Opus 5.5 --- assets/l10n/en.json | 1 + assets/l10n/ja.json | 1 + assets/l10n/zh-Hans.json | 1 + lib/ui/ai_dialog.dart | 4 +++- lib/ui/home_page.dart | 17 +++++++++++++++++ test/ai_confirm_test.dart | 4 ++++ test/batch_test.dart | 17 +++++++++++++++++ 7 files changed, 44 insertions(+), 1 deletion(-) diff --git a/assets/l10n/en.json b/assets/l10n/en.json index e390eae..e406f1d 100644 --- a/assets/l10n/en.json +++ b/assets/l10n/en.json @@ -443,6 +443,7 @@ "가져온 즐겨찾기": "Imported bookmarks", "가져온 즐겨찾기 ({0})": "Imported bookmarks ({0})", "가져올 즐겨찾기가 없습니다.": "No bookmarks to import.", + "감지한 언어: {0} (자동 감지)": "Detected language: {0} (auto-detect)", "감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "Detected language: {0} - if it is wrong, make them again with another language", "같은 시리즈 (번호만 다른 파일)": "Same series (files that differ only by number)", "같은 이름이 이미 있습니다": "An item with the same name already exists", diff --git a/assets/l10n/ja.json b/assets/l10n/ja.json index 1da1d0a..978d084 100644 --- a/assets/l10n/ja.json +++ b/assets/l10n/ja.json @@ -443,6 +443,7 @@ "가져온 즐겨찾기": "取り込んだブックマーク", "가져온 즐겨찾기 ({0})": "取り込んだブックマーク({0})", "가져올 즐겨찾기가 없습니다.": "取り込むブックマークがありません。", + "감지한 언어: {0} (자동 감지)": "検出した言語: {0} (自動検出)", "감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "検出した言語: {0} - 違っていれば別の言語で作り直してください", "같은 시리즈 (번호만 다른 파일)": "同じシリーズ(番号だけ違うファイル)", "같은 이름이 이미 있습니다": "同じ名前のものが既にあります", diff --git a/assets/l10n/zh-Hans.json b/assets/l10n/zh-Hans.json index 95429b2..fe3dbc3 100644 --- a/assets/l10n/zh-Hans.json +++ b/assets/l10n/zh-Hans.json @@ -443,6 +443,7 @@ "가져온 즐겨찾기": "导入的书签", "가져온 즐겨찾기 ({0})": "导入的书签({0})", "가져올 즐겨찾기가 없습니다.": "没有可导入的书签。", + "감지한 언어: {0} (자동 감지)": "检测到的语言:{0}(自动检测)", "감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "检测到的语言:{0} - 如有误,请用其他语言重新生成", "같은 시리즈 (번호만 다른 파일)": "同一系列(仅编号不同的文件)", "같은 이름이 이미 있습니다": "已存在同名项目", diff --git a/lib/ui/ai_dialog.dart b/lib/ui/ai_dialog.dart index db11565..3b7ebaa 100644 --- a/lib/ui/ai_dialog.dart +++ b/lib/ui/ai_dialog.dart @@ -60,7 +60,9 @@ void showDetectedLanguage(ScaffoldMessengerState messenger, OverlayState? overla ? found.single.$2.name : found.map((x) => '${x.$2.name} (${x.$1.fileName})').join(' · '); messenger.showSnackBar(SnackBar( - duration: const Duration(seconds: 12), + // 248 과 같게: 버튼이 있는 안내는 사용자가 닫을 때까지 ([✕]). 나중에는 MKV 목록의 그 동영상 세부 정보에서도 + persist: true, + showCloseIcon: true, content: Text(trf('감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요', [names])), action: overlay == null ? null diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index 03d5989..3379df5 100644 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -1063,6 +1063,23 @@ class _VideoDetail extends StatelessWidget { ], _Chip(trf('음성 {0}개', [audioCount])), ]), + // 198: 마지막 AI 자막의 원어를 자동 감지했으면 - 알림을 놓쳐도 여기서 다른 언어로 다시 만들 수 있게 + if (v.aiDetected != null) ...[ + const SizedBox(height: 8), + Wrap(crossAxisAlignment: WrapCrossAlignment.center, spacing: 8, children: [ + Text(trf('감지한 언어: {0} (자동 감지)', [languageOf(v.aiDetected).name]), + style: const TextStyle(fontSize: 12, color: JjColors.textDim)), + TextButton( + onPressed: c.busy + ? null + : () async { + final lang = await pickSourceLanguage(context, languageOf(v.aiDetected)); + if (lang != null) await c.generateAiSubtitles([v], c.aiOptions.copyWith(source: lang)); + }, + child: Text(tr('다른 언어로 다시')), + ), + ]), + ], if (v.message != null) ...[ const SizedBox(height: 12), Container( diff --git a/test/ai_confirm_test.dart b/test/ai_confirm_test.dart index 9c47598..e742ba5 100644 --- a/test/ai_confirm_test.dart +++ b/test/ai_confirm_test.dart @@ -89,6 +89,10 @@ void main() { await tester.pump(); await tester.pump(const Duration(milliseconds: 800)); // 알림이 다 올라올 때까지 expect(find.text('감지한 언어: 한국어 - 틀렸으면 다른 언어로 다시 만드세요'), findsOneWidget); + // 248 과 같게: 닫을 때까지 남는다 ([✕]) + await tester.pump(const Duration(minutes: 1)); + expect(find.text('감지한 언어: 한국어 - 틀렸으면 다른 언어로 다시 만드세요'), findsOneWidget); + expect(find.byIcon(Icons.close), findsOneWidget); await tester.tap(find.text('다른 언어로 다시')); await tester.pumpAndSettle(); expect(find.text('원어를 골라 다시 만들기'), findsOneWidget); diff --git a/test/batch_test.dart b/test/batch_test.dart index 97a29e5..cad2fa9 100644 --- a/test/batch_test.dart +++ b/test/batch_test.dart @@ -293,6 +293,23 @@ void main() { reason: '${v1.message} ${v2.message} ${v3.message}'); }); + testWidgets('198: 원어를 자동 감지한 동영상은 세부 정보에 감지한 언어 · [다른 언어로 다시] (알림을 놓쳐도)', (tester) async { + tester.view.physicalSize = const Size(1600, 900); + tester.view.devicePixelRatio = 1; + addTearDown(tester.view.reset); + final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); + c.videos.add(VideoItem(r'D:\v\a.mp4')..aiDetected = 'ko'); + c.selected = c.videos.first; + await tester.pumpWidget(MaterialApp(home: HomePage(c: c))); + expect(find.text('감지한 언어: 한국어 (자동 감지)'), findsOneWidget); + expect(find.widgetWithText(TextButton, '다른 언어로 다시'), findsOneWidget); + // 원어를 직접 고르면 (null) 보이지 않는다 + c.videos.first.aiDetected = null; + c.selected = c.videos.first; + await tester.pumpWidget(MaterialApp(key: UniqueKey(), home: HomePage(c: c))); + expect(find.textContaining('감지한 언어'), findsNothing); + }); + testWidgets('MKV 화면: 체크 → "자막 만들기 (2)" · "MKV 만들기 (2)" 글, 전체 선택', (tester) async { tester.view.physicalSize = const Size(1600, 900); // 위쪽 버튼 글이 다 보이는 너비 tester.view.devicePixelRatio = 1;