# 機能設計書 83-設定の自動リロード

## 概要

本ドキュメントは、Windows Terminal の settings.json ファイルの変更を監視し、変更検知時に自動的に設定を再読み込みする機能を記述する。AppLogic クラス内のファイル変更監視とスロットリング付きリロード処理が中核である。

### 本機能の処理概要

**業務上の目的・背景**：ユーザーが外部テキストエディタで settings.json を編集した場合、アプリケーションを再起動することなく変更を即座に反映させる必要がある。本機能はファイルシステムの変更通知を利用して settings.json の変更を検知し、自動的に設定を再読み込みする。

**機能の利用シーン**：ユーザーが VS Code や notepad などで settings.json を直接編集し保存した際に、Windows Terminal がその変更を自動検知してUIや動作に反映する。

**主要な処理内容**：
1. wil::unique_folder_change_reader_nothrow による設定ファイルディレクトリの監視
2. ファイル名変更および最終更新日時の変更イベントの検知
3. ThrottledFunc による 100ms のデバウンス付きリロード処理
4. AppLogic::ReloadSettings() によるCascadiaSettings の再読み込み
5. SettingsChanged イベントの発火による UI への変更通知

**関連システム・外部連携**：Windows ファイルシステム変更通知 API、言語プロファイル変更通知（LanguageProfileNotifier）。

**権限による制御**：特別な権限による制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | TerminalPage（メイン画面） | 結果表示画面 | 設定変更が反映される画面 |

## 機能種別

バックグラウンド監視 / イベント駆動処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| settingsPath | std::filesystem::path | Yes | settings.json のファイルパス | 有効なパス |

### 入力データソース

- ファイルシステムからの変更通知イベント（wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime）
- 言語プロファイル変更通知（LanguageProfileNotifier）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SettingsChanged イベント | typed_event | 設定変更を通知するイベント |
| SettingsLoadEventArgs | winrt オブジェクト | リロード結果（成功/失敗、警告一覧、新しい設定オブジェクト） |

### 出力先

- イベントバス：SettingsChanged イベントのサブスクライバ（TerminalWindow 等）に通知

## 処理フロー

### 処理シーケンス

```
1. AppLogic::Create() で初期化
   └─ _reloadSettings を ThrottledFunc として作成（100ms デバウンス）
2. 初回 ReloadSettings() の末尾で _RegisterSettingsChange() を呼び出し
   └─ _reader.create() で設定ディレクトリの監視を開始
3. ファイル変更検知
   └─ コールバックでファイル名が settings.json のベースネームと一致するか確認
   └─ 一致すれば ReloadSettingsThrottled() を呼び出し
4. ThrottledFunc がデバウンス後に ReloadSettings() を実行
   └─ _TryLoadSettings() で新しい設定を読み込み
5. 読み込み成功時
   └─ _ApplyLanguageSettingChange() で言語設定を適用
   └─ _ProcessLazySettingsChanges() で遅延設定変更を処理
   └─ SettingsChanged イベントを発火
6. 読み込み失敗時
   └─ 既存の設定を保持したまま、エラー情報を SettingsChanged イベントで通知
```

### フローチャート

```mermaid
flowchart TD
    A[settings.json 変更検知] --> B{ファイル名一致?}
    B -->|No| C[無視]
    B -->|Yes| D[ReloadSettingsThrottled]
    D --> E[ThrottledFunc - 100ms デバウンス]
    E --> F[ReloadSettings]
    F --> G[_TryLoadSettings]
    G --> H{読み込み成功?}
    H -->|Yes| I[_ApplyLanguageSettingChange]
    I --> J[_ProcessLazySettingsChanges]
    J --> K[SettingsChanged イベント発火]
    H -->|No| L{初回読み込み?}
    L -->|Yes| M[デフォルト設定にフォールバック]
    L -->|No| N[既存設定を保持]
    M --> K
    N --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-83-01 | デバウンス | 設定リロードは 100ms のデバウンスで実行される | ファイル変更検知時 |
| BR-83-02 | ファイル名フィルタリング | settings.json のベースネームと一致するファイルの変更のみ処理 | 変更通知受信時 |
| BR-83-03 | 初回読み込み失敗時のフォールバック | 初回に設定読み込みが失敗した場合はデフォルト設定を使用 | 初回起動時 |
| BR-83-04 | 既存設定の保持 | リロード時に設定読み込みが失敗した場合は既存の設定を保持 | リロード時 |
| BR-83-05 | テキストエディタ対応 | ファイル名変更イベントも監視することで、テンポラリファイル→リネームの操作パターンに対応 | 常時 |

### 計算ロジック

該当なし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 読み込み失敗 | settings.json のパースに失敗 | 初回は LoadDefaults()、リロード時は既存設定保持 |
| HRESULT | TryLoadSettings 失敗 | ファイル読み込みまたはパースのエラー | _settingsLoadedResult に格納し SettingsChanged で通知 |

### リトライ仕様

自動リトライは行わないが、次にファイルが変更された際に再度リロードが試行される。

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

該当なし。

## パフォーマンス要件

- ThrottledFunc により 100ms のデバウンスが適用され、高頻度のファイル変更（エディタによる連続書き込み等）でもリロードは1回にまとめられる。
- リロード処理は UI ディスパッチャキューで実行される。

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

- ファイル変更監視はユーザーの設定ディレクトリに限定される。

## 備考

- wil::FolderChangeEvents::FileName を監視する理由：テキストエディタはテンポラリファイルに書き込んでからリネームする場合がある（「why is App not registered?」問題の回避）。
- LanguageProfileNotifier からの通知でもリロードがトリガーされる。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AppLogic.h | `src/cascadia/TerminalApp/AppLogic.h` | _reloadSettings（ThrottledFunc, 68行目）、_reader（wil::unique_folder_change_reader_nothrow, 75行目）のメンバ定義。SettingsChanged イベント（52行目）の定義 |

**読解のコツ**: ThrottledFunc はスロットリング・デバウンス機能を提供するユーティリティで、UIスレッドでの実行保証も行う。_reader は WIL ライブラリのフォルダ変更監視クラス。

#### Step 2: エントリーポイント（初期化）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppLogic.cpp | `src/cascadia/TerminalApp/AppLogic.cpp` | AppLogic コンストラクタ（137-149行目）で _reloadSettings を初期化。100ms のデバウンス設定 |

**主要処理フロー**:
1. **137-149行目**: _reloadSettings を ThrottledFunc として作成。delay=100ms, debounce=true, trailing=true
2. **151-155行目**: LanguageProfileNotifier を初期化し、ReloadSettingsThrottled を呼ぶよう設定

#### Step 3: ファイル監視の登録を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AppLogic.cpp | `src/cascadia/TerminalApp/AppLogic.cpp` | _RegisterSettingsChange メソッド（303-337行目）でフォルダ変更監視を登録 |

**主要処理フロー**:
- **303行目**: _RegisterSettingsChange メソッド開始
- **305行目**: settings.json のパスから親ディレクトリを取得
- **306-336行目**: _reader.create() で監視を開始。FileName | LastWriteTime イベントを監視
- **332-334行目**: ファイル名がsettings.jsonと一致すれば ReloadSettingsThrottled() を呼ぶ

#### Step 4: リロード処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AppLogic.cpp | `src/cascadia/TerminalApp/AppLogic.cpp` | ReloadSettings メソッド（375-438行目）でリロードの全体フローを理解 |

**主要処理フロー**:
- **375行目**: ReloadSettings メソッド開始
- **382行目**: _TryLoadSettings() で新しい設定を読み込み
- **387-393行目**: 失敗時の処理。初回なら LoadDefaults()、そうでなければ既存設定保持
- **414行目**: _ApplyLanguageSettingChange()
- **415行目**: _ProcessLazySettingsChanges()
- **420行目**: 初回の場合は _RegisterSettingsChange() を呼んでリターン
- **432-437行目**: SettingsChanged イベントを発火

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

```
[ファイルシステム変更通知]
    │
    └─ _reader コールバック (AppLogic.cpp:314)
           │
           └─ AppLogic::ReloadSettingsThrottled (AppLogic.cpp:440)
                  │
                  └─ ThrottledFunc::Run (100ms デバウンス)
                         │
                         └─ AppLogic::ReloadSettings (AppLogic.cpp:375)
                                │
                                ├─ _TryLoadSettings (AppLogic.cpp:206)
                                │      └─ CascadiaSettings::LoadAll()
                                │
                                ├─ _ApplyLanguageSettingChange
                                ├─ _ProcessLazySettingsChanges
                                │
                                └─ SettingsChanged.raise()
```

### データフロー図

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

ファイルシステム ───▶ _reader コールバック ───▶ ThrottledFunc
変更通知                                       (100ms デバウンス)
                                                    │
                                                    ▼
settings.json ──────▶ ReloadSettings ────────▶ SettingsChanged
(ファイル)             ├─ _TryLoadSettings         イベント
                      │    └─ LoadAll()              │
                      └─ CascadiaSettings ◀──────────┘
                         (メモリ更新)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppLogic.h | `src/cascadia/TerminalApp/AppLogic.h` | ヘッダ | AppLogic クラス定義。_reloadSettings / _reader メンバ |
| AppLogic.cpp | `src/cascadia/TerminalApp/AppLogic.cpp` | ソース | _RegisterSettingsChange / ReloadSettings / ReloadSettingsThrottled 実装 |
| ThrottledFunc.h | `src/cascadia/TerminalApp/inc/ThrottledFunc.h` | ヘッダ | スロットリング・デバウンスユーティリティ |
| LanguageProfileNotifier.h | `src/cascadia/TerminalApp/LanguageProfileNotifier.h` | ヘッダ | 言語プロファイル変更通知 |
| CascadiaSettingsSerialization.cpp | `src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp` | ソース | LoadAll の実装 |
| SettingsLoadEventArgs.h | `src/cascadia/TerminalApp/SettingsLoadEventArgs.h` | ヘッダ | リロード結果イベントの引数 |
