# 画面設計書 39-NotificationSettings画面

## 概要

本ドキュメントは、Wikipedia iOSアプリにおけるNotificationSettings画面の設計仕様を定義するものです。

### 本画面の処理概要

NotificationSettings画面は、プッシュ通知の有効化/無効化を管理する設定画面です。ユーザーのログイン状態、システム通知権限の状態、Echo通知サブスクリプションの状態に応じて、適切なUIを表示します。

**業務上の目的・背景**：
ユーザーがWikipediaからのプッシュ通知を受け取るかどうかを制御できるようにすることが目的です。通知権限の状態に応じて、有効化の案内またはシステム設定への誘導を行います。

**画面へのアクセス方法**：
Settings画面から「Push notifications」を選択して遷移します。

**主要な操作・処理内容**：
1. プッシュ通知の有効化/無効化
2. システム設定への誘導（権限拒否時）
3. ログイン促進（未ログイン時）
4. Echo通知へのサブスクリプション管理

**画面遷移**：
- 遷移元：Settings画面
- 遷移先：ログインフロー、システム設定アプリ

**権限による表示制御**：
- 未ログインユーザー：ログインボタンを表示
- システム通知権限未決定：有効化スイッチを表示
- システム通知権限拒否：システム設定へのリンクを表示
- システム通知権限許可：サブスクリプション状態に応じた表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 45 | プッシュ通知設定 | 主機能 | 通知設定を行う |

## 画面種別

設定（テーブルビュー）

## URL/ルーティング

NSUserActivity対応：
- `wmf_notificationSettings()`: 通知設定へのディープリンク

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 説明 |
|--------|----------|---------|------|
| authManager | 入力 | WMFAuthenticationManager | 認証管理 |
| notificationsController | 入力 | WMFNotificationsController | 通知コントローラ |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| tableView | UITableView | 設定一覧 |
| WMFSettingsTableViewCell | UITableViewCell | 設定セル |

## イベント仕様

### 1-プッシュ通知有効化スイッチ

スイッチをONにすると、システム通知権限を要求し、許可された場合はEcho通知にサブスクライブします。

### 2-システム設定への遷移

権限拒否状態で「Turn on Notifications」をタップすると、UIApplication.openSettingsURLStringでシステム設定に遷移します。

### 3-ログインボタン

未ログイン状態で「Log in」をタップすると、ログイン/アカウント作成パネルが表示されます。

### 4-アプリがアクティブになった時

NotificationCenter.didBecomeActiveNotificationを監視し、アプリがアクティブになったらセクションを更新します（システム設定から戻ってきた場合に状態を反映）。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| プッシュ有効化 | UserDefaults | UPDATE | wmf_isSubscribedToEchoNotificationsをtrueに |
| プッシュ無効化 | UserDefaults | UPDATE | wmf_isSubscribedToEchoNotificationsをfalseに |
| サブスクライブ | - | API Call | Echo通知APIにサブスクライブ |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| settings-notifications-push-notifications | セクションタイトル | "Push notifications" | 常時 |
| settings-notifications-system-turn-on | ボタン | "Turn on Notifications" | 権限拒否時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| サブスクリプション失敗 | エラーアラート表示 |
| デバイストークン取得待ち | 待機中メッセージ表示 |
| デバイストークン取得失敗 | 失敗メッセージ表示 |

## 備考

- SubSettingsViewControllerを継承
- WMFNotificationsControllerDeviceTokenDelegateに準拠
- NotificationCenter.didBecomeActiveNotificationを監視
- 状態に応じてセクションを動的に切り替え

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NotificationSettingsItem | `Wikipedia/Code/NotificationSettingsViewController.swift` | 設定項目プロトコル |
| 1-2 | NotificationSettingsSwitchItem | `Wikipedia/Code/NotificationSettingsViewController.swift` | スイッチ項目 |
| 1-3 | NotificationSettingsButtonItem | `Wikipedia/Code/NotificationSettingsViewController.swift` | ボタン項目 |
| 1-4 | NotificationSettingsSection | `Wikipedia/Code/NotificationSettingsViewController.swift` | セクション |

**読解のコツ**: NotificationSettingsItem、NotificationSettingsSwitchItem、NotificationSettingsButtonItem、NotificationSettingsInfoItemの4種類のアイテムタイプがあります。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | NotificationSettingsViewController.swift | `Wikipedia/Code/NotificationSettingsViewController.swift` | init(authManager:notificationsController:)で初期化 |

**主要処理フロー**:
1. **48-53行目**: init時にauthManagerとnotificationsControllerを受け取り
2. **59-66行目**: viewDidLoadでセル登録、didBecomeActive監視
3. **74-77行目**: viewWillAppearでupdateSections()呼び出し

#### Step 3: 状態別セクション生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NotificationSettingsViewController.swift | `Wikipedia/Code/NotificationSettingsViewController.swift` | sectionsFor*メソッド群 |

**主要処理フロー**:
- **79-95行目**: sectionsForPermissionsNotDetermined() - 権限未決定時のセクション
- **134-142行目**: sectionsForNotLoggedIn() - 未ログイン時のセクション
- **144-152行目**: sectionsForPermissionsDenied() - 権限拒否時のセクション
- **155-158行目**: sectionsForSubscriptionFailure() - サブスクリプション失敗時
- **161-164行目**: sectionsForWaitingForDeviceToken() - トークン待ち時
- **167-175行目**: sectionsForPermissionsAllowed() - 権限許可時のセクション

#### Step 4: サブスクリプション処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | NotificationSettingsViewController.swift | `Wikipedia/Code/NotificationSettingsViewController.swift` | requestPermissionsIfNeededAndRegisterDeviceToken |

**主要処理フロー**:
- **97-131行目**: requestPermissionsIfNeededAndRegisterDeviceToken()
- **98-99行目**: notificationsController.requestPermissionsIfNecessary()呼び出し
- **120-128行目**: subscribeToEchoNotifications()でサーバーにサブスクライブ

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

```
NotificationSettingsViewController
    │
    ├─ init(authManager:notificationsController:)
    │
    ├─ viewDidLoad()
    │      └─ NotificationCenter.addObserver(didBecomeActive)
    │
    ├─ viewWillAppear()
    │      └─ updateSections()
    │
    ├─ updateSections()
    │      ├─ Check: authManager.isLoggedIn
    │      │      └─ sectionsForNotLoggedIn()
    │      │
    │      └─ notificationsController.notificationPermissionsStatus()
    │             ├─ .denied → sectionsForPermissionsDenied()
    │             ├─ .notDetermined → sectionsForPermissionsNotDetermined()
    │             └─ .authorized/.provisional/.ephemeral
    │                    ├─ isWaitingOnDeviceToken → sectionsForWaitingForDeviceToken()
    │                    ├─ deviceToken == nil → sectionsForSubscriptionFailure()
    │                    └─ sectionsForPermissionsAllowed()
    │
    └─ handleSwitchValueChange()
           └─ requestPermissionsIfNeededAndRegisterDeviceToken()
                  ├─ notificationsController.requestPermissionsIfNecessary()
                  └─ notificationsController.subscribeToEchoNotifications()
```

### データフロー図

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

viewWillAppear()       ──────▶ updateSections()           ──────▶ tableView.reloadData()
                               │
                               ├─ authManager.isLoggedIn
                               ├─ notificationPermissionsStatus
                               └─ remoteRegistrationDeviceToken
                               │
                               ▼
Switch ON              ──────▶ requestPermissionsIfNeededAndRegisterDeviceToken()
                               │
                               ├─ requestPermissionsIfNecessary() → システム許可ダイアログ
                               │
                               └─ subscribeToEchoNotifications() → API呼び出し
                               │
                               ▼
                               updateSections() → UI更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NotificationSettingsViewController.swift | `Wikipedia/Code/NotificationSettingsViewController.swift` | ソース | ViewController |
| SubSettingsViewController.swift | `Wikipedia/Code/SubSettingsViewController.swift` | ソース | 親クラス |
| WMFSettingsTableViewCell.swift | `Wikipedia/Code/WMFSettingsTableViewCell.swift` | ソース | 設定セル |
| WMFNotificationsController.swift | `WMF/Sources/` | ソース | 通知コントローラ |
| WMFAuthenticationManager.swift | `WMF/Sources/` | ソース | 認証管理 |
