mirror of
https://github.com/lights0123/n-link.git
synced 2024-12-22 18:25:27 +00:00
75 lines
2.3 KiB
Vue
75 lines
2.3 KiB
Vue
<template>
|
|
<div class="flex flex-wrap min-h-full items-start content-start" @mousedown.exact="selected = []">
|
|
<div class="mb-2 mx-1 w-24 flex flex-col items-center cursor-default" :class="{ selected: selected.includes(i) }"
|
|
v-for="(file, i) in filteredFiles" :key="file.path" @mousedown.ctrl.stop="xorSelection(i)" @mousedown.shift.stop="shiftSelection(i)"
|
|
@mousedown.exact.stop="selected = [i]"
|
|
@dblclick="file.isDir && $emit('nav', file.path)">
|
|
<file-icon :path="file.path" :dir="file.isDir"/>
|
|
<p class="mt-1 text-sm w-full text-center select-none break-words">{{ formatPath(file) }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import {Component, Prop, Vue, Watch} from 'vue-property-decorator';
|
|
import type {FileInfo} from './devices';
|
|
import FileIcon from "./FileIcon.vue";
|
|
|
|
@Component({
|
|
components: {FileIcon}
|
|
})
|
|
export default class FileView extends Vue {
|
|
@Prop({type: Array, default: () => ([])}) private files!: FileInfo[];
|
|
@Prop({type: Boolean, default: false}) private showHidden!: boolean;
|
|
selected: number[] = [];
|
|
|
|
@Watch('selected', {deep: true, immediate: true})
|
|
onSelect(selected: number[]) {
|
|
this.$emit('select', selected.map(file => this.filteredFiles[file]));
|
|
}
|
|
|
|
@Watch('files')
|
|
onFileChange() {
|
|
this.selected = [];
|
|
}
|
|
|
|
get filteredFiles() {
|
|
if (this.showHidden) return this.files;
|
|
return this.files.filter(file => file.isDir || file.path.endsWith('.tns'));
|
|
}
|
|
|
|
formatPath({path, isDir}: FileInfo) {
|
|
const name = path.split('/').pop() as string;
|
|
if (this.showHidden || isDir) return name;
|
|
return name.substring(0, name.length - 4);
|
|
}
|
|
|
|
xorSelection(i: number) {
|
|
if (this.selected.includes(i)) this.selected = this.selected.filter(num => num !== i);
|
|
else this.selected.push(i);
|
|
}
|
|
|
|
shiftSelection(item: number) {
|
|
const lastSelected = this.selected[this.selected.length-1];
|
|
if(lastSelected === undefined) {
|
|
this.selected.push(item);
|
|
return;
|
|
}
|
|
const [lower, upper] = item > lastSelected ? [lastSelected, item] : [item, lastSelected];
|
|
for(let i = lower; i <= upper; i++) {
|
|
if (!this.selected.includes(i))this.selected.push(i);
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.selected {
|
|
background-color: #4d88e8;
|
|
@apply rounded;
|
|
p {
|
|
@apply text-white;
|
|
}
|
|
}
|
|
</style>
|