From a5094289efb87e8ea4d86a08a97d7b04dd524ff6 Mon Sep 17 00:00:00 2001 From: Stijnus <72551117+Stijnus@users.noreply.github.com> Date: Tue, 18 Feb 2025 22:00:44 +0100 Subject: [PATCH] Revert "fix: bolt dyi UI bugfix" --- .../@settings/core/ControlPanel.tsx | 27 +- .../shared/components/TabManagement.tsx | 264 +++++------------- .../@settings/tabs/debug/DebugTab.tsx | 193 ++++++------- .../@settings/tabs/features/FeaturesTab.tsx | 10 +- .../@settings/tabs/profile/ProfileTab.tsx | 40 +-- .../providers/local/LocalProvidersTab.tsx | 68 +---- .../providers/local/OllamaModelInstaller.tsx | 26 +- .../@settings/tabs/settings/SettingsTab.tsx | 139 +++++++-- app/components/chat/BaseChat.tsx | 3 +- app/lib/hooks/useSettings.ts | 21 +- app/lib/stores/settings.ts | 77 +++-- app/utils/debounce.ts | 22 +- 12 files changed, 390 insertions(+), 500 deletions(-) diff --git a/app/components/@settings/core/ControlPanel.tsx b/app/components/@settings/core/ControlPanel.tsx index 0d90975cef..c0e1903501 100644 --- a/app/components/@settings/core/ControlPanel.tsx +++ b/app/components/@settings/core/ControlPanel.tsx @@ -263,27 +263,6 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { }, }; - // Reset to default view when modal opens/closes - useEffect(() => { - if (!open) { - // Reset when closing - setActiveTab(null); - setLoadingTab(null); - setShowTabManagement(false); - } else { - // When opening, set to null to show the main view - setActiveTab(null); - } - }, [open]); - - // Handle closing - const handleClose = () => { - setActiveTab(null); - setLoadingTab(null); - setShowTabManagement(false); - onClose(); - }; - // Handlers const handleBack = () => { if (showTabManagement) { @@ -426,8 +405,8 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { { {/* Close Button */} + ))} +
@@ -175,7 +245,7 @@ export default function SettingsTab() {
- {/* Simplified Keyboard Shortcuts */} + {/* Keyboard Shortcuts */}
-
-
- Toggle Theme - Switch between light and dark mode + {Object.entries(useStore(shortcutsStore)).map(([name, shortcut]) => ( +
+
+ + {name.replace(/([A-Z])/g, ' $1').toLowerCase()} + + {shortcut.description && ( + {shortcut.description} + )} +
+
+ {shortcut.ctrlOrMetaKey && ( + + {getModifierSymbol(isMac ? 'meta' : 'ctrl')} + + )} + {shortcut.ctrlKey && ( + + {getModifierSymbol('ctrl')} + + )} + {shortcut.metaKey && ( + + {getModifierSymbol('meta')} + + )} + {shortcut.altKey && ( + + {getModifierSymbol('alt')} + + )} + {shortcut.shiftKey && ( + + {getModifierSymbol('shift')} + + )} + + {formatShortcutKey(shortcut.key)} + +
-
- - {getModifierSymbol('meta')} - - - {getModifierSymbol('alt')} - - - {getModifierSymbol('shift')} - - - D - -
-
+ ))}
diff --git a/app/components/chat/BaseChat.tsx b/app/components/chat/BaseChat.tsx index ff1f4184ae..025fa1976f 100644 --- a/app/components/chat/BaseChat.tsx +++ b/app/components/chat/BaseChat.tsx @@ -34,7 +34,6 @@ import ChatAlert from './ChatAlert'; import type { ModelInfo } from '~/lib/modules/llm/types'; import ProgressCompilation from './ProgressCompilation'; import type { ProgressAnnotation } from '~/types/context'; -import { LOCAL_PROVIDERS } from '~/lib/stores/settings'; const TEXTAREA_MIN_HEIGHT = 76; @@ -405,7 +404,7 @@ export const BaseChat = React.forwardRef( apiKeys={apiKeys} modelLoading={isModelLoading} /> - {(providerList || []).length > 0 && provider && !LOCAL_PROVIDERS.includes(provider.name) && ( + {(providerList || []).length > 0 && provider && ( ; activeProviders: ProviderInfo[]; updateProviderSettings: (provider: string, config: IProviderSetting) => void; + isLocalModel: boolean; + enableLocalModels: (enabled: boolean) => void; // Debug and development settings debug: boolean; @@ -76,6 +81,7 @@ export function useSettings(): UseSettingsReturn { const debug = useStore(isDebugMode); const eventLogs = useStore(isEventLogsEnabled); const promptId = useStore(promptStore); + const isLocalModel = useStore(isLocalModelsEnabled); const isLatestBranch = useStore(latestBranchStore); const autoSelectTemplate = useStore(autoSelectStarterTemplate); const [activeProviders, setActiveProviders] = useState([]); @@ -94,12 +100,16 @@ export function useSettings(): UseSettingsReturn { }); useEffect(() => { - const active = Object.entries(providers) + let active = Object.entries(providers) .filter(([_key, provider]) => provider.settings.enabled) .map(([_k, p]) => p); + if (!isLocalModel) { + active = active.filter((p) => !LOCAL_PROVIDERS.includes(p.name)); + } + setActiveProviders(active); - }, [providers]); + }, [providers, isLocalModel]); const saveSettings = useCallback((newSettings: Partial) => { setSettings((prev) => { @@ -125,6 +135,11 @@ export function useSettings(): UseSettingsReturn { logStore.logSystem(`Event logs ${enabled ? 'enabled' : 'disabled'}`); }, []); + const enableLocalModels = useCallback((enabled: boolean) => { + updateLocalModels(enabled); + logStore.logSystem(`Local models ${enabled ? 'enabled' : 'disabled'}`); + }, []); + const setPromptId = useCallback((id: string) => { updatePromptId(id); logStore.logSystem(`Prompt template updated to ${id}`); @@ -190,6 +205,8 @@ export function useSettings(): UseSettingsReturn { providers, activeProviders, updateProviderSettings, + isLocalModel, + enableLocalModels, debug, enableDebugMode, eventLogs, diff --git a/app/lib/stores/settings.ts b/app/lib/stores/settings.ts index ccd3e2b1b3..d8b1ca186b 100644 --- a/app/lib/stores/settings.ts +++ b/app/lib/stores/settings.ts @@ -1,4 +1,5 @@ import { atom, map } from 'nanostores'; +import { workbenchStore } from './workbench'; import { PROVIDER_LIST } from '~/utils/constants'; import type { IProviderConfig } from '~/types/model'; import type { @@ -10,7 +11,7 @@ import type { import { DEFAULT_TAB_CONFIG } from '~/components/@settings/core/constants'; import Cookies from 'js-cookie'; import { toggleTheme } from './theme'; -import { create } from 'zustand'; +import { chatStore } from './chat'; export interface Shortcut { key: string; @@ -25,8 +26,10 @@ export interface Shortcut { } export interface Shortcuts { - toggleTheme: Shortcut; toggleTerminal: Shortcut; + toggleTheme: Shortcut; + toggleChat: Shortcut; + toggleSettings: Shortcut; } export const URL_CONFIGURABLE_PROVIDERS = ['Ollama', 'LMStudio', 'OpenAILike']; @@ -34,8 +37,15 @@ export const LOCAL_PROVIDERS = ['OpenAILike', 'LMStudio', 'Ollama']; export type ProviderSetting = Record; -// Simplified shortcuts store with only theme toggle +// Define safer shortcuts that don't conflict with browser defaults export const shortcutsStore = map({ + toggleTerminal: { + key: '`', + ctrlOrMetaKey: true, + action: () => workbenchStore.toggleTerminal(), + description: 'Toggle terminal', + isPreventDefault: true, + }, toggleTheme: { key: 'd', metaKey: true, @@ -45,13 +55,22 @@ export const shortcutsStore = map({ description: 'Toggle theme', isPreventDefault: true, }, - toggleTerminal: { - key: '`', + toggleChat: { + key: 'j', // Changed from 'k' to 'j' to avoid conflicts + ctrlOrMetaKey: true, + altKey: true, // Added alt key to make it more unique + action: () => chatStore.setKey('showChat', !chatStore.get().showChat), + description: 'Toggle chat', + isPreventDefault: true, + }, + toggleSettings: { + key: 's', ctrlOrMetaKey: true, + altKey: true, action: () => { - // This will be handled by the terminal component + document.dispatchEvent(new CustomEvent('toggle-settings')); }, - description: 'Toggle terminal', + description: 'Toggle settings', isPreventDefault: true, }, }); @@ -129,6 +148,7 @@ const SETTINGS_KEYS = { AUTO_SELECT_TEMPLATE: 'autoSelectTemplate', CONTEXT_OPTIMIZATION: 'contextOptimizationEnabled', EVENT_LOGS: 'isEventLogsEnabled', + LOCAL_MODELS: 'isLocalModelsEnabled', PROMPT_ID: 'promptId', DEVELOPER_MODE: 'isDeveloperMode', } as const; @@ -155,9 +175,10 @@ const getInitialSettings = () => { return { latestBranch: getStoredBoolean(SETTINGS_KEYS.LATEST_BRANCH, false), - autoSelectTemplate: getStoredBoolean(SETTINGS_KEYS.AUTO_SELECT_TEMPLATE, true), - contextOptimization: getStoredBoolean(SETTINGS_KEYS.CONTEXT_OPTIMIZATION, true), + autoSelectTemplate: getStoredBoolean(SETTINGS_KEYS.AUTO_SELECT_TEMPLATE, false), + contextOptimization: getStoredBoolean(SETTINGS_KEYS.CONTEXT_OPTIMIZATION, false), eventLogs: getStoredBoolean(SETTINGS_KEYS.EVENT_LOGS, true), + localModels: getStoredBoolean(SETTINGS_KEYS.LOCAL_MODELS, true), promptId: isBrowser ? localStorage.getItem(SETTINGS_KEYS.PROMPT_ID) || 'default' : 'default', developerMode: getStoredBoolean(SETTINGS_KEYS.DEVELOPER_MODE, false), }; @@ -170,6 +191,7 @@ export const latestBranchStore = atom(initialSettings.latestBranch); export const autoSelectStarterTemplate = atom(initialSettings.autoSelectTemplate); export const enableContextOptimizationStore = atom(initialSettings.contextOptimization); export const isEventLogsEnabled = atom(initialSettings.eventLogs); +export const isLocalModelsEnabled = atom(initialSettings.localModels); export const promptStore = atom(initialSettings.promptId); // Helper functions to update settings with persistence @@ -193,6 +215,11 @@ export const updateEventLogs = (enabled: boolean) => { localStorage.setItem(SETTINGS_KEYS.EVENT_LOGS, JSON.stringify(enabled)); }; +export const updateLocalModels = (enabled: boolean) => { + isLocalModelsEnabled.set(enabled); + localStorage.setItem(SETTINGS_KEYS.LOCAL_MODELS, JSON.stringify(enabled)); +}; + export const updatePromptId = (id: string) => { promptStore.set(id); localStorage.setItem(SETTINGS_KEYS.PROMPT_ID, id); @@ -292,35 +319,3 @@ export const setDeveloperMode = (value: boolean) => { localStorage.setItem(SETTINGS_KEYS.DEVELOPER_MODE, JSON.stringify(value)); } }; - -// First, let's define the SettingsStore interface -interface SettingsStore { - isOpen: boolean; - selectedTab: string; - openSettings: () => void; - closeSettings: () => void; - setSelectedTab: (tab: string) => void; -} - -export const useSettingsStore = create((set) => ({ - isOpen: false, - selectedTab: 'user', // Default tab - - openSettings: () => { - set({ - isOpen: true, - selectedTab: 'user', // Always open to user tab - }); - }, - - closeSettings: () => { - set({ - isOpen: false, - selectedTab: 'user', // Reset to user tab when closing - }); - }, - - setSelectedTab: (tab: string) => { - set({ selectedTab: tab }); - }, -})); diff --git a/app/utils/debounce.ts b/app/utils/debounce.ts index 56813aa93c..3b91d7a4e7 100644 --- a/app/utils/debounce.ts +++ b/app/utils/debounce.ts @@ -1,13 +1,17 @@ -export function debounce any>(func: T, wait: number): (...args: Parameters) => void { - let timeout: NodeJS.Timeout; +export function debounce(fn: (...args: Args) => void, delay = 100) { + if (delay === 0) { + return fn; + } - return function executedFunction(...args: Parameters) { - const later = () => { - clearTimeout(timeout); - func(...args); - }; + let timer: number | undefined; - clearTimeout(timeout); - timeout = setTimeout(later, wait); + return function (this: U, ...args: Args) { + const context = this; + + clearTimeout(timer); + + timer = window.setTimeout(() => { + fn.apply(context, args); + }, delay); }; }