# 機能設計書 47-外観設定

## 概要

本ドキュメントは、Wikipedia iOSアプリにおける外観設定機能の設計を記載する。テーマ（ライト/セピア/ダーク/ブラック）、フォントサイズ、画像の減光、テーブル展開などの外観に関する設定を管理する機能である。

### 本機能の処理概要

外観設定機能は、AppearanceSettingsViewControllerを通じて、アプリの視覚的な設定をユーザーがカスタマイズできる画面を提供する。

**業務上の目的・背景**：ユーザーの読書体験を最適化するため、好みに合わせたテーマ選択、文字サイズ調整、ダークモード時の画像減光などの機能を提供する。視覚的なアクセシビリティ向上にも貢献する。

**機能の利用シーン**：設定画面から「Reading Preferences」をタップして遷移。夜間読書用にダークテーマを選択、文字サイズを大きくして可読性向上、画像の減光で目の負担軽減などに使用される。

**主要な処理内容**：
1. 読書テーマ選択（デフォルト/ライト/セピア/ダーク/ブラック）
2. 画像減光設定（ダーク/ブラックテーマ時）
3. テーブル自動展開設定
4. テキストサイズ調整
5. アプリアイコン変更（Year in Review対象ユーザー）

**関連システム・外部連携**：UserDefaultsでテーマ名、画像減光設定、テーブル展開設定を保存。NotificationCenterでテーマ変更を通知。

**権限による制御**：特別な権限は不要。Year in Reviewアプリアイコンは対象ユーザーのみ表示。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 42 | AppearanceSettings画面 | 主画面 | テーマ・フォントサイズ等の外観設定 |
| 75 | ReadingThemesControls画面 | 参照画面 | テーマ切り替えの適用 |

## 機能種別

設定管理 / UI制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| theme | String | Yes | 選択されたテーマ名 | 有効なテーマ名のみ |
| isImageDimmingEnabled | Bool | No | 画像減光の有効/無効 | - |
| isAutomaticTableOpeningEnabled | Bool | No | テーブル自動展開の有効/無効 | - |

### 入力データソース

- 画面操作（テーマ選択、スイッチ操作、スライダー操作）
- UserDefaults（保存済み設定値）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| themeName | String | 選択されたテーマ名 |
| wmf_isImageDimmingEnabled | Bool | 画像減光設定 |
| wmf_isAutomaticTableOpeningEnabled | Bool | テーブル自動展開設定 |

### 出力先

- UserDefaults（設定値の永続化）
- NotificationCenter（WMFUserDidSelectThemeNotification）

## 処理フロー

### 処理シーケンス

```
1. viewDidLoad()
   ├─ テーブルビューセル登録
   └─ sectionsForAppearanceSettings() でセクション構成
2. sectionsForAppearanceSettings()
   ├─ 読書テーマセクション（デフォルト/ライト/セピア/ダーク/ブラック）
   ├─ テーマオプションセクション（画像減光）
   ├─ テーブル設定セクション（テーブル自動展開）
   ├─ テキストサイズセクション
   └─ アプリアイコンセクション（条件付き）
3. ユーザー操作
   ├─ テーマ選択: userDidSelect(theme:) → NotificationCenter通知
   ├─ 画像減光スイッチ: handleImageDimmingSwitchValueChange()
   ├─ テーブル展開スイッチ: handleAutomaticTableOpenSwitchValueChange()
   └─ アプリアイコン選択: AppIconUtility.shared.updateAppIcon()
4. 設定値の永続化
   └─ UserDefaultsへの保存
```

### フローチャート

```mermaid
flowchart TD
    A[viewDidLoad] --> B[セクション構成]
    B --> C[テーブルビュー表示]
    C --> D{ユーザー操作}
    D -->|テーマ選択| E[userDidSelect]
    D -->|画像減光トグル| F[handleImageDimmingSwitch]
    D -->|テーブル展開トグル| G[handleAutomaticTableOpenSwitch]
    D -->|アプリアイコン選択| H[AppIconUtility.updateAppIcon]
    E --> I[NotificationCenter通知]
    F --> J[applyImageDimmingChange]
    G --> K[UserDefaults保存]
    H --> L[アプリアイコン変更]
    I --> M[全画面テーマ適用]
    J --> I
    K --> N[設定完了]
    L --> N
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-47-01 | デフォルトテーマ | "standard"はシステムテーマに追従 | デフォルト選択時 |
| BR-47-02 | 画像減光適用 | ダーク/ブラックテーマ時のみ画像減光が有効 | ダーク系テーマ選択時 |
| BR-47-03 | テーマ名の接頭辞チェック | 現在のテーマがcheckmarkItem.themeで始まるかでチェック状態決定 | テーマ選択表示時 |
| BR-47-04 | アプリアイコン表示条件 | Year in Review対象かつ期限内の場合のみ表示 | セクション構成時 |
| BR-47-05 | スイッチ操作の遅延適用 | アニメーション完了後に設定適用 | スイッチ操作時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| テーマ選択 | UserDefaults | UPDATE | themeName の保存 |
| 画像減光設定 | UserDefaults | UPDATE | wmf_isImageDimmingEnabled の保存 |
| テーブル展開設定 | UserDefaults | UPDATE | wmf_isAutomaticTableOpeningEnabled の保存 |

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

#### UserDefaults

| 操作 | 項目（キー名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | themeName | テーマ名（light/sepia/dark/black/standard等） | NotificationCenter経由で更新 |
| UPDATE | wmf_isImageDimmingEnabled | true/false | スイッチ操作時 |
| UPDATE | wmf_isAutomaticTableOpeningEnabled | true/false | スイッチ操作時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | - | 特別なエラー処理なし（UI操作のみ） |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- スイッチ操作はアニメーション完了後に適用（遅延実行）
- テーマ変更は即座に全画面に反映

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

- 設定値はUserDefaultsに保存（機密情報は含まない）
- アプリアイコン変更はiOS標準機能を使用

## 備考

- Theme: light、sepia、dark、darkDimmed、black、blackDimmed、widgetLight、widgetDarkの各種テーマ
- AppearanceSettingsItemプロトコル: 各設定項目の共通インターフェース
- カスタムビューセル: ImageDimmingExampleViewController、FontSizeSliderViewController、TextSizeChangeExampleViewController

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AppearanceSettingsViewController.swift | `Wikipedia/Code/AppearanceSettingsViewController.swift` | AppearanceSettingsItemプロトコル、各種設定アイテム構造体 |

**読解のコツ**:
- **4-7行目**: AppearanceSettingsItemプロトコル（title、subtitle）
- **9-12行目**: AppearanceSettingsDimSwitchItem（画像減光スイッチ）
- **14-17行目**: AppearanceSettingsAutomaticTableOpenSwitchItem（テーブル展開スイッチ）
- **19-24行目**: AppearanceSettingsCheckmarkItem（テーマ選択項目）
- **26-31行目**: AppearanceSettingsIconItem（アプリアイコン選択項目）
- **33-37行目**: AppearanceSettingsSection（セクション定義）

#### Step 2: メイン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppearanceSettingsViewController.swift | `Wikipedia/Code/AppearanceSettingsViewController.swift` | sectionsForAppearanceSettings()、cellForRowAt |

**主要処理フロー**:
- **89-146行目**: sectionsForAppearanceSettings() - セクション構成の構築
- **91-95行目**: checkmarkItem(for:)ヘルパー関数でテーマ選択項目生成
- **97-101行目**: デフォルトテーマ項目の生成
- **103行目**: 5つのテーマ項目配列
- **105-112行目**: 各セクションの生成
- **156-245行目**: tableView(_:cellForRowAt:) - セルの生成とカスタマイズ

#### Step 3: ユーザー操作ハンドリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AppearanceSettingsViewController.swift | `Wikipedia/Code/AppearanceSettingsViewController.swift` | userDidSelect、handleSwitchValueChange |

**主要処理フロー**:
- **262-268行目**: userDidSelect(theme:isImageDimmingEnabled:) - テーマ選択通知
- **324-328行目**: handleImageDimmingSwitchValueChange() - 画像減光スイッチ
- **334-338行目**: handleAutomaticTableOpenSwitchValueChange() - テーブル展開スイッチ

#### Step 4: テーマシステムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Theme.swift | `WMF Framework/Theme.swift` | Themeクラス、Colorsクラス |

**主要処理フロー**:
- **821-993行目（Theme.swift）**: Themeクラスの定義
- **942-956行目**: 各テーマ（light、sepia、dark、darkDimmed、black、blackDimmed等）のインスタンス
- **922行目**: defaultThemeName = "standard"
- **976行目**: themesByName辞書でテーマ名からThemeオブジェクトを取得

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

```
AppearanceSettingsViewController
    │
    ├─ viewDidLoad()
    │      └─ sectionsForAppearanceSettings()
    │             │
    │             ├─ AppearanceSettingsSection（読書テーマ）
    │             │      └─ AppearanceSettingsCheckmarkItem × 5
    │             │
    │             ├─ AppearanceSettingsSection（テーマオプション）
    │             │      └─ AppearanceSettingsDimSwitchItem
    │             │
    │             ├─ AppearanceSettingsSection（テーブル設定）
    │             │      └─ AppearanceSettingsAutomaticTableOpenSwitchItem
    │             │
    │             └─ AppearanceSettingsSection（テキストサイズ）
    │                    └─ FontSizeSliderViewController
    │
    ├─ tableView(_:didSelectRowAt:)
    │      └─ checkmarkItem.checkmarkAction()
    │             └─ userDidSelect(theme:)
    │                    └─ NotificationCenter.post(WMFUserDidSelectThemeNotification)
    │
    └─ handleImageDimmingSwitchValueChange()
           └─ applyImageDimmingChange()
                  └─ userDidSelect(theme:isImageDimmingEnabled:)
```

### データフロー図

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

テーマ選択タップ      ───▶ checkmarkItem.checkmarkAction()
                           │
                           ▼
                    userDidSelect(theme:)
                           │
                           ▼
                    NotificationCenter.post() ───────────▶ WMFUserDidSelectThemeNotification
                                                                    │
                                                                    ▼
                                                          全画面にテーマ適用
                                                                    │
                                                                    ▼
                                                          UserDefaults保存

スイッチ操作         ───▶ handleSwitchValueChange()
                           │
                           ▼
                    UserDefaults保存 ───────────────────▶ 設定値永続化
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppearanceSettingsViewController.swift | `Wikipedia/Code/AppearanceSettingsViewController.swift` | ソース | 外観設定画面のViewController |
| Theme.swift | `WMF Framework/Theme.swift` | ソース | テーマ定義とThemeableプロトコル |
| ImageDimmingExampleViewController.swift | `Wikipedia/Code/ImageDimmingExampleViewController.swift` | ソース | 画像減光プレビュー |
| TextSizeChangeExampleViewController.swift | `Wikipedia/Code/TextSizeChangeExampleViewController.swift` | ソース | テキストサイズプレビュー |
| FontSizeSliderViewController.swift | `Wikipedia/Code/FontSizeSliderViewController.swift` | ソース | フォントサイズスライダー |
| ReadingThemesControlsViewController.swift | `Wikipedia/Code/ReadingThemesControlsViewController.swift` | ソース | テーマ変更通知の受信処理 |
| AppIconUtility.swift | - | ソース | アプリアイコン変更ユーティリティ |
