Fix notes tab handler guard and lint

This commit is contained in:
vgcman16 2025-06-05 21:23:06 -05:00
parent 10d192667a
commit 7912933c34
11 changed files with 68 additions and 65 deletions

View File

@ -10,7 +10,11 @@ export default function NotesTab() {
const handleAdd = () => { const handleAdd = () => {
const text = noteText.trim(); const text = noteText.trim();
if (!text) return;
if (!text) {
return;
}
addNote(text); addNote(text);
setNoteText(''); setNoteText('');
}; };
@ -27,7 +31,7 @@ export default function NotesTab() {
'border border-bolt-elements-borderColor', 'border border-bolt-elements-borderColor',
'text-bolt-elements-textPrimary', 'text-bolt-elements-textPrimary',
'focus:outline-none focus:ring-2 focus:ring-purple-500/30', 'focus:outline-none focus:ring-2 focus:ring-purple-500/30',
'min-h-[80px] resize-vertical' 'min-h-[80px] resize-vertical',
)} )}
placeholder="Add a note for the AI" placeholder="Add a note for the AI"
/> />
@ -37,25 +41,14 @@ export default function NotesTab() {
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
{notes.map((n) => ( {notes.map((n) => (
<div <div key={n.id} className="flex items-start gap-2 p-2 rounded-lg bg-bolt-elements-background-depth-2">
key={n.id} <div className="flex-1 whitespace-pre-wrap text-sm text-bolt-elements-textPrimary">{n.text}</div>
className="flex items-start gap-2 p-2 rounded-lg bg-bolt-elements-background-depth-2" <Button size="sm" variant="ghost" onClick={() => removeNote(n.id)}>
>
<div className="flex-1 whitespace-pre-wrap text-sm text-bolt-elements-textPrimary">
{n.text}
</div>
<Button
size="sm"
variant="ghost"
onClick={() => removeNote(n.id)}
>
<div className="i-ph:trash w-4 h-4" /> <div className="i-ph:trash w-4 h-4" />
</Button> </Button>
</div> </div>
))} ))}
{notes.length === 0 && ( {notes.length === 0 && <p className="text-sm text-bolt-elements-textSecondary">No notes added.</p>}
<p className="text-sm text-bolt-elements-textSecondary">No notes added.</p>
)}
</div> </div>
</div> </div>
); );

View File

@ -485,11 +485,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
</div> </div>
</StickToBottom> </StickToBottom>
<div className="flex flex-col justify-center"> <div className="flex flex-col justify-center">
{!chatStarted && ( {!chatStarted && <div className="flex justify-center gap-2">{ImportButtons(importChat)}</div>}
<div className="flex justify-center gap-2">
{ImportButtons(importChat)}
</div>
)}
<div className="flex flex-col gap-5"> <div className="flex flex-col gap-5">
{!chatStarted && {!chatStarted &&
ExamplePrompts((event, messageInput) => { ExamplePrompts((event, messageInput) => {

View File

@ -82,6 +82,7 @@ export const CodeBlock = memo(
title="Ask Bolt about this code" title="Ask Bolt about this code"
onClick={() => { onClick={() => {
const askFn = (window as any).__BOLT_ASK_SNIPPET__; const askFn = (window as any).__BOLT_ASK_SNIPPET__;
if (typeof askFn === 'function') { if (typeof askFn === 'function') {
askFn(code, language); askFn(code, language);
} }

View File

@ -1,7 +1,7 @@
import type { Message } from 'ai'; import type { Message } from 'ai';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { ImportFolderButton } from '~/components/chat/ImportFolderButton'; import { ImportFolderButton } from '~/components/chat/ImportFolderButton';
import GitCloneButton from '../GitCloneButton'; import GitCloneButton from '~/components/chat/GitCloneButton';
import { Button } from '~/components/ui/Button'; import { Button } from '~/components/ui/Button';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';

View File

@ -47,10 +47,22 @@ export function SetupWizard() {
<div className="space-y-4"> <div className="space-y-4">
<DialogTitle>Select a Provider</DialogTitle> <DialogTitle>Select a Provider</DialogTitle>
<div className="flex gap-2"> <div className="flex gap-2">
<DialogButton type="primary" onClick={() => { setProvider('supabase'); setStep(2); }}> <DialogButton
type="primary"
onClick={() => {
setProvider('supabase');
setStep(2);
}}
>
Supabase Supabase
</DialogButton> </DialogButton>
<DialogButton type="primary" onClick={() => { setProvider('firebase'); setStep(2); }}> <DialogButton
type="primary"
onClick={() => {
setProvider('firebase');
setStep(2);
}}
>
Firebase Firebase
</DialogButton> </DialogButton>
</div> </div>
@ -85,7 +97,9 @@ export function SetupWizard() {
)} )}
{supabaseConn.credentials && ( {supabaseConn.credentials && (
<div className="space-y-2 text-xs bg-bolt-elements-background-depth-3 p-3 rounded"> <div className="space-y-2 text-xs bg-bolt-elements-background-depth-3 p-3 rounded">
<div>Add these to your <code>.env.local</code>:</div> <div>
Add these to your <code>.env.local</code>:
</div>
<pre>{`VITE_SUPABASE_URL=${supabaseConn.credentials.supabaseUrl}\nVITE_SUPABASE_ANON_KEY=${supabaseConn.credentials.anonKey}`}</pre> <pre>{`VITE_SUPABASE_URL=${supabaseConn.credentials.supabaseUrl}\nVITE_SUPABASE_ANON_KEY=${supabaseConn.credentials.anonKey}`}</pre>
<div className="mt-2">Sample code:</div> <div className="mt-2">Sample code:</div>
<pre>{`import { createClient } from '@supabase/supabase-js';\n\nexport const supabase = createClient(import.meta.env.VITE_SUPABASE_URL!, import.meta.env.VITE_SUPABASE_ANON_KEY!);`}</pre> <pre>{`import { createClient } from '@supabase/supabase-js';\n\nexport const supabase = createClient(import.meta.env.VITE_SUPABASE_URL!, import.meta.env.VITE_SUPABASE_ANON_KEY!);`}</pre>
@ -111,12 +125,16 @@ export function SetupWizard() {
value={firebase.projectId} value={firebase.projectId}
onChange={(e) => updateFirebaseConfig({ projectId: e.currentTarget.value })} onChange={(e) => updateFirebaseConfig({ projectId: e.currentTarget.value })}
/> />
<DialogButton type="primary" onClick={handleFirebaseSave}>Save</DialogButton> <DialogButton type="primary" onClick={handleFirebaseSave}>
Save
</DialogButton>
</div> </div>
)} )}
{provider === 'firebase' && step === 3 && ( {provider === 'firebase' && step === 3 && (
<div className="space-y-2 text-xs bg-bolt-elements-background-depth-3 p-3 rounded"> <div className="space-y-2 text-xs bg-bolt-elements-background-depth-3 p-3 rounded">
<div>Add these to your <code>.env.local</code>:</div> <div>
Add these to your <code>.env.local</code>:
</div>
<pre>{`VITE_FIREBASE_API_KEY=${firebase.apiKey}\nVITE_FIREBASE_AUTH_DOMAIN=${firebase.authDomain}\nVITE_FIREBASE_PROJECT_ID=${firebase.projectId}`}</pre> <pre>{`VITE_FIREBASE_API_KEY=${firebase.apiKey}\nVITE_FIREBASE_AUTH_DOMAIN=${firebase.authDomain}\nVITE_FIREBASE_PROJECT_ID=${firebase.projectId}`}</pre>
<div className="mt-2">Sample code:</div> <div className="mt-2">Sample code:</div>
<pre>{`import { initializeApp } from 'firebase/app';\nimport { getAuth } from 'firebase/auth';\nimport { getFirestore } from 'firebase/firestore';\n\nconst firebaseConfig = {\n apiKey: import.meta.env.VITE_FIREBASE_API_KEY!,\n authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN!,\n projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID!,\n};\n\nconst app = initializeApp(firebaseConfig);\nexport const auth = getAuth(app);\nexport const db = getFirestore(app);`}</pre> <pre>{`import { initializeApp } from 'firebase/app';\nimport { getAuth } from 'firebase/auth';\nimport { getFirestore } from 'firebase/firestore';\n\nconst firebaseConfig = {\n apiKey: import.meta.env.VITE_FIREBASE_API_KEY!,\n authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN!,\n projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID!,\n};\n\nconst app = initializeApp(firebaseConfig);\nexport const auth = getAuth(app);\nexport const db = getFirestore(app);`}</pre>

View File

@ -3,18 +3,22 @@ export interface Feature {
* Unique identifier for the feature. * Unique identifier for the feature.
*/ */
id: string; id: string;
/** /**
* Short title of the feature to display in the UI. * Short title of the feature to display in the UI.
*/ */
name: string; name: string;
/** /**
* Description of what the feature does. * Description of what the feature does.
*/ */
description: string; description: string;
/** /**
* Whether the user has already viewed/acknowledged this feature. * Whether the user has already viewed/acknowledged this feature.
*/ */
viewed: boolean; viewed: boolean;
/** /**
* ISO date string for when the feature was released. * ISO date string for when the feature was released.
*/ */

View File

@ -31,24 +31,12 @@ export class PromptLibrary {
default: { default: {
label: 'Default Prompt', label: 'Default Prompt',
description: 'This is the battle tested default system Prompt', description: 'This is the battle tested default system Prompt',
get: (options) => get: (options) => getSystemPrompt(options.cwd, options.supabase, options.designScheme, options.userNotes),
getSystemPrompt(
options.cwd,
options.supabase,
options.designScheme,
options.userNotes,
),
}, },
enhanced: { enhanced: {
label: 'Fine Tuned Prompt', label: 'Fine Tuned Prompt',
description: 'An fine tuned prompt for better results', description: 'An fine tuned prompt for better results',
get: (options) => get: (options) => getFineTunedPrompt(options.cwd, options.supabase, options.designScheme, options.userNotes),
getFineTunedPrompt(
options.cwd,
options.supabase,
options.designScheme,
options.userNotes,
),
}, },
optimized: { optimized: {
label: 'Optimized Prompt (experimental)', label: 'Optimized Prompt (experimental)',

View File

@ -12,6 +12,7 @@ function loadNotes(): Note[] {
if (typeof localStorage === 'undefined') { if (typeof localStorage === 'undefined') {
return []; return [];
} }
try { try {
const json = localStorage.getItem(NOTES_KEY); const json = localStorage.getItem(NOTES_KEY);
return json ? JSON.parse(json) : []; return json ? JSON.parse(json) : [];
@ -21,7 +22,10 @@ function loadNotes(): Note[] {
} }
function saveNotes(notes: Note[]) { function saveNotes(notes: Note[]) {
if (typeof localStorage === 'undefined') return; if (typeof localStorage === 'undefined') {
return;
}
try { try {
localStorage.setItem(NOTES_KEY, JSON.stringify(notes)); localStorage.setItem(NOTES_KEY, JSON.stringify(notes));
} catch {} } catch {}

View File

@ -629,12 +629,9 @@ export class WorkbenchStore {
} }
} }
actionStreamSampler = createSampler( actionStreamSampler = createSampler(async (data: ActionCallbackData, isStreaming: boolean = false) => {
async (data: ActionCallbackData, isStreaming: boolean = false) => { return await this._runAction(data, isStreaming);
return await this._runAction(data, isStreaming); }, ACTION_STREAM_SAMPLE_INTERVAL);
},
ACTION_STREAM_SAMPLE_INTERVAL,
);
#getArtifact(id: string) { #getArtifact(id: string) {
const artifacts = this.artifacts.get(); const artifacts = this.artifacts.get();

View File

@ -38,23 +38,24 @@ function parseCookies(cookieHeader: string): Record<string, string> {
} }
async function chatAction({ context, request }: ActionFunctionArgs) { async function chatAction({ context, request }: ActionFunctionArgs) {
const { messages, files, promptId, contextOptimization, supabase, chatMode, designScheme, userNotes } = await request.json<{ const { messages, files, promptId, contextOptimization, supabase, chatMode, designScheme, userNotes } =
messages: Messages; await request.json<{
files: any; messages: Messages;
promptId?: string; files: any;
contextOptimization: boolean; promptId?: string;
chatMode: 'discuss' | 'build'; contextOptimization: boolean;
designScheme?: DesignScheme; chatMode: 'discuss' | 'build';
userNotes?: string; designScheme?: DesignScheme;
supabase?: { userNotes?: string;
isConnected: boolean; supabase?: {
hasSelectedProject: boolean; isConnected: boolean;
credentials?: { hasSelectedProject: boolean;
anonKey?: string; credentials?: {
supabaseUrl?: string; anonKey?: string;
supabaseUrl?: string;
};
}; };
}; }>();
}>();
const cookieHeader = request.headers.get('Cookie'); const cookieHeader = request.headers.get('Cookie');
const apiKeys = JSON.parse(parseCookies(cookieHeader || '').apiKeys || '{}'); const apiKeys = JSON.parse(parseCookies(cookieHeader || '').apiKeys || '{}');

View File

@ -8,6 +8,7 @@ export const MODEL_REGEX = /^\[Model: (.*?)\]\n\n/;
export const PROVIDER_REGEX = /\[Provider: (.*?)\]\n\n/; export const PROVIDER_REGEX = /\[Provider: (.*?)\]\n\n/;
export const DEFAULT_MODEL = 'claude-3-5-sonnet-latest'; export const DEFAULT_MODEL = 'claude-3-5-sonnet-latest';
export const PROMPT_COOKIE_KEY = 'cachedPrompt'; export const PROMPT_COOKIE_KEY = 'cachedPrompt';
// Interval used by actionStreamSampler in ms // Interval used by actionStreamSampler in ms
export const ACTION_STREAM_SAMPLE_INTERVAL = 100; export const ACTION_STREAM_SAMPLE_INTERVAL = 100;