# 画面設計書 19-ユーザー設定パネル (Preferences)

## 概要

本ドキュメントは、Next.js開発モード時にDevToolsのテーマ、表示位置、スケール、非表示ショートカットなどのユーザー設定を変更するパネルの画面設計書である。

### 本画面の処理概要

ユーザー設定パネルは、DevToolsメニューの"Preferences"項目からアクセスできる設定画面である。DevToolsの外観・動作に関する各種設定を変更でき、変更内容はlocalStorageに永続化される。

**業務上の目的・背景**：開発者が自分の好みに合わせてDevToolsの外観と動作をカスタマイズできるようにする。テーマ（Light/Dark/System）、表示位置（四隅）、サイズ（Small/Medium/Large）の変更、一時的な非表示設定、キーボードショートカットの設定、開発サーバーの再起動など、開発体験を向上させる各種機能を提供する。

**画面へのアクセス方法**：DevToolsメニューの"Preferences"（歯車アイコン）をクリックすると表示される。PanelRouterで`panel`状態が'preferences'の場合に描画される。

**主要な操作・処理内容**：
1. テーマ変更（System/Light/Dark）- Shadow DOMポータルのクラスを切り替え、設定を永続化
2. 表示位置変更（Bottom Left/Bottom Right/Top Left/Top Right）- インジケーターと全パネルの位置を更新
3. サイズ変更（Small/Medium/Large）- DevToolsのスケールを更新
4. DevTools一時非表示 - セッション期間または1日間DevToolsを非表示に
5. 非表示ショートカット設定 - カスタムキーボードショートカットで表示/非表示をトグル
6. DevTools完全無効化の案内 - next.config設定の説明
7. 開発サーバーの再起動 - ブラウザからサーバーをリスタート
8. バンドラーキャッシュのリセット（Turbopack永続キャッシュ有効時のみ）

**画面遷移**：
- 遷移元: DevToolsメニューのPreferencesクリック
- 遷移先: 閉じるボタンでDevToolsインジケーターに戻る / パネル外クリックで閉じる

**権限による表示制御**：バンドラーキャッシュリセット項目は`process.env.__NEXT_BUNDLER_HAS_PERSISTENT_CACHE`がtrueの場合のみ表示。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 94 | DevTools（開発者ツール） | 主機能 | DevToolsのテーマ・表示位置・スケール・非表示ショートカット等のユーザー設定変更処理 |
| 1 | next dev | 補助機能 | 開発サーバー設定のAPI呼び出しによるDevToolsインジケーター非表示化 |

## 画面種別

設定パネル（DynamicPanel、固定サイズ）

## URL/ルーティング

固有のURLは持たない。PanelRouterの`panel`状態が'preferences'の場合に表示される。

## 入出力項目

| 項目名 | 種別 | 型 | 説明 |
|--------|------|-----|------|
| state.theme | Context入力 | 'dark' \| 'light' \| 'system' | 現在のテーマ設定 |
| state.devToolsPosition | Context入力 | DevToolsIndicatorPosition | 現在の表示位置 |
| state.scale | Context入力 | DevToolsScale | 現在のスケール値 |
| state.hideShortcut | Context入力 | string \| null | 現在の非表示ショートカット設定 |

## 表示項目

| 表示項目 | UIコンポーネント | 説明 | 操作 |
|----------|-----------------|------|------|
| Theme | Select（ドロップダウン） | System/Light/Dark選択 | テーマアイコン（System/Light/Dark）付き |
| Position | Select（ドロップダウン） | Bottom Left/Bottom Right/Top Left/Top Right選択 | - |
| Size | Select（ドロップダウン） | NEXT_DEV_TOOLS_SCALE定義のSmall/Medium/Large選択 | - |
| Hide Dev Tools for this session | Button | 一時非表示ボタン（EyeIcon付き） | "Hide"ボタン |
| Hide Dev Tools shortcut | ShortcutRecorder | キーボードショートカット記録UI | ショートカット入力 |
| Disable Dev Tools for this project | 説明テキスト | `devIndicators: false`設定の案内 | 操作なし（情報のみ） |
| Restart Dev Server | Button | 開発サーバー再起動ボタン | "Restart"ボタン |
| Reset Bundler Cache | Button | バンドラーキャッシュリセットボタン | "Reset Cache"ボタン（永続キャッシュ有効時のみ） |

## イベント仕様

### 1-テーマ変更

handleThemeChange関数で以下を実行：
- "system": Shadow DOMポータルから'dark'/'light'クラスを両方除去。`saveDevToolsConfig({ theme: 'system' })`
- "dark": 'dark'クラス追加、'light'クラス除去。`saveDevToolsConfig({ theme: 'dark' })`
- "light": 'light'クラス追加、'dark'クラス除去。`saveDevToolsConfig({ theme: 'light' })`

### 2-表示位置変更

handlePositionChange関数で以下を実行：
1. `setPosition(value)` -> `dispatch(ACTION_DEVTOOLS_POSITION)`
2. `saveDevToolsConfig({ devToolsPosition: value })`
3. `updateAllPanelPositions(value)` -> 全パネルの位置同期

### 3-サイズ変更

handleSizeChange関数で以下を実行：
1. `setScale(Number(value))` -> `dispatch(ACTION_DEVTOOLS_SCALE)`
2. `saveDevToolsConfig({ scale: value })`

### 4-DevTools一時非表示

hide関数で以下を実行：
1. `dispatch(ACTION_DEV_INDICATOR_SET, disabled: true)` - インジケーター非表示化
2. `setSelectedIndex(-1)` - メニュー選択リセット
3. `setPanel(null)` - パネル閉じる
4. `fetch('/__nextjs_disable_dev_indicator', { method: 'POST' })` - サーバーサイドにも通知

### 5-非表示ショートカット設定

ShortcutRecorderコンポーネントでキー入力を記録し、`setHideShortcut(value)` -> `saveDevToolsConfig({ hideShortcut: value })`で永続化。値は`+`区切りの文字列（例: "Ctrl+Shift+H"）。

### 6-開発サーバー再起動

`restartServer({ invalidateFileSystemCache: false })`を呼び出し、開発サーバーを再起動。`isPending`中はボタンが無効化される。

### 7-バンドラーキャッシュリセット

`restartServer({ invalidateFileSystemCache: true })`を呼び出し、バンドラーキャッシュをクリアしてからサーバーを再起動。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| テーマ/位置/サイズ/ショートカット変更 | localStorage | WRITE | saveDevToolsConfigでの設定永続化 |
| DevTools一時非表示 | - | HTTP POST | `/__nextjs_disable_dev_indicator`でサーバーに通知 |
| サーバー再起動 | - | HTTP | useRestartServerフック経由でサーバー再起動APIを呼び出し |

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 表示条件 |
|---------------|---------------|----------|
| 説明 | "Select your theme preference." | Theme項目 |
| 説明 | "Adjust the placement of your dev tools." | Position項目 |
| 説明 | "Adjust the size of your dev tools." | Size項目 |
| 説明 | "Hide Dev Tools until you restart your dev server, or 1 day." | Hide項目 |
| 説明 | "Set a custom keyboard shortcut to toggle visibility." | Shortcut項目 |
| 説明 | "To disable this UI completely, set `devIndicators: false` in your `next.config` file." | Disable項目 |
| 説明 | "Restarts the development server without needing to leave the browser." | Restart項目 |
| 説明 | "Clears the bundler cache and restarts the dev server. Helpful if you are seeing stale errors or changes are not appearing." | Reset Cache項目 |

## 例外処理

- サーバー再起動中（`isPending`がtrue）はRestart/Reset Cacheボタンが無効化される（disabled属性）
- `/__nextjs_disable_dev_indicator`へのfetchが失敗した場合の明示的なエラーハンドリングはない（クライアント側の非表示状態は維持される）

## 備考

- パネルサイズは固定（高さ 500/scale、幅 480+32px）
- `closeOnClickOutside: true`でパネル外クリックによる閉じ動作を有効化
- `sharePanelSizeGlobally: false`でサイズを個別管理
- NEXT_DEV_TOOLS_SCALEはSmall(16/14)、Medium(16/16=1)、Large(16/18)の3段階
- テーマ切り替えはShadow DOMポータルのクラス操作で行われるため、ユーザーアプリのスタイルに影響しない
- ShortcutRecorderは`+`区切りのキー文字列（例: "Meta+Shift+D"）を管理

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | shared.ts | `packages/next/src/next-devtools/dev-overlay/shared.ts` | DevToolsConfig型（行11-22）: theme, devToolsPosition, scale, hideShortcut等の永続化設定。NEXT_DEV_TOOLS_SCALE（行29-33）: Small/Medium/Largeのスケール値。ACTION_DEVTOOLS_POSITION, ACTION_DEVTOOLS_SCALE, ACTION_DEV_INDICATOR_SET定数 |

#### Step 2: パネルルーティングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | panel-router.tsx | `packages/next/src/next-devtools/dev-overlay/menu/panel-router.tsx` | PanelRoute name="preferences"（行174-187）: DynamicPanelのサイズ設定。UserPreferencesWrapper（行265-307）: dispatch/state/setPanel/setSelectedIndex/updateAllPanelPositionsを取得してUserPreferencesBodyに渡すラッパー |

**主要処理フロー**:
1. **行176**: sharePanelSizeGlobally: false
2. **行178-180**: 高さ 500/scale、幅 480+32
3. **行182**: closeOnClickOutside: true
4. **行183**: DevToolsHeaderでタイトル"Preferences"
5. **行265-307**: UserPreferencesWrapperでユーザー設定の各コールバックを構成

#### Step 3: ユーザー設定UIを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | user-preferences.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/dev-tools-indicator/dev-tools-info/user-preferences.tsx` | UserPreferencesBody（行17-228）: Theme/Position/Size/Hide/Shortcut/Disable/Restart/Reset Cache各セクションの構成。handleThemeChange（行39-57）: テーマ切り替えロジック。handlePositionChange（行59-64）: 位置変更。handleSizeChange（行66-70）: サイズ変更 |

**主要処理フロー**:
1. **行36**: `useRestartServer()`からrestartServer, isPendingを取得
2. **行37**: `useDevOverlayContext()`からshadowRootを取得
3. **行39-57**: テーマ変更 - Shadow DOMポータルのクラス操作
4. **行59-64**: 位置変更 - setPosition + saveDevToolsConfig
5. **行66-70**: サイズ変更 - setScale + saveDevToolsConfig
6. **行140-149**: Hide Dev Toolsボタン - hide()コールバック
7. **行160-165**: ShortcutRecorderでショートカット記録
8. **行188-199**: Restart Dev Serverボタン
9. **行202-225**: Reset Bundler Cacheボタン（条件付き表示）

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

```
PanelRouter (panel-router.tsx)
    |
    +-- PanelRoute name="preferences"
           +-- DynamicPanel (fixed size, closeOnClickOutside)
                  |
                  +-- DevToolsHeader title="Preferences"
                  +-- UserPreferencesWrapper (panel-router.tsx)
                         +-- UserPreferencesBody (user-preferences.tsx)
                                |
                                +-- Theme Select
                                |      +-- handleThemeChange -> shadow DOM class toggle
                                |      +-- saveDevToolsConfig
                                |
                                +-- Position Select
                                |      +-- setPosition -> dispatch(ACTION_DEVTOOLS_POSITION)
                                |      +-- updateAllPanelPositions
                                |      +-- saveDevToolsConfig
                                |
                                +-- Size Select
                                |      +-- setScale -> dispatch(ACTION_DEVTOOLS_SCALE)
                                |      +-- saveDevToolsConfig
                                |
                                +-- Hide Button
                                |      +-- dispatch(ACTION_DEV_INDICATOR_SET)
                                |      +-- fetch(/__nextjs_disable_dev_indicator)
                                |
                                +-- ShortcutRecorder
                                |      +-- saveDevToolsConfig
                                |
                                +-- Restart Button
                                |      +-- restartServer({ invalidateFileSystemCache: false })
                                |
                                +-- Reset Cache Button [conditional]
                                       +-- restartServer({ invalidateFileSystemCache: true })
```

### データフロー図

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

state.theme             --> Theme Select               --> shadowRoot.host class
state.devToolsPosition  --> Position Select            --> dispatch + saveConfig
state.scale             --> Size Select                --> dispatch + saveConfig
state.hideShortcut      --> ShortcutRecorder           --> saveConfig
                              |
Hideボタンクリック        --> hide()                     --> dispatch + API POST
Restartボタンクリック     --> restartServer()            --> サーバー再起動
Reset Cacheクリック       --> restartServer(invalidate)  --> キャッシュクリア+再起動
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| user-preferences.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/dev-tools-indicator/dev-tools-info/user-preferences.tsx` | ソース | UserPreferencesBodyコンポーネント、各設定UIとハンドラー |
| panel-router.tsx | `packages/next/src/next-devtools/dev-overlay/menu/panel-router.tsx` | ソース | PanelRoute "preferences"、UserPreferencesWrapper |
| shortcut-recorder.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/dev-tools-indicator/dev-tools-info/shortcut-recorder.tsx` | ソース | ShortcutRecorderコンポーネント |
| save-devtools-config.ts | `packages/next/src/next-devtools/dev-overlay/utils/save-devtools-config.ts` | ソース | localStorage永続化ユーティリティ |
| use-restart-server.ts | `packages/next/src/next-devtools/dev-overlay/components/errors/error-overlay-toolbar/use-restart-server.ts` | ソース | 開発サーバー再起動フック |
| shared.ts | `packages/next/src/next-devtools/dev-overlay/shared.ts` | ソース | DevToolsConfig型、NEXT_DEV_TOOLS_SCALE、アクション定数 |
| dynamic-panel.tsx | `packages/next/src/next-devtools/dev-overlay/panel/dynamic-panel.tsx` | ソース | DynamicPanelコンポーネント |
| dev-tools-header.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/dev-tools-indicator/dev-tools-info/dev-tools-header.tsx` | ソース | DevToolsHeaderコンポーネント |
| eye-icon.tsx | `packages/next/src/next-devtools/dev-overlay/icons/eye-icon.tsx` | ソース | Hideボタンのアイコン |
| light-icon.tsx | `packages/next/src/next-devtools/dev-overlay/icons/light-icon.tsx` | ソース | Lightテーマアイコン |
| dark-icon.tsx | `packages/next/src/next-devtools/dev-overlay/icons/dark-icon.tsx` | ソース | Darkテーマアイコン |
| system-icon.tsx | `packages/next/src/next-devtools/dev-overlay/icons/system-icon.tsx` | ソース | Systemテーマアイコン |
