diff --git a/app/src/database/index.ts b/app/src/database/index.ts index 3359997..65e1cc8 100644 --- a/app/src/database/index.ts +++ b/app/src/database/index.ts @@ -1,5 +1,5 @@ import { deleteDB, openDB } from "idb"; -import { Group, Schema } from "./schema"; +import { Group, Message, Schema } from "./schema"; const NAME = "meal"; export const openDatabase = openDB(NAME, 1, { @@ -49,26 +49,25 @@ export async function getGroups(): Promise { return (await store.getAll()) as Group[]; } -export async function getGroup(groupId: string): Promise { - const database = await openDatabase; - const transaction = database.transaction("groups", "readonly"); - const store = transaction.objectStore("groups"); - return (await store.get(groupId)) as Group; -} - export async function* streamGroups() { const database = await openDatabase; const transaction = database.transaction("groups", "readonly"); for await (const cursor of transaction.store) { - yield cursor.value as Group; + yield cursor.value; } } -export async function updateGroup(group: Group) { +export async function pushMessage(groupId: string, message: Message) { const database = await openDatabase; const transaction = database.transaction("groups", "readwrite"); const store = transaction.objectStore("groups"); - store.put(group); + const group = await store.get(groupId); + if (group === undefined) throw new Error("Group not found"); + + group.messages.push(message); + + await store.put(group); + return group; } export async function insertGroup(group: Group) { diff --git a/app/src/database/schema.d.ts b/app/src/database/schema.d.ts index 99bb3c6..c19181a 100644 --- a/app/src/database/schema.d.ts +++ b/app/src/database/schema.d.ts @@ -48,5 +48,8 @@ interface Schema extends DBSchema { isOnboarded: boolean; }; - groups: Group; + groups: { + value: Group; + key: string; + }; } diff --git a/app/src/routes/chat.tsx b/app/src/routes/chat.tsx index 7725fca..b4f3b01 100644 --- a/app/src/routes/chat.tsx +++ b/app/src/routes/chat.tsx @@ -30,9 +30,13 @@ export default function Chat() { ).value; event.currentTarget.reset(); + const currentGroup = group(); + if (currentGroup === undefined) throw new Error("Expected group"); + const handle = await setupCrackle; await handle.sendMessage({ + friendId: currentGroup.friend.id, groupId, sentAt: new Date(), text, diff --git a/app/src/service-worker/serviceWorker.ts b/app/src/service-worker/serviceWorker.ts index b158194..cef4633 100644 --- a/app/src/service-worker/serviceWorker.ts +++ b/app/src/service-worker/serviceWorker.ts @@ -6,10 +6,9 @@ import { broadcastMessage } from "../broadcast"; import { deleteDatabase, getConfiguration, - getGroup, insertGroup, openDatabase, - updateGroup, + pushMessage, } from "../database"; import { messagesUrl } from "../messagesUrl"; @@ -138,6 +137,7 @@ function assertNotShared( } type SendMessageRequest = { + friendId: string; groupId: string; sentAt: Date; text: string; @@ -229,31 +229,29 @@ const handler = { }, async sendMessage(request: SendMessageRequest) { - const group = await getGroup(request.groupId); - if (group === undefined) throw new Error("Group not found"); const message: OutgoingMessage = { type: "outgoing", sentAt: request.sentAt, text: request.text, }; - group.messages.push(message); - //TODO update group in transaction to avoid race conditions - const groupUpdate = updateGroup(group); broadcastMessage({ type: "Message added", - groupId: group.id, + groupId: request.groupId, message, }); + // Storing the message should happen even if sending fails as that can be retried + const storeMessage = pushMessage(request.groupId, message); + const client = await getClient; - const body = client.send_message(group.id, { + const body = client.send_message(request.groupId, { sent_at: request.sentAt.toISOString(), text: request.text, }); assertNotShared(body); - await Promise.all([postMessage(group.friend.id, body), groupUpdate]); + await Promise.all([postMessage(request.friendId, body), storeMessage]); }, async wipe() { @@ -301,17 +299,12 @@ const handler = { text: message.content.text, }; - const group = await getGroup(message.group_id); - if (group === undefined) - //TODO are we able to reconstruct the group? - throw new Error("Got message for group that does not exist"); + await pushMessage(message.group_id, messageEntry); - // Assume it is sorted by time - group.messages.push(messageEntry); - await updateGroup(group); + // Need to store message before showing it broadcastMessage({ type: "Message added", - groupId: group.id, + groupId: message.group_id, message: messageEntry, }); }