From 7c90eca30ca2948928632264cfa2395ab4a355c8 Mon Sep 17 00:00:00 2001 From: joungmin Date: Mon, 15 Jun 2026 13:08:32 +0900 Subject: [PATCH] =?UTF-8?q?[05-Designer]=20#311=20fileMissing=20=EB=B6=84?= =?UTF-8?q?=EA=B8=B0=20[=EC=84=A4=EC=A0=95=EC=9C=BC=EB=A1=9C=20=EA=B0=80?= =?UTF-8?q?=EA=B8=B0]=20=EB=B2=84=ED=8A=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UX-REVIEW.md §마이크로카피 사전에서 fileMissing 케이스에 [설정으로 가기] 를 명시했으나 Developer 구현은 모든 kind 가 [다시 시도] 였음. fileMissing 에서 retry 해도 파일이 없어 같은 결과 → 사용자 막힘. - ChatWarmupFailureKind.fileMissing → SettingsScreen push (다운로드 재시도 경로 노출) - ChatWarmupFailureKind.runtime → 기존 retry() 유지 (일시적 회복 가능) 여전히 메시지 본문은 상태 기술만 (AC12), 행동은 버튼이 담당 (UX R5). Refs #311 --- app/lib/ui/screens/chat_screen.dart | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/lib/ui/screens/chat_screen.dart b/app/lib/ui/screens/chat_screen.dart index f50bfbb..a8e8727 100644 --- a/app/lib/ui/screens/chat_screen.dart +++ b/app/lib/ui/screens/chat_screen.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../ai/tools/tool_envelope.dart'; import '../../state/chat_providers.dart'; import '../../state/chat_warmup_provider.dart'; +import 'settings_screen.dart'; /// AI chat surface (#260). Multi-turn tool calling powered by Gemma 4 + /// in-process tool runtime. ConfirmGate modals appear on destructive @@ -179,7 +180,9 @@ class _ChatScreenState extends ConsumerState { } } -/// #311 AC5 / UX R5+R6: 실패 메시지는 상태만 기술, 행동은 [다시 시도] 버튼. +/// #311 AC5 / UX R5+R6: 실패 메시지는 상태만 기술, 행동은 버튼이 담당. +/// fileMissing 은 retry 로 회복 불가 — 설정 화면으로 유도해 재다운로드 경로를 연다. +/// runtime 은 일시적일 수 있으므로 [다시 시도] (in-place retry). class _WarmupErrorBanner extends ConsumerWidget { final ChatWarmupFailed warmup; const _WarmupErrorBanner({required this.warmup}); @@ -187,6 +190,8 @@ class _WarmupErrorBanner extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); + final isFileMissing = + warmup.kind == ChatWarmupFailureKind.fileMissing; return Container( width: double.infinity, color: theme.colorScheme.errorContainer, @@ -203,9 +208,15 @@ class _WarmupErrorBanner extends ConsumerWidget { alignment: Alignment.centerRight, child: OutlinedButton( onPressed: () { - ref.read(chatWarmupProvider.notifier).retry(); + if (isFileMissing) { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => const SettingsScreen(), + )); + } else { + ref.read(chatWarmupProvider.notifier).retry(); + } }, - child: const Text('다시 시도'), + child: Text(isFileMissing ? '설정으로 가기' : '다시 시도'), ), ), ],