welcome screen prototype

frdel committed Oct 30, 2025 at 10:35 UTC 8798d6f861645328084c502508dc7e9e8fa32d37
4 files changed +124 -88
webui/components/sidebar/top-section/quick-actions.html
+61 -48
@@ -1,9 +1,11 @@
1 <html>
2 +
3 <head>
4 <script type="module">
5 import { store } from "/components/sidebar/chats/chats-store.js";
6 </script>
7 </head>
8 +
9 <body>
10 <div class="config-section" x-data>
11 <button class="config-button" id="resetChat" @click="$store.chats.resetChat()">Reset Chat</button>
@@ -12,56 +14,67 @@
14 <button class="config-button" id="loadChat" @click="$store.chats.saveChat()">Save Chat</button>
15 <button class="config-button" id="restart" @click="$store.chats.restart()">Restart</button>
16 <button class="config-button" id="settings" @click="settingsModalProxy.openModal()"><svg
15 - xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.0 -17.0 110.0 135.0" fill="currentColor"
16 - width="24" height="24">
17 + xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.0 -17.0 110.0 135.0" fill="currentColor" width="24"
18 + height="24">
19 <path
18 - d="m52.301 90.102h-4.1016c-3 0-5 0-6.8984-1.3984-1.8984-1.3984-2.5-3.3008-3.5-6.1016l-1.1016-3.6016c-0.19922-0.60156-0.69922-1.1992-1.3984-1.6016l-1.1016-0.60156c-0.60156-0.30078-1.5-0.39844-2.3008-0.19922l-4.3008 1.1992c-3.1016 0.89844-5.1016 1.5-7.3984 0.5-2.3008-0.89844-3.3984-2.8008-5-5.6016l-1.8008-3.1016c-1.5-2.5-2.5-4.3008-2.3008-6.6992 0.19922-2.3984 1.6016-3.8008 3.6016-6.1016l3.8008-4.1992c0.19922-0.19922 0.60156-1.3984 0.60156-2.6016 0-1.1016-0.5-2.3008-0.80078-2.6992l-3.6016-4c-2-2.1992-3.3008-3.6992-3.6016-6.1016-0.19922-2.3984 0.80078-4.1992 2.3008-6.6992l1.8008-3.1016c1.6016-2.8008 2.6992-4.6016 5-5.6016 2.3008-0.89844 4.3008-0.39844 7.3984 0.5l4.3984 1.1992c0.69922 0.10156 1.5 0 2.3008-0.30078l1.1016-0.60156c0.5-0.30078 1-0.89844 1.3008-1.6992l1.1992-3.5c0.89844-2.8008 1.6016-4.6992 3.5-6.1016 1.8984-1.3984 3.8984-1.3984 6.8984-1.3984h4.1016c3 0 5 0 6.8984 1.3984 1.8984 1.3984 2.5 3.1992 3.5 6.1016l1.1992 3.6016c0.19922 0.60156 0.69922 1.1992 1.3984 1.6016l1.1016 0.60156c0.60156 0.30078 1.5 0.39844 2.3008 0.19922l4.3008-1.1992c3.1016-0.89844 5.1016-1.5 7.3984-0.5 2.3008 0.89844 3.3984 2.8008 5 5.5l1.8008 3.1016c1.3984 2.5 2.5 4.3008 2.3008 6.6992-0.19922 2.3984-1.6016 3.8008-3.6016 6.1016l-3.9961 4.4062c-0.19922 0.19922-0.60156 1.3984-0.60156 2.6016 0 1.1016 0.5 2.3008 0.80078 2.6992l3.6016 4c2 2.1992 3.3008 3.6992 3.6016 6.1016 0.19922 2.3984-0.80078 4.1992-2.3008 6.6992l-1.8008 3.1016c-1.6016 2.8008-2.6992 4.6016-5 5.6016-2.3008 0.89844-4.3984 0.39844-7.3984-0.5l-4.3984-1.1992c-0.69922-0.10156-1.5 0-2.3008 0.30078l-1.1016 0.60156c-0.5 0.30078-1 0.89844-1.3008 1.6992l-1.1992 3.5c-0.89844 2.8008-1.6016 4.6992-3.5 6.1016-1.8008 1.293-3.8008 1.293-6.8008 1.293zm-6.6016-7.3008c0.5 0.10156 1.6016 0.10156 2.6016 0.10156h4.1016c1 0 2 0 2.6016-0.10156 0.19922-0.5 0.60156-1.5 0.89844-2.3984l1.1992-3.6016c0.89844-2.3008 2.3984-4.1992 4.3984-5.3984l1.3984-0.80078c2.3984-1.3008 5.1016-1.6016 7.6016-1l4.6016 1.3008c1 0.30078 2.1016 0.60156 2.6992 0.69922 0.30078-0.5 0.89844-1.5 1.3984-2.3984l1.8008-3.1016c0.5-0.80078 1-1.8008 1.1992-2.3008-0.30078-0.39844-1-1.1992-1.6992-2l-3.8008-4.1992c-1.6016-2-2.5-4.8008-2.5-7.3984 0-2.6016 0.89844-5.3984 2.3008-7.3008l3.8984-4.3984c0.69922-0.69922 1.3984-1.5 1.6992-2-0.19922-0.5-0.80078-1.3984-1.1992-2.3008l-1.8984-3.1016c-0.5-0.89844-1.1016-1.8984-1.3984-2.3984-0.60156 0.10156-1.6992 0.39844-2.6992 0.69922l-4.3984 1.3008c-2.6992 0.60156-5.3008 0.30078-7.6016-0.89844l-1.4023-0.80469c-2.1016-1.3984-3.6016-3.1992-4.3984-5.3984l-1.3008-3.8008c-0.30078-0.89844-0.60156-1.8984-0.89844-2.3984-0.5-0.10156-1.6016-0.10156-2.6016-0.10156h-4.1016c-1 0-2 0-2.6016 0.10156-0.19922 0.5-0.60156 1.5-0.89844 2.3984l-1.1992 3.6016c-0.89844 2.3008-2.3984 4.1992-4.3984 5.3984l-1.3984 0.80078c-2.3984 1.3008-5.1016 1.6016-7.6016 1l-4.6016-1.3008c-1-0.30078-2.1016-0.60156-2.6992-0.69922-0.30078 0.5-0.89844 1.5-1.3984 2.3984l-1.8008 3.1016c-0.5 0.80078-1 1.8008-1.1992 2.3008 0.30078 0.39844 1 1.1992 1.6992 2l3.8008 4.1992c1.6016 2 2.5 4.8008 2.5 7.3984 0 2.6016-0.89844 5.3984-2.3008 7.3008l-3.8984 4.3984c-0.69922 0.69922-1.3984 1.5-1.6992 2 0.19922 0.5 0.80078 1.3984 1.1992 2.3008l1.8008 3.1016c0.5 0.89844 1.1016 1.8984 1.3984 2.3984 0.60156-0.10156 1.6992-0.39844 2.6992-0.69922l4.3984-1.1992c2.6992-0.60156 5.3008-0.30078 7.6016 0.89844l1.3984 0.80078c2.1016 1.3008 3.6016 3.1992 4.3984 5.3984l1.3008 3.8008c0.5 0.80078 0.80078 1.8008 1 2.3008z"></path>
20 + d="m52.301 90.102h-4.1016c-3 0-5 0-6.8984-1.3984-1.8984-1.3984-2.5-3.3008-3.5-6.1016l-1.1016-3.6016c-0.19922-0.60156-0.69922-1.1992-1.3984-1.6016l-1.1016-0.60156c-0.60156-0.30078-1.5-0.39844-2.3008-0.19922l-4.3008 1.1992c-3.1016 0.89844-5.1016 1.5-7.3984 0.5-2.3008-0.89844-3.3984-2.8008-5-5.6016l-1.8008-3.1016c-1.5-2.5-2.5-4.3008-2.3008-6.6992 0.19922-2.3984 1.6016-3.8008 3.6016-6.1016l3.8008-4.1992c0.19922-0.19922 0.60156-1.3984 0.60156-2.6016 0-1.1016-0.5-2.3008-0.80078-2.6992l-3.6016-4c-2-2.1992-3.3008-3.6992-3.6016-6.1016-0.19922-2.3984 0.80078-4.1992 2.3008-6.6992l1.8008-3.1016c1.6016-2.8008 2.6992-4.6016 5-5.6016 2.3008-0.89844 4.3008-0.39844 7.3984 0.5l4.3984 1.1992c0.69922 0.10156 1.5 0 2.3008-0.30078l1.1016-0.60156c0.5-0.30078 1-0.89844 1.3008-1.6992l1.1992-3.5c0.89844-2.8008 1.6016-4.6992 3.5-6.1016 1.8984-1.3984 3.8984-1.3984 6.8984-1.3984h4.1016c3 0 5 0 6.8984 1.3984 1.8984 1.3984 2.5 3.1992 3.5 6.1016l1.1992 3.6016c0.19922 0.60156 0.69922 1.1992 1.3984 1.6016l1.1016 0.60156c0.60156 0.30078 1.5 0.39844 2.3008 0.19922l4.3008-1.1992c3.1016-0.89844 5.1016-1.5 7.3984-0.5 2.3008 0.89844 3.3984 2.8008 5 5.5l1.8008 3.1016c1.3984 2.5 2.5 4.3008 2.3008 6.6992-0.19922 2.3984-1.6016 3.8008-3.6016 6.1016l-3.9961 4.4062c-0.19922 0.19922-0.60156 1.3984-0.60156 2.6016 0 1.1016 0.5 2.3008 0.80078 2.6992l3.6016 4c2 2.1992 3.3008 3.6992 3.6016 6.1016 0.19922 2.3984-0.80078 4.1992-2.3008 6.6992l-1.8008 3.1016c-1.6016 2.8008-2.6992 4.6016-5 5.6016-2.3008 0.89844-4.3984 0.39844-7.3984-0.5l-4.3984-1.1992c-0.69922-0.10156-1.5 0-2.3008 0.30078l-1.1016 0.60156c-0.5 0.30078-1 0.89844-1.3008 1.6992l-1.1992 3.5c-0.89844 2.8008-1.6016 4.6992-3.5 6.1016-1.8008 1.293-3.8008 1.293-6.8008 1.293zm-6.6016-7.3008c0.5 0.10156 1.6016 0.10156 2.6016 0.10156h4.1016c1 0 2 0 2.6016-0.10156 0.19922-0.5 0.60156-1.5 0.89844-2.3984l1.1992-3.6016c0.89844-2.3008 2.3984-4.1992 4.3984-5.3984l1.3984-0.80078c2.3984-1.3008 5.1016-1.6016 7.6016-1l4.6016 1.3008c1 0.30078 2.1016 0.60156 2.6992 0.69922 0.30078-0.5 0.89844-1.5 1.3984-2.3984l1.8008-3.1016c0.5-0.80078 1-1.8008 1.1992-2.3008-0.30078-0.39844-1-1.1992-1.6992-2l-3.8008-4.1992c-1.6016-2-2.5-4.8008-2.5-7.3984 0-2.6016 0.89844-5.3984 2.3008-7.3008l3.8984-4.3984c0.69922-0.69922 1.3984-1.5 1.6992-2-0.19922-0.5-0.80078-1.3984-1.1992-2.3008l-1.8984-3.1016c-0.5-0.89844-1.1016-1.8984-1.3984-2.3984-0.60156 0.10156-1.6992 0.39844-2.6992 0.69922l-4.3984 1.3008c-2.6992 0.60156-5.3008 0.30078-7.6016-0.89844l-1.4023-0.80469c-2.1016-1.3984-3.6016-3.1992-4.3984-5.3984l-1.3008-3.8008c-0.30078-0.89844-0.60156-1.8984-0.89844-2.3984-0.5-0.10156-1.6016-0.10156-2.6016-0.10156h-4.1016c-1 0-2 0-2.6016 0.10156-0.19922 0.5-0.60156 1.5-0.89844 2.3984l-1.1992 3.6016c-0.89844 2.3008-2.3984 4.1992-4.3984 5.3984l-1.3984 0.80078c-2.3984 1.3008-5.1016 1.6016-7.6016 1l-4.6016-1.3008c-1-0.30078-2.1016-0.60156-2.6992-0.69922-0.30078 0.5-0.89844 1.5-1.3984 2.3984l-1.8008 3.1016c-0.5 0.80078-1 1.8008-1.1992 2.3008 0.30078 0.39844 1 1.1992 1.6992 2l3.8008 4.1992c1.6016 2 2.5 4.8008 2.5 7.3984 0 2.6016-0.89844 5.3984-2.3008 7.3008l-3.8984 4.3984c-0.69922 0.69922-1.3984 1.5-1.6992 2 0.19922 0.5 0.80078 1.3984 1.1992 2.3008l1.8008 3.1016c0.5 0.89844 1.1016 1.8984 1.3984 2.3984 0.60156-0.10156 1.6992-0.39844 2.6992-0.69922l4.3984-1.1992c2.6992-0.60156 5.3008-0.30078 7.6016 0.89844l1.3984 0.80078c2.1016 1.3008 3.6016 3.1992 4.3984 5.3984l1.3008 3.8008c0.5 0.80078 0.80078 1.8008 1 2.3008z">
21 + </path>
22 <path
20 - d="m50.301 66.5c-9 0-16.398-7.3008-16.398-16.398 0-9.1016 7.3008-16.398 16.398-16.398 9.1016 0 16.398 7.3008 16.398 16.398 0 9.0977-7.3984 16.398-16.398 16.398zm0-25.5c-5 0-9.1016 4.1016-9.1016 9.1016s4.1016 9.1016 9.1016 9.1016 9.1016-4.1016 9.1016-9.1016c-0.003906-5-4.1016-9.1016-9.1016-9.1016z"></path>
21 - </svg>Settings</button>
22 - <button class="config-button" id="memory-dash"
23 - @click="openModal('settings/memory/memory-dashboard.html');">Memory</button>
23 + d="m50.301 66.5c-9 0-16.398-7.3008-16.398-16.398 0-9.1016 7.3008-16.398 16.398-16.398 9.1016 0 16.398 7.3008 16.398 16.398 0 9.0977-7.3984 16.398-16.398 16.398zm0-25.5c-5 0-9.1016 4.1016-9.1016 9.1016s4.1016 9.1016 9.1016 9.1016 9.1016-4.1016 9.1016-9.1016c-0.003906-5-4.1016-9.1016-9.1016-9.1016z">
24 + </path>
25 + </svg>Settings</button>
26 + <button class="config-button" id="memory-dash"
27 + @click="openModal('settings/memory/memory-dashboard.html');">Memory</button>
28 + <button class="config-button" id="dashboard" @click="deselectChat()">Dashboard</button>
29 +
30 </div>
31 </body>
26 - <style>
27 - .config-button {
28 - background-color: var(--color-background);
29 - border: 0.1rem solid var(--color-border);
30 - border-radius: var(--spacing-xs);
31 - cursor: pointer;
32 - display: inline;
33 - font-family: "Rubik", Arial, Helvetica, sans-serif;
34 - font-size: var(--font-size-small);
35 - opacity: 0.8;
36 - text-wrap: nowrap;
37 - width: calc(50% - var(--spacing-xs));
38 - float: left;
39 - margin: 0 var(--spacing-xs) var(--spacing-xs) 0;
40 - padding: var(--spacing-sm) 0.75rem;
41 - max-height: 2.3rem;
42 - -webkit-transition: all var(--transition-speed), transform 0.1s ease-in-out;
43 - transition: all var(--transition-speed), transform 0.1s ease-in-out;
44 - }
45 - .config-button:hover {
46 - background-color: var(--color-secondary);
47 - opacity: 1;
48 - }
49 - .config-button:active {
50 - opacity: 0.5;
51 - }
52 - #settings {
53 - display: flex;
54 - align-items: center;
55 - }
56 - .light-mode .config-button {
57 - background-color: var(--color-background);
58 - color: #333333;
59 - }
60 - .light-mode .config-button:hover {
61 - background-color: #d6dae8;
62 - }
63 - .light-mode .config-button:active {
64 - background-color: #bdc0cb;
65 - }
66 - </style>
32 +<style>
33 + .config-button {
34 + background-color: var(--color-background);
35 + border: 0.1rem solid var(--color-border);
36 + border-radius: var(--spacing-xs);
37 + cursor: pointer;
38 + display: inline;
39 + font-family: "Rubik", Arial, Helvetica, sans-serif;
40 + font-size: var(--font-size-small);
41 + opacity: 0.8;
42 + text-wrap: nowrap;
43 + width: calc(50% - var(--spacing-xs));
44 + float: left;
45 + margin: 0 var(--spacing-xs) var(--spacing-xs) 0;
46 + padding: var(--spacing-sm) 0.75rem;
47 + max-height: 2.3rem;
48 + -webkit-transition: all var(--transition-speed), transform 0.1s ease-in-out;
49 + transition: all var(--transition-speed), transform 0.1s ease-in-out;
50 + }
51 +
52 + .config-button:hover {
53 + background-color: var(--color-secondary);
54 + opacity: 1;
55 + }
56 +
57 + .config-button:active {
58 + opacity: 0.5;
59 + }
60 +
61 + #settings {
62 + display: flex;
63 + align-items: center;
64 + }
65 +
66 + .light-mode .config-button {
67 + background-color: var(--color-background);
68 + color: #333333;
69 + }
70 +
71 + .light-mode .config-button:hover {
72 + background-color: #d6dae8;
73 + }
74 +
75 + .light-mode .config-button:active {
76 + background-color: #bdc0cb;
77 + }
78 +</style>
79 +
80 </html>
\ No newline at end of file
webui/components/welcome/welcome-store.js
-1
@@ -1,5 +1,4 @@
1 import { createStore } from "/js/AlpineStore.js";
2 -import { store as contextStore } from "/components/chat/context/context-store.js";
2
3 const model = {
4 // State
webui/index.html
+6 -2
@@ -168,9 +168,13 @@
168 <!-- Project Selector -->
169 <x-component path="projects/project-selector.html"></x-component>
170 </div>
171 - <!-- Message History (actual messages) -->
172 - <div id="chat-history">
171 +
172 + <!-- Welcome Screen Component -->
173 + <div x-data x-show="$store.welcomeStore && $store.welcomeStore.isVisible">
174 + <x-component path="welcome/welcome-screen.html"></x-component>
175 </div>
176 + <!-- Message History (actual messages) -->
177 + <div id="chat-history" x-data x-show="!$store.welcomeStore || !$store.welcomeStore.isVisible"></div>
178
179 <!-- NEW: Toast Stack Component -->
180 <div style="position: relative; height: 0;">
webui/index.js
+57 -37
@@ -13,15 +13,24 @@ import { store as tasksStore } from "/components/sidebar/tasks/tasks-store.js";
13 globalThis.fetchApi = api.fetchApi; // TODO - backward compatibility for non-modular scripts, remove once refactored to alpine
14
15 // Declare variables for DOM elements, they will be assigned on DOMContentLoaded
16 -let leftPanel, rightPanel, container, chatInput, chatHistory, sendButton, inputSection, statusSection, progressBar, autoScrollSwitch, timeDate;
16 +let leftPanel,
17 + rightPanel,
18 + container,
19 + chatInput,
20 + chatHistory,
21 + sendButton,
22 + inputSection,
23 + statusSection,
24 + progressBar,
25 + autoScrollSwitch,
26 + timeDate;
27
28 let autoScroll = true;
19 -let context = "";
29 +let context = null;
30 globalThis.resetCounter = 0; // Used by stores and getChatBasedId
31 let skipOneSpeech = false;
32 let connectionStatus = undefined; // undefined = not checked yet, true = connected, false = disconnected
33
24 -
34 // Sidebar toggle logic is now handled by sidebar-store.js
35
36 export async function sendMessage() {
@@ -226,7 +235,9 @@ function setConnectionStatus(connected) {
235 connectionStatus = connected;
236 // Broadcast connection status without touching Alpine directly
237 try {
229 - window.dispatchEvent(new CustomEvent("connection-status", { detail: { connected } }));
238 + window.dispatchEvent(
239 + new CustomEvent("connection-status", { detail: { connected } })
240 + );
241 } catch (_e) {
242 // no-op
243 }
@@ -256,8 +267,13 @@ async function poll() {
267 return false;
268 }
269
259 - if (!context) setContext(response.context);
260 - if (response.context != context) return; //skip late polls after context change
270 + if (
271 + response.context != context &&
272 + !(response.context === null && context === null) &&
273 + context !== null
274 + ) {
275 + return;
276 + }
277
278 // if the chat has been reset, restart this poll as it may have been called with incorrect log_from
279 if (lastLogGuid != response.log_guid) {
@@ -311,7 +327,7 @@ async function poll() {
327 if (context) {
328 // Update selection in both stores
329 chatsStore.setSelected(context);
314 -
330 +
331 // Check if this context exists in the chats list
332 const contextExists = chatsStore.contains(context);
333
@@ -323,7 +339,7 @@ async function poll() {
339 chatsStore.setSelected(firstChatId);
340 }
341 }
326 -
342 +
343 tasksStore.setSelected(context);
344 } else {
345 // No context selected, try to select the first available item
@@ -429,8 +445,9 @@ globalThis.selectChat = async function (id) {
445 };
446
447 function generateShortId() {
432 - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
433 - let result = '';
448 + const chars =
449 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
450 + let result = "";
451 for (let i = 0; i < 8; i++) {
452 result += chars.charAt(Math.floor(Math.random() * chars.length));
453 }
@@ -440,7 +457,7 @@ function generateShortId() {
457 export const newContext = function () {
458 context = generateShortId();
459 setContext(context);
443 -}
460 +};
461 globalThis.newContext = newContext;
462
463 export const setContext = function (id) {
@@ -467,9 +484,22 @@ export const setContext = function (id) {
484 if (localStorage.getItem("speech") == "true") skipOneSpeech = true;
485 };
486
487 +export const deselectChat = function () {
488 + // Clear current context to show welcome screen
489 + setContext(null);
490 +
491 + // Clear localStorage selections so we don't auto-restore
492 + localStorage.removeItem("lastSelectedChat");
493 + localStorage.removeItem("lastSelectedTask");
494 +
495 + // Clear the chat history
496 + chatHistory.innerHTML = "";
497 +};
498 +globalThis.deselectChat = deselectChat;
499 +
500 export const getContext = function () {
501 return context;
472 -}
502 +};
503 globalThis.getContext = getContext;
504 globalThis.setContext = setContext;
505
@@ -477,7 +507,6 @@ export const getChatBasedId = function (id) {
507 return context + "-" + globalThis.resetCounter + "-" + id;
508 };
509
480 -
510 globalThis.loadChats = async function () {
511 await chatsStore.loadChats();
512 };
@@ -486,7 +515,6 @@ globalThis.saveChat = async function () {
515 await chatsStore.saveChat();
516 };
517
489 -
518 function addClassToElement(element, className) {
519 element.classList.add(className);
520 }
@@ -496,34 +524,26 @@ function removeClassFromElement(element, className) {
524 }
525
526 function justToast(text, type = "info", timeout = 5000, group = "") {
499 - notificationStore.addFrontendToastOnly(
500 - type,
501 - text,
502 - "",
503 - timeout / 1000,
504 - group
505 - )
527 + notificationStore.addFrontendToastOnly(type, text, "", timeout / 1000, group);
528 }
529 globalThis.justToast = justToast;
508 -
530
531 function toast(text, type = "info", timeout = 5000) {
532 // Convert timeout from milliseconds to seconds for new notification system
533 const display_time = Math.max(timeout / 1000, 1); // Minimum 1 second
534
535 // Use new frontend notification system based on type
515 - switch (type.toLowerCase()) {
516 - case "error":
517 - return notificationStore.frontendError(text, "Error", display_time);
518 - case "success":
519 - return notificationStore.frontendInfo(text, "Success", display_time);
520 - case "warning":
521 - return notificationStore.frontendWarning(text, "Warning", display_time);
522 - case "info":
523 - default:
524 - return notificationStore.frontendInfo(text, "Info", display_time);
525 - }
526 -
536 + switch (type.toLowerCase()) {
537 + case "error":
538 + return notificationStore.frontendError(text, "Error", display_time);
539 + case "success":
540 + return notificationStore.frontendInfo(text, "Success", display_time);
541 + case "warning":
542 + return notificationStore.frontendWarning(text, "Warning", display_time);
543 + case "info":
544 + default:
545 + return notificationStore.frontendInfo(text, "Info", display_time);
546 + }
547 }
548 globalThis.toast = toast;
549
@@ -540,7 +560,7 @@ function updateAfterScroll() {
560 const tolerancePx = 10;
561 const chatHistory = document.getElementById("chat-history");
562 if (!chatHistory) return;
543 -
563 +
564 const isAtBottom =
565 chatHistory.scrollHeight - chatHistory.scrollTop <=
566 chatHistory.clientHeight + tolerancePx;
@@ -590,9 +610,9 @@ document.addEventListener("DOMContentLoaded", function () {
610 progressBar = document.getElementById("progress-bar");
611 autoScrollSwitch = document.getElementById("auto-scroll-switch");
612 timeDate = document.getElementById("time-date-container");
593 -
613 +
614 // Sidebar and input event listeners are now handled by their respective stores
595 -
615 +
616 if (chatHistory) {
617 chatHistory.addEventListener("scroll", updateAfterScroll);
618 }