import { createContext, createEffect, createSignal, useContext, } from "solid-js"; import type { ParentProps } from "solid-js"; import { QueryClient, QueryClientProvider } from "@tanstack/solid-query"; import type { RawMessage, RawMessages } from "./values"; import { useSearchParams } from "@solidjs/router"; import { useCrypto } from "@tensamin/core-crypto/context"; import { useUser } from "@tensamin/core-user/context"; import { useStorage } from "@tensamin/core-storage/context"; export const context = createContext(); const queryClient = new QueryClient(); export default function Provider( props: ParentProps & { getMessages: ( amount: number, offset: number, user_id: number, ) => Promise; }, ) { const { get_shared_secret } = useCrypto(); const { get } = useUser(); const { load } = useStorage(); const [liveMessages, setLiveMessages] = createSignal([]); const [currentSharedSecret, setCurrentSharedSecret] = createSignal(""); const [searchParams] = useSearchParams(); const userId = () => Number(searchParams.id ?? 0); createEffect(() => { const recipientId = userId(); if (!recipientId) { setCurrentSharedSecret(""); return; } get(recipientId).then(async (recipientData) => { const ownId = await load("user_id"); const privateKey = await load("private_key"); const ownData = await get(ownId); const sharedSecret = await get_shared_secret( privateKey, ownData.public_key, recipientData.public_key, ); setCurrentSharedSecret(sharedSecret); }); }); async function customGetMessages(amount: number, offset: number) { const messages = await props.getMessages(amount, offset, userId()); const sorted = [...messages].sort((a, b) => a.timestamp - b.timestamp); return sorted; } function addLiveMessage(message: RawMessage) { setLiveMessages((prev) => [...prev, message]); } function clearLiveMessages() { setLiveMessages([]); } return ( {props.children} ); } type contextType = { getMessages: (amount: number, offset: number) => Promise; liveMessages: () => RawMessages; addLiveMessage: (message: RawMessage) => void; clearLiveMessages: () => void; sharedSecret: () => string; userId: () => number; }; export function useChat(): contextType { const ctx = useContext(context); if (!ctx) { throw new Error("useChat must be used within a ChatProvider"); } return ctx; }