forked from coracle/flotilla
Add room deletion
This commit is contained in:
@@ -26,7 +26,12 @@
|
|||||||
{replaceState}
|
{replaceState}
|
||||||
notification={notify ? $notifications.has(path) : false}>
|
notification={notify ? $notifications.has(path) : false}>
|
||||||
{#if $channel?.picture}
|
{#if $channel?.picture}
|
||||||
<Icon icon={$channel.picture} />
|
{@const src = $channel.picture}
|
||||||
|
{#if src.match("\.(png|svg)$") || src.match("image/(png|svg)")}
|
||||||
|
<Icon icon={src} />
|
||||||
|
{:else}
|
||||||
|
<img alt="Room icon" {src} class="h-6 w-6 rounded-lg" />
|
||||||
|
{/if}
|
||||||
{:else if $channel?.closed || $channel?.private}
|
{:else if $channel?.closed || $channel?.private}
|
||||||
<Icon icon={Lock} />
|
<Icon icon={Lock} />
|
||||||
{:else}
|
{:else}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
let instance: any | undefined
|
let instance: any | undefined
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
modal.subscribe($modal => {
|
return modal.subscribe($modal => {
|
||||||
if (instance) {
|
if (instance) {
|
||||||
unmount(instance, {outro: true})
|
unmount(instance, {outro: true})
|
||||||
instance = undefined
|
instance = undefined
|
||||||
|
|||||||
+54
-28
@@ -70,7 +70,9 @@ import {
|
|||||||
ROOM_JOIN,
|
ROOM_JOIN,
|
||||||
ROOM_LEAVE,
|
ROOM_LEAVE,
|
||||||
ROOM_MEMBERS,
|
ROOM_MEMBERS,
|
||||||
|
ROOM_ADMINS,
|
||||||
ROOM_META,
|
ROOM_META,
|
||||||
|
ROOM_DELETE,
|
||||||
ROOM_REMOVE_MEMBER,
|
ROOM_REMOVE_MEMBER,
|
||||||
ROOMS,
|
ROOMS,
|
||||||
THREAD,
|
THREAD,
|
||||||
@@ -278,8 +280,11 @@ export const deriveEventsForUrl = (url: string, filters: Filter[]) =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const deriveSignedEventsForUrl = (url: string, filters: Filter[]) =>
|
export const deriveSignedEventsForUrl = (url: string, filters: Filter[]) =>
|
||||||
derived([deriveEventsForUrl(url, filters), deriveRelay(url)], ([$events, $relay]) =>
|
derived(
|
||||||
$relay?.self ? $events.filter(spec({pubkey: $relay.self})) : [],
|
[deriveEventsForUrl(url, filters), deriveRelay(url)],
|
||||||
|
([$events, $relay]) => $events,
|
||||||
|
// Disable this check for now since khatru doesn't support self
|
||||||
|
// $relay?.self ? $events.filter(spec({pubkey: $relay.self})) : [],
|
||||||
)
|
)
|
||||||
|
|
||||||
// Context
|
// Context
|
||||||
@@ -559,37 +564,43 @@ export const splitChannelId = (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 channelEvents = deriveEvents(repository, {filters: [{kinds: [ROOM_META]}]})
|
|
||||||
|
|
||||||
export const channels = derived(
|
export const channels = derived(
|
||||||
[channelEvents, getUrlsForEvent],
|
[deriveEvents(repository, {filters: [{kinds: [ROOM_META, ROOM_DELETE]}]}), getUrlsForEvent],
|
||||||
([$channelEvents, $getUrlsForEvent]) => {
|
([$events, $getUrlsForEvent]) => {
|
||||||
const $channels: Channel[] = []
|
const result = new Map<string, Channel>()
|
||||||
|
|
||||||
for (const event of $channelEvents) {
|
for (const event of sortBy(e => e.created_at, $events)) {
|
||||||
const meta = fromPairs(event.tags)
|
for (const url of $getUrlsForEvent(event.id)) {
|
||||||
const room = meta.d
|
if (event.kind === ROOM_META) {
|
||||||
|
const meta = fromPairs(event.tags)
|
||||||
|
const room = meta.d
|
||||||
|
|
||||||
if (room) {
|
if (room) {
|
||||||
for (const url of $getUrlsForEvent(event.id)) {
|
const id = makeChannelId(url, room)
|
||||||
const id = makeChannelId(url, room)
|
|
||||||
|
|
||||||
$channels.push({
|
result.set(id, {
|
||||||
id,
|
id,
|
||||||
url,
|
url,
|
||||||
room,
|
room,
|
||||||
event,
|
event,
|
||||||
name: meta.name || room,
|
name: meta.name || room,
|
||||||
closed: Boolean(getTag("closed", event.tags)),
|
closed: Boolean(getTag("closed", event.tags)),
|
||||||
private: Boolean(getTag("private", event.tags)),
|
private: Boolean(getTag("private", event.tags)),
|
||||||
picture: meta.picture,
|
picture: meta.picture,
|
||||||
about: meta.about,
|
about: meta.about,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.kind === ROOM_DELETE) {
|
||||||
|
for (const room of getTagValues("h", event.tags)) {
|
||||||
|
result.delete(makeChannelId(url, room))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return uniqBy(c => c.id, $channels)
|
return Array.from(result.values())
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -745,7 +756,7 @@ export const deriveSpaceMembers = (url: string) =>
|
|||||||
|
|
||||||
const members = new Set()
|
const members = new Set()
|
||||||
|
|
||||||
for (const event of $events) {
|
for (const event of sortBy(e => e.created_at, $events)) {
|
||||||
const pubkeys = getPubkeyTagValues(event.tags)
|
const pubkeys = getPubkeyTagValues(event.tags)
|
||||||
|
|
||||||
if (event.kind === RELAY_ADD_MEMBER) {
|
if (event.kind === RELAY_ADD_MEMBER) {
|
||||||
@@ -768,7 +779,8 @@ export const deriveSpaceMembers = (url: string) =>
|
|||||||
export const deriveRoomMembers = (url: string, room: string) =>
|
export const deriveRoomMembers = (url: string, room: string) =>
|
||||||
derived(
|
derived(
|
||||||
deriveEventsForUrl(url, [
|
deriveEventsForUrl(url, [
|
||||||
{kinds: [ROOM_ADD_MEMBER, ROOM_REMOVE_MEMBER, ROOM_MEMBERS], "#h": [room]},
|
{kinds: [ROOM_MEMBERS], "#d": [room]},
|
||||||
|
{kinds: [ROOM_ADD_MEMBER, ROOM_REMOVE_MEMBER], "#h": [room]},
|
||||||
]),
|
]),
|
||||||
$events => {
|
$events => {
|
||||||
const membersEvent = $events.find(spec({kind: ROOM_MEMBERS}))
|
const membersEvent = $events.find(spec({kind: ROOM_MEMBERS}))
|
||||||
@@ -779,7 +791,7 @@ export const deriveRoomMembers = (url: string, room: string) =>
|
|||||||
|
|
||||||
const members = new Set()
|
const members = new Set()
|
||||||
|
|
||||||
for (const event of $events) {
|
for (const event of sortBy(e => -e.created_at, $events)) {
|
||||||
const pubkeys = getPubkeyTagValues(event.tags)
|
const pubkeys = getPubkeyTagValues(event.tags)
|
||||||
|
|
||||||
if (event.kind === ROOM_ADD_MEMBER) {
|
if (event.kind === ROOM_ADD_MEMBER) {
|
||||||
@@ -799,6 +811,17 @@ export const deriveRoomMembers = (url: string, room: string) =>
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const deriveRoomAdmins = (url: string, room: string) =>
|
||||||
|
derived(deriveEventsForUrl(url, [{kinds: [ROOM_ADMINS], "#d": [room]}]), $events => {
|
||||||
|
const adminsEvent = first($events)
|
||||||
|
|
||||||
|
if (adminsEvent) {
|
||||||
|
return getPubkeyTagValues(adminsEvent.tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
|
||||||
// User membership status
|
// User membership status
|
||||||
|
|
||||||
export enum MembershipStatus {
|
export enum MembershipStatus {
|
||||||
@@ -873,6 +896,9 @@ export const deriveUserCanCreateRoom = (url: string) =>
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const deriveUserIsRoomAdmin = (url: string, room: string) =>
|
||||||
|
derived([pubkey, deriveRoomAdmins(url, room)], ([$pubkey, $admins]) => $admins.includes($pubkey!))
|
||||||
|
|
||||||
// Other utils
|
// Other utils
|
||||||
|
|
||||||
export const encodeRelay = (url: string) =>
|
export const encodeRelay = (url: string) =>
|
||||||
|
|||||||
+12
-3
@@ -19,8 +19,13 @@ import {
|
|||||||
getRelayTagValues,
|
getRelayTagValues,
|
||||||
WRAP,
|
WRAP,
|
||||||
ROOM_META,
|
ROOM_META,
|
||||||
|
ROOM_DELETE,
|
||||||
|
ROOM_ADMINS,
|
||||||
|
ROOM_MEMBERS,
|
||||||
ROOM_ADD_MEMBER,
|
ROOM_ADD_MEMBER,
|
||||||
ROOM_REMOVE_MEMBER,
|
ROOM_REMOVE_MEMBER,
|
||||||
|
ROOM_CREATE_PERMISSION,
|
||||||
|
RELAY_MEMBERS,
|
||||||
isSignedEvent,
|
isSignedEvent,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import type {Filter, TrustedEvent} from "@welshman/util"
|
import type {Filter, TrustedEvent} from "@welshman/util"
|
||||||
@@ -165,12 +170,14 @@ const syncUserData = () => {
|
|||||||
|
|
||||||
const syncMembership = (url: string) => {
|
const syncMembership = (url: string) => {
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
|
const relayFilter = {kinds: [RELAY_MEMBERS, ROOM_CREATE_PERMISSION]}
|
||||||
|
const roomsFilter = {kinds: [ROOM_ADMINS, ROOM_MEMBERS, ROOM_META, ROOM_DELETE]}
|
||||||
|
|
||||||
// Load group metadata
|
// Load group metadata and member lists
|
||||||
pullConservatively({
|
pullConservatively({
|
||||||
relays: [url],
|
relays: [url],
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
filters: [{kinds: [ROOM_META]}],
|
filters: [relayFilter, roomsFilter],
|
||||||
})
|
})
|
||||||
|
|
||||||
// Load historical data from up to a month ago for quick page loading
|
// Load historical data from up to a month ago for quick page loading
|
||||||
@@ -184,7 +191,9 @@ const syncMembership = (url: string) => {
|
|||||||
request({
|
request({
|
||||||
relays: [url],
|
relays: [url],
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
filters: [MESSAGE_FILTER, COMMENT_FILTER, MEMBERSHIP_FILTER].map(assoc("since", now())),
|
filters: [relayFilter, roomsFilter, MESSAGE_FILTER, COMMENT_FILTER, MEMBERSHIP_FILTER].map(
|
||||||
|
assoc("since", now()),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => controller.abort()
|
return () => controller.abort()
|
||||||
|
|||||||
+54
-56
@@ -1,24 +1,35 @@
|
|||||||
import {prop, call, on, throttle, fromPairs, batch} from "@welshman/lib"
|
import {prop, call, on, throttle, fromPairs, batch} from "@welshman/lib"
|
||||||
import {throttled, freshness} from "@welshman/store"
|
import {throttled, freshness} from "@welshman/store"
|
||||||
import {
|
import {
|
||||||
PROFILE,
|
|
||||||
FOLLOWS,
|
|
||||||
MUTES,
|
|
||||||
RELAYS,
|
|
||||||
BLOSSOM_SERVERS,
|
|
||||||
INBOX_RELAYS,
|
|
||||||
ROOMS,
|
|
||||||
APP_DATA,
|
|
||||||
ALERT_STATUS,
|
|
||||||
ALERT_EMAIL,
|
|
||||||
ALERT_WEB,
|
|
||||||
ALERT_IOS,
|
|
||||||
ALERT_ANDROID,
|
ALERT_ANDROID,
|
||||||
EVENT_TIME,
|
ALERT_EMAIL,
|
||||||
THREAD,
|
ALERT_IOS,
|
||||||
MESSAGE,
|
ALERT_STATUS,
|
||||||
DIRECT_MESSAGE,
|
ALERT_WEB,
|
||||||
|
APP_DATA,
|
||||||
|
BLOSSOM_SERVERS,
|
||||||
DIRECT_MESSAGE_FILE,
|
DIRECT_MESSAGE_FILE,
|
||||||
|
DIRECT_MESSAGE,
|
||||||
|
EVENT_TIME,
|
||||||
|
FOLLOWS,
|
||||||
|
INBOX_RELAYS,
|
||||||
|
MESSAGE,
|
||||||
|
MUTES,
|
||||||
|
PROFILE,
|
||||||
|
RELAY_ADD_MEMBER,
|
||||||
|
RELAY_JOIN,
|
||||||
|
RELAY_LEAVE,
|
||||||
|
RELAY_MEMBERS,
|
||||||
|
RELAY_REMOVE_MEMBER,
|
||||||
|
RELAYS,
|
||||||
|
ROOM_ADD_MEMBER,
|
||||||
|
ROOM_CREATE_PERMISSION,
|
||||||
|
ROOM_MEMBERS,
|
||||||
|
ROOM_META,
|
||||||
|
ROOM_REMOVE_MEMBER,
|
||||||
|
ROOMS,
|
||||||
|
THREAD,
|
||||||
|
ZAP_GOAL,
|
||||||
verifiedSymbol,
|
verifiedSymbol,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import type {Zapper, TrustedEvent, RelayProfile} from "@welshman/util"
|
import type {Zapper, TrustedEvent, RelayProfile} from "@welshman/util"
|
||||||
@@ -50,47 +61,34 @@ const syncEvents = async () => {
|
|||||||
|
|
||||||
repository.load(initialEvents)
|
repository.load(initialEvents)
|
||||||
|
|
||||||
|
const metaKinds = [
|
||||||
|
PROFILE,
|
||||||
|
FOLLOWS,
|
||||||
|
MUTES,
|
||||||
|
RELAYS,
|
||||||
|
BLOSSOM_SERVERS,
|
||||||
|
INBOX_RELAYS,
|
||||||
|
APP_DATA,
|
||||||
|
ROOMS,
|
||||||
|
]
|
||||||
|
const alertKinds = [ALERT_STATUS, ALERT_EMAIL, ALERT_WEB, ALERT_IOS, ALERT_ANDROID]
|
||||||
|
const spaceKinds = [RELAY_ADD_MEMBER, RELAY_REMOVE_MEMBER, RELAY_MEMBERS, RELAY_JOIN, RELAY_LEAVE]
|
||||||
|
const roomKinds = [
|
||||||
|
ROOM_META,
|
||||||
|
ROOM_MEMBERS,
|
||||||
|
ROOM_ADD_MEMBER,
|
||||||
|
ROOM_REMOVE_MEMBER,
|
||||||
|
ROOM_CREATE_PERMISSION,
|
||||||
|
]
|
||||||
|
const contentKinds = [EVENT_TIME, THREAD, MESSAGE, ZAP_GOAL, DIRECT_MESSAGE, DIRECT_MESSAGE_FILE]
|
||||||
|
|
||||||
const rankEvent = (event: TrustedEvent) => {
|
const rankEvent = (event: TrustedEvent) => {
|
||||||
switch (event.kind) {
|
if (metaKinds.includes(event.kind)) return 9
|
||||||
case PROFILE:
|
if (alertKinds.includes(event.kind)) return 8
|
||||||
return 1
|
if (spaceKinds.includes(event.kind)) return 7
|
||||||
case FOLLOWS:
|
if (roomKinds.includes(event.kind)) return 6
|
||||||
return 1
|
if (contentKinds.includes(event.kind)) return 5
|
||||||
case MUTES:
|
return 0
|
||||||
return 1
|
|
||||||
case RELAYS:
|
|
||||||
return 1
|
|
||||||
case BLOSSOM_SERVERS:
|
|
||||||
return 1
|
|
||||||
case INBOX_RELAYS:
|
|
||||||
return 1
|
|
||||||
case ROOMS:
|
|
||||||
return 1
|
|
||||||
case APP_DATA:
|
|
||||||
return 1
|
|
||||||
case ALERT_STATUS:
|
|
||||||
return 1
|
|
||||||
case ALERT_EMAIL:
|
|
||||||
return 1
|
|
||||||
case ALERT_WEB:
|
|
||||||
return 1
|
|
||||||
case ALERT_IOS:
|
|
||||||
return 1
|
|
||||||
case ALERT_ANDROID:
|
|
||||||
return 1
|
|
||||||
case EVENT_TIME:
|
|
||||||
return 0.9
|
|
||||||
case THREAD:
|
|
||||||
return 0.9
|
|
||||||
case MESSAGE:
|
|
||||||
return 0.9
|
|
||||||
case DIRECT_MESSAGE:
|
|
||||||
return 0.9
|
|
||||||
case DIRECT_MESSAGE_FILE:
|
|
||||||
return 0.9
|
|
||||||
default:
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return on(
|
return on(
|
||||||
|
|||||||
@@ -9,21 +9,14 @@
|
|||||||
import {dev} from "$app/environment"
|
import {dev} from "$app/environment"
|
||||||
import {goto} from "$app/navigation"
|
import {goto} from "$app/navigation"
|
||||||
import {sync} from "@welshman/store"
|
import {sync} from "@welshman/store"
|
||||||
import {call, on, spec} from "@welshman/lib"
|
import {call, spec} from "@welshman/lib"
|
||||||
import {defaultSocketPolicies} from "@welshman/net"
|
import {defaultSocketPolicies} from "@welshman/net"
|
||||||
import {
|
import {pubkey, sessions, signerLog, shouldUnwrap, SignerLogEntryStatus} from "@welshman/app"
|
||||||
repository,
|
|
||||||
pubkey,
|
|
||||||
sessions,
|
|
||||||
signerLog,
|
|
||||||
shouldUnwrap,
|
|
||||||
loadRelaySelections,
|
|
||||||
SignerLogEntryStatus,
|
|
||||||
} from "@welshman/app"
|
|
||||||
import * as lib from "@welshman/lib"
|
import * as lib from "@welshman/lib"
|
||||||
import * as util from "@welshman/util"
|
import * as util from "@welshman/util"
|
||||||
import * as feeds from "@welshman/feeds"
|
import * as feeds from "@welshman/feeds"
|
||||||
import * as router from "@welshman/router"
|
import * as router from "@welshman/router"
|
||||||
|
import * as store from "@welshman/store"
|
||||||
import * as welshmanSigner from "@welshman/signer"
|
import * as welshmanSigner from "@welshman/signer"
|
||||||
import * as net from "@welshman/net"
|
import * as net from "@welshman/net"
|
||||||
import * as app from "@welshman/app"
|
import * as app from "@welshman/app"
|
||||||
@@ -58,6 +51,7 @@
|
|||||||
...lib,
|
...lib,
|
||||||
...welshmanSigner,
|
...welshmanSigner,
|
||||||
...router,
|
...router,
|
||||||
|
...store,
|
||||||
...util,
|
...util,
|
||||||
...feeds,
|
...feeds,
|
||||||
...net,
|
...net,
|
||||||
@@ -128,15 +122,6 @@
|
|||||||
// History, navigation, bug tracking, application data
|
// History, navigation, bug tracking, application data
|
||||||
unsubscribers.push(setupHistory(), setupAnalytics(), setupTracking(), syncApplicationData())
|
unsubscribers.push(setupHistory(), setupAnalytics(), setupTracking(), syncApplicationData())
|
||||||
|
|
||||||
// Whenever we see a new pubkey, load their outbox event
|
|
||||||
unsubscribers.push(
|
|
||||||
on(repository, "update", ({added}) => {
|
|
||||||
for (const event of added) {
|
|
||||||
loadRelaySelections(event.pubkey)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Subscribe to badge count for changes
|
// Subscribe to badge count for changes
|
||||||
unsubscribers.push(notifications.badgeCount.subscribe(notifications.handleBadgeCountChanges))
|
unsubscribers.push(notifications.badgeCount.subscribe(notifications.handleBadgeCountChanges))
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import {readable} from "svelte/store"
|
import {readable} from "svelte/store"
|
||||||
import {onMount, onDestroy} from "svelte"
|
import {onMount, onDestroy} from "svelte"
|
||||||
import {page} from "$app/stores"
|
import {page} from "$app/stores"
|
||||||
|
import {goto} from "$app/navigation"
|
||||||
import type {Readable} from "svelte/store"
|
import type {Readable} from "svelte/store"
|
||||||
import type {MakeNonOptional} from "@welshman/lib"
|
import type {MakeNonOptional} from "@welshman/lib"
|
||||||
import {now, formatTimestampAsDate, ago, MINUTE} from "@welshman/lib"
|
import {now, formatTimestampAsDate, ago, MINUTE} from "@welshman/lib"
|
||||||
@@ -14,11 +15,20 @@
|
|||||||
ROOM_ADD_MEMBER,
|
ROOM_ADD_MEMBER,
|
||||||
ROOM_REMOVE_MEMBER,
|
ROOM_REMOVE_MEMBER,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import {pubkey, publishThunk, waitForThunkError, joinRoom, leaveRoom} from "@welshman/app"
|
import {
|
||||||
|
pubkey,
|
||||||
|
publishThunk,
|
||||||
|
waitForThunkError,
|
||||||
|
deleteRoom,
|
||||||
|
joinRoom,
|
||||||
|
leaveRoom,
|
||||||
|
repository,
|
||||||
|
} from "@welshman/app"
|
||||||
import {slide, fade, fly} from "@lib/transition"
|
import {slide, fade, fly} from "@lib/transition"
|
||||||
import Hashtag from "@assets/icons/hashtag.svg?dataurl"
|
import Hashtag from "@assets/icons/hashtag.svg?dataurl"
|
||||||
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
|
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
|
||||||
import Login2 from "@assets/icons/login-3.svg?dataurl"
|
import Login2 from "@assets/icons/login-3.svg?dataurl"
|
||||||
|
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
|
||||||
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
|
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
|
||||||
import Logout2 from "@assets/icons/logout-3.svg?dataurl"
|
import Logout2 from "@assets/icons/logout-3.svg?dataurl"
|
||||||
import Bookmark from "@assets/icons/bookmark.svg?dataurl"
|
import Bookmark from "@assets/icons/bookmark.svg?dataurl"
|
||||||
@@ -28,6 +38,7 @@
|
|||||||
import PageBar from "@lib/components/PageBar.svelte"
|
import PageBar from "@lib/components/PageBar.svelte"
|
||||||
import PageContent from "@lib/components/PageContent.svelte"
|
import PageContent from "@lib/components/PageContent.svelte"
|
||||||
import Divider from "@lib/components/Divider.svelte"
|
import Divider from "@lib/components/Divider.svelte"
|
||||||
|
import Confirm from "@lib/components/Confirm.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 ChannelName from "@app/components/ChannelName.svelte"
|
import ChannelName from "@app/components/ChannelName.svelte"
|
||||||
@@ -46,6 +57,7 @@
|
|||||||
MembershipStatus,
|
MembershipStatus,
|
||||||
PROTECTED,
|
PROTECTED,
|
||||||
MESSAGE_KINDS,
|
MESSAGE_KINDS,
|
||||||
|
deriveUserIsRoomAdmin,
|
||||||
} from "@app/core/state"
|
} from "@app/core/state"
|
||||||
import {setChecked, checked} from "@app/util/notifications"
|
import {setChecked, checked} from "@app/util/notifications"
|
||||||
import {
|
import {
|
||||||
@@ -58,6 +70,8 @@
|
|||||||
import {makeFeed} from "@app/core/requests"
|
import {makeFeed} from "@app/core/requests"
|
||||||
import {popKey} from "@lib/implicit"
|
import {popKey} from "@lib/implicit"
|
||||||
import {pushToast} from "@app/util/toast"
|
import {pushToast} from "@app/util/toast"
|
||||||
|
import {pushModal} from "@app/util/modal"
|
||||||
|
import {makeSpacePath} from "@app/util/routes"
|
||||||
|
|
||||||
const {room, relay} = $page.params as MakeNonOptional<typeof $page.params>
|
const {room, relay} = $page.params as MakeNonOptional<typeof $page.params>
|
||||||
const mounted = now()
|
const mounted = now()
|
||||||
@@ -66,6 +80,7 @@
|
|||||||
const channel = deriveChannel(url, room)
|
const channel = deriveChannel(url, room)
|
||||||
const shouldProtect = canEnforceNip70(url)
|
const shouldProtect = canEnforceNip70(url)
|
||||||
const userRooms = deriveUserRooms(url)
|
const userRooms = deriveUserRooms(url)
|
||||||
|
const userIsAdmin = deriveUserIsRoomAdmin(url, room)
|
||||||
const isFavorite = $derived($userRooms.includes(room))
|
const isFavorite = $derived($userRooms.includes(room))
|
||||||
const membershipStatus = deriveUserRoomMembershipStatus(url, room)
|
const membershipStatus = deriveUserRoomMembershipStatus(url, room)
|
||||||
|
|
||||||
@@ -292,6 +307,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const startDelete = () =>
|
||||||
|
pushModal(Confirm, {
|
||||||
|
title: "Are you sure you want to delete this room?",
|
||||||
|
message:
|
||||||
|
"This room will no longer be accessible to space members, and all messages posted to it will be deleted.",
|
||||||
|
confirm: async () => {
|
||||||
|
const thunk = deleteRoom(url, makeRoomMeta({id: room}))
|
||||||
|
const message = await waitForThunkError(thunk)
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
repository.removeEvent(thunk.event.id)
|
||||||
|
pushToast({theme: "error", message})
|
||||||
|
} else {
|
||||||
|
goto(makeSpacePath(url))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const observer = new ResizeObserver(() => {
|
const observer = new ResizeObserver(() => {
|
||||||
if (dynamicPadding && chatCompose) {
|
if (dynamicPadding && chatCompose) {
|
||||||
@@ -332,7 +365,14 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet action()}
|
{#snippet action()}
|
||||||
<div class="row-2">
|
<div class="row-2">
|
||||||
{#if $membershipStatus === MembershipStatus.Initial}
|
{#if $userIsAdmin || true}
|
||||||
|
<Button
|
||||||
|
class="btn btn-neutral btn-sm tooltip tooltip-left"
|
||||||
|
data-tip="Delete this room"
|
||||||
|
onclick={startDelete}>
|
||||||
|
<Icon size={4} icon={TrashBin2} />
|
||||||
|
</Button>
|
||||||
|
{:else if $membershipStatus === MembershipStatus.Initial}
|
||||||
<Button
|
<Button
|
||||||
class="btn btn-neutral btn-sm tooltip tooltip-left"
|
class="btn btn-neutral btn-sm tooltip tooltip-left"
|
||||||
data-tip="Request to be added to the member list"
|
data-tip="Request to be added to the member list"
|
||||||
|
|||||||
Reference in New Issue
Block a user