// Cloud sync — espelha o state do app na tabela user_state do Supabase. // // Quando Supabase não está configurado, todas as funções viram no-op // e o app continua usando apenas localStorage (sem perder funcionalidade). (function () { const TABLE = 'user_state'; function client() { if (window.Auth && typeof window.Auth._client === 'function') { return window.Auth._client(); } return null; } // Carrega o state da nuvem para o user logado. // Retorna o objeto data se existir, ou null se for primeiro acesso. async function loadState(userId) { const c = client(); if (!c || !userId) return null; const { data, error } = await c .from(TABLE) .select('data, updated_at') .eq('user_id', userId) .maybeSingle(); if (error) { console.warn('[cloud-sync] loadState error:', error.message); return null; } return data ? { data: data.data, updatedAt: data.updated_at } : null; } // Upsert do state. Retorna { ok: boolean }. async function saveState(userId, stateData) { const c = client(); if (!c || !userId) return { ok: false, reason: 'not-configured' }; const { error } = await c .from(TABLE) .upsert({ user_id: userId, data: stateData }, { onConflict: 'user_id' }); if (error) { console.warn('[cloud-sync] saveState error:', error.message); return { ok: false, reason: error.message }; } return { ok: true }; } // Inscreve em UPDATEs de outros dispositivos. // Retorna função de cleanup. function subscribe(userId, onChange) { const c = client(); if (!c || !userId) return () => {}; const channel = c .channel('user-state-' + userId) .on( 'postgres_changes', { event: '*', schema: 'public', table: TABLE, filter: 'user_id=eq.' + userId }, (payload) => { if (payload && payload.new && payload.new.data) { onChange(payload.new.data, payload.new.updated_at); } } ) .subscribe(); return () => { try { c.removeChannel(channel); } catch (e) {} }; } // Debounced saver: chama saveState após `delay` ms de inatividade. function makeDebouncedSaver(delay) { delay = delay || 1500; let timer = null; let lastResolve = null; return function (userId, stateData, onStatus) { if (timer) clearTimeout(timer); onStatus && onStatus({ status: 'pending' }); return new Promise((resolve) => { lastResolve = resolve; timer = setTimeout(async () => { onStatus && onStatus({ status: 'saving' }); const res = await saveState(userId, stateData); onStatus && onStatus({ status: res.ok ? 'saved' : 'error', reason: res.reason }); if (lastResolve === resolve) resolve(res); }, delay); }); }; } window.CloudSync = { loadState, saveState, subscribe, makeDebouncedSaver, isConfigured: () => !!client(), }; })();