extractify.zip/app.vue

215 lines
7.9 KiB
Vue
Raw Normal View History

2023-05-15 03:32:16 +03:00
<script setup lang="ts">
import { getElementInfo } from "moveable";
import { VueSelecto } from "vue3-selecto";
2023-05-19 00:07:04 +03:00
import { useDisplay } from 'vuetify/lib/framework.mjs';
import { HistoryManager } from './composables/history-manager';
import { FilesManager } from './composables/files-manager';
2023-05-15 03:32:16 +03:00
2023-05-19 00:07:04 +03:00
let display = useDisplay();
let drawer = ref(!display.mdAndDown.value);
2023-05-19 18:09:48 +03:00
let loadingModel = ref(false);
2023-05-15 03:32:16 +03:00
let files = ref([]);
let filesList = ref<any>([]);
let selectedItem = useSelectedItem();
2023-05-19 18:09:48 +03:00
let filesGridList = ref<any>([])
2023-05-29 19:51:08 +03:00
let selectedList = ref<any>([]);
let history = new HistoryManager(selectedItem, filesList);
let fileManager = new FilesManager(filesList);
2023-05-15 03:32:16 +03:00
watchEffect(async () => {
if (files.value?.[0]) {
2023-05-19 18:09:48 +03:00
loadingModel.value = true;
2023-05-15 03:32:16 +03:00
filesList.value = [];
fileManager.loadArchive(files.value?.[0]);
2023-05-15 03:32:16 +03:00
2023-05-19 18:09:48 +03:00
loadingModel.value = false;
2023-05-15 03:32:16 +03:00
}
})
function onDrop(e: any) {
2023-05-29 19:51:08 +03:00
if (!e.dataTransfer.files.length) return;
2023-05-15 03:32:16 +03:00
files.value = e.dataTransfer.files;
selectedItem.value = '/';
}
function preventDefaults(e: any) {
e.preventDefault()
}
const events = ['dragenter', 'dragover', 'dragleave', 'drop']
onMounted(() => {
events.forEach((eventName) => {
document.body.addEventListener(eventName, preventDefaults)
})
})
onUnmounted(() => {
events.forEach((eventName) => {
document.body.removeEventListener(eventName, preventDefaults)
})
})
watchEffect(() => {
filesGridList.value = fileManager.getFile(selectedItem.value)?.content || [];
2023-05-18 23:54:37 +03:00
selectedList.value = [];
for (const selectedElement of document.querySelectorAll(".selectable.selected")) {
selectedElement.classList.remove("selected");
}
2023-05-15 03:32:16 +03:00
})
let dragContainer = document.querySelector(".select-area");
function onSelectStart(e: any) {
e.added.forEach((el: any) => {
el.classList.add("selected");
2023-05-18 23:54:37 +03:00
selectedList.value = [...selectedList.value, el?.__vnode?.ctx?.props?.value];
2023-05-15 03:32:16 +03:00
});
e.removed.forEach((el: any) => {
el.classList.remove("selected");
2023-05-18 23:54:37 +03:00
selectedList.value = selectedList.value.filter((value: string) => value != el?.__vnode?.ctx?.props?.value)
2023-05-15 03:32:16 +03:00
});
}
function onSelectEnd(e: any) {
e.afterAdded.forEach((el: any) => {
el.classList.add("selected");
2023-05-18 23:54:37 +03:00
selectedList.value = [...selectedList.value, el?.__vnode?.ctx?.props?.value];
2023-05-15 03:32:16 +03:00
});
e.afterRemoved.forEach((el: any) => {
el.classList.remove("selected");
2023-05-18 23:54:37 +03:00
selectedList.value = selectedList.value.filter((value: string) => value != el?.__vnode?.ctx?.props?.value)
2023-05-15 03:32:16 +03:00
});
}
2023-05-29 19:51:08 +03:00
// step up from current path
function stepUp(path: string) {
let pathArray = path.split("/");
2023-05-30 04:01:16 +03:00
if (path.endsWith("/")) {
2023-05-29 19:51:08 +03:00
pathArray.pop();
}
pathArray.pop();
2023-06-03 06:40:47 +03:00
return (pathArray.join("/") || "/");
2023-05-29 19:51:08 +03:00
}
2023-05-15 03:32:16 +03:00
</script>
<template>
<v-layout @drop.prevent="onDrop">
<v-app-bar color="light-blue-darken-1">
<v-btn variant="text" icon="mdi-menu" v-slot:prepend @click="drawer = !drawer"></v-btn>
2023-05-19 00:12:11 +03:00
<v-toolbar-title>Extractify.zip</v-toolbar-title>
2023-05-15 03:32:16 +03:00
</v-app-bar>
2023-05-19 00:07:04 +03:00
<v-navigation-drawer v-model="drawer" :permanent="!display.xs">
2023-05-15 03:32:16 +03:00
<v-toolbar density="comfortable" title="Files">
<template v-slot:prepend>
<v-btn icon="mdi-home" @click="selectedItem = '/'"></v-btn>
</template>
</v-toolbar>
<TreeView :filesList="filesList" :nav=true></TreeView>
</v-navigation-drawer>
<v-main class="select-area" style="height: 100dvh;">
2023-05-29 19:51:08 +03:00
<v-toolbar class="px-5" height="auto">
<v-row align="center" justify="center">
2023-05-30 04:01:16 +03:00
<v-col cols="12" lg="2" md="12" style="display: inline-flex;">
2023-05-29 19:51:08 +03:00
<v-btn title="Back" aria-label="Back" icon="mdi-arrow-left" :disabled="!history.hasUndo.value"
2023-05-30 04:01:16 +03:00
@click="history.undo();"></v-btn>
2023-05-29 19:51:08 +03:00
<v-btn title="Forward" aria-label="Forward" icon="mdi-arrow-right" :disabled="!history.hasRedo.value"
2023-05-30 04:01:16 +03:00
@click="history.redo();"></v-btn>
<v-btn title="Refresh" aria-label="Refresh" icon="mdi-refresh" :disabled="!files.length"
@click="history.refresh();"></v-btn>
<v-btn title="Parent Folder" aria-label="Parent Folder" icon="mdi-arrow-up" :disabled="selectedItem == '/'"
@click="selectedItem = stepUp(selectedItem);"></v-btn>
2023-05-29 19:51:08 +03:00
</v-col>
<v-col cols="10" lg="8" md="10">
2023-05-30 04:01:16 +03:00
<v-text-field :disabled="!files.length" hide-details title="Location" single-line placeholder="location"
v-model="selectedItem"></v-text-field>
</v-col>
<v-col cols="2">
2023-05-30 04:01:16 +03:00
<v-menu>
<template v-slot:activator="{ props }">
<v-btn :disabled="!files.length" title="Menu" aria-label="Menu" icon="mdi-dots-vertical"
v-bind="props"></v-btn>
</template>
<v-list>
<v-list-item title="Close" aria-label="Close" icon="mdi-close"
@click="files = []; selectedItem = '/'; selectedList = []; filesGridList = []; filesList = []; history.reset()">
<template v-slot:prepend>
<v-icon icon="mdi-close"></v-icon>
</template>
</v-list-item>
</v-list>
</v-menu>
2023-05-29 19:51:08 +03:00
</v-col>
</v-row>
2023-05-15 03:32:16 +03:00
</v-toolbar>
<template v-if="fileManager.getFile(selectedItem)?.isFolder || false">
2023-05-15 03:32:16 +03:00
<v-container>
<v-list :selected="[selectedItem]">
<v-row no-gutters>
2023-05-18 23:54:37 +03:00
<v-col cols="6" lg="2" md="3" sm="6" v-for="file of filesGridList" style="text-align: center;">
2023-05-29 19:51:08 +03:00
<v-list-item class="ma-2 pa-5 selectable" active-color="light-blue-darken-4" :value="file.path" rounded
@click="selectedItem = file.path">
2023-05-15 03:32:16 +03:00
<v-avatar class="mb-2" :color="file.isFolder ? 'light-blue-accent-4' : 'blue-grey-darken-1'">
<v-icon color="white">{{ file.isFolder ? 'mdi-folder' : 'mdi-file' }}</v-icon>
</v-avatar>
<p>{{ file.name }}</p>
</v-list-item>
</v-col>
</v-row>
</v-list>
</v-container>
</template>
2023-05-29 19:51:08 +03:00
2023-05-15 03:32:16 +03:00
<VueSelecto :selectableTargets="['.selectable']" :dragContainer="dragContainer" :hitRate="20"
:selectFromInside="false" :toggleContinueSelect="'ctrl'" @select="onSelectStart" @selectStart="onSelectStart"
:get-element-rect="getElementInfo" @selectEnd="onSelectEnd" :select-by-click="false" />
2023-05-29 19:51:08 +03:00
<template v-if="!files.length">
<!-- tutorial drag and drop zipped file here and review it securely -->
<v-container fill-height fluid>
<v-row align="center" justify="center">
2023-05-19 00:07:04 +03:00
<v-col cols="12">
<v-card variant="flat" class="mx-auto" max-width="768">
<!-- v-icon for file -->
<v-icon class="mx-auto" size="100">mdi-file</v-icon>
2023-05-19 00:07:04 +03:00
<v-card-title>Drag and Drop Compressed Files</v-card-title>
<v-card-text class="font-weight-bold">
Extract and Explore compressed files online and securely.
<p class="text-subtitle-2 font-weight-regular text-medium-emphasis">
2023-05-30 04:01:16 +03:00
<v-icon class="mx-auto" size="1em" color="#007B4F">mdi-shield</v-icon> <strong>nothing</strong> leave
your browser
</p>
</v-card-text>
2023-05-19 00:07:04 +03:00
<!-- file input -->
2023-05-29 19:51:08 +03:00
<v-file-input class="mx-5" v-model="files" accept=".zip,.7z,.rar,.tar.bz2,.tar.gz,.tar.xz"
label="or select a file..." variant="outlined"></v-file-input>
</v-card>
</v-col>
</v-row>
2023-05-29 19:51:08 +03:00
</v-container>
</template>
2023-05-15 03:32:16 +03:00
</v-main>
2023-05-29 19:51:08 +03:00
<v-dialog v-model="loadingModel" persistent width="auto">
2023-05-19 18:09:48 +03:00
<v-card>
<v-card-text>
Please stand by
2023-05-29 19:51:08 +03:00
<v-progress-linear indeterminate color="light-blue-darken-1" class="mb-0"></v-progress-linear>
2023-05-19 18:09:48 +03:00
</v-card-text>
</v-card>
</v-dialog>
2023-05-15 03:32:16 +03:00
</v-layout>
</template>
<style>
.v-list-item {
border: 2px solid transparent;
}
.selected {
background: rgba(48, 150, 243, 0.1);
2023-05-15 03:32:16 +03:00
}
</style>