WIP 266 폰 세로 MKV 화면: DNS 닿지 않음 줄을 한 줄로 (글 줄임 · 길게 누르면 전체 · 버튼 같은 줄) - 세부 정보의 자막 버튼이 밀려나지 않게 (검토 대기)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
묶음6
RyuJongJin 2026-10-12 09:25:47 +09:00
parent 1c6b008332
commit f596ef7253
3 changed files with 43 additions and 6 deletions

View File

@ -103,7 +103,7 @@ class HomePage extends StatelessWidget {
), ),
const Divider(height: 1), const Divider(height: 1),
// 249: DNS 서버에 닿지 않는 동안 작업 기록 위에 (아래 안내를 놓쳐도 MKV 화면에서 보고 바꿀 수 있게) // 249: DNS 서버에 닿지 않는 동안 작업 기록 위에 (아래 안내를 놓쳐도 MKV 화면에서 보고 바꿀 수 있게)
Padding(padding: const EdgeInsets.symmetric(horizontal: 12), child: DnsFailureLine(c: c)), Padding(padding: const EdgeInsets.symmetric(horizontal: 12), child: DnsFailureLine(c: c, compact: isCompact(context))),
if (c.settings.showLog) if (c.settings.showLog)
SizedBox( SizedBox(
// 화면이 낮은 기기 (휴대폰 가로) 에서 목록 · 자세히 보기를 가리지 않도록 화면 높이에 맞춘다. // 화면이 낮은 기기 (휴대폰 가로) 에서 목록 · 자세히 보기를 가리지 않도록 화면 높이에 맞춘다.

View File

@ -19,7 +19,11 @@ import 'tor_page.dart' show showTorNotice;
/// 서버가 다시 답하거나 DNS 설정을 바꾸면 사라진다. /// 서버가 다시 답하거나 DNS 설정을 바꾸면 사라진다.
class DnsFailureLine extends StatelessWidget { class DnsFailureLine extends StatelessWidget {
final AppController c; final AppController c;
const DnsFailureLine({super.key, required this.c});
/// 266: 좁은 화면 (폰 세로) - 한 줄 (글은 줄임, 길게 누르면 전체 · 버튼은 같은 줄). 두 줄이면 위의 세부 정보 칸이 줄어
/// [AI 자막 만들기] · [인터넷 자막 찾기] 가 칸 밖으로 밀렸다
final bool compact;
const DnsFailureLine({super.key, required this.c, this.compact = false});
@override @override
Widget build(BuildContext context) => ValueListenableBuilder<DnsFailure?>( Widget build(BuildContext context) => ValueListenableBuilder<DnsFailure?>(
@ -27,12 +31,33 @@ class DnsFailureLine extends StatelessWidget {
builder: (context, f, _) { builder: (context, f, _) {
if (f == null) return const SizedBox.shrink(); if (f == null) return const SizedBox.shrink();
String two(int x) => x.toString().padLeft(2, '0'); String two(int x) => x.toString().padLeft(2, '0');
final text = trf('DNS 서버 ({0}) 에 닿지 않음 ({1}부터)', [f.server, '${two(f.at.hour)}:${two(f.at.minute)}']);
if (compact) {
return SizedBox(
height: 36,
child: Row(children: [
const Icon(Icons.warning_amber_rounded, size: 16, color: Colors.orange),
const SizedBox(width: 6),
Expanded(
child: Tooltip(
message: text,
child: Text(text, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12, color: Colors.orange)),
),
),
TextButton(
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact, padding: const EdgeInsets.symmetric(horizontal: 8), minimumSize: const Size(0, 36)),
onPressed: () => c.updateSettings((x) => x.dnsMode = 'system'),
child: Text(tr('시스템 DNS 로 바꾸기'), style: const TextStyle(fontSize: 13)),
),
]),
);
}
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 4), padding: const EdgeInsets.symmetric(vertical: 4),
child: Wrap(spacing: 8, crossAxisAlignment: WrapCrossAlignment.center, children: [ child: Wrap(spacing: 8, crossAxisAlignment: WrapCrossAlignment.center, children: [
const Icon(Icons.warning_amber_rounded, size: 18, color: Colors.orange), const Icon(Icons.warning_amber_rounded, size: 18, color: Colors.orange),
Text(trf('DNS 서버 ({0}) 에 닿지 않음 ({1}부터)', [f.server, '${two(f.at.hour)}:${two(f.at.minute)}']), Text(text, style: const TextStyle(fontSize: 12, color: Colors.orange)),
style: const TextStyle(fontSize: 12, color: Colors.orange)),
TextButton( TextButton(
onPressed: () => c.updateSettings((x) => x.dnsMode = 'system'), onPressed: () => c.updateSettings((x) => x.dnsMode = 'system'),
child: Text(tr('시스템 DNS 로 바꾸기')), child: Text(tr('시스템 DNS 로 바꾸기')),

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:jj_mkvmaker/app/app_controller.dart'; import 'package:jj_mkvmaker/app/app_controller.dart';
import 'package:jj_mkvmaker/app/net_guard.dart';
import 'package:jj_mkvmaker/app/settings.dart'; import 'package:jj_mkvmaker/app/settings.dart';
import 'package:jj_mkvmaker/core/models.dart'; import 'package:jj_mkvmaker/core/models.dart';
import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart'; import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart';
@ -10,8 +11,8 @@ import 'package:jj_mkvmaker/ui/home_page.dart';
/// 261: 폰 세로 (노트 10+ 412×869) 의 MKV 세부 정보 - "감지한 언어" 줄이 생겨도 [AI 자막 만들기] 가 밀려 가려지지 않는다 /// 261: 폰 세로 (노트 10+ 412×869) 의 MKV 세부 정보 - "감지한 언어" 줄이 생겨도 [AI 자막 만들기] 가 밀려 가려지지 않는다
void main() { void main() {
for (final detected in [false, true]) { for (final (detected, dns) in [(false, false), (true, false), (true, true)]) {
testWidgets('261: 폰 세로 · 작업 기록 켬 · 감지한 언어 ${detected ? '있음' : '없음'} - [AI 자막 만들기] 가 스크롤 없이 보인다', (tester) async { testWidgets('261 · 266: 폰 세로 · 작업 기록 켬 · 감지한 언어 ${detected ? '있음' : '없음'}${dns ? ' · DNS 닿지 않음 줄' : ''} - [AI 자막 만들기] 가 스크롤 없이 보인다', (tester) async {
tester.view.physicalSize = const Size(412, 869); tester.view.physicalSize = const Size(412, 869);
tester.view.devicePixelRatio = 1; tester.view.devicePixelRatio = 1;
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
@ -27,6 +28,11 @@ void main() {
c.videos.add(VideoItem('D:/v/아주 긴 이름의 동영상 파일 $i.mp4')); c.videos.add(VideoItem('D:/v/아주 긴 이름의 동영상 파일 $i.mp4'));
} }
c.selected = c.videos.first..aiDetected = detected ? 'en' : null; c.selected = c.videos.first..aiDetected = detected ? 'en' : null;
// 266: DNS 가 닿지 않는 동안 작업 기록 위의 줄 (936 노트 10+ 에서 두 줄이 되어 버튼을 밀어냄)
if (dns) {
NetGuard.instance.failure.value = DnsFailure('192.0.2.1', '답이 없습니다', DateTime(2026, 10, 12, 8, 42));
addTearDown(() => NetGuard.instance.failure.value = null);
}
await tester.pumpWidget(MaterialApp(home: HomePage(c: c))); await tester.pumpWidget(MaterialApp(home: HomePage(c: c)));
await tester.pump(); await tester.pump();
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
@ -36,6 +42,12 @@ void main() {
final view = tester.getRect(find.ancestor(of: ai, matching: find.byType(Scrollable)).first); final view = tester.getRect(find.ancestor(of: ai, matching: find.byType(Scrollable)).first);
final button = tester.getRect(ai); final button = tester.getRect(ai);
expect(button.bottom, lessThanOrEqualTo(view.bottom), reason: '버튼 $button · 세부 정보 칸 $view'); expect(button.bottom, lessThanOrEqualTo(view.bottom), reason: '버튼 $button · 세부 정보 칸 $view');
if (dns) {
// 한 줄 · 버튼도 그 줄에
final line = tester.getRect(find.text('DNS 서버 (192.0.2.1) 에 닿지 않음 (08:42부터)'));
final sys = tester.getRect(find.text('시스템 DNS 로 바꾸기'));
expect((sys.center.dy - line.center.dy).abs(), lessThan(4), reason: '버튼이 같은 줄');
}
}); });
} }
} }