From 7535e161601249cc51c0523cdd1f0eaaef41b34b Mon Sep 17 00:00:00 2001 From: xKevIsDev Date: Tue, 8 Jul 2025 02:08:32 +0100 Subject: [PATCH] chore: remove redundant features - Remove getPackageJson and getGitInfo from vite config - Remove Updates tab and all related logic as there was no true update logic in the codebase --- .../@settings/core/ControlPanel.tsx | 14 +- app/components/@settings/core/constants.ts | 28 +- app/components/@settings/core/types.ts | 4 +- .../@settings/tabs/update/UpdateTab.tsx | 628 ------------------ app/lib/hooks/index.ts | 1 - app/lib/hooks/useUpdateCheck.ts | 58 -- vite.config.ts | 63 -- 7 files changed, 13 insertions(+), 783 deletions(-) delete mode 100644 app/components/@settings/tabs/update/UpdateTab.tsx delete mode 100644 app/lib/hooks/useUpdateCheck.ts diff --git a/app/components/@settings/core/ControlPanel.tsx b/app/components/@settings/core/ControlPanel.tsx index e1a25bf..1622146 100644 --- a/app/components/@settings/core/ControlPanel.tsx +++ b/app/components/@settings/core/ControlPanel.tsx @@ -3,7 +3,6 @@ import { useStore } from '@nanostores/react'; import * as RadixDialog from '@radix-ui/react-dialog'; import { classNames } from '~/utils/classNames'; import { TabTile } from '~/components/@settings/shared/components/TabTile'; -import { useUpdateCheck } from '~/lib/hooks/useUpdateCheck'; import { useFeatures } from '~/lib/hooks/useFeatures'; import { useNotifications } from '~/lib/hooks/useNotifications'; import { useConnectionStatus } from '~/lib/hooks/useConnectionStatus'; @@ -22,7 +21,6 @@ import NotificationsTab from '~/components/@settings/tabs/notifications/Notifica import FeaturesTab from '~/components/@settings/tabs/features/FeaturesTab'; import { DataTab } from '~/components/@settings/tabs/data/DataTab'; import { EventLogsTab } from '~/components/@settings/tabs/event-logs/EventLogsTab'; -import UpdateTab from '~/components/@settings/tabs/update/UpdateTab'; import ConnectionsTab from '~/components/@settings/tabs/connections/ConnectionsTab'; import CloudProvidersTab from '~/components/@settings/tabs/providers/cloud/CloudProvidersTab'; import ServiceStatusTab from '~/components/@settings/tabs/providers/status/ServiceStatusTab'; @@ -34,7 +32,7 @@ interface ControlPanelProps { } // Beta status for experimental features -const BETA_TABS = new Set(['service-status', 'update', 'local-providers']); +const BETA_TABS = new Set(['service-status', 'local-providers']); const BetaLabel = () => (
@@ -53,7 +51,6 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { const profile = useStore(profileStore) as Profile; // Status hooks - const { hasUpdate, currentVersion, acknowledgeUpdate } = useUpdateCheck(); const { hasNewFeatures, unviewedFeatures, acknowledgeAllFeatures } = useFeatures(); const { hasUnreadNotifications, unreadNotifications, markAllAsRead } = useNotifications(); const { hasConnectionIssues, currentIssue, acknowledgeIssue } = useConnectionStatus(); @@ -140,8 +137,6 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { return ; case 'event-logs': return ; - case 'update': - return ; case 'service-status': return ; default: @@ -151,8 +146,6 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { const getTabUpdateStatus = (tabId: TabType): boolean => { switch (tabId) { - case 'update': - return hasUpdate; case 'features': return hasNewFeatures; case 'notifications': @@ -166,8 +159,6 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { const getStatusMessage = (tabId: TabType): string => { switch (tabId) { - case 'update': - return `New update available (v${currentVersion})`; case 'features': return `${unviewedFeatures.length} new feature${unviewedFeatures.length === 1 ? '' : 's'} to explore`; case 'notifications': @@ -190,9 +181,6 @@ export const ControlPanel = ({ open, onClose }: ControlPanelProps) => { // Acknowledge notifications based on tab switch (tabId) { - case 'update': - acknowledgeUpdate(); - break; case 'features': acknowledgeAllFeatures(); break; diff --git a/app/components/@settings/core/constants.ts b/app/components/@settings/core/constants.ts index f4d1cfa..5969f3c 100644 --- a/app/components/@settings/core/constants.ts +++ b/app/components/@settings/core/constants.ts @@ -1,17 +1,16 @@ import type { TabType } from './types'; export const TAB_ICONS: Record = { - profile: 'i-ph:user-circle-fill', - settings: 'i-ph:gear-six-fill', - notifications: 'i-ph:bell-fill', - features: 'i-ph:star-fill', - data: 'i-ph:database-fill', - 'cloud-providers': 'i-ph:cloud-fill', - 'local-providers': 'i-ph:desktop-fill', + profile: 'i-ph:user-circle', + settings: 'i-ph:gear-six', + notifications: 'i-ph:bell', + features: 'i-ph:star', + data: 'i-ph:database', + 'cloud-providers': 'i-ph:cloud', + 'local-providers': 'i-ph:laptop', 'service-status': 'i-ph:activity-bold', - connection: 'i-ph:wifi-high-fill', - 'event-logs': 'i-ph:list-bullets-fill', - update: 'i-ph:arrow-clockwise-fill', + connection: 'i-ph:wifi-high', + 'event-logs': 'i-ph:list-bullets', }; export const TAB_LABELS: Record = { @@ -25,7 +24,6 @@ export const TAB_LABELS: Record = { 'service-status': 'Service Status', connection: 'Connection', 'event-logs': 'Event Logs', - update: 'Updates', }; export const TAB_DESCRIPTIONS: Record = { @@ -39,7 +37,6 @@ export const TAB_DESCRIPTIONS: Record = { 'service-status': 'Monitor cloud LLM service status', connection: 'Check connection status and settings', 'event-logs': 'View system events and logs', - update: 'Check for updates and release notes', }; export const DEFAULT_TAB_CONFIG = [ @@ -54,9 +51,6 @@ export const DEFAULT_TAB_CONFIG = [ // User Window Tabs (In dropdown, initially hidden) { id: 'profile', visible: true, window: 'user' as const, order: 7 }, - { id: 'settings', visible: true, window: 'user' as const, order: 8 }, - { id: 'service-status', visible: true, window: 'user' as const, order: 9 }, - - // User Window Tabs (Hidden, controlled by TaskManagerTab) - { id: 'update', visible: true, window: 'user' as const, order: 10 }, + { id: 'service-status', visible: true, window: 'user' as const, order: 8 }, + { id: 'settings', visible: true, window: 'user' as const, order: 9 }, ]; diff --git a/app/components/@settings/core/types.ts b/app/components/@settings/core/types.ts index 3d65dae..d9297cd 100644 --- a/app/components/@settings/core/types.ts +++ b/app/components/@settings/core/types.ts @@ -12,8 +12,7 @@ export type TabType = | 'local-providers' | 'service-status' | 'connection' - | 'event-logs' - | 'update'; + | 'event-logs'; export type WindowType = 'user' | 'developer'; @@ -73,7 +72,6 @@ export const TAB_LABELS: Record = { 'service-status': 'Service Status', connection: 'Connections', 'event-logs': 'Event Logs', - update: 'Updates', }; export const categoryLabels: Record = { diff --git a/app/components/@settings/tabs/update/UpdateTab.tsx b/app/components/@settings/tabs/update/UpdateTab.tsx deleted file mode 100644 index 53c05d0..0000000 --- a/app/components/@settings/tabs/update/UpdateTab.tsx +++ /dev/null @@ -1,628 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { motion } from 'framer-motion'; -import { useSettings } from '~/lib/hooks/useSettings'; -import { logStore } from '~/lib/stores/logs'; -import { toast } from 'react-toastify'; -import { Dialog, DialogRoot, DialogTitle, DialogDescription, DialogButton } from '~/components/ui/Dialog'; -import { classNames } from '~/utils/classNames'; -import { Markdown } from '~/components/chat/Markdown'; - -interface UpdateProgress { - stage: 'fetch' | 'pull' | 'install' | 'build' | 'complete'; - message: string; - progress?: number; - error?: string; - details?: { - changedFiles?: string[]; - additions?: number; - deletions?: number; - commitMessages?: string[]; - totalSize?: string; - currentCommit?: string; - remoteCommit?: string; - updateReady?: boolean; - changelog?: string; - compareUrl?: string; - }; -} - -interface UpdateSettings { - autoUpdate: boolean; - notifyInApp: boolean; - checkInterval: number; -} - -const ProgressBar = ({ progress }: { progress: number }) => ( -
- -
-); - -const UpdateProgressDisplay = ({ progress }: { progress: UpdateProgress }) => ( -
-
- {progress.message} - {progress.progress}% -
- - {progress.details && ( -
- {progress.details.changedFiles && progress.details.changedFiles.length > 0 && ( -
-
Changed Files:
-
- {/* Group files by type */} - {['Modified', 'Added', 'Deleted'].map((type) => { - const filesOfType = progress.details?.changedFiles?.filter((file) => file.startsWith(type)) || []; - - if (filesOfType.length === 0) { - return null; - } - - return ( -
-
- {type} ({filesOfType.length}) -
-
- {filesOfType.map((file, index) => { - const fileName = file.split(': ')[1]; - return ( -
-
- {fileName} -
- ); - })} -
-
- ); - })} -
-
- )} - {progress.details.totalSize &&
Total size: {progress.details.totalSize}
} - {progress.details.additions !== undefined && progress.details.deletions !== undefined && ( -
- Changes: +{progress.details.additions}{' '} - -{progress.details.deletions} -
- )} - {progress.details.currentCommit && progress.details.remoteCommit && ( -
- Updating from {progress.details.currentCommit} to {progress.details.remoteCommit} -
- )} -
- )} -
-); - -const UpdateTab = () => { - const { isLatestBranch } = useSettings(); - const [isChecking, setIsChecking] = useState(false); - const [error, setError] = useState(null); - const [updateSettings, setUpdateSettings] = useState(() => { - const stored = localStorage.getItem('update_settings'); - return stored - ? JSON.parse(stored) - : { - autoUpdate: false, - notifyInApp: true, - checkInterval: 24, - }; - }); - const [showUpdateDialog, setShowUpdateDialog] = useState(false); - const [updateProgress, setUpdateProgress] = useState(null); - - useEffect(() => { - localStorage.setItem('update_settings', JSON.stringify(updateSettings)); - }, [updateSettings]); - - const checkForUpdates = async () => { - console.log('Starting update check...'); - setIsChecking(true); - setError(null); - setUpdateProgress(null); - - try { - const branchToCheck = isLatestBranch ? 'main' : 'stable'; - - // Start the update check with streaming progress - const response = await fetch('/api/update', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - branch: branchToCheck, - autoUpdate: updateSettings.autoUpdate, - }), - }); - - if (!response.ok) { - throw new Error(`Update check failed: ${response.statusText}`); - } - - const reader = response.body?.getReader(); - - if (!reader) { - throw new Error('No response stream available'); - } - - // Read the stream - while (true) { - const { done, value } = await reader.read(); - - if (done) { - break; - } - - // Convert the chunk to text and parse the JSON - const chunk = new TextDecoder().decode(value); - const lines = chunk.split('\n').filter(Boolean); - - for (const line of lines) { - try { - const progress = JSON.parse(line) as UpdateProgress; - setUpdateProgress(progress); - - if (progress.error) { - setError(progress.error); - } - - // If we're done, update the UI accordingly - if (progress.stage === 'complete') { - setIsChecking(false); - - if (!progress.error) { - // Update check completed - toast.success('Update check completed'); - - // Show update dialog only if there are changes and auto-update is disabled - if (progress.details?.changedFiles?.length && progress.details.updateReady) { - setShowUpdateDialog(true); - } - } - } - } catch (e) { - console.error('Error parsing progress update:', e); - } - } - } - } catch (error) { - setError(error instanceof Error ? error.message : 'Unknown error occurred'); - logStore.logWarning('Update Check Failed', { - type: 'update', - message: error instanceof Error ? error.message : 'Unknown error occurred', - }); - } finally { - setIsChecking(false); - } - }; - - const handleUpdate = async () => { - setShowUpdateDialog(false); - - try { - const branchToCheck = isLatestBranch ? 'main' : 'stable'; - - // Start the update with autoUpdate set to true to force the update - const response = await fetch('/api/update', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - branch: branchToCheck, - autoUpdate: true, - }), - }); - - if (!response.ok) { - throw new Error(`Update failed: ${response.statusText}`); - } - - // Handle the update progress stream - const reader = response.body?.getReader(); - - if (!reader) { - throw new Error('No response stream available'); - } - - while (true) { - const { done, value } = await reader.read(); - - if (done) { - break; - } - - const chunk = new TextDecoder().decode(value); - const lines = chunk.split('\n').filter(Boolean); - - for (const line of lines) { - try { - const progress = JSON.parse(line) as UpdateProgress; - setUpdateProgress(progress); - - if (progress.error) { - setError(progress.error); - toast.error('Update failed'); - } - - if (progress.stage === 'complete' && !progress.error) { - toast.success('Update completed successfully'); - } - } catch (e) { - console.error('Error parsing update progress:', e); - } - } - } - } catch (error) { - setError(error instanceof Error ? error.message : 'Unknown error occurred'); - toast.error('Update failed'); - } - }; - - return ( -
- -
-
-

Updates

-

Check for and manage application updates

-
- - - {/* Update Settings Card */} - -
-
-

Update Settings

-
- -
-
-
- Automatic Updates -

- Automatically check and apply updates when available -

-
- -
- -
-
- In-App Notifications -

Show notifications when updates are available

-
- -
- -
-
- Check Interval -

How often to check for updates

-
- -
-
- - - {/* Update Status Card */} - -
-
-
-

Update Status

-
-
- {updateProgress?.details?.updateReady && !updateSettings.autoUpdate && ( - - )} - -
-
- - {/* Show progress information */} - {updateProgress && } - - {error &&
{error}
} - - {/* Show update source information */} - {updateProgress?.details?.currentCommit && updateProgress?.details?.remoteCommit && ( -
-
-
-

- Updates are fetched from: stackblitz-labs/bolt.diy ( - {isLatestBranch ? 'main' : 'stable'} branch) -

-

- Current version: {updateProgress.details.currentCommit} - - Latest version: {updateProgress.details.remoteCommit} -

-
- {updateProgress?.details?.compareUrl && ( - - - {updateProgress?.details?.additions !== undefined && updateProgress?.details?.deletions !== undefined && ( -
-
- Changes: +{updateProgress.details.additions}{' '} - -{updateProgress.details.deletions} -
- )} -
- )} - - {/* Add this before the changed files section */} - {updateProgress?.details?.changelog && ( -
-
-
-

Changelog

-
-
-
- {updateProgress.details.changelog} -
-
-
- )} - - {/* Add this in the update status card, after the commit info */} - {updateProgress?.details?.compareUrl && ( -
- - - )} - - {updateProgress?.details?.commitMessages && updateProgress.details.commitMessages.length > 0 && ( -
-

Changes in this Update:

-
-
- {updateProgress.details.commitMessages.map((section, index) => ( - {section} - ))} -
-
-
- )} - - - {/* Update dialog */} - - - Update Available - -
-

- A new version is available from stackblitz-labs/bolt.diy ( - {isLatestBranch ? 'main' : 'stable'} branch) -

- - {updateProgress?.details?.compareUrl && ( -
- - - )} - - {updateProgress?.details?.commitMessages && updateProgress.details.commitMessages.length > 0 && ( -
-

Commit Messages:

-
- {updateProgress.details.commitMessages.map((msg, index) => ( -
-
- {msg} -
- ))} -
-
- )} - - {updateProgress?.details?.totalSize && ( -
-
-
- Total size: {updateProgress.details.totalSize} -
- {updateProgress?.details?.additions !== undefined && - updateProgress?.details?.deletions !== undefined && ( -
-
- Changes: +{updateProgress.details.additions}{' '} - -{updateProgress.details.deletions} -
- )} -
- )} -
- -
- setShowUpdateDialog(false)}> - Cancel - - - Update Now - -
-
-
-
- ); -}; - -export default UpdateTab; diff --git a/app/lib/hooks/index.ts b/app/lib/hooks/index.ts index 648de4a..4fd4f8f 100644 --- a/app/lib/hooks/index.ts +++ b/app/lib/hooks/index.ts @@ -4,7 +4,6 @@ export * from './useShortcuts'; export * from './StickToBottom'; export * from './useEditChatDescription'; export { default } from './useViewport'; -export { useUpdateCheck } from './useUpdateCheck'; export { useFeatures } from './useFeatures'; export { useNotifications } from './useNotifications'; export { useConnectionStatus } from './useConnectionStatus'; diff --git a/app/lib/hooks/useUpdateCheck.ts b/app/lib/hooks/useUpdateCheck.ts deleted file mode 100644 index f53a794..0000000 --- a/app/lib/hooks/useUpdateCheck.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { useState, useEffect } from 'react'; -import { checkForUpdates, acknowledgeUpdate } from '~/lib/api/updates'; - -const LAST_ACKNOWLEDGED_VERSION_KEY = 'bolt_last_acknowledged_version'; - -export const useUpdateCheck = () => { - const [hasUpdate, setHasUpdate] = useState(false); - const [currentVersion, setCurrentVersion] = useState(''); - const [lastAcknowledgedVersion, setLastAcknowledgedVersion] = useState(() => { - try { - return localStorage.getItem(LAST_ACKNOWLEDGED_VERSION_KEY); - } catch { - return null; - } - }); - - useEffect(() => { - const checkUpdate = async () => { - try { - const { available, version } = await checkForUpdates(); - setCurrentVersion(version); - - // Only show update if it's a new version and hasn't been acknowledged - setHasUpdate(available && version !== lastAcknowledgedVersion); - } catch (error) { - console.error('Failed to check for updates:', error); - } - }; - - // Check immediately and then every 30 minutes - checkUpdate(); - - const interval = setInterval(checkUpdate, 30 * 60 * 1000); - - return () => clearInterval(interval); - }, [lastAcknowledgedVersion]); - - const handleAcknowledgeUpdate = async () => { - try { - const { version } = await checkForUpdates(); - await acknowledgeUpdate(version); - - // Store in localStorage - try { - localStorage.setItem(LAST_ACKNOWLEDGED_VERSION_KEY, version); - } catch (error) { - console.error('Failed to persist acknowledged version:', error); - } - - setLastAcknowledgedVersion(version); - setHasUpdate(false); - } catch (error) { - console.error('Failed to acknowledge update:', error); - } - }; - - return { hasUpdate, currentVersion, acknowledgeUpdate: handleAcknowledgeUpdate }; -}; diff --git a/vite.config.ts b/vite.config.ts index a1d61ff..65d4352 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,72 +5,9 @@ import { nodePolyfills } from 'vite-plugin-node-polyfills'; import { optimizeCssModules } from 'vite-plugin-optimize-css-modules'; import tsconfigPaths from 'vite-tsconfig-paths'; import * as dotenv from 'dotenv'; -import { execSync } from 'child_process'; -import { readFileSync } from 'fs'; -import { join } from 'path'; dotenv.config(); -// Get detailed git info with fallbacks -const getGitInfo = () => { - try { - return { - commitHash: execSync('git rev-parse --short HEAD').toString().trim(), - branch: execSync('git rev-parse --abbrev-ref HEAD').toString().trim(), - commitTime: execSync('git log -1 --format=%cd').toString().trim(), - author: execSync('git log -1 --format=%an').toString().trim(), - email: execSync('git log -1 --format=%ae').toString().trim(), - remoteUrl: execSync('git config --get remote.origin.url').toString().trim(), - repoName: execSync('git config --get remote.origin.url') - .toString() - .trim() - .replace(/^.*github.com[:/]/, '') - .replace(/\.git$/, ''), - }; - } catch { - return { - commitHash: 'no-git-info', - branch: 'unknown', - commitTime: 'unknown', - author: 'unknown', - email: 'unknown', - remoteUrl: 'unknown', - repoName: 'unknown', - }; - } -}; - -// Read package.json with detailed dependency info -const getPackageJson = () => { - try { - const pkgPath = join(process.cwd(), 'package.json'); - const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); - - return { - name: pkg.name, - description: pkg.description, - license: pkg.license, - dependencies: pkg.dependencies || {}, - devDependencies: pkg.devDependencies || {}, - peerDependencies: pkg.peerDependencies || {}, - optionalDependencies: pkg.optionalDependencies || {}, - }; - } catch { - return { - name: 'bolt.diy', - description: 'A DIY LLM interface', - license: 'MIT', - dependencies: {}, - devDependencies: {}, - peerDependencies: {}, - optionalDependencies: {}, - }; - } -}; - -const pkg = getPackageJson(); -const gitInfo = getGitInfo(); - export default defineConfig((config) => { return { define: {