# 画面設計書 34-WebView画面

## 概要

本ドキュメントは、Bagisto eコマースモバイルアプリにおける「WebView画面」の画面設計書です。本画面は、外部URLをアプリ内のWebViewで表示するための汎用画面を提供します。

### 本画面の処理概要

本画面は、指定されたURLをInAppWebViewを使用してアプリ内で表示します。認証情報（Cookie、Authorization、ロケール、通貨設定）をHTTPヘッダーに含めてリクエストを送信し、認証が必要なコンテンツも表示可能です。読み込み進捗はLinearProgressIndicatorで視覚的に表示されます。

**業務上の目的・背景**：ECアプリでは、外部の決済ページ、配送追跡ページ、ソーシャルメディアリンク、詳細な商品情報ページなど、アプリ外のWebコンテンツを表示する必要があるケースが多くあります。本画面は、ユーザーがアプリを離れることなくこれらのコンテンツを閲覧できるようにし、シームレスなユーザー体験を提供します。また、認証情報を引き継ぐことで、ログイン状態を維持したまま各種サービスにアクセスできます。

**画面へのアクセス方法**：他の画面から`Navigator.pushNamed(context, commonWebView, arguments: ColumnModel(...))`で遷移します。CMSページからのリンク、サイドドロワーメニューの外部リンク項目、商品詳細ページからの外部リンクなど、様々な場所から呼び出されます。ルーティングは`commonWebView`という名前で定義されています。

**主要な操作・処理内容**：
1. 画面表示時に指定されたURLをWebViewで読み込み開始
2. HTTPヘッダーに認証情報（Cookie、Authorization、x-currency、x-locale等）を設定
3. 読み込み進捗をLinearProgressIndicatorで表示（0%〜100%）
4. 読み込み完了後はプログレスバーを非表示
5. ページ内のナビゲーション（リンククリック等）は全て許可
6. 読み込みエラー時はdebugPrintでログ出力

**画面遷移**：本画面からの直接的な画面遷移はありません。WebView内でのリンククリックはWebView内でハンドリングされます。AppBarの戻るボタンで前の画面に戻ることができます。

**権限による表示制御**：本画面自体へのアクセス制限はありませんが、表示するURLによっては認証が必要な場合があります。その場合は、appStoragePrefから取得したCookieとAuthorizationトークンがリクエストヘッダーに含まれます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 70 | WebView表示 | 主機能 | 外部URLのWebView表示処理 |

## 画面種別

詳細（コンテンツ表示画面）

## URL/ルーティング

- ルート名: `commonWebView`
- ルート定数: `const String commonWebView = "commonWebView";`
- ナビゲーション: `Navigator.pushNamed(context, commonWebView, arguments: ColumnModel(url: "...", title: "..."))`
- 引数: `ColumnModel`オブジェクト（url, title）

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | データ型 | 必須 | バリデーション | 備考 |
|--------|--------|----------|----------|------|----------------|------|
| リダイレクトURL | redirectUrl | 入力（引数） | String? | 必須 | なし | 表示するWebページのURL |
| タイトル | title | 入力（引数） | String? | 任意 | なし | AppBarに表示 |

## 表示項目

| 項目名 | 表示位置 | データソース | 表示形式 | 備考 |
|--------|----------|-------------|----------|------|
| 画面タイトル | AppBar | widget.title | テキスト | 引数で渡されたタイトル |
| Webコンテンツ | 本文エリア | InAppWebView | HTML | 指定されたURLのコンテンツ |
| プログレスバー | 画面上部 | loadData | LinearProgressIndicator | 読み込み進捗（0%〜100%） |

## イベント仕様

### 1-WebView初期化（build）

画面ビルド時に以下の設定でInAppWebViewが初期化されます：

1. `initialUrlRequest`でURLとヘッダーを設定
2. `keepAlive: InAppWebViewKeepAlive()`でWebViewの状態を保持
3. HTTPヘッダーに以下を設定：
   - Cookie: `appStoragePref.getCookieGet()`
   - x-currency: `GlobalData.currencyCode`
   - x-locale: `GlobalData.locale`
   - is-cookie-exist: "1"
   - Accept: "application/json"
   - Authorization: `appStoragePref.getCustomerToken()`

### 2-読み込み開始（onLoadStart）

1. コントローラーとURLがコールバックで渡される
2. debugPrintでログ出力：「Page start loading: $url」

### 3-読み込み完了（onLoadStop）

1. コントローラーとURLがコールバックで渡される
2. debugPrintでログ出力：「Page finished loading: $url」

### 4-進捗更新（onProgressChanged）

1. コントローラーと進捗（0〜100）がコールバックで渡される
2. `setState()`で`loadData`を更新（progress / 100）
3. プログレスバーの表示が更新される
4. `loadData < 1`の間はプログレスバーが表示される

### 5-エラー発生（onReceivedError）

1. コントローラー、リクエスト、エラー情報がコールバックで渡される
2. debugPrintでエラーログ出力：「Page finished loading with error : ${error.description}」

### 6-URL遷移判定（shouldOverrideUrlLoading）

1. コントローラーとnavigationActionがコールバックで渡される
2. debugPrintでログ出力：「allowing navigation to $navigationAction」
3. `NavigationActionPolicy.ALLOW`を返却して全てのナビゲーションを許可

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面ではデータベース操作は発生しない |

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

本画面はWebコンテンツの表示のみを行い、ローカルデータベースへの更新操作はありません。WebView内でフォーム送信等が行われた場合のサーバー側処理は、表示されるWebページの実装に依存します。

## メッセージ仕様

| メッセージID | メッセージ種別 | 表示条件 | メッセージ内容 | 表示方法 |
|-------------|---------------|----------|---------------|----------|
| - | - | - | 本画面ではユーザー向けメッセージ表示なし | - |

## 例外処理

| 例外状況 | 対応処理 | ユーザーへの表示 |
|---------|---------|-----------------|
| ネットワークエラー | onReceivedErrorでキャッチ | WebViewの標準エラー表示 |
| URLが不正 | Uri.parseでパース | WebViewの標準エラー表示 |
| 認証エラー（401/403） | WebViewでエラーページ表示 | サーバーからのエラーページ |
| SSL証明書エラー | WebViewのデフォルト処理 | ブラウザ標準のSSLエラー画面 |

## 備考

- flutter_inappwebviewパッケージを使用
- InAppWebViewKeepAliveで画面遷移後もWebViewの状態を保持
- プログレスバーは読み込み完了（loadData >= 1）で非表示
- プログレスバーの色は灰色（進捗）、赤（背景）
- shouldOverrideUrlLoadingでは全てのナビゲーションを許可（NavigationActionPolicy.ALLOW）
- 現在のロケールと通貨設定をサーバーに送信することで、多言語・多通貨対応

---

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

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

### 推奨読解順序

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

まず、WebView画面に渡される引数の構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | app_navigation.dart | `lib/utils/app_navigation.dart` | ColumnModelの使用方法と引数の受け渡しを確認（行391-397） |

**読解のコツ**: ColumnModelはurl（表示するURL）とtitle（画面タイトル）を持つシンプルなデータクラスです。

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

処理の起点となるWidgetファイルを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | common_webview.dart | `lib/widgets/common_webview.dart` | StatefulWidget構成、build()メソッド、各コールバック |

**主要処理フロー**:
1. **行7-17**: CommonWebViewクラス定義、コンストラクタでredirectUrlとtitleを受け取る
2. **行19-21**: CommonWebViewState、loadDataで進捗管理
3. **行23-77**: build()メソッドでScaffold構築
4. **行30-64**: InAppWebViewの設定（URL、ヘッダー、各種コールバック）
5. **行65-73**: プログレスバーの表示制御

#### Step 3: HTTPヘッダー設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | common_webview.dart | `lib/widgets/common_webview.dart` | initialUrlRequestのheaders設定（行34-41） |

**ヘッダー構成**:
- **行35**: Cookie - セッション情報
- **行36**: x-currency - 通貨コード（GlobalData.currencyCode）
- **行37**: x-locale - ロケール（GlobalData.locale）
- **行38**: is-cookie-exist - Cookie存在フラグ
- **行39**: Accept - コンテンツタイプ
- **行40**: Authorization - 認証トークン

#### Step 4: コールバック処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | common_webview.dart | `lib/widgets/common_webview.dart` | 各WebViewコールバックの処理 |

**コールバック一覧**:
- **行43-45**: onLoadStart - 読み込み開始時のログ出力
- **行46-48**: onLoadStop - 読み込み完了時のログ出力
- **行49-54**: onProgressChanged - 進捗更新（setStateでUI更新）
- **行55-58**: onReceivedError - エラー時のログ出力
- **行59-63**: shouldOverrideUrlLoading - ナビゲーション許可判定

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

```
CommonWebView (common_webview.dart)
    │
    ├─ build() [行23-77]
    │      │
    │      ├─ Scaffold
    │      │      ├─ AppBar (title: widget.title)
    │      │      └─ body: Stack
    │      │             ├─ InAppWebView
    │      │             │      ├─ initialUrlRequest (URL + Headers)
    │      │             │      ├─ onLoadStart → debugPrint
    │      │             │      ├─ onLoadStop → debugPrint
    │      │             │      ├─ onProgressChanged → setState
    │      │             │      ├─ onReceivedError → debugPrint
    │      │             │      └─ shouldOverrideUrlLoading → ALLOW
    │      │             │
    │      │             └─ LinearProgressIndicator (if loadData < 1)
    │      │
    └─ State管理
           └─ loadData: 進捗率 (0.0 〜 1.0)
```

### データフロー図

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

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│ 画面引数         │    │ URL解析          │    │ WebView表示     │
│ - redirectUrl   │───▶│ - Uri.parse()    │───▶│ - HTMLレンダリング│
│ - title         │    └──────────────────┘    └─────────────────┘
└─────────────────┘              │
                                 ▼
┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│ 認証情報         │    │ HTTPヘッダー構築  │    │ HTTPリクエスト   │
│ - Cookie        │───▶│ - Authorization  │───▶│ - サーバーへ送信  │
│ - Token         │    │ - x-locale       │    └─────────────────┘
│ - Locale        │    │ - x-currency     │
│ - Currency      │    └──────────────────┘
└─────────────────┘
         │
         ▼
┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│ 進捗コールバック  │    │ setState()       │    │ プログレスバー    │
│ - progress      │───▶│ - loadData更新   │───▶│ - 表示/非表示    │
│ (0〜100)        │    └──────────────────┘    └─────────────────┘
└─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| common_webview.dart | `lib/widgets/common_webview.dart` | Widget | 汎用WebView画面 |
| app_navigation.dart | `lib/utils/app_navigation.dart` | Router | 画面ルーティング定義（行391-397） |
| route_constants.dart | `lib/utils/route_constants.dart` | Constants | ルート名定数（行43） |
| app_constants.dart | `lib/utils/app_constants.dart` | Constants | アプリ定数（baseDomain等） |
| app_storage_pref.dart | `lib/utils/prefrence/app_storage_pref.dart` | Storage | ローカルストレージ（Cookie、Token取得） |
| global_data.dart | `lib/utils/global_data.dart` | Global | グローバルデータ（locale、currencyCode） |
