# 画面設計書 70-SinglePageWebView画面

## 概要

本ドキュメントは、Wikipedia iOSアプリのSinglePageWebView画面の設計を記載したものです。この画面はWKWebViewを使用して単一のWebページを表示する汎用的なViewControllerであり、ヘルプページ、プライバシーポリシー、寄付ページなど様々な用途で使用されます。

### 本画面の処理概要

SinglePageWebView画面は、指定されたURLのWebページをWKWebViewで表示する汎用的な画面です。複数のコンフィグレーションタイプ（標準、寄付、Year In Review Learn More）をサポートし、それぞれ異なるナビゲーションバー設定やオーバーレイボタンを提供します。

**業務上の目的・背景**：アプリ内で外部または内部のWebコンテンツを表示する必要がある場面は多く、ヘルプページ、プライバシーポリシー、利用規約、寄付ページなどがあります。これらを統一的なUIで表示することで、ユーザー体験の一貫性を保ちつつ、各用途に応じたカスタマイズも可能にしています。

**画面へのアクセス方法**：Help画面、設定画面、寄付フローなど様々な画面からコンフィグレーションタイプを指定してインスタンス化されます。

**主要な操作・処理内容**：
1. 指定されたURLをWKWebViewで読み込み・表示
2. ナビゲーションバーの表示（シンプル/フル）
3. 検索機能への遷移（フルナビゲーションバー時）
4. Safari共有機能
5. 寄付完了時のThank Youページ検出と処理
6. Year In Review Learn More時の寄付ボタンオーバーレイ
7. リンクタップ時の遷移処理（LinkCoordinator使用）

**画面遷移**：
- 遷移元：Help画面、設定画面、Year In Review画面など
- 遷移先：Search画面、Safari、寄付完了画面、各種リンク先

**権限による表示制御**：特になし。コンテンツはWebページの内容に依存します。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 59 | ヘルプ表示 | 補助機能 | ヘルプやプライバシーポリシー表示 |

## 画面種別

WebView / 汎用ページ表示

## URL/ルーティング

コンフィグレーションによって異なるURLを表示します。

## 入出力項目

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| configType | ConfigType | 入力 | 必須 | 表示設定（standard/donate/yirLearnMore） |
| theme | Theme | 入力 | 必須 | 適用するテーマ |

### ConfigType詳細

#### StandardConfig
| 項目名 | 型 | 説明 |
|--------|-----|------|
| url | URL | 表示するURL |
| useSimpleNavigationBar | Bool | シンプルナビゲーションバーを使用するか |

#### DonateConfig
| 項目名 | 型 | 説明 |
|--------|-----|------|
| url | URL | 寄付ページのURL |
| dataController | WMFDonateDataController | 寄付データコントローラー |
| coordinatorDelegate | DonateCoordinatorDelegate? | 寄付コーディネータデリゲート |
| loggingDelegate | WMFDonateLoggingDelegate? | ロギングデリゲート |
| completeButtonTitle | String | 完了ボタンのタイトル |

#### YiRLearnMoreConfig
| 項目名 | 型 | 説明 |
|--------|-----|------|
| url | URL | Learn MoreページのURL |
| slideLoggingID | String | スライドのロギングID |
| donateButtonTitle | String | 寄付ボタンのタイトル |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| webView | 全体 | WKWebViewによるWebコンテンツ表示 |
| overlayButtonContainer | 下部（条件付き） | オーバーレイボタンのコンテナ |
| overlayButton | オーバーレイ内 | 寄付/完了ボタン |
| overlayButtonSpinner | ボタン内 | ローディングスピナー |
| searchBarButtonItem | ナビゲーション右 | 検索ボタン（フルナビ時） |

## イベント仕様

### 1-init

初期化処理。

- configType, themeを受け取り
- hidesBottomBarWhenPushedをtrueに設定

### 2-viewDidLoad

画面がロードされた際の初期化処理。

- webViewをビューに追加（制約をエッジに設定）
- useSimpleNavigationBarに応じてナビゲーションアイテムを設定
- copyCookiesFromSession()でセッションCookieをWebViewに引き渡し

### 3-viewWillAppear

画面表示前の処理。

- loadedフラグでロード済みかチェック
- load()でURLを読み込み
- configureNavigationBar()でナビゲーションバーを設定

### 4-viewDidAppear

画面表示後の処理。

- configTypeに応じた処理
  - donate: webViewFormDidAppearロギング
  - yirLearnMore: setupButtonOverlay()でボタンオーバーレイ設定

### 5-viewDidDisappear

画面非表示時の処理。

- donate configでThank Youページ到達時、ロギングとコーディネータ通知

### 6-handleNavigation(with:)

WKNavigationDelegateによるナビゲーション処理。

- 初回ナビゲーションは許可
- リンクタップ時はLinkCoordinatorで遷移処理
- Thank YouページのURLを検出して寄付完了処理
- 開発者設定で寄付バイパスオプションをサポート

### 7-didTapOverlayButton

オーバーレイボタン押下時の処理。

- donate: webViewFormThankYouDidTapReturnをログ/通知
- yirLearnMore: DonateCoordinatorを起動して寄付フローへ

### 8-userDidTapSearchButton

検索ボタン押下時の処理。

- SearchViewControllerをプッシュ遷移で表示

### 9-tappedAction

共有ボタン押下時の処理。

- UIActivityViewControllerでURL共有（TUSafariActivity含む）

### 10-closeButtonTapped

閉じるボタン押下時の処理。

- navigationController?.dismiss()で画面を閉じる

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

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

| 操作（イベント） | 対象 | 操作種別 | 概要 |
|----------------|-----|---------|------|
| Thank You到達 | LocalDonationHistory | INSERT | 寄付履歴の保存 |

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

#### LocalDonationHistory（寄付完了時）

| 操作 | 項目 | 更新値 | 備考 |
|-----|-----|------|------|
| INSERT | type | oneTime/recurring | 寄付タイプ |
| INSERT | amount | Decimal | 寄付額 |
| INSERT | currencyCode | String | 通貨コード |
| INSERT | isNative | false | Webフォーム経由 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| - | - | - | メッセージはWebコンテンツに依存 |

## 例外処理

| 例外条件 | 対処 |
|----------|------|
| WebView読み込み失敗（provisional） | DDLogWarn、WMFAlertManagerでエラー表示 |
| WebView読み込み失敗 | DDLogWarn、エラー表示（プラグインエラーは除外） |
| プラグインハンドルロードエラー (code 204) | エラー表示をスキップ |

## 備考

- WKWebViewConfiguration.applicationNameForUserAgentを"WikipediaApp"に設定
- WKWebsiteDataStore.nonPersistent()を使用（プライバシー保護）
- モバイルフロントエンドのヘッダークロームを非表示にするJavaScript注入
- WMF_STAGING/WMF_EXPERIMENTALビルドではWebView inspectable
- DonationInfo構造体でThank You URLから寄付情報をパース
- LinkCoordinatorでアプリ内遷移を優先、失敗時は従来の遷移処理
- preferredContentSizeは1400x1400（ポップオーバー用）

---

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

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

### 推奨読解順序

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

ConfigTypeと各Configクラスの構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SinglePageWebViewController.swift | `Wikipedia/Code/SinglePageWebViewController.swift` | DonateConfig, YiRLearnMoreConfig, StandardConfig, ConfigType |

**読解のコツ**: ConfigTypeはenumで3種類の設定を管理しています。各Configは初期化時に必要なパラメータを保持するfinal classです。

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

ViewControllerの初期化とライフサイクルを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SinglePageWebViewController.swift | `Wikipedia/Code/SinglePageWebViewController.swift` | init, viewDidLoad, viewWillAppear |

**主要処理フロー**:
1. **165-171行目**: init - configType設定、hidesBottomBarWhenPushed
2. **177-191行目**: viewDidLoad - WebView追加、Cookie設定
3. **241-251行目**: viewWillAppear - load(), configureNavigationBar()
4. **253-266行目**: viewDidAppear - configType別の処理

#### Step 3: ナビゲーション処理を理解する

WebView内のリンクタップとページ遷移の処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SinglePageWebViewController.swift | `Wikipedia/Code/SinglePageWebViewController.swift` | handleNavigation(with:), WKNavigationDelegate |

**主要処理フロー**:
- **396-462行目**: handleNavigation(with:) - ナビゲーション判定、リンク処理
- **538-553行目**: WKNavigationDelegate - decidePolicyFor
- **555-569行目**: webView(_:didFail:) - エラーハンドリング

#### Step 4: 寄付フロー処理を理解する

寄付ページ特有の処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SinglePageWebViewController.swift | `Wikipedia/Code/SinglePageWebViewController.swift` | parseThankYouURL, saveDonationToLocalHistory |

**主要処理フロー**:
- **466-487行目**: parseThankYouURL - Thank You URLから寄付情報をパース
- **489-499行目**: saveDonationToLocalHistory - 寄付履歴の保存

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

```
呼び出し元（Help, 設定, YiRなど）
    |
    +-- SinglePageWebViewController.init(configType:theme:)
           |
           +-- viewDidLoad()
           |      +-- wmf_addSubviewWithConstraintsToEdges(webView)
           |      +-- copyCookiesFromSession()
           |
           +-- viewWillAppear()
           |      +-- load() --> webView.load(URLRequest)
           |      +-- configureNavigationBar()
           |
           +-- viewDidAppear()
           |      +-- [donate] loggingDelegate.webViewFormDidAppear
           |      +-- [yirLearnMore] setupButtonOverlay()
           |
           +-- WKNavigationDelegate
           |      +-- handleNavigation(with:)
           |             +-- [linkActivated] LinkCoordinator.start()
           |             +-- [thank you] parseThankYouURL()
           |                           +-- saveDonationToLocalHistory()
           |                           +-- setupButtonOverlay()
           |
           +-- didTapOverlayButton()
           |      +-- [donate] coordinatorDelegate.webViewFormThankYouDidTapReturn
           |      +-- [yirLearnMore] DonateCoordinator.start()
           |
           +-- closeButtonTapped()
                  +-- dismiss()
```

### データフロー図

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

configType             --> SinglePageWebViewController      --> WebView表示
theme                       |
                            +-- viewDidLoad()
                            |      +-- copyCookiesFromSession()
                            |
                            +-- load()
                            |      |
                            |      v
                            |   WKWebView.load(URLRequest)
                            |
                            +-- handleNavigation()
                            |      |
                            |      +-- [link] LinkCoordinator
                            |      |           |
                            |      |           v
                            |      |        画面遷移
                            |      |
                            |      +-- [thankYou] parseThankYouURL()
                            |                     |
                            |                     v
                            |              saveDonationToLocalHistory()
                            |                     |
                            |                     v
                            |              WMFDonateDataController
                            |
                            +-- didTapOverlayButton()
                            |      |
                            |      +-- [yirLearnMore] DonateCoordinator
                            |
                            v
                       dismiss --> 元画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SinglePageWebViewController.swift | `Wikipedia/Code/SinglePageWebViewController.swift` | ソース | メインViewController |
| ThemeableViewController.swift | `Wikipedia/Code/ThemeableViewController.swift` | ソース | テーマ対応の基底ViewController |
| WMFNavigationBarConfiguring.swift | `WMFComponents/Sources/WMFComponents/` | ソース | ナビゲーションバー設定プロトコル |
| LinkCoordinator.swift | `Wikipedia/Code/LinkCoordinator.swift` | ソース | リンク遷移コーディネータ |
| DonateCoordinator.swift | `Wikipedia/Code/DonateCoordinator.swift` | ソース | 寄付フローコーディネータ |
| WMFDonateDataController.swift | `WMFData/Sources/WMFData/` | ソース | 寄付データコントローラー |
| SearchViewController.swift | `Wikipedia/Code/SearchViewController.swift` | ソース | 検索画面 |
| TUSafariActivity.swift | `Wikipedia/Code/TUSafariActivity.swift` | ソース | Safari共有アクティビティ |
