同期UIコンポーネント
クラウド同期システムのUIコンポーネント設計
同期UIコンポーネント
このドキュメントでは、クラウド同期システムに関連するUIコンポーネントについて説明します。
1. コンポーネント概要
| コンポーネント | ファイル | 役割 | レンダリング |
|---|---|---|---|
AutoSyncManager | components/sync/AutoSyncManager.tsx | バックグラウンド同期管理 | なし(Null component) |
SyncStatusIndicator | components/sync/SyncStatusIndicator.tsx | 同期ステータス表示 | あり(ボタン/ツールチップ) |
AutoSaveManager | components/AutoSaveManager.tsx | 自動保存管理 | なし(Null component) |
SyncConfirmationDialog | components/sync/SyncConfirmationDialog.tsx | 同期実行の確認・選択 | あり (Dialog) |
SyncSettings | components/sync/SyncSettings.tsx | 同期設定・デンジャーゾーン | あり (Page section) |
2. AutoSyncManager
アプリケーションルートにマウントされるUIなしコンポーネントです。
機能
-
SyncScheduler の初期化とライフサイクル管理
- 同期設定の変更検知
- タイマーのクリーンアップ
- コンポーネントアンマウント時のリソース解放
-
データ変更検知によるデバウンス同期
globalChunkVersionAtomを監視- リアルタイムモードで30秒のデバウンス後に同期を実行
-
クラウド更新チェック
- 定期的な更新チェック(デフォルト5分間隔)
- ウィンドウフォーカス時の更新チェック
[!IMPORTANT] 現在の手動同期モデルにおける注意点 実装上は自動同期のロジックを保持していますが、現在は信頼性確保のため「マニュアル同期」のみを推奨・有効化しています。そのため、
AutoSyncManagerは主に「クラウド側の更新チェック」と「フォーカス時の同期確認トリガー」を担当します。
実装
// SyncSchedulerの初期化
const scheduler = new SyncScheduler(
settings,
async () => { /* 同期実行 */ },
async () => { /* 更新チェック */ }
);
// データ変更検知
useEffect(() => {
if (!syncEnabled) return;
schedulerRef.current?.scheduleDebouncedUpload();
setIsDebouncing(schedulerRef.current?.isDebouncing() || false);
}, [globalChunkVersion, syncEnabled]);注意点
- 手動モードでは、初期チェックとデータ変更による同期をスキップ
isDebouncingAtomを使用して、UI側でデバウンシング状態を表示可能
3. AutoSaveManager
プロジェクトの自動保存を管理するUIなしコンポーネントです。
機能
-
isProjectDirtyAtomの監視- プロジェクトに未保存の変更があるかどうかを検知
- 変更がある場合のみ保存処理を実行
-
デバウンス付き自動保存
- 変更検知から2秒間待機
- 待機中に追加の変更があった場合、タイマーをリセット
- 2秒間変更がなければ、
saveProjectAtomを実行
実装
export const AutoSaveManager = () => {
const isDirty = useAtomValue(isProjectDirtyAtom);
const saveProject = useSetAtom(saveProjectAtom);
// ... デバウンス処理 ...
};4. SyncStatusIndicator
同期ステータスを表示するUIコンポーネントです。
表示要素
| 要素 | 説明 |
|---|---|
| アイコン | Loader2(同期中)、CheckCircle2(完了)、CloudOff(エラー)、Cloud(待機) |
| デバウンインジケーター | isDebouncing が true の場合、青いインジケーターを表示 |
| ツールチップ | ステータスラベル、最終同期時刻、クリックヒント |
ステータスとラベル
| ステータス | ラベル | アイコン |
|---|---|---|
idle | Cloud Sync | Cloud |
checking | Checking cloud... | Loader2 (animate-spin) |
uploading | Uploading changes... | Loader2 (animate-spin) |
downloading | Restoring from cloud... | Loader2 (animate-spin) |
synced | Synced | CheckCircle2 |
error | Sync Error | CloudOff (text-destructive) |
デバウンシング状態
isDebouncing が true の場合:
- ツールチップに「Waiting for cloud sync...」を表示
- 同期ステータスが
uploadingでない場合、青いインジケーターを表示
手動同期トリガー
ボタンのクリックで syncDataAtom を呼び出し、手動同期を実行します。
5. SyncConfirmationDialog
同期実行前に、ローカルとクラウドの状態を比較し、ユーザーに方向を選択させるダイアログです。
主な機能
- インライン・ステップ・トランジション:
Comparison→Confirm (Upload/Restore)のマルチステップ構成を単一ダイアログ内で実現。framer-motionによる滑らかなスライド遷移を採用。 - ステップ・インジケーター:
Progressコンポーネントを用い、現在のステップ(1/2)を明示。 - 状態の比較と推奨提示: クラウドの
user_sync_stateとローカルの最終更新・最終同期時刻を比較し、状況に応じた推奨アクションを色とアイコンで提示。 - i18n完全対応: すべてのメッセージとアクションラベルを多言語化 (
ja.json/en.json)。 - 実体フェッチ: ダイアログが開かれた際に Supabase から最新の同期メタデータを再取得。
6. SyncSettings (Danger Zone)
同期設定ページの下部に配置される、破壊的な操作を行うためのセクションです。
構成要素
- Wipe Cloud Backup: クラウド上のバックアップファイルとメタデータを完全に消去・初期化します。
- 警告ダイアログ: 実行前に「この操作は取り消せません」という警告を表示し、意図しない削除を防ぎます。
- 状態のクリーンアップ: ワイプ成功時、ローカルの同期関連キャッシュ(
cloudSyncStateAtom,lastSyncedAtAtom)を全てクリアし、UIを初期状態に戻します。
同期モードの制限
現在、SyncSettings では「オート(リアルタイム)」および「定期実行」の設定を disabled にし、**「COMING SOON」**バッジを表示しています。これにより、ユーザーによる予期せぬ自動上書きを防ぎ、動作が安定している「マニュアル同期」のみを使用させる運用としています。
7. Jotai Atom との連携
同期UIコンポーネントは、以下のJotai Atomと連携します。
| Atom | 用途 | 更新タイミング |
|---|---|---|
syncStatusAtom | 同期ステータスの保持 | 同期処理の各フェーズ |
lastSyncedAtAtom | 最終同期日時の保持 | 同期完了時・ワイプ時(nullリセット) |
cloudSyncStateAtom | クラウドデータのキャッシュ | フェッチ時・ワイプ時(nullリセット) |
isDebouncingAtom | デバウンシング状態の保持 | データ変更時・同期実行時 |
8. 同期完了後のUI更新
同期完了後、以下のAtomがトリガーされ、UIが更新されます。
// 同期完了後のデータリロード
await ctx.set(loadProjectAtom, activeProjectId);
await ctx.set(loadCharactersAtom);
await ctx.set(fetchPromptAssetsAtom);これにより、ブラウザの IndexedDB キャッシュによる不整合を回避しています。