감지한 언어 알림은 닫을 때까지 · MKV 세부 정보에도 [다른 언어로 다시] (198 보충)

- 관리자 지시: 248 과 같게 버튼이 있는 안내는 닫을 때까지, 알림을 놓쳐도 세부 정보에서 다시 할 수 있게

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
묶음5
RyuJongJin 2026-10-12 06:01:35 +09:00
parent 36bbee615d
commit 433f5b187a
7 changed files with 44 additions and 1 deletions

View File

@ -443,6 +443,7 @@
"가져온 즐겨찾기": "Imported bookmarks", "가져온 즐겨찾기": "Imported bookmarks",
"가져온 즐겨찾기 ({0})": "Imported bookmarks ({0})", "가져온 즐겨찾기 ({0})": "Imported bookmarks ({0})",
"가져올 즐겨찾기가 없습니다.": "No bookmarks to import.", "가져올 즐겨찾기가 없습니다.": "No bookmarks to import.",
"감지한 언어: {0} (자동 감지)": "Detected language: {0} (auto-detect)",
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "Detected language: {0} - if it is wrong, make them again with another language", "감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "Detected language: {0} - if it is wrong, make them again with another language",
"같은 시리즈 (번호만 다른 파일)": "Same series (files that differ only by number)", "같은 시리즈 (번호만 다른 파일)": "Same series (files that differ only by number)",
"같은 이름이 이미 있습니다": "An item with the same name already exists", "같은 이름이 이미 있습니다": "An item with the same name already exists",

View File

@ -443,6 +443,7 @@
"가져온 즐겨찾기": "取り込んだブックマーク", "가져온 즐겨찾기": "取り込んだブックマーク",
"가져온 즐겨찾기 ({0})": "取り込んだブックマーク({0})", "가져온 즐겨찾기 ({0})": "取り込んだブックマーク({0})",
"가져올 즐겨찾기가 없습니다.": "取り込むブックマークがありません。", "가져올 즐겨찾기가 없습니다.": "取り込むブックマークがありません。",
"감지한 언어: {0} (자동 감지)": "検出した言語: {0} (自動検出)",
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "検出した言語: {0} - 違っていれば別の言語で作り直してください", "감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "検出した言語: {0} - 違っていれば別の言語で作り直してください",
"같은 시리즈 (번호만 다른 파일)": "同じシリーズ(番号だけ違うファイル)", "같은 시리즈 (번호만 다른 파일)": "同じシリーズ(番号だけ違うファイル)",
"같은 이름이 이미 있습니다": "同じ名前のものが既にあります", "같은 이름이 이미 있습니다": "同じ名前のものが既にあります",

View File

@ -443,6 +443,7 @@
"가져온 즐겨찾기": "导入的书签", "가져온 즐겨찾기": "导入的书签",
"가져온 즐겨찾기 ({0})": "导入的书签({0})", "가져온 즐겨찾기 ({0})": "导入的书签({0})",
"가져올 즐겨찾기가 없습니다.": "没有可导入的书签。", "가져올 즐겨찾기가 없습니다.": "没有可导入的书签。",
"감지한 언어: {0} (자동 감지)": "检测到的语言:{0}(自动检测)",
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "检测到的语言:{0} - 如有误,请用其他语言重新生成", "감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "检测到的语言:{0} - 如有误,请用其他语言重新生成",
"같은 시리즈 (번호만 다른 파일)": "同一系列(仅编号不同的文件)", "같은 시리즈 (번호만 다른 파일)": "同一系列(仅编号不同的文件)",
"같은 이름이 이미 있습니다": "已存在同名项目", "같은 이름이 이미 있습니다": "已存在同名项目",

View File

@ -60,7 +60,9 @@ void showDetectedLanguage(ScaffoldMessengerState messenger, OverlayState? overla
? found.single.$2.name ? found.single.$2.name
: found.map((x) => '${x.$2.name} (${x.$1.fileName})').join(' · '); : found.map((x) => '${x.$2.name} (${x.$1.fileName})').join(' · ');
messenger.showSnackBar(SnackBar( messenger.showSnackBar(SnackBar(
duration: const Duration(seconds: 12), // 248 과 같게: 버튼이 있는 안내는 사용자가 닫을 때까지 ([✕]). 나중에는 MKV 목록의 그 동영상 세부 정보에서도
persist: true,
showCloseIcon: true,
content: Text(trf('감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요', [names])), content: Text(trf('감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요', [names])),
action: overlay == null action: overlay == null
? null ? null

View File

@ -1063,6 +1063,23 @@ class _VideoDetail extends StatelessWidget {
], ],
_Chip(trf('음성 {0}개', [audioCount])), _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) ...[ if (v.message != null) ...[
const SizedBox(height: 12), const SizedBox(height: 12),
Container( Container(

View File

@ -89,6 +89,10 @@ void main() {
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 800)); // 알림이 다 올라올 때까지 await tester.pump(const Duration(milliseconds: 800)); // 알림이 다 올라올 때까지
expect(find.text('감지한 언어: 한국어 - 틀렸으면 다른 언어로 다시 만드세요'), findsOneWidget); 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.tap(find.text('다른 언어로 다시'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('원어를 골라 다시 만들기'), findsOneWidget); expect(find.text('원어를 골라 다시 만들기'), findsOneWidget);

View File

@ -293,6 +293,23 @@ void main() {
reason: '${v1.message} ${v2.message} ${v3.message}'); 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 { testWidgets('MKV 화면: 체크 → "자막 만들기 (2)" · "MKV 만들기 (2)" 글, 전체 선택', (tester) async {
tester.view.physicalSize = const Size(1600, 900); // 위쪽 버튼 글이 다 보이는 너비 tester.view.physicalSize = const Size(1600, 900); // 위쪽 버튼 글이 다 보이는 너비
tester.view.devicePixelRatio = 1; tester.view.devicePixelRatio = 1;