# 画面設計書 5-Article画面

## 概要

本ドキュメントは、Wikipedia iOSアプリのArticle画面（記事閲覧画面）の設計仕様を記載したものである。

### 本画面の処理概要

Article画面は、Wikipedia記事のコンテンツを表示する画面である。WKWebViewを使用して記事のHTML/CSSをレンダリングし、リッチなインタラクションを提供する。

**業務上の目的・背景**：ユーザーがWikipediaの記事を快適に閲覧できるようにする。モバイル最適化されたレイアウト、目次ナビゲーション、テーマ設定、フォントサイズ調整など、読書体験を向上させる機能を提供。記事の保存、共有、編集へのアクセスも可能。

**画面へのアクセス方法**：Explore/Search/Saved/Places画面から記事を選択、リンクタップ、ディープリンク、Spotlight検索結果などから。

**主要な操作・処理内容**：
1. 記事コンテンツの表示（WebView）
2. 記事内リンクのタップによる遷移
3. 目次（Table of Contents）の表示・ナビゲーション
4. 参照（Reference）のポップオーバー表示
5. 画像のタップによるギャラリー表示
6. 記事の保存（ブックマーク）
7. 記事の共有
8. テーマ・フォントサイズの変更
9. 記事内検索（Find in Page）
10. 記事の編集画面への遷移
11. プルトゥリフレッシュによる記事更新

**画面遷移**：
- 遷移元：Explore画面、Search画面、Saved画面、Places画面、Article画面（リンク遷移）
- 遷移先：Article画面（リンク遷移）、ImageGallery画面、TableOfContents画面、Reference画面、EditArticle画面、Share画面

**権限による表示制御**：ログイン状態により編集ボタンの表示、ウォッチリスト機能の利用可否が変化。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | 記事閲覧 | 主機能 | 記事コンテンツの表示、スクロール、リンク遷移 |
| 2 | 目次ナビゲーション | 主機能 | 目次の表示、セクションへのジャンプ |
| 3 | 参照表示 | 主機能 | 参照のポップオーバー表示、バックリンク表示 |
| 4 | 画像ギャラリー | 遷移先機能 | 画像タップでギャラリー画面へ遷移 |
| 5 | テーマ設定 | 補助機能 | ライト/ダーク/セピアテーマの切り替え |
| 6 | フォントサイズ | 補助機能 | 記事のフォントサイズ調整 |
| 13 | オフライン保存 | 補助機能 | 記事の保存・オフライン閲覧 |
| 17 | 記事編集 | 遷移先機能 | 編集画面への遷移 |
| 44 | プロファイル画面 | 遷移先機能 | プロファイルボタンタップでプロファイル画面へ遷移 |
| 61 | タブ一覧 | 遷移先機能 | タブボタンタップでタブ一覧画面へ遷移 |

## 画面種別

詳細（WebView）

## URL/ルーティング

- エントリーポイント：`ArticleCoordinator`経由
- ディープリンク：`wikipedia://article/{title}`
- Storyboard ID：`ArticleViewController`
- Objective-C名：`WMFArticleViewController`

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 説明 |
|--------|----------|----------|------|
| 記事URL | 入力 | URL | articleURL プロパティ |
| 言語コード | 入力 | String | articleLanguageCode プロパティ |
| 記事データ | 出力 | WMFArticle | article プロパティ |
| メディアリスト | 出力 | MediaList | mediaList プロパティ |

## 表示項目

| 項目名 | データソース | 表示条件 | 備考 |
|--------|-------------|----------|------|
| リード画像 | WMFArticle | 画像URL存在時 | leadImageView |
| 記事本文 | Mobile HTML API | 常時 | WKWebView |
| ツールバー | - | 常時 | 下部に配置 |
| 目次パネル | tableOfContentsController | iPad/横向き時インライン | 左サイドパネル |
| リフレッシュコントロール | - | スクロールトップ時 | プルトゥリフレッシュ |

## イベント仕様

### 1-記事読み込み

`viewDidLoad`後、`load()`メソッドで記事の読み込みを開始。`ArticleFetcher`を通じてMobile HTML APIから記事データを取得し、WKWebViewにロード。

**ソースコード参照**: ArticleViewController.swift 行576-590（load関数）

### 2-リンクタップ

WebView内のリンクタップは`ArticleWebMessagingController`経由でJavaScriptブリッジから受信。`handleLink(with:)`メソッドで処理し、記事リンクの場合は`LinkCoordinator`で新しい記事画面へ遷移。

**ソースコード参照**: ArticleViewController.swift 行1133-1168（handleLink関数）

### 3-目次表示

ツールバーの目次ボタンタップで`ArticleTableOfContentsDisplayController`が目次パネルを表示。`tableOfContentsItems`配列でセクション一覧を管理。セクションタップで`scroll(to:animated:)`でスクロール。

**ソースコード参照**: ArticleViewController.swift 行1172-1220（tableOfContentsController関連）

### 4-参照タップ

記事内の脚注リンクタップで`ReferenceViewController`がポップオーバーで表示。参照内容と元記事へのバックリンクを表示。

### 5-画像タップ

リード画像または記事内画像タップで`ImageGalleryViewController`を表示。`mediaList`から画像一覧を取得しギャラリー表示。

**ソースコード参照**: ArticleViewController.swift 行286-288（userDidTapLeadImage）

### 6-保存ボタンタップ

ツールバーの保存ボタンタップで`article.isAnyVariantSaved`を切り替え。保存時はAddArticlesToReadingListViewControllerを表示してリスト選択可能。

### 7-共有ボタンタップ

ツールバーの共有ボタンタップで`shareArticle()`メソッドを実行。UIActivityViewControllerで共有シート表示。

### 8-テーマ変更

ツールバーのテーマボタンタップで`ReadingThemesControlsViewController`を表示。テーマ（ライト/セピア/ダーク/ブラック）とフォントサイズを変更可能。

### 9-プルトゥリフレッシュ

記事を下にスワイプすると`refresh()`メソッドが呼び出され、`performWebViewRefresh()`で記事を再読み込み。

**ソースコード参照**: ArticleViewController.swift 行1061-1067（refresh関数）

### 10-プロファイル/タブボタン

ナビゲーションバーのプロファイル/タブボタンタップで各Coordinatorを起動。

**ソースコード参照**: ArticleViewController.swift 行498-518

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 記事表示 | WMFArticle | UPDATE | 閲覧日時、スクロール位置の更新 |
| 記事保存 | WMFArticle | UPDATE | savedDate の更新 |
| 閲覧履歴 | WMFArticle | UPDATE | viewedDate、wasSignificantlyViewed の更新 |
| ウォッチリスト | - | API | Watchlist APIへのリクエスト |

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

#### WMFArticle

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | viewedDate | 現在時刻 | 閲覧履歴 |
| UPDATE | viewedScrollPosition | スクロールY座標 | 復元用 |
| UPDATE | viewedFragment | 表示中セクションID | 復元用 |
| UPDATE | wasSignificantlyViewed | true | 30秒以上閲覧時 |
| UPDATE | savedDate | 現在時刻/nil | 保存/保存解除 |

## メッセージ仕様

| メッセージID | メッセージ内容 | 表示条件 | 種別 |
|-------------|---------------|----------|------|
| article-load-error | Unable to load article | 記事読み込み失敗時 | エラー |
| article-saved | Article saved | 保存成功時 | 情報 |
| no-internet | No internet connection | ネットワークエラー時 | エラー |

## 例外処理

- **ネットワークエラー**：オフライン保存記事があればキャッシュから表示、なければエラービュー表示
- **記事読み込み失敗**：`handleArticleLoadFailure`でエラー処理、保存記事の場合は空ビュー回避
- **WebViewプロセス終了**：`webViewWebContentProcessDidTerminate`でWebViewを自動リロード

## 備考

- ArticleViewControllerはThemeableViewControllerを継承
- HintPresenting、UIScrollViewDelegate、WMFNavigationBarConfiguringなど複数プロトコルに準拠
- WKWebViewのカスタムスキームハンドラで`app://`スキームを処理
- JavaScriptブリッジ（ArticleWebMessagingController）でWebView↔ネイティブ間通信
- 閲覧時間トラッキング（Year In Review用）
- タブ管理（WMFArticleTabsDataController）との連携

---

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

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

### 推奨読解順序

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

記事データと関連モデルを理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WMFArticle+CoreDataClass.swift | `WMF/Sources/WMF/DataModel/WMFArticle+CoreDataClass.swift` | 記事メタデータ、保存状態、閲覧履歴 |
| 1-2 | MediaList.swift | `Wikipedia/Code/MediaList.swift` | 記事内メディア（画像・動画）リスト |
| 1-3 | TableOfContentsItem.swift | `Wikipedia/Code/TableOfContentsItem.swift` | 目次アイテムモデル |

**読解のコツ**: WMFArticleのviewedScrollPosition, viewedFragmentがスクロール復元に使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ArticleViewController.swift | `Wikipedia/Code/ArticleViewController.swift` | 行180-203 init、行452-458 viewDidLoad |

**主要処理フロー**:
1. **行452 viewDidLoad**: setup() でWebView、ツールバー、通知ハンドラを設定
2. **行460 viewWillAppear**: loadIfNecessary() で記事読み込み開始
3. **行576 load**: setupPageContentServiceJavaScriptInterface() でJSブリッジ設定後、loadPage()

#### Step 3: WebView通信層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ArticleWebMessagingController.swift | `Wikipedia/Code/ArticleWebMessagingController.swift` | JavaScript↔ネイティブ間メッセージング |
| 3-2 | SchemeHandler.swift | `Wikipedia/Code/SchemeHandler.swift` | カスタムURLスキーム処理 |
| 3-3 | ArticleFetcher.swift | `WMF/Sources/WMF/Fetchers/ArticleFetcher.swift` | Mobile HTML API呼び出し |

#### Step 4: UI補助コンポーネント層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ArticleToolbarController.swift | `Wikipedia/Code/ArticleToolbarController.swift` | 下部ツールバー管理 |
| 4-2 | ArticleTableOfContentsDisplayController.swift | `Wikipedia/Code/ArticleTableOfContentsDisplayController.swift` | 目次パネル表示管理 |
| 4-3 | ReadingThemesControlsViewController.swift | `Wikipedia/Code/ReadingThemesControlsViewController.swift` | テーマ設定UI |

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

```
ArticleViewController (1600行+)
    │
    ├─ WKWebView
    │      ├─ SchemeHandler (app:// scheme)
    │      └─ ArticleWebMessagingController (JS bridge)
    │
    ├─ ArticleFetcher
    │      └─ Mobile HTML API
    │
    ├─ ArticleToolbarController
    │      ├─ Save button
    │      ├─ Share button
    │      ├─ TOC button
    │      ├─ Theme button
    │      └─ More menu
    │
    ├─ ArticleTableOfContentsDisplayController
    │      └─ TableOfContentsViewController
    │
    ├─ ReadingThemesControlsViewController
    │      └─ FontSizeSliderViewController
    │
    ├─ ArticleCacheController
    │      └─ Offline caching
    │
    ├─ ProfileCoordinator
    │
    └─ TabsOverviewCoordinator
```

### データフロー図

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

Article URL ───────▶ ArticleFetcher ───▶ Mobile HTML API
                           │
                           ▼
HTML Response ─────▶ SchemeHandler ───▶ WKWebView
                           │
                           ▼
JS Events ─────────▶ ArticleWebMessagingController
                           │
                           ▼
Link Tap ──────────▶ handleLink() ───▶ LinkCoordinator ───▶ New ArticleVC
                           │
                           ▼
User Interaction ──▶ ArticleToolbarController ───▶ Various Actions
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ArticleViewController.swift | `Wikipedia/Code/ArticleViewController.swift` | ソース | メインViewController（1600行+） |
| ArticleViewController+*.swift | `Wikipedia/Code/` | ソース | 拡張ファイル群 |
| ArticleWebMessagingController.swift | `Wikipedia/Code/` | ソース | JSブリッジ |
| ArticleFetcher.swift | `WMF/Sources/WMF/Fetchers/` | ソース | API呼び出し |
| ArticleToolbarController.swift | `Wikipedia/Code/` | ソース | ツールバー管理 |
| ArticleTableOfContentsDisplayController.swift | `Wikipedia/Code/` | ソース | 目次表示管理 |
| SchemeHandler.swift | `Wikipedia/Code/` | ソース | URLスキーム処理 |
| ArticleCacheController.swift | `WMF/Sources/WMF/ArticleCache/` | ソース | オフラインキャッシュ |
| ReadingThemesControlsViewController.swift | `Wikipedia/Code/` | ソース | テーマ設定UI |
| WMFArticle+CoreDataClass.swift | `WMF/Sources/WMF/DataModel/` | ソース | 記事データモデル |
