fix: only use hex string when send message via compose dialog

This commit is contained in:
reya
2024-08-08 09:02:43 +07:00
parent 6d93c1e4d2
commit c2ebf8e22c
4 changed files with 61 additions and 39 deletions

View File

@@ -79,11 +79,6 @@ export function getReceivers(tags: string[][]) {
return p; return p;
} }
export function getChatId(pubkey: string, tags: string[][]) {
const id = [pubkey, tags.map((tag) => tag[0] === "p" && tag[1])].join("-");
return id;
}
export function groupEventByDate(events: NostrEvent[]) { export function groupEventByDate(events: NostrEvent[]) {
const groups = Object.groupBy(events, (event) => { const groups = Object.groupBy(events, (event) => {
return dayjs.unix(event.created_at).startOf("day").format("MMM DD, YYYY"); return dayjs.unix(event.created_at).startOf("day").format("MMM DD, YYYY");

View File

@@ -26,7 +26,7 @@ export function UserAvatar({ className }: { className?: string }) {
<> <>
{user.profile?.picture ? ( {user.profile?.picture ? (
<Avatar.Image <Avatar.Image
src={`https://wsrv.nl/?url=${user.profile?.picture}&w=200&h=200`} src={`https://wsrv.nl/?url=${user.profile?.picture}&w=200&h=200&default=1`}
alt={user.pubkey} alt={user.pubkey}
loading="lazy" loading="lazy"
decoding="async" decoding="async"

View File

@@ -157,7 +157,7 @@ function List() {
await queryClient.setQueryData( await queryClient.setQueryData(
["chats", id], ["chats", id],
(prevEvents: NostrEvent[]) => { (prevEvents: NostrEvent[]) => {
if (!prevEvents) return prevEvents; if (!prevEvents) return [event];
return [event, ...prevEvents]; return [event, ...prevEvents];
}, },
); );

View File

@@ -19,8 +19,9 @@ import { Menu, MenuItem, PredefinedMenuItem } from "@tauri-apps/api/menu";
import { readText } from "@tauri-apps/plugin-clipboard-manager"; import { readText } from "@tauri-apps/plugin-clipboard-manager";
import { message } from "@tauri-apps/plugin-dialog"; import { message } from "@tauri-apps/plugin-dialog";
import { open } from "@tauri-apps/plugin-shell"; import { open } from "@tauri-apps/plugin-shell";
import type { NostrEvent } from "nostr-tools"; import { type NostrEvent, nip19 } from "nostr-tools";
import { useCallback, useEffect, useState, useTransition } from "react"; import { useCallback, useEffect, useRef, useState, useTransition } from "react";
import { Virtualizer } from "virtua";
type EventPayload = { type EventPayload = {
event: string; event: string;
@@ -273,6 +274,7 @@ function Compose() {
}); });
const navigate = Route.useNavigate(); const navigate = Route.useNavigate();
const scrollRef = useRef<HTMLDivElement>(null);
const pasteFromClipboard = async () => { const pasteFromClipboard = async () => {
const val = await readText(); const val = await readText();
@@ -283,13 +285,33 @@ function Compose() {
startTransition(async () => { startTransition(async () => {
if (!newMessage.length) return; if (!newMessage.length) return;
if (!target.length) return; if (!target.length) return;
if (!target.startsWith("npub1")) {
await message("You must enter the public key as npub", {
title: "Send Message",
kind: "error",
});
return;
}
const decoded = nip19.decode(target);
let id: string;
if (decoded.type !== "npub") {
await message("You must enter the public key as npub", {
title: "Send Message",
kind: "error",
});
return;
} else {
id = decoded.data;
}
// Connect to user's inbox relays // Connect to user's inbox relays
const connect = await commands.connectInboxRelays(target, false); const connect = await commands.connectInboxRelays(target, false);
// Send message // Send message
if (connect.status === "ok") { if (connect.status === "ok") {
const res = await commands.sendMessage(target, newMessage); const res = await commands.sendMessage(id, newMessage);
if (res.status === "ok") { if (res.status === "ok") {
setTarget(""); setTarget("");
@@ -298,7 +320,7 @@ function Compose() {
navigate({ navigate({
to: "/$account/chats/$id", to: "/$account/chats/$id",
params: { account, id: target }, params: { account, id },
}); });
} else { } else {
await message(res.error, { title: "Send Message", kind: "error" }); await message(res.error, { title: "Send Message", kind: "error" });
@@ -343,7 +365,7 @@ function Compose() {
placeholder="npub1..." placeholder="npub1..."
value={target} value={target}
onChange={(e) => setTarget(e.target.value)} onChange={(e) => setTarget(e.target.value)}
disabled={isPending || isLoading} disabled={isPending}
className="w-full pr-14 h-9 bg-transparent focus:outline-none placeholder:text-neutral-400 dark:placeholder:text-neutral-600" className="w-full pr-14 h-9 bg-transparent focus:outline-none placeholder:text-neutral-400 dark:placeholder:text-neutral-600"
/> />
<button <button
@@ -361,7 +383,7 @@ function Compose() {
placeholder="hello..." placeholder="hello..."
value={newMessage} value={newMessage}
onChange={(e) => setNewMessage(e.target.value)} onChange={(e) => setNewMessage(e.target.value)}
disabled={isPending || isLoading} disabled={isPending}
className="flex-1 h-9 bg-transparent focus:outline-none placeholder:text-neutral-400 dark:placeholder:text-neutral-600" className="flex-1 h-9 bg-transparent focus:outline-none placeholder:text-neutral-400 dark:placeholder:text-neutral-600"
/> />
<button <button
@@ -383,32 +405,37 @@ function Compose() {
scrollHideDelay={300} scrollHideDelay={300}
className="overflow-hidden flex-1 size-full" className="overflow-hidden flex-1 size-full"
> >
<ScrollArea.Viewport className="relative h-full p-2"> <ScrollArea.Viewport
{isLoading ? ( ref={scrollRef}
<div className="h-[400px] flex items-center justify-center"> className="relative h-full p-2"
<Spinner className="size-4" /> >
</div> <Virtualizer scrollRef={scrollRef} overscan={1}>
) : !contacts?.length ? ( {isLoading ? (
<div className="h-[400px] flex items-center justify-center"> <div className="h-[400px] flex items-center justify-center">
<p className="text-sm">Contact is empty.</p> <Spinner className="size-4" />
</div> </div>
) : ( ) : !contacts?.length ? (
contacts?.map((contact) => ( <div className="h-[400px] flex items-center justify-center">
<button <p className="text-sm">Contact is empty.</p>
key={contact} </div>
type="button" ) : (
onClick={() => setTarget(contact)} contacts?.map((contact) => (
className="block w-full p-2 rounded-lg hover:bg-neutral-100 dark:hover:bg-neutral-800" <button
> key={contact}
<User.Provider pubkey={contact}> type="button"
<User.Root className="flex items-center gap-2"> onClick={() => setTarget(contact)}
<User.Avatar className="size-8 rounded-full" /> className="block w-full p-2 rounded-lg hover:bg-neutral-100 dark:hover:bg-neutral-800"
<User.Name className="text-sm font-medium" /> >
</User.Root> <User.Provider pubkey={contact}>
</User.Provider> <User.Root className="flex items-center gap-2">
</button> <User.Avatar className="size-8 rounded-full" />
)) <User.Name className="text-sm font-medium" />
)} </User.Root>
</User.Provider>
</button>
))
)}
</Virtualizer>
</ScrollArea.Viewport> </ScrollArea.Viewport>
<ScrollArea.Scrollbar <ScrollArea.Scrollbar
className="flex select-none touch-none p-0.5 duration-[160ms] ease-out data-[orientation=vertical]:w-2" className="flex select-none touch-none p-0.5 duration-[160ms] ease-out data-[orientation=vertical]:w-2"