diff --git a/lib/screens/camera_screen.dart b/lib/screens/camera_screen.dart index abc8091..b43df0a 100644 --- a/lib/screens/camera_screen.dart +++ b/lib/screens/camera_screen.dart @@ -567,12 +567,52 @@ class _CameraScreenState extends ConsumerState with SingleTickerPr } catch (e) { if (mounted) { Navigator.of(context).pop(); // Close AnalyzingDialog - - // Check for Quota Error to set Lockout - if (e.toString().contains('Quota') || e.toString().contains('429')) { - setState(() { - _quotaLockoutTime = DateTime.now().add(const Duration(minutes: 1)); - }); + + final errStr = e.toString(); + + // AIサーバー混雑(503)→ ドラフト保存してオフライン時と同じ扱いに + if (errStr.contains('[CONGESTION]')) { + try { + await DraftService.saveDraft(_capturedImages); + if (!mounted) return; + Navigator.of(context).pop(); // Close camera screen + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(LucideIcons.cloudOff, color: Colors.white, size: 16), + SizedBox(width: 8), + Text('AIサーバー混雑', style: TextStyle(fontWeight: FontWeight.bold)), + ], + ), + SizedBox(height: 4), + Text('写真を「解析待ち」として保存しました。'), + Text('時間をおいてホーム画面から解析できます。'), + ], + ), + duration: Duration(seconds: 5), + backgroundColor: Colors.orange, + ), + ); + } catch (_) { + // ドラフト保存も失敗した場合のみエラー表示 + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('解析もドラフト保存も失敗しました。再試行してください。')), + ); + } + return; + } + + // Quota エラー(429)→ ロックアウト + if (errStr.contains('Quota') || errStr.contains('429')) { + setState(() { + _quotaLockoutTime = DateTime.now().add(const Duration(minutes: 1)); + }); } final appColors = Theme.of(context).extension()!; diff --git a/lib/services/gemini_service.dart b/lib/services/gemini_service.dart index 357b2de..576c5f0 100644 --- a/lib/services/gemini_service.dart +++ b/lib/services/gemini_service.dart @@ -349,7 +349,8 @@ $extractedText if (isLastAttempt || !is503) { // 最終試行 or 503以外のエラーはそのまま投げる if (is503) { - throw Exception('AIサーバーが混雑しています。しばらく待ってから再試行してください。'); + // [CONGESTION] マーカー付きで投げる → camera_screen でドラフト保存へ + throw Exception('[CONGESTION] AIサーバーが混雑しています。解析待ちとして保存します。'); } throw Exception('AI解析エラー(Direct): $e'); }