diff --git a/src/App.jsx b/src/App.jsx index 3ded1e6..2be8595 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -26,6 +26,7 @@ import MainContent from './components/MainContent'; import MobileNav from './components/MobileNav'; import Settings from './components/Settings'; import QuickSettingsPanel from './components/QuickSettingsPanel'; +import VersionUpgradeModal from './components/modals/VersionUpgradeModal'; import { ThemeProvider } from './contexts/ThemeContext'; import { AuthProvider } from './contexts/AuthContext'; @@ -580,202 +581,6 @@ function AppContent() { } }, []); - // Version Upgrade Modal Component - const VersionUpgradeModal = () => { - const { t } = useTranslation('common'); - const [isUpdating, setIsUpdating] = useState(false); - const [updateOutput, setUpdateOutput] = useState(''); - const [updateError, setUpdateError] = useState(''); - - if (!showVersionModal) return null; - - // Clean up changelog by removing GitHub-specific metadata - const cleanChangelog = (body) => { - if (!body) return ''; - - return body - // Remove full commit hashes (40 character hex strings) - .replace(/\b[0-9a-f]{40}\b/gi, '') - // Remove short commit hashes (7-10 character hex strings at start of line or after dash/space) - .replace(/(?:^|\s|-)([0-9a-f]{7,10})\b/gi, '') - // Remove "Full Changelog" links - .replace(/\*\*Full Changelog\*\*:.*$/gim, '') - // Remove compare links (e.g., https://github.com/.../compare/v1.0.0...v1.0.1) - .replace(/https?:\/\/github\.com\/[^\/]+\/[^\/]+\/compare\/[^\s)]+/gi, '') - // Clean up multiple consecutive empty lines - .replace(/\n\s*\n\s*\n/g, '\n\n') - // Trim whitespace - .trim(); - }; - - const handleUpdateNow = async () => { - setIsUpdating(true); - setUpdateOutput('Starting update...\n'); - setUpdateError(''); - - try { - // Call the backend API to run the update command - const response = await authenticatedFetch('/api/system/update', { - method: 'POST', - }); - - const data = await response.json(); - - if (response.ok) { - setUpdateOutput(prev => prev + data.output + '\n'); - setUpdateOutput(prev => prev + '\n✅ Update completed successfully!\n'); - setUpdateOutput(prev => prev + 'Please restart the server to apply changes.\n'); - } else { - setUpdateError(data.error || 'Update failed'); - setUpdateOutput(prev => prev + '\n❌ Update failed: ' + (data.error || 'Unknown error') + '\n'); - } - } catch (error) { - setUpdateError(error.message); - setUpdateOutput(prev => prev + '\n❌ Update failed: ' + error.message + '\n'); - } finally { - setIsUpdating(false); - } - }; - - return ( -
- {/* Backdrop */} - -
- - {/* Version Info */} -
-
- {t('versionUpdate.currentVersion')} - {currentVersion} -
-
- {t('versionUpdate.latestVersion')} - {latestVersion} -
-
- - {/* Changelog */} - {releaseInfo?.body && ( -
-
-

{t('versionUpdate.whatsNew')}

- {releaseInfo?.htmlUrl && ( - - {t('versionUpdate.viewFullRelease')} - - - - - )} -
-
-
- {cleanChangelog(releaseInfo.body)} -
-
-
- )} - - {/* Update Output */} - {updateOutput && ( -
-

{t('versionUpdate.updateProgress')}

-
-
{updateOutput}
-
-
- )} - - {/* Upgrade Instructions */} - {!isUpdating && !updateOutput && ( -
-

{t('versionUpdate.manualUpgrade')}

-
- - git checkout main && git pull && npm install - -
-

- {t('versionUpdate.manualUpgradeHint')} -

-
- )} - - {/* Actions */} -
- - {!updateOutput && ( - <> - - - - )} -
- - - ); - }; return (
@@ -977,7 +782,7 @@ function AppContent() { /> {/* Version Upgrade Modal */} - +
); } diff --git a/src/components/modals/VersionUpgradeModal.tsx b/src/components/modals/VersionUpgradeModal.tsx new file mode 100644 index 0000000..bb7e459 --- /dev/null +++ b/src/components/modals/VersionUpgradeModal.tsx @@ -0,0 +1,206 @@ +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { authenticatedFetch } from "../../utils/api"; +import { useVersionCheck } from "../../hooks/useVersionCheck"; + +interface VersionUpgradeModalProps { + showVersionModal: boolean; + setShowVersionModal: (show: boolean) => void; +} + +export default function VersionUpgradeModal({ showVersionModal, setShowVersionModal }: VersionUpgradeModalProps) { + const { t } = useTranslation('common'); + const [isUpdating, setIsUpdating] = useState(false); + const [updateOutput, setUpdateOutput] = useState(''); + const [updateError, setUpdateError] = useState(''); + const { latestVersion, currentVersion, releaseInfo } = useVersionCheck('siteboon', 'claudecodeui'); + + if (!showVersionModal) return null; + + const handleUpdateNow = async () => { + setIsUpdating(true); + setUpdateOutput('Starting update...\n'); + setUpdateError(''); + + try { + // Call the backend API to run the update command + const response = await authenticatedFetch('/api/system/update', { + method: 'POST', + }); + + const data = await response.json(); + + if (response.ok) { + setUpdateOutput(prev => prev + data.output + '\n'); + setUpdateOutput(prev => prev + '\n✅ Update completed successfully!\n'); + setUpdateOutput(prev => prev + 'Please restart the server to apply changes.\n'); + } else { + setUpdateError(data.error || 'Update failed'); + setUpdateOutput(prev => prev + '\n❌ Update failed: ' + (data.error || 'Unknown error') + '\n'); + } + } catch (error: any) { + setUpdateError(error.message); + setUpdateOutput(prev => prev + '\n❌ Update failed: ' + error.message + '\n'); + } finally { + setIsUpdating(false); + } + }; + + return ( +
+ {/* Backdrop */} + +
+ + {/* Version Info */} +
+
+ {t('versionUpdate.currentVersion')} + {currentVersion} +
+
+ {t('versionUpdate.latestVersion')} + {latestVersion} +
+
+ + {/* Changelog */} + {releaseInfo?.body && ( +
+
+

{t('versionUpdate.whatsNew')}

+ {releaseInfo?.htmlUrl && ( + + {t('versionUpdate.viewFullRelease')} + + + + + )} +
+
+
+ {cleanChangelog(releaseInfo.body)} +
+
+
+ )} + + {/* Update Output */} + {updateOutput && ( +
+

{t('versionUpdate.updateProgress')}

+
+
{updateOutput}
+
+
+ )} + + {/* Upgrade Instructions */} + {!isUpdating && !updateOutput && ( +
+

{t('versionUpdate.manualUpgrade')}

+
+ + git checkout main && git pull && npm install + +
+

+ {t('versionUpdate.manualUpgradeHint')} +

+
+ )} + + {/* Actions */} +
+ + {!updateOutput && ( + <> + + + + )} +
+ + + ); +}; + +// Clean up changelog by removing GitHub-specific metadata +const cleanChangelog = (body: string) => { + if (!body) return ''; + + return body + // Remove full commit hashes (40 character hex strings) + .replace(/\b[0-9a-f]{40}\b/gi, '') + // Remove short commit hashes (7-10 character hex strings at start of line or after dash/space) + .replace(/(?:^|\s|-)([0-9a-f]{7,10})\b/gi, '') + // Remove "Full Changelog" links + .replace(/\*\*Full Changelog\*\*:.*$/gim, '') + // Remove compare links (e.g., https://github.com/.../compare/v1.0.0...v1.0.1) + .replace(/https?:\/\/github\.com\/[^\/]+\/[^\/]+\/compare\/[^\s)]+/gi, '') + // Clean up multiple consecutive empty lines + .replace(/\n\s*\n\s*\n/g, '\n\n') + // Trim whitespace + .trim(); +}; \ No newline at end of file