Initial commit

This commit is contained in:
root
2025-12-21 09:57:09 -05:00
committed by Sebastian Krupinski
commit 8ac20d8b45
38 changed files with 4677 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
<script setup lang="ts">
import { computed } from 'vue'
import { FileCollectionObject } from '@FileManager/models/collection'
import { FileEntityObject } from '@FileManager/models/entity'
import { getFileIcon, formatSize } from '@/utils/fileHelpers'
import { FileActionsMenu } from '@/components'
type ItemWithType = {
item: FileCollectionObject | FileEntityObject
type: 'collection' | 'entity'
}
const props = defineProps<{
collections: FileCollectionObject[]
entities: FileEntityObject[]
selectedIds: Set<string>
}>()
const emit = defineEmits<{
'item-click': [item: FileCollectionObject | FileEntityObject, event: MouseEvent | KeyboardEvent]
'rename': [item: FileCollectionObject | FileEntityObject]
'delete': [item: FileCollectionObject | FileEntityObject]
'download': [item: FileCollectionObject | FileEntityObject]
'show-details': [item: FileCollectionObject | FileEntityObject]
}>()
// Combine collections and entities into a single list for virtual scrolling
const allItems = computed<ItemWithType[]>(() => [
...props.collections.map(c => ({ item: c, type: 'collection' as const })),
...props.entities.map(e => ({ item: e, type: 'entity' as const }))
])
function isCollection(wrapped: ItemWithType): wrapped is { item: FileCollectionObject; type: 'collection' } {
return wrapped.type === 'collection'
}
</script>
<template>
<v-virtual-scroll
:items="allItems"
:item-height="56"
class="files-list-virtual pa-2"
>
<template #default="{ item: wrapped }">
<!-- Folder -->
<v-list-item
v-if="isCollection(wrapped)"
:active="selectedIds.has(wrapped.item.id)"
@click="($event: MouseEvent | KeyboardEvent) => emit('item-click', wrapped.item, $event)"
>
<template #prepend>
<v-icon color="amber-darken-2">mdi-folder</v-icon>
</template>
<v-list-item-title>{{ wrapped.item.label }}</v-list-item-title>
<template #append>
<FileActionsMenu
:item="wrapped.item"
@rename="emit('rename', $event)"
@delete="emit('delete', $event)"
@download="emit('download', $event)"
@show-details="emit('show-details', $event)"
/>
</template>
</v-list-item>
<!-- File -->
<v-list-item
v-else
:active="selectedIds.has(wrapped.item.id)"
@click="($event: MouseEvent | KeyboardEvent) => emit('item-click', wrapped.item, $event)"
>
<template #prepend>
<v-icon color="grey">{{ getFileIcon(wrapped.item as FileEntityObject) }}</v-icon>
</template>
<v-list-item-title>{{ wrapped.item.label }}</v-list-item-title>
<v-list-item-subtitle>{{ formatSize((wrapped.item as FileEntityObject).size) }}</v-list-item-subtitle>
<template #append>
<FileActionsMenu
:item="wrapped.item"
@rename="emit('rename', $event)"
@delete="emit('delete', $event)"
@download="emit('download', $event)"
@show-details="emit('show-details', $event)"
/>
</template>
</v-list-item>
</template>
</v-virtual-scroll>
</template>
<style scoped>
.files-list-virtual {
height: 100%;
}
</style>