116 lines
2.8 KiB
Vue
116 lines
2.8 KiB
Vue
<template>
|
|
<div @click="focus" class="shell" ref="scrollable" :class="{ ['shell--hidden']: !showShell}">
|
|
<div v-for="(c, index) in content" :key="index" class="shell__result" >
|
|
<div class="shell__prompt"><i class="material-icons">chevron_right</i></div>
|
|
<pre class="shell__text">{{ c.text }}</pre>
|
|
</div>
|
|
|
|
<div class="shell__result" :class="{ 'shell__result--hidden': !canInput }" >
|
|
<div class="shell__prompt"><i class="material-icons">chevron_right</i></div>
|
|
<pre
|
|
tabindex="0"
|
|
ref="input"
|
|
class="shell__text"
|
|
contenteditable="true"
|
|
@keydown.prevent.38="historyUp"
|
|
@keydown.prevent.40="historyDown"
|
|
@keypress.prevent.enter="submit" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapMutations, mapState, mapGetters } from 'vuex'
|
|
import { commands } from '@/api'
|
|
|
|
export default {
|
|
name: 'shell',
|
|
computed: {
|
|
...mapState([ 'user', 'showShell' ]),
|
|
...mapGetters([ 'isFiles', 'isLogged' ]),
|
|
path: function () {
|
|
if (this.isFiles) {
|
|
return this.$route.path
|
|
}
|
|
|
|
return ''
|
|
}
|
|
},
|
|
data: () => ({
|
|
content: [],
|
|
history: [],
|
|
historyPos: 0,
|
|
canInput: true
|
|
}),
|
|
methods: {
|
|
...mapMutations([ 'toggleShell' ]),
|
|
scroll: function () {
|
|
this.$refs.scrollable.scrollTop = this.$refs.scrollable.scrollHeight
|
|
},
|
|
focus: function () {
|
|
this.$refs.input.focus()
|
|
},
|
|
historyUp () {
|
|
if (this.historyPos > 0) {
|
|
this.$refs.input.innerText = this.history[--this.historyPos]
|
|
this.focus()
|
|
}
|
|
},
|
|
historyDown () {
|
|
if (this.historyPos >= 0 && this.historyPos < this.history.length - 1) {
|
|
this.$refs.input.innerText = this.history[++this.historyPos]
|
|
this.focus()
|
|
} else {
|
|
this.historyPos = this.history.length
|
|
this.$refs.input.innerText = ''
|
|
}
|
|
},
|
|
submit: function (event) {
|
|
const cmd = event.target.innerText.trim()
|
|
|
|
if (cmd === '') {
|
|
return
|
|
}
|
|
|
|
if (cmd === 'clear') {
|
|
this.content = []
|
|
event.target.innerHTML = ''
|
|
return
|
|
}
|
|
|
|
if (cmd === 'exit') {
|
|
event.target.innerHTML = ''
|
|
this.toggleShell()
|
|
return
|
|
}
|
|
|
|
this.canInput = false
|
|
event.target.innerHTML = ''
|
|
|
|
let results = {
|
|
text: `${cmd}\n\n`
|
|
}
|
|
|
|
this.history.push(cmd)
|
|
this.historyPos = this.history.length
|
|
this.content.push(results)
|
|
|
|
commands(
|
|
this.path,
|
|
cmd,
|
|
event => {
|
|
results.text += `${event.data}\n`
|
|
this.scroll()
|
|
},
|
|
() => {
|
|
results.text = results.text.trimEnd()
|
|
this.canInput = true
|
|
this.$refs.input.focus()
|
|
this.scroll()
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|
|
</script>
|