filepanel / file manager / fileexplorer

pull/1/head
yann300 6 years ago
parent 24e55f721b
commit 06cf9f5997
  1. 15
      src/app.js
  2. 18
      src/app/files/file-explorer.js
  3. 27
      src/app/files/fileManager.js
  4. 30
      src/app/panels/editor-panel.js
  5. 64
      src/app/panels/file-panel.js

@ -602,20 +602,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
chromeCloudStorageSync() chromeCloudStorageSync()
// ---------------- FilePanel -------------------- // ---------------- FilePanel --------------------
var FilePanelAPI = { var filePanel = new FilePanel()
switchFile: function (path) {
fileManager.switchFile(path)
},
event: fileManager.event,
config: config,
currentContent: function () {
return editor.get(config.get('currentFile'))
},
setText: function (text) {
editor.setText(text)
}
}
var filePanel = new FilePanel(FilePanelAPI, filesProviders)
// TODO this should happen inside file-panel.js // TODO this should happen inside file-panel.js
var filepanelContainer = document.querySelector('#filepanel') var filepanelContainer = document.querySelector('#filepanel')

@ -10,9 +10,11 @@ var helper = require('../../lib/helper')
var css = require('./styles/file-explorer-styles') var css = require('./styles/file-explorer-styles')
var globalRegistry = require('../../global/registry')
let MENU_HANDLE let MENU_HANDLE
function fileExplorer (appAPI, files) { function fileExplorer (localRegistry, files) {
var self = this var self = this
this.events = new EventManager() this.events = new EventManager()
// file provider backend // file provider backend
@ -22,13 +24,21 @@ function fileExplorer (appAPI, files) {
// path currently focused on // path currently focused on
this.focusPath = null this.focusPath = null
self._components = {}
self._components.registry = localRegistry || globalRegistry
self._deps = {
config: self._components.registry.get('config').api,
editor: self._components.registry.get('editor').api,
fileManager: self._components.registry.get('filemanager').api
}
// warn if file changed outside of Remix // warn if file changed outside of Remix
function remixdDialog () { function remixdDialog () {
return yo`<div>This file has been changed outside of Remix IDE.</div>` return yo`<div>This file has been changed outside of Remix IDE.</div>`
} }
this.files.event.register('fileExternallyChanged', (path, file) => { this.files.event.register('fileExternallyChanged', (path, file) => {
if (appAPI.config.get('currentFile') === path && appAPI.currentContent() && appAPI.currentContent() !== file.content) { if (self._deps.config.get('currentFile') === path && self._deps.editor.currentContent() && self._deps.editor.currentContent() !== file.content) {
modalDialog(path + ' changed', remixdDialog(), modalDialog(path + ' changed', remixdDialog(),
{ {
label: 'Keep the content displayed in Remix', label: 'Keep the content displayed in Remix',
@ -37,7 +47,7 @@ function fileExplorer (appAPI, files) {
{ {
label: 'Replace by the new content', label: 'Replace by the new content',
fn: () => { fn: () => {
appAPI.setText(file.content) self._deps.editor.setText(file.content)
} }
} }
) )
@ -186,7 +196,7 @@ function fileExplorer (appAPI, files) {
} }
// register to main app, trigger when the current file in the editor changed // register to main app, trigger when the current file in the editor changed
appAPI.event.register('currentFileChanged', (newFile, explorer) => { self._deps.fileManager.event.register('currentFileChanged', (newFile, explorer) => {
if (self.focusElement && (!explorer || explorer.type !== files.type) && self.focusPath !== newFile) { if (self.focusElement && (!explorer || explorer.type !== files.type) && self.focusPath !== newFile) {
self.focusElement.classList.remove(css.hasFocus) self.focusElement.classList.remove(css.hasFocus)
self.focusElement = null self.focusElement = null

@ -38,31 +38,6 @@ class FileManager {
self._deps.localhostExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) }) self._deps.localhostExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) })
self._deps.configExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) }) self._deps.configExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) })
self._deps.gistExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) }) self._deps.gistExplorer.event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) })
// tabs
var $filesEl = $('#files')
// Switch tab
$filesEl.on('click', '.file:not(.active)', function (ev) {
ev.preventDefault()
self.switchFile($(this).find('.name').text())
return false
})
// Remove current tab
$filesEl.on('click', '.file .remove', function (ev) {
ev.preventDefault()
var name = $(this).parent().find('.name').text()
delete self.tabbedFiles[name]
self.refreshTabs()
if (Object.keys(self.tabbedFiles).length) {
self.switchFile(Object.keys(self.tabbedFiles)[0])
} else {
self._deps.editor.displayEmptyReadOnlySession()
self._deps.config.set('currentFile', '')
}
return false
})
} }
fileRenamedEvent (oldName, newName, isFolder) { fileRenamedEvent (oldName, newName, isFolder) {
@ -136,7 +111,7 @@ class FileManager {
var self = this var self = this
if (file) return _switchFile(file) if (file) return _switchFile(file)
else { else {
var browserProvider = self._.filesProviders['browser'] var browserProvider = self._deps.filesProviders['browser']
browserProvider.resolveDirectory('browser', (error, filesTree) => { browserProvider.resolveDirectory('browser', (error, filesTree) => {
if (error) console.error(error) if (error) console.error(error)
var fileList = Object.keys(filesTree) var fileList = Object.keys(filesTree)

@ -1,6 +1,7 @@
var yo = require('yo-yo') var yo = require('yo-yo')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
var $ = require('jquery')
var Terminal = require('./terminal') var Terminal = require('./terminal')
var globalRegistry = require('../../global/registry') var globalRegistry = require('../../global/registry')
@ -20,7 +21,8 @@ class EditorPanel {
txlistener: self._components.registry.get('txlistener').api, txlistener: self._components.registry.get('txlistener').api,
contextView: self._components.registry.get('contextview').api, contextView: self._components.registry.get('contextview').api,
udapp: self._components.registry.get('udapp').api, udapp: self._components.registry.get('udapp').api,
cmdInterpreter: self._components.registry.get('cmdinterpreter').api cmdInterpreter: self._components.registry.get('cmdinterpreter').api,
fileManager: self._components.registry.get('filemanager').api
} }
self.event = new EventManager() self.event = new EventManager()
self.data = { self.data = {
@ -171,6 +173,32 @@ class EditorPanel {
</span> </span>
</div> </div>
` `
// tabs
var $filesEl = $(self._view.filetabs)
// Switch tab
$filesEl.on('click', '.file:not(.active)', function (ev) {
ev.preventDefault()
self._deps.fileManager.switchFile($(this).find('.name').text())
return false
})
// Remove current tab
$filesEl.on('click', '.file .remove', function (ev) {
ev.preventDefault()
var name = $(this).parent().find('.name').text()
delete self._deps.fileManager.tabbedFiles[name]
self._deps.fileManager.refreshTabs()
if (Object.keys(self._deps.fileManager.tabbedFiles).length) {
self.switchFile(Object.keys(self._deps.fileManager.tabbedFiles)[0])
} else {
self._deps.editor.displayEmptyReadOnlySession()
self._deps.config.set('currentFile', '')
}
return false
})
return self._view.tabsbar return self._view.tabsbar
function toggleScrollers (event = {}) { function toggleScrollers (event = {}) {
if (event.type) self.data._focus = event.type if (event.type) self.data._focus = event.type

@ -1,6 +1,5 @@
/* global FileReader */ /* global FileReader */
var async = require('async') var async = require('async')
var $ = require('jquery')
var yo = require('yo-yo') var yo = require('yo-yo')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var Gists = require('gists') var Gists = require('gists')
@ -13,6 +12,8 @@ var QueryParams = require('../../lib/query-params')
var queryParams = new QueryParams() var queryParams = new QueryParams()
var helper = require('../../lib/helper') var helper = require('../../lib/helper')
var globalRegistry = require('../../global/registry')
var styleGuide = require('../ui/styles-guide/theme-chooser') var styleGuide = require('../ui/styles-guide/theme-chooser')
var styles = styleGuide.chooser() var styles = styleGuide.chooser()
@ -39,14 +40,21 @@ var ghostbar = yo`<div class=${css.ghostbar}></div>`
- call fileProvider API - call fileProvider API
*/ */
function filepanel (appAPI, filesProvider) { function filepanel (localRegistry) {
var self = this var self = this
var fileExplorer = new FileExplorer(appAPI, filesProvider['browser']) self._components = {}
var fileSystemExplorer = new FileExplorer(appAPI, filesProvider['localhost']) self._components.registry = localRegistry || globalRegistry
var swarmExplorer = new FileExplorer(appAPI, filesProvider['swarm']) self._deps = {
var githubExplorer = new FileExplorer(appAPI, filesProvider['github']) fileProviders: self._components.registry.get('fileproviders').api,
var gistExplorer = new FileExplorer(appAPI, filesProvider['gist']) fileManager: self._components.registry.get('filemanager').api,
var configExplorer = new FileExplorer(appAPI, filesProvider['config']) config: self._components.registry.get('config').api
}
var fileExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['browser'])
var fileSystemExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['localhost'])
var swarmExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['swarm'])
var githubExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['github'])
var gistExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['gist'])
var configExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['config'])
var dragbar = yo`<div onmousedown=${mousedown} class=${css.dragbar}></div>` var dragbar = yo`<div onmousedown=${mousedown} class=${css.dragbar}></div>`
@ -114,51 +122,51 @@ function filepanel (appAPI, filesProvider) {
fileExplorer.ensureRoot() fileExplorer.ensureRoot()
configExplorer.ensureRoot() configExplorer.ensureRoot()
var websocketconn = element.querySelector('.websocketconn') var websocketconn = element.querySelector('.websocketconn')
filesProvider['localhost'].remixd.event.register('connecting', (event) => { self._deps.fileProviders['localhost'].remixd.event.register('connecting', (event) => {
websocketconn.style.color = styles.colors.yellow websocketconn.style.color = styles.colors.yellow
websocketconn.setAttribute('title', 'Connecting to localhost. ' + JSON.stringify(event)) websocketconn.setAttribute('title', 'Connecting to localhost. ' + JSON.stringify(event))
}) })
filesProvider['localhost'].remixd.event.register('connected', (event) => { self._deps.fileProviders['localhost'].remixd.event.register('connected', (event) => {
websocketconn.style.color = styles.colors.green websocketconn.style.color = styles.colors.green
websocketconn.setAttribute('title', 'Connected to localhost. ' + JSON.stringify(event)) websocketconn.setAttribute('title', 'Connected to localhost. ' + JSON.stringify(event))
fileSystemExplorer.show() fileSystemExplorer.show()
}) })
filesProvider['localhost'].remixd.event.register('errored', (event) => { self._deps.fileProviders['localhost'].remixd.event.register('errored', (event) => {
websocketconn.style.color = styles.colors.red websocketconn.style.color = styles.colors.red
websocketconn.setAttribute('title', 'localhost connection errored. ' + JSON.stringify(event)) websocketconn.setAttribute('title', 'localhost connection errored. ' + JSON.stringify(event))
fileSystemExplorer.hide() fileSystemExplorer.hide()
}) })
filesProvider['localhost'].remixd.event.register('closed', (event) => { self._deps.fileProviders['localhost'].remixd.event.register('closed', (event) => {
websocketconn.style.color = styles.colors.black websocketconn.style.color = styles.colors.black
websocketconn.setAttribute('title', 'localhost connection closed. ' + JSON.stringify(event)) websocketconn.setAttribute('title', 'localhost connection closed. ' + JSON.stringify(event))
fileSystemExplorer.hide() fileSystemExplorer.hide()
}) })
fileExplorer.events.register('focus', function (path) { fileExplorer.events.register('focus', function (path) {
appAPI.switchFile(path) self._deps.fileManager.switchFile(path)
}) })
configExplorer.events.register('focus', function (path) { configExplorer.events.register('focus', function (path) {
appAPI.switchFile(path) self._deps.fileManager.switchFile(path)
}) })
fileSystemExplorer.events.register('focus', function (path) { fileSystemExplorer.events.register('focus', function (path) {
appAPI.switchFile(path) self._deps.fileManager.switchFile(path)
}) })
swarmExplorer.events.register('focus', function (path) { swarmExplorer.events.register('focus', function (path) {
appAPI.switchFile(path) self._deps.fileManager.switchFile(path)
}) })
githubExplorer.events.register('focus', function (path) { githubExplorer.events.register('focus', function (path) {
appAPI.switchFile(path) self._deps.fileManager.switchFile(path)
}) })
gistExplorer.events.register('focus', function (path) { gistExplorer.events.register('focus', function (path) {
appAPI.switchFile(path) self._deps.fileManager.switchFile(path)
}) })
self.render = function render () { return element } self.render = function render () { return element }
@ -235,12 +243,12 @@ function filepanel (appAPI, filesProvider) {
function createNewFile () { function createNewFile () {
modalDialogCustom.prompt(null, 'File Name', 'Untitled.sol', (input) => { modalDialogCustom.prompt(null, 'File Name', 'Untitled.sol', (input) => {
helper.createNonClashingName(input, filesProvider['browser'], (error, newName) => { helper.createNonClashingName(input, self._deps.fileProviders['browser'], (error, newName) => {
if (error) return modalDialogCustom.alert('Failed to create file ' + newName + ' ' + error) if (error) return modalDialogCustom.alert('Failed to create file ' + newName + ' ' + error)
if (!filesProvider['browser'].set(newName, '')) { if (!self._deps.fileProviders['browser'].set(newName, '')) {
modalDialogCustom.alert('Failed to create file ' + newName) modalDialogCustom.alert('Failed to create file ' + newName)
} else { } else {
appAPI.switchFile(filesProvider['browser'].type + '/' + newName) self._deps.fileManager.switchFile(self._deps.fileProviders['browser'].type + '/' + newName)
} }
}) })
}, null, true) }, null, true)
@ -253,15 +261,15 @@ function filepanel (appAPI, filesProvider) {
* @param {String} txHash - hash of the transaction * @param {String} txHash - hash of the transaction
*/ */
function connectToLocalhost () { function connectToLocalhost () {
if (filesProvider['localhost'].isConnected()) { if (self._deps.fileProviders['localhost'].isConnected()) {
filesProvider['localhost'].close((error) => { self._deps.fileProviders['localhost'].close((error) => {
if (error) console.log(error) if (error) console.log(error)
}) })
} else { } else {
modalDialog('Connect to localhost', remixdDialog(), modalDialog('Connect to localhost', remixdDialog(),
{ label: 'Connect', { label: 'Connect',
fn: () => { fn: () => {
filesProvider['localhost'].init((error) => { self._deps.fileProviders['localhost'].init((error) => {
if (error) { if (error) {
console.log(error) console.log(error)
} else { } else {
@ -275,7 +283,7 @@ function filepanel (appAPI, filesProvider) {
// ------------------ gist publish -------------- // ------------------ gist publish --------------
function updateGist () { function updateGist () {
var gistId = filesProvider['gist'].id var gistId = self._deps.fileProviders['gist'].id
if (!gistId) { if (!gistId) {
tooltip('no gist content is currently loaded.') tooltip('no gist content is currently loaded.')
} else { } else {
@ -290,12 +298,12 @@ function filepanel (appAPI, filesProvider) {
} }
function toGist (fileProviderName, id) { function toGist (fileProviderName, id) {
packageFiles(filesProvider[fileProviderName], (error, packaged) => { packageFiles(self._deps.fileProviders[fileProviderName], (error, packaged) => {
if (error) { if (error) {
console.log(error) console.log(error)
modalDialogCustom.alert('Failed to create gist: ' + error) modalDialogCustom.alert('Failed to create gist: ' + error)
} else { } else {
var tokenAccess = appAPI.config.get('settings/gist-access-token') var tokenAccess = self._deps.config.get('settings/gist-access-token')
if (!tokenAccess) { if (!tokenAccess) {
modalDialogCustom.alert('Remix requires an access token (which includes gists creation permission). Please go to the settings tab for more information.') modalDialogCustom.alert('Remix requires an access token (which includes gists creation permission). Please go to the settings tab for more information.')
} else { } else {
@ -350,7 +358,7 @@ function filepanel (appAPI, filesProvider) {
}) })
function doCopy (target) { function doCopy (target) {
// package only files from the browser storage. // package only files from the browser storage.
packageFiles(filesProvider['browser'], (error, packaged) => { packageFiles(self._deps.fileProviders['browser'], (error, packaged) => {
if (error) { if (error) {
console.log(error) console.log(error)
} else { } else {

Loading…
Cancel
Save