# Phase 4: ユーザビリティ向上 - 実装計画 **Version:** 1.0 **Date:** 2026-01-16 **Based on:** Antigravity's proposal + Claude's improvements **Status:** Ready to implement --- ## Overview Phase 4では以下2つの機能を実装します: 1. 🌙 **ダークモード自動切替** - 時間帯に応じた自動テーマ変更 2. 🖋️ **和風フォント対応** - 日本酒アプリにふさわしいフォント選択 --- ## Feature 1: ダークモード自動切替 🌙 ### 要件定義 - **既存**: ライト/ダーク/システム連動の3モード - **追加**: 時間連動モード(夜間自動ダーク化) - **切替時刻**: 20:00〜06:00 = ダークモード - **ユーザー設定**: 設定画面で選択可能 ### 技術仕様 #### A. ThemeMode拡張 ```dart enum AppThemeMode { light, // 常にライト dark, // 常にダーク system, // OSに従う autoTime, // 時間連動(新規) } ``` #### B. 時刻判定ロジック ```dart class ThemeProvider extends ChangeNotifier { AppThemeMode _themeMode = AppThemeMode.autoTime; // 現在適用すべきThemeModeを計算 ThemeMode get effectiveThemeMode { if (_themeMode == AppThemeMode.autoTime) { final hour = DateTime.now().hour; // 20:00〜06:00 = ダークモード return (hour >= 20 || hour < 6) ? ThemeMode.dark : ThemeMode.light; } // その他のモードは既存ロジック return _themeModeToFlutterThemeMode(_themeMode); } } ``` #### C. 自動更新メカニズム **方式1: WidgetsBindingObserver(推奨)** - アプリがバックグラウンドから復帰した時に再計算 - 電池消費が少ない - リアルタイム性は低い(アプリを開いた時のみ) **方式2: Timer** - 1分ごとに時刻をチェック - リアルタイム性が高い - 電池消費がやや増える **採用: 方式1(推奨)** - 日本酒アプリでは厳密なリアルタイム性は不要 ```dart class ThemeProvider extends ChangeNotifier with WidgetsBindingObserver { @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { // アプリ復帰時にテーマを再計算 notifyListeners(); } } } ``` #### D. UI実装 **設定画面の選択肢:** ``` ○ ライトモード ○ ダークモード ○ システム設定に従う ● 自動(夜間ダーク) ← NEW ``` **現在の状態表示:** ``` テーマ: 自動(夜間ダーク) 現在: ダークモード(20:00〜06:00適用中) ``` ### 実装ファイル | ファイル | 変更内容 | |---------|---------| | `lib/providers/theme_provider.dart` | AppThemeMode enum追加、autoTime実装 | | `lib/screens/settings_screen.dart` | 4つ目の選択肢追加、状態表示追加 | | `lib/services/hive_service.dart` | autoTimeモードの永続化対応 | ### テスト計画 **1. 時刻判定テスト** ```dart // テスト用時刻注入 class TimeService { static DateTime Function() now = () => DateTime.now(); } // テストケース: // 05:59 → ダーク // 06:00 → ライト // 19:59 → ライト // 20:00 → ダーク ``` **2. UI動作テスト** - [ ] 設定で「自動(夜間ダーク)」を選択できる - [ ] 現在の適用状態が表示される - [ ] アプリ再起動後も設定が保持される - [ ] 時刻をまたいでアプリを開くとテーマが変わる **3. パフォーマンステスト** - [ ] 電池消費が増えていない - [ ] アプリ復帰時の遅延がない --- ## Feature 2: 和風フォント対応 🖋️ ### 要件定義 - **既存**: システムフォント(Noto Sans JP相当) - **追加**: 日本酒らしい和風フォント - **実装方式**: Google Fonts(動的読み込み) - **ユーザー設定**: 設定画面で選択可能 ### フォント候補 #### Option 1: Potta One(推奨 - Antigravity提案) - **特徴**: 丸みがあり親しみやすい、読みやすい - **サイズ**: ~2MB - **用途**: メイン表示、カジュアルな雰囲気 - **プレビュー**: ぽんしゅルーム / 純米大吟醸 #### Option 2: Yuji Syuku - **特徴**: 筆文字風、書道感が強い - **サイズ**: ~1.5MB - **用途**: タイトル、高級感演出 - **プレビュー**: ぽんしゅルーム / 純米大吟醸 #### Option 3: Shippori Mincho - **特徴**: 明朝体、洗練された印象 - **サイズ**: ~3MB - **用途**: フォーマルな表示、詳細画面 - **プレビュー**: ぽんしゅルーム / 純米大吟醸 #### Option 4: Zen Maru Gothic - **特徴**: ゴシック体、モダン和風 - **サイズ**: ~2MB - **用途**: 全般的な表示、バランス重視 - **プレビュー**: ぽんしゅルーム / 純米大吟醸 **初回実装: Potta One(1種類のみ)** 将来的に複数選択肢を追加可能な設計にする。 ### 技術仕様 #### A. フォント定義 ```dart enum AppFontStyle { standard, // システムフォント pottaOne, // 丸文字(和風カジュアル) // 将来の拡張: // yujiSyuku, // 筆文字 // shipporiMincho, // 明朝体 } ``` #### B. テーマ適用 ```dart // app_theme.dart class AppTheme { static ThemeData buildTheme({ required Brightness brightness, required AppFontStyle fontStyle, }) { final TextTheme textTheme; switch (fontStyle) { case AppFontStyle.pottaOne: textTheme = GoogleFonts.pottaOneTextTheme(); break; case AppFontStyle.standard: default: textTheme = const TextTheme(); // システムデフォルト } return ThemeData( brightness: brightness, textTheme: textTheme, // ... 既存の設定 ); } } ``` #### C. Provider統合 ```dart class ThemeProvider extends ChangeNotifier { AppFontStyle _fontStyle = AppFontStyle.standard; void setFontStyle(AppFontStyle style) { _fontStyle = style; notifyListeners(); // Hiveに保存 } } ``` #### D. UI実装 **設定画面の選択肢:** ``` フォント設定 ○ 標準フォント ● 和風フォント(丸文字) プレビュー: ┌─────────────────┐ │ ぽんしゅルーム │ ← 実際のフォントで表示 │ 純米大吟醸 │ └─────────────────┘ ``` ### 実装ファイル | ファイル | 変更内容 | |---------|---------| | `pubspec.yaml` | google_fonts: ^6.1.0(既存) | | `lib/theme/app_theme.dart` | AppFontStyle対応、GoogleFonts統合 | | `lib/providers/theme_provider.dart` | フォント設定管理 | | `lib/screens/settings_screen.dart` | フォント選択UI追加 | | `lib/services/hive_service.dart` | フォント設定の永続化 | ### パフォーマンス考慮 **初回読み込み:** - Google Fontsは初回のみネットワークからダウンロード - キャッシュに保存される(2回目以降は即座に表示) - ダウンロード中はシステムフォントで表示(フォント切替時の一瞬のちらつき) **オフライン対応(オプション):** ```yaml # pubspec.yaml fonts: - family: PottaOne fonts: - asset: assets/fonts/PottaOne-Regular.ttf ``` - 事前にアセットとして含める(アプリサイズ +2MB) - ネットワーク不要で即座に表示 **推奨: Google Fonts動的読み込み**(初回実装) アプリサイズを増やさず、将来的に複数フォント追加が容易。 ### テスト計画 **1. フォント適用テスト** - [ ] 設定で「和風フォント」を選択できる - [ ] 全画面でフォントが変わる(Home, Detail, Settings) - [ ] PDFでもフォントが反映される ※重要 - [ ] アプリ再起動後も設定が保持される **2. 読みやすさテスト** - [ ] 短文(銘柄名): 視認性OK - [ ] 長文(説明文): 読みやすさOK - [ ] 小サイズ(10px〜): 潰れない - [ ] ダークモード: コントラストOK **3. パフォーマンステスト** - [ ] 初回読み込み時間: 3秒以内 - [ ] 2回目以降: 即座に表示 - [ ] アプリサイズ増加: 0MB(動的読み込み) **4. PDF出力テスト** - [ ] PDF生成時にPotta Oneが使用される - [ ] PDFファイルサイズが適切(フォント埋め込み) - [ ] 印刷時にフォントが正しく表示される --- ## 実装スケジュール ### Phase 4A: ダークモード自動切替(所要時間: 2-3時間) **Step 1: Provider実装(30分)** - [ ] `AppThemeMode` enum追加 - [ ] `effectiveThemeMode` ロジック実装 - [ ] `WidgetsBindingObserver` 統合 **Step 2: UI実装(30分)** - [ ] 設定画面に「自動(夜間ダーク)」追加 - [ ] 現在の状態表示を追加 **Step 3: 永続化(30分)** - [ ] Hiveに `autoTime` モード保存 - [ ] 起動時の復元処理 **Step 4: テスト(1時間)** - [ ] 時刻判定テスト(モック使用) - [ ] UI動作確認 - [ ] 実機で夜間動作確認 ### Phase 4B: 和風フォント対応(所要時間: 2-3時間) **Step 1: テーマ実装(30分)** - [ ] `AppFontStyle` enum追加 - [ ] `AppTheme.buildTheme()` にフォント統合 - [ ] GoogleFonts.pottaOne() 適用 **Step 2: Provider実装(30分)** - [ ] ThemeProviderにフォント設定追加 - [ ] setFontStyle() 実装 **Step 3: UI実装(30分)** - [ ] 設定画面にフォント選択追加 - [ ] プレビュー表示 **Step 4: PDF対応(30分)** - [ ] PdfService でフォント設定を参照 - [ ] Potta One をPDFに埋め込み **Step 5: テスト(1時間)** - [ ] 全画面でフォント確認 - [ ] PDF出力確認 - [ ] パフォーマンス計測 --- ## リスク管理 ### リスク1: Google Fonts読み込み失敗 **シナリオ**: ネットワーク不安定、サーバーダウン **影響**: フォントがシステムフォントにフォールバック **対策**: - エラー時にユーザーに通知 - 次回起動時に再試行 - 最終的にはアセット埋め込みも検討 ### リスク2: PDFフォント埋め込み失敗 **シナリオ**: `pdf` パッケージがGoogle Fontsをサポートしない **影響**: PDFは標準フォントで生成される **対策**: - 事前に検証(PDF生成テスト) - 必要ならTTFファイルを手動ダウンロードして埋め込み ### リスク3: ダークモード切替のタイミングずれ **シナリオ**: アプリをバックグラウンドで長時間起動 **影響**: 20:00になってもライトモードのまま **対策**: - `WidgetsBindingObserver` で確実に検知 - 設定画面を開いた時も強制再計算 --- ## 成果物 ### コード変更 - `lib/providers/theme_provider.dart` (+50 lines) - `lib/theme/app_theme.dart` (+30 lines) - `lib/screens/settings_screen.dart` (+80 lines) - `lib/services/hive_service.dart` (+20 lines) ### ドキュメント - この実装計画書 - ユーザー向けリリースノート(後ほど作成) ### テスト結果レポート - ダークモード自動切替の動作確認 - フォント適用の全画面スクリーンショット --- ## 次フェーズへの展望 ### Phase 4C: フォント拡張(将来) - 複数フォント選択肢(Yuji Syuku, Shippori Mincho) - フォントサイズ調整(大/中/小) - 部分的フォント適用(タイトルのみ和風、本文は標準) ### Phase 4D: テーマカスタマイズ(将来) - カラーテーマ選択(青/緑/赤など) - アクセントカラー変更 - カスタムテーマ保存 --- ## 承認 **この計画で実装を開始してよろしいでしょうか?** 承認いただければ、Phase 4A(ダークモード)から実装を開始します。 --- **End of Plan**