diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx index 986034c39d..76c365c3b4 100644 --- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx +++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx @@ -1,7 +1,6 @@ import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line import './remix-ui-home-tab.css' -import JSZip from 'jszip' import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line import { Toaster } from '@remix-ui/toaster' // eslint-disable-line import PluginButton from './components/pluginButton' // eslint-disable-line @@ -176,46 +175,6 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => { const startPluginManager = async () => { plugin.verticalIcons.select('pluginManager') } - const saveAs = (blob, name) => { - const node = document.createElement('a') - node.download = name - node.rel = 'noopener' - node.href = URL.createObjectURL(blob) - setTimeout(function () { URL.revokeObjectURL(node.href) }, 4E4) // 40s - setTimeout(function () { - try { - node.dispatchEvent(new MouseEvent('click')) - } catch (e) { - const evt = document.createEvent('MouseEvents') - evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, - 20, false, false, false, false, 0, null) - node.dispatchEvent(evt) - } - }, 0) // 40s - } - const downloadFiles = async () => { - try { - plugin.call('notification', 'toast', 'preparing files for download, please wait..') - const zip = new JSZip() - zip.file("readme.txt", "This is a Remix backup file.\nThis zip should be used by the restore backup tool in Remix.\nThe .workspaces directory contains your workspaces.") - const browserProvider = fileManager.getProvider('browser') - await browserProvider.copyFolderToJson('/', ({ path, content }) => { - zip.file(path, content) - }) - zip.generateAsync({ type: 'blob' }).then(function (blob) { - const today = new Date() - const date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate() - const time = today.getHours() + 'h' + today.getMinutes() + 'min' - saveAs(blob, `remix-backup-at-${time}-${date}.zip`) - _paq.push(['trackEvent', 'Backup', 'download', 'home']) - }).catch((e) => { - _paq.push(['trackEvent', 'Backup', 'error', e.message]) - plugin.call('notification', 'toast', e.message) - }) - } catch (e) { - plugin.call('notification', 'toast', e.message) - } - } const restoreBackupZip = async () => { await plugin.appManager.activatePlugin(['restorebackupzip']) @@ -336,10 +295,6 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {

-

- - -

diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index 7e1a47e43a..ed1b47ce39 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -5,13 +5,14 @@ import { customAction } from '@remixproject/plugin-api/lib/file-system/file-pane import { displayNotification, displayPopUp, fetchDirectoryError, fetchDirectoryRequest, fetchDirectorySuccess, focusElement, fsInitializationCompleted, hidePopUp, removeInputFieldSuccess, setCurrentWorkspace, setExpandPath, setMode, setWorkspaces } from './payload' import { listenOnPluginEvents, listenOnProviderEvents } from './events' import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin } from './workspace' +import { QueryParams } from '@remix-project/remix-lib' +import JSZip from 'jszip' export * from './events' export * from './workspace' -import { QueryParams } from '@remix-project/remix-lib' - const queryParams = new QueryParams() +const _paq = window._paq = window._paq || [] let plugin, dispatch: React.Dispatch @@ -269,6 +270,33 @@ export const handleExpandPath = (paths: string[]) => { dispatch(setExpandPath(paths)) } +export const handleDownloadFiles = async () => { + try { + plugin.call('notification', 'toast', 'preparing files for download, please wait..') + const zip = new JSZip() + + zip.file("readme.txt", "This is a Remix backup file.\nThis zip should be used by the restore backup tool in Remix.\nThe .workspaces directory contains your workspaces.") + const browserProvider = plugin.fileManager.getProvider('browser') + + await browserProvider.copyFolderToJson('/', ({ path, content }) => { + zip.file(path, content) + }) + zip.generateAsync({ type: 'blob' }).then(function (blob) { + const today = new Date() + const date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate() + const time = today.getHours() + 'h' + today.getMinutes() + 'min' + + saveAs(blob, `remix-backup-at-${time}-${date}.zip`) + _paq.push(['trackEvent', 'Backup', 'download', 'home']) + }).catch((e) => { + _paq.push(['trackEvent', 'Backup', 'error', e.message]) + plugin.call('notification', 'toast', e.message) + }) + } catch (e) { + plugin.call('notification', 'toast', e.message) + } +} + const packageGistFiles = async (directory) => { const workspaceProvider = plugin.fileProviders.workspace const isFile = await workspaceProvider.isFile(directory) @@ -344,3 +372,23 @@ const getOriginalFiles = async (id) => { const data = await res.json() return data.files || [] } + +const saveAs = (blob, name) => { + const node = document.createElement('a') + + node.download = name + node.rel = 'noopener' + node.href = URL.createObjectURL(blob) + setTimeout(function () { URL.revokeObjectURL(node.href) }, 4E4) // 40s + setTimeout(function () { + try { + node.dispatchEvent(new MouseEvent('click')) + } catch (e) { + const evt = document.createEvent('MouseEvents') + + evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, + 20, false, false, false, false, 0, null) + node.dispatchEvent(evt) + } + }, 0) // 40s +} diff --git a/libs/remix-ui/workspace/src/lib/contexts/index.ts b/libs/remix-ui/workspace/src/lib/contexts/index.ts index 1aedce98b5..cb0d3a758b 100644 --- a/libs/remix-ui/workspace/src/lib/contexts/index.ts +++ b/libs/remix-ui/workspace/src/lib/contexts/index.ts @@ -27,5 +27,6 @@ export const FileSystemContext = createContext<{ dispatchRunScript: (path: string) => Promise, dispatchEmitContextMenuEvent: (cmd: customAction) => Promise, dispatchHandleClickFile: (path: string, type: 'file' | 'folder' | 'gist') => Promise - dispatchHandleExpandPath: (paths: string[]) => Promise + dispatchHandleExpandPath: (paths: string[]) => Promise, + dispatchHandleDownloadFiles: () => Promise }>(null) diff --git a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx index 904ed7cade..3803e34c14 100644 --- a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx +++ b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx @@ -5,7 +5,7 @@ import { Toaster } from '@remix-ui/toaster' // eslint-disable-line // eslint-disable-next-line @typescript-eslint/no-unused-vars import { FileSystemContext } from '../contexts' import { browserReducer, browserInitialState } from '../reducers/workspace' -import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder, deletePath, renamePath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile } from '../actions' +import { initWorkspace, fetchDirectory, removeInputField, deleteWorkspace, clearPopUp, publishToGist, createNewFile, setFocusElement, createNewFolder, deletePath, renamePath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile, handleExpandPath, addInputField, createWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile, handleDownloadFiles } from '../actions' import { Modal, WorkspaceProps } from '../types' // eslint-disable-next-line @typescript-eslint/no-unused-vars import { Workspace } from '../remix-ui-workspace' @@ -115,6 +115,10 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await handleExpandPath(paths) } + const dispatchHandleDownloadFiles = async () => { + await handleDownloadFiles() + } + useEffect(() => { dispatchInitWorkspace() }, []) @@ -214,7 +218,8 @@ export const FileSystemProvider = (props: WorkspaceProps) => { dispatchRunScript, dispatchEmitContextMenuEvent, dispatchHandleClickFile, - dispatchHandleExpandPath + dispatchHandleExpandPath, + dispatchHandleDownloadFiles } return ( diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index a51224f86c..11eec79c16 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -50,6 +50,14 @@ export function Workspace () { global.modal('Delete Current Workspace', 'Are you sure to delete the current workspace?', 'OK', onFinishDeleteWorkspace, '') } + const downloadWorkspaces = async () => { + try { + await global.dispatchHandleDownloadFiles() + } catch (e) { + console.error(e) + } + } + const onFinishRenameWorkspace = async () => { if (workspaceRenameInput.current === undefined) return // @ts-ignore: Object is possibly 'null'. @@ -156,9 +164,20 @@ export function Workspace () { e.stopPropagation() deleteCurrentWorkspace() }} - className='fas fa-trash' + className='fas fa-trash remixui_menuicon' title='Delete'> +