fix: move offline screenshots out of localStorage (Closes #473)
This commit is contained in:
1 parent
2b2e2cceb4
commit
8b7c56161c
5 files changed
+208
-19
No files matched your search
@@ -65,13 +65,18 @@ function createIssueSyncStore({ transaction, indexedDB = globalThis.indexedDB, n
|
||||
if (current.recordType === 'receipt-preference') continue;
|
||||
const currentLane = current.outboxLane || 'issue';
|
||||
if (currentLane !== outboxLane) continue;
|
||||
const replacement = incoming.get(current.id);
|
||||
let replacement = incoming.get(current.id);
|
||||
if (!replacement) {
|
||||
if (current.status !== 'sending' || Number(current.claimUntil) <= Number(now())) {
|
||||
await records.delete(current.id);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (current.operationId === replacement.operationId && current.attachment?.data &&
|
||||
replacement.attachment?.stored && !replacement.attachment.data) {
|
||||
replacement = { ...replacement, attachment: current.attachment };
|
||||
incoming.set(current.id, replacement);
|
||||
}
|
||||
if ((current.status === 'sending' && Number(current.claimUntil) > Number(now())) ||
|
||||
(current.status === 'attention' && replacement.status === 'attention') ||
|
||||
current.status === 'sent') {
|
||||
@@ -141,8 +146,10 @@ function createIssueSyncStore({ transaction, indexedDB = globalThis.indexedDB, n
|
||||
if (current && ((current.status === 'sending' && Number(current.claimUntil) > Number(now())) ||
|
||||
(current.status === 'attention' && item.status === 'attention') ||
|
||||
current.status === 'sent')) return current;
|
||||
const preservedAttachment = current?.attachment?.data && item?.attachment?.stored && !item.attachment.data
|
||||
? { attachment: current.attachment } : {};
|
||||
const next = current && current.operationId === item.operationId ? {
|
||||
...item,
|
||||
...item, ...preservedAttachment,
|
||||
...(current.deliveredIssue ? { deliveredIssue: current.deliveredIssue } : {}),
|
||||
...(current.attachmentMarkdown ? { attachmentMarkdown: current.attachmentMarkdown } : {}),
|
||||
} : { ...item };
|
||||
|
||||
+54
-16
@@ -9,7 +9,9 @@ function createIssueOutbox({ storage, fetchJson, coordinator, backgroundSync, ge
|
||||
const contentType = String(value?.contentType || '');
|
||||
const filename = String(value?.filename || '').slice(0, 255);
|
||||
const data = String(value?.data || '');
|
||||
if (!filename || !['image/png', 'image/jpeg', 'image/webp'].includes(contentType) || !data) return undefined;
|
||||
if (!filename || !['image/png', 'image/jpeg', 'image/webp'].includes(contentType)) return undefined;
|
||||
if (!data && value?.stored === true) return { filename, contentType, stored: true };
|
||||
if (!data) return undefined;
|
||||
return { filename, contentType, data };
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@ function createIssueOutbox({ storage, fetchJson, coordinator, backgroundSync, ge
|
||||
}
|
||||
}
|
||||
|
||||
function enqueue(draft, mirror = true) {
|
||||
function prepareItem(draft) {
|
||||
const ownerLogin = String(getOwnerLogin() || '').trim();
|
||||
if (!ownerLogin) throw new Error('Confirm your Gitea account before queueing an issue.');
|
||||
const items = read();
|
||||
@@ -55,28 +57,52 @@ function createIssueOutbox({ storage, fetchJson, coordinator, backgroundSync, ge
|
||||
item.milestoneId = Number(draft.milestoneId);
|
||||
}
|
||||
if (/^\d{4}-\d{2}-\d{2}$/.test(String(draft?.dueDate || ''))) item.dueDate = String(draft.dueDate);
|
||||
return item;
|
||||
}
|
||||
|
||||
function localIndexItem(item) {
|
||||
if (!item?.attachment?.data) return item;
|
||||
return {
|
||||
...item,
|
||||
attachment: {
|
||||
filename: item.attachment.filename,
|
||||
contentType: item.attachment.contentType,
|
||||
stored: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function enqueue(draft, mirror = true) {
|
||||
const items = read();
|
||||
const item = prepareItem(draft);
|
||||
items.push(item);
|
||||
write(items, mirror);
|
||||
return item;
|
||||
}
|
||||
|
||||
async function enqueueDurably(draft) {
|
||||
const item = enqueue(draft, false);
|
||||
if (!backgroundSync?.reconcile || !backgroundSync?.requestSync) {
|
||||
const item = enqueue(draft, false);
|
||||
return { item, background: false, durability: 'foreground-only' };
|
||||
}
|
||||
const item = prepareItem(draft);
|
||||
const current = read();
|
||||
try {
|
||||
await backgroundSync.reconcile(read());
|
||||
await backgroundSync.reconcile([...current, item]);
|
||||
const localItem = localIndexItem(item);
|
||||
write([...current, item].map(localIndexItem), false);
|
||||
await backgroundSync.requestSync();
|
||||
return { item, background: true, durability: 'background' };
|
||||
return { item: localItem, background: true, durability: 'background' };
|
||||
} catch (error) {
|
||||
return { item, background: false, durability: 'foreground-only', error };
|
||||
const persisted = read().find(candidate => candidate.id === item.id);
|
||||
if (!persisted) throw error;
|
||||
return { item: persisted, background: false, durability: 'foreground-only', error };
|
||||
}
|
||||
}
|
||||
|
||||
function update(id, draft, mirror = true) {
|
||||
function prepareUpdate(id, draft) {
|
||||
let updated = null;
|
||||
write(read().map(item => {
|
||||
const items = read().map(item => {
|
||||
if (item.id !== id) return item;
|
||||
const nextRepository = String(draft?.repository || '');
|
||||
const nextTitle = String(draft?.title || '');
|
||||
@@ -109,21 +135,33 @@ function createIssueOutbox({ storage, fetchJson, coordinator, backgroundSync, ge
|
||||
delete updated.error;
|
||||
delete updated.deliveryState;
|
||||
return updated;
|
||||
}), mirror);
|
||||
});
|
||||
return { items, updated };
|
||||
}
|
||||
|
||||
function update(id, draft, mirror = true) {
|
||||
const { items, updated } = prepareUpdate(id, draft);
|
||||
write(items, mirror);
|
||||
return updated;
|
||||
}
|
||||
|
||||
async function updateDurably(id, draft) {
|
||||
const item = update(id, draft, false);
|
||||
if (!item || !backgroundSync?.reconcile || !backgroundSync?.requestSync) {
|
||||
if (!backgroundSync?.reconcile || !backgroundSync?.requestSync) {
|
||||
const item = update(id, draft, false);
|
||||
return { item, background: false, durability: 'foreground-only' };
|
||||
}
|
||||
const { items, updated: item } = prepareUpdate(id, draft);
|
||||
if (!item) return { item, background: false, durability: 'foreground-only' };
|
||||
try {
|
||||
await backgroundSync.reconcile(read());
|
||||
await backgroundSync.reconcile(items);
|
||||
const localItems = items.map(localIndexItem);
|
||||
write(localItems, false);
|
||||
await backgroundSync.requestSync();
|
||||
return { item, background: true, durability: 'background' };
|
||||
return { item: localIndexItem(item), background: true, durability: 'background' };
|
||||
} catch (error) {
|
||||
return { item, background: false, durability: 'foreground-only', error };
|
||||
const persisted = read().find(candidate => candidate.id === id);
|
||||
if (!persisted || persisted.operationId !== item.operationId) throw error;
|
||||
return { item: persisted, background: false, durability: 'foreground-only', error };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,10 +356,10 @@ function createIssueOutbox({ storage, fetchJson, coordinator, backgroundSync, ge
|
||||
return [];
|
||||
}
|
||||
if (background?.status === 'attention') return [{
|
||||
...item, ...deliveryStage, status: 'attention', error: String(background.error || 'Issue needs attention').slice(0, 240),
|
||||
...localIndexItem(item), ...deliveryStage, status: 'attention', error: String(background.error || 'Issue needs attention').slice(0, 240),
|
||||
...(background.deliveryState ? { deliveryState: background.deliveryState } : {}),
|
||||
}];
|
||||
return [{ ...item, ...deliveryStage }];
|
||||
return [{ ...localIndexItem(item), ...deliveryStage }];
|
||||
});
|
||||
write(items);
|
||||
return items;
|
||||
|
||||
Reference in new issue
Block a user