import React, { useState, useEffect } from 'react'; import { useCrossDeviceSync } from '../hooks/useCrossDeviceSync'; import { SyncConflict } from '../services/CrossDeviceSync'; import './CrossDeviceSyncIndicator.css'; interface ConflictModalProps { conflict: SyncConflict; onResolve: (resolution: 'take_control' | 'let_other_control' | 'dismiss') => void; } const ConflictModal: React.FC = ({ conflict, onResolve }) => { const getConflictMessage = () => { switch (conflict.type) { case 'simultaneous_playback': return 'Another device is playing music. What would you like to do?'; case 'position_drift': return 'Playback position differs significantly between devices.'; case 'queue_mismatch': return 'The queue has changed on another device.'; default: return 'A sync conflict has been detected.'; } }; return (

Sync Conflict Detected

{getConflictMessage()}

Devices involved: {conflict.devices.length}
); }; export const CrossDeviceSyncIndicator: React.FC = () => { const { syncState, connectedDevices, isEnabled } = useCrossDeviceSync(); const [showDevices, setShowDevices] = useState(false); const [currentConflict, setCurrentConflict] = useState(null); const [lastSyncTime, setLastSyncTime] = useState(''); // Update last sync time display useEffect(() => { const updateTime = () => { if (syncState.lastSyncTime) { const now = Date.now(); const diff = now - syncState.lastSyncTime; if (diff < 5000) { setLastSyncTime('just now'); } else if (diff < 60000) { setLastSyncTime(`${Math.floor(diff / 1000)}s ago`); } else { setLastSyncTime(`${Math.floor(diff / 60000)}m ago`); } } }; updateTime(); const interval = setInterval(updateTime, 1000); return () => clearInterval(interval); }, [syncState.lastSyncTime]); // Handle conflict detection useEffect(() => { const { onConflictDetected } = useCrossDeviceSync(); const unsubscribe = onConflictDetected((conflict) => { setCurrentConflict(conflict); }); return unsubscribe; }, []); const handleConflictResolve = (resolution: 'take_control' | 'let_other_control' | 'dismiss') => { // Handle conflict resolution based on user choice switch (resolution) { case 'take_control': // Force this device to be the primary controller console.log('Taking control of playback'); break; case 'let_other_control': // Let the other device control playback console.log('Letting other device control playback'); break; case 'dismiss': // Just dismiss the conflict without action console.log('Dismissing sync conflict'); break; } setCurrentConflict(null); }; const getSyncStatusIcon = () => { if (!isEnabled) return '⚫'; // Disabled if (connectedDevices.length === 0) return '🔴'; // No devices if (Date.now() - syncState.lastSyncTime > 10000) return '🟡'; // Stale sync return '🟢'; // Active sync }; const getSyncStatusText = () => { if (!isEnabled) return 'Sync disabled'; if (connectedDevices.length === 0) return 'No devices connected'; if (Date.now() - syncState.lastSyncTime > 10000) return 'Sync stale'; return `Synced with ${connectedDevices.length} device${connectedDevices.length !== 1 ? 's' : ''}`; }; if (!isEnabled && connectedDevices.length === 0) { return null; // Don't show indicator if sync is disabled and no devices } return ( <>
{showDevices && (

Connected Devices

Last sync: {lastSyncTime}
{connectedDevices.length === 0 ? (
No other devices connected
) : (
{connectedDevices.map(device => (
{device.name} {device.type}
{device.isActive ? ( Active ) : ( Inactive )}
))}
)} {syncState.currentTrack && (
Synced track: {syncState.currentTrack}
Position: {Math.floor(syncState.playbackPosition / 1000)}s Queue: {syncState.queue.length} songs
)}
)}
{currentConflict && ( )} ); };