BluePeriod Docs
開発コンポーネント

同期コンポーネント

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 Key
  • uploadBackupAtom: バックアップアップロード処理
  • 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

役割: クラウド同期の初期設定をステップバイステップでガイドするモーダルコンポーネント。

フロー:

  1. Intro: 機能概要の説明と開始ボタン。
  2. Mode Selection:
    • Start New Sync: 新規キーを生成し、現在のデータをアップロード。
    • Restore Data: 既存キーを入力し、クラウドからデータをダウンロード。
  3. Key Management:
    • 新規作成時はキーを表示し、保存確認(チェックボックス)を要求。
    • 復元時は入力されたキーのフォーマット(BIP39)を検証。
  4. Completion:
    • 自動的に初回のアップロードまたはダウンロードを実行。
    • 完了メッセージとアニメーションを表示。

UX設計のポイント:

  • 明確な分岐: 「新規」か「復元」かを最初に選ばせることで、ユーザーのメンタルモデルに合わせる。
  • 安全なデフォルト: 復元時は「データが上書きされる」ことを警告。
  • フィードバック: 処理中はローディングを表示し、完了時は祝賀アニメーションを表示。

2.2. SyncStatusIndicator

ファイルパス: next-app/src/components/sync/SyncStatusIndicator.tsx

役割: グローバルヘッダーに配置される同期ステータスインジケーター。現在の同期状態を視覚的に表示し、手動同期のトリガーとしても機能します。

主な機能:

  • 同期ステータスのリアルタイム表示
  • クリックによる手動同期のトリガー
  • ツールチップでの詳細情報表示
  • 定期的なクラウド更新チェック

状態管理:

  • syncStatusAtom: 現在の同期ステータス
  • lastSyncedAtAtom: 最終同期時刻
  • uploadBackupAtom: 手動同期のトリガー
  • checkForCloudUpdatesAtom: クラウド更新チェック

ステータスとアイコン:

ステータスアイコン説明
idleCloudグレー待機中
checkingLoader (回転)プライマリクラウド確認中
uploadingLoader (回転)プライマリバックアップ中
downloadingLoader (回転)プライマリ復元中
syncedCheckCircle同期完了
errorCloudOffエラー発生

自動チェック機能:

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(): チャットメッセージ数の変化

チェックトリガー:

  1. ウィンドウフォーカス時: window.addEventListener('focus', ...)
  2. 定期実行: setInterval (5分間隔)
  3. 初回マウント時: コンポーネント表示時

設計のポイント:

  • UIレス: このコンポーネントは何もレンダリングせず、副作用のみを管理
  • 条件付き有効化: ログイン済み & Sync Key設定済みの場合のみ動作
  • 重複防止: アップロード中は新たなデバウンスタイマーをセットしない
  • クリーンアップ: アンマウント時にタイマーをクリア

3. データフロー

3.1. バックアップフロー

Click "Force Backup" Trigger upload exportDB() JSON Blob encryptData(blob, syncKey) Encrypted Blob Upload to user_backups Success Update user_sync_state Set status = 'synced' Show checkmark User SyncSettings uploadBackupAtom Dexie Crypto Supabase SyncStatusIndicator

3.2. リストアフロー

Click "Force Restore" Trigger download Download from user_backups Encrypted Blob decryptData(blob, syncKey) JSON Data importInto(db, data) Success Reload page User SyncSettings downloadBackupAtom Supabase Crypto Dexie

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 API
  • 03_state_management.md - syncAtoms
  • 04_database_schema_supabase.md - user_sync_state, user_backups
  • /doc/log/reports/2025-12-03_report_implement-e2e-cloud-sync.md - 実装レポート

On this page