Skip to content

Commit

Permalink
feat: add download to zip button
Browse files Browse the repository at this point in the history
  • Loading branch information
codewithtyler committed Nov 19, 2024
1 parent cecbc55 commit 99fc3c0
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 3 deletions.
45 changes: 43 additions & 2 deletions app/components/header/HeaderActionButtons.client.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,59 @@
import { useStore } from '@nanostores/react';
import JSZip from 'jszip';
import { chatStore } from '~/lib/stores/chat';
import { workbenchStore } from '~/lib/stores/workbench';
import { classNames } from '~/utils/classNames';
import { useStore } from '@nanostores/react';
import type { FileMap } from '~/lib/stores/files';
import { saveAs } from 'file-saver';

interface HeaderActionButtonsProps {}

export function HeaderActionButtons({}: HeaderActionButtonsProps) {
const showWorkbench = useStore(workbenchStore.showWorkbench);
const { showChat } = useStore(chatStore);
const files = useStore(workbenchStore.files) as FileMap;

const canHideChat = showWorkbench || !showChat;

const downloadZip = async () => {
const zip = new JSZip();

for (const [filePath, dirent] of Object.entries(files)) {
if (dirent?.type === 'file' && !dirent.isBinary) {
// remove '/home/project/' from the beginning of the path
const relativePath = filePath.replace(/^\/home\/project\//, '');

// split the path into segments
const pathSegments = relativePath.split('/');

// if there's more than one segment, we need to create folders
if (pathSegments.length > 1) {
let currentFolder = zip;

for (let i = 0; i < pathSegments.length - 1; i++) {
currentFolder = currentFolder.folder(pathSegments[i])!;
}
currentFolder.file(pathSegments[pathSegments.length - 1], dirent.content);
} else {
// if there's only one segment, it's a file in the root
zip.file(relativePath, dirent.content);
}
}
}

const content = await zip.generateAsync({ type: 'blob' });
saveAs(content, 'project.zip');
};

return (
<div className="flex">
<div className="flex gap-2">
<button
onClick={downloadZip}
className="rounded-md items-center justify-center outline-accent-600 px-3 py-1.25 text-xs bg-[#232323] text-bolt-elements-button-secondary-text enabled:hover:bg-bolt-elements-button-secondary-backgroundHover flex gap-1.7"
>
<div className="i-ph:download-bold" />
<span>Download</span>
</button>
<div className="flex border border-bolt-elements-borderColor rounded-md overflow-hidden">
<Button
active={showChat}
Expand Down
2 changes: 1 addition & 1 deletion app/components/ui/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const IconButton = memo(
return (
<button
className={classNames(
'flex items-center text-bolt-elements-item-contentDefault bg-transparent enabled:hover:text-bolt-elements-item-contentActive rounded-md p-1 enabled:hover:bg-bolt-elements-item-backgroundActive disabled:cursor-not-allowed',
'flex items-center p-1.5 text-bolt-elements-item-contentDefault hover:text-bolt-elements-item-contentActive rounded-md',
{
[classNames('opacity-30', disabledClassName)]: disabled,
},
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,24 @@
"@remix-run/cloudflare": "^2.10.2",
"@remix-run/cloudflare-pages": "^2.10.2",
"@remix-run/react": "^2.10.2",
"@types/file-saver": "^2.0.7",
"@uiw/codemirror-theme-vscode": "^4.23.0",
"@unocss/reset": "^0.61.0",
"@webcontainer/api": "1.3.0-internal.10",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/xterm": "^5.5.0",
"ai": "^3.3.4",
"classnames": "^2.5.1",
"date-fns": "^3.6.0",
"diff": "^5.2.0",
"fflate": "^0.8.2",
"file-saver": "^2.0.5",
"framer-motion": "^11.2.12",
"isbot": "^4.1.0",
"istextorbinary": "^9.5.0",
"jose": "^5.6.3",
"jszip": "^3.10.1",
"nanostores": "^0.10.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
57 changes: 57 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 99fc3c0

Please sign in to comment.