# 機能設計書 9-フィードカスタマイズ

## 概要

本ドキュメントは、Wikipedia iOSアプリにおけるフィードカスタマイズ機能の設計仕様を記述する。探索フィードに表示するカードの種類や言語を設定する。

### 本機能の処理概要

**業務上の目的・背景**：ユーザーが自分の興味関心に合わせて探索フィードをカスタマイズできるようにする。不要なカードタイプを非表示にしたり、特定の言語のコンテンツのみ表示したりすることで、よりパーソナライズされた体験を提供する。

**機能の利用シーン**：
- 設定画面から「Explore feed」を選択した時
- 特定のカードタイプを非表示にしたい時
- 複数言語を設定している場合に言語別にカードを管理したい時
- 探索タブ自体をオフにしたい時

**主要な処理内容**：
1. カードタイプ別の表示/非表示切り替え
2. 言語別のカード表示設定
3. グローバルカード（言語非依存）の設定
4. 探索タブ全体のオン/オフ切り替え
5. 設定変更後のフィード更新

**関連システム・外部連携**：
- FeedContentController（フィード設定の反映）
- UserDefaults（タブタイプの保存）

**権限による制御**：
- 特別な権限は不要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | ExploreFeedSettings画面 | 主画面 | フィードカードの設定変更 |
| 1 | Explore画面 | 連携画面 | 設定変更の反映 |

## 機能種別

設定管理 / 表示制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| dataStore | MWKDataStore | Yes | データストアインスタンス | nil不可 |
| theme | Theme | Yes | 適用するテーマ | 有効なThemeオブジェクト |

### 設定可能なカードタイプ（WMFContentGroupKind）

| カードタイプ | タイトル | 説明 | グローバル |
|-------------|---------|------|-----------|
| news | In the news | ニュース記事 | No |
| onThisDay | On this day | 今日の出来事 | No |
| featuredArticle | Featured article | 特集記事 | No |
| topRead | Top read | 人気記事 | No |
| location | Places | 近くの記事 | No |
| random | Randomizer | ランダム記事 | No |
| pictureOfTheDay | Picture of the day | 今日の画像 | Yes |
| continueReading | Continue reading | 続きを読む | Yes |
| relatedPages | Related pages | 関連記事 | Yes |
| suggestedEdits | Suggested edits | 編集の提案 | Yes |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 設定変更通知 | Notification | WMFExploreFeedPreferencesDidSave |
| タブタイプ | DefaultTabType | explore または settings |

### 出力先

- FeedContentController（カード表示設定）
- UserDefaults（タブタイプ設定）
- NotificationCenter（設定変更通知）

## 処理フロー

### 処理シーケンス

```
1. ExploreFeedSettingsViewController初期化
   └─ dataStoreを受け取り初期化

2. viewDidLoad
   └─ preferredLanguages.countでdisplayType判定
   └─ singleLanguage: スイッチ形式
   └─ multipleLanguages: disclosure形式

3. セクション構成
   └─ customizationSection: カードタイプ一覧
   └─ languagesSection: 言語別設定（multipleの場合）
   └─ mainSection: Explore全体のオン/オフ

4. スイッチトグル処理
   └─ settingsTableViewCell:didToggleDisclosureSwitch
   └─ controlTagでカードタイプを識別
   └─ feedContentController.toggleContentGroup呼び出し

5. Exploreオン/オフ
   └─ controlTag == -1で全体切り替え
   └─ アラートダイアログで確認
   └─ UserDefaults.defaultTabTypeを更新

6. viewWillDisappear
   └─ feedContentController.updateFeedSourcesUserInitiated
```

### フローチャート

```mermaid
flowchart TD
    A[設定画面表示] --> B{言語数}
    B -->|1言語| C[singleLanguageモード]
    B -->|複数言語| D[multipleLanguagesモード]
    C --> E[スイッチ形式でカード設定]
    D --> F[disclosure形式でカード設定]
    E --> G{ユーザーアクション}
    F --> G
    G -->|カードON/OFF| H[toggleContentGroup]
    G -->|言語別設定| I[FeedCardSettingsVC]
    G -->|Explore全体| J{ON/OFF?}
    J -->|OFF| K[アラート表示]
    J -->|ON| L[アラート表示]
    K --> M[defaultTabType = settings]
    L --> N[defaultTabType = explore]
    H --> O[フィード更新]
    M --> O
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 表示モード | 1言語ならスイッチ、複数言語ならdisclosure | preferredLanguages.count |
| BR-002 | グローバルカード | 言語に依存しないカードは特別扱い | isGlobal == true |
| BR-003 | Suggested Edits | 編集数50以上かつVoiceOffでないと表示 | editCount >= 50 && !isVoiceOverRunning |
| BR-004 | Explore無効化 | 全カードを非表示にするとExploreタブがSettingsに置換 | 全カードOFF |
| BR-005 | 確認ダイアログ | Explore ON/OFF時にアラートで確認 | 常時 |

### 表示モードによるUI差異

| モード | スイッチ | ディスクロージャ | サブタイトル |
|--------|---------|----------------|-------------|
| singleLanguage | Yes | No | 説明テキスト |
| multipleLanguages | No | Yes | 有効な言語コード |

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| カード設定 | WMFContentGroup | UPDATE | isInFeedフラグ更新 |
| 言語設定 | WMFContentGroup | UPDATE | 言語別表示設定 |

### UserDefaults操作

| キー | 操作 | 値 |
|-----|------|-----|
| defaultTabType | READ/WRITE | .explore / .settings |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 言語配列空 | preferredLanguagesが空 | assertionFailure |

### リトライ仕様

- 特別なリトライ処理なし

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

- 設定変更は即時反映
- viewWillDisappearでフィード更新をトリガー

## パフォーマンス要件

- 設定画面表示：即時
- 設定反映：フィード更新完了まで数秒

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

- 特別なセキュリティ要件なし

## 備考

- iPadでも同一のUI
- showCloseButton=trueでモーダル表示時に閉じるボタン表示

---

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

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

### 推奨読解順序

#### Step 1: メインViewControllerを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | 設定画面のメインVC |

**主要コード**:
- **4-155行目**: FeedCardクラス - カード設定項目のモデル
- **157-294行目**: ExploreFeedSettingsViewController - メインVC
- **175-179行目**: viewDidLoad - displayType判定
- **207-230行目**: feedCards - カードタイプ一覧の遅延初期化
- **240-265行目**: sections - セクション構成
- **269-293行目**: turnOnExploreAlertController/turnOffExploreAlertController
- **320-370行目**: settingsTableViewCell:didToggleDisclosureSwitch - スイッチ処理

#### Step 2: カード設定モデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | FeedCardクラス |

**主要コード**:
- **16-102行目**: init - カードタイプ別の初期化
- **104-136行目**: multipleLanguagesDisclosureText/multipleLanguagesSubtitle

**読解のコツ**: switchで各contentGroupKindごとにタイトル、説明、アイコンを設定している。

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

```
ExploreFeedSettingsViewController
    │
    ├─ FeedCard (カード設定モデル)
    │      └─ WMFContentGroupKind
    │
    ├─ UITableView
    │      ├─ customizationSection (カードタイプ一覧)
    │      ├─ languagesSection (言語別設定)
    │      └─ mainSection (Explore ON/OFF)
    │
    ├─ WMFSettingsTableViewCellDelegate
    │      └─ settingsTableViewCell:didToggleDisclosureSwitch
    │             └─ FeedContentController.toggleContentGroup
    │
    ├─ FeedCardSettingsViewController (言語別詳細)
    │
    └─ UIAlertController (確認ダイアログ)
           └─ UserDefaults.defaultTabType
```

### データフロー図

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

preferredLanguages ─────▶ displayType判定
                               │
                         ┌─────┴─────┐
                         ▼           ▼
                    [singleLanguage] [multipleLanguages]
                         │           │
                         └─────┬─────┘
                               ▼
                         UITableView表示
                               │
ユーザー操作 ──────────────▶    │
                               ▼
                         toggleContentGroup()
                               │
                               ▼
                         WMFContentGroup.isInFeed更新
                               │
                               ▼
                         [フィード更新]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ExploreFeedSettingsViewController.swift | `Wikipedia/Code/` | ソース | メインVC |
| BaseExploreFeedSettingsViewController.swift | `Wikipedia/Code/` | ソース | 基底クラス |
| FeedCardSettingsViewController.swift | `Wikipedia/Code/` | ソース | 言語別設定 |
| WMFSettingsTableViewCell.swift | `Wikipedia/Code/` | ソース | 設定セル |
| FeedContentController.swift | `WMF Framework/` | ソース | フィード制御 |
| WMFContentGroupKind.swift | `WMF Framework/` | ソース | カード種別enum |
