Get chat view started

This commit is contained in:
Jon Staab
2024-08-15 14:30:55 -07:00
parent 184634c6e8
commit 437cfa7bc4
10 changed files with 195 additions and 20 deletions
+48
View File
@@ -0,0 +1,48 @@
<script lang="ts">
import {readable} from 'svelte/store'
import type {CustomEvent} from '@welshman/util'
import {GROUP_REPLY, getAncestorTags, displayProfile, displayPubkey} from '@welshman/util'
import {deriveEvent} from '@welshman/store'
import {fly} from '@lib/transition'
import Icon from '@lib/components/Icon.svelte'
import Avatar from '@lib/components/Avatar.svelte'
import {repository} from '@app/base'
import {deriveProfile} from '@app/state'
export let event: CustomEvent
export let showPubkey: boolean
const profile = deriveProfile(event.pubkey)
const {replies} = getAncestorTags(event.tags)
const parentEvent = replies.length > 0
? deriveEvent(repository, replies[0][1])
: readable(null)
$: parentProfile = deriveProfile($parentEvent?.pubkey)
</script>
<div in:fly>
{#if event.kind === GROUP_REPLY}
<div class="pl-12">
<div class="text-xs flex gap-1">
<Icon icon="arrow-right" />
<Avatar src={$parentProfile?.picture} size={4}/>
<p class="text-primary">{displayProfile($parentProfile, displayPubkey($parentEvent.pubkey))}<p>
<p class="whitespace-nowrap overflow-hidden text-ellipsis">{$parentEvent.content}</p>
</div>
</div>
{/if}
<div class="flex gap-2">
{#if showPubkey}
<Avatar src={$profile?.picture} class="border border-solid border-base-content" size={10} />
{:else}
<div class="w-10" />
{/if}
<div class="-mt-1">
{#if showPubkey}
<strong class="text-sm text-primary">{displayProfile($profile, displayPubkey(event.pubkey))}</strong>
{/if}
<p class="text-sm">{event.content}</p>
</div>
</div>
</div>
+2 -7
View File
@@ -13,6 +13,7 @@
import {quintOut} from 'svelte/easing'
import {identity, nth} from '@welshman/lib'
import Icon from "@lib/components/Icon.svelte"
import Avatar from "@lib/components/Avatar.svelte"
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
import SpaceAdd from '@app/components/SpaceAdd.svelte'
import {session} from "@app/base"
@@ -53,13 +54,7 @@
<div class="flex h-full flex-col justify-between">
<div>
<PrimaryNavItem on:click={gotoHome}>
<div class="!flex w-10 items-center justify-center rounded-full border border-solid border-base-300">
{#if $userProfile?.picture}
<img alt="" src={$userProfile.picture} />
{:else}
<Icon icon="user-rounded" size={7} />
{/if}
</div>
<Avatar src={$userProfile?.picture} class="border border-solid border-base-300 !w-10 !h-10" size={7} />
</PrimaryNavItem>
{#each $userGroupsByNom.entries() as [nom, qualifiedGroups] (nom)}
{@const qualifiedGroup = qualifiedGroups[0]}
+13 -10
View File
@@ -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<Maybe<CustomEvent>>(resolve => {
new Promise<CustomEvent[]>(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<PublishedGroupMembership>(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<GroupMessage> => {
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<SubscribeRequest> = {}) => {
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}]})
},
})