forked from coracle/flotilla
Detect nip29 properly before choosing smart path, more robust auth error checking
This commit is contained in:
@@ -4,9 +4,15 @@
|
||||
import Dialog from "@lib/components/Dialog.svelte"
|
||||
import {modal, clearModals} from "@app/util/modal"
|
||||
|
||||
const closeModals = () => {
|
||||
if ($modal && !$modal.options.noEscape) {
|
||||
clearModals()
|
||||
}
|
||||
}
|
||||
|
||||
const onKeyDown = (e: any) => {
|
||||
if (e.code === "Escape" && e.target === document.body) {
|
||||
clearModals()
|
||||
closeModals()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +33,7 @@
|
||||
instance = mount(wrapper as any, {
|
||||
target: element,
|
||||
props: {
|
||||
onClose: clearModals,
|
||||
onClose: closeModals,
|
||||
children: createRawSnippet(() => ({
|
||||
render: () => "<div></div>",
|
||||
setup: (target: Element) => {
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
<script lang="ts">
|
||||
import {goto} from "$app/navigation"
|
||||
import {displayRelayUrl} from "@welshman/util"
|
||||
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
|
||||
import SpaceAvatar from "@app/components/SpaceAvatar.svelte"
|
||||
import {encodeRelay} from "@app/core/state"
|
||||
import {makeSpacePath} from "@app/util/routes"
|
||||
import {lastPageBySpaceUrl} from "@app/util/history"
|
||||
import {makeSpacePath, goToSpace} from "@app/util/routes"
|
||||
import {notifications} from "@app/util/notifications"
|
||||
|
||||
const {url} = $props()
|
||||
|
||||
const path = makeSpacePath(url)
|
||||
|
||||
const onClick = () => goto(lastPageBySpaceUrl.get(encodeRelay(url)) || path)
|
||||
const onClick = () => goToSpace(url)
|
||||
</script>
|
||||
|
||||
<PrimaryNavItem
|
||||
onclick={onClick}
|
||||
title={displayRelayUrl(url)}
|
||||
class="tooltip-right"
|
||||
notification={$notifications.has(path)}>
|
||||
notification={$notifications.has(makeSpacePath(url))}>
|
||||
<SpaceAvatar {url} />
|
||||
</PrimaryNavItem>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {goto} from "$app/navigation"
|
||||
import {displayRelayUrl} from "@welshman/util"
|
||||
import {parse, renderAsHtml} from "@welshman/content"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
@@ -14,7 +15,7 @@
|
||||
|
||||
const {url, error} = $props()
|
||||
|
||||
const back = () => history.back()
|
||||
const back = () => goto("/home")
|
||||
|
||||
const requestAccess = () => pushModal(SpaceAccessRequest, {url})
|
||||
</script>
|
||||
@@ -37,7 +38,7 @@
|
||||
<ModalFooter>
|
||||
<Button class="btn btn-link" onclick={back}>
|
||||
<Icon icon={AltArrowLeft} />
|
||||
Go back
|
||||
Go Home
|
||||
</Button>
|
||||
<Button type="submit" class="btn btn-primary">
|
||||
Request Access
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {sleep, nthEq} from "@welshman/lib"
|
||||
import {sleep} from "@welshman/lib"
|
||||
import {request} from "@welshman/net"
|
||||
import {displayRelayUrl, RELAY_INVITE} from "@welshman/util"
|
||||
import {displayRelayUrl, getTagValue, RELAY_INVITE} from "@welshman/util"
|
||||
import LinkRound from "@assets/icons/link-round.svg?dataurl"
|
||||
import Copy from "@assets/icons/copy.svg?dataurl"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
@@ -13,10 +13,12 @@
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import QRCode from "@app/components/QRCode.svelte"
|
||||
import {clip} from "@app/util/toast"
|
||||
import {PLATFORM_URL} from "@app/core/state"
|
||||
import {PLATFORM_URL, deriveRelayAuthError} from "@app/core/state"
|
||||
|
||||
const {url} = $props()
|
||||
|
||||
const authError = deriveRelayAuthError(url)
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
const copyInvite = () => clip(invite)
|
||||
@@ -38,12 +40,13 @@
|
||||
request({
|
||||
relays: [url],
|
||||
autoClose: true,
|
||||
signal: AbortSignal.timeout(3000),
|
||||
filters: [{kinds: [RELAY_INVITE]}],
|
||||
}),
|
||||
sleep(2000),
|
||||
])
|
||||
|
||||
claim = event?.tags.find(nthEq(0, "claim"))?.[1] || ""
|
||||
claim = getTagValue("claim", event?.tags || []) || ""
|
||||
loading = false
|
||||
})
|
||||
</script>
|
||||
@@ -65,6 +68,8 @@
|
||||
<p class="center">
|
||||
<Spinner {loading}>Requesting an invite link...</Spinner>
|
||||
</p>
|
||||
{:else if $authError}
|
||||
<p class="center">Oops! It looks like you're not a member of this relay.</p>
|
||||
{:else}
|
||||
<div class="flex flex-col items-center gap-6">
|
||||
<QRCode code={invite} />
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
try {
|
||||
await removeSpaceMembership(url)
|
||||
await removeTrustedRelay(url)
|
||||
goto("/")
|
||||
goto("/home")
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
|
||||
@@ -982,8 +982,8 @@ export const deriveRelayAuthError = (url: string, claim = "") => {
|
||||
})
|
||||
|
||||
return derived(
|
||||
[relaysMostlyRestricted, deriveSocket(url)],
|
||||
([$relaysMostlyRestricted, $socket]) => {
|
||||
[thunk, relaysMostlyRestricted, deriveSocket(url)],
|
||||
([$thunk, $relaysMostlyRestricted, $socket]) => {
|
||||
if ($socket.auth.status === AuthStatus.Forbidden && $socket.auth.details) {
|
||||
return stripPrefix($socket.auth.details)
|
||||
}
|
||||
@@ -992,7 +992,7 @@ export const deriveRelayAuthError = (url: string, claim = "") => {
|
||||
return stripPrefix($relaysMostlyRestricted[url])
|
||||
}
|
||||
|
||||
const error = getThunkError(thunk)
|
||||
const error = getThunkError($thunk)
|
||||
|
||||
if (error) {
|
||||
const isEmptyInvite = !claim && error.includes("invite code")
|
||||
|
||||
@@ -6,6 +6,7 @@ import {page} from "$app/stores"
|
||||
|
||||
export type ModalOptions = {
|
||||
drawer?: boolean
|
||||
noEscape?: boolean
|
||||
fullscreen?: boolean
|
||||
replaceState?: boolean
|
||||
path?: string
|
||||
|
||||
@@ -62,11 +62,10 @@ export const mostlyRestrictedPolicy = (socket: Socket) => {
|
||||
|
||||
const pending = new Set<string>()
|
||||
|
||||
const updateStatus = () => {
|
||||
const updateStatus = () =>
|
||||
relaysMostlyRestricted.update(
|
||||
restricted > total / 2 ? assoc(socket.url, error) : dissoc(socket.url),
|
||||
)
|
||||
}
|
||||
|
||||
const unsubscribers = [
|
||||
on(socket, SocketEvent.Receive, (message: RelayMessage) => {
|
||||
|
||||
+14
-9
@@ -4,7 +4,7 @@ import * as nip19 from "nostr-tools/nip19"
|
||||
import {goto} from "$app/navigation"
|
||||
import {nthEq, sleep} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {tracker, relaysByUrl} from "@welshman/app"
|
||||
import {tracker, loadRelay} from "@welshman/app"
|
||||
import {scrollToEvent} from "@lib/html"
|
||||
import {identity} from "@welshman/lib"
|
||||
import {
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
hasNip29,
|
||||
ROOM,
|
||||
} from "@app/core/state"
|
||||
import {lastPageBySpaceUrl} from "@app/util/history"
|
||||
|
||||
export const makeSpacePath = (url: string, ...extra: (string | undefined)[]) => {
|
||||
let path = `/spaces/${encodeRelay(url)}`
|
||||
@@ -37,19 +38,23 @@ export const makeSpacePath = (url: string, ...extra: (string | undefined)[]) =>
|
||||
.filter(identity)
|
||||
.map(s => encodeURIComponent(s as string))
|
||||
.join("/")
|
||||
} else {
|
||||
const relay = relaysByUrl.get().get(url)
|
||||
|
||||
if (hasNip29(relay)) {
|
||||
path += "/recent"
|
||||
} else {
|
||||
path += "/chat"
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
export const goToSpace = async (url: string) => {
|
||||
const prevPath = lastPageBySpaceUrl.get(encodeRelay(url))
|
||||
|
||||
if (prevPath) {
|
||||
goto(prevPath)
|
||||
} else if (hasNip29(await loadRelay(url))) {
|
||||
goto(makeSpacePath(url, "recent"))
|
||||
} else {
|
||||
goto(makeSpacePath("chat"))
|
||||
}
|
||||
}
|
||||
|
||||
export const makeChatPath = (pubkeys: string[]) => `/chat/${makeChatId(pubkeys)}`
|
||||
|
||||
export const makeRoomPath = (url: string, h: string) => `/spaces/${encodeRelay(url)}/${h}`
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {goto} from "$app/navigation"
|
||||
import {makeSpacePath} from "@app/util/routes"
|
||||
import {goToSpace} from "@app/util/routes"
|
||||
import {PLATFORM_RELAYS} from "@app/core/state"
|
||||
|
||||
onMount(() => {
|
||||
onMount(async () => {
|
||||
if (PLATFORM_RELAYS.length > 0) {
|
||||
goto(makeSpacePath(PLATFORM_RELAYS[0]))
|
||||
goToSpace(PLATFORM_RELAYS[0])
|
||||
} else {
|
||||
goto("/home")
|
||||
}
|
||||
|
||||
@@ -12,16 +12,16 @@
|
||||
import SpaceAdd from "@app/components/SpaceAdd.svelte"
|
||||
import ChatEnable from "@app/components/ChatEnable.svelte"
|
||||
import {pushModal} from "@app/util/modal"
|
||||
import {makeSpacePath} from "@app/util/routes"
|
||||
import {goToSpace} from "@app/util/routes"
|
||||
import {PLATFORM_NAME, PLATFORM_RELAYS} from "@app/core/state"
|
||||
|
||||
const addSpace = () => pushModal(SpaceAdd)
|
||||
|
||||
const openChat = () => ($shouldUnwrap ? goto("/chat") : pushModal(ChatEnable, {next: "/chat"}))
|
||||
|
||||
onMount(() => {
|
||||
onMount(async () => {
|
||||
if (PLATFORM_RELAYS.length > 0) {
|
||||
goto(makeSpacePath(PLATFORM_RELAYS[0]))
|
||||
goToSpace(PLATFORM_RELAYS[0])
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import {page} from "$app/stores"
|
||||
import {once} from "@welshman/lib"
|
||||
import Page from "@lib/components/Page.svelte"
|
||||
import Dialog from "@lib/components/Dialog.svelte"
|
||||
import SecondaryNav from "@lib/components/SecondaryNav.svelte"
|
||||
import MenuSpace from "@app/components/MenuSpace.svelte"
|
||||
import SpaceAuthError from "@app/components/SpaceAuthError.svelte"
|
||||
@@ -23,7 +22,11 @@
|
||||
|
||||
const authError = deriveRelayAuthError(url)
|
||||
|
||||
const showAuthError = once(() => pushModal(SpaceAuthError, {url, error: $authError}))
|
||||
const showAuthError = once(() =>
|
||||
pushModal(SpaceAuthError, {url, error: $authError}, {noEscape: true}),
|
||||
)
|
||||
|
||||
const showPendingTrust = once(() => pushModal(SpaceTrustRelay, {url}, {noEscape: true}))
|
||||
|
||||
// We have to watch this one, since on mobile the badge will be visible when active
|
||||
$effect(() => {
|
||||
@@ -36,6 +39,8 @@
|
||||
$effect(() => {
|
||||
if ($authError) {
|
||||
showAuthError()
|
||||
} else if ($relaysPendingTrust.includes(url)) {
|
||||
showPendingTrust()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -48,9 +53,3 @@
|
||||
{@render children?.()}
|
||||
{/key}
|
||||
</Page>
|
||||
|
||||
{#if $relaysPendingTrust.includes(url)}
|
||||
<Dialog>
|
||||
<SpaceTrustRelay {url} />
|
||||
</Dialog>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user