fix: push notification toggle, textarea resize, mobile viewport, card alignment
1. Fix push toggle error: VAPID key field name mismatch (public_key → vapid_public_key) 2. Fix textarea auto-resize: proper height reset, overflow handling, mobile Enter inserts newline instead of sending (send via button on mobile) 3. Fix mobile viewport overflow: add overflow-x hidden to html/body, overflow-x hidden on content container 4. Fix dashboard cards: always 4 columns with responsive text sizing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
15e7877ea0
commit
71288f64d8
@@ -20,6 +20,10 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
max-width: 100vw;
|
||||
}
|
||||
body {
|
||||
font-family: 'DM Sans', sans-serif;
|
||||
background-color: var(--bg-primary);
|
||||
|
||||
@@ -223,7 +223,7 @@ export const push = {
|
||||
request<{ id: number; message: string }>('POST', '/api/push/subscribe', subscription),
|
||||
unsubscribe: (endpoint: string) =>
|
||||
request<{ message: string }>('DELETE', '/api/push/subscribe', { endpoint }),
|
||||
vapidKey: () => request<{ public_key: string }>('GET', '/api/push/vapid-key')
|
||||
vapidKey: () => request<{ vapid_public_key: string }>('GET', '/api/push/vapid-key')
|
||||
};
|
||||
|
||||
// User profile
|
||||
|
||||
@@ -55,20 +55,29 @@
|
||||
|
||||
function autoResize() {
|
||||
if (!textareaEl) return;
|
||||
textareaEl.style.height = 'auto';
|
||||
// Reset to measure true scrollHeight
|
||||
textareaEl.style.height = '80px';
|
||||
const maxHeight = 240; // ~12 lines
|
||||
const scrollHeight = textareaEl.scrollHeight;
|
||||
if (scrollHeight > maxHeight) {
|
||||
textareaEl.style.height = maxHeight + 'px';
|
||||
textareaEl.style.overflowY = 'auto';
|
||||
textareaEl.classList.remove('overflow-hidden');
|
||||
} else {
|
||||
textareaEl.style.height = scrollHeight + 'px';
|
||||
textareaEl.style.height = Math.max(80, scrollHeight) + 'px';
|
||||
textareaEl.style.overflowY = 'hidden';
|
||||
textareaEl.classList.add('overflow-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function isMobile(): boolean {
|
||||
return typeof window !== 'undefined' && window.innerWidth < 768;
|
||||
}
|
||||
|
||||
function handleKeydown(e: KeyboardEvent) {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
// On mobile, Enter inserts newline (send via button only)
|
||||
// On desktop, Enter sends, Shift+Enter inserts newline
|
||||
if (e.key === 'Enter' && !e.shiftKey && !isMobile()) {
|
||||
e.preventDefault();
|
||||
handleSubmit();
|
||||
}
|
||||
@@ -161,9 +170,9 @@
|
||||
<!-- Message body -->
|
||||
<textarea
|
||||
bind:this={textareaEl}
|
||||
placeholder="Write a message..."
|
||||
class="w-full px-4 py-3 bg-transparent text-sm text-text-primary placeholder-text-secondary resize-none outline-none"
|
||||
style="min-height: 72px; max-height: 240px;"
|
||||
placeholder="Write a message... {isMobile() ? '' : '(Shift+Enter for new line)'}"
|
||||
class="w-full px-4 py-3 bg-transparent text-sm text-text-primary placeholder-text-secondary resize-none outline-none overflow-hidden"
|
||||
style="min-height: 80px; max-height: 240px;"
|
||||
bind:value={body}
|
||||
rows="3"
|
||||
onkeydown={handleKeydown}
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
{:else if $user}
|
||||
<div class="h-screen flex overflow-hidden bg-bg-primary">
|
||||
<Sidebar open={sidebarOpen} onclose={() => (sidebarOpen = false)} />
|
||||
<div class="md:ml-[260px] flex-1 flex flex-col min-w-0">
|
||||
<div class="md:ml-[260px] flex-1 flex flex-col min-w-0 overflow-x-hidden">
|
||||
<Header onMenuToggle={() => (sidebarOpen = !sidebarOpen)} />
|
||||
<main class="flex-1 overflow-y-auto flex flex-col">
|
||||
{@render children()}
|
||||
|
||||
+14
-14
@@ -91,7 +91,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="p-5 max-w-6xl">
|
||||
<div class="p-3 md:p-5 max-w-6xl w-full">
|
||||
<!-- Top bar -->
|
||||
<div class="flex items-center justify-between mb-5">
|
||||
<div>
|
||||
@@ -120,22 +120,22 @@
|
||||
{/if}
|
||||
|
||||
<!-- Summary Cards -->
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-5">
|
||||
<div class="card p-4">
|
||||
<p class="text-xs text-text-secondary mb-1">Total Messages</p>
|
||||
<p class="text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : summary.total_messages}</p>
|
||||
<div class="grid grid-cols-4 gap-2 md:gap-3 mb-5">
|
||||
<div class="card p-3 md:p-4">
|
||||
<p class="text-[10px] md:text-xs text-text-secondary mb-1">Messages</p>
|
||||
<p class="text-lg md:text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : summary.total_messages}</p>
|
||||
</div>
|
||||
<div class="card p-4">
|
||||
<p class="text-xs text-text-secondary mb-1">Agents</p>
|
||||
<p class="text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : summary.total_agents}</p>
|
||||
<div class="card p-3 md:p-4">
|
||||
<p class="text-[10px] md:text-xs text-text-secondary mb-1">Agents</p>
|
||||
<p class="text-lg md:text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : summary.total_agents}</p>
|
||||
</div>
|
||||
<div class="card p-4">
|
||||
<p class="text-xs text-text-secondary mb-1">Channels</p>
|
||||
<p class="text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : summary.total_channels}</p>
|
||||
<div class="card p-3 md:p-4">
|
||||
<p class="text-[10px] md:text-xs text-text-secondary mb-1">Channels</p>
|
||||
<p class="text-lg md:text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : summary.total_channels}</p>
|
||||
</div>
|
||||
<div class="card p-4">
|
||||
<p class="text-xs text-text-secondary mb-1">Conversations</p>
|
||||
<p class="text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : recentConversations.length}</p>
|
||||
<div class="card p-3 md:p-4">
|
||||
<p class="text-[10px] md:text-xs text-text-secondary mb-1">Convos</p>
|
||||
<p class="text-lg md:text-2xl font-bold text-text-primary font-display">{loadingData ? '-' : recentConversations.length}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
const reg = await navigator.serviceWorker.ready;
|
||||
const sub = await reg.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(keyRes.public_key)
|
||||
applicationServerKey: urlBase64ToUint8Array(keyRes.vapid_public_key)
|
||||
});
|
||||
const subJson = sub.toJSON();
|
||||
await pushApi.subscribe({
|
||||
|
||||
Reference in New Issue
Block a user