Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support file drag-and-drop functionality #3

Merged
merged 4 commits into from
Oct 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -3,4 +3,3 @@
Stream data through multiple QRCodes

https://github.com/user-attachments/assets/5328d238-0f4e-4eb6-80ec-deb59d2e9897

75 changes: 75 additions & 0 deletions app/components/DropZone.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
defineProps<{
text: string
}>()
const emit = defineEmits<{
(e: 'file', files: File): void
}>()
// Ported from https://github.com/react-dropzone/react-dropzone/issues/753#issuecomment-774782919
const isDragging = ref(false)
const dragCounter = ref(0)
function onDragEnter(event: DragEvent) {
event.preventDefault()
dragCounter.value++
isDragging.value = true
}
function onDragLeave(event: DragEvent) {
event.preventDefault()
dragCounter.value--
if (dragCounter.value > 0)
return
isDragging.value = false
}
function onDragOver(event: DragEvent) {
event.preventDefault()
}
async function onDrop(event: DragEvent) {
event.preventDefault()
isDragging.value = false
if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length > 0) {
dragCounter.value = 0
if (event.dataTransfer.files.length > 1) {
console.warn('Multiple files are not supported. Only the first file will be processed.')
}
const firstFile = event.dataTransfer.files[0]
if (!firstFile)
return
emit('file', firstFile)
event.dataTransfer.clearData()
}
}
onMounted(() => {
window.addEventListener('dragenter', onDragEnter)
window.addEventListener('dragleave', onDragLeave)
window.addEventListener('dragover', onDragOver)
window.addEventListener('drop', onDrop)
})
onUnmounted(() => {
window.removeEventListener('dragenter', onDragEnter)
window.removeEventListener('dragleave', onDragLeave)
window.removeEventListener('dragover', onDragOver)
window.removeEventListener('drop', onDrop)
})
</script>

<template>
<div
v-if="isDragging"
fixed inset-0 z-50 flex items-center justify-center bg-gray-900 bg-opacity-50 p-4
>
<div h-full w-full flex items-center justify-center border-4 border-white rounded-lg border-dashed p-8>
<span text-2xl text-white>{{ text }}</span>
</div>
</div>
</template>
8 changes: 2 additions & 6 deletions app/pages/index.vue
Original file line number Diff line number Diff line change
@@ -69,11 +69,7 @@ async function onFileChange(file?: File) {
min-h="[calc(100vh-250px)]" h-full w-full
text="neutral-600 dark:neutral-400"
@file="onFileChange"
>
<div i-carbon:document-add text-2xl />
<p font-semi-bold pl-4 text-2xl>
<span>Choose</span>
</p>
</InputFile>
/>
<DropZone text="Drop File Here" @file="onFileChange" />
</div>
</template>