diff --git a/src/db/db.ts b/src/db/db.ts index 0feb8c2..b1adb67 100644 --- a/src/db/db.ts +++ b/src/db/db.ts @@ -224,6 +224,32 @@ export async function addParticipant(data: AddParticipant) { return await db.participants.add({...data, deleted, notes}); } +export async function addParticipants(data: AddParticipant[]) { + const participants = data.map(p => ({ + ...p, + deleted: (p.deleted ? 1 : 0) as IDBBoolean, + notes: p.notes || '', + })); + + // Firefox does not support compound indexes with auto-incrementing keys + // Essentially, when inserting an item with an auto-incrementing key, the + // index does not get updated so the item is not found when searching for it afterwards + // A workaround is to first insert the items and then use put() with the new key which + // forces the index to update. + // https://bugzilla.mozilla.org/show_bug.cgi?id=1404276 + // There was a similar issue which has been fixed: + // https://bugs.chromium.org/p/chromium/issues/detail?id=701972 + if (isFirefox()) { + return await db.transaction('readwrite', db.participants, async () => { + const ids = await db.participants.bulkAdd(participants, {allKeys: true}); + const participantsWithIds = participants.map((p, i) => ({...p, id: ids[i]})); + await db.participants.bulkPut(participantsWithIds); + }); + } else { + return await db.participants.bulkAdd(participants); + } +} + export async function deleteEvent(id: number) { return db.transaction('readwrite', [db.events, db.regforms, db.participants], async () => { const regforms = await db.regforms.where({eventId: id}).toArray(); @@ -272,3 +298,7 @@ export async function updateParticipant(id: number, data: IndicoParticipant) { isPaid, }); } + +function isFirefox() { + return navigator.userAgent.toLowerCase().includes('firefox'); +} diff --git a/src/pages/Events/sync.ts b/src/pages/Events/sync.ts index d816d16..8a2aa4c 100644 --- a/src/pages/Events/sync.ts +++ b/src/pages/Events/sync.ts @@ -1,5 +1,12 @@ import {ErrorModalFunction} from '../../context/ModalContextProvider'; -import db, {Event, type IDBBoolean, Participant, Regform, updateParticipant} from '../../db/db'; +import db, { + Event, + type IDBBoolean, + Participant, + Regform, + updateParticipant, + addParticipants, +} from '../../db/db'; import { FailedResponse, getEvent, @@ -183,11 +190,9 @@ export async function syncParticipants( // participants that we don't have locally, add them const newData = onlyNew.map(p => ({ ...p, - notes: '', - deleted: 0 as IDBBoolean, - regformId: regform.id as number, + regformId: regform.id, })); - await db.participants.bulkAdd(newData); + await addParticipants(newData); // participants that we have both locally and in Indico, just update them const commonData = common.map(([{id}, data]) => ({key: id, changes: data})); await db.participants.bulkUpdate(commonData);