aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2023-01-05 16:35:10 -0800
committerAdam Soltys <[email protected]>2023-01-05 16:35:16 -0800
commitd2582a22a6df7c257281d9511ad07a2d72498d26 (patch)
treec885ee295de14af7dcd74e0891d90d884c965924
parentb74882b7e0eb0cc04c6cff5b20d56a7aa4470dda (diff)
downloadcoinos-ui-d2582a22a6df7c257281d9511ad07a2d72498d26.tar.gz
coinos-ui-d2582a22a6df7c257281d9511ad07a2d72498d26.zip
messages cache
-rw-r--r--doc/i18n.md5
-rw-r--r--src/components/AppHeader.svelte2
-rw-r--r--src/lib/nostr.js2
-rw-r--r--src/lib/store.js3
-rw-r--r--src/routes/(app)/[username]/(profile)/+layout.svelte22
-rw-r--r--src/routes/(app)/[username]/(profile)/followers/+page.svelte5
-rw-r--r--src/routes/(app)/[username]/(profile)/messages/+page.server.js6
-rw-r--r--src/routes/(app)/[username]/(profile)/messages/+page.svelte74
-rw-r--r--src/routes/(app)/login/+page.svelte1
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;