diff options
Diffstat (limited to 'src/feed-sync.js')
| -rw-r--r-- | src/feed-sync.js | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/feed-sync.js b/src/feed-sync.js new file mode 100644 index 0000000..55d5845 --- /dev/null +++ b/src/feed-sync.js @@ -0,0 +1,23 @@ +// Custom feeds across devices: per feed, the newest edit (`at`) wins, and a +// deletion is remembered (gone: { id: ms }) so a device still holding the +// feed doesn't hand it back. Commutative, so snapshots apply in any order. +// Returns null when the remote copy changes nothing. +export function mergeFeeds(local, remote) { + const gone = { ...(local.gone || {}) }; + let changed = false; + for (const [id, t] of Object.entries(remote.gone || {})) + if (typeof t === 'number' && (gone[id] || 0) < t) { gone[id] = t; changed = true; } + const feeds = [...(local.feeds || [])]; + const touched = []; + for (const f of Array.isArray(remote.feeds) ? remote.feeds : []) { + if (!f || typeof f.id !== 'string' || (gone[f.id] || 0) >= (f.at || 0)) continue; + const i = feeds.findIndex((x) => x.id === f.id); + if (i < 0) feeds.push(f); + else if ((f.at || 0) > (feeds[i].at || 0)) feeds[i] = f; + else continue; + touched.push(f.id); changed = true; + } + const kept = feeds.filter((f) => (gone[f.id] || 0) < (f.at || 0)); + if (kept.length !== feeds.length) changed = true; + return changed ? { feeds: kept, gone, touched } : null; +} |
