88 lines
No EOL
3 KiB
Vue
88 lines
No EOL
3 KiB
Vue
<template>
|
|
<div @dragenter.prevent="dragenter" @dragover.prevent="dragover" @dragleave.prevent="dragleave"
|
|
@drop.prevent="drop" ref="dropzone">
|
|
<slot></slot>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.dragover {
|
|
opacity: 0.5;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
import * as BIcons from "bootstrap-icons-vue";
|
|
|
|
export default {
|
|
name: "DragDropFileSource",
|
|
components: {
|
|
...BIcons
|
|
},
|
|
emits: ["input"],
|
|
methods: {
|
|
dragenter(e) {
|
|
if (e.dataTransfer.types.includes("Files")) {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
this.$refs.dropzone.classList.add("dragover")
|
|
}else{
|
|
console.log(e.dataTransfer.types) //TODO text/uri-list?
|
|
}
|
|
},
|
|
dragover(e) {
|
|
if (e.dataTransfer.types.includes("Files")) {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
this.$refs.dropzone.classList.add("dragover")
|
|
}
|
|
},
|
|
dragleave(e) {
|
|
if (e.dataTransfer.types.includes("Files")) {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
this.$refs.dropzone.classList.remove("dragover")
|
|
}
|
|
},
|
|
drop(e) {
|
|
if (e.dataTransfer.types.includes("Files")) {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
this.$refs.dropzone.classList.remove("dragover")
|
|
const jobs = [...e.dataTransfer.files].map((file) => {
|
|
return new Promise((resolve, reject) => {
|
|
let reader = new FileReader();
|
|
reader.readAsArrayBuffer(file)
|
|
reader.onloadend = () => {
|
|
const buffer = reader.result;
|
|
if (!(buffer instanceof ArrayBuffer)) {
|
|
console.log(buffer)
|
|
reject("Not an ArrayBuffer");
|
|
}
|
|
const data = new Uint8Array(buffer);
|
|
const hash = nacl.crypto_hash(data).reduce((a, b) => a + b.toString(16).padStart(2, "0"), "");
|
|
var base64 = btoa(
|
|
data.reduce((a, b) => a + String.fromCharCode(b), '')
|
|
);
|
|
resolve({
|
|
name: file.name,
|
|
size: file.size,
|
|
mime_type: file.type,
|
|
data: base64,
|
|
hash: hash,
|
|
});
|
|
}
|
|
reader.onerror = (e) => {
|
|
reject(e)
|
|
}
|
|
})
|
|
})
|
|
Promise.all(jobs).then((files) => {
|
|
this.$emit("input", files)
|
|
console.log("drop", files)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script> |