// The prayer journal on this device, kept in step with your account. Every change is saved here at once and // sent to the account a moment later; signing in merges the two (the newer version of each prayer wins), so a prayer // added on your phone appears on your computer. Signing out clears this device's copy. import { useCallback, useEffect, useRef, useState } from 'react'; import { getRemotePrayers, saveRemotePrayers } from '../syncService.js'; import { markAnswered, markDeleted, mergePrayers, newPrayer, prayersEqual, reopen, touch, togglePrayedToday } from '../utils/prayers.js'; import { localDateString } from '../utils/readingPlans.js'; const KEY = 'prayers'; const PUSH_DELAY_MS = 1500; const load = () => { try { const v = JSON.parse(localStorage.getItem(KEY) || '[]'); return Array.isArray(v) ? v : []; } catch { return []; } }; const save = (list) => { try { localStorage.setItem(KEY, JSON.stringify(list)); } catch { /* storage unavailable */ } }; export function usePrayers() { const [prayers, setPrayersState] = useState(load); const ref = useRef(prayers); ref.current = prayers; const enabledRef = useRef(false); const timerRef = useRef(null); const push = useCallback(async () => { window.clearTimeout(timerRef.current); if (!enabledRef.current) return; const result = await saveRemotePrayers(ref.current); if (result.ok) { const merged = mergePrayers(ref.current, result.data?.prayers); if (!prayersEqual(merged, ref.current)) { ref.current = merged; save(merged); setPrayersState(merged); } } }, []); const set = useCallback((next) => { ref.current = next; save(next); setPrayersState(next); if (enabledRef.current) { window.clearTimeout(timerRef.current); timerRef.current = window.setTimeout(push, PUSH_DELAY_MS); } }, [push]); const replace = (id, fn) => set(ref.current.map((p) => (p.id === id ? fn(p) : p))); const addPrayer = (fields) => { const p = newPrayer(fields); set([p, ...ref.current]); return p; }; const editPrayer = (id, patch) => replace(id, (p) => touch(p, patch)); const togglePrayed = (id) => replace(id, (p) => togglePrayedToday(p, localDateString())); const answerPrayer = (id, note) => replace(id, (p) => markAnswered(p, note)); const reopenPrayer = (id) => replace(id, (p) => reopen(p)); // Deleting leaves a marker so the other devices drop it too; the returned function puts it back const deletePrayer = (id) => { const before = ref.current.find((p) => p.id === id); if (!before) return () => {}; set(ref.current.map((p) => (p.id === id ? markDeleted(p) : p))); return () => set(ref.current.map((p) => (p.id === id ? touch(before, {}) : p))); }; // Prayers from a backup file are added; a prayer already here keeps whichever copy is newer const importPrayers = (list) => set(mergePrayers(ref.current, list)); const pull = useCallback(async () => { enabledRef.current = true; const result = await getRemotePrayers(); if (!result.ok) return; const merged = mergePrayers(ref.current, result.data?.prayers); if (!prayersEqual(merged, ref.current)) { ref.current = merged; save(merged); setPrayersState(merged); } if (!prayersEqual(merged, result.data?.prayers ?? [])) await push(); }, [push]); const stop = useCallback(() => { enabledRef.current = false; window.clearTimeout(timerRef.current); try { localStorage.removeItem(KEY); } catch { /* storage unavailable */ } ref.current = []; setPrayersState([]); }, []); useEffect(() => () => window.clearTimeout(timerRef.current), []); return { prayers, addPrayer, editPrayer, togglePrayed, answerPrayer, reopenPrayer, deletePrayer, importPrayers, pullPrayers: pull, stopPrayers: stop }; }