Render the desktop and mobile space menus from one SpaceMenuActions and let SpaceEdit read the relay from its url
This commit is contained in:
parent
8f9ff3a366
commit
8d0c73b364
4 changed files with 71 additions and 161 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {displayRelayUrl} from "@welshman/util"
|
import {displayRelayUrl} from "@welshman/util"
|
||||||
import type {RelayInfo} from "@welshman/domain"
|
|
||||||
import Widget from "@assets/icons/widget-4.svg?dataurl"
|
import Widget from "@assets/icons/widget-4.svg?dataurl"
|
||||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||||
import {preventDefault} from "@lib/html"
|
import {preventDefault} from "@lib/html"
|
||||||
|
|
@ -23,19 +22,20 @@
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
initialValues: Partial<RelayInfo>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const {url, initialValues = {}}: Props = $props()
|
const {url}: Props = $props()
|
||||||
|
|
||||||
const values = $state({...initialValues})
|
const relay = $relays.get(url)
|
||||||
|
|
||||||
|
const values = $state({name: relay?.name, description: relay?.description})
|
||||||
|
|
||||||
const compressOptions = {maxWidth: 128, maxHeight: 128}
|
const compressOptions = {maxWidth: 128, maxHeight: 128}
|
||||||
|
|
||||||
const back = () => history.back()
|
const back = () => history.back()
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
if (values.name != initialValues.name) {
|
if (values.name != relay?.name) {
|
||||||
const res = await $relayManagement.forUrl(url).changeRelayName(values.name || "")
|
const res = await $relayManagement.forUrl(url).changeRelayName(values.name || "")
|
||||||
|
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.description != initialValues.description) {
|
if (values.description != relay?.description) {
|
||||||
const res = await $relayManagement
|
const res = await $relayManagement
|
||||||
.forUrl(url)
|
.forUrl(url)
|
||||||
.changeRelayDescription(values.description || "")
|
.changeRelayDescription(values.description || "")
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
const icon = await resolveImageInput(imageFile, imagePreview, compressOptions)
|
const icon = await resolveImageInput(imageFile, imagePreview, compressOptions)
|
||||||
|
|
||||||
if (icon && icon !== initialValues.icon) {
|
if (icon && icon !== relay?.icon) {
|
||||||
const res = await $relayManagement.forUrl(url).changeRelayIcon(icon)
|
const res = await $relayManagement.forUrl(url).changeRelayIcon(icon)
|
||||||
|
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
|
|
||||||
let loading = $state(false)
|
let loading = $state(false)
|
||||||
let imageFile = $state<File | undefined>()
|
let imageFile = $state<File | undefined>()
|
||||||
let imagePreview = $state(initialValues.icon)
|
let imagePreview = $state(relay?.icon)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal tag="form" onsubmit={preventDefault(trySubmit)}>
|
<Modal tag="form" onsubmit={preventDefault(trySubmit)}>
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,10 @@
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
|
sheet?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const {url}: Props = $props()
|
const {url, sheet = false}: Props = $props()
|
||||||
|
|
||||||
const relay = $relays.one(url)
|
const relay = $relays.one(url)
|
||||||
const permissions = deriveSpacePermissions(url)
|
const permissions = deriveSpacePermissions(url)
|
||||||
|
|
@ -38,17 +39,17 @@
|
||||||
const actionItems = deriveSpaceActionItems(url)
|
const actionItems = deriveSpaceActionItems(url)
|
||||||
const shouldNotify = deriveShouldNotify(url)
|
const shouldNotify = deriveShouldNotify(url)
|
||||||
|
|
||||||
const createInvite = () => pushModal(SpaceInvite, {url})
|
const createInvite = () => pushModal(SpaceInvite, {url}, {replaceState: sheet})
|
||||||
|
|
||||||
const startEdit = () => pushModal(SpaceEdit, {url, initialValues: $relay || {url}})
|
const startEdit = () => pushModal(SpaceEdit, {url}, {replaceState: sheet})
|
||||||
|
|
||||||
const leaveSpace = () => pushModal(SpaceExit, {url})
|
const leaveSpace = () => pushModal(SpaceExit, {url}, {replaceState: sheet})
|
||||||
|
|
||||||
const joinSpace = () => pushModal(SpaceJoin, {url})
|
const joinSpace = () => pushModal(SpaceJoin, {url}, {replaceState: sheet})
|
||||||
|
|
||||||
const showActionItems = () => pushModal(SpaceActionItems, {url})
|
const showActionItems = () => pushModal(SpaceActionItems, {url}, {replaceState: sheet})
|
||||||
|
|
||||||
const contactOwner = () => goToChat([$relay!.pubkey!])
|
const contactOwner = () => goToChat([$relay!.pubkey!], {replaceState: sheet})
|
||||||
|
|
||||||
const toggleSpaceNotifications = () => {
|
const toggleSpaceNotifications = () => {
|
||||||
popModal()
|
popModal()
|
||||||
|
|
@ -61,7 +62,23 @@
|
||||||
icon: string,
|
icon: string,
|
||||||
label: string,
|
label: string,
|
||||||
variant?: "error" | "primary",
|
variant?: "error" | "primary",
|
||||||
|
dot?: boolean,
|
||||||
)}
|
)}
|
||||||
|
{#if sheet}
|
||||||
|
<Button
|
||||||
|
class={cx("button w-full justify-start", {
|
||||||
|
"button-neutral": !variant,
|
||||||
|
"button-error": variant === "error",
|
||||||
|
"button-primary": variant === "primary",
|
||||||
|
})}
|
||||||
|
{onclick}>
|
||||||
|
<Icon size={4} {icon} />
|
||||||
|
{label}
|
||||||
|
{#if dot}
|
||||||
|
<div class="h-2 w-2 rounded-full bg-primary text-primary-content"></div>
|
||||||
|
{/if}
|
||||||
|
</Button>
|
||||||
|
{:else}
|
||||||
<li>
|
<li>
|
||||||
<Button
|
<Button
|
||||||
{onclick}
|
{onclick}
|
||||||
|
|
@ -72,22 +89,40 @@
|
||||||
style={variant === "primary" ? "color: var(--primary-content)" : undefined}>
|
style={variant === "primary" ? "color: var(--primary-content)" : undefined}>
|
||||||
<Icon {icon} />
|
<Icon {icon} />
|
||||||
{label}
|
{label}
|
||||||
</Button>
|
{#if dot}
|
||||||
</li>
|
|
||||||
{/snippet}
|
|
||||||
|
|
||||||
{@render actionButton(createInvite, LinkRound, "Create Invite")}
|
|
||||||
{#if $permissions.review}
|
|
||||||
<li>
|
|
||||||
<Button onclick={showActionItems}>
|
|
||||||
<Icon icon={Danger} />
|
|
||||||
Action Items ({$actionItems.length})
|
|
||||||
{#if $actionItems.length > 0}
|
|
||||||
<div class="h-2 w-2 rounded-full bg-primary text-primary-content"></div>
|
<div class="h-2 w-2 rounded-full bg-primary text-primary-content"></div>
|
||||||
{/if}
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
{/if}
|
{/if}
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{#snippet actionLink(href: string, icon: string, label: string)}
|
||||||
|
{#if sheet}
|
||||||
|
<Link {href} class="button button-neutral w-full justify-start">
|
||||||
|
<Icon size={4} {icon} />
|
||||||
|
{label}
|
||||||
|
</Link>
|
||||||
|
{:else}
|
||||||
|
<li>
|
||||||
|
<Link {href}>
|
||||||
|
<Icon {icon} />
|
||||||
|
{label}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{@render actionButton(createInvite, LinkRound, "Create Invite")}
|
||||||
|
{#if $permissions.review}
|
||||||
|
{@render actionButton(
|
||||||
|
showActionItems,
|
||||||
|
Danger,
|
||||||
|
`Action Items (${$actionItems.length})`,
|
||||||
|
undefined,
|
||||||
|
$actionItems.length > 0,
|
||||||
|
)}
|
||||||
|
{/if}
|
||||||
{#if $relay?.pubkey && $relay.pubkey !== $user.pubkey}
|
{#if $relay?.pubkey && $relay.pubkey !== $user.pubkey}
|
||||||
{@render actionButton(contactOwner, Letter, "Contact Owner")}
|
{@render actionButton(contactOwner, Letter, "Contact Owner")}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -98,20 +133,10 @@
|
||||||
`${$shouldNotify ? "Turn off" : "Turn on"} notifications`,
|
`${$shouldNotify ? "Turn off" : "Turn on"} notifications`,
|
||||||
)}
|
)}
|
||||||
{:else}
|
{:else}
|
||||||
<li>
|
{@render actionLink("/settings/alerts", Bell, "Enable notifications")}
|
||||||
<Link href="/settings/alerts">
|
|
||||||
<Icon icon={Bell} />
|
|
||||||
Enable notifications
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
{/if}
|
{/if}
|
||||||
{#if HOSTING_ENABLED && $hostedRelay.relay}
|
{#if HOSTING_ENABLED && $hostedRelay.relay}
|
||||||
<li>
|
{@render actionLink(makeSpacePath(url, "admin"), ServerPath, "Hosting settings")}
|
||||||
<Link href={makeSpacePath(url, "admin")}>
|
|
||||||
<Icon icon={ServerPath} />
|
|
||||||
Hosting settings
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
{:else if $permissions.editSpace}
|
{:else if $permissions.editSpace}
|
||||||
{@render actionButton(startEdit, Pen, "Edit Space")}
|
{@render actionButton(startEdit, Pen, "Edit Space")}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import cx from "classnames"
|
|
||||||
import Danger from "@assets/icons/danger.svg?dataurl"
|
|
||||||
import ServerPath from "@assets/icons/server-path.svg?dataurl"
|
|
||||||
import LinkRound from "@assets/icons/link-round.svg?dataurl"
|
|
||||||
import Pen from "@assets/icons/pen.svg?dataurl"
|
|
||||||
import Exit from "@assets/icons/logout-3.svg?dataurl"
|
|
||||||
import Letter from "@assets/icons/letter.svg?dataurl"
|
|
||||||
import Login from "@assets/icons/login-3.svg?dataurl"
|
|
||||||
import Bell from "@assets/icons/bell.svg?dataurl"
|
|
||||||
import BellOff from "@assets/icons/bell-off.svg?dataurl"
|
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
|
||||||
import Link from "@lib/components/Link.svelte"
|
|
||||||
import Button from "@lib/components/Button.svelte"
|
|
||||||
import SpaceInvite from "@app/components/SpaceInvite.svelte"
|
|
||||||
import SpaceExit from "@app/components/SpaceExit.svelte"
|
|
||||||
import SpaceEdit from "@app/components/SpaceEdit.svelte"
|
|
||||||
import SpaceJoin from "@app/components/SpaceJoin.svelte"
|
|
||||||
import SpaceActionItems from "@app/components/SpaceActionItems.svelte"
|
|
||||||
import {relays, user} from "@app/core"
|
|
||||||
import {deriveHostedRelay, HOSTING_ENABLED} from "@app/hosting"
|
|
||||||
import {deriveSpacePermissions} from "@app/management"
|
|
||||||
import {userSpaceUrls} from "@app/rooms"
|
|
||||||
import {deriveSpaceActionItems} from "@app/actionItems"
|
|
||||||
import {notificationSettings, deriveShouldNotify, setSpaceNotifications} from "@app/settings"
|
|
||||||
import {pushModal, popModal} from "@app/modal"
|
|
||||||
import {makeSpacePath, goToChat} from "@app/routes"
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
url: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const {url}: Props = $props()
|
|
||||||
|
|
||||||
const relay = $relays.one(url)
|
|
||||||
const permissions = deriveSpacePermissions(url)
|
|
||||||
const hostedRelay = deriveHostedRelay(url)
|
|
||||||
const actionItems = deriveSpaceActionItems(url)
|
|
||||||
const shouldNotify = deriveShouldNotify(url)
|
|
||||||
|
|
||||||
const createInvite = () => pushModal(SpaceInvite, {url}, {replaceState: true})
|
|
||||||
|
|
||||||
const startEdit = () =>
|
|
||||||
pushModal(SpaceEdit, {url, initialValues: $relay || {url}}, {replaceState: true})
|
|
||||||
|
|
||||||
const leaveSpace = () => pushModal(SpaceExit, {url}, {replaceState: true})
|
|
||||||
|
|
||||||
const joinSpace = () => pushModal(SpaceJoin, {url}, {replaceState: true})
|
|
||||||
|
|
||||||
const showActionItems = () => pushModal(SpaceActionItems, {url}, {replaceState: true})
|
|
||||||
|
|
||||||
const contactOwner = () => goToChat([$relay!.pubkey!], {replaceState: true})
|
|
||||||
|
|
||||||
const toggleSpaceNotifications = () => {
|
|
||||||
popModal()
|
|
||||||
setSpaceNotifications(url, !$shouldNotify)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#snippet actionButton(
|
|
||||||
onclick: () => void,
|
|
||||||
icon: string,
|
|
||||||
label: string,
|
|
||||||
variant?: "error" | "primary",
|
|
||||||
)}
|
|
||||||
<Button
|
|
||||||
class={cx("button w-full justify-start", {
|
|
||||||
"button-neutral": !variant,
|
|
||||||
"button-error": variant === "error",
|
|
||||||
"button-primary": variant === "primary",
|
|
||||||
})}
|
|
||||||
{onclick}>
|
|
||||||
<Icon size={4} {icon} />
|
|
||||||
{label}
|
|
||||||
</Button>
|
|
||||||
{/snippet}
|
|
||||||
|
|
||||||
{@render actionButton(createInvite, LinkRound, "Create Invite")}
|
|
||||||
{#if $permissions.review}
|
|
||||||
<Button class="button button-neutral w-full justify-start" onclick={showActionItems}>
|
|
||||||
<Icon size={4} icon={Danger} />
|
|
||||||
Action Items ({$actionItems.length})
|
|
||||||
{#if $actionItems.length > 0}
|
|
||||||
<div class="h-2 w-2 rounded-full bg-primary text-primary-content"></div>
|
|
||||||
{/if}
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
{#if $relay?.pubkey && $relay.pubkey !== $user.pubkey}
|
|
||||||
{@render actionButton(contactOwner, Letter, "Contact Owner")}
|
|
||||||
{/if}
|
|
||||||
{#if $notificationSettings.push}
|
|
||||||
{@render actionButton(
|
|
||||||
toggleSpaceNotifications,
|
|
||||||
$shouldNotify ? Bell : BellOff,
|
|
||||||
`${$shouldNotify ? "Turn off" : "Turn on"} notifications`,
|
|
||||||
)}
|
|
||||||
{:else}
|
|
||||||
<Link href="/settings/alerts" class="button button-neutral w-full justify-start">
|
|
||||||
<Icon size={4} icon={Bell} />
|
|
||||||
Enable notifications
|
|
||||||
</Link>
|
|
||||||
{/if}
|
|
||||||
{#if HOSTING_ENABLED && $hostedRelay.relay}
|
|
||||||
<Link href={makeSpacePath(url, "admin")} class="button button-neutral w-full justify-start">
|
|
||||||
<Icon size={4} icon={ServerPath} />
|
|
||||||
Hosting settings
|
|
||||||
</Link>
|
|
||||||
{:else if $permissions.editSpace}
|
|
||||||
{@render actionButton(startEdit, Pen, "Edit Space")}
|
|
||||||
{/if}
|
|
||||||
{#if $userSpaceUrls.includes(url)}
|
|
||||||
{@render actionButton(leaveSpace, Exit, "Leave Space", "error")}
|
|
||||||
{:else}
|
|
||||||
{@render actionButton(joinSpace, Login, "Join Space", "primary")}
|
|
||||||
{/if}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Modal from "@lib/components/Modal.svelte"
|
import Modal from "@lib/components/Modal.svelte"
|
||||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||||
import SpaceMenuActionsMobile from "@app/components/SpaceMenuActionsMobile.svelte"
|
import SpaceMenuActions from "@app/components/SpaceMenuActions.svelte"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<Modal label="Space menu">
|
<Modal label="Space menu">
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<SpaceMenuActionsMobile {url} />
|
<SpaceMenuActions sheet {url} />
|
||||||
</div>
|
</div>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue