409 lines
12 KiB
Markdown
409 lines
12 KiB
Markdown
# 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**
|