# 機能設計書 29-編集通知

## 概要

本ドキュメントは、Wikipedia iOSアプリケーションにおける編集通知機能の設計を記載する。この機能により、記事編集時に表示される重要な通知（編集ルール、テンプレート情報など）をユーザーに提示する。

### 本機能の処理概要

編集通知機能は、記事編集開始時にMediaWiki APIから取得した編集通知（editnotice）をモーダル画面で表示し、ユーザーに編集前の注意事項を伝える。

**業務上の目的・背景**：特定の記事やカテゴリには編集に関する重要な通知が設定されている。これらを編集前に表示することで、編集者がルールを把握し、質の高い編集を行えるよう支援する。

**機能の利用シーン**：記事編集を開始する際、その記事に編集通知が存在する場合に自動的に表示される。ユーザー設定で常時表示を制御可能。

**主要な処理内容**：
1. VisualEditor APIから編集通知を取得
2. HTML形式の通知内容をAttributedStringに変換
3. モーダル画面で通知を表示
4. リンクタップ時のナビゲーション
5. 「常に表示」設定のトグル制御

**関連システム・外部連携**：MediaWiki VisualEditor API

**権限による制御**：特になし（通知がある場合に表示）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 記事編集画面 | 遷移元 | 編集開始時に通知確認 |
| - | 編集通知画面 | メイン画面 | 通知内容の表示 |

## 機能種別

情報表示、API連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| theme | Theme | Yes | テーマ設定 | - |
| viewModel | EditNoticesViewModel | Yes | 通知データ | - |
| siteURL | URL | Yes | サイトURL（ViewModel内） | - |
| notices | [Notice] | Yes | 通知配列（ViewModel内） | - |

### 入力データソース

- MediaWiki VisualEditor API（action=visualeditor, paction=metadata）
- UserDefaults（wmf_alwaysDisplayEditNotices設定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| wmf_alwaysDisplayEditNotices | Bool | 常時表示設定 |

### 出力先

- UserDefaults（トグル設定保存）
- EditNoticesViewControllerDelegate.editNoticesControllerUserTapped（リンクナビゲーション）

## 処理フロー

### 処理シーケンス

```
1. 通知取得（編集画面側）
   ├─ EditNoticesFetcher.fetchNotices
   ├─ VisualEditor APIリクエスト
   └─ Notice配列生成

2. 画面表示
   ├─ EditNoticesViewModel生成
   ├─ EditNoticesViewController生成
   └─ モーダル表示

3. 通知レンダリング
   ├─ HTML→AttributedString変換
   ├─ RTL言語対応
   └─ テキストビュー表示

4. ユーザー操作
   ├─ Done: 画面クローズ
   ├─ トグル: 設定保存
   └─ リンクタップ: デリゲート通知
```

### フローチャート

```mermaid
flowchart TD
    A[編集開始] --> B[EditNoticesFetcher.fetchNotices]
    B --> C{通知あり?}
    C -->|No| D[編集画面表示]
    C -->|Yes| E{常時表示 OR 初回?}
    E -->|Yes| F[EditNoticesViewController表示]
    E -->|No| D
    F --> G[通知内容表示]
    G --> H{ユーザー操作}
    H -->|Done| I[画面クローズ]
    H -->|トグル| J[UserDefaults保存]
    H -->|リンクタップ| K[URLナビゲーション]
    I --> D
    J --> G
    K --> L[外部/内部遷移]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | editnoticeフィルタ | キーに"editnotice"を含む通知のみ表示 | 常時 |
| BR-002 | 常時表示設定 | wmf_alwaysDisplayEditNoticesで制御 | 設定時 |
| BR-003 | RTL対応 | 言語コードに応じてテキスト配置を変更 | RTL言語時 |
| BR-004 | HTML変換 | 通知HTMLをAttributedStringに変換 | 常時 |
| BR-005 | 相対URLベース | リンクはsiteURLを基準に解決 | リンクタップ時 |

### 計算ロジック

| 計算項目 | 計算式・ロジック |
|---------|----------------|
| semanticContentAttribute | `MWKLanguageLinkController.semanticContentAttribute(forContentLanguageCode:)` |
| テキスト配置 | RTL ? .right : .left |

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

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

本機能はデータベース操作を行わない。UserDefaultsに設定を保存。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 処理内容 |
|-----------|---------|---------|
| invalidParameters | タイトル取得失敗 | 通知取得中断 |
| API error | ネットワークエラー | 通知なしとして処理 |

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

該当なし

## パフォーマンス要件

特になし

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

特になし

## 備考

- 通知はHTML形式で提供され、HtmlUtilsでAttributedStringに変換
- VoiceOver対応として、textViewのアクセシビリティ要素を遅延表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EditNoticesFetcher.swift | `Wikipedia/Code/EditNoticesFetcher.swift` | Notice構造体（L5-8） |
| 1-2 | EditNoticesViewModel.swift | `Wikipedia/Code/EditNoticesViewModel.swift` | ViewModel定義（L3-21） |

**読解のコツ**: Notice.descriptionがHTML形式であり、後でAttributedStringに変換されることを理解する。

#### Step 2: API通信を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EditNoticesFetcher.swift | `Wikipedia/Code/EditNoticesFetcher.swift` | fetchNotices（L24-54） |
| 2-2 | EditNoticesFetcher.swift | `Wikipedia/Code/EditNoticesFetcher.swift` | Response構造体（L10-20） |

**主要処理フロー**:
- **L30-37**: APIパラメータ（action=visualeditor, paction=metadata）
- **L45-48**: editnoticeキーでフィルタリング
- **L39-53**: レスポンス解析とNotice配列生成

#### Step 3: View Controller を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | EditNoticesViewController.swift | `Wikipedia/Code/EditNoticesViewController.swift` | init（L21-25） |
| 3-2 | EditNoticesViewController.swift | `Wikipedia/Code/EditNoticesViewController.swift` | loadView（L31-40） |

**主要処理フロー**:
- **L34**: `editNoticesView.configure(viewModel:theme:)` 呼び出し
- **L36-39**: ボタン/スイッチのアクション設定
- **L38**: UserDefaults読み込み（wmf_alwaysDisplayEditNotices）

#### Step 4: View レイアウトを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | EditNoticesView.swift | `Wikipedia/Code/EditNoticesView.swift` | UI要素定義（L7-157） |
| 4-2 | EditNoticesView.swift | `Wikipedia/Code/EditNoticesView.swift` | configure（L253-274） |

**主要処理フロー**:
- **L254**: HtmlUtils.Stylesでフォント・色設定
- **L256-260**: 通知をAttributedStringに変換
- **L262**: 改行の正規化
- **L263**: RTL対応テキスト配置

#### Step 5: イベント処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | EditNoticesViewController.swift | `Wikipedia/Code/EditNoticesViewController.swift` | dismissView（L55-57） |
| 5-2 | EditNoticesViewController.swift | `Wikipedia/Code/EditNoticesViewController.swift` | didToggleSwitch（L59-61） |
| 5-3 | EditNoticesViewController.swift | `Wikipedia/Code/EditNoticesViewController.swift` | UITextViewDelegate（L72-85） |

**主要処理フロー**:
- **L55-57**: Doneボタンで画面dismiss
- **L59-61**: トグル変更時にUserDefaults更新
- **L74-81**: リンクタップ時にURLをデリゲートに通知

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

```
EditorViewController / ArticleViewController
    │
    └─ EditNoticesFetcher.fetchNotices()
           │
           ├─ performDecodableMediaWikiAPIGET()
           │      └─ action=visualeditor, paction=metadata
           │
           └─ [Notice] 取得成功
                  │
                  ▼
           EditNoticesViewModel(siteURL:, notices:)
                  │
                  ▼
           EditNoticesViewController(theme:, viewModel:)
                  │
                  ├─ loadView()
                  │      └─ EditNoticesView.configure()
                  │             ├─ HtmlUtils.Styles
                  │             └─ NSAttributedString.attributedStringFromHtml()
                  │
                  ├─ dismissView()
                  │      └─ dismiss(animated:)
                  │
                  ├─ didToggleSwitch()
                  │      └─ UserDefaults.wmf_alwaysDisplayEditNotices = ...
                  │
                  └─ textView(_:shouldInteractWith:)
                         └─ delegate?.editNoticesControllerUserTapped(url:)
```

### データフロー図

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

articleURL             ───▶ EditNoticesFetcher.fetchNotices()
                                │
                                ▼
                         VisualEditor API
                                │
                                ▼
                         Response.visualEditor.notices
                                │
                                ▼
                         editnoticeフィルタ ───▶ [Notice]
                                │
                                ▼
                         EditNoticesViewModel
                                │
                                ▼
                         EditNoticesView.configure()
                                │
                                ├─▶ AttributedString変換 ───▶ textView.attributedText
                                │
                                └─▶ semanticContentAttribute ───▶ テキスト配置

トグル操作             ───▶ didToggleSwitch() ───▶ UserDefaults

リンクタップ           ───▶ textView(_:shouldInteractWith:)
                                │
                                ▼
                         delegate.editNoticesControllerUserTapped() ───▶ URL遷移
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EditNoticesViewController.swift | `Wikipedia/Code/EditNoticesViewController.swift` | ソース | 編集通知表示VC |
| EditNoticesView.swift | `Wikipedia/Code/EditNoticesView.swift` | ソース | 編集通知カスタムビュー |
| EditNoticesViewModel.swift | `Wikipedia/Code/EditNoticesViewModel.swift` | ソース | 編集通知ビューモデル |
| EditNoticesFetcher.swift | `Wikipedia/Code/EditNoticesFetcher.swift` | ソース | 編集通知API取得 |
| HtmlUtils.swift | `Wikipedia/Code/HtmlUtils.swift` | ソース | HTML→AttributedString変換 |
| MWKLanguageLinkController.swift | `Wikipedia/Code/MWKLanguageLinkController.swift` | ソース | 言語・RTL判定 |
