Merge pull request #1044 from ethereum/contextmenu

Context menu in file explorer
pull/3094/head
yann300 7 years ago committed by GitHub
commit 0892c2a44d
  1. 7
      src/app/editor/editor.js
  2. 37
      src/app/files/file-explorer.js
  3. 3
      src/app/files/fileManager.js
  4. 18
      src/app/panels/file-panel.js
  5. 63
      src/app/ui/contextMenu.js

@ -186,6 +186,13 @@ function Editor (opts = {}) {
return editor.session.doc.positionToIndex(editor.getCursorPosition(), 0)
}
this.discardCurrentSession = function () {
if (sessions[currentSession]) {
delete sessions[currentSession]
currentSession = null
}
}
this.discard = function (path) {
if (currentSession !== path) {
delete sessions[path]

@ -5,7 +5,7 @@ var modalDialog = require('../ui/modaldialog')
var modalDialogCustom = require('../ui/modal-dialog-custom')
var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager
var contextMenu = require('../ui/contextMenu')
var helper = require('../../lib/helper')
var styleGuide = remixLib.ui.themeChooser
@ -117,7 +117,7 @@ function fileExplorer (appAPI, files) {
}
function fileRemoved (filepath) {
var label = this.treeView.labelAt(filepath)
var label = self.treeView.labelAt(filepath)
if (label && label.parentElement) {
label.parentElement.removeChild(label)
}
@ -154,13 +154,25 @@ function fileExplorer (appAPI, files) {
return yo`<label class="${data.children ? css.folder : css.file}"
data-path="${data.path}"
style="${isRoot ? 'font-weight:bold;' : ''}"
onclick=${editModeOn}
onkeydown=${editModeOff}
onblur=${editModeOff}
>${key.split('/').pop()}</label>`
}
})
self.treeView.event.register('leafRightClick', function (key, data, label, event) {
contextMenu(event, {
'Rename': () => {
if (self.files.readonly) return
var name = label.querySelector('label[data-path="' + key + '"]')
if (name) editModeOn(name)
},
'Delete': () => {
modalDialogCustom.confirm(null, 'Do you want to delete this file?', () => { files.remove(key) }, () => {})
}
})
})
self.treeView.event.register('leafClick', function (key, data, label) {
if (self.focusElement) {
self.focusElement.classList.remove(css.hasFocus)
@ -172,7 +184,6 @@ function fileExplorer (appAPI, files) {
self.focusElement.classList.add(css.hasFocus)
self.focusPath = key
self.events.trigger('focus', [key])
appAPI.config.set('currentFile', key)
}
})
@ -199,7 +210,7 @@ function fileExplorer (appAPI, files) {
// register to main app, trigger when the current file in the editor changed
appAPI.event.register('currentFileChanged', (newFile, explorer) => {
if (self.focusElement && 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 = null
self.focusPath = null
@ -209,17 +220,11 @@ function fileExplorer (appAPI, files) {
var textUnderEdit = null
var textInRename = false
function editModeOn (event) {
if (self.files.readonly) return
var label = this
var li = label.parentElement.parentElement.parentElement
var classes = li.className
if (~classes.indexOf('hasFocus') && !label.getAttribute('contenteditable') && label.getAttribute('data-path') !== self.files.type) {
textUnderEdit = label.innerText
label.setAttribute('contenteditable', true)
label.classList.add(css.rename)
label.focus()
}
function editModeOn (label) {
textUnderEdit = label.innerText
label.setAttribute('contenteditable', true)
label.classList.add(css.rename)
label.focus()
}
function editModeOff (event) {

@ -92,7 +92,7 @@ class FileManager {
if (path === this.opt.config.get('currentFile')) {
this.opt.config.set('currentFile', '')
}
this.opt.editor.discard(path)
this.opt.editor.discardCurrentSession()
delete this.tabbedFiles[path]
this.refreshTabs()
}
@ -131,6 +131,7 @@ class FileManager {
_switchFile(browserProvider.type + '/' + fileList[0])
} else {
self.event.trigger('currentFileChanged', [])
self.opt.editor.displayEmptyReadOnlySession()
}
})
}

@ -311,6 +311,7 @@ function filepanel (appAPI, filesProvider) {
// return all the files, except the temporary/readonly ones..
function packageFiles (files, callback) {
var ret = {}
// @TODO remove use of `list()`
var filtered = Object.keys(files.list()).filter(function (path) { if (!files.isReadOnly(path)) { return path } })
async.eachSeries(filtered, function (path, cb) {
ret[path.replace(files.type + '/', '')] = { content: files.get(path) }
@ -320,4 +321,21 @@ function packageFiles (files, callback) {
})
}
/*
Overview of APIs:
* fileManager: @args fileProviders (browser, shared-folder, swarm, github, etc ...) & config & editor
- listen on browser & localhost file provider (`fileRenamed` & `fileRemoved`)
- update the tabs, switchFile
- trigger `currentFileChanged`
- set the current file in the config
* fileProvider: currently browser, swarm, localhost, github, gist
- link to backend
- provide properties `type`, `readonly`
- provide API `resolveDirectory`, `remove`, `exists`, `rename`, `get`, `set`
- trigger `fileExternallyChanged`, `fileRemoved`, `fileRenamed`, `fileRenamedError`, `fileAdded`
* file-explorer: treeview @args fileProvider
- listen on events triggered by fileProvider
- call fileProvider API
*/
module.exports = filepanel

@ -0,0 +1,63 @@
var yo = require('yo-yo')
// -------------- copyToClipboard ----------------------
var csjs = require('csjs-inject')
var styleGuide = require('remix-lib').ui.themeChooser
var styles = styleGuide.chooser()
var css = csjs`
.container
{
display: none;
position: fixed;
border: 1px solid ${styles.appProperties.solidBorderBox_BorderColor};
width:150px;
background: ${styles.appProperties.solidBorderBox_BackgroundColor};
border-radius: 2px;
}
.liitem
{
padding: 3px;
padding-left: 10px;
cursor: pointer;
}
#menuitems
{
list-style: none;
margin: 0px;
margin-top: 4px;
padding-left: 5px;
padding-right: 5px;
padding-bottom: 3px;
color: ${styles.appProperties.solidBorderBox_TextColor};
}
#menuitems :hover
{
background: ${styles.appProperties.highlight_BackgroundColor};
border-radius: 2px;
}
`
module.exports = (event, items) => {
event.preventDefault()
var menu = Object.keys(items).map((item, index) => {
var current = yo`<li class=${css.liitem}>${item}</li>`
current.onclick = () => items[item]()
return current
})
var container = yo`<div class=${css.container}><ul id='menuitems'>${menu}</ul></div>`
container.style.left = event.pageX + 'px'
container.style.top = event.pageY + 'px'
container.style.display = 'block'
function hide (event) {
if (event.target !== container) {
container.parentElement.removeChild(container)
}
window.removeEventListener('click', hide)
}
window.addEventListener('click', hide)
document.querySelector('body').appendChild(container)
}
Loading…
Cancel
Save