Files
battle-caster-v1/src/components/FileManager/FileManager.vue

147 lines
3.2 KiB
Vue

<template>
<div class="file-manager">
<div class="file-manager__toolbar">
<input class="file-manager__search" type="search" placeholder="search" v-model="search">
<button
@click="buildIndex"
:disabled="buildingIndex"
>
<template v-if="buildingIndex">building {{ indexCounter }}</template>
<template v-else>Build Index</template>
</button>
</div>
<div class="file-manager__files">
<ul
v-if="searchResults.length > 0"
class="file-manager-dir"
>
<FileManagerFile
v-for="file in searchResults"
:key="file.name"
:file="file"
@openFile="$emit('openFile', $event)"
@filePreview="onFilePreview"
/>
</ul>
<ul
v-else
class="file-manager-dir"
>
<FileManagerDir
v-for="dir in fs.root"
:key="dir.name"
:fs="fs"
:dir="dir"
@openFile="$emit('openFile', $event)"
@filePreview="onFilePreview"
/>
</ul>
</div>
<div class="file-manager__preview">
<FilePreview :file="filePreview" />
</div>
</div>
</template>
<script setup lang="ts">
import {inject, ref, watch} from 'vue';
import {MountedFsSymbol} from '../../model/injectionSymbols';
import FileManagerDir from './FileManagerDir.vue';
import {VirtualFile} from '../../model/FileSystem/types';
import FileManagerFile from './FileManagerFile.vue';
import FilePreview from './FilePreview.vue';
const fs = inject(MountedFsSymbol)!;
const emit = defineEmits<{
'openFile': [value: VirtualFile]
'filePreview': [value: VirtualFile]
}>();
const search = ref('');
let searchAbort: AbortController;
const searchResults = ref<VirtualFile[]>([]);
const filePreview = ref<VirtualFile>();
function onFilePreview(file: VirtualFile) {
filePreview.value = file;
emit('filePreview', file)
}
watch(search, async (value) => {
searchResults.value = [];
if (value.length < 3) {
return;
}
if (searchAbort) {
searchAbort.abort();
}
searchAbort = new AbortController();
let numberOfResults = 0;
for await (let result of fs.search(value, searchAbort.signal)) {
searchResults.value.push(result);
if (numberOfResults++ > 100) {
break;
}
}
});
const buildingIndex = ref(false);
const indexCounter = ref(0);
async function buildIndex() {
buildingIndex.value = true;
for await(let counter of fs.buildIndex()) {
indexCounter.value = counter;
}
}
</script>
<style>
.file-manager {
display: grid;
height: 100%;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr auto;
gap: 0.5rem;
padding: 0.5rem 0.25rem;
}
.file-manager__search {
flex: 1;
border-radius: 4px;
border:none;
padding: 2px 8px;
}
.file-manager__toolbar {
padding: 4px;
display: flex;
flex-direction: row;
grid-gap: 4px;
}
.file-manager-dir {
list-style-type: none;
padding-left: 1rem;
}
.file-manager__files {
overflow: auto;
}
.file-manager-dir__label {
cursor: pointer;
}
.file-manager-dir__label::before {
content: '📁';
margin-right: 0.5rem;
display: inline-block;
}
.file-manager-dir__label--open::before {
content: '📂';
}
</style>