Move download from homepage to File Explorer

auto_exec_v2
David Disu 3 years ago committed by yann300
parent b3a7bab95c
commit 758f1a81a7
  1. 45
      libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx
  2. 52
      libs/remix-ui/workspace/src/lib/actions/index.ts
  3. 3
      libs/remix-ui/workspace/src/lib/contexts/index.ts
  4. 9
      libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx
  5. 21
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx

@ -1,7 +1,6 @@
import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line
import './remix-ui-home-tab.css' import './remix-ui-home-tab.css'
import JSZip from 'jszip'
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
import PluginButton from './components/pluginButton' // eslint-disable-line import PluginButton from './components/pluginButton' // eslint-disable-line
@ -176,46 +175,6 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
const startPluginManager = async () => { const startPluginManager = async () => {
plugin.verticalIcons.select('pluginManager') 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 () => { const restoreBackupZip = async () => {
await plugin.appManager.activatePlugin(['restorebackupzip']) await plugin.appManager.activatePlugin(['restorebackupzip'])
@ -336,10 +295,6 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
<i className="mr-1 far fa-hdd"></i> <i className="mr-1 far fa-hdd"></i>
<label className="ml-1 remixui_home_text" onClick={() => connectToLocalhost()}>Connect to Localhost</label> <label className="ml-1 remixui_home_text" onClick={() => connectToLocalhost()}>Connect to Localhost</label>
</p> </p>
<p className="mb-1">
<i className="mr-1 far fa-download"></i>
<label className="ml-1 remixui_home_text" onClick={() => downloadFiles()}>Download Backup</label>
</p>
<p className="mb-1"> <p className="mb-1">
<i className="mr-1 far fa-upload"></i> <i className="mr-1 far fa-upload"></i>
<label className="ml-1 remixui_home_text" onClick={() => restoreBackupZip()}>Restore Backup</label> <label className="ml-1 remixui_home_text" onClick={() => restoreBackupZip()}>Restore Backup</label>

@ -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 { displayNotification, displayPopUp, fetchDirectoryError, fetchDirectoryRequest, fetchDirectorySuccess, focusElement, fsInitializationCompleted, hidePopUp, removeInputFieldSuccess, setCurrentWorkspace, setExpandPath, setMode, setWorkspaces } from './payload'
import { listenOnPluginEvents, listenOnProviderEvents } from './events' import { listenOnPluginEvents, listenOnProviderEvents } from './events'
import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin } from './workspace' import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin } from './workspace'
import { QueryParams } from '@remix-project/remix-lib'
import JSZip from 'jszip'
export * from './events' export * from './events'
export * from './workspace' export * from './workspace'
import { QueryParams } from '@remix-project/remix-lib'
const queryParams = new QueryParams() const queryParams = new QueryParams()
const _paq = window._paq = window._paq || []
let plugin, dispatch: React.Dispatch<any> let plugin, dispatch: React.Dispatch<any>
@ -269,6 +270,33 @@ export const handleExpandPath = (paths: string[]) => {
dispatch(setExpandPath(paths)) 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 packageGistFiles = async (directory) => {
const workspaceProvider = plugin.fileProviders.workspace const workspaceProvider = plugin.fileProviders.workspace
const isFile = await workspaceProvider.isFile(directory) const isFile = await workspaceProvider.isFile(directory)
@ -344,3 +372,23 @@ const getOriginalFiles = async (id) => {
const data = await res.json() const data = await res.json()
return data.files || [] 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
}

@ -27,5 +27,6 @@ export const FileSystemContext = createContext<{
dispatchRunScript: (path: string) => Promise<void>, dispatchRunScript: (path: string) => Promise<void>,
dispatchEmitContextMenuEvent: (cmd: customAction) => Promise<void>, dispatchEmitContextMenuEvent: (cmd: customAction) => Promise<void>,
dispatchHandleClickFile: (path: string, type: 'file' | 'folder' | 'gist') => Promise<void> dispatchHandleClickFile: (path: string, type: 'file' | 'folder' | 'gist') => Promise<void>
dispatchHandleExpandPath: (paths: string[]) => Promise<void> dispatchHandleExpandPath: (paths: string[]) => Promise<void>,
dispatchHandleDownloadFiles: () => Promise<void>
}>(null) }>(null)

@ -5,7 +5,7 @@ import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
import { FileSystemContext } from '../contexts' import { FileSystemContext } from '../contexts'
import { browserReducer, browserInitialState } from '../reducers/workspace' 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' import { Modal, WorkspaceProps } from '../types'
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
import { Workspace } from '../remix-ui-workspace' import { Workspace } from '../remix-ui-workspace'
@ -115,6 +115,10 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
await handleExpandPath(paths) await handleExpandPath(paths)
} }
const dispatchHandleDownloadFiles = async () => {
await handleDownloadFiles()
}
useEffect(() => { useEffect(() => {
dispatchInitWorkspace() dispatchInitWorkspace()
}, []) }, [])
@ -214,7 +218,8 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
dispatchRunScript, dispatchRunScript,
dispatchEmitContextMenuEvent, dispatchEmitContextMenuEvent,
dispatchHandleClickFile, dispatchHandleClickFile,
dispatchHandleExpandPath dispatchHandleExpandPath,
dispatchHandleDownloadFiles
} }
return ( return (
<FileSystemContext.Provider value={value}> <FileSystemContext.Provider value={value}>

@ -50,6 +50,14 @@ export function Workspace () {
global.modal('Delete Current Workspace', 'Are you sure to delete the current workspace?', 'OK', onFinishDeleteWorkspace, '') 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 () => { const onFinishRenameWorkspace = async () => {
if (workspaceRenameInput.current === undefined) return if (workspaceRenameInput.current === undefined) return
// @ts-ignore: Object is possibly 'null'. // @ts-ignore: Object is possibly 'null'.
@ -156,9 +164,20 @@ export function Workspace () {
e.stopPropagation() e.stopPropagation()
deleteCurrentWorkspace() deleteCurrentWorkspace()
}} }}
className='fas fa-trash' className='fas fa-trash remixui_menuicon'
title='Delete'> title='Delete'>
</span> </span>
<span
hidden={currentWorkspace === NO_WORKSPACE}
id='workspacesDownload'
data-id='workspacesDownload'
onClick={(e) => {
e.stopPropagation()
downloadWorkspaces()
}}
className='far fa-download remixui_menuicon'
title='Download Workspaces'>
</span>
</span> </span>
<select id="workspacesSelect" value={currentWorkspace} data-id="workspacesSelect" onChange={(e) => switchWorkspace(e.target.value)} className="form-control custom-select"> <select id="workspacesSelect" value={currentWorkspace} data-id="workspacesSelect" onChange={(e) => switchWorkspace(e.target.value)} className="form-control custom-select">
{ {

Loading…
Cancel
Save