# 画面設計書 18-InsertLink画面

## 概要

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

### 本画面の処理概要

リンク挿入画面は、記事編集時に新しい内部リンクを挿入するための画面です。ユーザーは検索機能を使用してリンク先の記事を見つけ、選択することでリンクを挿入できます。

**業務上の目的・背景**：Wikipedia記事を編集する際、関連する他の記事へのリンクを挿入することは、百科事典としての価値を高める重要な作業です。本画面は、検索バーを使用して記事を素早く見つけ、ワンタップでリンクを挿入できるインターフェースを提供します。

**画面へのアクセス方法**：記事編集画面（EditorViewController）のリンク挿入ツールバーボタンをタップすることでアクセスします。テキストを選択している場合は、そのテキストが初期検索語として設定されます。

**主要な操作・処理内容**：
1. 検索バーでリンク先記事を検索
2. 検索結果から記事を選択
3. 選択した記事へのリンクを挿入

**画面遷移**：
- 遷移元: EditorViewController（記事編集画面）
- 遷移先: なし（記事選択後に閉じて呼び出し元に戻る）

**権限による表示制御**：特になし。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | リンク挿入/編集 | 主機能 | 新規リンクの挿入 |

## 画面種別

検索 / 選択

## URL/ルーティング

iOSネイティブアプリのため、URLルーティングは適用されません。モーダル表示されます。

## 入出力項目

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|---------|------|------|
| link | Link | 入力 | 必須 | 挿入するリンクの初期情報（選択テキスト） |
| siteURL | URL | 入力 | 任意 | サイトURL |
| dataStore | MWKDataStore | 入力 | 必須 | データストア |
| theme | Theme | 入力 | 必須 | 表示テーマ |
| delegate | InsertLinkViewControllerDelegate | 入力 | 必須 | デリゲート |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|---------|------|
| 検索バー | UISearchBar | ナビゲーションバーに統合されたSearchController |
| 検索結果 | テーブルビュー | SearchViewControllerを埋め込み |
| キャンセルボタン | ボタン | ナビゲーションバー左 |

## イベント仕様

### 1-検索バー入力

検索文字列が変更された際の処理。

- UISearchResultsUpdatingのupdateSearchResults(for:)で処理
- SearchViewControllerのsearchTermを更新
- 空文字の場合はsearchTermをnil、そうでない場合はsearch()を実行
- updateRecentlySearchedVisibility()で最近の検索表示を更新

### 2-検索結果選択

検索結果から記事を選択した際の処理。

- navigateToSearchResultActionクロージャで処理
- articleURLからtitleを抽出
- delegate.insertLinkViewController(_:didInsertLinkFor:withLabel:)を呼び出し
- searchController.isActive = falseで検索を終了

### 3-キャンセルボタンタップ

リンク挿入をキャンセルする処理。

- delegate.insertLinkViewController(_:didTapCloseButton:)を呼び出し
- searchController.isActive = falseで検索を終了

### 4-検索バーキャンセル

検索バーのキャンセルボタンをタップした際の処理。

- UISearchBarDelegateのsearchBarCancelButtonClicked()で処理
- dismiss(animated:)でモーダルを閉じる

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

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

ローカルデータベースへの直接的な更新はありません。選択結果はdelegateを通じてエディターに返されます。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| CommonStrings.insertLinkTitle | タイトル | "Insert Link" | ナビゲーションバー |
| CommonStrings.searchBarPlaceholder | プレースホルダー | "Search Wikipedia" | 検索バー |
| CommonStrings.cancelActionTitle | ボタン | "Cancel" | ナビゲーションバー左 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| タイトル抽出失敗 | 検索結果選択時に処理をスキップ（guardでreturn） |
| 検索失敗 | SearchViewController内でエラー表示 |

## 備考

- WMFNavigationBarConfiguringプロトコルに準拠
- UISearchResultsUpdatingプロトコルを実装
- UISearchBarDelegateプロトコルを実装
- EditingFlowViewControllerプロトコルに準拠
- SearchViewControllerをsearchResultsControllerとして使用
- link.pageが初期検索語として設定される（存在する場合）
- アクセシビリティ対応: accessibilityPerformEscape()でVoiceOverエスケープジェスチャーをサポート

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | InsertLinkViewController.swift | `Wikipedia/Code/InsertLinkViewController.swift` | init()（16-22行目）、viewDidLoad()（28-32行目） |

**主要処理フロー**:
1. **16-22行目**: init - link、siteURL、dataStore、themeの初期化
2. **28-32行目**: viewDidLoad - テーマ適用
3. **34-79行目**: configureNavigationBar - SearchController設定

#### Step 2: 検索機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | InsertLinkViewController.swift | `Wikipedia/Code/InsertLinkViewController.swift` | configureNavigationBar()（40-79行目） |

**主要処理フロー**:
- **46-67行目**: SearchViewController生成、populateSearchBarWithTextAction、navigateToSearchResultAction設定
- **69-78行目**: WMFNavigationBarSearchConfig設定

#### Step 3: 検索結果更新を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | InsertLinkViewController.swift | `Wikipedia/Code/InsertLinkViewController.swift` | UISearchResultsUpdating拡張（131-150行目） |

**主要処理フロー**:
- **132-149行目**: updateSearchResults - 検索文字列に応じてSearchViewControllerを更新

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

```
InsertLinkViewController
    │
    ├─ init(link:siteURL:dataStore:theme:)
    │
    ├─ viewDidLoad()
    │      └─ apply(theme:)
    │
    ├─ viewWillAppear()
    │      └─ configureNavigationBar()
    │             ├─ SearchViewController生成
    │             ├─ populateSearchBarWithTextAction設定
    │             ├─ navigateToSearchResultAction設定
    │             │      └─ delegate?.insertLinkViewController(_:didInsertLinkFor:withLabel:)
    │             └─ WMFNavigationBarSearchConfig設定
    │
    ├─ viewDidAppear()
    │      └─ searchBar.text = link.page
    │         searchBar.becomeFirstResponder()
    │
    ├─ delegateCloseButtonTap() [Cancel button]
    │      └─ delegate?.insertLinkViewController(_:didTapCloseButton:)
    │
    └─ UISearchResultsUpdating
           └─ updateSearchResults(for:)
                  ├─ [empty] searchViewController.searchTerm = nil
                  └─ [text] searchViewController.searchTerm = text
                            searchViewController.search()
```

### データフロー図

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

link.page             UISearchController                 delegate
(初期検索語)      ───▶ SearchViewController           ───▶ didInsertLinkFor
                      ├─ search()                         (page, label)
                      └─ 検索結果表示

ユーザー入力           updateSearchResults()             SearchViewController
(検索文字列)      ───▶ searchTerm更新                ───▶ 検索結果更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| InsertLinkViewController.swift | `Wikipedia/Code/InsertLinkViewController.swift` | ソース | メインViewController |
| SearchViewController.swift | `Wikipedia/Code/SearchViewController.swift` | ソース | 検索結果表示 |
| Link.swift | （参照のみ） | ソース | リンクデータ構造 |
| WMFNavigationBarConfiguring.swift | （参照のみ） | ソース | ナビゲーションバー設定プロトコル |
