# 機能設計書 36-プッシュ通知

## 概要

本ドキュメントは、Wikipedia iOSアプリにおけるプッシュ通知機能について、その設計仕様を詳細に記載したものである。

### 本機能の処理概要

プッシュ通知機能は、WikipediaのEcho通知システムと連携し、ユーザーに関連するアクティビティをリアルタイムでプッシュ通知として配信する機能である。

**業務上の目的・背景**：Wikipediaでは、ユーザーの投稿への反応やトークページでの議論など、重要なアクティビティがリアルタイムで発生する。プッシュ通知により、ユーザーはアプリを開いていなくてもこれらの通知を受け取ることができ、コミュニティへの迅速な応答が可能になる。

**機能の利用シーン**：
- トークページで返信があった際に通知を受け取りたい場合
- 自分の編集が取り消された際に通知を受け取りたい場合
- 他のユーザーから感謝を受けた際に通知を受け取りたい場合

**主要な処理内容**：
1. プッシュ通知の許可リクエスト
2. デバイストークンの取得とサーバー登録
3. Echo通知サービスへの購読
4. プッシュ通知の受信と処理
5. フォアグラウンドでのバナー表示

**関連システム・外部連携**：
- APNs（Apple Push Notification service）
- WikipediaのEcho通知システム
- WMFNotificationsController

**権限による制御**：ログイン済みユーザーのみ利用可能。iOSの通知許可が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | PushNotificationsSettingsViewController | 設定画面 | プッシュ通知の有効化/無効化 |
| - | NotificationsCenterViewController | 連携画面 | プッシュ通知からの遷移先 |

## 機能種別

システム連携 / データ連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| deviceToken | Data | Yes | APNsから取得したデバイストークン | 有効なトークン形式 |

### 入力データソース

- システム入力：APNsからのデバイストークン
- システム入力：APNsからのプッシュ通知ペイロード

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 通知表示 | UNNotificationContent | プッシュ通知のコンテンツ |
| 購読状態 | Bool | Echo通知サービスへの購読状態 |

### 出力先

- iOSシステム（通知センター、バナー）
- 画面表示（フォアグラウンド時のカスタムバナー）

## 処理フロー

### 処理シーケンス

```
1. ユーザーがプッシュ通知を有効化
   └─ 設定画面またはオンボーディングで有効化
2. 通知許可をリクエスト
   └─ notificationsController.requestPermissionsIfNecessary()
3. デバイストークンを取得
   └─ UIApplication.registerForRemoteNotifications()
4. Echo通知サービスに購読
   └─ notificationsController.subscribeToEchoNotifications()
5. プッシュ通知を受信
   └─ AppDelegate.didReceiveRemoteNotification()
6. 通知を処理して表示
   └─ フォアグラウンド時はカスタムバナー表示
7. 通知タップで通知センターへ遷移
   └─ 通知センター画面を表示
```

### フローチャート

```mermaid
flowchart TD
    A[プッシュ通知有効化] --> B{通知許可?}
    B -->|許可| C[デバイストークン取得]
    B -->|拒否| D[設定画面へ誘導]
    C --> E{トークン取得成功?}
    E -->|Yes| F[Echo購読]
    E -->|No| G[リトライ]
    F --> H{購読成功?}
    H -->|Yes| I[プッシュ通知受信待機]
    H -->|No| J[エラー表示]
    I --> K[通知受信]
    K --> L{アプリ状態}
    L -->|フォアグラウンド| M[カスタムバナー表示]
    L -->|バックグラウンド| N[システム通知表示]
    M --> O[通知センター更新]
    N --> P[通知タップ]
    P --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-36-01 | ログイン必須 | プッシュ通知はログイン済みユーザーのみ | 常時 |
| BR-36-02 | 許可必須 | iOS通知許可が必要 | 常時 |
| BR-36-03 | トークンリトライ | デバイストークン取得失敗時はリトライ | トークン取得失敗時 |
| BR-36-04 | フォアグラウンドバナー | アプリがフォアグラウンド時はカスタムバナーで表示 | フォアグラウンド時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 購読状態保存 | UserDefaults | UPDATE | wmf_isSubscribedToEchoNotifications |

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

プッシュ通知の購読状態はUserDefaultsに保存される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 許可拒否 | ユーザーが通知許可を拒否 | 設定画面への誘導 |
| - | トークン取得失敗 | デバイストークン取得失敗 | リトライ処理 |
| - | 購読失敗 | Echo購読API失敗 | エラー表示（オンボーディング時は無視） |

### リトライ仕様

RetryBlockTaskを使用してデバイストークン取得をリトライ。

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

該当なし

## パフォーマンス要件

プッシュ通知の受信処理は即座に完了する必要がある。

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

- デバイストークンは安全に送信
- 認証済みユーザーのみ購読可能

## 備考

- オンボーディング時にプッシュ通知の許可を促すパネルを表示
- 通知センター表示時に自動的にオンボーディングを表示

---

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

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

### 推奨読解順序

#### Step 1: 通知コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WMFNotificationsController | `WMF Framework/Notifications/WMFNotificationsController.swift` | 通知許可とデバイストークン管理 |

**読解のコツ**: `remoteRegistrationDeviceToken`プロパティでデバイストークンを管理し、`subscribeToEchoNotifications()`でサーバーに購読登録する。

#### Step 2: オンボーディングフローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | NotificationsCenterViewController.swift | `Wikipedia/Code/NotificationsCenterViewController.swift` | オンボーディングとプッシュ許可 |

**主要処理フロー**:
- **556-622行目**: オンボーディングモーダルとプッシュオプトイン
- **996-1017行目**: requestPushPermissionsAndSilentlySubscribeToEchoNotifications()

#### Step 3: 設定画面を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PushNotificationsSettingsViewController.swift | `Wikipedia/Code/PushNotificationsSettingsViewController.swift` | プッシュ通知設定UI |

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

```
AppDelegate
    │
    ├─ application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
    │      └─ WMFNotificationsController.remoteRegistrationDeviceToken = token
    │
    └─ application(_:didReceiveRemoteNotification:)
           └─ 通知処理

NotificationsCenterViewController
    │
    ├─ presentOnboardingPushOptInIfNecessary()
    │      └─ NotificationsCenterOnboardingPushPanelViewController
    │
    └─ requestPushPermissionsAndSilentlySubscribeToEchoNotifications()
           ├─ notificationsController.requestPermissionsIfNecessary()
           ├─ UIApplication.registerForRemoteNotifications()
           └─ notificationsController.subscribeToEchoNotifications()
```

### データフロー図

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

ユーザー許可 ────────────────▶ WMFNotificationsController        ▶ 許可状態
                             ┌─────────────────────────────┐
APNsトークン ────────────────▶│  デバイストークン管理          │  ▶ Echo購読
                             │  ・許可リクエスト              │
                             │  ・トークン保存                │  ▶ UserDefaults
                             │  ・Echo購読                    │
APNs通知 ───────────────────▶│  通知受信処理                  │  ▶ 通知表示
                             └─────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WMFNotificationsController.swift | `WMF Framework/Notifications/WMFNotificationsController.swift` | ソース | 通知許可とデバイストークン管理 |
| NotificationsCenterViewController.swift | `Wikipedia/Code/NotificationsCenterViewController.swift` | ソース | オンボーディングとプッシュ許可 |
| PushNotificationsSettingsViewController.swift | `Wikipedia/Code/PushNotificationsSettingsViewController.swift` | ソース | プッシュ通知設定UI |
| NotificationsCenterOnboardingPushPanelViewController.swift | `Wikipedia/Code/NotificationsCenterOnboardingPushPanelViewController.swift` | ソース | プッシュ許可促進パネル |
| AppDelegate.swift | `Wikipedia/Code/AppDelegate.swift` | ソース | プッシュ通知受信処理 |
