diff --git a/packages/chat/src/components/message.tsx b/packages/chat/src/components/message.tsx
index 997f42f..de819fc 100644
--- a/packages/chat/src/components/message.tsx
+++ b/packages/chat/src/components/message.tsx
@@ -143,7 +143,7 @@ function MessageComponent({
}, [message.Content]);
// Message editing
- const { chatSecret, editMessage, userId } = useChat();
+ const { chatSecret, editMessage, userId, deleteMessage } = useChat();
const [editing, setEditing] = useState(false);
const [editDraft, setEditDraft] = useState(message.Content);
useEffect(() => {
@@ -283,14 +283,46 @@ function MessageComponent({
)}
{editing ? (
- {
- submitEditMessage(editDraft);
- setEditing(false);
- }}
- />
+
+
{
+ submitEditMessage(editDraft);
+ setEditing(false);
+ }}
+ />
+
+
+
+
+
) : isValidURL ? (
) : (
diff --git a/packages/chat/src/context.tsx b/packages/chat/src/context.tsx
index af0226f..384f3c6 100644
--- a/packages/chat/src/context.tsx
+++ b/packages/chat/src/context.tsx
@@ -436,6 +436,65 @@ export default function Provider({ children }: { children: ReactNode }) {
[currentChatSecret, userIdValue],
);
+ const deleteMessage = useCallback(
+ async (sendTime: number) => {
+ try {
+ const response = await send("MessageDelete", {
+ ChatPartnerId: userIdValue,
+ SendTime: sendTime,
+ });
+
+ assertProtocolSuccess("MessageDelete", response);
+
+ setLiveMessagesState((prev) =>
+ prev.filter((message) => message.SendTime !== sendTime),
+ );
+
+ const queryKey = [
+ "chat-messages",
+ String(userIdValue),
+ currentChatSecret !== null,
+ ] as const;
+
+ queryClient.setQueryData>(
+ queryKey,
+ (current) => {
+ if (!current) {
+ return current;
+ }
+
+ let updated = false;
+
+ const pages = current.pages.map((page) => {
+ const nextPage = page.filter((message) => {
+ const keep = message.SendTime !== sendTime;
+ if (!keep) {
+ updated = true;
+ }
+ return keep;
+ });
+
+ return nextPage;
+ });
+
+ if (!updated) {
+ return current;
+ }
+
+ return {
+ ...current,
+ pages,
+ };
+ },
+ );
+ } catch (err) {
+ log(1, "chat", "red", "Failed to delete message", err);
+ toast("error", "Failed to delete message", String(err));
+ }
+ },
+ [currentChatSecret, send, userIdValue],
+ );
+
const addLiveMessage = useCallback(
(message: RawMessage) => {
const localId =
@@ -578,6 +637,7 @@ export default function Provider({ children }: { children: ReactNode }) {
liveMessages: () => liveMessagesState,
addLiveMessage,
editMessage,
+ deleteMessage,
clearLiveMessages,
chatSecret: currentChatSecret,
userId: userIdValue,
@@ -602,6 +662,7 @@ type contextType = {
setFailed: (failed: boolean) => void;
};
editMessage: (sendTime: number, edit: MessageEdit) => void;
+ deleteMessage: (sendTime: number) => void;
clearLiveMessages: () => void;
chatSecret: Uint8Array | null;
userId: number;
diff --git a/packages/shared/src/data.ts b/packages/shared/src/data.ts
index 5bba99a..e065598 100644
--- a/packages/shared/src/data.ts
+++ b/packages/shared/src/data.ts
@@ -202,6 +202,13 @@ export const mtp = {
PingIota: z.number(),
}),
},
+ MessageDelete: {
+ request: z.object({
+ ChatPartnerId: z.number(),
+ SendTime: z.number(),
+ }),
+ response: z.object({}),
+ },
MessageEditLive: {
request: z.object({}),
response: z.object({