mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-06-23 02:16:08 +00:00
update fixes BETA
This commit is contained in:
parent
d479550c49
commit
07435fc255
@ -19,6 +19,7 @@ interface UpdateProgress {
|
||||
totalSize?: string;
|
||||
currentCommit?: string;
|
||||
remoteCommit?: string;
|
||||
updateReady?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@ -113,7 +114,10 @@ const UpdateTab = () => {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ branch: branchToCheck }),
|
||||
body: JSON.stringify({
|
||||
branch: branchToCheck,
|
||||
autoUpdate: updateSettings.autoUpdate,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@ -152,10 +156,11 @@ const UpdateTab = () => {
|
||||
setIsChecking(false);
|
||||
|
||||
if (!progress.error) {
|
||||
// Update was successful
|
||||
// Update check completed
|
||||
toast.success('Update check completed');
|
||||
|
||||
if (progress.details?.changedFiles?.length) {
|
||||
// Show update dialog only if there are changes and auto-update is disabled
|
||||
if (progress.details?.changedFiles?.length && progress.details.updateReady) {
|
||||
setShowUpdateDialog(true);
|
||||
}
|
||||
}
|
||||
@ -176,6 +181,69 @@ const UpdateTab = () => {
|
||||
}
|
||||
};
|
||||
|
||||
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 (
|
||||
<div className="flex flex-col gap-6">
|
||||
<motion.div
|
||||
@ -286,6 +354,21 @@ const UpdateTab = () => {
|
||||
<div className="i-ph:arrows-clockwise text-purple-500 w-5 h-5" />
|
||||
<h3 className="text-lg font-medium text-bolt-elements-textPrimary">Update Status</h3>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{updateProgress?.details?.updateReady && !updateSettings.autoUpdate && (
|
||||
<button
|
||||
onClick={handleUpdate}
|
||||
className={classNames(
|
||||
'flex items-center gap-2 px-4 py-2 rounded-lg text-sm',
|
||||
'bg-purple-500 text-white',
|
||||
'hover:bg-purple-600',
|
||||
'transition-colors duration-200',
|
||||
)}
|
||||
>
|
||||
<div className="i-ph:arrow-circle-up w-4 h-4" />
|
||||
Update Now
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={() => {
|
||||
setError(null);
|
||||
@ -319,11 +402,27 @@ const UpdateTab = () => {
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Show progress information */}
|
||||
{updateProgress && <UpdateProgressDisplay progress={updateProgress} />}
|
||||
|
||||
{error && <div className="mt-4 p-4 bg-red-100 text-red-700 rounded">{error}</div>}
|
||||
|
||||
{/* Show update source information */}
|
||||
<div className="mt-4 text-sm text-bolt-elements-textSecondary">
|
||||
<p>
|
||||
Updates are fetched from: <span className="font-mono">stackblitz-labs/bolt.diy</span> (
|
||||
{isLatestBranch ? 'main' : 'stable'} branch)
|
||||
</p>
|
||||
{updateProgress?.details?.currentCommit && updateProgress?.details?.remoteCommit && (
|
||||
<p className="mt-1">
|
||||
Current version: <span className="font-mono">{updateProgress.details.currentCommit}</span>
|
||||
<span className="mx-2">→</span>
|
||||
Latest version: <span className="font-mono">{updateProgress.details.remoteCommit}</span>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Update dialog */}
|
||||
@ -331,34 +430,53 @@ const UpdateTab = () => {
|
||||
<Dialog>
|
||||
<DialogTitle>Update Available</DialogTitle>
|
||||
<DialogDescription>
|
||||
{updateProgress?.details?.changedFiles && (
|
||||
<div className="mt-4">
|
||||
<p className="font-medium">Changes:</p>
|
||||
<ul className="list-disc list-inside mt-2">
|
||||
<p className="text-sm text-bolt-elements-textSecondary mb-4">
|
||||
A new version is available from <span className="font-mono">stackblitz-labs/bolt.diy</span> (
|
||||
{isLatestBranch ? 'main' : 'stable'} branch)
|
||||
</p>
|
||||
{updateProgress?.details?.commitMessages && updateProgress.details.commitMessages.length > 0 && (
|
||||
<div className="mb-4">
|
||||
<p className="font-medium mb-2">Commit Messages:</p>
|
||||
<ul className="list-disc list-inside space-y-1">
|
||||
{updateProgress.details.commitMessages.map((msg, index) => (
|
||||
<li key={index} className="text-sm text-bolt-elements-textSecondary">
|
||||
{msg}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
{updateProgress?.details?.changedFiles && (
|
||||
<div>
|
||||
<p className="font-medium mb-2">Changed Files:</p>
|
||||
<ul className="list-disc list-inside space-y-1">
|
||||
{updateProgress.details.changedFiles.map((file, index) => (
|
||||
<li key={index} className="text-sm">
|
||||
<li key={index} className="text-sm text-bolt-elements-textSecondary">
|
||||
{file}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{updateProgress.details.totalSize && (
|
||||
<p className="mt-2 text-sm">Total size: {updateProgress.details.totalSize}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{updateProgress?.details?.totalSize && (
|
||||
<p className="mt-4 text-sm text-bolt-elements-textSecondary">
|
||||
Total size: {updateProgress.details.totalSize}
|
||||
</p>
|
||||
)}
|
||||
{updateProgress?.details?.additions !== undefined && updateProgress?.details?.deletions !== undefined && (
|
||||
<p className="mt-2 text-sm text-bolt-elements-textSecondary">
|
||||
Changes: <span className="text-green-600">+{updateProgress.details.additions}</span>{' '}
|
||||
<span className="text-red-600">-{updateProgress.details.deletions}</span>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</DialogDescription>
|
||||
<div className="flex justify-end gap-2 mt-4">
|
||||
<div className="flex justify-end gap-2 mt-6">
|
||||
<DialogButton type="secondary" onClick={() => setShowUpdateDialog(false)}>
|
||||
Cancel
|
||||
</DialogButton>
|
||||
<DialogButton
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setShowUpdateDialog(false);
|
||||
|
||||
// Handle update initiation here
|
||||
}}
|
||||
>
|
||||
<DialogButton type="primary" onClick={handleUpdate}>
|
||||
Update Now
|
||||
</DialogButton>
|
||||
</div>
|
||||
|
@ -7,6 +7,7 @@ const execAsync = promisify(exec);
|
||||
|
||||
interface UpdateRequestBody {
|
||||
branch: string;
|
||||
autoUpdate?: boolean;
|
||||
}
|
||||
|
||||
interface UpdateProgress {
|
||||
@ -22,6 +23,7 @@ interface UpdateProgress {
|
||||
totalSize?: string;
|
||||
currentCommit?: string;
|
||||
remoteCommit?: string;
|
||||
updateReady?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,7 +39,7 @@ export const action: ActionFunction = async ({ request }) => {
|
||||
return json({ error: 'Invalid request body: branch is required and must be a string' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { branch } = body as UpdateRequestBody;
|
||||
const { branch, autoUpdate = false } = body as UpdateRequestBody;
|
||||
|
||||
// Create a ReadableStream to send progress updates
|
||||
const stream = new ReadableStream({
|
||||
@ -271,9 +273,30 @@ export const action: ActionFunction = async ({ request }) => {
|
||||
totalSize: formatSize(totalSizeInBytes),
|
||||
currentCommit: currentCommit.trim().substring(0, 7),
|
||||
remoteCommit: remoteCommit.trim().substring(0, 7),
|
||||
updateReady: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Only proceed with update if autoUpdate is true
|
||||
if (!autoUpdate) {
|
||||
sendProgress({
|
||||
stage: 'complete',
|
||||
message: 'Update is ready to be applied. Click "Update Now" to proceed.',
|
||||
progress: 100,
|
||||
details: {
|
||||
changedFiles,
|
||||
additions: stats?.[2] ? parseInt(stats[2]) : 0,
|
||||
deletions: stats?.[3] ? parseInt(stats[3]) : 0,
|
||||
commitMessages,
|
||||
totalSize: formatSize(totalSizeInBytes),
|
||||
currentCommit: currentCommit.trim().substring(0, 7),
|
||||
remoteCommit: remoteCommit.trim().substring(0, 7),
|
||||
updateReady: true,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Pull stage
|
||||
sendProgress({
|
||||
stage: 'pull',
|
||||
|
Loading…
Reference in New Issue
Block a user