mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-03-10 06:00:19 +00:00
upload new files
This commit is contained in:
parent
074161024d
commit
809b54e04a
@ -57,6 +57,7 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
|
|||||||
renderLogger.trace('Workbench');
|
renderLogger.trace('Workbench');
|
||||||
|
|
||||||
const [isSyncing, setIsSyncing] = useState(false);
|
const [isSyncing, setIsSyncing] = useState(false);
|
||||||
|
const [isUploading, setIsUploading] = useState(false);
|
||||||
|
|
||||||
const hasPreview = useStore(computed(workbenchStore.previews, (previews) => previews.length > 0));
|
const hasPreview = useStore(computed(workbenchStore.previews, (previews) => previews.length > 0));
|
||||||
const showWorkbench = useStore(workbenchStore.showWorkbench);
|
const showWorkbench = useStore(workbenchStore.showWorkbench);
|
||||||
@ -119,6 +120,60 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleUploadFiles = useCallback(async () => {
|
||||||
|
setIsUploading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// const directoryHandle = await window.showDirectoryPicker();
|
||||||
|
|
||||||
|
// // First upload new files
|
||||||
|
// await workbenchStore.uploadFilesFromDisk(directoryHandle);
|
||||||
|
|
||||||
|
// // Get current files state
|
||||||
|
// const currentFiles = workbenchStore.files.get();
|
||||||
|
|
||||||
|
// // Create new modifications map with all files as "new"
|
||||||
|
// const newModifications = new Map();
|
||||||
|
// Object.entries(currentFiles).forEach(([path, file]) => {
|
||||||
|
// if (file.type === 'file') {
|
||||||
|
// newModifications.set(path, file.content);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // Update workbench state
|
||||||
|
// await workbenchStore.refreshFiles();
|
||||||
|
// workbenchStore.resetAllFileModifications();
|
||||||
|
|
||||||
|
// toast.success('Files uploaded successfully');
|
||||||
|
// } catch (error) {
|
||||||
|
// toast.error('Failed to upload files');
|
||||||
|
// }
|
||||||
|
await handleUploadFilesFunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
finally {
|
||||||
|
setIsUploading(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function handleUploadFilesFunc() {
|
||||||
|
try {
|
||||||
|
// First clean all statuses
|
||||||
|
await workbenchStore.saveAllFiles();
|
||||||
|
await workbenchStore.resetAllFileModifications();
|
||||||
|
await workbenchStore.refreshFiles();
|
||||||
|
|
||||||
|
// Now upload new files
|
||||||
|
const directoryHandle = await window.showDirectoryPicker();
|
||||||
|
await workbenchStore.uploadFilesFromDisk(directoryHandle);
|
||||||
|
|
||||||
|
toast.success('Files uploaded successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Upload files error:', error);
|
||||||
|
toast.error('Failed to upload files');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
chatStarted && (
|
chatStarted && (
|
||||||
<motion.div
|
<motion.div
|
||||||
@ -158,6 +213,10 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
|
|||||||
{isSyncing ? <div className="i-ph:spinner" /> : <div className="i-ph:cloud-arrow-down" />}
|
{isSyncing ? <div className="i-ph:spinner" /> : <div className="i-ph:cloud-arrow-down" />}
|
||||||
{isSyncing ? 'Syncing...' : 'Sync Files'}
|
{isSyncing ? 'Syncing...' : 'Sync Files'}
|
||||||
</PanelHeaderButton>
|
</PanelHeaderButton>
|
||||||
|
<PanelHeaderButton className="mr-1 text-sm" onClick={handleUploadFiles} disabled={isSyncing}>
|
||||||
|
{isSyncing ? <div className="i-ph:spinner" /> : <div className="i-ph:cloud-arrow-up" />}
|
||||||
|
{isSyncing ? 'Uploading...' : 'Upload Files'}
|
||||||
|
</PanelHeaderButton>
|
||||||
<PanelHeaderButton
|
<PanelHeaderButton
|
||||||
className="mr-1 text-sm"
|
className="mr-1 text-sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -80,6 +80,10 @@ export class FilesStore {
|
|||||||
this.#modifiedFiles.clear();
|
this.#modifiedFiles.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markFileAsNew(filePath: string) {
|
||||||
|
this.#modifiedFiles.set(filePath, '');
|
||||||
|
}
|
||||||
|
|
||||||
async saveFile(filePath: string, content: string) {
|
async saveFile(filePath: string, content: string) {
|
||||||
const webcontainer = await this.#webcontainer;
|
const webcontainer = await this.#webcontainer;
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ export type WorkbenchViewType = 'code' | 'preview';
|
|||||||
export class WorkbenchStore {
|
export class WorkbenchStore {
|
||||||
#previewsStore = new PreviewsStore(webcontainer);
|
#previewsStore = new PreviewsStore(webcontainer);
|
||||||
#filesStore = new FilesStore(webcontainer);
|
#filesStore = new FilesStore(webcontainer);
|
||||||
|
|
||||||
#editorStore = new EditorStore(this.#filesStore);
|
#editorStore = new EditorStore(this.#filesStore);
|
||||||
#terminalStore = new TerminalStore(webcontainer);
|
#terminalStore = new TerminalStore(webcontainer);
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ export class WorkbenchStore {
|
|||||||
modifiedFiles = new Set<string>();
|
modifiedFiles = new Set<string>();
|
||||||
artifactIdList: string[] = [];
|
artifactIdList: string[] = [];
|
||||||
#boltTerminal: { terminal: ITerminal; process: WebContainerProcess } | undefined;
|
#boltTerminal: { terminal: ITerminal; process: WebContainerProcess } | undefined;
|
||||||
#globalExecutionQueue=Promise.resolve();
|
#globalExecutionQueue = Promise.resolve();
|
||||||
constructor() {
|
constructor() {
|
||||||
if (import.meta.hot) {
|
if (import.meta.hot) {
|
||||||
import.meta.hot.data.artifacts = this.artifacts;
|
import.meta.hot.data.artifacts = this.artifacts;
|
||||||
@ -54,7 +55,7 @@ export class WorkbenchStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addToExecutionQueue(callback: () => Promise<void>) {
|
addToExecutionQueue(callback: () => Promise<void>) {
|
||||||
this.#globalExecutionQueue=this.#globalExecutionQueue.then(()=>callback())
|
this.#globalExecutionQueue = this.#globalExecutionQueue.then(() => callback())
|
||||||
}
|
}
|
||||||
|
|
||||||
get previews() {
|
get previews() {
|
||||||
@ -277,11 +278,11 @@ export class WorkbenchStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runAction(data: ActionCallbackData, isStreaming: boolean = false) {
|
runAction(data: ActionCallbackData, isStreaming: boolean = false) {
|
||||||
if(isStreaming) {
|
if (isStreaming) {
|
||||||
this._runAction(data, isStreaming)
|
this._runAction(data, isStreaming)
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
this.addToExecutionQueue(()=>this._runAction(data, isStreaming))
|
this.addToExecutionQueue(() => this._runAction(data, isStreaming))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async _runAction(data: ActionCallbackData, isStreaming: boolean = false) {
|
async _runAction(data: ActionCallbackData, isStreaming: boolean = false) {
|
||||||
@ -381,6 +382,61 @@ export class WorkbenchStore {
|
|||||||
return syncedFiles;
|
return syncedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async uploadFilesFromDisk(sourceHandle: FileSystemDirectoryHandle) {
|
||||||
|
const loadedFiles = [];
|
||||||
|
const wc = await webcontainer;
|
||||||
|
const newFiles = {};
|
||||||
|
|
||||||
|
const processDirectory = async (handle: FileSystemDirectoryHandle, currentPath: string = '') => {
|
||||||
|
const entries = await Array.fromAsync(handle.values());
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const entryPath = currentPath ? `${currentPath}/${entry.name}` : entry.name;
|
||||||
|
const fullPath = `/${entryPath}`;
|
||||||
|
|
||||||
|
if (entry.kind === 'directory') {
|
||||||
|
await wc.fs.mkdir(fullPath, { recursive: true });
|
||||||
|
const subDirHandle = await handle.getDirectoryHandle(entry.name);
|
||||||
|
await processDirectory(subDirHandle, entryPath);
|
||||||
|
} else {
|
||||||
|
const file = await entry.getFile();
|
||||||
|
const content = await file.text();
|
||||||
|
|
||||||
|
// Write to WebContainer
|
||||||
|
await wc.fs.writeFile(fullPath, content);
|
||||||
|
|
||||||
|
// Mark file as new
|
||||||
|
this.#filesStore.markFileAsNew(fullPath);
|
||||||
|
|
||||||
|
// Update the files store with the current content
|
||||||
|
this.files.setKey(fullPath, { type: 'file', content, isBinary: false });
|
||||||
|
|
||||||
|
// Collect for editor store with actual content
|
||||||
|
newFiles[fullPath] = { type: 'file', content, isBinary: false };
|
||||||
|
loadedFiles.push(entryPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await processDirectory(sourceHandle);
|
||||||
|
|
||||||
|
return loadedFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
async refreshFiles() {
|
||||||
|
// Clear old state
|
||||||
|
this.modifiedFiles = new Set<string>();
|
||||||
|
this.artifactIdList = [];
|
||||||
|
|
||||||
|
// Reset stores
|
||||||
|
this.#filesStore = new FilesStore(webcontainer);
|
||||||
|
this.#editorStore = new EditorStore(this.#filesStore);
|
||||||
|
|
||||||
|
// Update UI state
|
||||||
|
this.currentView.set('code');
|
||||||
|
this.unsavedFiles.set(new Set<string>());
|
||||||
|
}
|
||||||
|
|
||||||
async pushToGitHub(repoName: string, githubUsername: string, ghToken: string) {
|
async pushToGitHub(repoName: string, githubUsername: string, ghToken: string) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -486,6 +542,21 @@ export class WorkbenchStore {
|
|||||||
console.error('Error pushing to GitHub:', error instanceof Error ? error.message : String(error));
|
console.error('Error pushing to GitHub:', error instanceof Error ? error.message : String(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async markFileAsModified(filePath: string) {
|
||||||
|
const file = this.#filesStore.getFile(filePath);
|
||||||
|
if (file?.type === 'file') {
|
||||||
|
// First collect all original content
|
||||||
|
const originalContent = file.content;
|
||||||
|
console.log(`Processing ${filePath}:`, originalContent);
|
||||||
|
|
||||||
|
// Then save modifications
|
||||||
|
await this.saveFile(filePath, originalContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const workbenchStore = new WorkbenchStore();
|
export const workbenchStore = new WorkbenchStore();
|
||||||
|
Loading…
Reference in New Issue
Block a user