From 3b8ea95aa6e4651111396e4f445fd5e7691e806f Mon Sep 17 00:00:00 2001 From: joungmin Date: Mon, 15 Jun 2026 14:30:21 +0900 Subject: [PATCH] =?UTF-8?q?[hotfix]=20#342=20v0.4.2=20=E2=80=94=20ChatScre?= =?UTF-8?q?en=20SafeArea=20+=20LLM=20=EC=97=90=EB=9F=AC=20=EC=A7=84?= =?UTF-8?q?=EB=8B=A8=20=EB=85=B8=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix - ChatScreen body 를 SafeArea(top: false) 로 감쌈. Android edge-to-edge 모드에서 시스템 nav bar 가 입력창을 덮던 문제 해결. Dev (#342) - userTurn catch 블록이 e.toString() + stack trace 를 error 상태에 저장. - 빨간 에러 컨테이너를 SingleChildScrollView + SelectableText (monospace) + 최대 화면 1/3 높이 제약. 스크롤 + 복사 가능. release 빌드에서도 full stack 노출 (#342 종료 후 follow-up 으로 좁힘). 테스트: chat_session_controller_test 8/8 통과. APK: app-release.apk 301.0MB SHA 02a5d1c8. Refs #342 --- CHANGELOG.md | 8 ++++++++ app/lib/state/chat_providers.dart | 8 ++++++-- app/lib/ui/screens/chat_screen.dart | 31 +++++++++++++++++++++-------- app/pubspec.yaml | 2 +- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9332c5e..6fda593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ 본 프로젝트의 모든 의미있는 변경은 본 파일에 기록한다. 형식: [Keep a Changelog](https://keepachangelog.com/) · 버전: [SemVer](https://semver.org/). +## [0.4.2] — 2026-06-15 (hotfix, dev) + +### Fixed (Redmine #342) +- **ChatScreen 하단 잘림** — Android edge-to-edge 모드에서 시스템 nav bar (3-button / gesture handle) 가 입력창을 덮던 문제. `Scaffold.body` 를 `SafeArea(top: false, …)` 로 감쌈. AppBar 가 이미 top inset 처리하므로 top 만 false. + +### Dev +- **LLM 실패 빨간 배너에 full message + stack trace** — 단말 진단을 위해 release 빌드에서도 노출. `LLM 응답 실패: \n\n--- STACK ---\n` 형식. SelectableText + monospace + 최대 화면 1/3 높이 + scroll. 사용자 친화 메시지로 좁히는 작업은 #342 종료 후 follow-up. + ## [0.4.1] — 2026-06-15 ### Added — ChatScreen LLM warm-up (Redmine #311, follow-up of #260) diff --git a/app/lib/state/chat_providers.dart b/app/lib/state/chat_providers.dart index 8a5c1e6..a4b6704 100644 --- a/app/lib/state/chat_providers.dart +++ b/app/lib/state/chat_providers.dart @@ -206,12 +206,16 @@ class ChatSessionController extends StateNotifier { clearStreamingText: true, error: '도구 호출 루프가 너무 길어 중단했습니다.', ); - } catch (e) { + } catch (e, st) { if (!mounted) return; + // 개발 단계 (#342) — 실 단말 진단을 위해 release 빌드에서도 full + // message + stack 노출. 사용자 친화 메시지로 다시 좁히는 작업은 + // #342 종료 후 follow-up. + final detail = 'LLM 응답 실패: ${e.runtimeType}\n$e\n\n--- STACK ---\n$st'; state = state.copyWith( isStreaming: false, clearStreamingText: true, - error: 'LLM 응답 실패: ${e.runtimeType}', + error: detail, ); } } diff --git a/app/lib/ui/screens/chat_screen.dart b/app/lib/ui/screens/chat_screen.dart index 085377f..597d335 100644 --- a/app/lib/ui/screens/chat_screen.dart +++ b/app/lib/ui/screens/chat_screen.dart @@ -76,10 +76,16 @@ class _ChatScreenState extends ConsumerState { ), ], ), - body: depsAsync.when( - loading: () => const Center(child: CircularProgressIndicator()), - error: (e, _) => Center(child: Text('초기화 실패: $e')), - data: (_) => _buildBody(context), + // Android edge-to-edge: 시스템 nav bar (3-button / gesture handle) 가 + // 입력창을 가리지 않도록 SafeArea 로 감싼다. AppBar 가 이미 top inset + // 을 처리하므로 top 만 false. + body: SafeArea( + top: false, + child: depsAsync.when( + loading: () => const Center(child: CircularProgressIndicator()), + error: (e, _) => Center(child: Text('초기화 실패: $e')), + data: (_) => _buildBody(context), + ), ), ); } @@ -105,14 +111,23 @@ class _ChatScreenState extends ConsumerState { children: [ if (warmup is ChatWarmupFailed) _WarmupErrorBanner(warmup: warmup), if (state.error != null) + // #342 dev — 단말에서 원인 진단을 위해 stack 까지 노출되는 케이스를 + // 위해 multi-line + scrollable + selectable. 높이는 화면의 1/3 까지만. Container( width: double.infinity, color: theme.colorScheme.errorContainer, padding: const EdgeInsets.all(12), - child: Text( - state.error!, - style: TextStyle( - color: theme.colorScheme.onErrorContainer, + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height / 3, + ), + child: SingleChildScrollView( + child: SelectableText( + state.error!, + style: TextStyle( + color: theme.colorScheme.onErrorContainer, + fontFamily: 'monospace', + fontSize: 12, + ), ), ), ), diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 06de7ed..934ddef 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -1,7 +1,7 @@ name: life_helper description: "Huberman + Atomic Habits + Tiny Habits + If-Then. Local-first habit/checklist/todo." publish_to: 'none' -version: 0.4.1+5 +version: 0.4.2+6 environment: sdk: ^3.12.2