- ${self._view.log}
+
+ ${self._view.journal}
${self._view.cli}
`
- self._view.panel = yo`
+ self._view.el = yo`
${self._view.bar}
${self._view.term}
`
- self.log(self.data.banner)
+ self._output(self.data.banner)
+ function focusinput (event) {
+ if (self._view.journal.offsetHeight - (self._view.term.scrollTop + self._view.term.offsetHeight) < 50) {
+ refocus()
+ }
+ }
+ function refocus () {
+ self._view.input.focus()
+ reattach({ currentTarget: self._view.term })
+ self.scroll2bottom()
+ }
+ var css2 = csjs`
+ .anchor {
+ position : static;
+ border-top : 2px dotted blue;
+ height : 10px;
+ }
+ .overlay {
+ position : absolute;
+ width : 100%;
+ display : flex;
+ align-items : center;
+ justify-content : center;
+ bottom : 0;
+ right : 15px;
+ height : 20%;
+ min-height : 50px;
+ }
+ .text {
+ z-index : 2;
+ color : black;
+ font-size : 25px;
+ font-weight : bold;
+ pointer-events : none;
+ }
+ .background {
+ z-index : 1;
+ opacity : 0.8;
+ background-color : #a6aeba;
+ cursor : pointer;
+ }
+ `
+ var text = yo`
`
+ var background = yo`
`
+ var placeholder = yo`
${background}${text}
`
+ var inserted = false
+
+ function throttle (fn, wait) {
+ var time = Date.now()
+ return function () {
+ if ((time + wait - Date.now()) < 0) {
+ fn.apply(this, arguments)
+ time = Date.now()
+ }
+ }
+ }
function reattach (event) {
var el = event.currentTarget
- var isBottomed = el.scrollHeight - el.scrollTop === el.clientHeight
+ var isBottomed = el.scrollHeight - el.scrollTop < el.clientHeight + 30
if (isBottomed) {
+ if (inserted) {
+ text.innerText = ''
+ background.onclick = undefined
+ self._view.journal.removeChild(placeholder)
+ }
+ inserted = false
delete self.scroll2bottom
- // @TODO: delete new message indicator
} else {
- self.scroll2bottom = function () { }
- // @TODO: while in stopped mode: show indicator about new lines getting logged
+ if (!inserted) self._view.journal.appendChild(placeholder)
+ inserted = true
+ check()
+ if (!placeholder.nextElementSibling) {
+ placeholder.style.display = 'none'
+ } else {
+ placeholder.style = ''
+ }
+ self.scroll2bottom = function () {
+ var next = placeholder.nextElementSibling
+ if (next) {
+ placeholder.style = ''
+ check()
+ var messages = 1
+ while ((next = next.nextElementSibling)) messages += 1
+ text.innerText = `${messages} new unread log entries`
+ } else {
+ placeholder.style.display = 'none'
+ }
+ }
+ }
+ }
+ function check () {
+ var pos1 = self._view.term.offsetHeight + self._view.term.scrollTop - (self._view.el.offsetHeight * 0.15)
+ var pos2 = placeholder.offsetTop
+ if ((pos1 - pos2) > 0) {
+ text.style.display = 'none'
+ background.style.position = 'relative'
+ background.style.opacity = 0.3
+ background.style.right = 0
+ background.style.borderBox = 'content-box'
+ background.style.padding = '2px'
+ background.style.height = (self._view.journal.offsetHeight - (placeholder.offsetTop + placeholder.offsetHeight)) + 'px'
+ background.onclick = undefined
+ background.style.cursor = 'default'
+ } else {
+ background.style = ''
+ text.style = ''
+ background.onclick = function (event) {
+ console.error('background click')
+ placeholder.scrollIntoView()
+ check()
+ }
}
}
function hover (event) { event.currentTarget.classList.toggle(css.hover) }
function minimize (event) {
event.preventDefault()
event.stopPropagation()
- var classList = self._view.icon.classList
- classList.toggle('fa-angle-double-down')
- classList.toggle('fa-angle-double-up')
- self.event.trigger('resize', [])
+ if (event.button === 0) {
+ var classList = self._view.icon.classList
+ classList.toggle('fa-angle-double-down')
+ classList.toggle('fa-angle-double-up')
+ self.event.trigger('resize', [])
+ }
}
// ----------------- resizeable ui ---------------
function mousedown (event) {
@@ -256,7 +375,7 @@ class Terminal {
self.event.trigger('resize', [self._api.getPosition(event)])
}
- return self._view.panel
+ return self._view.el
function change (event) {
if (event.which === 13) {
@@ -301,7 +420,7 @@ class Terminal {
}
_blocksRenderer (mode) {
var self = this
- var modes = { log: true, info: true, error: true, default: true }
+ var modes = { log: true, info: true, error: true }
if (modes[mode]) {
return function render () {
var args = [].slice.call(arguments)
@@ -319,23 +438,44 @@ class Terminal {
throw new Error('mode is not supported')
}
}
+ execute (script) {
+ var self = this
+ script = String(script)
+ self._output({ type: 'log', value: `> ${script}` })
+ self._shell(script, function (error, output) {
+ if (error) {
+ self._output({ type: 'error', value: error })
+ return error
+ } else {
+ self._output({ type: 'log', value: output })
+ return output
+ }
+ })
+ }
registerType (typename, template) {
var self = this
if (typeof template !== 'function') throw new Error('invalid template')
self._templates[typename] = template
+ self.logger[typename] = function () {
+ var args = [...arguments].map(x => ({ type: typename, value: x }))
+ self._output.apply(self, args)
+ }
}
log () {
+ // @TODO: temporary to not break stuff that uses the old API
+ this._output.apply(this, arguments)
+ }
+ _output () {
var self = this
var args = [...arguments]
self.data.session.push(args)
args.forEach(function (data) {
- if (!data || !data.type) data = { type: 'default', value: data }
+ if (!data || !data.type) data = { type: 'log', value: data }
var render = self._templates[data.type]
- if (!render) render = self._templates.default
var blocks = render(data.value)
- blocks = blocks instanceof Array ? blocks : [blocks]
+ blocks = [].concat(blocks)
blocks.forEach(function (block) {
- self._view.log.appendChild(yo`
+ self._view.journal.appendChild(yo`
${block}
@@ -344,41 +484,18 @@ class Terminal {
})
})
}
- info () {
- var self = this
- var args = [...arguments].map(x => ({ type: 'info', value: x }))
- self.log.apply(self, args)
- }
- error () {
- var self = this
- var args = [...arguments].map(x => ({ type: 'error', value: x }))
- self.log.apply(self, args)
- }
scroll2bottom () {
var self = this
setTimeout(function () {
self._view.term.scrollTop = self._view.term.scrollHeight
}, 0)
}
- execute (input) {
+ _shell (script, done) { // default shell
var self = this
- input = String(input)
- self.log(`> ${input}`)
- self._shell(input, function (error, output) {
- if (error) {
- self.error(error)
- return error
- } else {
- self.log(output)
- return output
- }
- })
- }
- _shell (input, done) { // default shell
try {
- var context = vm.createContext(Object.assign(this._jsSandboxContext, domTerminalFeatures(this)))
- var result = vm.runInContext(input, context)
- this._jsSandboxContext = Object.assign({}, context)
+ var context = vm.createContext(Object.assign(self._jsSandboxContext, domTerminalFeatures(self)))
+ var result = vm.runInContext(script, context)
+ self._jsSandboxContext = Object.assign({}, context)
done(null, result)
} catch (error) {
done(error.message)
@@ -386,12 +503,12 @@ class Terminal {
}
}
-// @TODO add all the `console` functions
function domTerminalFeatures (self) {
+ // @TODO add all the `console` functions
return {
- web3: self._api.context() !== 'vm' ? new Web3(self._api.web3().currentProvider) : null,
+ web3: executionContext.getProvider() !== 'vm' ? new Web3(executionContext.web3().currentProvider) : null,
console: {
- log: function () { self.log.apply(self, arguments) }
+ log: function () { self._output.apply(self, arguments) }
}
}
}