# 画面設計書 66-Share画面

## 概要

本ドキュメントは、Wikipedia iOSアプリのShare画面の設計を記載したものです。この画面は記事の共有機能において、Share-a-factカードを生成し、システムの共有シートを表示するための中間画面です。

### 本画面の処理概要

Share画面は、ユーザーが記事内のテキストを選択して共有する際に、選択テキストと記事情報を組み合わせたShare-a-factカード（画像）を生成し、iOSの標準共有シート（UIActivityViewController）を表示する画面です。

**業務上の目的・背景**：Wikipediaの情報を他のアプリやSNSで簡単に共有できるようにすることで、知識の拡散を促進します。単純なURLの共有ではなく、選択したテキストと記事タイトル、画像を組み合わせた視覚的に魅力的なShare-a-factカードを生成することで、共有コンテンツの質を高めています。

**画面へのアクセス方法**：Article画面で記事内のテキストを選択し、コンテキストメニューから「Share-a-fact」を選択することで表示されます。

**主要な操作・処理内容**：
1. 画面表示中に「Building Share-a-fact card...」メッセージを表示
2. 記事の画像とライセンス情報を非同期で取得
3. ShareAFactViewControllerを使用してShare-a-factカードを生成
4. 生成したカードをプレビュー表示
5. UIActivityViewControllerで共有シートを表示
6. キャンセルボタンでの中断対応

**画面遷移**：
- 遷移元：Article画面（テキスト選択後のコンテキストメニュー）
- 遷移先：システム共有シート（UIActivityViewController）、元のArticle画面（共有完了/キャンセル時）

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 記事共有 | 主機能 | 記事URLやテキストの共有 |

## 画面種別

共有準備画面 / モーダル

## URL/ルーティング

該当なし（コードからインスタンス化してモーダル表示）

## 入出力項目

| 項目名 | 型 | 入力/出力 | 必須 | 説明 |
|--------|-----|----------|------|------|
| text | String | 入力 | 必須 | 共有するテキスト |
| article | WMFArticle | 入力 | 必須 | 共有する記事オブジェクト |
| theme | Theme | 入力 | 必須 | 適用するテーマ |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| busyView | 中央 | ローディング中の背景ビュー |
| busyLabel | 中央 | 「Building Share-a-fact card...」メッセージ |
| cancelButton | 下部 | キャンセルボタン |
| imageView | 中央 | 生成されたShare-a-factカードのプレビュー |

## イベント仕様

### 1-init

初期化処理。

- text, article, themeを受け取り
- articleURLをarticle.urlから取得（失敗時はnil返却）
- articleTitle, articleDescription, articleImageURLを設定
- modalPresentationStyleを.overCurrentContextに設定
- loadImage()で画像の非同期読み込みを開始

### 2-viewDidLoad

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

- busyLabelに「Building Share-a-fact card...」を設定
- cancelButtonに「Cancel」を設定
- apply(theme:)でテーマを適用

### 3-viewDidAppear

画面表示後の処理。

- loadGroup.waitInBackground()で画像読み込み完了を待機
- createShareAFactCard()でShare-a-factカードを生成
- showActivityViewController(with:)で共有シートを表示

### 4-loadImage

画像とライセンス情報の非同期読み込み。

- articleImageURLからファイル名を抽出
- MWKImageInfoFetcherでGallery情報（ライセンス）を取得
- imageCache.fetchImageで画像を取得
- WMFTaskGroupで複数の非同期処理を管理

### 5-createShareAFactCard

Share-a-factカードの生成。

- ShareAFactViewControllerをインスタンス化
- update(with:)で記事情報、テキスト、画像、ライセンスを設定
- wmf_snapshotImage()でビューを画像に変換

### 6-showActivityViewController

共有シートの表示。

- cancelButtonを無効化
- imageViewに生成したカードをプレビュー表示
- busyViewをフェードアウト
- ShareAFactActivityTextItemProvider, ShareAFactActivityImageItemProviderを設定
- UIActivityViewControllerを表示
- completionWithItemsHandlerでdismiss処理

### 7-cancel

キャンセルボタン押下時の処理。

- 画面をdismiss

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

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

この画面ではデータベース操作は発生しません。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| share-building | 情報 | Building Share-a-fact card... | カード生成中 |
| cancel | ボタン | Cancel | 常時 |

## 例外処理

| 例外条件 | 対処 |
|----------|------|
| articleURLがnil | init?でnil返却 |
| 画像読み込み失敗 | 画像なしでカード生成 |
| ライセンス情報取得失敗 | ライセンス情報なしでカード生成 |

## 備考

- MWKDataStore.shared()をシングルトンとして使用（TODOコメントあり）
- 画像の幅640pxでリクエスト
- UIActivityViewControllerでは.addToReadingListを除外
- ポップオーバー表示に対応（iPad）
- 共有完了後、0.75秒のディレイを入れてからActivity Controllerを表示

---

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

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

### 推奨読解順序

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

共有に必要なデータ構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ShareViewController.swift | `Wikipedia/Code/ShareViewController.swift` | プロパティ定義（text, articleTitle, articleURL等） |
| 1-2 | ShareAFactActivityTextItemProvider.swift | `Wikipedia/Code/ShareAFactActivityTextItemProvider.swift` | 共有テキストのフォーマット定義 |

**読解のコツ**: WMFTaskGroupが画像読み込みとライセンス情報取得の完了を同期するために使用されています。

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

初期化から共有シート表示までの流れを確認します。

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

**主要処理フロー**:
1. **25-39行目**: init - パラメータ設定、loadImage()呼び出し
2. **45-50行目**: viewDidLoad - UIラベル設定、テーマ適用
3. **52-58行目**: viewDidAppear - loadGroup待機、カード生成、共有シート表示
4. **72-97行目**: loadImage - 画像とライセンスの非同期読み込み

#### Step 3: カード生成を理解する

Share-a-factカードの生成処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ShareAFactViewController.swift | `Wikipedia/Code/ShareAFactViewController.swift` | update(with:)メソッド |

**主要処理フロー**:
- **49-111行目**: update(with:) - 記事情報、テキスト、画像、ライセンスの設定
- **31-47行目**: viewDidLoad - UIの初期設定、グラデーションの設定

#### Step 4: 共有アイテムプロバイダを理解する

共有時のテキストフォーマットを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ShareAFactActivityTextItemProvider.swift | `Wikipedia/Code/ShareAFactActivityTextItemProvider.swift` | activityTypeごとのフォーマット |

**主要処理フロー**:
- **15-29行目**: item - activityTypeによるフォーマット分岐
- **35-58行目**: 各種フォーマット定義（email, message, social等）

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

```
Article画面（テキスト選択）
    |
    +-- ShareViewController.init(text:article:theme:)
           |
           +-- loadImage()
           |      +-- MWKImageInfoFetcher.fetchGalleryInfo()
           |      +-- imageCache.fetchImage()
           |
           +-- viewDidAppear()
                  +-- loadGroup.waitInBackground()
                  |
                  +-- createShareAFactCard()
                  |      +-- ShareAFactViewController
                  |      +-- update(with:...)
                  |      +-- wmf_snapshotImage()
                  |
                  +-- showActivityViewController()
                         +-- ShareAFactActivityTextItemProvider
                         +-- ShareAFactActivityImageItemProvider
                         +-- UIActivityViewController
```

### データフロー図

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

text                   --> ShareViewController              --> busyLabel表示
article                     |
theme                       +-- loadImage()
                            |      |
                            |      v
                            |   MWKImageInfoFetcher --> imageLicense
                            |   imageCache --> image
                            |
                            +-- createShareAFactCard()
                            |      |
                            |      v
                            |   ShareAFactViewController
                            |      |
                            |      v
                            |   wmf_snapshotImage() --> UIImage
                            |
                            +-- showActivityViewController()
                            |      |
                            |      v
                            |   imageView表示
                            |      |
                            |      v
                            |   UIActivityViewController
                            |
                            v
                       共有完了/キャンセル --> dismiss
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ShareViewController.swift | `Wikipedia/Code/ShareViewController.swift` | ソース | 共有画面のViewController |
| ShareViewController.xib | `Wikipedia/Code/ShareViewController.xib` | NIB | 画面レイアウト |
| ShareAFactViewController.swift | `Wikipedia/Code/ShareAFactViewController.swift` | ソース | Share-a-factカード生成 |
| ShareAFactViewController.xib | `Wikipedia/Code/ShareAFactViewController.xib` | NIB | カードレイアウト |
| ShareAFactActivityTextItemProvider.swift | `Wikipedia/Code/ShareAFactActivityTextItemProvider.swift` | ソース | テキスト共有アイテムプロバイダ |
| ShareAFactActivityImageItemProvider.swift | `Wikipedia/Code/ShareAFactActivityImageItemProvider.swift` | ソース | 画像共有アイテムプロバイダ |
| MWKImageInfoFetcher.swift | `WMF/Sources/WMF/` | ソース | 画像情報フェッチャー |
| LicenseView.swift | `Wikipedia/Code/LicenseView.swift` | ソース | ライセンス表示ビュー |
