diff options
| author | Adam Soltys <[email protected]> | 2023-01-05 16:35:10 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2023-01-05 16:35:16 -0800 |
| commit | d2582a22a6df7c257281d9511ad07a2d72498d26 (patch) | |
| tree | c885ee295de14af7dcd74e0891d90d884c965924 | |
| parent | b74882b7e0eb0cc04c6cff5b20d56a7aa4470dda (diff) | |
| download | coinos-ui-d2582a22a6df7c257281d9511ad07a2d72498d26.tar.gz coinos-ui-d2582a22a6df7c257281d9511ad07a2d72498d26.zip | |
messages cache
| -rw-r--r-- | doc/i18n.md | 5 | ||||
| -rw-r--r-- | src/components/AppHeader.svelte | 2 | ||||
| -rw-r--r-- | src/lib/nostr.js | 2 | ||||
| -rw-r--r-- | src/lib/store.js | 3 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/(profile)/+layout.svelte | 22 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/(profile)/followers/+page.svelte | 5 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/(profile)/messages/+page.server.js | 6 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/(profile)/messages/+page.svelte | 74 | ||||
| -rw-r--r-- | src/routes/(app)/login/+page.svelte | 1 |
9 files changed, 73 insertions, 47 deletions
diff --git a/doc/i18n.md b/doc/i18n.md index fbfe8263..acf7027e 100644 --- a/doc/i18n.md +++ b/doc/i18n.md @@ -65,7 +65,7 @@ These denote sections of the JSON file, which helps keep it organized. If you're In the translation files, sections roughly correspond to where the the text is in coinos. This can be useful if you need context for some text. Here are some of these associations (`A.B` means section `B` is located inside `A`): | Section | Location | -|----------------|---------------------------------------------------| +| -------------- | ------------------------------------------------- | | 404 | the 404 page | | about | the 'About' section at the bottom of the homepage | | error | the error page | @@ -82,7 +82,8 @@ In the translation files, sections roughly correspond to where the the text is i | user.support | the user's support page | | transactions | anything to do with transactions | -If you have the `grep` tool installed and know how to use a terminal, you can use it to find where a certain bit of text is being used. In the main folder (usually called `coinos-ui-v2`), you can use the following command to find where `transactions.submit` is being used, for example: +If you have the `grep` tool installed and know how to use a terminal, you can use it to find where a certain bit of text is being used. In the main folder (usually called `coinos-ui-v2`), you can use the following command to find where `transactions.submit` is being used, for example: + ```bash grep -r "transactions.submit" src ``` diff --git a/src/components/AppHeader.svelte b/src/components/AppHeader.svelte index e5747542..e182a60f 100644 --- a/src/components/AppHeader.svelte +++ b/src/components/AppHeader.svelte @@ -100,7 +100,7 @@ <ul class="space-y-5 w-48"> {#each menuButtons as { href, icon, key }} <li> - <a {href} data-sveltekit-prefetch="off"> + <a {href} data-sveltekit-prefetch="off"> <button class="flex justify-center items-center font-semibold hover:opacity-80" ><Icon {icon} style="mr-2 w-6 md:w-8" /> {$t(key)} </button> diff --git a/src/lib/nostr.js b/src/lib/nostr.js index aff75c1b..ae18fbf1 100644 --- a/src/lib/nostr.js +++ b/src/lib/nostr.js @@ -60,7 +60,7 @@ export let encrypt = async ({ message, recipient, user }) => { export let decrypt = async ({ event, user }) => { try { let { content, pubkey } = event; - if (pubkey === user.pubkey) pubkey = event.tags[0][1]; + if (pubkey === user.pubkey) pubkey = event.tags[0][1]; pubkey = Uint8Array.from(Buffer.from('02' + pubkey, 'hex')); let sharedPoint = Buffer.from( diff --git a/src/lib/store.js b/src/lib/store.js index 9660bf55..6a2d7fd6 100644 --- a/src/lib/store.js +++ b/src/lib/store.js @@ -55,5 +55,6 @@ export const request = writable(); export const invoice = writable(); export const txns = persistLocal('transactions', []); export const events = writable({}); -export const password = writable(); +export const password = persistLocal('password'); export const passwordPrompt = writable(); +export const messages = persistLocal('messages', {}); diff --git a/src/routes/(app)/[username]/(profile)/+layout.svelte b/src/routes/(app)/[username]/(profile)/+layout.svelte index 98842016..8a651852 100644 --- a/src/routes/(app)/[username]/(profile)/+layout.svelte +++ b/src/routes/(app)/[username]/(profile)/+layout.svelte @@ -83,16 +83,18 @@ </div> {/if} {/if} - <div class="w-full flex"> - <a href={`/${subject.pubkey}/messages`} class="mx-auto"> - <button class="rounded-full border py-3 px-6 font-bold hover:opacity-80 flex w-60"> - <div class="mx-auto flex"> - <Icon icon="support" style="mr-1" /> - <div>Message</div> - </div> - </button> - </a> - </div> + {#if user.pubkey !== subject.pubkey} + <div class="w-full flex"> + <a href={`/${subject.pubkey}/messages`} class="mx-auto"> + <button class="rounded-full border py-3 px-6 font-bold hover:opacity-80 flex w-60"> + <div class="mx-auto flex"> + <Icon icon="support" style="mr-1" /> + <div>Message</div> + </div> + </button> + </a> + </div> + {/if} {#if !subject.anon} <div class="w-full flex"> <a href={`/${subject.username}/receive`} class="mx-auto"> diff --git a/src/routes/(app)/[username]/(profile)/followers/+page.svelte b/src/routes/(app)/[username]/(profile)/followers/+page.svelte index eebc11f3..87a3b947 100644 --- a/src/routes/(app)/[username]/(profile)/followers/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/followers/+page.svelte @@ -20,7 +20,10 @@ {#if followers.length} <VirtualScroll data={followers} key="pubkey" let:data pageMode={true}> <a href={`/${data.pubkey}`}> - <div class="flex border-b last:border-b-0 py-4 text-sm lg:text-lg text-secondary" :key={data.pubkey}> + <div + class="flex border-b last:border-b-0 py-4 text-sm lg:text-lg text-secondary" + :key={data.pubkey} + > <div class="mb-auto mr-2"> <div class="md:hidden"> <Avatar size={12} user={data} disabled={true} /> diff --git a/src/routes/(app)/[username]/(profile)/messages/+page.server.js b/src/routes/(app)/[username]/(profile)/messages/+page.server.js index 2efddf77..63116099 100644 --- a/src/routes/(app)/[username]/(profile)/messages/+page.server.js +++ b/src/routes/(app)/[username]/(profile)/messages/+page.server.js @@ -2,15 +2,15 @@ import { get } from '$lib/utils'; export async function load({ params, parent, url }) { let { user, subject } = await parent(); + let { since = 0 } = params; let messages = []; try { - messages = await get(`/nostr/${user.pubkey}/${subject.pubkey}/messages`); - console.log('MESSAGES', messages); + messages = await get(`/nostr/${user.pubkey}/${subject.pubkey}/${since}/messages`); } catch (e) { console.log(`failed to fetch nostr messages`, e); } - return { messages }; + return { newMessages: messages }; } diff --git a/src/routes/(app)/[username]/(profile)/messages/+page.svelte b/src/routes/(app)/[username]/(profile)/messages/+page.svelte index 3f8f5a72..dbf02cf2 100644 --- a/src/routes/(app)/[username]/(profile)/messages/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/messages/+page.svelte @@ -1,27 +1,45 @@ <script> + import { browser } from '$app/environment'; import { t } from '$lib/translations'; import { format, parseISO } from 'date-fns'; import { scale } from 'svelte/transition'; import { enhance } from '$app/forms'; import { Icon } from '$comp'; - import { back, failure } from '$lib/utils'; + import { back, failure, focus } from '$lib/utils'; import { sign, send, encrypt, decrypt } from '$lib/nostr'; + import { messages, password } from '$lib/store'; + import { tick, onMount } from 'svelte'; + import { calculateId } from 'nostr'; export let data; export let form; - const scrollToBottom = (node) => { - const scroll = () => - node.scroll({ - top: node.scrollHeight, - behavior: 'smooth' - }); - scroll(); + let { newMessages, subject, user } = data; + let input, pane; - return { update: scroll }; + $: initialize($password); + let initialize = async (p) => { + if (!p) return; + $messages[user.pubkey] = $messages[user.pubkey] || {}; + $messages[user.pubkey][subject.pubkey] = $messages[user.pubkey][subject.pubkey] || {}; + + for (let m of newMessages) { + if (!$messages[user.pubkey][subject.pubkey][m.id]) { + m.message = await decrypt({ event: m, user }); + $messages[user.pubkey][subject.pubkey][m.id] = m; + tick().then(() => (pane.scrollTop = pane.scrollHeight)); + } + } + tick().then(() => (pane.scrollTop = pane.scrollHeight)); }; - let { messages, subject, user } = data; + $: events = + ($messages[user.pubkey] && + $messages[user.pubkey][subject.pubkey] && + Object.values($messages[user.pubkey][subject.pubkey]).sort( + (a, b) => a.created_at - b.created + )) || + []; let sent, submitting, message; let submit = async () => { @@ -35,8 +53,10 @@ }; event.message = message; - messages.push(event); - messages = messages; + event.id = await calculateId(event); + $messages[user.pubkey][subject.pubkey][event.id] = event; + $messages = $messages; + tick().then(() => (pane.scrollTop = pane.scrollHeight)); try { event.content = await encrypt({ message, recipient: subject.pubkey, user }); @@ -46,10 +66,11 @@ sent = true; } catch (e) { failure('Failed to send message'); - messages.pop(); - messages = messages; + delete $messages[user.pubkey][subject.pubkey][event.id]; + $messages = $messages; } + message = ''; submitting = false; }; </script> @@ -59,25 +80,20 @@ {$t('transactions.sendMessage')} </h1> - <div class="max-h-[calc(50vh)] overflow-y-scroll p-4" use:scrollToBottom={messages}> - {#each messages as event} - {@const ours = event.pubkey === user.pubkey} + <div class="max-h-[calc(50vh)] overflow-y-scroll p-4" bind:this={pane}> + {#each events as data} + {@const ours = data.pubkey === user.pubkey} {@const theirs = !ours} <div class="rounded-2xl p-4 max-w-[300px] mb-1 text-md" class:ours class:theirs> - {#if event.message} - {event.message} + {#if data.message} + {data.message} {:else} - {#await decrypt({ event, user })} - - - {:then message} - {(event.message = message) && ''} - {event.message} - {/await} + - {/if} </div> - <div class="text-sm text-gray-400 ml-2 mb-6"> - {format(new Date(event.created_at * 1000), 'MMM d')}, - {format(new Date(event.created_at * 1000), 'h:mm aa')} + <div class="text-sm text-gray-400 mb-6" class:text-right={ours}> + {format(new Date(data.created_at * 1000), 'MMM d')}, + {format(new Date(data.created_at * 1000), 'h:mm aa')} </div> {/each} </div> @@ -87,10 +103,12 @@ <input type="hidden" name="recipient" value={subject.username} /> <input + use:focus name="message" placeholder={$t('transactions.sendMessage')} class="w-full p-4 border rounded-xl" bind:value={message} + bind:this={input} /> </form> </div> diff --git a/src/routes/(app)/login/+page.svelte b/src/routes/(app)/login/+page.svelte index 75998cd0..9a1e41da 100644 --- a/src/routes/(app)/login/+page.svelte +++ b/src/routes/(app)/login/+page.svelte @@ -1,4 +1,5 @@ <script> + import { messages } from '$lib/store'; import { RegisterOrLogin } from '$comp'; export let form; |
