fix(y-indexeddb): alert user when write operation unfinished (#2085)

This commit is contained in:
Himself65
2023-04-22 17:32:57 -05:00
committed by GitHub
parent 74e21311dc
commit 2ad1b770d0
2 changed files with 69 additions and 21 deletions

View File

@@ -240,6 +240,31 @@ describe('indexeddb provider', () => {
expect(yDoc.getMap().get('foo')).toBe('bar');
}
});
test('beforeunload', async () => {
const oldAddEventListener = window.addEventListener;
window.addEventListener = vi.fn((event: string, fn, options) => {
expect(event).toBe('beforeunload');
return oldAddEventListener(event, fn, options);
});
const oldRemoveEventListener = window.removeEventListener;
window.removeEventListener = vi.fn((event: string, fn, options) => {
expect(event).toBe('beforeunload');
return oldRemoveEventListener(event, fn, options);
});
const doc = new Doc();
const provider = createIndexedDBProvider('1', doc);
const map = doc.getMap('map');
map.set('1', 1);
provider.connect();
await provider.whenSynced;
expect(window.addEventListener).toBeCalledTimes(1);
expect(window.removeEventListener).toBeCalledTimes(1);
window.addEventListener = oldAddEventListener;
window.removeEventListener = oldRemoveEventListener;
});
});
describe('milestone', () => {

View File

@@ -21,6 +21,25 @@ const snapshotOrigin = Symbol('snapshot-origin');
let mergeCount = 500;
/**
* @internal
*/
const saveAlert = (event: BeforeUnloadEvent) => {
event.preventDefault();
return (event.returnValue =
'Data is not saved. Are you sure you want to leave?');
};
export const writeOperation = async (op: Promise<unknown>) => {
window.addEventListener('beforeunload', saveAlert, {
capture: true,
});
await op;
window.removeEventListener('beforeunload', saveAlert, {
capture: true,
});
};
export function setMergeCount(count: number) {
mergeCount = count;
}
@@ -169,9 +188,9 @@ export const createIndexedDBProvider = (
},
],
};
await store.put(data);
await writeOperation(store.put(data));
} else {
await store.put(data);
await writeOperation(store.put(data));
}
}
@@ -205,15 +224,17 @@ export const createIndexedDBProvider = (
return;
}
if (!data) {
await db.put('workspace', {
id,
updates: [
{
timestamp: Date.now(),
update: encodeStateAsUpdate(doc),
},
],
});
await writeOperation(
db.put('workspace', {
id,
updates: [
{
timestamp: Date.now(),
update: encodeStateAsUpdate(doc),
},
],
})
);
} else {
const updates = data.updates.map(({ update }) => update);
const fakeDoc = new Doc();
@@ -226,16 +247,18 @@ export const createIndexedDBProvider = (
encodeStateAsUpdate(doc),
encodeStateAsUpdate(fakeDoc)
);
await store.put({
...data,
updates: [
...data.updates,
{
timestamp: Date.now(),
update: newUpdate,
},
],
});
await writeOperation(
store.put({
...data,
updates: [
...data.updates,
{
timestamp: Date.now(),
update: newUpdate,
},
],
})
);
doc.transact(() => {
updates.forEach(update => {
applyUpdate(doc, update);