diff --git a/src/locales/ar.json b/src/locales/ar.json index 9daae14d..95572d6c 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -122,7 +122,15 @@ "friendsEmpty": "لا توجد رسائل من الأشخاص الذين تتابعهم.", "translateDialogTitle": "هل تريد ترجمة الرسائل الخاصة؟", "translateDialogDescription": "سيتم إرسال الرسائل المستلمة إلى خدمة الترجمة التي قمت بتكوينها. لن تتم ترجمة الرسائل المرسلة. سيتذكر Agora هذا الاختيار على هذا الجهاز.", - "confirmTranslate": "ترجمة الرسائل" + "confirmTranslate": "ترجمة الرسائل", + "newMessage": "رسالة جديدة", + "newMessageTitle": "رسالة جديدة", + "recipientLabel": "إلى", + "recipientPlaceholder": "ابحث بالاسم أو NIP-05 أو npub…", + "recipientHint": "ابحث عن شخص لبدء محادثة جديدة.", + "recipientSearching": "جارٍ البحث…", + "noRecipientResults": "لم يُعثر على أشخاص. جرّب اسمًا أو NIP-05 أو npub مختلفًا.", + "recipientFollowed": "أنت تتابع هذا الشخص" }, "auth": { "join": "انضمام", diff --git a/src/locales/en.json b/src/locales/en.json index 0c7c900f..50883318 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -123,7 +123,15 @@ "friendsEmpty": "No messages from people you follow.", "translateDialogTitle": "Translate private messages?", "translateDialogDescription": "Received messages will be sent to your configured translation service. Sent messages will not be translated. Agora will remember this choice on this device.", - "confirmTranslate": "Translate messages" + "confirmTranslate": "Translate messages", + "newMessage": "New message", + "newMessageTitle": "New message", + "recipientLabel": "To", + "recipientPlaceholder": "Search by name, NIP-05, or npub…", + "recipientHint": "Search for someone to start a new conversation.", + "recipientSearching": "Searching…", + "noRecipientResults": "No people found. Try a different name, NIP-05, or npub.", + "recipientFollowed": "You follow this person" }, "auth": { "join": "Join", diff --git a/src/locales/es.json b/src/locales/es.json index 8bf785b0..ab47ef9b 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -122,7 +122,15 @@ "friendsEmpty": "No hay mensajes de personas que sigues.", "translateDialogTitle": "¿Traducir mensajes privados?", "translateDialogDescription": "Los mensajes recibidos se enviarán al servicio de traducción que configuraste. Los mensajes enviados no se traducirán. Agora recordará esta elección en este dispositivo.", - "confirmTranslate": "Traducir mensajes" + "confirmTranslate": "Traducir mensajes", + "newMessage": "Mensaje nuevo", + "newMessageTitle": "Mensaje nuevo", + "recipientLabel": "Para", + "recipientPlaceholder": "Busca por nombre, NIP-05 o npub…", + "recipientHint": "Busca a alguien para iniciar una nueva conversación.", + "recipientSearching": "Buscando…", + "noRecipientResults": "No se encontraron personas. Prueba con otro nombre, NIP-05 o npub.", + "recipientFollowed": "Sigues a esta persona" }, "auth": { "join": "Unirse", diff --git a/src/locales/fa.json b/src/locales/fa.json index 9cb80428..8f72bbe6 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -122,7 +122,15 @@ "friendsEmpty": "پیامی از افرادی که دنبال میکنید وجود ندارد.", "translateDialogTitle": "پیامهای خصوصی ترجمه شوند؟", "translateDialogDescription": "پیامهای دریافتی به سرویس ترجمه تنظیمشده شما ارسال میشوند. پیامهای ارسالی ترجمه نخواهند شد. Agora این انتخاب را در این دستگاه به خاطر میسپارد.", - "confirmTranslate": "ترجمه پیامها" + "confirmTranslate": "ترجمه پیامها", + "newMessage": "پیام جدید", + "newMessageTitle": "پیام جدید", + "recipientLabel": "به", + "recipientPlaceholder": "جستجو بر اساس نام، NIP-05 یا npub…", + "recipientHint": "برای شروع یک گفتگوی جدید، کسی را جستجو کنید.", + "recipientSearching": "در حال جستجو…", + "noRecipientResults": "کسی یافت نشد. نام، NIP-05 یا npub دیگری را امتحان کنید.", + "recipientFollowed": "شما این فرد را دنبال میکنید" }, "auth": { "join": "پیوستن", diff --git a/src/locales/fr.json b/src/locales/fr.json index 03ee3423..50573373 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -122,7 +122,15 @@ "friendsEmpty": "Aucun message des personnes que vous suivez.", "translateDialogTitle": "Traduire les messages privés ?", "translateDialogDescription": "Les messages reçus seront envoyés au service de traduction configuré. Les messages envoyés ne seront pas traduits. Agora mémorisera ce choix sur cet appareil.", - "confirmTranslate": "Traduire les messages" + "confirmTranslate": "Traduire les messages", + "newMessage": "Nouveau message", + "newMessageTitle": "Nouveau message", + "recipientLabel": "À", + "recipientPlaceholder": "Rechercher par nom, NIP-05 ou npub…", + "recipientHint": "Recherchez quelqu'un pour démarrer une nouvelle conversation.", + "recipientSearching": "Recherche en cours…", + "noRecipientResults": "Aucune personne trouvée. Essayez un autre nom, NIP-05 ou npub.", + "recipientFollowed": "Vous suivez cette personne" }, "auth": { "join": "Rejoindre", diff --git a/src/locales/hi.json b/src/locales/hi.json index 3ec3581f..d4d98b71 100644 --- a/src/locales/hi.json +++ b/src/locales/hi.json @@ -122,7 +122,15 @@ "friendsEmpty": "जिन लोगों को आप फ़ॉलो करते हैं उनसे कोई संदेश नहीं।", "translateDialogTitle": "निजी संदेशों का अनुवाद करें?", "translateDialogDescription": "प्राप्त संदेश आपकी कॉन्फ़िगर की गई अनुवाद सेवा को भेजे जाएंगे। भेजे गए संदेशों का अनुवाद नहीं किया जाएगा। Agora इस डिवाइस पर यह विकल्प याद रखेगा।", - "confirmTranslate": "संदेशों का अनुवाद करें" + "confirmTranslate": "संदेशों का अनुवाद करें", + "newMessage": "नया संदेश", + "newMessageTitle": "नया संदेश", + "recipientLabel": "को", + "recipientPlaceholder": "नाम, NIP-05, या npub से खोजें…", + "recipientHint": "नई बातचीत शुरू करने के लिए किसी को खोजें।", + "recipientSearching": "खोज रहे हैं…", + "noRecipientResults": "कोई व्यक्ति नहीं मिला। कोई दूसरा नाम, NIP-05, या npub आज़माएं।", + "recipientFollowed": "आप इस व्यक्ति को फ़ॉलो करते हैं" }, "auth": { "join": "जुड़ें", diff --git a/src/locales/id.json b/src/locales/id.json index e05e968b..1bf59312 100644 --- a/src/locales/id.json +++ b/src/locales/id.json @@ -122,7 +122,15 @@ "friendsEmpty": "Tidak ada pesan dari orang yang Anda ikuti.", "translateDialogTitle": "Terjemahkan pesan pribadi?", "translateDialogDescription": "Pesan yang diterima akan dikirim ke layanan terjemahan yang Anda konfigurasi. Pesan terkirim tidak akan diterjemahkan. Agora akan mengingat pilihan ini di perangkat ini.", - "confirmTranslate": "Terjemahkan pesan" + "confirmTranslate": "Terjemahkan pesan", + "newMessage": "Pesan baru", + "newMessageTitle": "Pesan baru", + "recipientLabel": "Kepada", + "recipientPlaceholder": "Cari berdasarkan nama, NIP-05, atau npub…", + "recipientHint": "Cari seseorang untuk memulai percakapan baru.", + "recipientSearching": "Mencari…", + "noRecipientResults": "Tidak ada orang ditemukan. Coba nama, NIP-05, atau npub yang berbeda.", + "recipientFollowed": "Anda mengikuti orang ini" }, "auth": { "join": "Gabung", diff --git a/src/locales/km.json b/src/locales/km.json index a028e4ff..63db2ec9 100644 --- a/src/locales/km.json +++ b/src/locales/km.json @@ -122,7 +122,15 @@ "friendsEmpty": "គ្មានសារពីមនុស្សដែលអ្នកតាមដានទេ។", "translateDialogTitle": "បកប្រែសារឯកជនឬ?", "translateDialogDescription": "សារដែលបានទទួលនឹងត្រូវបានផ្ញើទៅសេវាបកប្រែដែលអ្នកបានកំណត់។ សារដែលបានផ្ញើនឹងមិនត្រូវបានបកប្រែទេ។ Agora នឹងចងចាំជម្រើសនេះនៅលើឧបករណ៍នេះ។", - "confirmTranslate": "បកប្រែសារ" + "confirmTranslate": "បកប្រែសារ", + "newMessage": "សារថ្មី", + "newMessageTitle": "សារថ្មី", + "recipientLabel": "ទៅ", + "recipientPlaceholder": "ស្វែងរកតាមឈ្មោះ, NIP-05, ឬ npub…", + "recipientHint": "ស្វែងរកនរណាម្នាក់ដើម្បីចាប់ផ្តើមការសន្ទនាថ្មី។", + "recipientSearching": "កំពុងស្វែងរក…", + "noRecipientResults": "រកមិនឃើញនរណាម្នាក់ទេ។ សាកល្បងឈ្មោះ, NIP-05, ឬ npub ផ្សេង។", + "recipientFollowed": "អ្នកតាមដានមនុស្សនេះ" }, "auth": { "join": "ចូលរួម", diff --git a/src/locales/ps.json b/src/locales/ps.json index fde9c809..919719e3 100644 --- a/src/locales/ps.json +++ b/src/locales/ps.json @@ -122,7 +122,15 @@ "friendsEmpty": "د هغو خلکو څخه پیغامونه نشته چې تاسو یې تعقیبوئ.", "translateDialogTitle": "شخصي پیغامونه وژباړل شي؟", "translateDialogDescription": "ترلاسه شوي پیغامونه به ستاسو ټاکل شوي ژباړې خدمت ته واستول شي. لېږل شوي پیغامونه به نه ژباړل کېږي. Agora به دا انتخاب په دې وسیله کې په یاد وساتي.", - "confirmTranslate": "پیغامونه وژباړئ" + "confirmTranslate": "پیغامونه وژباړئ", + "newMessage": "نوی پیغام", + "newMessageTitle": "نوی پیغام", + "recipientLabel": "ته", + "recipientPlaceholder": "د نوم، NIP-05 یا npub له مخې لټون وکړئ…", + "recipientHint": "د نوې خبرې اترې پیلولو لپاره څوک ولټوئ.", + "recipientSearching": "په لټون کې…", + "noRecipientResults": "هیڅ خلک ونه موندل شول. بل نوم، NIP-05 یا npub هڅه وکړئ.", + "recipientFollowed": "تاسو دا کس تعقیبوئ" }, "auth": { "join": "ګډون", diff --git a/src/locales/pt.json b/src/locales/pt.json index af861e44..b488d75c 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -122,7 +122,15 @@ "friendsEmpty": "Não há mensagens de pessoas que você segue.", "translateDialogTitle": "Traduzir mensagens privadas?", "translateDialogDescription": "As mensagens recebidas serão enviadas ao serviço de tradução configurado. As mensagens enviadas não serão traduzidas. O Agora lembrará esta escolha neste dispositivo.", - "confirmTranslate": "Traduzir mensagens" + "confirmTranslate": "Traduzir mensagens", + "newMessage": "Nova mensagem", + "newMessageTitle": "Nova mensagem", + "recipientLabel": "Para", + "recipientPlaceholder": "Pesquisar por nome, NIP-05 ou npub…", + "recipientHint": "Pesquise alguém para iniciar uma nova conversa.", + "recipientSearching": "Pesquisando…", + "noRecipientResults": "Nenhuma pessoa encontrada. Tente um nome, NIP-05 ou npub diferente.", + "recipientFollowed": "Você segue esta pessoa" }, "auth": { "join": "Entrar", diff --git a/src/locales/ru.json b/src/locales/ru.json index 2b31e372..e8195b31 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -122,7 +122,15 @@ "friendsEmpty": "Нет сообщений от людей, на которых вы подписаны.", "translateDialogTitle": "Переводить личные сообщения?", "translateDialogDescription": "Полученные сообщения будут отправляться в настроенный вами сервис перевода. Отправленные сообщения переводиться не будут. Agora запомнит этот выбор на этом устройстве.", - "confirmTranslate": "Переводить сообщения" + "confirmTranslate": "Переводить сообщения", + "newMessage": "Новое сообщение", + "newMessageTitle": "Новое сообщение", + "recipientLabel": "Кому", + "recipientPlaceholder": "Поиск по имени, NIP-05 или npub…", + "recipientHint": "Найдите кого-нибудь, чтобы начать новую беседу.", + "recipientSearching": "Поиск…", + "noRecipientResults": "Никто не найден. Попробуйте другое имя, NIP-05 или npub.", + "recipientFollowed": "Вы подписаны на этого человека" }, "auth": { "join": "Присоединиться", diff --git a/src/locales/sn.json b/src/locales/sn.json index 8d3f7945..d6cd6f95 100644 --- a/src/locales/sn.json +++ b/src/locales/sn.json @@ -122,7 +122,15 @@ "friendsEmpty": "Hapana mameseji kubva kuvanhu vaunotevera.", "translateDialogTitle": "Dudzira mameseji epachivande?", "translateDialogDescription": "Mameseji agamuchirwa achaendeswa kusevhisi yako yekushandura yawakagadzirisa. Mameseji atumirwa haazodudzirwi. Agora icharangarira sarudzo iyi pachigadzirwa ichi.", - "confirmTranslate": "Dudzira mameseji" + "confirmTranslate": "Dudzira mameseji", + "newMessage": "Meseji itsva", + "newMessageTitle": "Meseji itsva", + "recipientLabel": "Kuna", + "recipientPlaceholder": "Tsvaga nezita, NIP-05, kana npub…", + "recipientHint": "Tsvaga munhu kuti utange nhaurirano itsva.", + "recipientSearching": "Kutsvaga…", + "noRecipientResults": "Hapana vanhu vawanikwa. Edza rimwe zita, NIP-05, kana npub.", + "recipientFollowed": "Unotevera munhu uyu" }, "auth": { "join": "Joinha", diff --git a/src/locales/sw.json b/src/locales/sw.json index 677bc7af..7dcbbb9a 100644 --- a/src/locales/sw.json +++ b/src/locales/sw.json @@ -122,7 +122,15 @@ "friendsEmpty": "Hakuna ujumbe kutoka kwa watu unaowafuata.", "translateDialogTitle": "Tafsiri ujumbe wa faragha?", "translateDialogDescription": "Ujumbe uliopokelewa utatumwa kwa huduma yako ya tafsiri uliyosanidi. Ujumbe uliotumwa hautatafsiriwa. Agora itakumbuka chaguo hili kwenye kifaa hiki.", - "confirmTranslate": "Tafsiri ujumbe" + "confirmTranslate": "Tafsiri ujumbe", + "newMessage": "Ujumbe mpya", + "newMessageTitle": "Ujumbe mpya", + "recipientLabel": "Kwa", + "recipientPlaceholder": "Tafuta kwa jina, NIP-05, au npub…", + "recipientHint": "Tafuta mtu ili kuanza mazungumzo mapya.", + "recipientSearching": "Inatafuta…", + "noRecipientResults": "Hakuna watu waliopatikana. Jaribu jina, NIP-05, au npub tofauti.", + "recipientFollowed": "Unamfuata mtu huyu" }, "auth": { "join": "Jiunge", diff --git a/src/locales/tr.json b/src/locales/tr.json index e5699b64..c676e259 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -122,7 +122,15 @@ "friendsEmpty": "Takip ettiğiniz kişilerden mesaj yok.", "translateDialogTitle": "Özel mesajlar çevrilsin mi?", "translateDialogDescription": "Alınan mesajlar yapılandırdığınız çeviri hizmetine gönderilecek. Gönderilen mesajlar çevrilmeyecek. Agora bu tercihi bu cihazda hatırlayacak.", - "confirmTranslate": "Mesajları çevir" + "confirmTranslate": "Mesajları çevir", + "newMessage": "Yeni mesaj", + "newMessageTitle": "Yeni mesaj", + "recipientLabel": "Kime", + "recipientPlaceholder": "İsim, NIP-05 veya npub ile ara…", + "recipientHint": "Yeni bir sohbet başlatmak için birini arayın.", + "recipientSearching": "Aranıyor…", + "noRecipientResults": "Kimse bulunamadı. Farklı bir isim, NIP-05 veya npub deneyin.", + "recipientFollowed": "Bu kişiyi takip ediyorsunuz" }, "auth": { "join": "Katıl", diff --git a/src/locales/zh-Hant.json b/src/locales/zh-Hant.json index 17c10aba..828bfd24 100644 --- a/src/locales/zh-Hant.json +++ b/src/locales/zh-Hant.json @@ -122,7 +122,15 @@ "friendsEmpty": "沒有來自您追蹤的人的訊息。", "translateDialogTitle": "要翻譯私人訊息嗎?", "translateDialogDescription": "收到的訊息將會傳送至你設定的翻譯服務。已傳送的訊息不會被翻譯。Agora 會在此裝置上記住這個選擇。", - "confirmTranslate": "翻譯訊息" + "confirmTranslate": "翻譯訊息", + "newMessage": "新訊息", + "newMessageTitle": "新訊息", + "recipientLabel": "收件人", + "recipientPlaceholder": "按名稱、NIP-05 或 npub 搜尋…", + "recipientHint": "搜尋某人以開始新的對話。", + "recipientSearching": "正在搜尋…", + "noRecipientResults": "找不到任何人。請嘗試其他名稱、NIP-05 或 npub。", + "recipientFollowed": "你追蹤了此人" }, "auth": { "join": "加入", diff --git a/src/locales/zh.json b/src/locales/zh.json index 1c58fcc1..d1e47419 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -122,7 +122,15 @@ "friendsEmpty": "没有来自您关注的人的消息。", "translateDialogTitle": "要翻译私信吗?", "translateDialogDescription": "收到的消息将发送到你配置的翻译服务。已发送的消息不会被翻译。Agora 会在此设备上记住此选择。", - "confirmTranslate": "翻译消息" + "confirmTranslate": "翻译消息", + "newMessage": "新消息", + "newMessageTitle": "新消息", + "recipientLabel": "收件人", + "recipientPlaceholder": "按名称、NIP-05 或 npub 搜索…", + "recipientHint": "搜索某人以开始新的对话。", + "recipientSearching": "正在搜索…", + "noRecipientResults": "未找到任何人。请尝试其他名称、NIP-05 或 npub。", + "recipientFollowed": "你关注了此人" }, "auth": { "join": "加入", diff --git a/src/pages/MessagesPage.tsx b/src/pages/MessagesPage.tsx index 6f1cb8e6..2fa15a6f 100644 --- a/src/pages/MessagesPage.tsx +++ b/src/pages/MessagesPage.tsx @@ -3,7 +3,8 @@ import { useEffect, useMemo, useRef, useState, type FormEvent, type KeyboardEven import { Link, Navigate, useSearchParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useInView } from 'react-intersection-observer'; -import { ArrowLeft, ArrowUp, BellOff, Inbox, Loader2, Lock, MessageSquare, Search, UserCheck, X } from 'lucide-react'; +import { ArrowLeft, ArrowUp, BellOff, Inbox, Loader2, Lock, MessageSquare, PenSquare, Search, UserCheck, X } from 'lucide-react'; +import { nip19 } from 'nostr-tools'; import { AlertDialog, @@ -37,6 +38,7 @@ import { import { useFollowList } from '@/hooks/useFollowActions'; import { useMuteList } from '@/hooks/useMuteList'; import { useProfileUrl } from '@/hooks/useProfileUrl'; +import { useSearchProfiles, type SearchProfile } from '@/hooks/useSearchProfiles'; import { useToast } from '@/hooks/useToast'; import { useVerifierStatement } from '@/hooks/useVerifierStatement'; import { getDisplayName } from '@/lib/genUserName'; @@ -523,6 +525,164 @@ function MessageThread({ ); } +/** A single recipient suggestion row inside the new-message pane. */ +function RecipientSuggestion({ + profile, + active, + followed, + onSelect, +}: { + profile: SearchProfile; + active: boolean; + followed: boolean; + onSelect: () => void; +}) { + const { t } = useTranslation(); + const name = getDisplayName(profile.metadata, profile.pubkey); + const picture = sanitizeUrl(profile.metadata.picture); + const handle = profile.metadata.nip05 ?? nip19.npubEncode(profile.pubkey); + + return ( + + + + {name.charAt(0)} + + + + {name} + {followed && ( + + )} + + {handle} + + + ); +} + +/** + * The "start a new chat" pane. Renders in the right column in place of the + * empty-state prompt. A "To:" field drives debounced profile autocomplete + * (npub / nprofile / NIP-05 / name) and the suggestions render inline below + * the field — no modal, no popover. Selecting a person opens a fresh thread. + */ +function NewMessagePane({ + onSelectRecipient, + onCancel, +}: { + onSelectRecipient: (pubkey: string) => void; + onCancel: () => void; +}) { + const { t } = useTranslation(); + const [query, setQuery] = useState(''); + const [activeIndex, setActiveIndex] = useState(0); + const { data: profiles, isFetching, followedPubkeys } = useSearchProfiles(query); + const trimmed = query.trim(); + const results = useMemo(() => profiles ?? [], [profiles]); + + useEffect(() => { + setActiveIndex(0); + }, [results]); + + const handleKeyDown = (e: KeyboardEvent) => { + if (results.length === 0) return; + if (e.key === 'ArrowDown') { + e.preventDefault(); + setActiveIndex((i) => (i + 1) % results.length); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + setActiveIndex((i) => (i - 1 + results.length) % results.length); + } else if (e.key === 'Enter') { + e.preventDefault(); + const chosen = results[activeIndex]; + if (chosen) onSelectRecipient(chosen.pubkey); + } else if (e.key === 'Escape') { + e.preventDefault(); + onCancel(); + } + }; + + return ( + + + + + {t('messages.conversations')} + + {t('messages.newMessageTitle')} + + + + + + + + {t('messages.recipientLabel')} + + + + setQuery(e.target.value)} + onKeyDown={handleKeyDown} + placeholder={t('messages.recipientPlaceholder')} + aria-label={t('messages.recipientLabel')} + className="h-11 rounded-full border-0 bg-muted/40 pl-9 pr-9 text-base shadow-sm focus-visible:ring-2 focus-visible:ring-ring md:text-sm" + autoComplete="off" + autoFocus + /> + {isFetching && ( + + )} + + + + + + {results.length > 0 ? ( + results.map((profile, index) => ( + onSelectRecipient(profile.pubkey)} + /> + )) + ) : ( + + + + {trimmed + ? (isFetching ? t('messages.recipientSearching') : t('messages.noRecipientResults')) + : t('messages.recipientHint')} + + + )} + + + + ); +} + export function MessagesPage() { const { t } = useTranslation(); const [searchParams, setSearchParams] = useSearchParams(); @@ -540,6 +700,7 @@ export function MessagesPage() { const { muteItems } = useMuteList(); const requestedPeer = getValidPubkey(searchParams.get('to')); const [selectedPeer, setSelectedPeer] = useState(() => requestedPeer); + const [composing, setComposing] = useState(false); const [search, setSearch] = useState(''); const [conversationFilter, setConversationFilter] = useState<'all' | 'friends'>('all'); const [hiddenMutedPeers, setHiddenMutedPeers] = useState>(() => new Set()); @@ -578,6 +739,7 @@ export function MessagesPage() { const selectPeer = (peer: string) => { setSelectedPeer(peer); + setComposing(false); setSearchParams((current) => { const next = new URLSearchParams(current); next.delete('to'); @@ -587,6 +749,7 @@ export function MessagesPage() { const clearSelectedPeer = () => { setSelectedPeer(null); + setComposing(false); setSearchParams((current) => { const next = new URLSearchParams(current); next.delete('to'); @@ -631,8 +794,8 @@ export function MessagesPage() { @@ -659,6 +822,20 @@ export function MessagesPage() { > {conversationFilter === 'all' ? : } + { + setSelectedPeer(null); + setComposing(true); + }} + aria-label={t('messages.newMessage')} + title={t('messages.newMessage')} + > + + {isLoading ? ( Array.from({ length: 5 }).map((_, i) => ( @@ -697,9 +874,14 @@ export function MessagesPage() { {/* Thread */} - + {selectedThread ? ( + ) : composing ? ( + setComposing(false)} + /> ) : ( @@ -707,6 +889,18 @@ export function MessagesPage() { {t('messages.selectPrompt')} + { + setSelectedPeer(null); + setComposing(true); + }} + > + + {t('messages.newMessage')} + )}
{name}
{handle}
{t('messages.newMessageTitle')}
+ {trimmed + ? (isFetching ? t('messages.recipientSearching') : t('messages.noRecipientResults')) + : t('messages.recipientHint')} +
{t('messages.selectPrompt')}