開発コンポーネント
同期コンポーネント
E2E暗号化クラウド同期機能のUIコンポーネント設計
09. 同期コンポーネント (Sync Components)
1. 概要
このドキュメントでは、E2E暗号化クラウド同期機能に関連するUIコンポーネントについて説明します。これらのコンポーネントは、ユーザーがデバイス間で安全にデータを同期するためのインターフェースを提供します。
2. コンポーネント一覧
2.1. SyncSettings
ファイルパス: next-app/src/components/sync/SyncSettings.tsx
役割: Sync Keyの管理とクラウド同期の設定を行うメインコンポーネント。Settings ページに配置され、ログインユーザーのみに表示されます。
主な機能:
- 未設定時のセットアップウィザード起動 (
SyncSetupWizard) - Sync Keyの表示/非表示切り替え
- Sync Keyのクリップボードへのコピー
- 手動バックアップ・リストアのトリガー(確認ダイアログ付き)
- Sync機能の無効化
状態管理:
syncKeyAtom: 現在のSync KeyuploadBackupAtom: バックアップアップロード処理downloadBackupAtom: バックアップダウンロード処理
UI構成:
Sync Key未設定時
┌─────────────────────────────────────┐
│ ☁️ Cloud Sync │
│ Sync your data across devices... │
├─────────────────────────────────────┤
│ │
│ [🛡️ Shield Icon] │
│ │
│ Sync is not set up │
│ Enable secure cloud backup... │
│ │
│ [Start Cloud Sync Setup] │
│ │
└─────────────────────────────────────┘Sync Key設定済み
┌─────────────────────────────────────┐
│ ✅ E2E Encrypted Sync Active │
│ Your data is encrypted before │
│ leaving this device. │
├─────────────────────────────────────┤
│ Your Sync Key │
│ ┌─────────────────────────────────┐ │
│ │ •••••••••••••••••••••••••• [👁]│ │
│ └─────────────────────────────────┘ │
│ You will need this key to access │
│ your data on other devices. │
│ │
│ [📋 Copy Key] [🗑️ Disable Sync] │
├─────────────────────────────────────┤
│ Danger Zone │
│ [⬆️ Force Backup] [⬇️ Force Restore]│
│ (Requires confirmation) │
└─────────────────────────────────────┘2.2. SyncSetupWizard
ファイルパス: next-app/src/components/sync/SyncSetupWizard.tsx
役割: クラウド同期の初期設定をステップバイステップでガイドするモーダルコンポーネント。
フロー:
- Intro: 機能概要の説明と開始ボタン。
- Mode Selection:
- Start New Sync: 新規キーを生成し、現在のデータをアップロード。
- Restore Data: 既存キーを入力し、クラウドからデータをダウンロード。
- Key Management:
- 新規作成時はキーを表示し、保存確認(チェックボックス)を要求。
- 復元時は入力されたキーのフォーマット(BIP39)を検証。
- Completion:
- 自動的に初回のアップロードまたはダウンロードを実行。
- 完了メッセージとアニメーションを表示。
UX設計のポイント:
- 明確な分岐: 「新規」か「復元」かを最初に選ばせることで、ユーザーのメンタルモデルに合わせる。
- 安全なデフォルト: 復元時は「データが上書きされる」ことを警告。
- フィードバック: 処理中はローディングを表示し、完了時は祝賀アニメーションを表示。
2.2. SyncStatusIndicator
ファイルパス: next-app/src/components/sync/SyncStatusIndicator.tsx
役割: グローバルヘッダーに配置される同期ステータスインジケーター。現在の同期状態を視覚的に表示し、手動同期のトリガーとしても機能します。
主な機能:
- 同期ステータスのリアルタイム表示
- クリックによる手動同期のトリガー
- ツールチップでの詳細情報表示
- 定期的なクラウド更新チェック
状態管理:
syncStatusAtom: 現在の同期ステータスlastSyncedAtAtom: 最終同期時刻uploadBackupAtom: 手動同期のトリガーcheckForCloudUpdatesAtom: クラウド更新チェック
ステータスとアイコン:
| ステータス | アイコン | 色 | 説明 |
|---|---|---|---|
idle | Cloud | グレー | 待機中 |
checking | Loader (回転) | プライマリ | クラウド確認中 |
uploading | Loader (回転) | プライマリ | バックアップ中 |
downloading | Loader (回転) | プライマリ | 復元中 |
synced | CheckCircle | 緑 | 同期完了 |
error | CloudOff | 赤 | エラー発生 |
自動チェック機能:
useEffect(() => {
checkUpdates(); // 初回チェック
// 5分ごとに定期チェック
const interval = setInterval(() => {
checkUpdates();
}, 5 * 60 * 1000);
return () => clearInterval(interval);
}, [checkUpdates]);ツールチップ表示内容:
┌─────────────────────────┐
│ Synced │
│ Last synced: 14:32:15 │
│ │
│ Click to sync now │
└─────────────────────────┘配置:
- グローバルヘッダー(
Header.tsx)の右側 - ユーザーアバターの左隣
- ログインユーザーのみ表示
実装の詳細:
const getIcon = () => {
switch (status) {
case 'checking':
case 'uploading':
case 'downloading':
return <Loader2 className="h-4 w-4 animate-spin text-primary" />;
case 'synced':
return <CheckCircle2 className="h-4 w-4 text-green-500" />;
case 'error':
return <CloudOff className="h-4 w-4 text-destructive" />;
default:
return <Cloud className="h-4 w-4 text-muted-foreground" />;
}
};2.3. AutoSyncManager
ファイルパス: next-app/src/components/sync/AutoSyncManager.tsx
役割: バックグラウンド自動同期を管理するUIレスコンポーネント。アプリのルートレイアウトに配置され、ユーザーの操作を妨げずに自動同期を実行します。
主な機能:
- データベース変更の監視(
useLiveQuery) - 30秒のデバウンス処理
- ウィンドウフォーカス時のクラウド更新チェック
- 5分間隔の定期更新チェック
状態管理:
syncKeyAtom: Sync Keyの有無を確認userAtom: ログイン状態を確認syncStatusAtom: 現在の同期ステータスisDebouncingAtom: デバウンス中かどうか(新規)uploadBackupAtom: バックアップアップロード処理checkForCloudUpdatesAtom: クラウド更新チェック処理
デバウンスロジック:
const scheduleUpload = useCallback(() => {
if (!syncEnabled || status === 'uploading') return;
// Clear existing timer
if (debounceTimerRef.current) {
clearTimeout(debounceTimerRef.current);
}
lastChangeTimeRef.current = Date.now();
setIsDebouncing(true);
// Set new timer (30 seconds)
debounceTimerRef.current = setTimeout(() => {
console.log('[AutoSync] Triggering background upload after 30s debounce');
setIsDebouncing(false);
triggerUpload();
}, 30000); // 30 seconds
}, [syncEnabled, status, triggerUpload, setIsDebouncing]);監視対象:
db.projects.count(): プロジェクト数の変化db.chatMessages.count(): チャットメッセージ数の変化
チェックトリガー:
- ウィンドウフォーカス時:
window.addEventListener('focus', ...) - 定期実行:
setInterval(5分間隔) - 初回マウント時: コンポーネント表示時
設計のポイント:
- UIレス: このコンポーネントは何もレンダリングせず、副作用のみを管理
- 条件付き有効化: ログイン済み & Sync Key設定済みの場合のみ動作
- 重複防止: アップロード中は新たなデバウンスタイマーをセットしない
- クリーンアップ: アンマウント時にタイマーをクリア
3. データフロー
3.1. バックアップフロー
3.2. リストアフロー
4. エラーハンドリング
4.1. 復号失敗
try {
jsonData = await decryptData(data, syncKey);
} catch (decryptError) {
console.error('Decryption failed:', decryptError);
toast.error('Failed to decrypt backup. Incorrect Sync Key?');
throw decryptError;
}4.2. ネットワークエラー
try {
const { error: uploadError } = await supabase.storage
.from(BUCKET_NAME)
.upload(filePath, encryptedBlob, { upsert: true });
if (uploadError) throw uploadError;
} catch (error) {
console.error('Backup upload failed:', error);
set(syncStatusAtom, 'error');
toast.error('Cloud sync failed. Please check your connection.');
}4.3. Sync Key未設定
if (!syncKey) {
console.log('Sync skipped: No sync key configured');
return;
}5. セキュリティ考慮事項
5.1. Zero-Knowledge アーキテクチャ
- すべての暗号化処理はクライアント側で実行
- Sync Keyはサーバーに送信されない
- サーバー側ではデータを復号できない
5.2. Sync Keyの保存
localStorageに平文で保存- HTTPS通信が前提
- XSS対策はアプリケーション全体で実施
5.3. RLS(Row Level Security)
- Supabase側でユーザーごとにアクセス制御
- 他ユーザーのバックアップにはアクセス不可
6. 今後の拡張
Phase 2: 自動同期 ✅ 実装済み (2025-12-04)
- ✅ データ変更検知による自動バックアップ
- ✅ アプリ起動時の自動リストア
- ✅ バックグラウンド同期
- ✅ デバウンス処理(30秒)
- ✅ 定期更新チェック(5分間隔)
- ✅ ウィンドウフォーカス時の更新チェック
Phase 3: 競合解決
- タイムスタンプベースのマージ
- ユーザーによる手動選択UI
- 差分同期の実装
Phase 4: Pro Plan統合
- 無料ユーザーへの制限
- バックアップ履歴の管理
- 複数デバイスの管理UI
7. 関連ドキュメント
02_technology_stack.md- Web Crypto API03_state_management.md- syncAtoms04_database_schema_supabase.md- user_sync_state, user_backups/doc/log/reports/2025-12-03_report_implement-e2e-cloud-sync.md- 実装レポート