mirror of
https://github.com/45Drives/cockpit-navigator.git
synced 2025-07-28 16:14:25 +02:00
work on selection and print escaped names
This commit is contained in:
parent
1df94ae49c
commit
d9d777c431
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user