-
- {#if $userProfile?.picture}
-

- {:else}
-
- {/if}
-
+
{#each $userGroupsByNom.entries() as [nom, qualifiedGroups] (nom)}
{@const qualifiedGroup = qualifiedGroups[0]}
diff --git a/src/app/state.ts b/src/app/state.ts
index d3f0946..db1989f 100644
--- a/src/app/state.ts
+++ b/src/app/state.ts
@@ -2,8 +2,8 @@ import type {Readable} from "svelte/store"
import type {FuseResult} from 'fuse.js'
import {get, writable, readable, derived} from "svelte/store"
import type {Maybe} from "@welshman/lib"
-import {uniq, uniqBy, groupBy, pushToMapKey, nthEq, batcher, postJson, stripProtocol, assoc, indexBy, now} from "@welshman/lib"
-import {getIdentifier, getRelayTags, getRelayTagValues, normalizeRelayUrl, getPubkeyTagValues, GROUP_META, PROFILE, RELAYS, FOLLOWS, MUTES, GROUPS, getGroupTags, readProfile, readList, asDecryptedEvent, editList, makeList, createList} from "@welshman/util"
+import {max, uniq, between, uniqBy, groupBy, pushToMapKey, nthEq, batcher, postJson, stripProtocol, assoc, indexBy, now} from "@welshman/lib"
+import {getIdentifier, getRelayTags, getRelayTagValues, normalizeRelayUrl, getPubkeyTagValues, GROUP_META, PROFILE, RELAYS, FOLLOWS, MUTES, GROUPS, getGroupTags, readProfile, readList, asDecryptedEvent, editList, makeList, createList, GROUP_JOIN, GROUP_ADD_USER} from "@welshman/util"
import type {Filter, SignedEvent, CustomEvent, PublishedProfile, PublishedList} from '@welshman/util'
import type {SubscribeRequest, PublishRequest} from '@welshman/net'
import {publish as basePublish, subscribe} from '@welshman/net'
@@ -75,16 +75,16 @@ export const publish = (request: PublishRequest) => {
}
export const load = (request: SubscribeRequest) =>
- new Promise
>(resolve => {
+ new Promise(resolve => {
const sub = subscribe({closeOnEose: true, timeout: 3000, delay: 50, ...request})
+ const events: CustomEvent[] = []
sub.emitter.on('event', (url: string, e: SignedEvent) => {
repository.publish(e)
- sub.close()
- resolve(e)
+ events.push(e)
})
- sub.emitter.on('complete', () => resolve(undefined))
+ sub.emitter.on('complete', () => resolve(events))
})
// Freshness
@@ -448,7 +448,7 @@ export const groupMemberships = deriveEventsMapped(rep
export const {
indexStore: groupMembershipByPubkey,
- getIndex: getGroupMembersipByPubkey,
+ getIndex: getGroupMembershipsByPubkey,
deriveItem: deriveGroupMembership,
loadItem: loadGroupMembership,
} = createCollection({
@@ -473,7 +473,7 @@ export type GroupMessage = {
export const readGroupMessage = (event: CustomEvent): Maybe => {
const nom = event.tags.find(nthEq(0, 'h'))?.[1]
- if (!nom) {
+ if (!nom || between(GROUP_ADD_USER - 1, GROUP_JOIN + 1, event.kind)) {
return undefined
}
@@ -501,7 +501,7 @@ export const groupConversations = derived(groupMessages, $groupMessages => {
export const {
indexStore: groupConversationByNom,
- getIndex: getGroupMembersipByNom,
+ getIndex: getGroupConversationsByNom,
deriveItem: deriveGroupConversation,
loadItem: loadGroupConversation,
} = createCollection({
@@ -510,12 +510,15 @@ export const {
getKey: groupConversation => groupConversation.nom,
load: (nom: string, hints = [], request: Partial = {}) => {
const relays = [...hints, ...get(relayUrlsByNom).get(nom) || []]
+ const conversation = get(groupConversations).find(c => c.nom === nom)
+ const timestamps = conversation?.messages.map(m => m.event.created_at) || []
+ const since = Math.min(0, max(timestamps) - 3600)
if (relays.length === 0) {
console.warn(`Attempted to load conversation for ${nom} with no qualified groups`)
}
- return load({...request, relays, filters: [{'#h': [nom]}]})
+ return load({...request, relays, filters: [{'#h': [nom], since}]})
},
})
diff --git a/src/assets/icons/Arrow Right.svg b/src/assets/icons/Arrow Right.svg
new file mode 100644
index 0000000..938becc
--- /dev/null
+++ b/src/assets/icons/Arrow Right.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/lib/components/Avatar.svelte b/src/lib/components/Avatar.svelte
new file mode 100644
index 0000000..29fbf0f
--- /dev/null
+++ b/src/lib/components/Avatar.svelte
@@ -0,0 +1,17 @@
+
+
+
+ {#if src}
+
![]()
+ {:else}
+
+ {/if}
+
diff --git a/src/lib/components/Icon.svelte b/src/lib/components/Icon.svelte
index 0ec4d59..e54566b 100644
--- a/src/lib/components/Icon.svelte
+++ b/src/lib/components/Icon.svelte
@@ -12,6 +12,7 @@
import AddCircle from "@assets/icons/Add Circle.svg?dataurl"
import AltArrowRight from "@assets/icons/Alt Arrow Right.svg?dataurl"
import AltArrowLeft from "@assets/icons/Alt Arrow Left.svg?dataurl"
+ import ArrowRight from "@assets/icons/Arrow Right.svg?dataurl"
import CheckCircle from "@assets/icons/Check Circle.svg?dataurl"
import ClipboardText from "@assets/icons/Clipboard Text.svg?dataurl"
import CloseCircle from "@assets/icons/Close Circle.svg?dataurl"
@@ -48,6 +49,7 @@
"add-circle": AddCircle,
"alt-arrow-right": AltArrowRight,
"alt-arrow-left": AltArrowLeft,
+ "arrow-right": ArrowRight,
"check-circle": CheckCircle,
"clipboard-text": ClipboardText,
"close-circle": CloseCircle,
diff --git a/src/lib/util.ts b/src/lib/util.ts
index faf5d7a..08f5d16 100644
--- a/src/lib/util.ts
+++ b/src/lib/util.ts
@@ -60,3 +60,33 @@ export const createSearch = (data: T[], opts: SearchOptions) => {
searchValues: (term: string) => search(term).map(opts.getValue),
}
}
+
+
+export const secondsToDate = (ts: number) => new Date(ts * 1000)
+
+export const dateToSeconds = (date: Date) => Math.round(date.valueOf() / 1000)
+
+export const getTimeZone = () => new Date().toString().match(/GMT[^\s]+/)
+
+export const createLocalDate = (dateString: any) => new Date(`${dateString} ${getTimeZone()}`)
+
+export const getLocale = () => new Intl.DateTimeFormat().resolvedOptions().locale
+
+export const formatTimestamp = (ts: number) => {
+ const formatter = new Intl.DateTimeFormat(getLocale(), {
+ dateStyle: "short",
+ timeStyle: "short",
+ })
+
+ return formatter.format(secondsToDate(ts))
+}
+
+export const formatTimestampAsDate = (ts: number) => {
+ const formatter = new Intl.DateTimeFormat(getLocale(), {
+ year: "numeric",
+ month: "long",
+ day: "numeric",
+ })
+
+ return formatter.format(secondsToDate(ts))
+}
diff --git a/src/routes/spaces/[nom]/+page.svelte b/src/routes/spaces/[nom]/+page.svelte
index 2774523..13f7b38 100644
--- a/src/routes/spaces/[nom]/+page.svelte
+++ b/src/routes/spaces/[nom]/+page.svelte
@@ -1,16 +1,88 @@
-
+
-
+
+ {#each elements as {type, id, value, showPubkey} (id)}
+ {#if type === "date"}
+
+ {:else}
+
+ {/if}
+ {/each}
+
+
+ {#if loading}
+ Looking for messages...
+ {:else}
+ End of message history
+ {/if}
+
+
-
+
diff --git a/src/routes/spaces/[nom]/+page.ts b/src/routes/spaces/[nom]/+page.ts
new file mode 100644
index 0000000..9786e09
--- /dev/null
+++ b/src/routes/spaces/[nom]/+page.ts
@@ -0,0 +1 @@
+export const prerender = false