ponshu-room-lite/docs/phase4_implementation_plan.md

409 lines
12 KiB
Markdown
Raw Permalink Normal View History

# 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 One1種類のみ**
将来的に複数選択肢を追加可能な設計にする。
### 技術仕様
#### 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**