diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index f539d1a..6bdba63 100644 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -99,7 +99,12 @@ class HomePage extends StatelessWidget { SizedBox( // 화면이 낮은 기기 (휴대폰 가로) 에서 목록 · 자세히 보기를 가리지 않도록 화면 높이에 맞춘다. // 256: 폰 가로 (높이 500 미만) 는 더 작게 - 목록이 한 줄만 보였다 - height: MediaQuery.sizeOf(context).height < 500 ? 52 : (MediaQuery.sizeOf(context).height * 0.22).clamp(80.0, 140.0), + // 관리자 판단 (10/17, 15 지적): 폰 세로에서 기록이 비었으면 안내 한 줄 높이만 (빈 자리만 없앰), 기록이 생기면 예전 높이 + height: isCompact(context) && c.logs.isEmpty + ? _LogPanel.emptyHeight + : MediaQuery.sizeOf(context).height < 500 + ? 52 + : (MediaQuery.sizeOf(context).height * 0.22).clamp(80.0, 140.0), child: _LogPanel( logs: c.logs, onClose: () => c.updateSettings((s) => s.showLog = false), @@ -1415,6 +1420,9 @@ class _LogPanel extends StatelessWidget { final VoidCallback onClose; const _LogPanel({required this.logs, required this.onClose}); + /// 폰 세로에서 기록이 비었을 때의 높이 (안내 한 줄) + static const emptyHeight = 40.0; + @override Widget build(BuildContext context) => Container( color: JjColors.bg, @@ -1423,9 +1431,9 @@ class _LogPanel extends StatelessWidget { if (logs.isEmpty) Positioned.fill( child: Padding( - padding: const EdgeInsets.fromLTRB(16, 10, 44, 8), + padding: const EdgeInsets.fromLTRB(16, 12, 44, 0), child: Text(tr('작업 기록이 아직 없습니다. MKV 만들기 · 자막 · 다운로드를 하면 여기에 차례로 남습니다.'), - style: const TextStyle(fontSize: 12, color: JjColors.textDim)), + maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12, color: JjColors.textDim)), ), ), Positioned.fill( diff --git a/lib/ui/scroll_more.dart b/lib/ui/scroll_more.dart index 1885c5a..2619b0a 100644 --- a/lib/ui/scroll_more.dart +++ b/lib/ui/scroll_more.dart @@ -53,34 +53,37 @@ class _ScrollMoreState extends State { _scroll.animateTo(to, duration: const Duration(milliseconds: 220), curve: Curves.easeOut); } + /// 끝의 [›] · [‹]: 짧은 흐림 + 바탕을 깐 단추 (15 지적: 잘린 버튼 글자가 [›] 뒤로 비쳐 보였다) Widget _edge(bool right) { final bg = widget.background ?? Theme.of(context).scaffoldBackgroundColor; + final fade = Container( + width: 20, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: right ? Alignment.centerLeft : Alignment.centerRight, + end: right ? Alignment.centerRight : Alignment.centerLeft, + colors: [bg.withValues(alpha: 0), bg], + ), + ), + ); + final button = ColoredBox( + color: bg, + child: Center( + child: IconButton( + tooltip: right ? tr('버튼 더 보기') : tr('앞의 버튼 보기'), + visualDensity: VisualDensity.compact, + style: IconButton.styleFrom(backgroundColor: JjColors.panelHigh), + icon: Icon(right ? Icons.chevron_right : Icons.chevron_left, color: JjColors.accent), + onPressed: () => _jump(right ? 1 : -1), + ), + ), + ); return Positioned( top: 0, bottom: 0, left: right ? null : 0, right: right ? 0 : null, - child: DecoratedBox( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: right ? Alignment.centerLeft : Alignment.centerRight, - end: right ? Alignment.centerRight : Alignment.centerLeft, - colors: [bg.withValues(alpha: 0), bg.withValues(alpha: 0.95), bg], - stops: const [0, 0.45, 1], - ), - ), - child: Padding( - padding: EdgeInsets.only(left: right ? 18 : 0, right: right ? 0 : 18), - child: Center( - child: IconButton( - tooltip: right ? tr('버튼 더 보기') : tr('앞의 버튼 보기'), - visualDensity: VisualDensity.compact, - icon: Icon(right ? Icons.chevron_right : Icons.chevron_left, color: JjColors.accent), - onPressed: () => _jump(right ? 1 : -1), - ), - ), - ), - ), + child: Row(mainAxisSize: MainAxisSize.min, children: right ? [fade, button] : [button, fade]), ); } diff --git a/test/mkv_compact_list_test.dart b/test/mkv_compact_list_test.dart index 546764c..ff2cdff 100644 --- a/test/mkv_compact_list_test.dart +++ b/test/mkv_compact_list_test.dart @@ -98,10 +98,26 @@ void main() { expect(find.byTooltip('앞의 버튼 보기'), findsOneWidget); }); - testWidgets('작업 기록이 비었으면 무엇이 들어오는 칸인지 적는다', (tester) async { + /// 작업 기록 칸 (✕ 가 든 SizedBox) 의 높이 + double logHeight(WidgetTester tester) => + tester.getSize(find.ancestor(of: find.byTooltip('작업 기록 숨기기'), matching: find.byType(SizedBox)).first).height; + + testWidgets('작업 기록이 비었으면 무엇이 들어오는 칸인지 적고, 폰 세로는 한 줄 높이 - 기록이 생기면 예전 높이', (tester) async { final c = make(3); c.logs.clear(); await show(tester, c, const Size(412, 869)); expect(find.textContaining('작업 기록이 아직 없습니다'), findsOneWidget); + expect(logHeight(tester), 40, reason: '관리자 판단: 빈 자리만 없앤다'); + c.note('MKV 만들기 시작'); + await tester.pump(); + expect(logHeight(tester), 140); + expect(find.textContaining('작업 기록이 아직 없습니다'), findsNothing); + }); + + testWidgets('넓은 화면은 기록이 비어도 예전 높이 (폰 세로만 바꿈)', (tester) async { + final c = make(3); + c.logs.clear(); + await show(tester, c, const Size(1280, 800)); + expect(logHeight(tester), 140); }); }