(feat): finish chat crypto migration
(wip): prep for full ECDH repo migration
This commit is contained in:
parent
ecca5241bc
commit
2cd326d0b1
10 changed files with 195 additions and 339 deletions
|
|
@ -1,16 +1,16 @@
|
|||
import { useCrypto } from "@tensamin/crypto/context";
|
||||
import { useStorage } from "@tensamin/storage/context";
|
||||
import { useUser } from "@tensamin/user/context";
|
||||
import { useChat } from "@tensamin/chat/context";
|
||||
import { useMTP } from "@tensamin/mtp";
|
||||
import { createContext, useEffect, useContext } from "react";
|
||||
import z from "zod";
|
||||
import { toast as sonnerToast } from "sonner";
|
||||
import { Message as MessageSchema } from "@tensamin/shared/data";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@tensamin/ui";
|
||||
import { isTauri } from "@tauri-apps/api/core";
|
||||
import { useSession } from "@tensamin/storage/session";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { decryptChatText } from "@tensamin/crypto/chatSecret";
|
||||
import { log } from "@tensamin/shared/log";
|
||||
import { type RawMessage } from "@tensamin/chat/values";
|
||||
|
||||
export const context = createContext<contextType | undefined>(undefined);
|
||||
|
||||
|
|
@ -27,108 +27,113 @@ export default function Provider(props: { children: React.ReactNode }) {
|
|||
const { subscribePush, send } = useMTP();
|
||||
const { load } = useStorage();
|
||||
const { get } = useUser();
|
||||
const { decryptText, getSharedSecret } = useCrypto();
|
||||
const { addLiveMessage, userId } = useChat();
|
||||
const { addLiveMessage, getChatSecret, userId } = useChat();
|
||||
const { moveUserIdToTop } = useSession();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
return subscribePush(async (ttpMessage) => {
|
||||
if (ttpMessage.type === "MessageLive") {
|
||||
const { message, SenderId } = ttpMessage.data as {
|
||||
message: z.infer<typeof MessageSchema>;
|
||||
SenderId: number;
|
||||
return subscribePush(async (message) => {
|
||||
if (message.type === "MessageLive") {
|
||||
const data = message.data as {
|
||||
Message?: RawMessage;
|
||||
SenderId?: number;
|
||||
};
|
||||
|
||||
const user = await get(SenderId);
|
||||
if (!data.SenderId) return;
|
||||
|
||||
const decryptedContent = await decryptText(
|
||||
await getSharedSecret(
|
||||
await load("mtp_keyring"),
|
||||
await get(await load("user_id")).then((data) => data.PublicKey),
|
||||
user.PublicKey,
|
||||
),
|
||||
message.Content,
|
||||
);
|
||||
const chatSecret = await getChatSecret(data.SenderId);
|
||||
|
||||
// Update message state
|
||||
if (userId === SenderId) {
|
||||
addLiveMessage({
|
||||
...message,
|
||||
Content: decryptedContent,
|
||||
SentBySelf: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!data.Message || !chatSecret) return;
|
||||
const user = await get(data.SenderId);
|
||||
|
||||
// todo: add notification symbol to conversation cards (incl. message start)
|
||||
|
||||
moveUserIdToTop(SenderId);
|
||||
|
||||
if (await load("settings.receive_confirmations")) {
|
||||
void send(
|
||||
"MessageState",
|
||||
{
|
||||
MessageState: "received",
|
||||
},
|
||||
{
|
||||
id: ttpMessage.id,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (isTauri()) {
|
||||
console.log("weewoo");
|
||||
} else {
|
||||
const hasPermissions = await requestNotificationPermission();
|
||||
|
||||
if (hasPermissions) {
|
||||
const notification = new Notification(user.Display, {
|
||||
body: decryptedContent,
|
||||
icon: user.Avatar || user.Display.slice(0, 2).toUpperCase(),
|
||||
badge: user.Avatar || user.Display.slice(0, 2).toUpperCase(),
|
||||
tag: `message-${user.UserId}`,
|
||||
silent: true,
|
||||
void decryptChatText(chatSecret, data.Message.Content)
|
||||
.catch((err) => {
|
||||
log(1, "chat", "red", "Failed to decrypt live message", err, {
|
||||
SendTime: data.Message?.SendTime,
|
||||
});
|
||||
return null;
|
||||
})
|
||||
.then(async (content) => {
|
||||
if (!data.Message || !content || !data.SenderId) return;
|
||||
|
||||
notification.onclick = () => {
|
||||
window.focus();
|
||||
navigate({
|
||||
to: `/chat?id=${user.UserId}`,
|
||||
if (userId === data.SenderId) {
|
||||
addLiveMessage({
|
||||
...data.Message,
|
||||
Content: content ?? "Failed to decrypt message",
|
||||
decryptionFailed: content === null,
|
||||
SentBySelf: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
notification.close();
|
||||
};
|
||||
} else {
|
||||
sonnerToast(user.Display, {
|
||||
classNames: {
|
||||
content: "pl-4",
|
||||
},
|
||||
description: decryptedContent,
|
||||
icon: (
|
||||
<Avatar>
|
||||
<AvatarImage src={user.Avatar} />
|
||||
<AvatarFallback>
|
||||
{user.Display.slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
// todo: add notification symbol to conversation cards (incl. message start)
|
||||
moveUserIdToTop(data.SenderId);
|
||||
|
||||
if (await load("settings.receive_confirmations")) {
|
||||
void send(
|
||||
"MessageState",
|
||||
{
|
||||
MessageState: "received",
|
||||
},
|
||||
{
|
||||
id: data.Message.SendTime,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (isTauri()) {
|
||||
console.log("weewoo");
|
||||
} else {
|
||||
const hasPermissions = await requestNotificationPermission();
|
||||
|
||||
if (hasPermissions) {
|
||||
const notification = new Notification(user.Display, {
|
||||
body: content,
|
||||
icon: user.Avatar || user.Display.slice(0, 2).toUpperCase(),
|
||||
badge: user.Avatar || user.Display.slice(0, 2).toUpperCase(),
|
||||
tag: `message-${user.UserId}`,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
notification.onclick = () => {
|
||||
window.focus();
|
||||
navigate({
|
||||
to: `/chat?id=${user.UserId}`,
|
||||
});
|
||||
|
||||
notification.close();
|
||||
};
|
||||
} else {
|
||||
sonnerToast(user.Display, {
|
||||
classNames: {
|
||||
content: "pl-4",
|
||||
},
|
||||
description: content,
|
||||
icon: (
|
||||
<Avatar>
|
||||
<AvatarImage src={user.Avatar} />
|
||||
<AvatarFallback>
|
||||
{user.Display.slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
}, [
|
||||
subscribePush,
|
||||
decryptText,
|
||||
getSharedSecret,
|
||||
load,
|
||||
get,
|
||||
addLiveMessage,
|
||||
userId,
|
||||
moveUserIdToTop,
|
||||
send,
|
||||
get,
|
||||
load,
|
||||
navigate,
|
||||
send,
|
||||
moveUserIdToTop,
|
||||
subscribePush,
|
||||
getChatSecret,
|
||||
userId,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
Loading…
Reference in a new issue