Push a history entry when switching spaces instead of replacing the current one (#407)
Co-authored-by: Coracle-Bot <npub1klq6260@nostr.local>
This commit is contained in:
parent
70e3b2bd32
commit
097cde0201
7 changed files with 79 additions and 13 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
import {spec} from "@welshman/lib"
|
import {spec} from "@welshman/lib"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {RelayMessageType} from "@welshman/net"
|
import {RelayMessageType} from "@welshman/net"
|
||||||
import {expect, getTranscript, roomPath, test, users} from "../harness"
|
import {expect, getTranscript, roomPath, spacePath, test, users} from "../harness"
|
||||||
|
|
||||||
test("keeps two spaces' contents on their own relays", async ({seed, as}) => {
|
test("keeps two spaces' contents on their own relays", async ({seed, as}) => {
|
||||||
const scenario = await seed(({relay, user}) => {
|
const scenario = await seed(({relay, user}) => {
|
||||||
|
|
@ -55,3 +55,60 @@ test("keeps two spaces' contents on their own relays", async ({seed, as}) => {
|
||||||
|
|
||||||
expect(strays).toEqual([])
|
expect(strays).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("goes back to the room you left when you switch spaces", async ({seed, as}) => {
|
||||||
|
const scenario = await seed(({relay, user}) => {
|
||||||
|
const space = relay("space")
|
||||||
|
const other = relay("other")
|
||||||
|
|
||||||
|
space.room("lounge", {name: "Space Lounge"})
|
||||||
|
other.room("lounge", {name: "Other Lounge"})
|
||||||
|
space.join(user.alice, "lounge")
|
||||||
|
other.join(user.alice, "lounge")
|
||||||
|
})
|
||||||
|
|
||||||
|
const space = scenario.space("space")
|
||||||
|
const other = scenario.space("other")
|
||||||
|
const page = await as(users.alice, roomPath(space.url, "lounge"))
|
||||||
|
|
||||||
|
await expect(page.getByRole("link", {name: "Space Lounge"})).toBeVisible()
|
||||||
|
|
||||||
|
await page.locator('.primary-nav [data-tip^="other"]').click()
|
||||||
|
await expect(page).toHaveURL(new RegExp(spacePath(other.url)))
|
||||||
|
|
||||||
|
await page.getByRole("link", {name: "Other Lounge"}).click()
|
||||||
|
await expect(page).toHaveURL(new RegExp(`${roomPath(other.url, "lounge")}$`))
|
||||||
|
|
||||||
|
// Two entries back: the other space's landing page, then the room this started on. The switch
|
||||||
|
// used to replace that room's entry rather than push one, so the second step overshot it.
|
||||||
|
await page.goBack()
|
||||||
|
await page.goBack()
|
||||||
|
|
||||||
|
await expect(page).toHaveURL(new RegExp(`${roomPath(space.url, "lounge")}$`))
|
||||||
|
})
|
||||||
|
|
||||||
|
test("does not stack a history entry for the space you are already in", async ({seed, as}) => {
|
||||||
|
const scenario = await seed(({relay, user}) => {
|
||||||
|
const space = relay("space")
|
||||||
|
|
||||||
|
space.room("lounge", {name: "Space Lounge"})
|
||||||
|
space.room("garden", {name: "Space Garden"})
|
||||||
|
space.join(user.alice, "lounge")
|
||||||
|
space.join(user.alice, "garden")
|
||||||
|
})
|
||||||
|
|
||||||
|
const space = scenario.space("space")
|
||||||
|
const page = await as(users.alice, roomPath(space.url, "lounge"))
|
||||||
|
|
||||||
|
await page.getByRole("link", {name: "Space Garden"}).click()
|
||||||
|
await expect(page).toHaveURL(new RegExp(`${roomPath(space.url, "garden")}$`))
|
||||||
|
|
||||||
|
// The space's entry page is the room you are on, so this navigates nowhere and should replace
|
||||||
|
// rather than push. One step back is the room this started on, not the one it never left.
|
||||||
|
await page.locator('.primary-nav [data-tip^="space"]').click()
|
||||||
|
await expect(page).toHaveURL(new RegExp(`${roomPath(space.url, "garden")}$`))
|
||||||
|
|
||||||
|
await page.goBack()
|
||||||
|
|
||||||
|
await expect(page).toHaveURL(new RegExp(`${roomPath(space.url, "lounge")}$`))
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import {goto} from "$app/navigation"
|
||||||
|
import {page} from "$app/stores"
|
||||||
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
|
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
|
||||||
import RelayIcon from "@app/components/RelayIcon.svelte"
|
import RelayIcon from "@app/components/RelayIcon.svelte"
|
||||||
import {relays} from "@app/core"
|
import {relays} from "@app/core"
|
||||||
import {makeSpacePath, goToSpace} from "@app/routes"
|
import {makeSpacePath, makeSpaceEntryPath} from "@app/routes"
|
||||||
import {notifications} from "@app/notifications"
|
import {notifications} from "@app/notifications"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -12,7 +14,11 @@
|
||||||
|
|
||||||
const {url, showTooltip = true}: Props = $props()
|
const {url, showTooltip = true}: Props = $props()
|
||||||
|
|
||||||
const onClick = () => goToSpace(url)
|
const onClick = () => {
|
||||||
|
const entryPath = makeSpaceEntryPath(url)
|
||||||
|
|
||||||
|
goto(entryPath, {replaceState: entryPath === $page.url.pathname})
|
||||||
|
}
|
||||||
|
|
||||||
const path = makeSpacePath(url)
|
const path = makeSpacePath(url)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
pushToast({message: "Welcome to the space!"})
|
pushToast({message: "Welcome to the space!"})
|
||||||
await goToSpace(data.url)
|
await goToSpace(data.url, {replaceState: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
const join = async () => {
|
const join = async () => {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
await access.completeJoin(notifications)
|
await access.completeJoin(notifications)
|
||||||
|
|
||||||
pushToast({message: "Welcome to the space!"})
|
pushToast({message: "Welcome to the space!"})
|
||||||
await goToSpace(url)
|
await goToSpace(url, {replaceState: true})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to join space:", e)
|
console.error("Failed to join space:", e)
|
||||||
pushToast({theme: "error", message: "Failed to join space. Please try again."})
|
pushToast({theme: "error", message: "Failed to join space. Please try again."})
|
||||||
|
|
|
||||||
|
|
@ -85,30 +85,33 @@ export const makeSpacePath = (url: string, ...extra: (string | undefined)[]) =>
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
export const goToSpace = (url: string, hash = "") => {
|
export const makeSpaceEntryPath = (url: string) => {
|
||||||
const prevPath = lastPageBySpaceUrl.get(encodeRelay(url))
|
const prevPath = lastPageBySpaceUrl.get(encodeRelay(url))
|
||||||
|
|
||||||
if (prevPath && prevPath !== makeSpacePath(url)) {
|
if (prevPath && prevPath !== makeSpacePath(url)) {
|
||||||
return goto(prevPath + hash, {replaceState: true})
|
return prevPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!relays.get().get(url)?.hasNip(29)) {
|
if (!relays.get().get(url)?.hasNip(29)) {
|
||||||
return goto(makeSpaceChatPath(url) + hash, {replaceState: true})
|
return makeSpaceChatPath(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.matchMedia(`(min-width: ${theme.screens.md})`).matches) {
|
if (window.matchMedia(`(min-width: ${theme.screens.md})`).matches) {
|
||||||
return goto(makeSpacePath(url, "about") + hash, {replaceState: true})
|
return makeSpacePath(url, "about")
|
||||||
}
|
}
|
||||||
|
|
||||||
return goto(makeSpacePath(url) + hash, {replaceState: true})
|
return makeSpacePath(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const goToSpace = (url: string, options: {replaceState?: boolean} = {}) =>
|
||||||
|
goto(makeSpaceEntryPath(url), options)
|
||||||
|
|
||||||
export const goToMovedSpace = (oldUrl: string, newUrl: string) =>
|
export const goToMovedSpace = (oldUrl: string, newUrl: string) =>
|
||||||
goto(get(page).url.pathname.replace(encodeRelay(oldUrl), encodeRelay(newUrl)))
|
goto(get(page).url.pathname.replace(encodeRelay(oldUrl), encodeRelay(newUrl)))
|
||||||
|
|
||||||
export const goToHome = () => {
|
export const goToHome = () => {
|
||||||
if (PLATFORM_RELAYS.length > 0) {
|
if (PLATFORM_RELAYS.length > 0) {
|
||||||
return goToSpace(PLATFORM_RELAYS[0], get(page).url.hash)
|
return goto(makeSpaceEntryPath(PLATFORM_RELAYS[0]) + get(page).url.hash, {replaceState: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
return goto("/home" + get(page).url.hash)
|
return goto("/home" + get(page).url.hash)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (PLATFORM_RELAYS.length > 0) {
|
if (PLATFORM_RELAYS.length > 0) {
|
||||||
goToSpace(PLATFORM_RELAYS[0])
|
goToSpace(PLATFORM_RELAYS[0], {replaceState: true})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (width > md) {
|
if (width > md) {
|
||||||
goToSpace(url)
|
goToSpace(url, {replaceState: true})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue