diff --git a/.ackrc b/.ackrc
index 7811c3c8..1435106f 100644
--- a/.ackrc
+++ b/.ackrc
@@ -1,5 +1,6 @@
--ignore-dir=.svelte-kit
--ignore-dir=android
+--ignore-dir=target
--ignore-dir=build
--ignore-dir=ios/DerivedData
--ignore-dir=ios/App/App/public
diff --git a/src/app/components/SpaceMembers.svelte b/src/app/components/SpaceMembers.svelte
index b0491474..9d535b98 100644
--- a/src/app/components/SpaceMembers.svelte
+++ b/src/app/components/SpaceMembers.svelte
@@ -2,6 +2,7 @@
import {ManagementMethod} from "@welshman/util"
import {manageRelay, displayProfileByPubkey} from "@welshman/app"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
+ import UserMinus from "@assets/icons/user-minus.svg?dataurl"
import MinusCircle from "@assets/icons/minus-circle.svg?dataurl"
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
@@ -24,6 +25,7 @@
deriveSpaceMembers,
deriveSpaceBannedPubkeyItems,
deriveUserIsSpaceAdmin,
+ deriveSupportedMethods,
} from "@app/core/state"
import {pushModal} from "@app/util/modal"
import {pushToast} from "@app/util/toast"
@@ -37,6 +39,9 @@
const members = deriveSpaceMembers(url)
const bans = deriveSpaceBannedPubkeyItems(url)
const userIsAdmin = deriveUserIsSpaceAdmin(url)
+ const supportedMethods = deriveSupportedMethods(url)
+ const canBan = $derived($supportedMethods.includes(ManagementMethod.BanPubkey))
+ const canUnallow = $derived($supportedMethods.includes(ManagementMethod.UnallowPubkey))
const back = () => history.back()
@@ -52,6 +57,25 @@
const addMember = () => pushModal(SpaceMembersAdd, {url})
+ const unallowMember = (pubkey: string) =>
+ pushModal(Confirm, {
+ title: "Remove User",
+ message: `Are you sure you want to remove @${displayProfileByPubkey(pubkey)} from the space?`,
+ confirm: async () => {
+ const {error} = await manageRelay(url, {
+ method: ManagementMethod.UnallowPubkey,
+ params: [pubkey],
+ })
+
+ if (error) {
+ pushToast({theme: "error", message: error})
+ } else {
+ pushToast({message: "User has successfully been removed!"})
+ back()
+ }
+ },
+ })
+
const banMember = (pubkey: string) =>
pushModal(Confirm, {
title: "Ban User",
@@ -94,25 +118,37 @@
-
-
- {#if menuPubkey === pubkey}
-
-
- -
-
-
-
-
- {/if}
-
+ {#if canBan || canUnallow}
+
+
+ {#if menuPubkey === pubkey}
+
+
+ {#if canUnallow}
+ -
+
+
+ {/if}
+ {#if canBan}
+ -
+
+
+ {/if}
+
+
+ {/if}
+
+ {/if}
{/each}
diff --git a/src/app/components/SpaceMembersBanned.svelte b/src/app/components/SpaceMembersBanned.svelte
index 755da7c7..2fda4adf 100644
--- a/src/app/components/SpaceMembersBanned.svelte
+++ b/src/app/components/SpaceMembersBanned.svelte
@@ -3,6 +3,7 @@
import {manageRelay} from "@welshman/app"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import Restart from "@assets/icons/restart.svg?dataurl"
+ import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import {fly} from "@lib/transition"
import Button from "@lib/components/Button.svelte"
@@ -15,7 +16,7 @@
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Profile from "@app/components/Profile.svelte"
- import {deriveSpaceBannedPubkeyItems} from "@app/core/state"
+ import {deriveSpaceBannedPubkeyItems, deriveSupportedMethods} from "@app/core/state"
import {pushToast} from "@app/util/toast"
interface Props {
@@ -25,6 +26,9 @@
const {url}: Props = $props()
const bans = deriveSpaceBannedPubkeyItems(url)
+ const supportedMethods = deriveSupportedMethods(url)
+ const canUnban = $derived($supportedMethods.includes(ManagementMethod.UnbanPubkey))
+ const canRestore = $derived($supportedMethods.includes(ManagementMethod.AllowPubkey))
const back = () => history.back()
@@ -36,6 +40,20 @@
menuPubkey = undefined
}
+ const unbanMember = async (pubkey: string) => {
+ const {error} = await manageRelay(url, {
+ method: ManagementMethod.UnbanPubkey,
+ params: [pubkey],
+ })
+
+ if (error) {
+ pushToast({theme: "error", message: error})
+ } else {
+ pushToast({message: "User has successfully been removed from the ban list!"})
+ back()
+ }
+ }
+
const restoreMember = async (pubkey: string) => {
const {error} = await manageRelay(url, {
method: ManagementMethod.AllowPubkey,
@@ -45,7 +63,7 @@
if (error) {
pushToast({theme: "error", message: error})
} else {
- pushToast({message: "User has successfully been restored!"})
+ pushToast({message: "User has successfully been restored to membership!"})
back()
}
}
@@ -66,25 +84,37 @@
-
-
- {#if menuPubkey === pubkey}
-
-
- -
-
-
-
-
- {/if}
-
+ {#if canUnban || canRestore}
+
+
+ {#if menuPubkey === pubkey}
+
+
+ {#if canUnban}
+ -
+
+
+ {/if}
+ {#if canRestore}
+ -
+
+
+ {/if}
+
+
+ {/if}
+
+ {/if}
{/each}
diff --git a/src/app/core/state.ts b/src/app/core/state.ts
index 76938495..3ce4a135 100644
--- a/src/app/core/state.ts
+++ b/src/app/core/state.ts
@@ -29,6 +29,7 @@ import {
fromPairs,
groupBy,
remove,
+ simpleCache,
} from "@welshman/lib"
import type {Override} from "@welshman/lib"
import type {RepositoryUpdate} from "@welshman/net"
@@ -1124,6 +1125,15 @@ export const deriveSocketStatus = (url: string) =>
}),
)
+export const deriveSupportedMethods = simpleCache(([url]: [string]) => {
+ return readable([], set => {
+ manageRelay(url, {
+ method: ManagementMethod.SupportedMethods,
+ params: [],
+ }).then(({result = []}) => set(result))
+ })
+})
+
export const deriveTimeout = (timeout: number) => {
const store = writable(false)