Spaces:
Paused
Paused
Hemang Thakur
commited on
Commit
·
a7de061
1
Parent(s):
661a2f2
added auto-scroll to the bottom
Browse files
frontend/src/Components/AiPage.css
CHANGED
@@ -288,6 +288,11 @@ button.send-btn.stop-btn:hover {
|
|
288 |
/* Chat container */
|
289 |
.chat-container {
|
290 |
flex-grow: 1;
|
|
|
|
|
|
|
|
|
|
|
291 |
margin-bottom: 40rem;
|
292 |
}
|
293 |
|
@@ -304,4 +309,4 @@ button.send-btn.stop-btn:hover {
|
|
304 |
margin: 0;
|
305 |
padding: 1rem;
|
306 |
}
|
307 |
-
}
|
|
|
288 |
/* Chat container */
|
289 |
.chat-container {
|
290 |
flex-grow: 1;
|
291 |
+
margin-bottom: 9rem;
|
292 |
+
}
|
293 |
+
|
294 |
+
/* When processing a new prompt */
|
295 |
+
.chat-container.processing {
|
296 |
margin-bottom: 40rem;
|
297 |
}
|
298 |
|
|
|
309 |
margin: 0;
|
310 |
padding: 1rem;
|
311 |
}
|
312 |
+
}
|
frontend/src/Components/AiPage.js
CHANGED
@@ -45,6 +45,9 @@ function AiPage() {
|
|
45 |
const [activeBlockId, setActiveBlockId] = useState(null);
|
46 |
const activeEventSourceRef = useRef(null);
|
47 |
|
|
|
|
|
|
|
48 |
// Snackbar state
|
49 |
const [snackbar, setSnackbar] = useState({
|
50 |
open: false,
|
@@ -71,6 +74,24 @@ function AiPage() {
|
|
71 |
const tokenExpiryTimersRef = useRef({});
|
72 |
const notificationIdsRef = useRef({});
|
73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
// Function to open the snackbar
|
75 |
const openSnackbar = useCallback((message, severity = "success", duration) => {
|
76 |
let finalDuration;
|
@@ -215,14 +236,6 @@ function AiPage() {
|
|
215 |
return Date.now() < expiryTime;
|
216 |
};
|
217 |
|
218 |
-
// Function to get valid token
|
219 |
-
const getValidToken = (provider) => {
|
220 |
-
if (isTokenValid(provider)) {
|
221 |
-
return sessionStorage.getItem(`${provider}_token`);
|
222 |
-
}
|
223 |
-
return null;
|
224 |
-
};
|
225 |
-
|
226 |
// Function to get provider icon
|
227 |
const getProviderIcon = useCallback((provider) => {
|
228 |
switch (provider.toLowerCase()) {
|
@@ -504,6 +517,11 @@ function AiPage() {
|
|
504 |
// Create a new chat block and initiate the SSE
|
505 |
const handleSend = () => {
|
506 |
if (!searchText.trim()) return;
|
|
|
|
|
|
|
|
|
|
|
507 |
const blockId = new Date().getTime();
|
508 |
setActiveBlockId(blockId);
|
509 |
setIsProcessing(true);
|
@@ -537,6 +555,13 @@ function AiPage() {
|
|
537 |
}
|
538 |
};
|
539 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
540 |
// Stop the user request and close the active SSE connection
|
541 |
const handleStop = async () => {
|
542 |
// Close the active SSE connection if it exists
|
@@ -903,7 +928,7 @@ function AiPage() {
|
|
903 |
<main className="main-content">
|
904 |
{showChatWindow ? (
|
905 |
<>
|
906 |
-
<div className=
|
907 |
{chatBlocks.map((block) => (
|
908 |
<ChatWindow
|
909 |
key={block.id}
|
|
|
45 |
const [activeBlockId, setActiveBlockId] = useState(null);
|
46 |
const activeEventSourceRef = useRef(null);
|
47 |
|
48 |
+
// State to track if we should auto-scroll to the bottom
|
49 |
+
const [autoScrollEnabled, setAutoScrollEnabled] = useState(false);
|
50 |
+
|
51 |
// Snackbar state
|
52 |
const [snackbar, setSnackbar] = useState({
|
53 |
open: false,
|
|
|
74 |
const tokenExpiryTimersRef = useRef({});
|
75 |
const notificationIdsRef = useRef({});
|
76 |
|
77 |
+
// Function to check if we are near the bottom of the page
|
78 |
+
const checkIfNearBottom = (threshold = 400) => {
|
79 |
+
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
80 |
+
const scrollHeight = document.documentElement.scrollHeight;
|
81 |
+
const clientHeight = window.innerHeight;
|
82 |
+
const distanceFromBottom = scrollHeight - (scrollTop + clientHeight);
|
83 |
+
|
84 |
+
return distanceFromBottom <= threshold;
|
85 |
+
};
|
86 |
+
|
87 |
+
// Helper to scroll to bottom
|
88 |
+
const scrollToBottom = (smooth = true) => {
|
89 |
+
window.scrollTo({
|
90 |
+
top: document.documentElement.scrollHeight,
|
91 |
+
behavior: smooth ? 'smooth' : 'auto'
|
92 |
+
});
|
93 |
+
};
|
94 |
+
|
95 |
// Function to open the snackbar
|
96 |
const openSnackbar = useCallback((message, severity = "success", duration) => {
|
97 |
let finalDuration;
|
|
|
236 |
return Date.now() < expiryTime;
|
237 |
};
|
238 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
// Function to get provider icon
|
240 |
const getProviderIcon = useCallback((provider) => {
|
241 |
switch (provider.toLowerCase()) {
|
|
|
517 |
// Create a new chat block and initiate the SSE
|
518 |
const handleSend = () => {
|
519 |
if (!searchText.trim()) return;
|
520 |
+
|
521 |
+
// Check if user is near bottom before adding new block
|
522 |
+
const shouldScroll = checkIfNearBottom(1000); // 1000px threshold
|
523 |
+
setAutoScrollEnabled(shouldScroll);
|
524 |
+
|
525 |
const blockId = new Date().getTime();
|
526 |
setActiveBlockId(blockId);
|
527 |
setIsProcessing(true);
|
|
|
555 |
}
|
556 |
};
|
557 |
|
558 |
+
// Auto-scroll when chat block is added
|
559 |
+
useEffect(() => {
|
560 |
+
if (autoScrollEnabled && isProcessing) {
|
561 |
+
scrollToBottom();
|
562 |
+
}
|
563 |
+
}, [isProcessing, autoScrollEnabled]);
|
564 |
+
|
565 |
// Stop the user request and close the active SSE connection
|
566 |
const handleStop = async () => {
|
567 |
// Close the active SSE connection if it exists
|
|
|
928 |
<main className="main-content">
|
929 |
{showChatWindow ? (
|
930 |
<>
|
931 |
+
<div className={`chat-container ${isProcessing ? 'processing' : ''}`}>
|
932 |
{chatBlocks.map((block) => (
|
933 |
<ChatWindow
|
934 |
key={block.id}
|
src/utils/api_key_manager.py
CHANGED
@@ -17,6 +17,9 @@ import asyncio
|
|
17 |
|
18 |
# Tell Pydantic to finish wiring up this dynamic model
|
19 |
ChatGoogleGenerativeAI.model_rebuild()
|
|
|
|
|
|
|
20 |
|
21 |
ModelProvider = Literal["openai", "anthropic", "google", "xai"]
|
22 |
|
|
|
17 |
|
18 |
# Tell Pydantic to finish wiring up this dynamic model
|
19 |
ChatGoogleGenerativeAI.model_rebuild()
|
20 |
+
ChatAnthropic.model_rebuild()
|
21 |
+
ChatOpenAI.model_rebuild()
|
22 |
+
ChatXAI.model_rebuild()
|
23 |
|
24 |
ModelProvider = Literal["openai", "anthropic", "google", "xai"]
|
25 |
|