Merge branch 'dev'

This commit is contained in:
Jeff Emmett 2026-03-23 13:21:14 -07:00
commit 9533a71b42
2 changed files with 39 additions and 9 deletions

View File

@ -264,9 +264,17 @@ function autoResolveSpace(token: string, username: string): void {
// Detect current space
const currentSpace = _getCurrentSpace();
if (currentSpace !== "demo") return; // Already on a non-demo space
// Provision personal space and redirect
if (currentSpace !== "demo") {
// User followed a link to a specific space (e.g., orgname.rspace.online).
// Provision their personal space silently, then reload to apply the
// authenticated session (clears access gates, reconnects CRDT sync, etc.).
autoProvisionSpace(token);
window.location.reload();
return;
}
// On demo/landing — provision personal space and redirect there
fetch("/api/spaces/auto-provision", {
method: "POST",
headers: {

View File

@ -6685,31 +6685,53 @@
function showBulkDeleteConfirm(count) {
if (bulkDeleteOverlay) return; // prevent stacking from key repeat
const overlay = document.createElement("div");
overlay.style.cssText = "position:fixed;inset:0;background:rgba(0,0,0,0.6);z-index:10000;display:flex;align-items:center;justify-content:center";
overlay.style.cssText = "position:fixed;inset:0;background:rgba(0,0,0,0.6);z-index:100002;display:flex;align-items:center;justify-content:center;touch-action:manipulation";
const dialog = document.createElement("div");
dialog.style.cssText = "background:var(--rs-bg-surface,#1e1b4b);border:1px solid var(--rs-border,#334155);border-radius:12px;padding:1.5rem 2rem;max-width:380px;text-align:center;color:var(--rs-text-primary,#e2e8f0);font-family:system-ui,sans-serif";
dialog.style.cssText = "background:var(--rs-bg-surface,#1e1b4b);border:1px solid var(--rs-border,#334155);border-radius:12px;padding:1.5rem 2rem;max-width:380px;text-align:center;color:var(--rs-text-primary,#e2e8f0);font-family:system-ui,sans-serif;user-select:none";
const btnBase = "padding:0.5rem 1.25rem;border-radius:8px;cursor:pointer;font-size:0.875rem;touch-action:manipulation;user-select:none;-webkit-tap-highlight-color:transparent;transition:filter 0.1s";
dialog.innerHTML = `
<h3 style="margin:0 0 0.5rem;font-size:1.125rem">Delete ${count} elements?</h3>
<p style="color:var(--rs-text-secondary,#94a3b8);font-size:0.875rem;margin:0 0 1.25rem;line-height:1.5">You are about to delete a large number of elements. This action cannot be easily undone.</p>
<div style="display:flex;gap:0.75rem;justify-content:center">
<button id="bulk-delete-cancel" style="padding:0.5rem 1.25rem;border-radius:8px;border:1px solid var(--rs-border,#334155);background:transparent;color:var(--rs-text-primary,#e2e8f0);cursor:pointer;font-size:0.875rem">Cancel</button>
<button id="bulk-delete-confirm" style="padding:0.5rem 1.25rem;border-radius:8px;border:1px solid #dc2626;background:#dc2626;color:#fff;cursor:pointer;font-size:0.875rem;font-weight:600">DELETE</button>
<button id="bulk-delete-cancel" style="${btnBase};border:1px solid var(--rs-border,#334155);background:transparent;color:var(--rs-text-primary,#e2e8f0)">Cancel</button>
<button id="bulk-delete-confirm" style="${btnBase};border:1px solid #dc2626;background:#dc2626;color:#fff;font-weight:600">DELETE</button>
</div>`;
overlay.appendChild(dialog);
document.body.appendChild(overlay);
bulkDeleteOverlay = overlay;
overlay.addEventListener("click", (e) => { if (e.target === overlay) dismissBulkDelete(); });
dialog.querySelector("#bulk-delete-cancel").addEventListener("click", dismissBulkDelete);
dialog.querySelector("#bulk-delete-confirm").addEventListener("click", () => {
const cancelBtn = dialog.querySelector("#bulk-delete-cancel");
const confirmBtn = dialog.querySelector("#bulk-delete-confirm");
// Use pointerdown for instant response (no 300ms click delay on touch)
overlay.addEventListener("pointerdown", (e) => {
if (e.target === overlay) { e.stopPropagation(); dismissBulkDelete(); }
});
cancelBtn.addEventListener("pointerdown", (e) => {
e.stopPropagation();
dismissBulkDelete();
});
confirmBtn.addEventListener("pointerdown", (e) => {
e.stopPropagation();
dismissBulkDelete();
doDeleteSelected();
});
// Visual feedback on hover/active
[cancelBtn, confirmBtn].forEach(btn => {
btn.addEventListener("pointerenter", () => { btn.style.filter = "brightness(1.2)"; });
btn.addEventListener("pointerleave", () => { btn.style.filter = ""; });
btn.addEventListener("pointerdown", () => { btn.style.filter = "brightness(0.85)"; });
});
// Escape key closes dialog
const escHandler = (e) => {
if (e.key === "Escape") { dismissBulkDelete(); document.removeEventListener("keydown", escHandler); }
};
document.addEventListener("keydown", escHandler);
// Focus the confirm button so Enter also works
confirmBtn.focus();
}
// ── Canvas pointer interaction: pan-first + hold-to-select ──