# 機能設計書 51-ウォッチリスト管理

## 概要

本ドキュメントは、Wikipedia iOSアプリにおけるウォッチリスト管理機能の設計を記述する。この機能は、ユーザーがWikipedia記事をウォッチリストに追加・削除するための機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：ウォッチリスト機能は、Wikipediaのログインユーザーが関心のある記事の変更を追跡するための重要な機能である。編集者や読者が記事の更新状況を把握し、荒らし行為の検知や編集の品質監視を行うために必要不可欠である。モバイルアプリからもこの機能にアクセスできることで、ユーザーはいつでもどこでも記事の監視状態を管理できる。

**機能の利用シーン**：記事を閲覧している際に、その記事の変更を追跡したい場合にウォッチリストに追加する。また、差分比較画面から特定のリビジョンに関連する記事をウォッチすることも可能。不要になった記事はウォッチリストから削除できる。

**主要な処理内容**：
1. 記事のウォッチリスト追加（期限付きまたは永続的）
2. 期限オプションの選択（1週間、1ヶ月、3ヶ月、6ヶ月、1年、永続）
3. ウォッチリストからの記事削除
4. ウォッチ操作成功時のトースト通知表示
5. ログイン状態の確認と未ログイン時のログイン画面への誘導

**関連システム・外部連携**：Wikipedia MediaWiki API（watchlist API）と連携してウォッチ操作を実行する。WMFWatchlistDataControllerを通じてAPIリクエストを送信する。

**権限による制御**：ログインユーザーのみがウォッチリスト機能を使用できる。未ログイン状態でウォッチ操作を行おうとすると、ログイン画面が表示される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | Article画面 | 主画面 | 記事のウォッチリスト追加・削除 |
| 32 | DiffContainer画面 | 参照画面 | 差分比較からのウォッチ操作 |

## 機能種別

API連携 / CRUD操作（ウォッチリストへの追加・削除）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pageTitle | String | Yes | ウォッチ対象の記事タイトル | 空文字列でないこと |
| siteURL | URL | Yes | 対象のWikipediaサイトURL | 有効なURL形式 |
| expiry | WMFWatchlistExpiryType | Yes | ウォッチの有効期限 | 列挙型の有効な値 |
| viewController | UIViewController | Yes | 操作元のビューコントローラ | nil不可 |
| authenticationManager | WMFAuthenticationManager | Yes | 認証マネージャー | nil不可 |
| theme | Theme | Yes | 現在のテーマ | nil不可 |

### 入力データソース

ユーザーのタップ操作（記事画面のウォッチボタン、差分画面のウォッチボタン）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| watchStatus | Bool | ウォッチ状態（true=ウォッチ中） |
| expiryType | WMFWatchlistExpiryType | 設定された有効期限 |
| successMessage | String | 成功時に表示するメッセージ |

### 出力先

トースト通知（WMFAlertManager経由）、デリゲートへのコールバック

## 処理フロー

### 処理シーケンス

```
1. ウォッチボタンタップ
   └─ WatchlistControllerのwatch/unwatchメソッドが呼ばれる
2. 認証状態の確認
   └─ authStateIsPermanentをチェック
3. 未ログインの場合
   └─ ログイン画面を表示し、ログイン後に処理を再開
4. ログイン済みの場合（ウォッチ追加時）
   └─ 期限選択アクションシートを表示
5. 期限選択後
   └─ WMFWatchlistDataControllerのwatch APIを呼び出し
6. API成功時
   └─ デリゲートに通知、成功トースト表示
7. API失敗時
   └─ エラーハンドリング、必要に応じて再ログイン
```

### フローチャート

```mermaid
flowchart TD
    A[ウォッチボタンタップ] --> B{ログイン済み?}
    B -->|No| C[ログイン画面表示]
    C --> D{ログイン成功?}
    D -->|No| E[終了]
    D -->|Yes| A
    B -->|Yes| F{追加 or 削除?}
    F -->|追加| G[期限選択シート表示]
    G --> H[期限選択]
    H --> I[watch API呼び出し]
    F -->|削除| J[unwatch API呼び出し]
    I --> K{API成功?}
    J --> K
    K -->|Yes| L[成功トースト表示]
    K -->|No| M[エラー処理]
    L --> N[デリゲート通知]
    M --> O{再ログイン必要?}
    O -->|Yes| C
    O -->|No| P[エラー表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-51-01 | ログイン必須 | ウォッチリスト操作にはログインが必須 | 全てのウォッチ操作時 |
| BR-51-02 | 期限オプション | ウォッチには期限を設定可能 | ウォッチ追加時 |
| BR-51-03 | アクセシビリティ対応 | VoiceOver使用時はトースト表示時間を延長 | VoiceOver有効時 |

### 計算ロジック

特になし

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

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

ローカルデータベースへの直接操作はなし。サーバー側のウォッチリストのみが更新される。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | ローカルDBへの操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| notloggedin | 認証エラー | セッション切れ | ログイン画面表示 |
| serviceError | サービスエラー | API呼び出し失敗 | エラーアラート表示 |

### リトライ仕様

セッション切れの場合は再ログイン後に自動的に操作を再実行する

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

サーバーサイドAPIへの単一リクエストのため、ローカルトランザクションは不要

## パフォーマンス要件

API呼び出しの完了までローディング状態を維持

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

- 認証トークンはWMFAuthenticationManagerで管理
- HTTPS通信を使用
- 認証状態はauthStateIsPermanentで確認

## 備考

WatchlistControllerは記事画面と差分画面の両方から使用される再利用可能なコントローラである。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WMFWatchlistExpiryType | `WMFData/` | 期限タイプの列挙型を確認 |

**読解のコツ**: WMFWatchlistExpiryTypeは.never, .oneWeek, .oneMonth, .threeMonths, .sixMonths, .oneYearの6種類

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | WatchlistController.swift | `Wikipedia/Code/WatchlistController.swift` | メインのコントローラクラス |

**主要処理フロー**:
1. **42-66行目**: watch()メソッド - ウォッチ追加のエントリーポイント
2. **126-220行目**: presentChooseExpiryActionSheet() - 期限選択シート表示
3. **222-280行目**: unwatch()メソッド - ウォッチ解除処理

#### Step 3: API連携層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | WMFWatchlistDataController | `WMFData/` | API呼び出しを担当 |

**主要処理フロー**:
- **170行目**: dataController.watch() - ウォッチAPIの呼び出し
- **245行目**: dataController.unwatch() - アンウォッチAPIの呼び出し

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

```
ArticleViewController / DiffContainerViewController
    │
    ├─ WatchlistController
    │      ├─ watch(pageTitle:siteURL:expiry:...)
    │      │      ├─ authenticationManager.authStateIsPermanent
    │      │      ├─ presentChooseExpiryActionSheet()
    │      │      └─ WMFWatchlistDataController.watch()
    │      │             └─ displayWatchSuccessMessage()
    │      │
    │      └─ unwatch(pageTitle:siteURL:...)
    │             ├─ authenticationManager.authStateIsPermanent
    │             └─ WMFWatchlistDataController.unwatch()
    │
    └─ WMFAlertManager (トースト表示)
```

### データフロー図

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

ユーザー操作 ───▶ WatchlistController ───▶ WMFWatchlistDataController
(ボタンタップ)      │                          │
                   │                          ▼
                   │                      MediaWiki API
                   │                          │
                   ▼                          ▼
             アクションシート            APIレスポンス
             (期限選択)                      │
                                            ▼
                                      WMFAlertManager
                                      (トースト表示)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WatchlistController.swift | `Wikipedia/Code/` | ソース | ウォッチリスト操作の主要ロジック |
| WMFWatchlistDataController | `WMFData/` | ソース | API通信を担当 |
| WatchlistFunnel.swift | `Wikipedia/Code/` | ソース | アナリティクス記録 |
| WMFAuthenticationManager.swift | `WMF Framework/` | ソース | 認証状態管理 |
| WMFAlertManager | `WMF Framework/` | ソース | トースト表示 |
