mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Saves push silently as before, but if the relay copy is NEWER than the one this device last pushed (another device changed it), the user is now asked to confirm before overwriting — preventing a silent multi-device clobber. No nag on normal saves. - js/services/settingsSyncFlags.js: track per-pubkey+kind last-pushed created_at (getSyncPushedAt/setSyncPushedAt). - js/services/syncConflict.js: pushWithConflictCheck — peek remote created_at (list-only, no decrypt), compare to last push, call confirmOverwrite only on a real conflict, then push strictly-newer than remote so the replace wins. - storage/walletSyncService push()/enable() route through it and accept a confirmOverwrite callback. - ProfileStorage/WalletController supply confirmOverwrite (window.confirm) and surface a "kept the newer copy" status when the user declines. tests/sync-conflict.test.mjs: no-remote→silent, newer→prompt(+decline blocks push), confirm→strictly-newer push, older→no prompt. Mutation-verified (ignoring the decline fails). Service-test twins gained exists(). Co-Authored-By: Claude Opus 4.8 <[email protected]>
83 lines
2.3 KiB
JavaScript
83 lines
2.3 KiB
JavaScript
// Per-pubkey opt-in flags for encrypted settings sync (todo #15). Shared by the
|
|
// storage and wallet sync services so the toggle state persists locally.
|
|
// Shape: { [pubkey]: { storage?: boolean, wallet?: boolean } }. Off by default.
|
|
|
|
const FLAG_STORAGE_KEY = "bitvid:settings-sync:v1";
|
|
|
|
function readFlags() {
|
|
try {
|
|
if (typeof localStorage === "undefined") {
|
|
return {};
|
|
}
|
|
const raw = localStorage.getItem(FLAG_STORAGE_KEY);
|
|
if (!raw) {
|
|
return {};
|
|
}
|
|
const parsed = JSON.parse(raw);
|
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
} catch (error) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
function writeFlags(flags) {
|
|
try {
|
|
if (typeof localStorage === "undefined") {
|
|
return;
|
|
}
|
|
localStorage.setItem(FLAG_STORAGE_KEY, JSON.stringify(flags || {}));
|
|
} catch (error) {
|
|
// Best-effort; the flag is a convenience, not a source of truth.
|
|
}
|
|
}
|
|
|
|
function normalizePubkey(pubkey) {
|
|
return typeof pubkey === "string" ? pubkey.trim() : "";
|
|
}
|
|
|
|
export function isSyncEnabled(pubkey, kind) {
|
|
const key = normalizePubkey(pubkey);
|
|
if (!key || !kind) {
|
|
return false;
|
|
}
|
|
return readFlags()[key]?.[kind] === true;
|
|
}
|
|
|
|
export function setSyncEnabled(pubkey, kind, enabled) {
|
|
const key = normalizePubkey(pubkey);
|
|
if (!key || !kind) {
|
|
return;
|
|
}
|
|
const flags = readFlags();
|
|
const entry = flags[key] && typeof flags[key] === "object" ? flags[key] : {};
|
|
entry[kind] = enabled === true;
|
|
flags[key] = entry;
|
|
writeFlags(flags);
|
|
}
|
|
|
|
// Remember the created_at of the note we last published, per pubkey+kind, so a
|
|
// later save can detect when the relay copy is NEWER (another device changed it)
|
|
// and warn before overwriting.
|
|
export function getSyncPushedAt(pubkey, kind) {
|
|
const key = normalizePubkey(pubkey);
|
|
if (!key || !kind) {
|
|
return 0;
|
|
}
|
|
const value = Number(readFlags()[key]?.[`${kind}PushedAt`]);
|
|
return Number.isFinite(value) ? value : 0;
|
|
}
|
|
|
|
export function setSyncPushedAt(pubkey, kind, createdAt) {
|
|
const key = normalizePubkey(pubkey);
|
|
if (!key || !kind) {
|
|
return;
|
|
}
|
|
const flags = readFlags();
|
|
const entry = flags[key] && typeof flags[key] === "object" ? flags[key] : {};
|
|
entry[`${kind}PushedAt`] = Number(createdAt) || 0;
|
|
flags[key] = entry;
|
|
writeFlags(flags);
|
|
}
|
|
|
|
export const SETTINGS_SYNC_FLAG_KEY = FLAG_STORAGE_KEY;
|