# 機能設計書 33-ページ内検索

## 概要

本ドキュメントは、Wikipedia iOSアプリにおけるトークページ内のテキスト検索機能（Find in Page）について、その設計仕様を詳細に記載したものである。

### 本機能の処理概要

トークページ内検索機能は、ユーザーがトークページ上のトピックや返信コメント内から特定のテキストを検索し、ハイライト表示・ナビゲーションする機能である。

**業務上の目的・背景**：トークページは多くのトピックと返信で構成され、特に活発な議論ページでは情報量が膨大になる。ページ内検索機能により、ユーザーは特定のキーワードや発言者名を素早く見つけることができ、議論の追跡や過去の発言の参照が効率化される。

**機能の利用シーン**：
- 特定のトピックやキーワードを含む議論を探したい場合
- 過去の発言や合意事項を確認したい場合
- 長いトークページで特定の内容に素早くジャンプしたい場合

**主要な処理内容**：
1. 検索バー（キーボードバー）の表示
2. 検索テキストの入力とリアルタイム検索
3. トピックタイトル、リードコメント、返信コメント内のテキスト検索
4. 検索結果のハイライト表示
5. 前後の検索結果へのナビゲーション
6. アクティブな検索結果へのスクロール

**関連システム・外部連携**：外部システムとの連携なし。ローカルでの検索処理。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | TalkPageViewController | 主画面 | 検索機能の起動、結果のスクロール表示 |
| - | FindAndReplaceKeyboardBar | 入力UI | 検索テキスト入力、前後ナビゲーション |

## 機能種別

検索処理 / UIインタラクション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| searchTerm | String | Yes | 検索するテキスト | 任意の文字列 |

### 入力データソース

- 画面入力：ユーザーがキーボードバーに入力した検索テキスト
- システム内部：トークページのトピックとコメントのビューモデル配列

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| matches | [SearchResult] | 検索結果の配列 |
| selectedIndex | Int | 現在選択中の検索結果インデックス |
| highlightText | String? | ハイライト表示用のテキスト |

### 出力先

- 画面表示（検索結果のハイライト、マッチ件数表示）

## 処理フロー

### 処理シーケンス

```
1. ユーザーがFind in Pageを起動
   └─ TalkPageViewController.showFindInPage()
2. キーボードバーを表示
   └─ FindAndReplaceKeyboardBar
3. ユーザーが検索テキストを入力
   └─ keyboardBar(_:didChangeSearchTerm:)
4. 検索処理を実行
   └─ TalkPageFindInPageState.search()
   └─ TalkPageFindInPageSearchController.search()
5. 検索結果をビューモデルに反映
   └─ highlightText, activeHighlightResultの設定
6. セルを再描画してハイライト表示
   └─ rethemeVisibleCells()
7. 前後ナビゲーション
   └─ keyboardBarDidTapPrevious/keyboardBarDidTapNext
8. 検索結果へスクロール
   └─ scrollToFindInPageResult()
```

### フローチャート

```mermaid
flowchart TD
    A[Find in Page起動] --> B[キーボードバー表示]
    B --> C[検索テキスト入力]
    C --> D[検索実行]
    D --> E{結果あり?}
    E -->|Yes| F[ハイライト表示]
    F --> G[マッチ件数更新]
    G --> H{ナビゲーション操作}
    H -->|次へ| I[次の結果を選択]
    H -->|前へ| J[前の結果を選択]
    I --> K[該当位置へスクロール]
    J --> K
    H -->|閉じる| L[検索状態リセット]
    E -->|No| M[0件表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | 大文字小文字無視 | 検索は大文字小文字を区別しない | 常時 |
| BR-33-02 | ループナビゲーション | 最後の結果から「次へ」で最初に戻る | 結果が存在する場合 |
| BR-33-03 | 逆ループナビゲーション | 最初の結果から「前へ」で最後に移動 | 結果が存在する場合 |
| BR-33-04 | 検索対象範囲 | トピックタイトル、リードコメント、その他コンテンツ、返信すべてが対象 | 常時 |

### 計算ロジック

該当なし

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

ローカル検索のため、データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 結果なし | 検索結果が0件の場合 | 0件表示、ナビゲーションボタン無効化 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- リアルタイム検索のため、入力ごとに即座に検索を実行
- 大量のトピック・コメントがある場合でもUIがブロックされないこと

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

特になし（ローカル処理のみ）

## 備考

- 検索結果は複数のカテゴリに分類される：トピックタイトル、リードコメント、その他コンテンツ、返信
- 各検索結果にはNSRangeで位置情報が保持される

---

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

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

### 推奨読解順序

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

まず、検索結果を表すデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TalkPageFindInPageSearchController.swift | `Wikipedia/Code/TalkPageFindInPageSearchController.swift` | SearchResult構造体（8-34行目） |

**読解のコツ**: SearchResult.Locationはenum型で、`topicTitle`、`topicLeadComment`、`topicOtherContent`、`reply`の4種類がある。それぞれにインデックスと識別子が関連付けられている。

#### Step 2: 状態管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TalkPageFindInPageState.swift | `Wikipedia/Code/TalkPageFindInPageState.swift` | 検索状態の管理クラス |

**主要処理フロー**:
1. **7-8行目**: searchControllerとkeyboardBarの保持
2. **10-28行目**: selectedIndexとmatchesの管理
3. **33-58行目**: next()とprevious()によるナビゲーション
4. **60-78行目**: reset()とsearch()による状態制御

#### Step 3: 検索ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TalkPageFindInPageSearchController.swift | `Wikipedia/Code/TalkPageFindInPageSearchController.swift` | 検索アルゴリズムの実装 |

**主要処理フロー**:
- **43-102行目**: search()メソッドでトピック階層を走査
- 各トピックのタイトル、リードコメント、その他コンテンツ、返信を順次検索
- `localizedCaseInsensitiveContains`で大文字小文字を無視して検索

#### Step 4: UIとの連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TalkPageViewController+FindInPage.swift | `Wikipedia/Code/TalkPageViewController+FindInPage.swift` | UIコントローラーとの連携 |

**主要処理フロー**:
- **25-40行目**: showFindInPage()とhideFindInPage()
- **74-120行目**: scrollToFindInPageResult()での結果位置へのスクロール
- **129-167行目**: FindAndReplaceKeyboardBarDelegateの実装

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

```
TalkPageViewController
    │
    ├─ showFindInPage()
    │      └─ FindAndReplaceKeyboardBar（表示）
    │
    ├─ keyboardBar(_:didChangeSearchTerm:) [デリゲート]
    │      └─ TalkPageFindInPageState.search()
    │              └─ TalkPageFindInPageSearchController.search()
    │
    ├─ keyboardBarDidTapNext/Previous [デリゲート]
    │      ├─ TalkPageFindInPageState.next()/previous()
    │      └─ scrollToFindInPageResult()
    │
    └─ hideFindInPage()
           └─ TalkPageFindInPageState.reset()
```

### データフロー図

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

検索テキスト ────────────▶  TalkPageFindInPageState            ▶ matches[]
                           ┌─────────────────────────┐
トピック配列 ────────────▶  │  TalkPageFindInPage    │         ▶ selectedIndex
(viewModel.topics)         │  SearchController      │
                           │  ・タイトル検索         │         ▶ highlightText
                           │  ・コメント検索         │            (各ビューモデル)
                           │  ・返信検索             │
                           └─────────────────────────┘         ▶ UIハイライト表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TalkPageFindInPageState.swift | `Wikipedia/Code/TalkPageFindInPageState.swift` | ソース | 検索状態管理 |
| TalkPageFindInPageSearchController.swift | `Wikipedia/Code/TalkPageFindInPageSearchController.swift` | ソース | 検索ロジック実装 |
| TalkPageViewController+FindInPage.swift | `Wikipedia/Code/TalkPageViewController+FindInPage.swift` | ソース | UIコントローラー連携 |
| FindAndReplaceKeyboardBar.swift | `Wikipedia/Code/FindAndReplaceKeyboardBar.swift` | ソース | 検索入力UI |
| TalkPageCellViewModel.swift | `Wikipedia/Code/TalkPageCellViewModel.swift` | ソース | highlightText, activeHighlightResultプロパティ |
