# 画面設計書 43-ExploreFeedSettings画面

## 概要

本ドキュメントはWikipedia iOSアプリにおけるExploreフィード設定画面（ExploreFeedSettingsViewController）の設計内容を記載したものです。

### 本画面の処理概要

ExploreFeedSettings画面は、Wikipedia iOSアプリのExplore画面（ホームフィード）に表示されるコンテンツカードをカスタマイズするための画面です。ユーザーはフィードに表示する各種カード（ニュース、今日の出来事、おすすめ記事など）の表示/非表示を設定でき、複数言語を設定している場合は言語別の制御も可能です。

**業務上の目的・背景**：ユーザーがExploreフィードを自分の興味に合わせてカスタマイズできるようにし、より快適な情報閲覧体験を提供します。不要なカードを非表示にすることで、関心のあるコンテンツにより素早くアクセスできます。また、Exploreタブ自体のオン/オフ切り替えも可能で、設定タブに置き換えることもできます。

**画面へのアクセス方法**：
1. 設定画面（Settings）から「Explore feed」項目をタップ
2. Explore画面のギアアイコンから直接アクセス

**主要な操作・処理内容**：
1. 各フィードカード（In the news、On this day、Featured article等）の表示/非表示切り替え
2. 言語別のカード表示設定（複数言語設定時）
3. グローバルカード（言語非依存カード）の一括制御
4. Exploreタブ自体のオン/オフ切り替え

**画面遷移**：
- 遷移元：Settings画面、Explore画面
- 遷移先：FeedCardSettings画面（複数言語設定時、カードをタップ）

**権限による表示制御**：
- Suggested Editsカードは、VoiceOverが無効かつ編集回数が50回以上のユーザーにのみ表示
- 複数言語設定時と単一言語設定時でUI構成が異なる

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | フィードカスタマイズ | 主機能 | 探索フィードに表示するコンテンツの設定 |

## 画面種別

設定（スイッチ切替型設定画面 + 詳細画面遷移）

## URL/ルーティング

iOSネイティブアプリのため、URLは使用しない。画面遷移はUINavigationControllerのpush遷移とモーダル表示で管理。

## 入出力項目

| 項目名 | 項目ID | データ型 | 入力/出力 | 必須 | 説明 |
|--------|--------|----------|-----------|------|------|
| カード表示設定 | contentGroupKind.isInFeed | Bool | 入出力 | - | 各カードの表示/非表示 |
| 言語別表示設定 | languageLink.isInFeed | Bool | 入出力 | - | 言語別のカード表示設定 |
| グローバルカード設定 | areGlobalContentGroupKindsInFeed | Bool | 入出力 | - | グローバルカードの表示設定 |
| Exploreタブ設定 | defaultTabType | TabType | 入出力 | - | Exploreタブの有効/無効 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| ナビゲーションタイトル | String | "Explore feed" |
| Customize the Explore feed セクション | Section | フィードカード設定群 |
| Languages セクション | Section | 言語別設定（複数言語時のみ） |
| Explore tab セクション | Section | Exploreタブのオン/オフ |

## イベント仕様

### 1-フィードカードスイッチ切替（単一言語モード）

ユーザーがフィードカードのスイッチを切り替えた際の処理。

1. `settingsTableViewCell(_:didToggleDisclosureSwitch:)`が呼び出される
2. controlTagからWMFContentGroupKindを取得
3. `feedContentController.toggleContentGroup(of:isOn:updateFeed:)`を実行
4. NotificationCenterを通じてフィード更新を通知

### 2-フィードカード詳細画面遷移（複数言語モード）

複数言語設定時にフィードカード行をタップした際の処理。

1. `tableView(_:didSelectRowAt:)`が呼び出される
2. FeedCardSettingsViewControllerを生成
3. `configure(with:dataStore:contentGroupKind:theme:)`で初期化
4. navigationController.pushViewControllerで遷移

### 3-言語別スイッチ切替

言語セクションのスイッチを切り替えた際の処理。

1. `settingsTableViewCell(_:didToggleDisclosureSwitch:)`が呼び出される
2. controlTagから対応するlanguageを特定
3. `feedContentController.toggleContent(forSiteURL:isOn:waitForCallbackFromCoordinator:updateFeed:)`を実行

### 4-Exploreタブ切替

Exploreタブのスイッチを切り替えた際の処理。

1. controlTag=-1を検出
2. sender.isOnに応じてアラートを表示（turnOnExploreAlertController / turnOffExploreAlertController）
3. 確認後、`feedContentController.toggleAllContentGroupKinds(_:updateFeed:)`を実行
4. `UserDefaults.standard.defaultTabType`を.exploreまたは.settingsに更新

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| カード表示切替 | CoreData/UserDefaults | UPDATE | フィード設定を更新 |
| 言語別表示切替 | CoreData | UPDATE | 言語別フィード設定を更新 |
| Exploreタブ切替 | UserDefaults | UPDATE | defaultTabTypeを更新 |

### テーブル別更新項目詳細

#### UserDefaults

| 操作 | 項目（キー名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | defaultTabType | .explore / .settings | Exploreタブの有効/無効 |

#### CoreData (WMFExploreFeedContentController経由)

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| UPDATE | ContentGroup visibility | Bool | カードごとの表示設定 |
| UPDATE | Site preferences | Bool | 言語ごとの設定 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| explore-feed-preferences-customize-explore-feed | ヘッダー | "Customize the Explore feed" | カスタマイズセクション |
| explore-feed-preferences-customize-explore-feed-footer-text | フッター | "Hiding a card type will stop this card type from appearing..." | カスタマイズセクション |
| explore-feed-preferences-languages-footer-text | フッター | "Hiding all Explore feed cards in all of your languages will turn off the Explore tab." | 言語セクション |
| explore-feed-preferences-turn-off-feed-disclosure | フッター | "Turning off the Explore tab will replace the Explore tab with a Settings tab." | メインセクション |
| explore-feed-preferences-turn-on-explore-tab-message | アラート | "This will replace the Settings tab with the Explore tab..." | Exploreオン時 |
| explore-feed-preferences-turn-off-explore-tab-title | アラート | "Turn off the Explore tab?" | Exploreオフ時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| feedContentControllerがnil | assertionFailure発生、処理中断 |
| preferredLanguagesが空 | assertionFailure発生 |
| アラートキャンセル | スイッチを元の状態に戻す |

## 備考

- 本画面はBaseExploreFeedSettingsViewControllerを継承
- 単一言語モードと複数言語モードで表示内容が異なる
- viewWillDisappearでupdateFeedBeforeViewDisappearsフラグを確認し、必要に応じてフィード更新
- showCloseButtonフラグでモーダル表示時の閉じるボタン表示を制御

---

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

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

### 推奨読解順序

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

まず、フィードカードを表現するデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | BaseExploreFeedSettingsViewController.swift | `Wikipedia/Code/BaseExploreFeedSettingsViewController.swift` | ExploreFeedSettingsItemプロトコル（1-32行目） |
| 1-2 | ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | FeedCardクラス（4-155行目） |

**読解のコツ**: FeedCardクラスがWMFContentGroupKindを保持し、各カードの表示設定を管理します。displayTypeによって単一言語/複数言語モードの切り替えが行われます。

#### Step 2: セクション構築を理解する

設定画面のセクション構成を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | feedCards遅延プロパティ（207-230行目） |
| 2-2 | ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | sectionsプロパティ（257-265行目） |

**主要処理フロー**:
1. **207-230行目**: 各フィードカード（News、OnThisDay等）のFeedCardインスタンス生成
2. **222-226行目**: Suggested Editsカードの条件付き追加
3. **240-242行目**: customizationSectionの生成
4. **244-246行目**: mainSection（Exploreタブスイッチ）の生成
5. **248-255行目**: languagesSection（複数言語時のみ）の生成

#### Step 3: スイッチ操作のハンドリングを理解する

ユーザーがスイッチを操作した際の処理フローを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | settingsTableViewCell(_:didToggleDisclosureSwitch:)（320-370行目） |

**主要処理フロー**:
- **327-344行目**: controlTag=-1（Exploreタブスイッチ）の処理、アラート表示
- **345-348行目**: controlTag=-2（グローバルカード）の処理
- **349-361行目**: 単一言語モードでのカード個別切り替え
- **362-368行目**: 複数言語モードでの言語別切り替え

#### Step 4: 詳細画面への遷移を理解する

複数言語モードでのカード詳細画面遷移を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | tableView(_:didSelectRowAt:)（299-314行目） |

**主要処理フロー**:
- **303-305行目**: 単一言語モードでは遷移しない
- **306-308行目**: FeedCard項目かどうかを確認
- **310-312行目**: FeedCardSettingsViewControllerを生成・設定してプッシュ遷移

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

```
ExploreFeedSettingsViewController
    │
    ├─ viewDidLoad()
    │      ├─ displayType判定（単一/複数言語）
    │      └─ BaseExploreFeedSettingsViewController.viewDidLoad()
    │
    ├─ feedCards（遅延プロパティ）
    │      └─ FeedCard生成（contentGroupKindごと）
    │
    ├─ sections（計算プロパティ）
    │      ├─ customizationSection（カード設定）
    │      ├─ languagesSection（言語設定、複数言語時）
    │      └─ mainSection（Exploreタブ設定）
    │
    ├─ settingsTableViewCell(_:didToggleDisclosureSwitch:)
    │      ├─ tag=-1 → Exploreタブ切替アラート
    │      │      ├─ turnOnExploreAlertController
    │      │      └─ turnOffExploreAlertController
    │      ├─ tag=-2 → グローバルカード切替
    │      │      └─ feedContentController.toggleGlobalContentGroupKinds()
    │      ├─ 単一言語モード → カード個別切替
    │      │      └─ feedContentController.toggleContentGroup()
    │      └─ 複数言語モード → 言語別切替
    │             └─ feedContentController.toggleContent(forSiteURL:)
    │
    └─ tableView(_:didSelectRowAt:)（複数言語時）
           └─ FeedCardSettingsViewController → push遷移
```

### データフロー図

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

カードスイッチ操作 ───▶ settingsTableViewCell    ──────▶ WMFExploreFeedContentController
                      (_:didToggleDisclosureSwitch:)           │
                              │                                 ▼
                              ▼                          CoreData更新
                       feedContentController                   │
                       .toggleContentGroup()                   ▼
                                                    NotificationCenter通知
                                                               │
                                                               ▼
                                                    Exploreフィード再構築

Exploreタブ切替 ────▶ アラート表示 ───────────────▶ UserDefaults更新
                          │                         (defaultTabType)
                          ▼                                │
                   ユーザー確認                             ▼
                          │                          タブバー更新
                          ▼
                   toggleAllContentGroupKinds()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ExploreFeedSettingsViewController.swift | `Wikipedia/Code/ExploreFeedSettingsViewController.swift` | ソース | メインのViewController |
| BaseExploreFeedSettingsViewController.swift | `Wikipedia/Code/BaseExploreFeedSettingsViewController.swift` | ソース | 親クラス（フィード設定共通基盤） |
| FeedCardSettingsViewController.swift | `Wikipedia/Code/FeedCardSettingsViewController.swift` | ソース | カード詳細設定画面 |
| WMFExploreFeedContentController.swift | `WMF/Sources/WMF/DataControllers/WMFExploreFeedContentController.swift` | ソース | フィードコンテンツ管理 |
| WMFContentGroupKind.swift | `WMF/Sources/WMF/DataModel/WMFContentGroupKind.swift` | ソース | カード種別定義 |
| SubSettingsViewController.swift | `Wikipedia/Code/SubSettingsViewController.swift` | ソース | 設定画面基底クラス |
