Files
filebrowser/frontend/src/components/Shell.vue
T

195 lines
5.0 KiB
Vue
Raw Normal View History

2019-01-05 16:12:09 +00:00
<template>
2021-03-21 12:51:58 +01:00
<div
class="shell"
:class="{ ['shell--hidden']: !showShell }"
2024-02-09 12:04:02 +02:00
:style="{ height: `${this.shellHeight}em`, direction: 'ltr' }"
2021-03-21 12:51:58 +01:00
>
2023-09-14 15:50:40 -07:00
<div
@pointerdown="startDrag()"
@pointerup="stopDrag()"
class="shell__divider"
:style="this.shellDrag ? { background: `${checkTheme()}` } : ''"
></div>
<div @click="focus" class="shell__content" ref="scrollable">
<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>
2021-03-21 12:51:58 +01:00
</div>
2019-01-05 16:12:09 +00:00
2023-09-14 15:50:40 -07:00
<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"
2024-04-01 17:18:22 +02:00
:contenteditable="true"
@keydown.prevent.arrow-up="historyUp"
@keydown.prevent.arrow-down="historyDown"
2023-09-14 15:50:40 -07:00
@keypress.prevent.enter="submit"
/>
2021-03-21 12:51:58 +01:00
</div>
2019-01-05 16:12:09 +00:00
</div>
2023-09-14 15:50:40 -07:00
<div
@pointerup="stopDrag()"
class="shell__overlay"
v-show="this.shellDrag"
></div>
2019-01-05 16:12:09 +00:00
</div>
</template>
<script>
2024-04-01 17:18:22 +02:00
import { mapState, mapActions } from "pinia";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
2021-03-21 12:51:58 +01:00
import { commands } from "@/api";
2024-12-09 12:27:18 +01:00
import { throttle } from "lodash-es";
2023-09-14 15:50:40 -07:00
import { theme } from "@/utils/constants";
2019-01-05 16:12:09 +00:00
export default {
2021-03-21 12:51:58 +01:00
name: "shell",
2019-01-05 16:12:09 +00:00
computed: {
2024-04-01 17:18:22 +02:00
...mapState(useLayoutStore, ["showShell"]),
...mapState(useFileStore, ["isFiles"]),
2019-01-05 16:12:09 +00:00
path: function () {
if (this.isFiles) {
2021-03-21 12:51:58 +01:00
return this.$route.path;
2019-01-05 16:12:09 +00:00
}
2021-03-21 12:51:58 +01:00
return "";
},
2019-01-05 16:12:09 +00:00
},
data: () => ({
content: [],
history: [],
historyPos: 0,
2021-03-21 12:51:58 +01:00
canInput: true,
2023-09-14 15:50:40 -07:00
shellDrag: false,
shellHeight: 25,
fontsize: parseFloat(getComputedStyle(document.documentElement).fontSize),
2019-01-05 16:12:09 +00:00
}),
2023-09-14 15:50:40 -07:00
mounted() {
window.addEventListener("resize", this.resize);
},
2024-04-01 17:18:22 +02:00
beforeUnmount() {
2023-09-14 15:50:40 -07:00
window.removeEventListener("resize", this.resize);
},
2019-01-05 16:12:09 +00:00
methods: {
2024-04-01 17:18:22 +02:00
...mapActions(useLayoutStore, ["toggleShell"]),
2023-09-14 15:50:40 -07:00
checkTheme() {
if (theme == "dark") {
return "rgba(255, 255, 255, 0.4)";
}
return "rgba(127, 127, 127, 0.4)";
},
startDrag() {
document.addEventListener("pointermove", this.handleDrag);
this.shellDrag = true;
},
stopDrag() {
document.removeEventListener("pointermove", this.handleDrag);
this.shellDrag = false;
},
handleDrag: throttle(function (event) {
const top = window.innerHeight / this.fontsize - 4;
const userPos = (window.innerHeight - event.clientY) / this.fontsize;
const bottom =
2.25 +
document.querySelector(".shell__divider").offsetHeight / this.fontsize;
if (userPos <= top && userPos >= bottom) {
this.shellHeight = userPos.toFixed(2);
}
}, 32),
resize: throttle(function () {
const top = window.innerHeight / this.fontsize - 4;
const bottom =
2.25 +
document.querySelector(".shell__divider").offsetHeight / this.fontsize;
if (this.shellHeight > top) {
this.shellHeight = top;
} else if (this.shellHeight < bottom) {
this.shellHeight = bottom;
}
}, 32),
2019-01-05 16:12:09 +00:00
scroll: function () {
2021-03-21 12:51:58 +01:00
this.$refs.scrollable.scrollTop = this.$refs.scrollable.scrollHeight;
2019-01-05 16:12:09 +00:00
},
focus: function () {
2021-03-21 12:51:58 +01:00
this.$refs.input.focus();
2019-01-05 16:12:09 +00:00
},
2021-03-21 12:51:58 +01:00
historyUp() {
2019-01-05 16:12:09 +00:00
if (this.historyPos > 0) {
2021-03-21 12:51:58 +01:00
this.$refs.input.innerText = this.history[--this.historyPos];
this.focus();
2019-01-05 16:12:09 +00:00
}
},
2021-03-21 12:51:58 +01:00
historyDown() {
2019-01-05 16:12:09 +00:00
if (this.historyPos >= 0 && this.historyPos < this.history.length - 1) {
2021-03-21 12:51:58 +01:00
this.$refs.input.innerText = this.history[++this.historyPos];
this.focus();
2019-01-05 16:12:09 +00:00
} else {
2021-03-21 12:51:58 +01:00
this.historyPos = this.history.length;
this.$refs.input.innerText = "";
2019-01-05 16:12:09 +00:00
}
},
submit: function (event) {
2021-03-21 12:51:58 +01:00
const cmd = event.target.innerText.trim();
2019-01-05 16:12:09 +00:00
2021-03-21 12:51:58 +01:00
if (cmd === "") {
return;
2019-01-05 16:12:09 +00:00
}
2021-03-21 12:51:58 +01:00
if (cmd === "clear") {
this.content = [];
event.target.innerHTML = "";
return;
2019-01-05 16:12:09 +00:00
}
2021-03-21 12:51:58 +01:00
if (cmd === "exit") {
event.target.innerHTML = "";
this.toggleShell();
return;
2019-01-05 16:12:09 +00:00
}
2021-03-21 12:51:58 +01:00
this.canInput = false;
event.target.innerHTML = "";
2019-01-05 16:12:09 +00:00
2025-01-30 10:18:48 +01:00
const results = {
2021-03-21 12:51:58 +01:00
text: `${cmd}\n\n`,
};
this.history.push(cmd);
this.historyPos = this.history.length;
this.content.push(results);
2019-01-05 16:12:09 +00:00
commands(
this.path,
cmd,
2021-03-21 12:51:58 +01:00
(event) => {
results.text += `${event.data}\n`;
this.scroll();
2019-01-05 16:12:09 +00:00
},
() => {
2023-07-20 23:38:53 +08:00
results.text = results.text
2025-01-30 10:18:48 +01:00
2023-07-20 23:38:53 +08:00
.replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now
.trimEnd();
2021-03-21 12:51:58 +01:00
this.canInput = true;
this.$refs.input.focus();
this.scroll();
2019-01-05 16:12:09 +00:00
}
2021-03-21 12:51:58 +01:00
);
},
},
};
2019-01-05 16:12:09 +00:00
</script>