From 52deef4118f2eec029d85365d45893f65e2f69bc Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Sun, 4 Oct 2026 18:36:55 +0900 Subject: [PATCH] =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95:=20?= =?UTF-8?q?=EC=9C=84=EC=AA=BD=20=EB=AC=B6=EC=9D=8C=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=ED=99=94=EB=A9=B4=20=EB=B0=96=20=EB=AC=B6?= =?UTF-8?q?=EC=9D=8C=20(=EB=8B=A4=EC=9A=B4=EB=A1=9C=EB=93=9C=20=EB=93=B1)?= =?UTF-8?q?=20=EC=97=90=EB=8F=84=20=EC=9D=B4=EB=8F=99,=20=EB=AC=B6?= =?UTF-8?q?=EC=9D=8C=20=EB=B2=84=ED=8A=BC=20=EC=A4=84=EC=9D=80=20=EC=9C=84?= =?UTF-8?q?=EC=97=90=20=EA=B3=A0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- lib/ui/settings_page.dart | 20 +++++++++++++------- test/queue_test.dart | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/ui/settings_page.dart b/lib/ui/settings_page.dart index 9584726..c49adfd 100644 --- a/lib/ui/settings_page.dart +++ b/lib/ui/settings_page.dart @@ -264,12 +264,16 @@ class _SettingsPageState extends State { AppActions(c: c, onSettingsPage: true), ]), ), + // 묶음 바로가기 (누르면 그 묶음으로). 스크롤해도 위에 그대로 + Padding( + padding: const EdgeInsets.fromLTRB(24, 12, 24, 0), + child: _groupBar(desk), + ), Expanded( - child: ListView( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), - children: [ - // 묶음 바로가기 (누르면 그 묶음으로) - _groupBar(desk), + // 모든 묶음을 한 번에 그린다 (ListView 는 화면 밖 묶음을 그리지 않아 바로가기로 갈 수 없었음) + child: SingleChildScrollView( + padding: const EdgeInsets.fromLTRB(24, 4, 24, 16), + child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _group('general', Icons.tune, tr('일반'), [ // 화면 언어 (읽을 수 없는 언어를 골라도 바로 찾아 되돌릴 수 있게 맨 위) const LanguageSettings(), @@ -696,7 +700,7 @@ class _SettingsPageState extends State { ]), ), ]), - ], + ]), ), ), ]), @@ -736,7 +740,9 @@ class _SettingsPageState extends State { onPressed: () { final ctx = _groupKeys[id]?.currentContext; if (ctx != null) { - Scrollable.ensureVisible(ctx, duration: const Duration(milliseconds: 300), curve: Curves.easeOut); + // 그 묶음의 제목이 맨 위에 오게 + Scrollable.ensureVisible(ctx, + alignment: 0, duration: const Duration(milliseconds: 300), curve: Curves.easeOut); } }, ), diff --git a/test/queue_test.dart b/test/queue_test.dart index 69c3414..69c1d33 100644 --- a/test/queue_test.dart +++ b/test/queue_test.dart @@ -204,6 +204,29 @@ void main() { expect(find.byTooltip('작업 기록 숨기기'), findsOneWidget); }); + testWidgets('환경 설정: 위쪽 묶음 버튼을 누르면 (화면 밖 묶음도) 그 묶음으로 간다', (tester) async { + tester.view.physicalSize = const Size(1400, 800); + tester.view.devicePixelRatio = 1; + addTearDown(tester.view.reset); + final c = AppController(PlatformServices(mediaTool: _Tool(), storage: DesktopStorageService())); + await tester.pumpWidget(MaterialApp(home: SettingsPage(c: c))); + await tester.pumpAndSettle(); + final groups = ['다운로드', '웹 브라우저', '자막 (AI · 인터넷)', 'MKV 만들기', '화면', '실행 · 종료', '재생', '일반']; + for (final g in groups) { + await tester.tap(find.widgetWithText(ActionChip, g)); + await tester.pumpAndSettle(); + // 묶음 제목 (버튼이 아닌 카드 안의 글) 이 화면 위쪽에 보인다 + final title = find.descendant(of: find.byType(Card), matching: find.text(g)).first; + final y = tester.getTopLeft(title).dy; + expect(y, inInclusiveRange(0, 400), reason: '$g 묶음 제목 위치 $y'); + } + // 끝의 묶음 (프로그램 정보) 도 화면에 보인다 + await tester.tap(find.widgetWithText(ActionChip, '프로그램 정보')); + await tester.pumpAndSettle(); + final about = find.descendant(of: find.byType(Card), matching: find.text('프로그램 정보')).first; + expect(tester.getTopLeft(about).dy, inInclusiveRange(0, 800)); + }); + testWidgets('환경 설정: 새 항목이 깨지지 않고 보임', (tester) async { // 스크롤 없이 모두 보이도록 세로로 긴 화면 tester.view.physicalSize = const Size(1400, 3200);