mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-13 14:52:19 +00:00
Never let a share rewrite the Data Library entries remembered as on
Every restore wrote the selection it applied to browser storage, so opening a link that switched no library entry on stored every saved entry as off, and the next bare visit restored them off. Core layer state never writes a recipient's preferences from a share. The library now keeps what is remembered as on apart from what a share switches on for the session: a share's entries still join the library, but only a local restore and the viewer's own choices change what is remembered.
This commit is contained in:
1 parent
53f0a32a1b
commit
2d5db9f63d
2 files changed
+60
-7
No files matched your search
@@ -69,6 +69,10 @@ export function createDataLibrary({
|
|||||||
let availability = new Map();
|
let availability = new Map();
|
||||||
let serverPresent = false;
|
let serverPresent = false;
|
||||||
let selection = { added: [], on: [] };
|
let selection = { added: [], on: [] };
|
||||||
|
// What this browser remembers as on. Like core layer state, a share
|
||||||
|
// decides what is on for the session but never rewrites it: only the
|
||||||
|
// viewer's explicit choices and a local restore do.
|
||||||
|
let savedOn = [];
|
||||||
let started = false;
|
let started = false;
|
||||||
// Set once availability is known; a share navigated to before then waits.
|
// Set once availability is known; a share navigated to before then waits.
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
@@ -89,7 +93,11 @@ export function createDataLibrary({
|
|||||||
|
|
||||||
const persist = () => {
|
const persist = () => {
|
||||||
selection = normalizeLibrarySelection(selection, switchable);
|
selection = normalizeLibrarySelection(selection, switchable);
|
||||||
writeStoredLibrarySelection(storage, selection);
|
savedOn = savedOn.filter((id) => selection.added.includes(id));
|
||||||
|
writeStoredLibrarySelection(storage, {
|
||||||
|
added: selection.added,
|
||||||
|
on: savedOn,
|
||||||
|
});
|
||||||
shareLink?.onLibraryStateChange?.();
|
shareLink?.onLibraryStateChange?.();
|
||||||
notify();
|
notify();
|
||||||
};
|
};
|
||||||
@@ -163,9 +171,16 @@ export function createDataLibrary({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const on = new Set(selection.on);
|
const on = new Set(selection.on);
|
||||||
if (change.enabled) on.add(id);
|
const saved = new Set(savedOn);
|
||||||
else on.delete(id);
|
if (change.enabled) {
|
||||||
|
on.add(id);
|
||||||
|
saved.add(id);
|
||||||
|
} else {
|
||||||
|
on.delete(id);
|
||||||
|
saved.delete(id);
|
||||||
|
}
|
||||||
selection = { ...selection, on: [...on] };
|
selection = { ...selection, on: [...on] };
|
||||||
|
savedOn = [...saved];
|
||||||
persist();
|
persist();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -217,9 +232,10 @@ export function createDataLibrary({
|
|||||||
console.warn(`[Library] ${id} restore failed:`, error),
|
console.warn(`[Library] ${id} restore failed:`, error),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
writeStoredLibrarySelection(storage, selection);
|
// A share's entries join the library; only a local restore sets what
|
||||||
shareLink?.onLibraryStateChange?.();
|
// is remembered as on.
|
||||||
notify();
|
if (origin !== 'share-restore') savedOn = selection.on;
|
||||||
|
persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,6 +278,7 @@ export function createDataLibrary({
|
|||||||
availability = answer.availability;
|
availability = answer.availability;
|
||||||
serverPresent = answer.server;
|
serverPresent = answer.server;
|
||||||
const stored = readStoredLibrarySelection(storage, switchable);
|
const stored = readStoredLibrarySelection(storage, switchable);
|
||||||
|
savedOn = stored.on;
|
||||||
// A share opened in this tab while availability loaded wins over the
|
// A share opened in this tab while availability loaded wins over the
|
||||||
// opening one.
|
// opening one.
|
||||||
const linked = queuedShare ? idsForTokens(queuedShare) : openingShare();
|
const linked = queuedShare ? idsForTokens(queuedShare) : openingShare();
|
||||||
|
|||||||
@@ -201,12 +201,48 @@ test('a link decides what is on and adds its entries to the library', async (t)
|
|||||||
await manager.waitForLayerSettled?.('lib-sea-marks');
|
await manager.waitForLayerSettled?.('lib-sea-marks');
|
||||||
assert.equal(manager.isEnabled('lib-sea-marks'), true);
|
assert.equal(manager.isEnabled('lib-sea-marks'), true);
|
||||||
assert.equal(manager.isEnabled('lib-night-lights'), false);
|
assert.equal(manager.isEnabled('lib-night-lights'), false);
|
||||||
|
// The link's entry joins the library; what is remembered as on stays
|
||||||
|
// the viewer's own.
|
||||||
assert.deepEqual(JSON.parse(storage.store.get(LIBRARY_STORAGE_KEY)), {
|
assert.deepEqual(JSON.parse(storage.store.get(LIBRARY_STORAGE_KEY)), {
|
||||||
added: ['night-lights', 'sea-marks'],
|
added: ['night-lights', 'sea-marks'],
|
||||||
on: ['sea-marks'],
|
on: ['night-lights'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('a share never rewrites what this browser remembers as on', async (t) => {
|
||||||
|
const saved = JSON.stringify({
|
||||||
|
added: ['night-lights', 'sea-marks'],
|
||||||
|
on: ['night-lights'],
|
||||||
|
});
|
||||||
|
const storage = memoryStorage(saved);
|
||||||
|
const manager = sealedManager(t);
|
||||||
|
const shareLink = fakeShareLink([]);
|
||||||
|
const library = createDataLibrary({
|
||||||
|
entries,
|
||||||
|
ledger,
|
||||||
|
dataManager: manager,
|
||||||
|
services: {},
|
||||||
|
storage,
|
||||||
|
shareLink,
|
||||||
|
source: source({}),
|
||||||
|
});
|
||||||
|
await library.start();
|
||||||
|
assert.equal(manager.isEnabled('lib-night-lights'), false);
|
||||||
|
shareLink.listener(['01']);
|
||||||
|
await manager.waitForLayerSettled?.('lib-sea-marks');
|
||||||
|
assert.equal(manager.isEnabled('lib-sea-marks'), true);
|
||||||
|
assert.deepEqual(JSON.parse(storage.store.get(LIBRARY_STORAGE_KEY)), {
|
||||||
|
added: ['night-lights', 'sea-marks'],
|
||||||
|
on: ['night-lights'],
|
||||||
|
});
|
||||||
|
// An explicit choice is remembered, and only that one.
|
||||||
|
await manager.setEnabled('lib-sea-marks', false, { origin: 'user' });
|
||||||
|
await manager.setEnabled('lib-night-lights', true, { origin: 'user' });
|
||||||
|
await manager.setEnabled('lib-night-lights', false, { origin: 'user' });
|
||||||
|
assert.deepEqual(JSON.parse(storage.store.get(LIBRARY_STORAGE_KEY)).on, []);
|
||||||
|
library.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
/** A ShareLinkManager stand-in: the opening share and in-tab navigation. */
|
/** A ShareLinkManager stand-in: the opening share and in-tab navigation. */
|
||||||
function fakeShareLink(initialLibraryTokens) {
|
function fakeShareLink(initialLibraryTokens) {
|
||||||
const link = {
|
const link = {
|
||||||
|
|||||||
Reference in new issue
Block a user