diff --git a/server/spaces.ts b/server/spaces.ts index b57291e..7ceb088 100644 --- a/server/spaces.ts +++ b/server/spaces.ts @@ -241,6 +241,8 @@ spaces.get("/", async (c) => { seenSlugs.add(slug); let vis = data.meta.visibility || "private"; + // Demo space is always public + if (slug === "demo") vis = "public"; // Check both claims.sub (raw userId) and did:key: format for // compatibility — auto-provisioned spaces store ownerDID as did:key: const callerDid = claims ? ((claims.did as string) || `did:key:${(claims.sub as string).slice(0, 32)}`) : ""; @@ -261,9 +263,7 @@ spaces.get("/", async (c) => { // For unauthenticated: only show demo if (!claims && slug !== "demo") continue; - // For authenticated: skip public spaces the user has no role in - // (demo is shown separately, other public spaces are noise) - if (claims && isPublicSpace && !isOwner && !isMember && slug !== "demo") continue; + // Public spaces are shown in the PUBLIC section for all authenticated users // Determine relationship const relationship = isOwner @@ -290,6 +290,7 @@ spaces.get("/", async (c) => { accessible, relationship, pendingRequest: pendingRequest || undefined, + isPersonal: !!(username && slug === username), }); } } diff --git a/shared/components/rstack-space-switcher.ts b/shared/components/rstack-space-switcher.ts index f4cec69..a09f656 100644 --- a/shared/components/rstack-space-switcher.ts +++ b/shared/components/rstack-space-switcher.ts @@ -21,6 +21,7 @@ interface SpaceInfo { accessible?: boolean; relationship?: "owner" | "member" | "demo" | "other"; pendingRequest?: boolean; + isPersonal?: boolean; } export class RStackSpaceSwitcher extends HTMLElement { @@ -141,10 +142,9 @@ export class RStackSpaceSwitcher extends HTMLElement { return { cls: "vis-public", label: "👁" }; } - /** Format display name based on visibility type */ + /** Format display name — only rename the user's personal space */ #displayName(s: SpaceInfo): string { - const v = s.visibility || "public"; - if (v === "private") { + if (s.isPersonal || s.slug === getUsername()?.toLowerCase()) { const username = getUsername(); return username ? `${username}'s Space` : "My Space"; } @@ -168,130 +168,60 @@ export class RStackSpaceSwitcher extends HTMLElement { .join(""); } - #demoSpaceHTML(current: string, moduleId: string): string { - const isActive = current === "demo"; - return ` - - - Demo Space - 👁 - `; - } - #renderMenu(menu: HTMLElement, current: string) { const auth = isAuthenticated(); const moduleId = this.#getCurrentModule(); - if (this.#spaces.length === 0) { - let cta = ""; - if (!auth) { - cta = this.#yourSpaceCTAhtml("Sign in to create →"); - } else { - const username = getUsername(); - const label = username ? `Create ${username}'s Space →` : "Create My Space →"; - cta = this.#yourSpaceCTAhtml(label); - } - menu.innerHTML = ` - ${this.#demoSpaceHTML(current, moduleId)} -
- ${cta} - - - - ${this.#createFormHTML()} - `; - this.#attachYourSpaceCTA(menu); - this.#attachCreatePopout(menu); - return; - } + // Split spaces by visibility + const privateSpaces = this.#spaces.filter((s) => s.visibility === "private"); + const permissionedSpaces = this.#spaces.filter((s) => s.visibility === "permissioned"); + const publicSpaces = this.#spaces.filter((s) => s.visibility === "public"); - // Split spaces by visibility and role - const mySpaces = this.#spaces.filter((s) => s.role); - const discoverSpaces = this.#spaces.filter((s) => s.accessible === false); - - const privateSpaces = mySpaces.filter((s) => s.visibility === "private"); - const permissionedSpaces = mySpaces.filter((s) => s.visibility === "permissioned"); - const publicSpaces = mySpaces.filter((s) => s.visibility === "public"); - - const hasOwnedSpace = mySpaces.some((s) => s.relationship === "owner"); + const hasOwnedSpace = this.#spaces.some((s) => s.relationship === "owner"); let html = ""; - // ── Demo Space — always first ── - html += this.#demoSpaceHTML(current, moduleId); - html += ``; - - // ── Create personal space CTA — only if user has no owned spaces ── + // ── PRIVATE section ── + html += `