- Implemented.
Rebuilt embed-example.html with inline, full-screen, and popup examples. Fixed host-page/frame scrolling and contained reply navigation. New logins now transactionally replace prior sessions; displaced clients return to login. Added per-user session/IP locking with automatic SQLite migration. Added modular Spam Control dashboard for locks, honeypot, and CAPTCHA settings. Moved CAPTCHA controls out of Plans & Platform.
This commit is contained in:
@@ -67,7 +67,7 @@ input, button { font-family: inherit; }
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 360px;
|
||||
min-height: 0;
|
||||
background: var(--bg0);
|
||||
color: var(--t0);
|
||||
font-family: var(--ui);
|
||||
@@ -76,6 +76,8 @@ input, button { font-family: inherit; }
|
||||
border: 1px solid var(--bd);
|
||||
border-radius: var(--r2);
|
||||
overflow: hidden;
|
||||
overscroll-behavior: contain;
|
||||
contain: layout paint;
|
||||
position: relative;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
@@ -222,6 +224,7 @@ input, button { font-family: inherit; }
|
||||
/* ─── Body area ──────────────────────────────────────────────────────────── */
|
||||
.cc-body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@@ -629,7 +632,10 @@ input, button { font-family: inherit; }
|
||||
/* Messages */
|
||||
.cc-messages {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
scrollbar-gutter: stable;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 6px 0 4px;
|
||||
@@ -1239,14 +1245,15 @@ input, button { font-family: inherit; }
|
||||
.cc-auth-wrap { align-items: flex-start; }
|
||||
}
|
||||
|
||||
/* ─── Full-page (index.html) embed ───────────────────────────────────────── */
|
||||
html, body {
|
||||
/* ─── Full-page (index.html) shell ───────────────────────────────────────── */
|
||||
html.cc-fullpage-document,
|
||||
body.cc-fullpage {
|
||||
width: 100%; height: 100%;
|
||||
margin: 0; padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#app {
|
||||
body.cc-fullpage #app {
|
||||
width: 100%; height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
});
|
||||
const data = await response.json().catch(() => ({ error: 'The server returned an invalid response' }));
|
||||
if (!response.ok && !data.error) data.error = 'Request failed';
|
||||
if (data && typeof data === 'object') data.http_status = response.status;
|
||||
return data;
|
||||
}
|
||||
function feature(key, fallback = false) {
|
||||
@@ -631,6 +632,11 @@
|
||||
if (!state.poll.active || state.poll.generation !== generation || state.view !== 'chat') {
|
||||
return { ok: false, hasMore: false };
|
||||
}
|
||||
if (result?.http_status === 401 || result?.http_status === 423) {
|
||||
await logout(false);
|
||||
toast('Your session ended or was replaced. Sign in again.', 'info');
|
||||
return { ok: false, hasMore: false };
|
||||
}
|
||||
if (!result || result.error || !Array.isArray(result.messages)) {
|
||||
throw new Error(result?.error || 'Invalid poll response');
|
||||
}
|
||||
@@ -798,7 +804,11 @@
|
||||
const parentId = Number(event.currentTarget.dataset.parentId);
|
||||
const parent = $(`.cc-msg[data-id="${parentId}"]`);
|
||||
if (!parent) return toast('Original message is outside the current view', 'info');
|
||||
parent.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
const list = $('#messages');
|
||||
if (list) {
|
||||
const top = parent.offsetTop - ((list.clientHeight - parent.offsetHeight) / 2);
|
||||
list.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
|
||||
}
|
||||
parent.classList.add('cc-msg-focus');
|
||||
setTimeout(() => parent.classList.remove('cc-msg-focus'), 1200);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user