89 lines
3.0 KiB
JavaScript
89 lines
3.0 KiB
JavaScript
(function (root, factory) {
|
|
const createConversationPhotoDrafts = factory();
|
|
if (typeof module === 'object' && module.exports) module.exports = createConversationPhotoDrafts;
|
|
else root.createConversationPhotoDrafts = createConversationPhotoDrafts;
|
|
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
|
'use strict';
|
|
|
|
return function createConversationPhotoDrafts({ store, lanes }) {
|
|
const states = {};
|
|
Object.entries(lanes || {}).forEach(([kind, lane]) => {
|
|
states[kind] = { ...lane, target:null, generation:0, restoring:false, pending:Promise.resolve() };
|
|
});
|
|
|
|
function state(kind) {
|
|
const value = states[kind];
|
|
if (!value) throw new Error('Unknown conversation photo draft lane.');
|
|
return value;
|
|
}
|
|
|
|
async function checkpoint(kind) {
|
|
const current = state(kind);
|
|
if (!current.target || current.restoring) return null;
|
|
const target = { ...current.target };
|
|
const attachments = await current.controller.serialize();
|
|
const save = current.pending.then(() => store.save(target, attachments));
|
|
current.pending = save.catch(() => null);
|
|
try { return await save; }
|
|
catch (error) { current.onError?.(error); throw error; }
|
|
}
|
|
|
|
async function open(kind, target) {
|
|
const current = state(kind);
|
|
const generation = ++current.generation;
|
|
current.target = { ...target };
|
|
await current.pending;
|
|
const attachments = await store.load(target);
|
|
if (generation !== current.generation) return false;
|
|
current.restoring = true;
|
|
try {
|
|
current.controller.clear();
|
|
if (attachments?.length) current.controller.restore(attachments);
|
|
} finally { current.restoring = false; }
|
|
return Boolean(attachments?.length);
|
|
}
|
|
|
|
async function leave(kind) {
|
|
const current = state(kind);
|
|
const generation = current.generation;
|
|
if (!current.target) return true;
|
|
try { await checkpoint(kind); }
|
|
catch (_error) { return false; }
|
|
if (generation === current.generation) {
|
|
current.restoring = true;
|
|
try { current.controller.clear(); }
|
|
finally {
|
|
current.restoring = false;
|
|
current.target = null;
|
|
current.generation += 1;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
async function complete(kind) {
|
|
const current = state(kind);
|
|
if (!current.target) return false;
|
|
const target = { ...current.target };
|
|
await current.pending;
|
|
await store.remove(target);
|
|
current.restoring = true;
|
|
try { current.controller.clear(); }
|
|
finally {
|
|
current.restoring = false;
|
|
current.target = null;
|
|
current.generation += 1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
async function switchTo(kind, target, isCurrent = () => true) {
|
|
if (!await leave(kind) || !isCurrent()) return false;
|
|
return open(kind, target);
|
|
}
|
|
|
|
function hasTarget(kind) { return Boolean(state(kind).target); }
|
|
return { checkpoint, open, switchTo, leave, complete, hasTarget };
|
|
};
|
|
});
|