fix some issues
This commit is contained in:
+19
-13
@@ -5,11 +5,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Sign in · Elsewhere</title>
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<script src="/app/theme-bootstrap.js">
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls">
|
||||
</script>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="/pages.css">
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/pages.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body class="site-page account-page">
|
||||
@@ -29,11 +29,15 @@
|
||||
<span>Username</span>
|
||||
<input name="username" autocomplete="username" required minlength="3">
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Password</span>
|
||||
<input name="password" type="password" autocomplete="current-password" required minlength="6">
|
||||
</label>
|
||||
<button type="button" id="showPassword" class="text-button" aria-pressed="false">Show password</button>
|
||||
<div class="field">
|
||||
<label for="accountPassword">Password</label>
|
||||
<div class="password-input">
|
||||
<input id="accountPassword" name="password" type="password" autocomplete="current-password" required minlength="6">
|
||||
<button type="button" id="showPassword" class="icon-button password-toggle" aria-label="Show password" title="Show password" aria-controls="accountPassword" aria-pressed="false">
|
||||
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z"/><circle cx="12" cy="12" r="3"/><path class="eye-slash" d="m3 3 18 18"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<label id="inviteField" class="field hidden">
|
||||
<span>Invite code</span>
|
||||
<input name="inviteCode" autocomplete="off">
|
||||
@@ -42,9 +46,11 @@
|
||||
<input name="consent" type="checkbox">
|
||||
<span>I agree to the <a href="/tos.html" target="_blank" rel="noopener">Terms</a> and <a href="/privacy.html" target="_blank" rel="noopener">Privacy Policy</a>.</span>
|
||||
</label>
|
||||
<div id="accountStatus" class="account-status hidden" role="status" aria-live="polite" aria-atomic="true" tabindex="-1">
|
||||
<svg class="account-error-icon" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v6m0 3v1"/></svg>
|
||||
<span id="accountStatusText"></span>
|
||||
</div>
|
||||
<button id="accountSubmit" class="primary-action" type="submit">Sign in</button>
|
||||
<p id="accountStatus" role="status" aria-live="polite">
|
||||
</p>
|
||||
</form>
|
||||
<p id="accountSwitch">
|
||||
</p>
|
||||
@@ -56,8 +62,8 @@
|
||||
<a href="/privacy.html">Privacy</a>
|
||||
<a href="/tos.html">Terms</a>
|
||||
</footer>
|
||||
<script type="module" src="/pages.js">
|
||||
<script type="module" src="/pages.js?v=20260909-account-controls">
|
||||
</script>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
import {chatDrawer, chatDrawerButton, chatDrawerCloseBtn} from "./dom.js";
|
||||
import {chatDrawer, chatDrawerButton, chatDrawerCloseBtn} from "./dom.js?v=20260909-account-controls";
|
||||
|
||||
let lastFocusedElement = null;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {themes} from "./constants.js";
|
||||
import {themes} from "./constants.js?v=20260909-account-controls";
|
||||
|
||||
export const THEME_STORAGE_KEY = "krishd-theme";
|
||||
export const THEME_MODE_STORAGE_KEY = "krishd-theme-mode";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {post} from './api.js';
|
||||
import {post} from './api.js?v=20260909-account-controls';
|
||||
|
||||
// Every page gets this control from the same server-rendered header.
|
||||
for (const button of document.querySelectorAll('[data-sign-out]')) {
|
||||
|
||||
+5
-5
@@ -7,10 +7,10 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<script src="/app/theme-bootstrap.js"></script>
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-elsewhere"/>
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls"></script>
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-account-controls"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/pages.css"><link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="/pages.css?v=20260909-account-controls"><link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
</head>
|
||||
<body class="site-page chat-page" data-theme="fakegpt" data-theme-mode="light">
|
||||
<!-- site-header -->
|
||||
@@ -352,7 +352,7 @@
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js" defer></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.min.js" defer></script>
|
||||
<script type="module" src="/script.js?v=20260908-model-descriptions"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script>
|
||||
<script type="module" src="/script.js?v=20260909-account-controls"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Discover personas · Elsewhere</title>
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<script src="/app/theme-bootstrap.js">
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls">
|
||||
</script>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="/pages.css">
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/pages.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body class="site-page discover-page">
|
||||
@@ -30,8 +30,8 @@
|
||||
<a href="/privacy.html">Privacy</a>
|
||||
<a href="/tos.html">Terms</a>
|
||||
</footer>
|
||||
<script type="module" src="/pages.js">
|
||||
<script type="module" src="/pages.js?v=20260909-account-controls">
|
||||
</script>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
+6
-6
@@ -5,11 +5,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Home · Elsewhere</title>
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<script src="/app/theme-bootstrap.js">
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls">
|
||||
</script>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="/pages.css">
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/pages.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body class="site-page home-page">
|
||||
@@ -50,8 +50,8 @@
|
||||
</p>
|
||||
</main>
|
||||
|
||||
<script type="module" src="/pages.js">
|
||||
<script type="module" src="/pages.js?v=20260909-account-controls">
|
||||
</script>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
+6
-6
@@ -5,10 +5,10 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Elsewhere</title>
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<script src="/app/theme-bootstrap.js"></script>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<link rel="stylesheet" href="/pages.css">
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls"></script>
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/pages.css?v=20260909-account-controls">
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body class="site-page landing-page">
|
||||
@@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</main>
|
||||
<footer class="site-footer"><span>elsewhere / a little room for imagination</span><a href="/privacy.html">Privacy</a><a href="/tos.html">Terms</a></footer>
|
||||
<script type="module" src="/pages.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script>
|
||||
<script type="module" src="/pages.js?v=20260909-account-controls"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+5
-5
@@ -7,10 +7,10 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<script src="/app/theme-bootstrap.js"></script>
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-elsewhere"/>
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls"></script>
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-account-controls"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
</head>
|
||||
<body class="site-page market-page" data-theme="fakegpt" data-theme-mode="light">
|
||||
<!-- site-header -->
|
||||
@@ -237,6 +237,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/market.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script></body>
|
||||
<script type="module" src="/market.js?v=20260909-account-controls"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script></body>
|
||||
</html>
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import {get, post, put} from "./app/api.js";
|
||||
import {initializeAppearance} from "./app/themeController.js";
|
||||
import {clearStatus, setStatus} from "./app/statusNotice.js";
|
||||
import {populatePersonaForm, readPersonaForm} from "./app/personaForm.js";
|
||||
import {get, post, put} from "./app/api.js?v=20260909-account-controls";
|
||||
import {initializeAppearance} from "./app/themeController.js?v=20260909-account-controls";
|
||||
import {clearStatus, setStatus} from "./app/statusNotice.js?v=20260909-account-controls";
|
||||
import {populatePersonaForm, readPersonaForm} from "./app/personaForm.js?v=20260909-account-controls";
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const marketPersonaList = $("marketPersonaList");
|
||||
|
||||
@@ -49,3 +49,22 @@
|
||||
.entry-door { width:65px; height:92px; border-width:1px; }.entry-door::before { inset:4px; }.entry-door span { inset:4px 4px 0 14px; border-width:1px; }.entry-door span::after { width:3px; height:3px; left:5px; }.entry-door::after { bottom:-8px; left:-10px; right:-10px; }
|
||||
.entry-copy h1 { font-size:2.8rem; }.entry-copy > p:not(.eyebrow) { margin:18px 0 24px; }
|
||||
}
|
||||
|
||||
/* Account controls stay quiet; errors must be unmistakable. */
|
||||
.password-input { position:relative; }
|
||||
#accountForm .password-input input { padding-right:50px; }
|
||||
#accountForm .password-toggle { position:absolute; right:6px; top:50%; transform:translateY(-50%); width:36px; height:36px; min-height:36px; padding:0; border:0; border-radius:8px; background:transparent; color:var(--text-soft); box-shadow:none; }
|
||||
#accountForm .password-toggle:hover { transform:translateY(-50%); background:var(--surface-hover); color:var(--text); }
|
||||
.password-toggle svg { display:block; flex-shrink:0; }
|
||||
.password-toggle .eye-slash { display:none; }
|
||||
.password-toggle[aria-pressed="true"] .eye-slash { display:block; }
|
||||
.account-status { display:flex; align-items:flex-start; gap:10px; margin:0; font-size:.9rem; line-height:1.6; color:var(--text-soft); }
|
||||
.account-error-icon { display:none; flex:0 0 20px; margin-top:2px; }
|
||||
.account-status[data-state="error"] { padding:13px 15px; border:1px solid #dfaaa5; border-left:4px solid #b3261e; border-radius:10px; background:#fff1f0; color:#92221b; font-weight:600; }
|
||||
.account-status[data-state="error"] .account-error-icon { display:block; }
|
||||
#accountForm input[aria-invalid="true"] { border-color:#b3261e; }
|
||||
body[data-theme-mode="dark"] .account-status[data-state="error"] { background:#351f22; color:#ffb4ad; border-color:#925350; border-left-color:#ffb4ad; }
|
||||
body[data-theme-mode="dark"] #accountForm input[aria-invalid="true"] { border-color:#ffb4ad; }
|
||||
#accountForm .field > label { font-size:.82rem; font-weight:600; color:var(--text-soft); }
|
||||
.account-status:focus { outline:none; }
|
||||
#accountSwitch { margin-top:20px; }
|
||||
|
||||
+26
-5
@@ -1,4 +1,4 @@
|
||||
import {get, post} from "/app/api.js";
|
||||
import {get, post} from "/app/api.js?v=20260909-account-controls";
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
function returnPath() {
|
||||
@@ -20,6 +20,14 @@ if (form) {
|
||||
const register = location.pathname === "/register";
|
||||
const status = document.querySelector("#accountStatus");
|
||||
const submit = document.querySelector("#accountSubmit");
|
||||
function showAccountStatus(message, error = false) {
|
||||
status.dataset.state = error ? "error" : "pending";
|
||||
status.setAttribute("role", error ? "alert" : "status");
|
||||
status.setAttribute("aria-live", error ? "assertive" : "polite");
|
||||
status.classList.toggle("hidden", !message);
|
||||
document.querySelector("#accountStatusText").textContent = message;
|
||||
if (error) status.focus();
|
||||
}
|
||||
const label = register ? "Create account" : "Sign in";
|
||||
document.title = `${label} · Elsewhere`;
|
||||
document.querySelector("#accountTitle").textContent = label;
|
||||
@@ -34,7 +42,7 @@ if (form) {
|
||||
document.querySelector("#accountHeadline").textContent = "Your next conversation starts here.";
|
||||
document.querySelector("#accountDescription").textContent = "Choose a username and a password of at least 6 characters.";
|
||||
}
|
||||
if (session.error) status.textContent = session.error;
|
||||
if (session.error) showAccountStatus(session.error, true);
|
||||
const switchText = document.querySelector("#accountSwitch");
|
||||
switchText.append(register ? "Already have an account? " : "New to Elsewhere? ");
|
||||
const link = document.createElement("a");
|
||||
@@ -44,18 +52,31 @@ if (form) {
|
||||
document.querySelector("#showPassword").addEventListener("click", event => {
|
||||
const show = form.elements.password.type === "password";
|
||||
form.elements.password.type = show ? "text" : "password";
|
||||
event.currentTarget.textContent = show ? "Hide password" : "Show password";
|
||||
const label = show ? "Hide password" : "Show password";
|
||||
event.currentTarget.setAttribute("aria-label", label);
|
||||
event.currentTarget.title = label;
|
||||
event.currentTarget.setAttribute("aria-pressed", String(show));
|
||||
});
|
||||
form.addEventListener("submit", async event => {
|
||||
event.preventDefault();
|
||||
submit.disabled = true;
|
||||
status.textContent = register ? "Creating your account…" : "Signing in…";
|
||||
form.elements.username.removeAttribute("aria-invalid");
|
||||
form.elements.username.removeAttribute("aria-describedby");
|
||||
showAccountStatus(register ? "Creating your account..." : "Signing in...");
|
||||
const result = await post(register ? "/register" : "/login", {
|
||||
username: form.elements.username.value.trim(), password: form.elements.password.value,
|
||||
...(register ? {inviteCode: form.elements.inviteCode.value.trim()} : {})
|
||||
});
|
||||
if (result.error) { status.textContent = result.error; submit.disabled = false; return; }
|
||||
if (result.error) {
|
||||
const duplicate = register && result.error === "User already exists";
|
||||
if (duplicate) {
|
||||
form.elements.username.setAttribute("aria-invalid", "true");
|
||||
form.elements.username.setAttribute("aria-describedby", "accountStatus");
|
||||
}
|
||||
showAccountStatus(duplicate ? "That username is already taken. Choose another, or sign in below." : result.error, true);
|
||||
submit.disabled = false;
|
||||
return;
|
||||
}
|
||||
location.assign(returnPath());
|
||||
});
|
||||
}
|
||||
|
||||
+5
-5
@@ -5,10 +5,10 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Privacy Policy – DeepFake</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link rel="stylesheet" href="legal.css" />
|
||||
<script src="/app/theme-bootstrap.js"></script>
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="style.css?v=20260909-account-controls" />
|
||||
<link rel="stylesheet" href="legal.css?v=20260909-account-controls" />
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls"></script>
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body class="site-page legal-page">
|
||||
@@ -89,6 +89,6 @@
|
||||
<p>We may update this document. Changes will be posted with a “Last updated” date.</p>
|
||||
</section>
|
||||
</main>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
import {del, get, post, put, stream} from "./app/api.js";
|
||||
import {closeChatDrawer, openChatDrawer} from "./app/chatDrawer.js";
|
||||
import {onboardingPrompts, requestedChatId} from "./app/constants.js";
|
||||
import {getModelProfile} from "./app/modelProfiles.js";
|
||||
import {applyTheme as applySharedTheme, applyThemeMode as applySharedThemeMode, readStoredAppearance} from "./app/themeController.js";
|
||||
import {del, get, post, put, stream} from "./app/api.js?v=20260909-account-controls";
|
||||
import {closeChatDrawer, openChatDrawer} from "./app/chatDrawer.js?v=20260909-account-controls";
|
||||
import {onboardingPrompts, requestedChatId} from "./app/constants.js?v=20260909-account-controls";
|
||||
import {getModelProfile} from "./app/modelProfiles.js?v=20260909-account-controls";
|
||||
import {applyTheme as applySharedTheme, applyThemeMode as applySharedThemeMode, readStoredAppearance} from "./app/themeController.js?v=20260909-account-controls";
|
||||
import {
|
||||
activeChatTitle,
|
||||
activeUserPersonaStatus,
|
||||
@@ -99,7 +99,7 @@ import {
|
||||
brandLogoTargets,
|
||||
brandNameTargets,
|
||||
userPersonaList
|
||||
} from "./app/dom.js";
|
||||
} from "./app/dom.js?v=20260909-account-controls";
|
||||
|
||||
const headerModelButton = document.getElementById("headerModelButton");
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<script src="/app/theme-bootstrap.js"></script>
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-elsewhere"/>
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls"></script>
|
||||
<link rel="stylesheet" href="/style.css?v=20260909-account-controls"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
</head>
|
||||
<body class="site-page settings-page" data-theme="fakegpt" data-theme-mode="light">
|
||||
<!-- site-header -->
|
||||
@@ -298,6 +298,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/settings.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script></body>
|
||||
<script type="module" src="/settings.js?v=20260909-account-controls"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script></body>
|
||||
</html>
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
import {del, get, post, put} from "./app/api.js";
|
||||
import {del, get, post, put} from "./app/api.js?v=20260909-account-controls";
|
||||
import {
|
||||
applyTheme as applySharedTheme,
|
||||
applyThemeMode as applySharedThemeMode,
|
||||
initializeAppearance
|
||||
} from "./app/themeController.js";
|
||||
import {clearStatus, setStatus} from "./app/statusNotice.js";
|
||||
import {populatePersonaForm, readPersonaForm} from "./app/personaForm.js";
|
||||
} from "./app/themeController.js?v=20260909-account-controls";
|
||||
import {clearStatus, setStatus} from "./app/statusNotice.js?v=20260909-account-controls";
|
||||
import {populatePersonaForm, readPersonaForm} from "./app/personaForm.js?v=20260909-account-controls";
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const settingsNotice = $("settingsNotice");
|
||||
|
||||
+5
-5
@@ -5,10 +5,10 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Terms of Service – DeepFake</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link rel="stylesheet" href="legal.css" />
|
||||
<script src="/app/theme-bootstrap.js"></script>
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<link rel="stylesheet" href="style.css?v=20260909-account-controls" />
|
||||
<link rel="stylesheet" href="legal.css?v=20260909-account-controls" />
|
||||
<script src="/app/theme-bootstrap.js?v=20260909-account-controls"></script>
|
||||
<link rel="stylesheet" href="/shell.css?v=20260909-account-controls">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body class="site-page legal-page">
|
||||
@@ -47,6 +47,6 @@
|
||||
<p>We may modify these Terms at any time. Updates will be reflected with a new “Last updated” date.</p>
|
||||
</section>
|
||||
</main>
|
||||
<script type="module" src="/app/workspaceNavigation.js"></script>
|
||||
<script type="module" src="/app/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -283,6 +283,10 @@ export function createApp(options = {}) {
|
||||
app.use(express.static(config.publicDir, {
|
||||
maxAge: config.staticMaxAge,
|
||||
etag: config.staticEtag,
|
||||
setHeaders(res, filePath) {
|
||||
// HTML and its modules must not drift apart after a deployment.
|
||||
if (/\.(?:js|css)$/.test(filePath)) res.setHeader("Cache-Control", "no-cache");
|
||||
},
|
||||
fallthrough: config.staticFallthrough
|
||||
}));
|
||||
app.use(createAuthRouter({repositories, authRateLimiters, config}));
|
||||
|
||||
@@ -1064,3 +1064,17 @@ test("page headers share navigation and keep session markup private", async () =
|
||||
assert.ok(html.includes('href="/login"'));
|
||||
} finally { await server.close(); }
|
||||
});
|
||||
|
||||
test("frontend scripts and styles revalidate across deployments", async () => {
|
||||
const server = await startTestServer({config: {staticMaxAge: "1h"}});
|
||||
try {
|
||||
for (const asset of ["/script.js?v=20260909-account-controls", "/app/dom.js?v=20260909-account-controls", "/pages.css?v=20260909-account-controls"]) {
|
||||
const response = await fetch(server.baseUrl + asset);
|
||||
assert.equal(response.status, 200);
|
||||
assert.equal(response.headers.get("cache-control"), "no-cache");
|
||||
const etag = response.headers.get("etag");
|
||||
assert.ok(etag);
|
||||
await response.text();
|
||||
}
|
||||
} finally { await server.close(); }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user