mirror of
https://github.com/xlmnxp/extractify.zip.git
synced 2024-11-23 17:13:12 +03:00
move folders to folders view; fix some bugs
This commit is contained in:
parent
dac3982370
commit
249cc552ec
74
app.vue
74
app.vue
@ -1,6 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getElementInfo } from "moveable";
|
|
||||||
import { VueSelecto } from "vue3-selecto";
|
|
||||||
import { useDisplay } from 'vuetify/lib/framework.mjs';
|
import { useDisplay } from 'vuetify/lib/framework.mjs';
|
||||||
import { HistoryManager } from './composables/history-manager';
|
import { HistoryManager } from './composables/history-manager';
|
||||||
import { FilesManager, supportedExtensions, imageExtensions } from './composables/files-manager';
|
import { FilesManager, supportedExtensions, imageExtensions } from './composables/files-manager';
|
||||||
@ -66,44 +64,13 @@ watchEffect(async () => {
|
|||||||
const file = filesManager.getFile(selectedPath.value);
|
const file = filesManager.getFile(selectedPath.value);
|
||||||
filesGridList.value = file?.content;
|
filesGridList.value = file?.content;
|
||||||
|
|
||||||
console.log("Selected file", file);
|
|
||||||
|
|
||||||
selectedList.value = [];
|
|
||||||
for (const selectedElement of document.querySelectorAll(".selectable.selected")) {
|
|
||||||
selectedElement.classList.remove("selected");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update to handle both video and image files
|
// Update to handle both video and image files
|
||||||
if (videoExtensions.includes(filesManager.getFile(selectedPath.value)?.extension?.toLowerCase()) ||
|
if (videoExtensions.includes(filesManager.getFile(selectedPath.value)?.extension?.toLowerCase()) ||
|
||||||
imageExtensions.includes(filesManager.getFile(selectedPath.value)?.extension?.toLowerCase())) {
|
imageExtensions.includes(filesManager.getFile(selectedPath.value)?.extension?.toLowerCase())) {
|
||||||
mediaBlobUrl.value = await filesManager.getFileBlobUrl(selectedPath.value) as string;
|
mediaBlobUrl.value = await filesManager.getFileBlobUrl(selectedPath.value) as string;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const dragContainer = document.querySelector(".select-area");
|
|
||||||
|
|
||||||
function onSelectStart(e: any) {
|
|
||||||
e.added.forEach((el: any) => {
|
|
||||||
el.classList.add("selected");
|
|
||||||
selectedList.value = [...selectedList.value, el?.__vnode?.ctx?.props?.value];
|
|
||||||
});
|
|
||||||
e.removed.forEach((el: any) => {
|
|
||||||
el.classList.remove("selected");
|
|
||||||
selectedList.value = selectedList.value.filter((value: string) => value != el?.__vnode?.ctx?.props?.value)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSelectEnd(e: any) {
|
|
||||||
e.afterAdded.forEach((el: any) => {
|
|
||||||
el.classList.add("selected");
|
|
||||||
selectedList.value = [...selectedList.value, el?.__vnode?.ctx?.props?.value];
|
|
||||||
});
|
|
||||||
e.afterRemoved.forEach((el: any) => {
|
|
||||||
el.classList.remove("selected");
|
|
||||||
selectedList.value = selectedList.value.filter((value: string) => value != el?.__vnode?.ctx?.props?.value)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// step up from current path
|
// step up from current path
|
||||||
function stepUp(path: string) {
|
function stepUp(path: string) {
|
||||||
const pathArray = path.split("/");
|
const pathArray = path.split("/");
|
||||||
@ -135,9 +102,8 @@ function stepUp(path: string) {
|
|||||||
</div>
|
</div>
|
||||||
</v-footer>
|
</v-footer>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
<v-main class="select-area" style="height: 100dvh;">
|
<v-main style="height: 100dvh;">
|
||||||
<v-toolbar class="px-5" height="auto">
|
<v-toolbar class="px-5" height="auto">
|
||||||
|
|
||||||
<v-row align="center" justify="center">
|
<v-row align="center" justify="center">
|
||||||
<v-col cols="12" lg="2" md="12" style="display: inline-flex;">
|
<v-col cols="12" lg="2" md="12" style="display: inline-flex;">
|
||||||
<v-btn title="Back" aria-label="Back" icon="mdi-arrow-left" :disabled="!history.hasUndo.value"
|
<v-btn title="Back" aria-label="Back" icon="mdi-arrow-left" :disabled="!history.hasUndo.value"
|
||||||
@ -173,32 +139,7 @@ function stepUp(path: string) {
|
|||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
<v-container>
|
<v-container>
|
||||||
<template v-if="filesManager.getFile(selectedPath)?.isFolder">
|
<template v-if="filesManager.getFile(selectedPath)?.isFolder">
|
||||||
<v-list :selected="[selectedPath]" style="height: calc(100vh - 120px);">
|
<FolderViewer :filesManager="filesManager" :filesGridList="filesGridList" :selectedList="selectedList"></FolderViewer>
|
||||||
<v-row no-gutters>
|
|
||||||
<v-col cols="6" lg="2" md="3" sm="6" v-for="file of filesGridList" style="text-align: center;">
|
|
||||||
<v-list-item class="position-relative ma-2 pa-5 selectable" active-color="light-blue-darken-4"
|
|
||||||
:value="file.path" rounded @click="selectedPath = file.path">
|
|
||||||
<v-menu v-if="!file.isFolder">
|
|
||||||
<template v-slot:activator="{ props }">
|
|
||||||
<v-btn class="position-absolute" style="right: 0; top: 0;" icon="mdi-dots-vertical" variant="text"
|
|
||||||
v-bind="props"></v-btn>
|
|
||||||
</template>
|
|
||||||
<v-list>
|
|
||||||
<v-list-item title="Download" aria-label="Download" icon="mdi-download"
|
|
||||||
@click="filesManager.downloadFile(file.path)">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<v-icon icon="mdi-download"></v-icon>
|
|
||||||
</template>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-menu>
|
|
||||||
|
|
||||||
<file-logo class="mb-2" :file="file" :key="file.path" />
|
|
||||||
<p>{{ file.name }}</p>
|
|
||||||
</v-list-item>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-list>
|
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template
|
||||||
v-if="!filesManager.getFile(selectedPath)?.isFolder && videoExtensions.includes(filesManager.getFile(selectedPath)?.extension)">
|
v-if="!filesManager.getFile(selectedPath)?.isFolder && videoExtensions.includes(filesManager.getFile(selectedPath)?.extension)">
|
||||||
@ -234,17 +175,14 @@ function stepUp(path: string) {
|
|||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<!-- file input -->
|
<!-- file input -->
|
||||||
<v-file-input class="mx-5" v-model="files" :accept="supportedExtensions.map(extension => `.${extension}`).join(',')"
|
<v-file-input class="mx-5" v-model="files"
|
||||||
label="or select a file..." variant="outlined"></v-file-input>
|
:accept="supportedExtensions.map(extension => `.${extension}`).join(',')" label="or select a file..."
|
||||||
|
variant="outlined"></v-file-input>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</template>
|
</template>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
<VueSelecto :selectableTargets="['.selectable']" :dragContainer="dragContainer" :hitRate="0"
|
|
||||||
:selectFromInside="false" :toggleContinueSelect="'ctrl'" @select="onSelectStart" @selectStart="onSelectStart"
|
|
||||||
:get-element-rect="getElementInfo" @selectEnd="onSelectEnd" :select-by-click="false" />
|
|
||||||
</v-main>
|
</v-main>
|
||||||
<v-dialog v-model="loadingModel" persistent width="auto">
|
<v-dialog v-model="loadingModel" persistent width="auto">
|
||||||
<v-card>
|
<v-card>
|
||||||
|
79
components/folder-viewer.vue
Normal file
79
components/folder-viewer.vue
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { getElementInfo } from "moveable";
|
||||||
|
import { VueSelecto } from "vue3-selecto";
|
||||||
|
import { FilesManager } from '~/composables/files-manager';
|
||||||
|
import { iFile } from '~/composables/worker/7zip-manager';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
filesManager: FilesManager;
|
||||||
|
filesGridList: iFile[];
|
||||||
|
selectedList: Ref<string[]>
|
||||||
|
};
|
||||||
|
|
||||||
|
const { filesManager, filesGridList, selectedList } = defineProps<Props>();
|
||||||
|
|
||||||
|
const selectedPath = useSelectedPath();
|
||||||
|
|
||||||
|
const dragContainer = document.querySelector(".select-area");
|
||||||
|
|
||||||
|
function onSelectStart(e: any) {
|
||||||
|
e.added.forEach((el: any) => {
|
||||||
|
el.classList.add("selected");
|
||||||
|
selectedList.value = [...selectedList.value, el?.__vnode?.ctx?.props?.value];
|
||||||
|
});
|
||||||
|
e.removed.forEach((el: any) => {
|
||||||
|
el.classList.remove("selected");
|
||||||
|
selectedList.value = selectedList.value.filter((value: string) => value != el?.__vnode?.ctx?.props?.value)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSelectEnd(e: any) {
|
||||||
|
e.afterAdded.forEach((el: any) => {
|
||||||
|
el.classList.add("selected");
|
||||||
|
selectedList.value = [...selectedList.value, el?.__vnode?.ctx?.props?.value];
|
||||||
|
});
|
||||||
|
e.afterRemoved.forEach((el: any) => {
|
||||||
|
el.classList.remove("selected");
|
||||||
|
selectedList.value = selectedList.value.filter((value: string) => value != el?.__vnode?.ctx?.props?.value)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
selectedList.value = [];
|
||||||
|
for (const selectedElement of document.querySelectorAll(".selectable.selected")) {
|
||||||
|
selectedElement.classList.remove("selected");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-list class="select-area" :selected="[selectedPath]" style="height: calc(100vh - 120px);">
|
||||||
|
<v-row no-gutters>
|
||||||
|
<v-col cols="6" lg="2" md="3" sm="6" v-for="file of filesGridList" style="text-align: center;">
|
||||||
|
<v-list-item class="position-relative ma-2 pa-5 selectable" active-color="light-blue-darken-4"
|
||||||
|
:value="file.path" rounded @click="selectedPath = file.path">
|
||||||
|
<v-menu v-if="!file.isFolder">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn class="position-absolute" style="right: 0; top: 0;" icon="mdi-dots-vertical"
|
||||||
|
variant="text" v-bind="props"></v-btn>
|
||||||
|
</template>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item title="Download" aria-label="Download" icon="mdi-download"
|
||||||
|
@click="filesManager.downloadFile(file.path)">
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<v-icon icon="mdi-download"></v-icon>
|
||||||
|
</template>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
|
|
||||||
|
<file-logo class="mb-2" :file="file" :key="file.path" />
|
||||||
|
<p>{{ file.name }}</p>
|
||||||
|
</v-list-item>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<VueSelecto :selectableTargets="['.selectable']" :dragContainer="dragContainer" :hitRate="0"
|
||||||
|
:selectFromInside="false" :toggleContinueSelect="'ctrl'" @select="onSelectStart" @selectStart="onSelectStart"
|
||||||
|
:get-element-rect="getElementInfo" @selectEnd="onSelectEnd" :select-by-click="false" />
|
||||||
|
</v-list>
|
||||||
|
</template>
|
@ -1,4 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
src: string;
|
src: string;
|
||||||
}>();
|
}>();
|
@ -2,7 +2,6 @@
|
|||||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
|
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { FilesManager } from '~/composables/files-manager';
|
import { FilesManager } from '~/composables/files-manager';
|
||||||
// @ts-ignore
|
|
||||||
import { iFile } from '~/composables/worker/7zip-manager';
|
import { iFile } from '~/composables/worker/7zip-manager';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -18,6 +17,7 @@ let { file, filesManager } = defineProps<Props>()
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const darkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
|
const darkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
|
|
||||||
|
if(!file) return;
|
||||||
let fileContent = await filesManager.getFileContent(file.path);
|
let fileContent = await filesManager.getFileContent(file.path);
|
||||||
monaco.editor.create(editor.value, {
|
monaco.editor.create(editor.value, {
|
||||||
value: fileContent?.toString()!,
|
value: fileContent?.toString()!,
|
||||||
|
@ -166,9 +166,10 @@ export class SevenZipManager {
|
|||||||
async getFileContent(file: iFile, encoding: "utf8" | "binary" = "utf8") {
|
async getFileContent(file: iFile, encoding: "utf8" | "binary" = "utf8") {
|
||||||
if (!this.sevenZip) return;
|
if (!this.sevenZip) return;
|
||||||
file = typeof file === "string" ? JSON.parse(file) : file;
|
file = typeof file === "string" ? JSON.parse(file) : file;
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
// extract file from archive
|
// extract file from archive
|
||||||
this.execute(['x', '-y', this.archiveName, file.path.substring(1)]);
|
this.execute(['x', '-y', this.archiveName, file?.path.substring(1)]);
|
||||||
this.sevenZip.FS.chmod(file.path, 0o777);
|
this.sevenZip.FS.chmod(file.path, 0o777);
|
||||||
|
|
||||||
// get file buffer
|
// get file buffer
|
||||||
|
Loading…
Reference in New Issue
Block a user