work on selection and print escaped names

This commit is contained in:
joshuaboud 2022-05-25 16:12:15 -03:00
parent 1df94ae49c
commit d9d777c431
No known key found for this signature in database
GPG Key ID: 17EFB59E2A8BF50E

View File

@ -3,42 +3,58 @@
<tr <tr
v-show="show || showEntries" v-show="show || showEntries"
@dblclick.stop="doubleClickCallback" @dblclick.stop="doubleClickCallback"
@click.stop="$emit('toggleSelected')" @click.stop.prevent="$emit('toggleSelected', { ctrlKey: $event.ctrlKey, shiftKey: $event.shiftKey })"
:class="['hover:!bg-red-600/10']" :class="['hover:!bg-red-600/10 select-none']"
v-bind="$attrs"
> >
<td class="flex items-center gap-1 !pl-1"> <td :class="['!pl-1', ...selectedClasses]">
<div :style="{ width: `${24 * level}px` }"></div> <div :class="['flex items-center gap-1']">
<div class="relative w-6"> <div :style="{ width: `${24 * level}px` }"></div>
<component :is="icon" class="size-icon icon-default" /> <div class="relative w-6">
<LinkIcon <component :is="icon" class="size-icon icon-default" />
v-if="entry.type === 'symbolic link'" <LinkIcon
class="w-2 h-2 absolute right-0 bottom-0 text-default" v-if="entry.type === 'symbolic link'"
/> class="w-2 h-2 absolute right-0 bottom-0 text-default"
</div>
<button v-if="directoryLike" @click.stop="toggleShowEntries">
<ChevronDownIcon v-if="!showEntries" class="size-icon icon-default" />
<ChevronUpIcon v-else class="size-icon icon-default" />
</button>
<div>{{ entry.name }}</div>
<div v-if="entry.type === 'symbolic link'" class="inline-flex gap-1 items-center">
<div class="inline relative">
<ArrowNarrowRightIcon class="text-default size-icon-sm inline" />
<XIcon
v-if="entry.target?.broken"
class="icon-danger size-icon-sm absolute inset-x-0 bottom-0"
/> />
</div> </div>
<div>{{ entry.target?.rawPath ?? '' }}</div> <button v-if="directoryLike" @click.stop="toggleShowEntries">
<ChevronDownIcon v-if="!showEntries" class="size-icon icon-default" />
<ChevronUpIcon v-else class="size-icon icon-default" />
</button>
<div v-html="escapeName(entry.name)"></div>
<div v-if="entry.type === 'symbolic link'" class="inline-flex gap-1 items-center">
<div class="inline relative">
<ArrowNarrowRightIcon class="text-default size-icon-sm inline" />
<XIcon
v-if="entry.target?.broken"
class="icon-danger size-icon-sm absolute inset-x-0 bottom-0"
/>
</div>
<div v-html="escapeName(entry.target?.rawPath ?? '')"></div>
</div>
</div> </div>
</td> </td>
<td v-if="settings?.directoryView?.cols?.mode" class="font-mono">{{ entry.modeStr }}</td> <td
<td v-if="settings?.directoryView?.cols?.owner">{{ entry.owner }}</td> v-if="settings?.directoryView?.cols?.mode"
<td v-if="settings?.directoryView?.cols?.group">{{ entry.group }}</td> :class="['font-mono', ...(selectedClasses)]"
<td v-if="settings?.directoryView?.cols?.size" class="font-mono text-right">{{ entry.sizeHuman }}</td> >{{ entry.modeStr }}</td>
<td v-if="settings?.directoryView?.cols?.ctime">{{ entry.ctime?.toLocaleString() ?? '-' }}</td> <td v-if="settings?.directoryView?.cols?.owner" :class="selectedClasses">{{ entry.owner }}</td>
<td v-if="settings?.directoryView?.cols?.mtime">{{ entry.mtime?.toLocaleString() ?? '-' }}</td> <td v-if="settings?.directoryView?.cols?.group" :class="selectedClasses">{{ entry.group }}</td>
<td v-if="settings?.directoryView?.cols?.atime">{{ entry.atime?.toLocaleString() ?? '-' }}</td> <td
v-if="settings?.directoryView?.cols?.size"
:class="['font-mono text-right', ...(selectedClasses)]"
>{{ entry.sizeHuman }}</td>
<td
v-if="settings?.directoryView?.cols?.ctime"
:class="selectedClasses"
>{{ entry.ctime?.toLocaleString() ?? '-' }}</td>
<td
v-if="settings?.directoryView?.cols?.mtime"
:class="selectedClasses"
>{{ entry.mtime?.toLocaleString() ?? '-' }}</td>
<td
v-if="settings?.directoryView?.cols?.atime"
:class="selectedClasses"
>{{ entry.atime?.toLocaleString() ?? '-' }}</td>
</tr> </tr>
<component <component
:show="show || showEntries" :show="show || showEntries"
@ -53,6 +69,7 @@
@startProcessing="(...args) => $emit('startProcessing', ...args)" @startProcessing="(...args) => $emit('startProcessing', ...args)"
@stopProcessing="(...args) => $emit('stopProcessing', ...args)" @stopProcessing="(...args) => $emit('stopProcessing', ...args)"
@cancelShowEntries="showEntries = false" @cancelShowEntries="showEntries = false"
@deselectAll="$emit('deselectAll')"
ref="directoryViewRef" ref="directoryViewRef"
:level="level + 1" :level="level + 1"
/> />
@ -61,22 +78,23 @@
v-else v-else
v-show="show" v-show="show"
@dblclick.stop="doubleClickCallback" @dblclick.stop="doubleClickCallback"
@click.stop="$emit('toggleSelected')" @click.stop.prevent="$emit('toggleSelected', { ctrlKey: $event.ctrlKey, shiftKey: $event.shiftKey })"
class="flex flex-col items-center w-20 overflow-hidden"
> >
<div class="relative w-20"> <div :class="[...selectedClasses, 'flex flex-col items-center w-20 overflow-hidden select-none']">
<component :is="icon" class="icon-default w-20 h-auto" /> <div class="relative w-20">
<div <component :is="icon" class="icon-default w-20 h-auto" />
:class="[directoryLike ? 'right-3 bottom-5' : 'right-5 bottom-3', 'inline absolute']" <div
:title="`-> ${entry.target?.rawPath ?? '?'}`" :class="[directoryLike ? 'right-3 bottom-5' : 'right-5 bottom-3', 'inline absolute']"
> :title="`-> ${entry.target?.rawPath ?? '?'}`"
<LinkIcon >
v-if="entry.type === 'symbolic link'" <LinkIcon
:class="[entry.target?.broken ? 'text-red-300 dark:text-red-800' : 'text-gray-100 dark:text-gray-900', 'w-4 h-auto']" v-if="entry.type === 'symbolic link'"
/> :class="[entry.target?.broken ? 'text-red-300 dark:text-red-800' : 'text-gray-100 dark:text-gray-900', 'w-4 h-auto']"
/>
</div>
</div> </div>
<div class="text-center w-full" style="overflow-wrap: break-word;">{{ entry.name }}</div>
</div> </div>
<div class="text-center w-full" style="overflow-wrap: break-word;">{{ entry.name }}</div>
</div> </div>
</template> </template>
@ -98,6 +116,7 @@ export default {
default: null, default: null,
}, },
level: Number, level: Number,
neighboursSelected: Object,
}, },
setup(props, { emit }) { setup(props, { emit }) {
const settings = inject(settingsInjectionKey); const settings = inject(settingsInjectionKey);
@ -106,6 +125,8 @@ export default {
const showEntries = ref(false); const showEntries = ref(false);
const directoryViewRef = ref(); const directoryViewRef = ref();
const selectedClasses = ref([]);
const doubleClickCallback = () => { const doubleClickCallback = () => {
if (directoryLike.value) { if (directoryLike.value) {
emit('cd', props.entry.path); emit('cd', props.entry.path);
@ -128,6 +149,16 @@ export default {
const getSelected = () => directoryViewRef.value?.getSelected?.() ?? []; const getSelected = () => directoryViewRef.value?.getSelected?.() ?? [];
const selectAll = () => {
directoryViewRef.value?.selection.selectAll();
}
const deselectAllForward = () => {
directoryViewRef.value?.selection.deselectAllForward();
}
const escapeName = (string) => string.replace(/[^ -~]/gi, c => `<span class="text-orange-500">${JSON.stringify(c).replace(/^['"]|['"]$/g, '')}</span>`)
watch(props.entry, () => { watch(props.entry, () => {
if (props.entry.type === 'directory' || (props.entry.type === 'symbolic link' && props.entry.target?.type === 'directory')) { if (props.entry.type === 'directory' || (props.entry.type === 'symbolic link' && props.entry.target?.type === 'directory')) {
icon.value = FolderIcon; icon.value = FolderIcon;
@ -138,16 +169,27 @@ export default {
} }
}, { immediate: true }); }, { immediate: true });
watch([() => props.neighboursSelected, () => props.entry.selected, () => settings.directoryView?.view], () => selectedClasses.value = [
'border-dashed border-red-600/50 first:border-l-2 last:border-r-2',
props.entry.selected ? 'bg-red-600/5 first:border-l-red-600/50 last:border-r-red-600/50' : 'first:border-l-transparent last:border-r-transparent',
props.entry.selected && (!props.neighboursSelected.above || settings.directoryView?.view !== 'list') ? 'border-t-2' : 'border-t-0',
props.entry.selected && (!props.neighboursSelected.below || settings.directoryView?.view !== 'list') ? 'border-b-2' : 'border-b-0',
], { immediate: true, deep: true });
return { return {
settings, settings,
icon, icon,
directoryLike, directoryLike,
selectedClasses,
showEntries, showEntries,
directoryViewRef, directoryViewRef,
doubleClickCallback, doubleClickCallback,
getEntries, getEntries,
toggleShowEntries, toggleShowEntries,
getSelected, getSelected,
selectAll,
deselectAllForward,
escapeName,
DirectoryEntryList, DirectoryEntryList,
nextTick, nextTick,
} }
@ -169,6 +211,7 @@ export default {
'toggleSelected', 'toggleSelected',
'startProcessing', 'startProcessing',
'stopProcessing', 'stopProcessing',
'deselectAll',
] ]
} }
</script> </script>