|
1 | 1 | import { useStore } from '@nanostores/preact';
|
2 |
| -import { ComponentChild } from 'preact'; |
3 |
| -// Removed useEffect, useRef |
4 |
| -// Removed import './app.css'; |
| 2 | +import { ComponentChild, VNode } from 'preact'; // Import VNode |
| 3 | +import { FunctionalComponent } from 'preact'; |
| 4 | +import { useEffect, useRef } from 'preact/hooks'; // Added useRef |
5 | 5 | import { SettingPage } from './pages/SettingPage';
|
6 | 6 | import { ChatPage } from './pages/ChatPage';
|
7 |
| -import { ChatListPage } from './pages/ChatListPage'; // Import ChatListPage |
8 |
| -import { router } from './stores/router'; |
| 7 | +import { ChatListPage } from './pages/ChatListPage'; |
| 8 | +import { router, $location } from './stores/router'; // Import router and $location |
| 9 | +import { requestData } from './utils/communication'; |
| 10 | +import { ChatSession } from '../../src/common/types'; |
| 11 | + |
| 12 | +// Removed HeaderNavItem component as header is removed |
9 | 13 |
|
10 | 14 | export function App() {
|
11 | 15 | const page = useStore(router);
|
| 16 | + const lastLocation = useStore($location); // Get last location state |
| 17 | + const initialRedirectDone = useRef(false); // Prevent multiple redirects |
12 | 18 |
|
13 |
| - // Removed initial redirect logic |
| 19 | + // Effect to handle initial redirection from '/' |
| 20 | + useEffect(() => { |
| 21 | + // Only run once on initial load when page might be null or '/' |
| 22 | + if (!initialRedirectDone.current && (page === null || window.location.pathname === '/')) { |
| 23 | + initialRedirectDone.current = true; // Mark as done |
| 24 | + // Wait for lastLocation to be loaded (not 'loading' or 'error') |
| 25 | + if (typeof lastLocation === 'string' && lastLocation !== 'loading' && lastLocation !== 'error' && lastLocation !== '/') { |
| 26 | + console.log(`[App] Initial load: Redirecting to last location: ${lastLocation}`); |
| 27 | + router.open(lastLocation, true); // Redirect to last known location |
| 28 | + } else if (lastLocation !== 'loading') { // If loaded but invalid/error/root, go to new chat |
| 29 | + console.log(`[App] Initial load: No valid last location found (or was '/'). Redirecting to /chat/new.`); |
| 30 | + router.open('/chat/new', true); // Default redirect to new chat |
| 31 | + } |
| 32 | + // If lastLocation is still 'loading', the $location subscribe effect in router.ts will handle the initial open later. |
| 33 | + } |
| 34 | + }, [page, lastLocation]); // Rerun if page or lastLocation changes |
14 | 35 |
|
15 |
| - // --- Page Routing --- |
16 |
| - let CurrentPage: ComponentChild = null; |
| 36 | + // Effect to handle /chat/new route |
| 37 | + useEffect(() => { |
| 38 | + if (page?.route === 'newChat') { |
| 39 | + console.log('[App] Detected /chat/new route, requesting new session...'); |
| 40 | + // Prevent potential double requests if component re-renders quickly |
| 41 | + let createRequestSent = false; // Use a simple flag within the effect's scope |
| 42 | + if (!createRequestSent) { |
| 43 | + createRequestSent = true; |
| 44 | + requestData<ChatSession>('createNewChat') |
| 45 | + .then(newSession => { |
| 46 | + if (newSession?.id) { |
| 47 | + console.log(`[App] New session created: ${newSession.id}. Redirecting...`); |
| 48 | + router.open(`/chat/${newSession.id}`, true); // Redirect with replace |
| 49 | + } else { |
| 50 | + console.error('[App] Backend did not return a valid new session.'); |
| 51 | + router.open('/chat/list'); // Fallback to list |
| 52 | + } |
| 53 | + }) |
| 54 | + .catch(error => { |
| 55 | + console.error('[App] Error creating new chat:', error); |
| 56 | + router.open('/chat/list'); // Fallback to list |
| 57 | + }); |
| 58 | + // Note: createRequestSent flag only prevents immediate re-trigger within the same render cycle. |
| 59 | + // If the component unmounts and remounts quickly on the same route, it might still trigger again. |
| 60 | + // A more robust solution might involve a store or ref if needed, but this handles simple cases. |
| 61 | + } |
| 62 | + } |
| 63 | + }, [page]); // Depend only on page |
17 | 64 |
|
18 |
| - // Wait for the router 'page' object to be defined |
19 |
| - if (!page) { |
20 |
| - return ( |
21 |
| - <div class="flex justify-center items-center h-screen text-gray-500 dark:text-gray-400"> |
22 |
| - Initializing Router... |
23 |
| - </div> |
24 |
| - ); |
25 |
| - } |
| 65 | + // --- Page Routing --- |
| 66 | + let CurrentPage: ComponentChild | VNode<any> | null = null; |
26 | 67 |
|
27 |
| - // Determine which component to render based on the route name |
28 |
| - // '/' and '/chat/:chatId' now both render ChatPage |
29 |
| - if (page.route === 'home' || page.route === 'chat') { |
30 |
| - // Pass potential chatId from params. ChatPage will handle if it's undefined. |
31 |
| - const chatId = (page.route === 'chat' && page.params && page.params.chatId) ? page.params.chatId : undefined; |
32 |
| - // Use key={chatId || 'new'} to ensure component remounts when navigating between '/' and '/chat/:id' |
33 |
| - // or between different chat IDs. 'new' key for the initial '/' load. |
34 |
| - CurrentPage = <ChatPage key={chatId || 'new'} chatIdFromRoute={chatId} />; |
| 68 | + // Handle initial loading state or root path before redirect |
| 69 | + if (!page || page.path === '/') { |
| 70 | + CurrentPage = ( |
| 71 | + <div class="flex justify-center items-center h-full bg-background text-foreground/70"> |
| 72 | + <span class="i-carbon-circle-dash animate-spin mr-2"></span> |
| 73 | + Loading... |
| 74 | + </div> |
| 75 | + ); |
| 76 | + } else if (page.route === 'chat') { // Specific chat |
| 77 | + const chatId = page.params.chatId; |
| 78 | + CurrentPage = <ChatPage key={chatId} chatIdFromRoute={chatId} />; |
35 | 79 | } else if (page.route === 'settings') {
|
36 | 80 | CurrentPage = <SettingPage />;
|
37 |
| - } else if (page.route === 'sessions') { // Add route for sessions |
| 81 | + } else if (page.route === 'chatList') { // Use new route name 'chatList' |
38 | 82 | CurrentPage = <ChatListPage />;
|
39 |
| - } else { |
40 |
| - // Fallback for unknown routes |
41 |
| - CurrentPage = <div class="p-6 text-center text-red-500">404: Page Not Found</div>; |
| 83 | + } else if (page.route === 'newChat') { // Display loading while creating |
| 84 | + CurrentPage = ( |
| 85 | + <div class="flex justify-center items-center h-full bg-background text-foreground/70"> |
| 86 | + <span class="i-carbon-circle-dash animate-spin mr-2"></span> |
| 87 | + Creating new chat... |
| 88 | + </div> |
| 89 | + ); |
| 90 | + } else { // Fallback 404 |
| 91 | + CurrentPage = <div class="p-6 text-center text-vscode-error">404: Page Not Found</div>; |
42 | 92 | }
|
43 | 93 |
|
44 | 94 | return (
|
45 |
| - <div class="flex w-screen h-screen text-gray-900 dark:text-gray-100 overflow-hidden"> |
46 |
| - <div class="flex-grow flex flex-col overflow-y-auto"> |
| 95 | + // Main container: Single column flex layout |
| 96 | + <div class="flex flex-col w-screen h-screen bg-background text-foreground overflow-hidden font-sans text-vscode"> |
| 97 | + {/* Main Content Area */} |
| 98 | + <main class="flex-1 flex flex-col overflow-y-auto"> |
47 | 99 | {CurrentPage}
|
48 |
| - </div> |
| 100 | + </main> |
49 | 101 | </div>
|
50 | 102 | );
|
51 | 103 | }
|
0 commit comments