Merge branch 'dev'
This commit is contained in:
commit
627277303e
|
|
@ -240,8 +240,12 @@ spaces.get("/", async (c) => {
|
||||||
const isPermissioned = vis === "permissioned";
|
const isPermissioned = vis === "permissioned";
|
||||||
const accessible = isPublicSpace || isOwner || isMember || (isPermissioned && !!claims);
|
const accessible = isPublicSpace || isOwner || isMember || (isPermissioned && !!claims);
|
||||||
|
|
||||||
// For unauthenticated: only show public spaces
|
// For unauthenticated: only show demo
|
||||||
if (!claims && !isPublicSpace) continue;
|
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;
|
||||||
|
|
||||||
// Determine relationship
|
// Determine relationship
|
||||||
const relationship = isOwner
|
const relationship = isOwner
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,18 @@ function autoResolveSpace(token: string, username: string): void {
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Silent provisioning (no redirect) — ensures user's space exists ──
|
||||||
|
|
||||||
|
function autoProvisionSpace(token: string): void {
|
||||||
|
fetch("/api/spaces/auto-provision", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
// ── Inline URL helpers (avoid import cycle with url-helpers) ──
|
// ── Inline URL helpers (avoid import cycle with url-helpers) ──
|
||||||
const _RESERVED = ["www", "rspace", "create", "new", "start", "auth"];
|
const _RESERVED = ["www", "rspace", "create", "new", "start", "auth"];
|
||||||
function _isSubdomain(): boolean {
|
function _isSubdomain(): boolean {
|
||||||
|
|
@ -264,12 +276,12 @@ export class RStackIdentity extends HTMLElement {
|
||||||
this.#refreshIfNeeded();
|
this.#refreshIfNeeded();
|
||||||
this.#render();
|
this.#render();
|
||||||
|
|
||||||
// Belt-and-suspenders: if a session already exists on page load,
|
// If a session already exists on page load, provision the
|
||||||
// ensure the user's personal space is provisioned (catches edge
|
// user's personal space in the background (but do NOT redirect —
|
||||||
// cases like iframe embedding or direct navigation).
|
// the user intentionally navigated to this space).
|
||||||
const session = getSession();
|
const session = getSession();
|
||||||
if (session?.accessToken && session.claims.username) {
|
if (session?.accessToken && session.claims.username) {
|
||||||
autoResolveSpace(session.accessToken, session.claims.username);
|
autoProvisionSpace(session.accessToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,9 +171,8 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3-section split — exclude demo from public since we show it separately
|
// Split: user's own spaces vs permissioned spaces they can discover
|
||||||
const mySpaces = this.#spaces.filter((s) => s.role);
|
const mySpaces = this.#spaces.filter((s) => s.role);
|
||||||
const publicSpaces = this.#spaces.filter((s) => s.accessible !== false && !s.role && s.slug !== "demo");
|
|
||||||
const discoverSpaces = this.#spaces.filter((s) => s.accessible === false);
|
const discoverSpaces = this.#spaces.filter((s) => s.accessible === false);
|
||||||
|
|
||||||
const hasOwnedSpace = mySpaces.some((s) => s.relationship === "owner");
|
const hasOwnedSpace = mySpaces.some((s) => s.relationship === "owner");
|
||||||
|
|
@ -214,25 +213,7 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Public spaces ──
|
// ── Discover (permissioned spaces the user can request access to) ──
|
||||||
if (publicSpaces.length > 0) {
|
|
||||||
if (mySpaces.length > 0) html += `<div class="divider"></div>`;
|
|
||||||
html += `<div class="section-label">Public spaces</div>`;
|
|
||||||
html += publicSpaces
|
|
||||||
.map((s) => {
|
|
||||||
const vis = this.#visibilityInfo(s);
|
|
||||||
return `
|
|
||||||
<a class="item ${vis.cls} ${s.slug === current ? "active" : ""}"
|
|
||||||
href="${rspaceNavUrl(s.slug, moduleId)}">
|
|
||||||
<span class="item-icon">${s.icon || "🌐"}</span>
|
|
||||||
<span class="item-name">${this.#displayName(s)}</span>
|
|
||||||
<span class="item-vis ${vis.cls}">${vis.label}</span>
|
|
||||||
</a>`;
|
|
||||||
})
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Discover (inaccessible spaces) ──
|
|
||||||
if (auth && discoverSpaces.length > 0) {
|
if (auth && discoverSpaces.length > 0) {
|
||||||
html += `<div class="divider"></div>`;
|
html += `<div class="divider"></div>`;
|
||||||
html += `<div class="section-label">Discover</div>`;
|
html += `<div class="section-label">Discover</div>`;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue