diff options
| author | Adam Soltys <[email protected]> | 2026-03-01 21:36:02 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-03-01 21:36:02 -0800 |
| commit | c4a5498968b531b3965b347ed6b2b744a6cea7a3 (patch) | |
| tree | 5bd24783a9b90811d62bf1031c2820b4ff0dfdc0 /src | |
| parent | 77f407e06d21152546ccee3d8f4b21766d598c6f (diff) | |
| download | coinos-ui-c4a5498968b531b3965b347ed6b2b744a6cea7a3.tar.gz coinos-ui-c4a5498968b531b3965b347ed6b2b744a6cea7a3.zip | |
scrollbar
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/nip17.ts | 1 | ||||
| -rw-r--r-- | src/routes/(app)/messages/+layout.svelte | 42 | ||||
| -rw-r--r-- | src/routes/(app)/messages/[pubkey]/+page.svelte | 148 |
3 files changed, 149 insertions, 42 deletions
diff --git a/src/lib/nip17.ts b/src/lib/nip17.ts index 69f69464..ecdee29c 100644 --- a/src/lib/nip17.ts +++ b/src/lib/nip17.ts @@ -307,6 +307,7 @@ const publishToPreferred = async ( if (expiryEnabled) { preferredRelays = await relaysSupporting(preferredRelays, [40]); } + console.log("[nip17] publishing to relays for", pubkey, ":", preferredRelays); if (preferredRelays.length === 0) { throw new Error("No relays available to publish to"); } diff --git a/src/routes/(app)/messages/+layout.svelte b/src/routes/(app)/messages/+layout.svelte index 7e7e3cd0..230f8baf 100644 --- a/src/routes/(app)/messages/+layout.svelte +++ b/src/routes/(app)/messages/+layout.svelte @@ -28,28 +28,38 @@ <svelte:window bind:innerWidth={w} /> -<nav class="flex items-center p-4 gap-4"> - {#if isDetail} - <a href="/messages" class="btn-menu" aria-label="Back"> - <iconify-icon noobserver icon="ph:arrow-left-bold" width={(w ?? 0) > 640 ? 32 : 24}></iconify-icon> - </a> - {/if} +<div class="messages-layout"> + <nav class="flex items-center p-4 gap-4 shrink-0"> + {#if isDetail} + <a href="/messages" class="btn-menu" aria-label="Back"> + <iconify-icon noobserver icon="ph:arrow-left-bold" width={(w ?? 0) > 640 ? 32 : 24}></iconify-icon> + </a> + {/if} - <div class="ml-auto flex items-center gap-4"> - <a href="/{user?.username}" data-sveltekit-preload-code="eager" aria-label="Home"> - <button class="btn-menu" aria-label="Home"> - <iconify-icon noobserver icon="ph:house-bold" width={(w ?? 0) > 640 ? 32 : 24}></iconify-icon> - </button> - </a> - <Menu {opacity} {user} t={$t} {w} /> - </div> -</nav> + <div class="ml-auto flex items-center gap-4"> + <a href="/{user?.username}" data-sveltekit-preload-code="eager" aria-label="Home"> + <button class="btn-menu" aria-label="Home"> + <iconify-icon noobserver icon="ph:house-bold" width={(w ?? 0) > 640 ? 32 : 24}></iconify-icon> + </button> + </a> + <Menu {opacity} {user} t={$t} {w} /> + </div> + </nav> -{@render children?.()} + <div class="flex-1 min-h-0"> + {@render children?.()} + </div> +</div> <style> @reference "../../../app.css"; + .messages-layout { + display: flex; + flex-direction: column; + height: 100dvh; + } + .btn-menu { @apply flex justify-center items-center bg-base-100 p-2 rounded-full w-12 h-12 sm:w-16 sm:h-16 drop-shadow-xl; } diff --git a/src/routes/(app)/messages/[pubkey]/+page.svelte b/src/routes/(app)/messages/[pubkey]/+page.svelte index 0efa6206..5bd77203 100644 --- a/src/routes/(app)/messages/[pubkey]/+page.svelte +++ b/src/routes/(app)/messages/[pubkey]/+page.svelte @@ -143,9 +143,11 @@ try { await libnip17.send(message, user, selectedChat); text = ""; + const ta = document.getElementById("message-contents") as HTMLTextAreaElement; + if (ta) ta.style.height = "auto"; updateEvents(); await tick(); - document.getElementById("message-contents")?.focus(); + ta?.focus(); } catch (e: any) { console.error("Failed to send message:", e); sendError = $t("dm.sendFailed"); @@ -171,6 +173,20 @@ let closeSub: (() => void) | undefined; + // Keep input visible when mobile keyboard opens + onMount(() => { + const vv = window.visualViewport; + if (!vv) return; + const onResize = () => { + const active = document.activeElement; + if (active?.id === "message-contents") { + active.scrollIntoView({ block: "nearest" }); + } + }; + vv.addEventListener("resize", onResize); + return () => vv.removeEventListener("resize", onResize); + }); + onMount(() => { libnip17.subscribeToMessages(user, async (rumour) => { if (!allRumours.find((r) => r.id === rumour.id)) { @@ -204,10 +220,10 @@ onDestroy(() => closeSub?.()); </script> -<div class="container mx-auto max-w-xl px-4 space-y-2"> +<div class="chat-container"> {#if selectedChat} {@const chatProfile = selectedChat.coinosUsername ? `/${selectedChat.coinosUsername}` : null} - <a href={chatProfile} class="flex items-center gap-3 mb-2 hover:opacity-80"> + <a href={chatProfile} class="chat-header"> {#if selectedChat.picture} <img src={selectedChat.picture} alt={name(selectedChat)} class="w-10 h-10 rounded-full object-cover" /> {/if} @@ -262,27 +278,35 @@ </div> <div class="input-bar"> - <textarea - id="message-contents" - bind:value={text} - use:focus - onkeydown={(e) => { - if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault(); - if (canSend && text.trim()) sendMessage(text); - } - }} - ></textarea> - <input - id="send-message" - type="button" - class="btn btn-accent" - disabled={!canSend} - value={canSend - ? $t("dm.sendMessage") - : $t("dm.relaysNotFound").replace("[R]", selectedChat ? name(selectedChat) : "")} - onclick={async () => sendMessage(text)} - /> + <div class="input-row"> + <textarea + id="message-contents" + bind:value={text} + use:focus + rows="1" + placeholder={canSend ? "" : $t("dm.relaysNotFound").replace("[R]", selectedChat ? name(selectedChat) : "")} + disabled={!canSend} + oninput={(e) => { + const el = e.currentTarget; + el.style.height = "auto"; + el.style.height = Math.min(el.scrollHeight, 120) + "px"; + }} + onkeydown={(e) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + if (canSend && text.trim()) sendMessage(text); + } + }} + ></textarea> + <button + class="send-btn" + disabled={!canSend || !text.trim()} + onclick={() => sendMessage(text)} + aria-label="Send" + > + <iconify-icon noobserver icon="ph:paper-plane-right-fill" width="22"></iconify-icon> + </button> + </div> {#if sendError} <p class="warning"><em>{sendError}</em></p> {/if} @@ -300,6 +324,27 @@ </div> <style> + .chat-container { + display: flex; + flex-direction: column; + height: 100%; + max-width: 36rem; + margin: 0 auto; + padding: 0 1rem; + } + + .chat-header { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.5rem 0; + flex-shrink: 0; + } + + .chat-header:hover { + opacity: 0.8; + } + .warning { color: #ff7f00; } @@ -352,9 +397,18 @@ } #messages { + flex: 1; overflow-y: auto; - max-height: 50vh; scrollbar-width: thin; + margin-right: -1rem; + padding-right: 1.5rem; + } + + @media (min-width: 36rem) { + #messages { + margin-right: 0; + padding-right: 0.5rem; + } } #messages::-webkit-scrollbar { @@ -386,9 +440,51 @@ } .input-bar { + flex-shrink: 0; padding: 0.5rem 0; + } + + .input-row { display: flex; - flex-direction: column; + align-items: flex-end; gap: 0.5rem; } + + .input-row textarea { + flex: 1; + resize: none; + overflow-y: auto; + line-height: 1.4; + padding: 0.5rem 0.75rem; + border-radius: 1.25rem; + border: 1px solid rgba(128, 128, 128, 0.3); + background: transparent; + color: inherit; + font: inherit; + min-height: unset; + } + + .input-row textarea:focus { + outline: none; + border-color: rgba(128, 128, 128, 0.6); + } + + .send-btn { + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + border-radius: 9999px; + background: var(--accent, #6366f1); + color: white; + border: none; + cursor: pointer; + flex-shrink: 0; + } + + .send-btn:disabled { + opacity: 0.35; + cursor: default; + } </style> |
