[UI] FileEditor improvements.

- Switched to dark mode (I couldn't find any decent light theme
  combination that works with the Platypush UI).

- Support passing static `content` and `content-type` rather than only a
  `file`.

- Pass the `with-save` property from `EditorModal` to `Editor`.
This commit is contained in:
Fabio Manganiello 2024-11-20 02:52:46 +01:00
parent 010b52ed19
commit 575c0ab730
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774
2 changed files with 88 additions and 37 deletions

View file

@ -33,7 +33,7 @@
<script> <script>
import axios from 'axios'; import axios from 'axios';
import hljs from 'highlight.js'; import hljs from 'highlight.js';
import 'highlight.js/styles/intellij-light.css'; import 'highlight.js/styles/night-owl.min.css'
import FloatingButton from "@/components/elements/FloatingButton"; import FloatingButton from "@/components/elements/FloatingButton";
import Highlighter from "./Highlighter"; import Highlighter from "./Highlighter";
@ -51,7 +51,16 @@ export default {
props: { props: {
file: { file: {
type: String, type: String,
required: true, },
text: {
type: String,
default: '',
},
contentType: {
type: String,
default: 'plaintext',
}, },
isNew: { isNew: {
@ -114,41 +123,43 @@ export default {
methods: { methods: {
async loadFile() { async loadFile() {
this.setUrlArgs({file: this.file}) if (!this.text?.length) {
if (this.isNew) { this.setUrlArgs({file: this.file})
this.content = '' if (this.isNew) {
this.initialContentHash = 0 this.content = ''
this.highlightedContent = '' this.initialContentHash = 0
this.info = {} this.highlightedContent = ''
this.type = this.getLanguageType({path: this.file}) this.info = {}
return this.type = this.getLanguageType({path: this.file})
} return
this.loading = true
try {
this.info = (
await this.request('file.info', {files: [this.file]})
)[this.file] || {}
this.type = this.getLanguageType(this.info)
this.content = (
await axios.get(`/file?path=${encodeURIComponent(this.file)}`)
).data
if (typeof this.content === 'object') {
this.content = JSON.stringify(this.content, null, 2)
} }
this.initialContentHash = this.content.hashCode() this.loading = true
} catch (e) {
this.notify({ try {
error: true, this.info = (
text: e.message, await this.request('file.info', {files: [this.file]})
title: 'Failed to load file', )[this.file] || {}
})
} finally { this.type = this.getLanguageType(this.info)
this.loading = false this.content = (
await axios.get(`/file?path=${encodeURIComponent(this.file)}`)
).data
if (typeof this.content === 'object') {
this.content = JSON.stringify(this.content, null, 2)
}
this.initialContentHash = this.content.hashCode()
} catch (e) {
this.notify({
error: true,
text: e.message,
title: 'Failed to load file',
})
} finally {
this.loading = false
}
} }
if (this.selectedLine) { if (this.selectedLine) {
@ -270,6 +281,11 @@ export default {
window.removeEventListener('beforeunload', this.beforeUnload) window.removeEventListener('beforeunload', this.beforeUnload)
}, },
convertType(type) {
const parts = type.split('/')
return parts[parts.length - 1]
},
reset() { reset() {
this.setUrlArgs({file: null, line: null}) this.setUrlArgs({file: null, line: null})
this.removeBeforeUnload() this.removeBeforeUnload()
@ -278,6 +294,14 @@ export default {
}, },
watch: { watch: {
contentType() {
if (!this.contentType?.length) {
return
}
this.type = this.convertType(this.contentType)
},
file() { file() {
this.loadFile() this.loadFile()
}, },
@ -323,6 +347,10 @@ export default {
this.$refs.selectedLine.style.top = `${offset}px` this.$refs.selectedLine.style.top = `${offset}px`
}) })
}, },
text() {
this.content = this.text
},
}, },
mounted() { mounted() {
@ -334,6 +362,8 @@ export default {
} }
} }
this.content = this.text
this.type = this.convertType(this.contentType)
this.loadFile() this.loadFile()
this.addBeforeUnload() this.addBeforeUnload()
this.addKeyListener() this.addKeyListener()
@ -354,6 +384,11 @@ export default {
$line-numbers-width: 2.5em; $line-numbers-width: 2.5em;
.file-editor { .file-editor {
--body-bg: #080808;
--body-fg: #f8f8f2;
--line-numbers-bg: #282a36;
--line-numbers-fg: #6272a4;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
@ -366,6 +401,8 @@ $line-numbers-width: 2.5em;
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: var(--body-bg);
color: var(--body-fg);
} }
.editor-highlight-loading { .editor-highlight-loading {
@ -412,6 +449,8 @@ $line-numbers-width: 2.5em;
align-items: flex-end; align-items: flex-end;
overflow: hidden; overflow: hidden;
z-index: 2; z-index: 2;
background: var(--line-numbers-bg);
color: var(--line-numbers-fg);
.line-number { .line-number {
width: 100%; width: 100%;
@ -444,7 +483,7 @@ $line-numbers-width: 2.5em;
overflow-x: scroll; overflow-x: scroll;
z-index: 2; z-index: 2;
color: rgba(0, 0, 0, 0); color: rgba(0, 0, 0, 0);
caret-color: black; caret-color: var(--body-fg);
border: none; border: none;
outline: none; outline: none;
} }

View file

@ -9,6 +9,9 @@
:file="file" :file="file"
:is-new="isNew" :is-new="isNew"
:line="line" :line="line"
:text="text"
:content-type="contentType"
:with-save="withSave"
@save="$emit('save', $event)" @save="$emit('save', $event)"
v-if="file" /> v-if="file" />
</div> </div>
@ -41,7 +44,16 @@ export default {
props: { props: {
file: { file: {
type: String, type: String,
required: true, },
text: {
type: String,
default: '',
},
contentType: {
type: String,
default: 'text/plain',
}, },
isNew: { isNew: {