mirror of
https://github.com/coracle-social/flotilla.git
synced 2025-12-11 03:17:02 +00:00
Use new kinds, re work channels
This commit is contained in:
@@ -39,7 +39,7 @@
|
|||||||
if ($page.url.pathname === path) return false
|
if ($page.url.pathname === path) return false
|
||||||
|
|
||||||
const lastChecked = max([$checked["*"], $checked[path]])
|
const lastChecked = max([$checked["*"], $checked[path]])
|
||||||
const roomEvents = $events.filter(e => matchFilter({"#~": [room]}, e))
|
const roomEvents = $events.filter(e => matchFilter({"#h": [room]}, e))
|
||||||
|
|
||||||
return getNotification($pubkey, lastChecked, roomEvents)
|
return getNotification($pubkey, lastChecked, roomEvents)
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
||||||
import {makeSpacePath} from "@app/routes"
|
import {makeSpacePath} from "@app/routes"
|
||||||
|
import {displayRoom} from "@app/state"
|
||||||
import {deriveNotification, getRoomFilters} from "@app/notifications"
|
import {deriveNotification, getRoomFilters} from "@app/notifications"
|
||||||
|
|
||||||
export let url
|
export let url
|
||||||
@@ -13,5 +14,5 @@
|
|||||||
|
|
||||||
<SecondaryNavItem href={path} notification={$notification}>
|
<SecondaryNavItem href={path} notification={$notification}>
|
||||||
<Icon icon="hashtag" />
|
<Icon icon="hashtag" />
|
||||||
{room}
|
{displayRoom(room)}
|
||||||
</SecondaryNavItem>
|
</SecondaryNavItem>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const THREAD_FILTERS: Filter[] = [
|
|||||||
export const getNotificationFilters = (since: number): Filter[] =>
|
export const getNotificationFilters = (since: number): Filter[] =>
|
||||||
[...CHAT_FILTERS, ...SPACE_FILTERS, ...THREAD_FILTERS].map(assoc("since", since))
|
[...CHAT_FILTERS, ...SPACE_FILTERS, ...THREAD_FILTERS].map(assoc("since", since))
|
||||||
|
|
||||||
export const getRoomFilters = (room: string): Filter[] => ROOM_FILTERS.map(assoc("#~", [room]))
|
export const getRoomFilters = (room: string): Filter[] => ROOM_FILTERS.map(assoc("#h", [room]))
|
||||||
|
|
||||||
// Notification derivation
|
// Notification derivation
|
||||||
|
|
||||||
|
|||||||
244
src/app/state.ts
244
src/app/state.ts
@@ -1,7 +1,6 @@
|
|||||||
import twColors from "tailwindcss/colors"
|
import twColors from "tailwindcss/colors"
|
||||||
import {get, derived} from "svelte/store"
|
import {get, derived} from "svelte/store"
|
||||||
import {nip19} from "nostr-tools"
|
import {nip19} from "nostr-tools"
|
||||||
import type {Maybe} from "@welshman/lib"
|
|
||||||
import {
|
import {
|
||||||
ctx,
|
ctx,
|
||||||
setContext,
|
setContext,
|
||||||
@@ -32,8 +31,6 @@ import {
|
|||||||
readList,
|
readList,
|
||||||
getListTags,
|
getListTags,
|
||||||
asDecryptedEvent,
|
asDecryptedEvent,
|
||||||
isSignedEvent,
|
|
||||||
hasValidSignature,
|
|
||||||
normalizeRelayUrl,
|
normalizeRelayUrl,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import type {TrustedEvent, SignedEvent, PublishedList, List, Filter} from "@welshman/util"
|
import type {TrustedEvent, SignedEvent, PublishedList, List, Filter} from "@welshman/util"
|
||||||
@@ -48,6 +45,7 @@ import {
|
|||||||
getDefaultNetContext,
|
getDefaultNetContext,
|
||||||
makeRouter,
|
makeRouter,
|
||||||
tracker,
|
tracker,
|
||||||
|
trackerStore,
|
||||||
relay,
|
relay,
|
||||||
getSession,
|
getSession,
|
||||||
getSigner,
|
getSigner,
|
||||||
@@ -56,22 +54,23 @@ import {
|
|||||||
createSearch,
|
createSearch,
|
||||||
userFollows,
|
userFollows,
|
||||||
ensurePlaintext,
|
ensurePlaintext,
|
||||||
|
thunkWorker,
|
||||||
} from "@welshman/app"
|
} from "@welshman/app"
|
||||||
import type {AppSyncOpts} from "@welshman/app"
|
import type {AppSyncOpts, Thunk} from "@welshman/app"
|
||||||
import type {SubscribeRequestWithHandlers} from "@welshman/net"
|
import type {SubscribeRequestWithHandlers} from "@welshman/net"
|
||||||
import {deriveEvents, deriveEventsMapped, withGetter, synced} from "@welshman/store"
|
import {deriveEvents, deriveEventsMapped, withGetter, synced} from "@welshman/store"
|
||||||
|
|
||||||
export const ROOM = "~"
|
export const ROOM = "h"
|
||||||
|
|
||||||
export const GENERAL = "general"
|
export const GENERAL = "_"
|
||||||
|
|
||||||
export const MESSAGE = 209
|
export const MESSAGE = 9
|
||||||
|
|
||||||
export const THREAD = 309
|
export const THREAD = 11
|
||||||
|
|
||||||
export const COMMENT = 1111
|
export const COMMENT = 1111
|
||||||
|
|
||||||
export const MEMBERSHIPS = 10209
|
export const MEMBERSHIPS = 10009
|
||||||
|
|
||||||
export const INDEXER_RELAYS = [
|
export const INDEXER_RELAYS = [
|
||||||
"wss://purplepag.es/",
|
"wss://purplepag.es/",
|
||||||
@@ -154,7 +153,7 @@ export const pubkeyLink = (
|
|||||||
relays = ctx.app.router.FromPubkeys([pubkey]).getUrls(),
|
relays = ctx.app.router.FromPubkeys([pubkey]).getUrls(),
|
||||||
) => entityLink(nip19.nprofileEncode({pubkey, relays}))
|
) => entityLink(nip19.nprofileEncode({pubkey, relays}))
|
||||||
|
|
||||||
export const tagRoom = (room: string, url: string) => [ROOM, room, url]
|
export const tagRoom = (room: string, url: string) => [ROOM, room]
|
||||||
|
|
||||||
export const getDefaultPubkeys = () => {
|
export const getDefaultPubkeys = () => {
|
||||||
const appPubkeys = DEFAULT_PUBKEYS.split(",")
|
const appPubkeys = DEFAULT_PUBKEYS.split(",")
|
||||||
@@ -222,30 +221,6 @@ export const pullConservatively = ({relays, filters}: AppSyncOpts) => {
|
|||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
}
|
}
|
||||||
|
|
||||||
setContext({
|
|
||||||
net: getDefaultNetContext({
|
|
||||||
isValid: (url: string, event: TrustedEvent) => {
|
|
||||||
if (!isSignedEvent(event) || !hasValidSignature(event)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const roomTags = event.tags.filter(nthEq(0, "~"))
|
|
||||||
|
|
||||||
if (roomTags.length > 0 && !roomTags.some(nthEq(2, url))) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
app: getDefaultAppContext({
|
|
||||||
dufflepudUrl: DUFFLEPUD_URL,
|
|
||||||
indexerRelays: INDEXER_RELAYS,
|
|
||||||
requestTimeout: 5000,
|
|
||||||
router: makeRouter(),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const deriveEvent = (idOrAddress: string, hints: string[] = []) => {
|
export const deriveEvent = (idOrAddress: string, hints: string[] = []) => {
|
||||||
let attempted = false
|
let attempted = false
|
||||||
|
|
||||||
@@ -265,23 +240,42 @@ export const deriveEvent = (idOrAddress: string, hints: string[] = []) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const eventIsForUrl = (url: string, event: TrustedEvent) =>
|
|
||||||
event.tags.find(nthEq(0, "~"))?.[2] === url
|
|
||||||
|
|
||||||
export const getEventsForUrl = (url: string, filters: Filter[]) =>
|
export const getEventsForUrl = (url: string, filters: Filter[]) =>
|
||||||
sortBy(
|
sortBy(
|
||||||
e => -e.created_at,
|
e => -e.created_at,
|
||||||
repository.query(filters).filter(e => eventIsForUrl(url, e)),
|
repository.query(filters).filter(e => tracker.hasRelay(e.id, url)),
|
||||||
)
|
)
|
||||||
|
|
||||||
export const deriveEventsForUrl = (url: string, filters: Filter[]) =>
|
export const deriveEventsForUrl = (url: string, filters: Filter[]) =>
|
||||||
derived(deriveEvents(repository, {filters}), $events =>
|
derived([deriveEvents(repository, {filters}), trackerStore], ([$events, $tracker]) =>
|
||||||
sortBy(
|
sortBy(
|
||||||
e => -e.created_at,
|
e => -e.created_at,
|
||||||
$events.filter(e => eventIsForUrl(url, e)),
|
$events.filter(e => $tracker.hasRelay(e.id, url)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Context
|
||||||
|
|
||||||
|
setContext({
|
||||||
|
net: getDefaultNetContext(),
|
||||||
|
app: getDefaultAppContext({
|
||||||
|
dufflepudUrl: DUFFLEPUD_URL,
|
||||||
|
indexerRelays: INDEXER_RELAYS,
|
||||||
|
requestTimeout: 5000,
|
||||||
|
router: makeRouter(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Track what urls we're attempting to send messages to so we can associate them with spaces immediately
|
||||||
|
|
||||||
|
thunkWorker.addGlobalHandler((thunk: Thunk) => {
|
||||||
|
if (thunk.event.tags.find(t => t[0] === ROOM)) {
|
||||||
|
for (const url of thunk.request.relays) {
|
||||||
|
tracker.track(thunk.event.id, url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
|
|
||||||
export const canDecrypt = synced("canDecrypt", false)
|
export const canDecrypt = synced("canDecrypt", false)
|
||||||
@@ -335,7 +329,7 @@ export const {
|
|||||||
export const hasMembershipUrl = (list: List | undefined, url: string) =>
|
export const hasMembershipUrl = (list: List | undefined, url: string) =>
|
||||||
getListTags(list).some(t => {
|
getListTags(list).some(t => {
|
||||||
if (t[0] === "r") return t[1] === url
|
if (t[0] === "r") return t[1] === url
|
||||||
if (t[0] === "~") return t[2] === url
|
if (t[0] === "group") return t[2] === url
|
||||||
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@@ -344,13 +338,13 @@ export const getMembershipUrls = (list?: List) => sort(getRelayTagValues(getList
|
|||||||
|
|
||||||
export const getMembershipRooms = (list?: List) =>
|
export const getMembershipRooms = (list?: List) =>
|
||||||
getListTags(list)
|
getListTags(list)
|
||||||
.filter(t => t[0] === "~")
|
.filter(t => t[0] === "group")
|
||||||
.map(t => ({url: t[2], room: t[1]}))
|
.map(t => ({url: t[2], room: t[1]}))
|
||||||
|
|
||||||
export const getMembershipRoomsByUrl = (url: string, list?: List) =>
|
export const getMembershipRoomsByUrl = (url: string, list?: List) =>
|
||||||
sort(
|
sort(
|
||||||
getListTags(list)
|
getListTags(list)
|
||||||
.filter(t => t[0] === "~" && t[2] === url)
|
.filter(t => t[0] === "group" && t[2] === url)
|
||||||
.map(nth(1)),
|
.map(nth(1)),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -375,85 +369,6 @@ export const {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Messages
|
|
||||||
|
|
||||||
export type ChannelMessage = {
|
|
||||||
url: string
|
|
||||||
room: string
|
|
||||||
event: TrustedEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
export const readMessage = (event: TrustedEvent): Maybe<ChannelMessage> => {
|
|
||||||
const roomTags = event.tags.filter(nthEq(0, ROOM))
|
|
||||||
|
|
||||||
if (roomTags.length !== 1) return undefined
|
|
||||||
|
|
||||||
const [_, room, url] = roomTags[0]
|
|
||||||
|
|
||||||
if (!url || !room) return undefined
|
|
||||||
|
|
||||||
return {url: normalizeRelayUrl(url), room, event}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const channelMessages = deriveEventsMapped<ChannelMessage>(repository, {
|
|
||||||
filters: [{kinds: [MESSAGE]}],
|
|
||||||
eventToItem: readMessage,
|
|
||||||
itemToEvent: item => item.event,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Channels
|
|
||||||
|
|
||||||
export type Channel = {
|
|
||||||
id: string
|
|
||||||
url: string
|
|
||||||
room: string
|
|
||||||
messages: ChannelMessage[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const makeChannelId = (url: string, room: string) => `${url}|${room}`
|
|
||||||
|
|
||||||
export const splitChannelId = (id: string) => id.split("|")
|
|
||||||
|
|
||||||
export const channels = derived(
|
|
||||||
[memberships, channelMessages],
|
|
||||||
([$memberships, $channelMessages]) => {
|
|
||||||
const messagesByChannelId = new Map<string, ChannelMessage[]>()
|
|
||||||
|
|
||||||
// Add known rooms by membership so we don't have to scan messages to load all rooms
|
|
||||||
for (const membership of $memberships) {
|
|
||||||
for (const {url, room} of getMembershipRooms(membership)) {
|
|
||||||
messagesByChannelId.set(makeChannelId(url, room), [])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add messages/rooms without memberships
|
|
||||||
for (const message of $channelMessages) {
|
|
||||||
pushToMapKey(messagesByChannelId, makeChannelId(message.url, message.room), message)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(messagesByChannelId.entries()).map(([id, messages]) => {
|
|
||||||
const [url, room] = splitChannelId(id)
|
|
||||||
|
|
||||||
return {id, url, room, messages}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
export const {
|
|
||||||
indexStore: channelsById,
|
|
||||||
deriveItem: deriveChannel,
|
|
||||||
loadItem: loadChannel,
|
|
||||||
} = collection({
|
|
||||||
name: "channels",
|
|
||||||
store: channels,
|
|
||||||
getKey: channel => channel.id,
|
|
||||||
load: (id: string, request: Partial<SubscribeRequestWithHandlers> = {}) => {
|
|
||||||
const [url, room] = splitChannelId(id)
|
|
||||||
|
|
||||||
return load({...request, relays: [url], filters: [{"#~": [room]}]})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Chats
|
// Chats
|
||||||
|
|
||||||
export const chatMessages = deriveEvents(repository, {filters: [{kinds: [DIRECT_MESSAGE]}]})
|
export const chatMessages = deriveEvents(repository, {filters: [{kinds: [DIRECT_MESSAGE]}]})
|
||||||
@@ -518,20 +433,95 @@ export const chatSearch = derived(chats, $chats =>
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Messages
|
||||||
|
|
||||||
|
export const messages = deriveEvents(repository, {filters: [{kinds: [MESSAGE]}]})
|
||||||
|
|
||||||
|
// Channels
|
||||||
|
|
||||||
|
export type Channel = {
|
||||||
|
url: string
|
||||||
|
room: string
|
||||||
|
name: string
|
||||||
|
events: TrustedEvent[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makeChannelId = (url: string, room: string) => `${url}|${room}`
|
||||||
|
|
||||||
|
export const splitChannelId = (id: string) => id.split("|")
|
||||||
|
|
||||||
|
export const channelsById = derived(
|
||||||
|
[memberships, messages, trackerStore],
|
||||||
|
([$memberships, $messages, $tracker]) => {
|
||||||
|
const eventsByChannelId = new Map<string, TrustedEvent[]>()
|
||||||
|
|
||||||
|
// Add known rooms by membership so we have a full listing even if there are no messages there
|
||||||
|
for (const membership of $memberships) {
|
||||||
|
for (const {url, room} of getMembershipRooms(membership)) {
|
||||||
|
eventsByChannelId.set(makeChannelId(url, room), [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add known messages to rooms
|
||||||
|
for (const event of $messages) {
|
||||||
|
const [_, room] = event.tags.find(nthEq(0, ROOM)) || []
|
||||||
|
|
||||||
|
if (room) {
|
||||||
|
for (const url of $tracker.getRelays(event.id)) {
|
||||||
|
pushToMapKey(eventsByChannelId, makeChannelId(url, room), event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const channelsById = new Map<string, Channel>()
|
||||||
|
|
||||||
|
for (const [id, unsorted] of eventsByChannelId.entries()) {
|
||||||
|
const [url, room] = splitChannelId(id)
|
||||||
|
const events = sortBy(e => -e.created_at, unsorted)
|
||||||
|
|
||||||
|
let name = room
|
||||||
|
for (const event of events) {
|
||||||
|
const tag = event.tags.find(t => t[0] === ROOM && t[2])
|
||||||
|
|
||||||
|
if (tag) {
|
||||||
|
name = tag[2]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channelsById.set(id, {url, room, name, events})
|
||||||
|
}
|
||||||
|
|
||||||
|
return channelsById
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
export const deriveChannel = (url: string, room: string) =>
|
||||||
|
derived(channelsById, $channelsById => $channelsById.get(makeChannelId(url, room)))
|
||||||
|
|
||||||
|
export const deriveChannelMessages = (url: string, room: string) =>
|
||||||
|
derived(channelsById, $channelsById => $channelsById.get(makeChannelId(url, room))?.events || [])
|
||||||
|
|
||||||
// Rooms
|
// Rooms
|
||||||
|
|
||||||
export const roomsByUrl = derived(channels, $channels => {
|
export const roomsByUrl = derived(channelsById, $channelsById => {
|
||||||
const $roomsByUrl = new Map<string, string[]>()
|
const $roomsByUrl = new Map<string, string[]>()
|
||||||
|
|
||||||
for (const channel of $channels) {
|
for (const {url, room} of $channelsById.values()) {
|
||||||
if (channel.room) {
|
pushToMapKey($roomsByUrl, url, room)
|
||||||
pushToMapKey($roomsByUrl, channel.url, channel.room)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $roomsByUrl
|
return $roomsByUrl
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const displayRoom = (room: string) => {
|
||||||
|
if (room === GENERAL) {
|
||||||
|
return "general"
|
||||||
|
}
|
||||||
|
|
||||||
|
return room
|
||||||
|
}
|
||||||
|
|
||||||
// User stuff
|
// User stuff
|
||||||
|
|
||||||
export const userSettings = withGetter(
|
export const userSettings = withGetter(
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
filters: [
|
filters: [
|
||||||
{kinds: [THREAD], limit: 1},
|
{kinds: [THREAD], limit: 1},
|
||||||
{kinds: [COMMENT], "#K": [String(THREAD)], limit: 1},
|
{kinds: [COMMENT], "#K": [String(THREAD)], limit: 1},
|
||||||
...rooms.map(room => ({kinds: [MESSAGE], "#~": [room], limit: 1})),
|
...rooms.map(room => ({kinds: [MESSAGE], "#h": [room], limit: 1})),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
filters: [
|
filters: [
|
||||||
{kinds: [THREAD], since},
|
{kinds: [THREAD], since},
|
||||||
{kinds: [COMMENT], "#K": [String(THREAD)], since},
|
{kinds: [COMMENT], "#K": [String(THREAD)], since},
|
||||||
{kinds: [MESSAGE], "#~": rooms, since},
|
{kinds: [MESSAGE], "#h": rooms, since},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
import type {Readable} from "svelte/store"
|
import type {Readable} from "svelte/store"
|
||||||
import type {Editor} from "svelte-tiptap"
|
import type {Editor} from "svelte-tiptap"
|
||||||
import {page} from "$app/stores"
|
import {page} from "$app/stores"
|
||||||
import {sortBy, sleep, append, now, ctx} from "@welshman/lib"
|
import {sleep, append, now, ctx} from "@welshman/lib"
|
||||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||||
import {createEvent, DELETE} from "@welshman/util"
|
import {createEvent, DELETE} from "@welshman/util"
|
||||||
import {formatTimestampAsDate, publishThunk} from "@welshman/app"
|
import {formatTimestampAsDate, publishThunk} from "@welshman/app"
|
||||||
@@ -32,12 +32,12 @@
|
|||||||
userSettingValues,
|
userSettingValues,
|
||||||
userMembership,
|
userMembership,
|
||||||
decodeRelay,
|
decodeRelay,
|
||||||
makeChannelId,
|
deriveChannelMessages,
|
||||||
deriveChannel,
|
|
||||||
GENERAL,
|
GENERAL,
|
||||||
tagRoom,
|
tagRoom,
|
||||||
MESSAGE,
|
MESSAGE,
|
||||||
getMembershipRoomsByUrl,
|
getMembershipRoomsByUrl,
|
||||||
|
displayRoom,
|
||||||
} from "@app/state"
|
} from "@app/state"
|
||||||
import {setChecked} from "@app/notifications"
|
import {setChecked} from "@app/notifications"
|
||||||
import {addRoomMembership, removeRoomMembership, subscribePersistent} from "@app/commands"
|
import {addRoomMembership, removeRoomMembership, subscribePersistent} from "@app/commands"
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
const {room = GENERAL} = $page.params
|
const {room = GENERAL} = $page.params
|
||||||
const content = popKey<string>("content") || ""
|
const content = popKey<string>("content") || ""
|
||||||
const url = decodeRelay($page.params.relay)
|
const url = decodeRelay($page.params.relay)
|
||||||
const channel = deriveChannel(makeChannelId(url, room))
|
const events = deriveChannelMessages(url, room)
|
||||||
|
|
||||||
const assertEvent = (e: any) => e as TrustedEvent
|
const assertEvent = (e: any) => e as TrustedEvent
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
let previousDate
|
let previousDate
|
||||||
let previousPubkey
|
let previousPubkey
|
||||||
|
|
||||||
for (const {event} of sortBy(m => m.event.created_at, $channel?.messages || [])) {
|
for (const event of $events.toReversed()) {
|
||||||
const {id, pubkey, created_at} = event
|
const {id, pubkey, created_at} = event
|
||||||
const date = formatTimestampAsDate(created_at)
|
const date = formatTimestampAsDate(created_at)
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
|
|
||||||
pullConservatively({
|
pullConservatively({
|
||||||
relays: [url],
|
relays: [url],
|
||||||
filters: [{kinds: [MESSAGE, DELETE], "#~": [room]}],
|
filters: [{kinds: [MESSAGE, DELETE], "#h": [room]}],
|
||||||
})
|
})
|
||||||
|
|
||||||
scroller = createScroller({
|
scroller = createScroller({
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
|
|
||||||
unsub = subscribePersistent({
|
unsub = subscribePersistent({
|
||||||
relays: [url],
|
relays: [url],
|
||||||
filters: [{kinds: [MESSAGE], "#~": [room], since: now()}],
|
filters: [{kinds: [MESSAGE], "#h": [room], since: now()}],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@
|
|||||||
<div slot="icon" class="center">
|
<div slot="icon" class="center">
|
||||||
<Icon icon="hashtag" />
|
<Icon icon="hashtag" />
|
||||||
</div>
|
</div>
|
||||||
<strong slot="title">{room}</strong>
|
<strong slot="title">{displayRoom(room)}</strong>
|
||||||
<div slot="action" class="row-2">
|
<div slot="action" class="row-2">
|
||||||
{#if room !== GENERAL}
|
{#if room !== GENERAL}
|
||||||
{#if getMembershipRoomsByUrl(url, $userMembership).includes(room)}
|
{#if getMembershipRoomsByUrl(url, $userMembership).includes(room)}
|
||||||
|
|||||||
Reference in New Issue
Block a user