# 機能設計書 64-テーマ切替

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおけるテーマ切替機能の設計を記述するものである。アプリのカラースキーム（ライト/ダーク/システム連動）を切り替える機能の仕様を定義する。

### 本機能の処理概要

本機能は、アプリの外観テーマを3つのモード（System：システム設定に連動、Light：明るいテーマ、Dark：暗いテーマ）から選択できるダイアログを提供する。選択されたテーマはAdaptiveThemeパッケージにより管理され、アプリ全体に即座に反映される。

**業務上の目的・背景**：現場作業では照明環境が様々であり、倉庫内の暗い場所ではダークテーマが目に優しく、明るいオフィスではライトテーマが見やすい場合がある。また、デバイスのシステム設定に連動させることで、自動的に最適なテーマが選択される。本機能により、ユーザーは作業環境に応じてアプリの外観をカスタマイズできる。

**機能の利用シーン**：
- 作業環境の明るさに応じてテーマを切り替えたい場合
- 夜間作業時に目の疲れを軽減するためダークテーマに切り替えたい場合
- デバイスのシステム設定に連動させて自動切り替えを行いたい場合

**主要な処理内容**：
1. ドロワーメニューからテーマ選択ダイアログの表示
2. 現在のテーマモードのラジオボタン選択状態の表示
3. ユーザーがテーマを選択するとAdaptiveThemeにより即座に適用
4. 選択されたテーマは次回起動時にも保持される

**関連システム・外部連携**：adaptive_themeパッケージを使用してテーマ管理を行う。テーマ設定は自動的に永続化される。

**権限による制御**：本機能に特別な権限制御はなく、すべてのユーザーが利用可能である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | ドロワーメニュー | 主画面 | テーマ選択ダイアログの表示とテーマ変更処理 |

## 機能種別

UI設定 / CRUD操作（Read/Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| themeMode | AdaptiveThemeMode | Yes | 選択されたテーマモード | system/light/dark |

### 入力データソース

- 画面入力：テーマ選択ダイアログのRadioListTileからの選択操作
- ローカルストレージ：AdaptiveThemeによる自動永続化

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| themeMode | AdaptiveThemeMode | 選択されたテーマモード |

### 出力先

- アプリ全体：MaterialAppのtheme/darkTheme切り替え
- ローカルストレージ：AdaptiveThemeによる自動永続化

## 処理フロー

### 処理シーケンス

```
1. ドロワーメニュー表示
   └─ テーマ設定タイルに現在のテーマアイコンを表示
2. テーマタイルタップ
   └─ ThemeSelectionDialogを表示
3. テーマ選択（RadioListTileタップ）
   └─ AdaptiveTheme.of(context).setThemeMode()でテーマ適用
   └─ onThemeSelectedコールバックでダイアログとドロワーを閉じる
```

### フローチャート

```mermaid
flowchart TD
    A[ドロワーメニュー表示] --> B[テーマタイル表示]
    B --> C{テーマタイルタップ}
    C --> D[ThemeSelectionDialog表示]
    D --> E{テーマ選択}
    E -->|System| F[setThemeMode system]
    E -->|Light| G[setThemeMode light]
    E -->|Dark| H[setThemeMode dark]
    F --> I[ダイアログ閉じる]
    G --> I
    H --> I
    I --> J[ドロワー閉じる]
    E -->|Cancel| K[ダイアログ閉じる]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-64-01 | デフォルトテーマ | 初回起動時はSystemモードが適用される | 初回起動時 |
| BR-64-02 | 即時適用 | テーマ選択は即座にアプリ全体に反映 | テーマ選択時 |
| BR-64-03 | 永続化 | 選択されたテーマは次回起動時にも保持 | テーマ選択後 |
| BR-64-04 | System連動 | Systemモード選択時はデバイスのダーク/ライト設定に連動 | Systemモード時 |

### 計算ロジック

該当なし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| テーマ読み込み | SharedPreferences | SELECT | AdaptiveThemeが自動的に管理 |
| テーマ保存 | SharedPreferences | UPDATE | AdaptiveThemeが自動的に管理 |

### テーブル別操作詳細

AdaptiveThemeパッケージが内部的にSharedPreferencesを使用してテーマモードを永続化する。アプリコードでは直接操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | テーマ適用エラー | 通常発生しない | デフォルトテーマを適用 |

### リトライ仕様

リトライは不要。AdaptiveThemeパッケージが内部で適切にハンドリングする。

## トランザクション仕様

SharedPreferencesの単一値操作のため、明示的なトランザクション管理は不要。

## パフォーマンス要件

- テーマ切り替え：即座（16ms以内）
- 次回起動時のテーマ復元：100ms以内

## セキュリティ考慮事項

- テーマ設定はローカルデバイスにのみ保存
- 機密情報は含まれないため、暗号化は不要

## 備考

- AdaptiveThemeパッケージを使用することで、テーマの永続化と復元が自動的に行われる
- ThemeSelectionDialogは独立したStatelessWidgetとして実装されている
- ドロワーのテーマタイルには現在のテーマモードに対応するアイコンが表示される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

AdaptiveThemeModeの列挙型とテーマ設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | main.dart | `lib/main.dart` | AdaptiveThemeの初期化と設定 |

**読解のコツ**:
- **24行目**: `AdaptiveTheme.getThemeMode()`で保存されたテーマモードを取得
- **158-189行目**: `AdaptiveTheme`ウィジェットでライト/ダークテーマを定義
- **169行目**: `initial`パラメータで初期テーマモードを設定

#### Step 2: テーマ選択ダイアログを理解する

ThemeSelectionDialogの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | drawer.dart | `lib/widget/drawer.dart` | ThemeSelectionDialogクラス |

**主要処理フロー**:
1. **23-95行目**: `ThemeSelectionDialog`がStatelessWidgetとして定義
2. **24-25行目**: コンストラクタで`onThemeSelected`コールバックを受け取る
3. **31行目**: `AdaptiveTheme.of(context).mode`で現在のテーマモードを取得
4. **38-51行目**: Systemテーマ選択のRadioListTile
5. **53-66行目**: Lightテーマ選択のRadioListTile
6. **68-81行目**: Darkテーマ選択のRadioListTile
7. **49行目**: `AdaptiveTheme.of(context).setThemeMode()`でテーマを適用

#### Step 3: ドロワーメニューとの連携を理解する

InvenTreeDrawerからの呼び出しを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | drawer.dart | `lib/widget/drawer.dart` | InvenTreeDrawerクラスのテーマ関連処理 |

**主要処理フロー**:
- **196-206行目**: `_getThemeModeIcon`メソッドで現在のテーマに対応するアイコンを返す
- **285-305行目**: テーマ設定タイルの定義とダイアログ表示処理
- **287-298行目**: `showDialog`でThemeSelectionDialogを表示
- **303行目**: `trailing`に現在のテーマアイコンを表示

### プログラム呼び出し階層図

```
InvenTreeApp (main.dart)
    │
    ├─ AdaptiveTheme
    │      ├─ light: ThemeData(brightness: Brightness.light)
    │      └─ dark: ThemeData(brightness: Brightness.dark)
    │
    └─ InvenTreeDrawer (drawer.dart)
           │
           ├─ _getThemeModeIcon()
           │      └─ 現在テーマに対応するアイコンを返す
           │
           └─ ListTile (テーマ設定)
                  └─ onTap: showDialog
                         └─ ThemeSelectionDialog
                                │
                                ├─ RadioListTile (System)
                                │      └─ AdaptiveTheme.setThemeMode(system)
                                ├─ RadioListTile (Light)
                                │      └─ AdaptiveTheme.setThemeMode(light)
                                └─ RadioListTile (Dark)
                                       └─ AdaptiveTheme.setThemeMode(dark)
```

### データフロー図

```
[入力]                        [処理]                         [出力]

                      ┌─────────────────────┐
SharedPreferences ───▶│ AdaptiveTheme       │
(テーマモード)         │ - getThemeMode()    │
                      └──────────┬──────────┘
                                 │
                                 ▼
                      ┌─────────────────────┐
                      │ InvenTreeApp        │──────▶ アプリテーマ適用
                      │ - light/dark theme  │
                      └──────────┬──────────┘
                                 │
                                 ▼
                      ┌─────────────────────┐
RadioListTileタップ ──▶│ setThemeMode()      │
                      │ - 即時テーマ適用     │──────▶ SharedPreferences
                      │ - 自動永続化        │        (テーマモード保存)
                      └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| drawer.dart | `lib/widget/drawer.dart` | ソース | ドロワーメニュー・ThemeSelectionDialog |
| main.dart | `lib/main.dart` | ソース | アプリ初期化・AdaptiveTheme設定 |
| l10.dart | `lib/l10.dart` | ソース | 多言語テキスト取得ヘルパー |
| app_colors.dart | `lib/app_colors.dart` | ソース | アプリ共通カラー定義 |
