forked from coracle/flotilla
Rename channel to room
This commit is contained in:
+1
-1
@@ -69,7 +69,7 @@ Here are a few important domain objects:
|
|||||||
|
|
||||||
- Spaces are relays used as community groups. Their `url`s are core to a lot of data and components, and are frequently passed around from place to place.
|
- Spaces are relays used as community groups. Their `url`s are core to a lot of data and components, and are frequently passed around from place to place.
|
||||||
- Chats are direct message conversations. There is currently some ambiguity in routing, since relays that don't support NIP 29 also have a "chat" tab, which uses vanilla NIP-C7.
|
- Chats are direct message conversations. There is currently some ambiguity in routing, since relays that don't support NIP 29 also have a "chat" tab, which uses vanilla NIP-C7.
|
||||||
- NIP 29 groups are variously called "rooms" and "channels". Conventionally, a "room" is a group id, while a "channel" as an object representing the group's metadata.
|
- NIP 29 groups are variously called "rooms" and "rooms". Conventionally, a "room" is a group id, while a "room" as an object representing the group's metadata.
|
||||||
- "Alerts" are records of requests the user has made to be notified, following [this NIP](https://github.com/nostr-protocol/nips/pull/1796)
|
- "Alerts" are records of requests the user has made to be notified, following [this NIP](https://github.com/nostr-protocol/nips/pull/1796)
|
||||||
|
|
||||||
`app/core/requests` contains utilities related to loading data from the nostr network. This might include feed manager utilities, loaders, or listeners.
|
`app/core/requests` contains utilities related to loading data from the nostr network. This might include feed manager utilities, loaders, or listeners.
|
||||||
|
|||||||
Generated
+14
-14
@@ -4179,19 +4179,19 @@ packages:
|
|||||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
side-channel-list@1.0.0:
|
side-room-list@1.0.0:
|
||||||
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
|
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
side-channel-map@1.0.1:
|
side-room-map@1.0.1:
|
||||||
resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
|
resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
side-channel-weakmap@1.0.2:
|
side-room-weakmap@1.0.2:
|
||||||
resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
|
resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
side-channel@1.1.0:
|
side-room@1.1.0:
|
||||||
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
|
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
@@ -8136,7 +8136,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
side-channel: 1.1.0
|
side-room: 1.1.0
|
||||||
|
|
||||||
is-array-buffer@3.0.5:
|
is-array-buffer@3.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9334,33 +9334,33 @@ snapshots:
|
|||||||
|
|
||||||
shebang-regex@3.0.0: {}
|
shebang-regex@3.0.0: {}
|
||||||
|
|
||||||
side-channel-list@1.0.0:
|
side-room-list@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
object-inspect: 1.13.4
|
object-inspect: 1.13.4
|
||||||
|
|
||||||
side-channel-map@1.0.1:
|
side-room-map@1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
object-inspect: 1.13.4
|
object-inspect: 1.13.4
|
||||||
|
|
||||||
side-channel-weakmap@1.0.2:
|
side-room-weakmap@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
object-inspect: 1.13.4
|
object-inspect: 1.13.4
|
||||||
side-channel-map: 1.0.1
|
side-room-map: 1.0.1
|
||||||
|
|
||||||
side-channel@1.1.0:
|
side-room@1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
object-inspect: 1.13.4
|
object-inspect: 1.13.4
|
||||||
side-channel-list: 1.0.0
|
side-room-list: 1.0.0
|
||||||
side-channel-map: 1.0.1
|
side-room-map: 1.0.1
|
||||||
side-channel-weakmap: 1.0.2
|
side-room-weakmap: 1.0.2
|
||||||
|
|
||||||
signal-exit@3.0.7: {}
|
signal-exit@3.0.7: {}
|
||||||
|
|
||||||
@@ -9483,7 +9483,7 @@ snapshots:
|
|||||||
internal-slot: 1.1.0
|
internal-slot: 1.1.0
|
||||||
regexp.prototype.flags: 1.5.4
|
regexp.prototype.flags: 1.5.4
|
||||||
set-function-name: 2.0.2
|
set-function-name: 2.0.2
|
||||||
side-channel: 1.1.0
|
side-room: 1.1.0
|
||||||
|
|
||||||
string.prototype.trim@1.2.10:
|
string.prototype.trim@1.2.10:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url?: string
|
url?: string
|
||||||
channel?: string
|
room?: string
|
||||||
notifyChat?: boolean
|
notifyChat?: boolean
|
||||||
notifyThreads?: boolean
|
notifyThreads?: boolean
|
||||||
notifyCalendar?: boolean
|
notifyCalendar?: boolean
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
let {
|
let {
|
||||||
url = "",
|
url = "",
|
||||||
channel = "email",
|
room = "email",
|
||||||
notifyChat = true,
|
notifyChat = true,
|
||||||
notifyThreads = true,
|
notifyThreads = true,
|
||||||
notifyCalendar = true,
|
notifyCalendar = true,
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
const back = () => history.back()
|
const back = () => history.back()
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
if (channel === "email" && !email.includes("@")) {
|
if (room === "email" && !email.includes("@")) {
|
||||||
return pushToast({
|
return pushToast({
|
||||||
theme: "error",
|
theme: "error",
|
||||||
message: "Please provide an email address",
|
message: "Please provide an email address",
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
feed: makeIntersectionFeed(feedFromFilters(filters), makeRelayFeed(url)),
|
feed: makeIntersectionFeed(feedFromFilters(filters), makeRelayFeed(url)),
|
||||||
claims: claim ? {[url]: claim} : {},
|
claims: claim ? {[url]: claim} : {},
|
||||||
description: `for ${displayList(display)} on ${displayRelayUrl(url)}`,
|
description: `for ${displayList(display)} on ${displayRelayUrl(url)}`,
|
||||||
email: channel === "email" ? {cron, email} : undefined,
|
email: room === "email" ? {cron, email} : undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (!canSendPushNotifications()) {
|
if (!canSendPushNotifications()) {
|
||||||
channel = "email"
|
room = "email"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -136,14 +136,14 @@
|
|||||||
<p>Alert Type*</p>
|
<p>Alert Type*</p>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet input()}
|
{#snippet input()}
|
||||||
<select bind:value={channel} class="select select-bordered">
|
<select bind:value={room} class="select select-bordered">
|
||||||
<option value="email">Email Digest</option>
|
<option value="email">Email Digest</option>
|
||||||
<option value="push">Push Notification</option>
|
<option value="push">Push Notification</option>
|
||||||
</select>
|
</select>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</FieldInline>
|
</FieldInline>
|
||||||
{/if}
|
{/if}
|
||||||
{#if channel === "email"}
|
{#if room === "email"}
|
||||||
<FieldInline>
|
<FieldInline>
|
||||||
{#snippet label()}
|
{#snippet label()}
|
||||||
<p>Email Address*</p>
|
<p>Email Address*</p>
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
const {alert}: Props = $props()
|
const {alert}: Props = $props()
|
||||||
|
|
||||||
const cron = $derived(getTagValue("cron", alert.tags))
|
const cron = $derived(getTagValue("cron", alert.tags))
|
||||||
const channel = $derived(getTagValue("channel", alert.tags))
|
const room = $derived(getTagValue("room", alert.tags))
|
||||||
const feeds = $derived(getTagValues("feed", alert.tags))
|
const feeds = $derived(getTagValues("feed", alert.tags))
|
||||||
const description = $derived(
|
const description = $derived(
|
||||||
getTagValue("description", alert.tags) ||
|
getTagValue("description", alert.tags) ||
|
||||||
[
|
[
|
||||||
`${cron?.endsWith("1") ? "Weekly" : "Daily"} alert for events`,
|
`${cron?.endsWith("1") ? "Weekly" : "Daily"} alert for events`,
|
||||||
displayFeeds(feeds.map(parseJson)),
|
displayFeeds(feeds.map(parseJson)),
|
||||||
`sent via ${channel}.`,
|
`sent via ${room}.`,
|
||||||
].join(" "),
|
].join(" "),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,11 @@
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url?: string
|
url?: string
|
||||||
channel?: string
|
room?: string
|
||||||
hideSpaceField?: boolean
|
hideSpaceField?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const {url = "", channel = "push", hideSpaceField = false}: Props = $props()
|
const {url = "", room = "push", hideSpaceField = false}: Props = $props()
|
||||||
|
|
||||||
const dmStatus = $derived($dmAlert ? deriveAlertStatus(getAddress($dmAlert.event)) : undefined)
|
const dmStatus = $derived($dmAlert ? deriveAlertStatus(getAddress($dmAlert.event)) : undefined)
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const startAlert = () => pushModal(AlertAdd, {url, channel, hideSpaceField})
|
const startAlert = () => pushModal(AlertAdd, {url, room, hideSpaceField})
|
||||||
|
|
||||||
const uncheckDmAlert = async (message: string) => {
|
const uncheckDmAlert = async (message: string) => {
|
||||||
await sleep(100)
|
await sleep(100)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import ChannelName from "@app/components/ChannelName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
||||||
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
|
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
|
||||||
import EventActivity from "@app/components/EventActivity.svelte"
|
import EventActivity from "@app/components/EventActivity.svelte"
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<div class="flex flex-grow flex-wrap justify-end gap-2">
|
<div class="flex flex-grow flex-wrap justify-end gap-2">
|
||||||
{#if h && showRoom}
|
{#if h && showRoom}
|
||||||
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
|
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
|
||||||
Posted in #<ChannelName {h} {url} />
|
Posted in #<RoomName {h} {url} />
|
||||||
</Link>
|
</Link>
|
||||||
{/if}
|
{/if}
|
||||||
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
|
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import CalendarEventActions from "@app/components/CalendarEventActions.svelte"
|
import CalendarEventActions from "@app/components/CalendarEventActions.svelte"
|
||||||
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
|
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
|
||||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||||
import ChannelLink from "@app/components/ChannelLink.svelte"
|
import RoomLink from "@app/components/RoomLink.svelte"
|
||||||
import {makeCalendarPath} from "@app/util/routes"
|
import {makeCalendarPath} from "@app/util/routes"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
||||||
Posted by <ProfileLink pubkey={event.pubkey} {url} />
|
Posted by <ProfileLink pubkey={event.pubkey} {url} />
|
||||||
{#if h}
|
{#if h}
|
||||||
in <ChannelLink {url} {h} />
|
in <RoomLink {url} {h} />
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<CalendarEventActions showActivity {url} {event} />
|
<CalendarEventActions showActivity {url} {event} />
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import {channelsById, makeChannelId} from "@app/core/state"
|
|
||||||
|
|
||||||
const {url, h} = $props()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{$channelsById.get(makeChannelId(url, h))?.name || h}
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
||||||
import ProfileCircles from "@app/components/ProfileCircles.svelte"
|
import ProfileCircles from "@app/components/ProfileCircles.svelte"
|
||||||
import {goToEvent} from "@app/util/routes"
|
import {goToEvent} from "@app/util/routes"
|
||||||
import {displayChannel} from "@app/core/state"
|
import {displayRoom} from "@app/core/state"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<div class="flex items-center gap-2 text-sm opacity-70">
|
<div class="flex items-center gap-2 text-sm opacity-70">
|
||||||
{#if h}
|
{#if h}
|
||||||
<span class="truncate font-medium text-blue-400">
|
<span class="truncate font-medium text-blue-400">
|
||||||
#{displayChannel(url, h)}
|
#{displayRoom(url, h)}
|
||||||
</span>
|
</span>
|
||||||
<span class="opacity-50">•</span>
|
<span class="opacity-50">•</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||||
import ChannelName from "@app/components/ChannelName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import {channelsByUrl} from "@app/core/state"
|
import {roomsByUrl} from "@app/core/state"
|
||||||
import {makeRoomPath} from "@app/util/routes"
|
import {makeRoomPath} from "@app/util/routes"
|
||||||
|
|
||||||
const {url, noun, event}: {url: string; noun: string; event: TrustedEvent} = $props()
|
const {url, noun, event}: {url: string; noun: string; event: TrustedEvent} = $props()
|
||||||
@@ -39,14 +39,14 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<div class="grid grid-cols-3 gap-2">
|
<div class="grid grid-cols-3 gap-2">
|
||||||
{#each $channelsByUrl.get(url) || [] as channel (channel.h)}
|
{#each $roomsByUrl.get(url) || [] as room (room.h)}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn"
|
class="btn"
|
||||||
class:btn-neutral={selection !== channel.h}
|
class:btn-neutral={selection !== room.h}
|
||||||
class:btn-primary={selection === channel.h}
|
class:btn-primary={selection === room.h}
|
||||||
onclick={() => toggleRoom(channel.h)}>
|
onclick={() => toggleRoom(room.h)}>
|
||||||
#<ChannelName {...channel} />
|
#<RoomName {...room} />
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
|
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
|
||||||
import EventActivity from "@app/components/EventActivity.svelte"
|
import EventActivity from "@app/components/EventActivity.svelte"
|
||||||
import EventActions from "@app/components/EventActions.svelte"
|
import EventActions from "@app/components/EventActions.svelte"
|
||||||
import ChannelName from "@app/components/ChannelName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import {publishDelete, publishReaction, canEnforceNip70} from "@app/core/commands"
|
import {publishDelete, publishReaction, canEnforceNip70} from "@app/core/commands"
|
||||||
import {makeGoalPath, makeSpacePath} from "@app/util/routes"
|
import {makeGoalPath, makeSpacePath} from "@app/util/routes"
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<div class="flex flex-grow flex-wrap justify-end gap-2">
|
<div class="flex flex-grow flex-wrap justify-end gap-2">
|
||||||
{#if h && showRoom}
|
{#if h && showRoom}
|
||||||
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
|
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
|
||||||
Posted in #<ChannelName {h} {url} />
|
Posted in #<RoomName {h} {url} />
|
||||||
</Link>
|
</Link>
|
||||||
{/if}
|
{/if}
|
||||||
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
|
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||||
import GoalActions from "@app/components/GoalActions.svelte"
|
import GoalActions from "@app/components/GoalActions.svelte"
|
||||||
import GoalSummary from "@app/components/GoalSummary.svelte"
|
import GoalSummary from "@app/components/GoalSummary.svelte"
|
||||||
import ChannelLink from "@app/components/ChannelLink.svelte"
|
import RoomLink from "@app/components/RoomLink.svelte"
|
||||||
import {makeGoalPath} from "@app/util/routes"
|
import {makeGoalPath} from "@app/util/routes"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
||||||
Posted by <ProfileLink pubkey={event.pubkey} {url} />
|
Posted by <ProfileLink pubkey={event.pubkey} {url} />
|
||||||
{#if h}
|
{#if h}
|
||||||
in <ChannelLink {url} {h} />
|
in <RoomLink {url} {h} />
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<GoalActions showActivity {url} {event} />
|
<GoalActions showActivity {url} {event} />
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
const manageAlerts = () => {
|
const manageAlerts = () => {
|
||||||
const component = hasAlerts ? Alerts : AlertAdd
|
const component = hasAlerts ? Alerts : AlertAdd
|
||||||
const params = {url, channel: "push", hideSpaceField: true}
|
const params = {url, room: "push", hideSpaceField: true}
|
||||||
|
|
||||||
pushModal(component, params, {replaceState})
|
pushModal(component, params, {replaceState})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
||||||
import ChannelNameWithImage from "@app/components/ChannelNameWithImage.svelte"
|
import RoomNameWithImage from "@app/components/RoomNameWithImage.svelte"
|
||||||
import {makeRoomPath} from "@app/util/routes"
|
import {makeRoomPath} from "@app/util/routes"
|
||||||
import {notifications} from "@app/util/notifications"
|
import {notifications} from "@app/util/notifications"
|
||||||
|
|
||||||
@@ -20,5 +20,5 @@
|
|||||||
href={path}
|
href={path}
|
||||||
{replaceState}
|
{replaceState}
|
||||||
notification={notify ? $notifications.has(path) : false}>
|
notification={notify ? $notifications.has(path) : false}>
|
||||||
<ChannelNameWithImage {url} {h} />
|
<RoomNameWithImage {url} {h} />
|
||||||
</SecondaryNavItem>
|
</SecondaryNavItem>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||||
import RoomForm from "@app/components/RoomForm.svelte"
|
import RoomForm from "@app/components/RoomForm.svelte"
|
||||||
import {deriveChannel} from "@app/core/state"
|
import {deriveRoom} from "@app/core/state"
|
||||||
import {makeSpacePath} from "@app/util/routes"
|
import {makeSpacePath} from "@app/util/routes"
|
||||||
import {pushModal} from "@app/util/modal"
|
import {pushModal} from "@app/util/modal"
|
||||||
import {pushToast} from "@app/util/toast"
|
import {pushToast} from "@app/util/toast"
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
const {url, h}: Props = $props()
|
const {url, h}: Props = $props()
|
||||||
|
|
||||||
const channel = deriveChannel(url, h)
|
const room = deriveRoom(url, h)
|
||||||
const initialValues = $channel ? readRoomMeta($channel.event) : makeRoomMeta({h})
|
const initialValues = $room ? readRoomMeta($room.event) : makeRoomMeta({h})
|
||||||
|
|
||||||
const back = () => history.back()
|
const back = () => history.back()
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,14 @@
|
|||||||
import ThunkFailure from "@app/components/ThunkFailure.svelte"
|
import ThunkFailure from "@app/components/ThunkFailure.svelte"
|
||||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||||
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
||||||
import ChannelItemZapButton from "@app/components/ChannelItemZapButton.svelte"
|
import RoomItemZapButton from "@app/components/RoomItemZapButton.svelte"
|
||||||
import ChannelItemEmojiButton from "@app/components/ChannelItemEmojiButton.svelte"
|
import RoomItemEmojiButton from "@app/components/RoomItemEmojiButton.svelte"
|
||||||
import ChannelItemMenuButton from "@app/components/ChannelItemMenuButton.svelte"
|
import RoomItemMenuButton from "@app/components/RoomItemMenuButton.svelte"
|
||||||
import ChannelItemMenuMobile from "@app/components/ChannelItemMenuMobile.svelte"
|
import RoomItemMenuMobile from "@app/components/RoomItemMenuMobile.svelte"
|
||||||
import ChannelItemContent from "@app/components/ChannelItemContent.svelte"
|
import RoomItemContent from "@app/components/RoomItemContent.svelte"
|
||||||
import {colors, ENABLE_ZAPS, deriveEventsForUrl} from "@app/core/state"
|
import {colors, ENABLE_ZAPS, deriveEventsForUrl} from "@app/core/state"
|
||||||
import {publishDelete, publishReaction, canEnforceNip70} from "@app/core/commands"
|
import {publishDelete, publishReaction, canEnforceNip70} from "@app/core/commands"
|
||||||
import {getChannelItemPath} from "@app/util/routes"
|
import {getRoomItemPath} from "@app/util/routes"
|
||||||
import {pushModal} from "@app/util/modal"
|
import {pushModal} from "@app/util/modal"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
onEdit,
|
onEdit,
|
||||||
}: Props = $props()
|
}: Props = $props()
|
||||||
|
|
||||||
const path = getChannelItemPath(url, event)
|
const path = getRoomItemPath(url, event)
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
const today = formatTimestampAsDate(now())
|
const today = formatTimestampAsDate(now())
|
||||||
const profile = deriveProfile(event.pubkey, [url])
|
const profile = deriveProfile(event.pubkey, [url])
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
const reply = () => replyTo!(event)
|
const reply = () => replyTo!(event)
|
||||||
const edit = canEdit(event) ? () => onEdit(event) : undefined
|
const edit = canEdit(event) ? () => onEdit(event) : undefined
|
||||||
|
|
||||||
const onTap = () => pushModal(ChannelItemMenuMobile, {url, event, reply, edit})
|
const onTap = () => pushModal(RoomItemMenuMobile, {url, event, reply, edit})
|
||||||
|
|
||||||
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey, url})
|
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey, url})
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class:mt-2={showPubkey && event.kind !== MESSAGE}>
|
<div class:mt-2={showPubkey && event.kind !== MESSAGE}>
|
||||||
<ChannelItemContent {url} {event} />
|
<RoomItemContent {url} {event} />
|
||||||
{#if thunk}
|
{#if thunk}
|
||||||
<ThunkFailure showToastOnRetry {thunk} class="mt-2 text-sm" />
|
<ThunkFailure showToastOnRetry {thunk} class="mt-2 text-sm" />
|
||||||
{/if}
|
{/if}
|
||||||
@@ -142,9 +142,9 @@
|
|||||||
class="join absolute right-1 top-1 border border-solid border-neutral text-xs opacity-0 transition-all"
|
class="join absolute right-1 top-1 border border-solid border-neutral text-xs opacity-0 transition-all"
|
||||||
class:group-hover:opacity-100={!isMobile}>
|
class:group-hover:opacity-100={!isMobile}>
|
||||||
{#if ENABLE_ZAPS}
|
{#if ENABLE_ZAPS}
|
||||||
<ChannelItemZapButton {url} {event} />
|
<RoomItemZapButton {url} {event} />
|
||||||
{/if}
|
{/if}
|
||||||
<ChannelItemEmojiButton {url} {event} />
|
<RoomItemEmojiButton {url} {event} />
|
||||||
{#if replyTo}
|
{#if replyTo}
|
||||||
<Button class="btn join-item btn-xs" onclick={reply}>
|
<Button class="btn join-item btn-xs" onclick={reply}>
|
||||||
<Icon icon={Reply} size={4} />
|
<Icon icon={Reply} size={4} />
|
||||||
@@ -155,7 +155,7 @@
|
|||||||
<Icon icon={Pen} size={4} />
|
<Icon icon={Pen} size={4} />
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
<ChannelItemMenuButton {url} {event} />
|
<RoomItemMenuButton {url} {event} />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</TapTarget>
|
</TapTarget>
|
||||||
+2
-2
@@ -5,11 +5,11 @@
|
|||||||
import {isMobile} from "@lib/html"
|
import {isMobile} from "@lib/html"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import NoteContent from "@app/components/NoteContent.svelte"
|
import NoteContent from "@app/components/NoteContent.svelte"
|
||||||
import {getChannelItemPath} from "@app/util/routes"
|
import {getRoomItemPath} from "@app/util/routes"
|
||||||
|
|
||||||
const props: ComponentProps<typeof NoteContent> = $props()
|
const props: ComponentProps<typeof NoteContent> = $props()
|
||||||
|
|
||||||
const path = getChannelItemPath(props.url!, props.event)
|
const path = getRoomItemPath(props.url!, props.event)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={cx("text-sm", {"card2 card2-sm bg-alt": props.event.kind !== MESSAGE})}>
|
<div class={cx("text-sm", {"card2 card2-sm bg-alt": props.event.kind !== MESSAGE})}>
|
||||||
+2
-2
@@ -5,7 +5,7 @@
|
|||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import Tippy from "@lib/components/Tippy.svelte"
|
import Tippy from "@lib/components/Tippy.svelte"
|
||||||
import ChannelItemMenu from "@app/components/ChannelItemMenu.svelte"
|
import RoomItemMenu from "@app/components/RoomItemMenu.svelte"
|
||||||
|
|
||||||
const {url, event} = $props()
|
const {url, event} = $props()
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
<Tippy
|
<Tippy
|
||||||
bind:popover
|
bind:popover
|
||||||
component={ChannelItemMenu}
|
component={RoomItemMenu}
|
||||||
props={{url, event, onClick}}
|
props={{url, event, onClick}}
|
||||||
params={{trigger: "manual", interactive: true}} />
|
params={{trigger: "manual", interactive: true}} />
|
||||||
</div>
|
</div>
|
||||||
+2
-2
@@ -17,7 +17,7 @@
|
|||||||
import EventDeleteConfirm from "@app/components/EventDeleteConfirm.svelte"
|
import EventDeleteConfirm from "@app/components/EventDeleteConfirm.svelte"
|
||||||
import {ENABLE_ZAPS} from "@app/core/state"
|
import {ENABLE_ZAPS} from "@app/core/state"
|
||||||
import {publishReaction, canEnforceNip70} from "@app/core/commands"
|
import {publishReaction, canEnforceNip70} from "@app/core/commands"
|
||||||
import {getChannelItemPath} from "@app/util/routes"
|
import {getRoomItemPath} from "@app/util/routes"
|
||||||
import {pushModal} from "@app/util/modal"
|
import {pushModal} from "@app/util/modal"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
const {url, event, reply}: Props = $props()
|
const {url, event, reply}: Props = $props()
|
||||||
|
|
||||||
const path = getChannelItemPath(url, event)
|
const path = getRoomItemPath(url, event)
|
||||||
|
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import cx from "classnames"
|
import cx from "classnames"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import ChannelName from "@app/components/ChannelName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import {makeSpacePath} from "@app/util/routes"
|
import {makeSpacePath} from "@app/util/routes"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -17,5 +17,5 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Link href={path} class={cx(props.class, {"link-content bg-alt": !unstyled})}>
|
<Link href={path} class={cx(props.class, {"link-content bg-alt": !unstyled})}>
|
||||||
#<ChannelName {h} {url} />
|
#<RoomName {h} {url} />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {roomsById, makeRoomId} from "@app/core/state"
|
||||||
|
|
||||||
|
const {url, h} = $props()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{$roomsById.get(makeRoomId(url, h))?.name || h}
|
||||||
+7
-7
@@ -2,8 +2,8 @@
|
|||||||
import Lock from "@assets/icons/lock-keyhole.svg?dataurl"
|
import Lock from "@assets/icons/lock-keyhole.svg?dataurl"
|
||||||
import Hashtag from "@assets/icons/hashtag.svg?dataurl"
|
import Hashtag from "@assets/icons/hashtag.svg?dataurl"
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import ChannelName from "@app/components/ChannelName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import {deriveChannel} from "@app/core/state"
|
import {deriveRoom} from "@app/core/state"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
url: any
|
url: any
|
||||||
@@ -12,21 +12,21 @@
|
|||||||
|
|
||||||
const {url, h}: Props = $props()
|
const {url, h}: Props = $props()
|
||||||
|
|
||||||
const channel = deriveChannel(url, h)
|
const room = deriveRoom(url, h)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $channel?.picture}
|
{#if $room?.picture}
|
||||||
{@const src = $channel.picture}
|
{@const src = $room.picture}
|
||||||
{#if src.match("\.(png|svg)$") || src.match("image/(png|svg)")}
|
{#if src.match("\.(png|svg)$") || src.match("image/(png|svg)")}
|
||||||
<Icon icon={src} />
|
<Icon icon={src} />
|
||||||
{:else}
|
{:else}
|
||||||
<img alt="Room icon" {src} class="h-6 w-6 rounded-lg" />
|
<img alt="Room icon" {src} class="h-6 w-6 rounded-lg" />
|
||||||
{/if}
|
{/if}
|
||||||
{:else if $channel?.closed || $channel?.private}
|
{:else if $room?.closed || $room?.private}
|
||||||
<Icon icon={Lock} />
|
<Icon icon={Lock} />
|
||||||
{:else}
|
{:else}
|
||||||
<Icon icon={Hashtag} />
|
<Icon icon={Hashtag} />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="min-w-0 overflow-hidden text-ellipsis">
|
<div class="min-w-0 overflow-hidden text-ellipsis">
|
||||||
<ChannelName {url} {h} />
|
<RoomName {url} {h} />
|
||||||
</div>
|
</div>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||||
import {getTagValue} from "@welshman/util"
|
import {getTagValue} from "@welshman/util"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import ChannelName from "@app/components/ChannelName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
||||||
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
|
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
|
||||||
import EventActivity from "@app/components/EventActivity.svelte"
|
import EventActivity from "@app/components/EventActivity.svelte"
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<div class="flex flex-grow flex-wrap justify-end gap-2">
|
<div class="flex flex-grow flex-wrap justify-end gap-2">
|
||||||
{#if h && showRoom}
|
{#if h && showRoom}
|
||||||
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
|
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
|
||||||
Posted in #<ChannelName {h} {url} />
|
Posted in #<RoomName {h} {url} />
|
||||||
</Link>
|
</Link>
|
||||||
{/if}
|
{/if}
|
||||||
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
|
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import Content from "@app/components/Content.svelte"
|
import Content from "@app/components/Content.svelte"
|
||||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||||
import ThreadActions from "@app/components/ThreadActions.svelte"
|
import ThreadActions from "@app/components/ThreadActions.svelte"
|
||||||
import ChannelLink from "@app/components/ChannelLink.svelte"
|
import RoomLink from "@app/components/RoomLink.svelte"
|
||||||
import {makeThreadPath} from "@app/util/routes"
|
import {makeThreadPath} from "@app/util/routes"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
Posted by
|
Posted by
|
||||||
<ProfileLink pubkey={event.pubkey} {url} />
|
<ProfileLink pubkey={event.pubkey} {url} />
|
||||||
{#if h}
|
{#if h}
|
||||||
in <ChannelLink {url} {h} />
|
in <RoomLink {url} {h} />
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<ThreadActions showActivity {url} {event} />
|
<ThreadActions showActivity {url} {event} />
|
||||||
|
|||||||
+24
-24
@@ -530,11 +530,11 @@ export const chatSearch = derived(chats, $chats =>
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Channels
|
// Rooms
|
||||||
|
|
||||||
export const messages = deriveEvents(repository, {filters: [{kinds: [MESSAGE]}]})
|
export const messages = deriveEvents(repository, {filters: [{kinds: [MESSAGE]}]})
|
||||||
|
|
||||||
export type Channel = {
|
export type Room = {
|
||||||
id: string
|
id: string
|
||||||
url: string
|
url: string
|
||||||
h: string
|
h: string
|
||||||
@@ -546,17 +546,17 @@ export type Channel = {
|
|||||||
about?: string
|
about?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const makeChannelId = (url: string, h: string) => `${url}'${h}`
|
export const makeRoomId = (url: string, h: string) => `${url}'${h}`
|
||||||
|
|
||||||
export const splitChannelId = (id: string) => id.split("'")
|
export const splitRoomId = (id: string) => id.split("'")
|
||||||
|
|
||||||
export const hasNip29 = (relay?: RelayProfile) =>
|
export const hasNip29 = (relay?: RelayProfile) =>
|
||||||
relay?.supported_nips?.map?.(String)?.includes?.("29")
|
relay?.supported_nips?.map?.(String)?.includes?.("29")
|
||||||
|
|
||||||
export const channels = derived(
|
export const rooms = derived(
|
||||||
[deriveEvents(repository, {filters: [{kinds: [ROOM_META, ROOM_DELETE]}]}), getUrlsForEvent],
|
[deriveEvents(repository, {filters: [{kinds: [ROOM_META, ROOM_DELETE]}]}), getUrlsForEvent],
|
||||||
([$events, $getUrlsForEvent]) => {
|
([$events, $getUrlsForEvent]) => {
|
||||||
const result = new Map<string, Channel>()
|
const result = new Map<string, Room>()
|
||||||
|
|
||||||
for (const event of sortBy(e => e.created_at, $events)) {
|
for (const event of sortBy(e => e.created_at, $events)) {
|
||||||
for (const url of $getUrlsForEvent(event.id)) {
|
for (const url of $getUrlsForEvent(event.id)) {
|
||||||
@@ -565,7 +565,7 @@ export const channels = derived(
|
|||||||
const h = meta.d
|
const h = meta.d
|
||||||
|
|
||||||
if (h) {
|
if (h) {
|
||||||
const id = makeChannelId(url, h)
|
const id = makeRoomId(url, h)
|
||||||
|
|
||||||
result.set(id, {
|
result.set(id, {
|
||||||
id,
|
id,
|
||||||
@@ -583,7 +583,7 @@ export const channels = derived(
|
|||||||
|
|
||||||
if (event.kind === ROOM_DELETE) {
|
if (event.kind === ROOM_DELETE) {
|
||||||
for (const h of getTagValues("h", event.tags)) {
|
for (const h of getTagValues("h", event.tags)) {
|
||||||
result.delete(makeChannelId(url, h))
|
result.delete(makeRoomId(url, h))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -593,18 +593,18 @@ export const channels = derived(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
export const channelsByUrl = derived(channels, $channels => groupBy(c => c.url, $channels))
|
export const roomsByUrl = derived(rooms, $rooms => groupBy(c => c.url, $rooms))
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
indexStore: channelsById,
|
indexStore: roomsById,
|
||||||
deriveItem: _deriveChannel,
|
deriveItem: _deriveRoom,
|
||||||
loadItem: _loadChannel,
|
loadItem: _loadRoom,
|
||||||
} = collection({
|
} = collection({
|
||||||
name: "channels",
|
name: "rooms",
|
||||||
store: channels,
|
store: rooms,
|
||||||
getKey: channel => channel.id,
|
getKey: room => room.id,
|
||||||
load: async (id: string) => {
|
load: async (id: string) => {
|
||||||
const [url, h] = splitChannelId(id)
|
const [url, h] = splitRoomId(id)
|
||||||
|
|
||||||
await load({
|
await load({
|
||||||
relays: [url],
|
relays: [url],
|
||||||
@@ -613,12 +613,12 @@ export const {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const deriveChannel = (url: string, h: string) => _deriveChannel(makeChannelId(url, h))
|
export const deriveRoom = (url: string, h: string) => _deriveRoom(makeRoomId(url, h))
|
||||||
|
|
||||||
export const displayChannel = (url: string, h: string) =>
|
export const displayRoom = (url: string, h: string) =>
|
||||||
channelsById.get().get(makeChannelId(url, h))?.name || h
|
roomsById.get().get(makeRoomId(url, h))?.name || h
|
||||||
|
|
||||||
export const roomComparator = (url: string) => (h: string) => displayChannel(url, h).toLowerCase()
|
export const roomComparator = (url: string) => (h: string) => displayRoom(url, h).toLowerCase()
|
||||||
|
|
||||||
// User space/room selections
|
// User space/room selections
|
||||||
|
|
||||||
@@ -701,11 +701,11 @@ export const loadUserGroupSelections = makeUserLoader(loadGroupSelections)
|
|||||||
export const userSpaceUrls = derived(userGroupSelections, getSpaceUrlsFromGroupSelections)
|
export const userSpaceUrls = derived(userGroupSelections, getSpaceUrlsFromGroupSelections)
|
||||||
|
|
||||||
export const deriveUserRooms = (url: string) =>
|
export const deriveUserRooms = (url: string) =>
|
||||||
derived([userGroupSelections, channelsById], ([$userGroupSelections, $channelsById]) => {
|
derived([userGroupSelections, roomsById], ([$userGroupSelections, $roomsById]) => {
|
||||||
const rooms: string[] = []
|
const rooms: string[] = []
|
||||||
|
|
||||||
for (const h of getSpaceRoomsFromGroupSelections(url, $userGroupSelections)) {
|
for (const h of getSpaceRoomsFromGroupSelections(url, $userGroupSelections)) {
|
||||||
if ($channelsById.has(makeChannelId(url, h))) {
|
if ($roomsById.has(makeRoomId(url, h))) {
|
||||||
rooms.push(h)
|
rooms.push(h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,10 +714,10 @@ export const deriveUserRooms = (url: string) =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const deriveOtherRooms = (url: string) =>
|
export const deriveOtherRooms = (url: string) =>
|
||||||
derived([deriveUserRooms(url), channelsByUrl], ([$userRooms, $channelsByUrl]) => {
|
derived([deriveUserRooms(url), roomsByUrl], ([$userRooms, $roomsByUrl]) => {
|
||||||
const rooms: string[] = []
|
const rooms: string[] = []
|
||||||
|
|
||||||
for (const {h} of $channelsByUrl.get(url) || []) {
|
for (const {h} of $roomsByUrl.get(url) || []) {
|
||||||
if (!$userRooms.includes(h)) {
|
if (!$userRooms.includes(h)) {
|
||||||
rooms.push(h)
|
rooms.push(h)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ export const getEventPath = async (event: TrustedEvent, urls: string[]) => {
|
|||||||
return entityLink(nip19.neventEncode({id: event.id, relays: urls}))
|
return entityLink(nip19.neventEncode({id: event.id, relays: urls}))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getChannelItemPath = (url: string, event: TrustedEvent) => {
|
export const getRoomItemPath = (url: string, event: TrustedEvent) => {
|
||||||
switch (event.kind) {
|
switch (event.kind) {
|
||||||
case THREAD:
|
case THREAD:
|
||||||
return makeThreadPath(url, event.id)
|
return makeThreadPath(url, event.id)
|
||||||
|
|||||||
@@ -32,19 +32,19 @@
|
|||||||
import ThunkToast from "@app/components/ThunkToast.svelte"
|
import ThunkToast from "@app/components/ThunkToast.svelte"
|
||||||
import MenuSpaceButton from "@app/components/MenuSpaceButton.svelte"
|
import MenuSpaceButton from "@app/components/MenuSpaceButton.svelte"
|
||||||
import RoomEdit from "@app/components/RoomEdit.svelte"
|
import RoomEdit from "@app/components/RoomEdit.svelte"
|
||||||
import ChannelName from "@app/components/ChannelName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import ChannelItem from "@app/components/ChannelItem.svelte"
|
import RoomItem from "@app/components/RoomItem.svelte"
|
||||||
import ChannelItemAddMember from "@src/app/components/ChannelItemAddMember.svelte"
|
import RoomItemAddMember from "@src/app/components/RoomItemAddMember.svelte"
|
||||||
import ChannelItemRemoveMember from "@src/app/components/ChannelItemRemoveMember.svelte"
|
import RoomItemRemoveMember from "@src/app/components/RoomItemRemoveMember.svelte"
|
||||||
import ChannelCompose from "@app/components/ChannelCompose.svelte"
|
import RoomCompose from "@app/components/RoomCompose.svelte"
|
||||||
import ChannelComposeEdit from "@src/app/components/ChannelComposeEdit.svelte"
|
import RoomComposeEdit from "@src/app/components/RoomComposeEdit.svelte"
|
||||||
import ChannelComposeParent from "@app/components/ChannelComposeParent.svelte"
|
import RoomComposeParent from "@app/components/RoomComposeParent.svelte"
|
||||||
import {
|
import {
|
||||||
deriveUserRooms,
|
deriveUserRooms,
|
||||||
userSettingsValues,
|
userSettingsValues,
|
||||||
decodeRelay,
|
decodeRelay,
|
||||||
deriveUserRoomMembershipStatus,
|
deriveUserRoomMembershipStatus,
|
||||||
deriveChannel,
|
deriveRoom,
|
||||||
MembershipStatus,
|
MembershipStatus,
|
||||||
PROTECTED,
|
PROTECTED,
|
||||||
MESSAGE_KINDS,
|
MESSAGE_KINDS,
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
const mounted = now()
|
const mounted = now()
|
||||||
const lastChecked = $checked[$page.url.pathname]
|
const lastChecked = $checked[$page.url.pathname]
|
||||||
const url = decodeRelay(relay)
|
const url = decodeRelay(relay)
|
||||||
const channel = deriveChannel(url, h)
|
const room = deriveRoom(url, h)
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
const userRooms = deriveUserRooms(url)
|
const userRooms = deriveUserRooms(url)
|
||||||
const userIsAdmin = deriveUserIsRoomAdmin(url, h)
|
const userIsAdmin = deriveUserIsRoomAdmin(url, h)
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
let showScrollButton = $state(false)
|
let showScrollButton = $state(false)
|
||||||
let cleanup: () => void
|
let cleanup: () => void
|
||||||
let events: Readable<TrustedEvent[]> = $state(readable([]))
|
let events: Readable<TrustedEvent[]> = $state(readable([]))
|
||||||
let compose: ChannelCompose | undefined = $state()
|
let compose: RoomCompose | undefined = $state()
|
||||||
let eventToEdit: TrustedEvent | undefined = $state()
|
let eventToEdit: TrustedEvent | undefined = $state()
|
||||||
|
|
||||||
const elements = $derived.by(() => {
|
const elements = $derived.by(() => {
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet title()}
|
{#snippet title()}
|
||||||
<strong class="ellipsize">
|
<strong class="ellipsize">
|
||||||
<ChannelName {url} {h} />
|
<RoomName {url} {h} />
|
||||||
</strong>
|
</strong>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet action()}
|
{#snippet action()}
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
|
|
||||||
<PageContent bind:element onscroll={onScroll} class="flex flex-col-reverse pt-4">
|
<PageContent bind:element onscroll={onScroll} class="flex flex-col-reverse pt-4">
|
||||||
<div bind:this={dynamicPadding}></div>
|
<div bind:this={dynamicPadding}></div>
|
||||||
{#if $channel?.private && $membershipStatus !== MembershipStatus.Granted}
|
{#if $room?.private && $membershipStatus !== MembershipStatus.Granted}
|
||||||
<div class="py-20">
|
<div class="py-20">
|
||||||
<div class="card2 col-8 m-auto max-w-md items-center text-center">
|
<div class="card2 col-8 m-auto max-w-md items-center text-center">
|
||||||
<p class="row-2">You aren't currently a member of this room.</p>
|
<p class="row-2">You aren't currently a member of this room.</p>
|
||||||
@@ -423,12 +423,12 @@
|
|||||||
{:else}
|
{:else}
|
||||||
{@const event = $state.snapshot(value as TrustedEvent)}
|
{@const event = $state.snapshot(value as TrustedEvent)}
|
||||||
{#if event.kind === ROOM_ADD_MEMBER}
|
{#if event.kind === ROOM_ADD_MEMBER}
|
||||||
<ChannelItemAddMember {url} {event} />
|
<RoomItemAddMember {url} {event} />
|
||||||
{:else if event.kind === ROOM_REMOVE_MEMBER}
|
{:else if event.kind === ROOM_REMOVE_MEMBER}
|
||||||
<ChannelItemRemoveMember {url} {event} />
|
<RoomItemRemoveMember {url} {event} />
|
||||||
{:else}
|
{:else}
|
||||||
<div in:slide class:-mt-1={!showPubkey}>
|
<div in:slide class:-mt-1={!showPubkey}>
|
||||||
<ChannelItem
|
<RoomItem
|
||||||
{url}
|
{url}
|
||||||
{event}
|
{event}
|
||||||
{replyTo}
|
{replyTo}
|
||||||
@@ -450,9 +450,9 @@
|
|||||||
</PageContent>
|
</PageContent>
|
||||||
|
|
||||||
<div class="chat__compose bg-base-200" bind:this={chatCompose}>
|
<div class="chat__compose bg-base-200" bind:this={chatCompose}>
|
||||||
{#if $channel?.private && $membershipStatus !== MembershipStatus.Granted}
|
{#if $room?.private && $membershipStatus !== MembershipStatus.Granted}
|
||||||
<!-- pass -->
|
<!-- pass -->
|
||||||
{:else if $channel?.closed && $membershipStatus !== MembershipStatus.Granted}
|
{:else if $room?.closed && $membershipStatus !== MembershipStatus.Granted}
|
||||||
<div class="bg-alt card m-4 flex flex-row items-center justify-between px-4 py-3">
|
<div class="bg-alt card m-4 flex flex-row items-center justify-between px-4 py-3">
|
||||||
<p>Only members are allowed to post to this room.</p>
|
<p>Only members are allowed to post to this room.</p>
|
||||||
{#if $membershipStatus === MembershipStatus.Pending}
|
{#if $membershipStatus === MembershipStatus.Pending}
|
||||||
@@ -474,17 +474,17 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div>
|
<div>
|
||||||
{#if parent}
|
{#if parent}
|
||||||
<ChannelComposeParent event={parent} clear={clearParent} verb="Replying to" />
|
<RoomComposeParent event={parent} clear={clearParent} verb="Replying to" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if share}
|
{#if share}
|
||||||
<ChannelComposeParent event={share} clear={clearShare} verb="Sharing" />
|
<RoomComposeParent event={share} clear={clearShare} verb="Sharing" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if eventToEdit}
|
{#if eventToEdit}
|
||||||
<ChannelComposeEdit clear={clearEventToEdit} />
|
<RoomComposeEdit clear={clearEventToEdit} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#key eventToEdit}
|
{#key eventToEdit}
|
||||||
<ChannelCompose
|
<RoomCompose
|
||||||
{url}
|
{url}
|
||||||
{h}
|
{h}
|
||||||
{onSubmit}
|
{onSubmit}
|
||||||
|
|||||||
@@ -18,12 +18,12 @@
|
|||||||
import Divider from "@lib/components/Divider.svelte"
|
import Divider from "@lib/components/Divider.svelte"
|
||||||
import ThunkToast from "@app/components/ThunkToast.svelte"
|
import ThunkToast from "@app/components/ThunkToast.svelte"
|
||||||
import MenuSpaceButton from "@app/components/MenuSpaceButton.svelte"
|
import MenuSpaceButton from "@app/components/MenuSpaceButton.svelte"
|
||||||
import ChannelItem from "@app/components/ChannelItem.svelte"
|
import RoomItem from "@app/components/RoomItem.svelte"
|
||||||
import ChannelItemAddMember from "@src/app/components/ChannelItemAddMember.svelte"
|
import RoomItemAddMember from "@src/app/components/RoomItemAddMember.svelte"
|
||||||
import ChannelItemRemoveMember from "@src/app/components/ChannelItemRemoveMember.svelte"
|
import RoomItemRemoveMember from "@src/app/components/RoomItemRemoveMember.svelte"
|
||||||
import ChannelCompose from "@app/components/ChannelCompose.svelte"
|
import RoomCompose from "@app/components/RoomCompose.svelte"
|
||||||
import ChannelComposeEdit from "@src/app/components/ChannelComposeEdit.svelte"
|
import RoomComposeEdit from "@src/app/components/RoomComposeEdit.svelte"
|
||||||
import ChannelComposeParent from "@app/components/ChannelComposeParent.svelte"
|
import RoomComposeParent from "@app/components/RoomComposeParent.svelte"
|
||||||
import {userSettingsValues, decodeRelay, PROTECTED, MESSAGE_KINDS} from "@app/core/state"
|
import {userSettingsValues, decodeRelay, PROTECTED, MESSAGE_KINDS} from "@app/core/state"
|
||||||
import {prependParent, canEnforceNip70, publishDelete} from "@app/core/commands"
|
import {prependParent, canEnforceNip70, publishDelete} from "@app/core/commands"
|
||||||
import {setChecked, checked} from "@app/util/notifications"
|
import {setChecked, checked} from "@app/util/notifications"
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
let showScrollButton = $state(false)
|
let showScrollButton = $state(false)
|
||||||
let cleanup: () => void
|
let cleanup: () => void
|
||||||
let events: Readable<TrustedEvent[]> = $state(readable([]))
|
let events: Readable<TrustedEvent[]> = $state(readable([]))
|
||||||
let compose: ChannelCompose | undefined = $state()
|
let compose: RoomCompose | undefined = $state()
|
||||||
let eventToEdit: TrustedEvent | undefined = $state()
|
let eventToEdit: TrustedEvent | undefined = $state()
|
||||||
|
|
||||||
const elements = $derived.by(() => {
|
const elements = $derived.by(() => {
|
||||||
@@ -274,12 +274,12 @@
|
|||||||
{:else}
|
{:else}
|
||||||
{@const event = $state.snapshot(value as TrustedEvent)}
|
{@const event = $state.snapshot(value as TrustedEvent)}
|
||||||
{#if event.kind === RELAY_ADD_MEMBER}
|
{#if event.kind === RELAY_ADD_MEMBER}
|
||||||
<ChannelItemAddMember {url} {event} />
|
<RoomItemAddMember {url} {event} />
|
||||||
{:else if event.kind === RELAY_REMOVE_MEMBER}
|
{:else if event.kind === RELAY_REMOVE_MEMBER}
|
||||||
<ChannelItemRemoveMember {url} {event} />
|
<RoomItemRemoveMember {url} {event} />
|
||||||
{:else}
|
{:else}
|
||||||
<div class:-mt-1={!showPubkey}>
|
<div class:-mt-1={!showPubkey}>
|
||||||
<ChannelItem
|
<RoomItem
|
||||||
{url}
|
{url}
|
||||||
{event}
|
{event}
|
||||||
{replyTo}
|
{replyTo}
|
||||||
@@ -302,17 +302,17 @@
|
|||||||
<div class="chat__compose bg-base-200" bind:this={chatCompose}>
|
<div class="chat__compose bg-base-200" bind:this={chatCompose}>
|
||||||
<div>
|
<div>
|
||||||
{#if parent}
|
{#if parent}
|
||||||
<ChannelComposeParent event={parent} clear={clearParent} verb="Replying to" />
|
<RoomComposeParent event={parent} clear={clearParent} verb="Replying to" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if share}
|
{#if share}
|
||||||
<ChannelComposeParent event={share} clear={clearShare} verb="Sharing" />
|
<RoomComposeParent event={share} clear={clearShare} verb="Sharing" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if eventToEdit}
|
{#if eventToEdit}
|
||||||
<ChannelComposeEdit clear={clearEventToEdit} />
|
<RoomComposeEdit clear={clearEventToEdit} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#key eventToEdit}
|
{#key eventToEdit}
|
||||||
<ChannelCompose
|
<RoomCompose
|
||||||
{url}
|
{url}
|
||||||
{onSubmit}
|
{onSubmit}
|
||||||
{onEditPrevious}
|
{onEditPrevious}
|
||||||
|
|||||||
Reference in New Issue
Block a user