diff --git a/src/components/ActualSearch.tsx b/src/components/ActualSearch.tsx
index 695b38063..72130494c 100644
--- a/src/components/ActualSearch.tsx
+++ b/src/components/ActualSearch.tsx
@@ -157,6 +157,16 @@ export function ActualSearch(props: { initialValue?: string }) {
async function createContact(contact: ContactFormValues) {
try {
+ // First check if the contact already exists
+ const existingContact = contacts()?.find(
+ (c) => c.npub === contact.npub?.trim().toLowerCase()
+ );
+
+ if (existingContact) {
+ sendToContact(existingContact);
+ return;
+ }
+
const contactId = await state.mutiny_wallet?.create_new_contact(
contact.name,
contact.npub ? contact.npub.trim() : undefined,
diff --git a/src/components/NostrActivity.tsx b/src/components/NostrActivity.tsx
index 3ae4ff1d1..723f42f85 100644
--- a/src/components/NostrActivity.tsx
+++ b/src/components/NostrActivity.tsx
@@ -77,12 +77,25 @@ export function NostrActivity() {
// TODO: can this be part of mutiny wallet?
async function newContactFromHexpub(hexpub: string) {
try {
+ const npub = await MutinyWallet.hexpub_to_npub(hexpub);
+
+ if (!npub) {
+ throw new Error("No npub for that hexpub");
+ }
+
+ const existingContact =
+ await state.mutiny_wallet?.get_contact_for_npub(npub);
+
+ if (existingContact) {
+ navigate(`/chat/${existingContact.id}`);
+ return;
+ }
+
const profile = data.latest?.profiles[hexpub];
if (!profile) return;
const parsed = JSON.parse(profile.content);
const name = parsed.display_name || parsed.name || profile.pubkey;
const image_url = parsed.image || parsed.picture || undefined;
- const npub = await MutinyWallet.hexpub_to_npub(hexpub);
const ln_address = parsed.lud16 || undefined;
const lnurl = parsed.lud06 || undefined;
diff --git a/src/routes/Chat.tsx b/src/routes/Chat.tsx
index 65638d54e..4d1fe3386 100644
--- a/src/routes/Chat.tsx
+++ b/src/routes/Chat.tsx
@@ -26,6 +26,7 @@ import {
BackPop,
Button,
ContactButton,
+ ContactFormValues,
ContactViewer,
HackActivityType,
IActivityItem,
@@ -37,7 +38,7 @@ import {
} from "~/components";
import { ParsedParams, toParsedParams } from "~/logic/waila";
import { useMegaStore } from "~/state/megaStore";
-import { createDeepSignal, timeAgo } from "~/utils";
+import { createDeepSignal, eify, hexpubFromNpub, timeAgo } from "~/utils";
type CombinedMessagesAndActivity =
| { kind: "message"; content: FakeDirectMessage }
@@ -425,6 +426,40 @@ export function Chat() {
});
}
+ async function saveContact(id: string, contact: ContactFormValues) {
+ console.log("saving contact", id, contact);
+ const hexpub = await hexpubFromNpub(contact.npub?.trim());
+ try {
+ const existing = state.mutiny_wallet?.get_tag_item(id);
+ // This shouldn't happen
+ if (!existing) throw new Error("No existing contact");
+ await state.mutiny_wallet?.edit_contact(
+ id,
+ contact.name,
+ hexpub ? hexpub : undefined,
+ contact.ln_address ? contact.ln_address.trim() : undefined,
+ existing.lnurl,
+ existing.image_url
+ );
+ } catch (e) {
+ console.error(e);
+ showToast(eify(e));
+ }
+
+ // TODO: refetch contact
+ refetch();
+ }
+
+ async function deleteContact(id: string) {
+ try {
+ await state.mutiny_wallet?.delete_contact(id);
+ } catch (e) {
+ console.error(e);
+ showToast(eify(e));
+ }
+ navigate("/search");
+ }
+
return (
*/}
-
+
{}}