added backdrop and loading screen

This commit is contained in:
Anirban Kar 2024-12-08 22:53:20 +05:30
parent 9f002279b6
commit b304749b21
4 changed files with 81 additions and 35 deletions

View File

@ -8,6 +8,8 @@ import { Chat } from '~/components/chat/Chat.client';
import { useGit } from '~/lib/hooks/useGit'; import { useGit } from '~/lib/hooks/useGit';
import { useChatHistory } from '~/lib/persistence'; import { useChatHistory } from '~/lib/persistence';
import { createCommandsMessage, detectProjectCommands } from '~/utils/projectCommands'; import { createCommandsMessage, detectProjectCommands } from '~/utils/projectCommands';
import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
import { toast } from 'react-toastify';
const IGNORE_PATTERNS = [ const IGNORE_PATTERNS = [
'node_modules/**', 'node_modules/**',
@ -38,6 +40,7 @@ export function GitUrlImport() {
const { ready: historyReady, importChat } = useChatHistory(); const { ready: historyReady, importChat } = useChatHistory();
const { ready: gitReady, gitClone } = useGit(); const { ready: gitReady, gitClone } = useGit();
const [imported, setImported] = useState(false); const [imported, setImported] = useState(false);
const [loading, setLoading] = useState(true);
const importRepo = async (repoUrl?: string) => { const importRepo = async (repoUrl?: string) => {
if (!gitReady && !historyReady) { if (!gitReady && !historyReady) {
@ -109,9 +112,23 @@ ${file.content}
return; return;
} }
importRepo(url); importRepo(url).catch((error) => {
console.error('Error importing repo:', error);
toast.error('Failed to import repository');
setLoading(false);
window.location.href = '/';
});
setImported(true); setImported(true);
}, [searchParams, historyReady, gitReady, imported]); }, [searchParams, historyReady, gitReady, imported]);
return <ClientOnly fallback={<BaseChat />}>{() => <Chat />}</ClientOnly>; return (
<ClientOnly fallback={<BaseChat />}>
{() => (
<>
<Chat />
{loading && <LoadingOverlay message="Please wait while we clone the repository..." />}
</>
)}
</ClientOnly>
);
} }

View File

@ -0,0 +1,14 @@
export const LoadingOverlay = ({ message = 'Loading...' }) => {
return (
<div className="fixed inset-0 flex items-center justify-center bg-black/80 z-50 backdrop-blur-sm">
{/* Loading content */}
<div className="relative flex flex-col items-center gap-4 p-8 rounded-lg bg-bolt-elements-background-depth-2 shadow-lg">
<div
className={'i-svg-spinners:90-ring-with-bg text-bolt-elements-loader-progress'}
style={{ fontSize: '2rem' }}
></div>
<p className="text-lg text-bolt-elements-textTertiary">{message}</p>
</div>
</div>
);
};

View File

@ -10,7 +10,6 @@ import { toast } from 'react-toastify';
import { useNavigate } from '@remix-run/react'; import { useNavigate } from '@remix-run/react';
import commit from '~/commit.json'; import commit from '~/commit.json';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { SettingsSlider } from './SettingsSlider';
import '~/styles/components/SettingsSlider.scss'; import '~/styles/components/SettingsSlider.scss';
import '~/styles/components/Settings.scss'; import '~/styles/components/Settings.scss';
@ -219,9 +218,7 @@ export const Settings = ({ open, onClose }: SettingsProps) => {
<button <button
key={tab.id} key={tab.id}
onClick={() => setActiveTab(tab.id)} onClick={() => setActiveTab(tab.id)}
className={classNames( className={classNames(activeTab === tab.id ? 'active' : '')}
activeTab === tab.id ? 'active' : ''
)}
> >
<div className={tab.icon} /> <div className={tab.icon} />
{tab.label} {tab.label}
@ -250,7 +247,9 @@ export const Settings = ({ open, onClose }: SettingsProps) => {
</div> </div>
<div className="flex-1 flex flex-col p-8 bg-gray-50 dark:bg-gray-800"> <div className="flex-1 flex flex-col p-8 bg-gray-50 dark:bg-gray-800">
<DialogTitle className="flex-shrink-0 text-lg font-semibold text-bolt-elements-textPrimary">Settings</DialogTitle> <DialogTitle className="flex-shrink-0 text-lg font-semibold text-bolt-elements-textPrimary">
Settings
</DialogTitle>
<div className="flex-1 overflow-y-auto"> <div className="flex-1 overflow-y-auto">
{activeTab === 'chat-history' && ( {activeTab === 'chat-history' && (
<div className="p-4"> <div className="p-4">
@ -304,14 +303,20 @@ export const Settings = ({ open, onClose }: SettingsProps) => {
checked={provider.isEnabled} checked={provider.isEnabled}
onChange={() => handleToggleProvider(provider.name)} onChange={() => handleToggleProvider(provider.name)}
/> />
<div className={classNames( <div
'settings-toggle__track', className={classNames(
provider.isEnabled ? 'settings-toggle__track--enabled' : 'settings-toggle__track--disabled' 'settings-toggle__track',
)}></div> provider.isEnabled
<div className={classNames( ? 'settings-toggle__track--enabled'
'settings-toggle__thumb', : 'settings-toggle__track--disabled',
provider.isEnabled ? 'settings-toggle__thumb--enabled' : '' )}
)}></div> ></div>
<div
className={classNames(
'settings-toggle__thumb',
provider.isEnabled ? 'settings-toggle__thumb--enabled' : '',
)}
></div>
</label> </label>
</div> </div>
{/* Base URL input for configurable providers */} {/* Base URL input for configurable providers */}
@ -343,14 +348,18 @@ export const Settings = ({ open, onClose }: SettingsProps) => {
checked={isDebugEnabled} checked={isDebugEnabled}
onChange={() => setIsDebugEnabled(!isDebugEnabled)} onChange={() => setIsDebugEnabled(!isDebugEnabled)}
/> />
<div className={classNames( <div
'settings-toggle__track', className={classNames(
isDebugEnabled ? 'settings-toggle__track--enabled' : 'settings-toggle__track--disabled' 'settings-toggle__track',
)}></div> isDebugEnabled ? 'settings-toggle__track--enabled' : 'settings-toggle__track--disabled',
<div className={classNames( )}
'settings-toggle__thumb', ></div>
isDebugEnabled ? 'settings-toggle__thumb--enabled' : '' <div
)}></div> className={classNames(
'settings-toggle__thumb',
isDebugEnabled ? 'settings-toggle__thumb--enabled' : '',
)}
></div>
</label> </label>
</div> </div>
</div> </div>
@ -367,14 +376,18 @@ export const Settings = ({ open, onClose }: SettingsProps) => {
checked={isJustSayEnabled} checked={isJustSayEnabled}
onChange={() => setIsJustSayEnabled(!isJustSayEnabled)} onChange={() => setIsJustSayEnabled(!isJustSayEnabled)}
/> />
<div className={classNames( <div
'settings-toggle__track', className={classNames(
isJustSayEnabled ? 'settings-toggle__track--enabled' : 'settings-toggle__track--disabled' 'settings-toggle__track',
)}></div> isJustSayEnabled ? 'settings-toggle__track--enabled' : 'settings-toggle__track--disabled',
<div className={classNames( )}
'settings-toggle__thumb', ></div>
isJustSayEnabled ? 'settings-toggle__thumb--enabled' : '' <div
)}></div> className={classNames(
'settings-toggle__thumb',
isJustSayEnabled ? 'settings-toggle__thumb--enabled' : '',
)}
></div>
</label> </label>
</div> </div>
</div> </div>
@ -408,7 +421,9 @@ export const Settings = ({ open, onClose }: SettingsProps) => {
<ul> <ul>
<li className="text-bolt-elements-textSecondary">Ollama: {process.env.REACT_APP_OLLAMA_URL}</li> <li className="text-bolt-elements-textSecondary">Ollama: {process.env.REACT_APP_OLLAMA_URL}</li>
<li className="text-bolt-elements-textSecondary">OpenAI: {process.env.REACT_APP_OPENAI_URL}</li> <li className="text-bolt-elements-textSecondary">OpenAI: {process.env.REACT_APP_OPENAI_URL}</li>
<li className="text-bolt-elements-textSecondary">LM Studio: {process.env.REACT_APP_LM_STUDIO_URL}</li> <li className="text-bolt-elements-textSecondary">
LM Studio: {process.env.REACT_APP_LM_STUDIO_URL}
</li>
</ul> </ul>
<h4 className="text-md font-medium text-bolt-elements-textPrimary mt-4">Version Information</h4> <h4 className="text-md font-medium text-bolt-elements-textPrimary mt-4">Version Information</h4>

View File

@ -27,7 +27,7 @@ export const SettingsSlider = memo(<T,>({ selected, options, setSelected }: Sett
<motion.div <motion.div
className={classNames( className={classNames(
'settings-slider__thumb', 'settings-slider__thumb',
isLeftSelected ? 'settings-slider__thumb--left' : 'settings-slider__thumb--right' isLeftSelected ? 'settings-slider__thumb--left' : 'settings-slider__thumb--right',
)} )}
initial={false} initial={false}
animate={{ animate={{
@ -44,7 +44,7 @@ export const SettingsSlider = memo(<T,>({ selected, options, setSelected }: Sett
onClick={() => setSelected?.(options.left.value)} onClick={() => setSelected?.(options.left.value)}
className={classNames( className={classNames(
'settings-slider__button', 'settings-slider__button',
isLeftSelected ? 'settings-slider__button--selected' : 'settings-slider__button--unselected' isLeftSelected ? 'settings-slider__button--selected' : 'settings-slider__button--unselected',
)} )}
> >
{options.left.text} {options.left.text}
@ -53,7 +53,7 @@ export const SettingsSlider = memo(<T,>({ selected, options, setSelected }: Sett
onClick={() => setSelected?.(options.right.value)} onClick={() => setSelected?.(options.right.value)}
className={classNames( className={classNames(
'settings-slider__button', 'settings-slider__button',
!isLeftSelected ? 'settings-slider__button--selected' : 'settings-slider__button--unselected' !isLeftSelected ? 'settings-slider__button--selected' : 'settings-slider__button--unselected',
)} )}
> >
{options.right.text} {options.right.text}