mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
feat(client): add shift-click selection to book dock
Allow users to select a range of files in the book dock by holding the shift key while clicking checkboxes, matching standard multi-select behavior. Closes #136
This commit is contained in:
@@ -37,13 +37,17 @@ const props = withDefaults(
|
||||
},
|
||||
)
|
||||
|
||||
defineEmits<{
|
||||
select: [number]
|
||||
const emit = defineEmits<{
|
||||
select: [number, boolean]
|
||||
selectAll: []
|
||||
open: [BookDockFile]
|
||||
applyFetched: [number]
|
||||
}>()
|
||||
|
||||
function onCheckboxClick(event: MouseEvent, id: number) {
|
||||
emit('select', id, event.shiftKey)
|
||||
}
|
||||
|
||||
function backendCoverUrl(file: BookDockFile): string {
|
||||
return `/api/v1/book-dock/files/${file.id}/cover?v=${new Date(file.updatedAt).getTime()}`
|
||||
}
|
||||
@@ -234,8 +238,7 @@ function targetSummary(file: BookDockFile): string {
|
||||
type="checkbox"
|
||||
:checked="isSelected(file.id)"
|
||||
class="size-3.5 rounded border-input accent-primary shrink-0 self-center"
|
||||
@click.stop
|
||||
@change.stop="$emit('select', file.id)"
|
||||
@click.stop="onCheckboxClick($event, file.id)"
|
||||
/>
|
||||
|
||||
<HoverCardRoot :open-delay="250" :close-delay="100">
|
||||
|
||||
@@ -23,6 +23,7 @@ export function useBookDockFiles() {
|
||||
const selectedIds = ref<Set<number>>(new Set())
|
||||
const selectAll = ref(false)
|
||||
const excludedIds = ref<Set<number>>(new Set())
|
||||
const lastToggledId = ref<number | null>(null)
|
||||
let fetchReqSeq = 0
|
||||
|
||||
const pageCount = computed(() => Math.ceil(total.value / filters.limit) || 1)
|
||||
@@ -85,16 +86,37 @@ export function useBookDockFiles() {
|
||||
fetchFiles()
|
||||
}
|
||||
|
||||
function toggleSelect(id: number) {
|
||||
function setSelected(id: number, selected: boolean) {
|
||||
if (selectAll.value) {
|
||||
if (excludedIds.value.has(id)) excludedIds.value.delete(id)
|
||||
if (selected) excludedIds.value.delete(id)
|
||||
else excludedIds.value.add(id)
|
||||
} else {
|
||||
if (selectedIds.value.has(id)) selectedIds.value.delete(id)
|
||||
else selectedIds.value.add(id)
|
||||
if (selected) selectedIds.value.add(id)
|
||||
else selectedIds.value.delete(id)
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSelect(id: number, options: { range?: boolean } = {}) {
|
||||
const willBeSelected = !isSelected(id)
|
||||
|
||||
if (options.range && lastToggledId.value !== null && lastToggledId.value !== id) {
|
||||
const anchorIdx = items.value.findIndex((f) => f.id === lastToggledId.value)
|
||||
const targetIdx = items.value.findIndex((f) => f.id === id)
|
||||
if (anchorIdx !== -1 && targetIdx !== -1) {
|
||||
const [start, end] = anchorIdx < targetIdx ? [anchorIdx, targetIdx] : [targetIdx, anchorIdx]
|
||||
for (let i = start; i <= end; i++) {
|
||||
const item = items.value[i]
|
||||
if (item) setSelected(item.id, willBeSelected)
|
||||
}
|
||||
lastToggledId.value = id
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
setSelected(id, willBeSelected)
|
||||
lastToggledId.value = id
|
||||
}
|
||||
|
||||
function toggleSelectAll() {
|
||||
if (selectAll.value) {
|
||||
selectAll.value = false
|
||||
@@ -111,6 +133,7 @@ export function useBookDockFiles() {
|
||||
selectAll.value = false
|
||||
selectedIds.value.clear()
|
||||
excludedIds.value.clear()
|
||||
lastToggledId.value = null
|
||||
}
|
||||
|
||||
function isSelected(id: number): boolean {
|
||||
|
||||
@@ -84,6 +84,10 @@ function openSheet(file: BookDockFile) {
|
||||
selectedFile.value = file
|
||||
}
|
||||
|
||||
function handleSelect(id: number, shiftKey: boolean) {
|
||||
toggleSelect(id, { range: shiftKey })
|
||||
}
|
||||
|
||||
function closeSheet() {
|
||||
selectedFile.value = null
|
||||
}
|
||||
@@ -469,7 +473,7 @@ onUnmounted(() => {
|
||||
:select-all="selectAll"
|
||||
:name-preview-by-file-id="namePreviewByFileId"
|
||||
:empty-message="emptyMessage"
|
||||
@select="toggleSelect"
|
||||
@select="handleSelect"
|
||||
@select-all="toggleSelectAll"
|
||||
@open="openSheet"
|
||||
@apply-fetched="handleInlineApplyFetched"
|
||||
|
||||
Reference in New Issue
Block a user