diff --git a/packages/chat/src/components/message.tsx b/packages/chat/src/components/message.tsx index 351e76f..fc6fc10 100644 --- a/packages/chat/src/components/message.tsx +++ b/packages/chat/src/components/message.tsx @@ -15,7 +15,7 @@ import { import MessageContextMenu from "./messageContextMenu"; import Media from "./media/media"; import { useStorage } from "@tensamin/storage/context"; -import { requireRelaySuccess, useMTP } from "@tensamin/mtp"; +import { useMTP } from "@tensamin/mtp"; import { getMessage, useChat } from "../context"; import { decryptChatText, encryptChatText } from "@tensamin/crypto/chatSecret"; import { log, toast } from "@tensamin/shared/log"; @@ -42,7 +42,6 @@ function MessageComponent({ user: SelectedUser | null; }) { const actuallyFailed = - Boolean(message.ErrorType) || (message.failed && message.MessageState === "awaiting") || message.decryptionFailed; @@ -66,7 +65,7 @@ function MessageComponent({ // Message states const { load } = useStorage(); - const { send, sendSealedRelay } = useMTP(); + const { send } = useMTP(); const [ownId, setOwnId] = useState(0); useEffect(() => { load("user_id").then(setOwnId); @@ -74,38 +73,22 @@ function MessageComponent({ const messageStateReadUpdate = useCallback(async () => { const readConfirmations = await load("settings.read_confirmations"); - if (!user?.UserId || !message.RelayMessageId || ownId === 0) return; - const [ownIota, peerIota] = await Promise.all([ - send("GetIotaData", { UserId: ownId }), - send("GetIotaData", { UserId: user.UserId }), - ]); - if (ownIota.type !== "GetIotaData" || peerIota.type !== "GetIotaData") { - throw new Error("Could not resolve an Iota for this receipt"); + if (readConfirmations) { + if (!user?.UserId) return; + + await send("MessageState", { + ChatPartnerId: user?.UserId, + SendTime: message.SendTime, + MessageState: "read", + }); + } else { + await send("MessageState", { + ChatPartnerId: user?.UserId, + SendTime: message.SendTime, + MessageState: "received", + }); } - const response = await sendSealedRelay( - "MessageState", - { - ChatPartnerId: user.UserId, - RelayMessageId: message.RelayMessageId, - EventAt: Date.now(), - MessageState: readConfirmations ? "read" : "received", - ReceiverId: user.UserId, - }, - { - nextHop: { kind: "iota", id: ownIota.data.IotaId }, - finalRecipientId: user.UserId, - metadataRecipients: [ - { value: ownIota.data.PublicKey, encoding: "base64" }, - { value: peerIota.data.PublicKey, encoding: "base64" }, - ], - contentRecipients: [ - { value: ownIota.data.PublicKey, encoding: "base64" }, - { value: peerIota.data.PublicKey, encoding: "base64" }, - ], - }, - ); - requireRelaySuccess(response); - }, [load, message.RelayMessageId, ownId, send, sendSealedRelay, user]); + }, [load, message.SendTime, user?.UserId, send]); useEffect(() => { if (message.SenderId === ownId || ownId === 0) return; diff --git a/packages/chat/src/context.tsx b/packages/chat/src/context.tsx index c4328db..bc9f90c 100644 --- a/packages/chat/src/context.tsx +++ b/packages/chat/src/context.tsx @@ -69,14 +69,6 @@ type MessageEdit = Partial< > >; -const messageStateRank: Record = { - awaiting: 0, - sending: 0, - sent: 1, - received: 2, - read: 3, -}; - function updateMessagesBySendTime( messages: T[], sendTime: number, @@ -89,13 +81,6 @@ function updateMessagesBySendTime( return item; } - if ( - edit.MessageState !== undefined && - messageStateRank[edit.MessageState] < messageStateRank[item.MessageState] - ) { - return item; - } - const entries = Object.entries(edit) as Array< [keyof MessageEdit, MessageEdit[keyof MessageEdit]] >; @@ -998,7 +983,9 @@ export default function Provider({ children }: { children: ReactNode }) { ); return; } - editMessage(data.SendTime, { MessageState: data.MessageState }); + editMessage(data.SendTime, { + MessageState: data.MessageState, + }); }); return () => { unsubscribeEdit(); diff --git a/packages/notifications/src/context.tsx b/packages/notifications/src/context.tsx index eef4e8b..ca311b0 100644 --- a/packages/notifications/src/context.tsx +++ b/packages/notifications/src/context.tsx @@ -29,7 +29,7 @@ async function requestNotificationPermission() { } export default function Provider(props: { children: React.ReactNode }) { - const { subscribe } = useMTP(); + const { subscribe, send } = useMTP(); const { load } = useStorage(); const { get } = useUser(); const { addLiveMessage, chatSecret, getChatSecret, userId } = useChat(); @@ -79,6 +79,11 @@ export default function Provider(props: { children: React.ReactNode }) { // todo: add notification symbol to conversation cards (incl. message start) moveUserIdToTop(data.SenderId); + if (await load("settings.receive_confirmations")) { + void send("MessageState", { + MessageState: "received", + }); + } } const user = await get(data.SenderId, [ @@ -175,6 +180,7 @@ export default function Provider(props: { children: React.ReactNode }) { load, location.pathname, navigate, + send, moveUserIdToTop, subscribe, getChatSecret, diff --git a/packages/shared/src/data.ts b/packages/shared/src/data.ts index e7d2c33..4a64c80 100644 --- a/packages/shared/src/data.ts +++ b/packages/shared/src/data.ts @@ -70,7 +70,6 @@ const callSecretEnvelopeRequest = z.object({ export const Reaction = z.object({ Reaction: z.string(), SenderId: z.number(), - RelayMessageId: z.string().optional(), }); export const Message = z.object({ @@ -83,8 +82,6 @@ export const Message = z.object({ Avatar: z.boolean().optional(), Display: z.boolean().optional(), ReplyId: z.number().optional(), - UpdatedAt: z.number().optional(), - ErrorType: z.string().optional(), MessageState: z .enum(["read", "received", "sent", "sending", "awaiting"]) // awaiting for 'internal' use .default("received"), @@ -110,7 +107,6 @@ const authPayload = z.object({ .array( z.object({ LastMessageAt: z.number().default(0), - CreatedAt: z.number().optional(), UserId: z.number(), LastMessage: z .object({ @@ -401,12 +397,17 @@ export const mtp = { response: z.object({}), }, MessageState: { - request: z.object({ - ChatPartnerId: z.number(), - RelayMessageId: z.string(), - EventAt: z.number(), - MessageState: z.enum(["received", "read"]), - }), + request: z + .object({ + ChatPartnerId: z.number(), + SendTime: z.number(), + MessageState: Message.shape.MessageState, + }) + .or( + z.object({ + MessageState: Message.shape.MessageState, + }), + ), response: z.object({ ChatPartnerId: z.number(), MessageState: Message.shape.MessageState,