import { Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, Input, Button, useIsMobile, } from "@methanium/ui"; import z from "zod"; import { MTPProtocolError } from "mtp"; import { RelayRejectedError, requireRelaySuccess, useMTP } from "@tensamin/mtp"; import { log } from "@tensamin/shared/log"; import { useState } from "react"; import { Loader2 } from "lucide-react"; import { isTauri } from "@tauri-apps/api/core"; import { useSession } from "@tensamin/identity/session"; import { useStorage } from "@tensamin/storage/context"; import { ShieldAlert } from "lucide-react"; import { useUser } from "@tensamin/identity/context"; // The page export default function Page() { const isMobile = useIsMobile(); const { secureStorage } = useStorage(); return (
{secureStorage && !secureStorage.secure && (

Secure storage is unavailable

{secureStorage.reason}

Your keyring and cached messages will get saved in regular storage.

)}
); } // Add Conversation Button Component function AddConversationButton() { const { send, sendSealedRelay } = useMTP(); const { contacts, insertContact } = useSession(); const { load } = useStorage(); const { getIota } = useUser(); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); const [error, setError] = useState(null); async function submit(username: string | null) { if (loading) return; setError(null); // username check const schema = z .string() .regex(/^[a-z0-9]+$/, "Username must use lowercase letters and numbers") .max(15, "Username is too long"); const result = schema.safeParse(username?.toLowerCase().trim()); if (!result.success) { setError(result.error.issues[0].message); return; } let user; try { user = await send("GetUserData", { Username: result.data }); } catch (error) { if (error instanceof MTPProtocolError && error.type === "ErrorNotFound") { setError("User not found"); } else if (error instanceof MTPProtocolError) { setError(`User lookup failed: ${error.type}`); } else { setError("User lookup failed: connection error"); } return; } if (user.type === "ErrorNotFound") { setError("User not found"); return; } if (user.type !== "GetUserData") { setError(`User lookup failed: ${user.type}`); return; } // alrady added check if (contacts.some((contact) => contact.UserId === user.data.UserId)) { setError("Conversation already exists"); return; } // add the conv const timeout = setTimeout(() => setLoading(true), 500); try { const userId = await load("user_id"); const iota = await getIota(userId); const response = await sendSealedRelay( "AddConversation", { ChatPartnerId: user.data.UserId }, { nextHop: { kind: "iota", id: iota.IotaId }, finalRecipientId: userId, metadataRecipients: [{ value: iota.PublicKey, encoding: "base64" }], contentRecipients: [{ value: iota.PublicKey, encoding: "base64" }], }, ); requireRelaySuccess(response); insertContact(user.data.UserId); setOpen(false); } catch (error) { if (error instanceof RelayRejectedError) { setError( `Could not route the request to your Iota: ${error.responseType}`, ); } else { log(1, "mtp", "red", "Add conversation failed", error); const detail = error instanceof Error ? error.message : "unknown error"; setError(`Add conversation failed: ${detail}`); } } finally { clearTimeout(timeout); setLoading(false); } } return ( { if (value) { setError(null); } setOpen(value); }} > ( )} /> New Conversation Add a new conversation. Just enter the username of the person you want to add as a conversation.
{ event.preventDefault(); const form = new FormData(event.currentTarget); const username = form.get("username") as string | null; submit(username); }} >
{error && (

{error}

)} ( )} />
); }