mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 11:15:41 +02:00
fix(frontend): resolve detail entry for any remaining child after ctrl-deselect
Add entryCacheRef (uid→entry Map) populated on every row click. When ctrl/meta-deselecting leaves exactly one other entry selected, look up the remaining UID in the cache before falling back to the root entries array. Without this, deselecting from a multi-selection where the remaining entry is a child row left selectedEntry null (auto-snap only searches root entries).
This commit is contained in:
parent
03406099de
commit
74d3b0b3be
3 changed files with 30 additions and 16 deletions
File diff suppressed because one or more lines are too long
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Archivr</title>
|
<title>Archivr</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DQR_MNv8.js"></script>
|
<script type="module" crossorigin src="/assets/index-mnEjEwmD.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-sQJOY7Hx.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-sQJOY7Hx.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,9 @@ export default function App() {
|
||||||
const pendingSearchFocus = useRef(false)
|
const pendingSearchFocus = useRef(false)
|
||||||
const firstArchiveLoad = useRef(true)
|
const firstArchiveLoad = useRef(true)
|
||||||
const lastAnchorIndexRef = useRef(null)
|
const lastAnchorIndexRef = useRef(null)
|
||||||
|
// uid → entry object cache; populated on every row click so ctrl/shift
|
||||||
|
// selections can resolve child entries that aren't in the root entries array.
|
||||||
|
const entryCacheRef = useRef(new Map())
|
||||||
|
|
||||||
const humanizeTags = currentUser?.humanize_slugs ?? false;
|
const humanizeTags = currentUser?.humanize_slugs ?? false;
|
||||||
|
|
||||||
|
|
@ -260,6 +263,10 @@ export default function App() {
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleRowClick = useCallback((entry, e) => {
|
const handleRowClick = useCallback((entry, e) => {
|
||||||
|
// Cache every clicked entry so shift/ctrl can resolve child entries
|
||||||
|
// that are not present in the root `entries` array.
|
||||||
|
entryCacheRef.current.set(entry.entry_uid, entry)
|
||||||
|
|
||||||
if (e.shiftKey && lastAnchorIndexRef.current !== null) {
|
if (e.shiftKey && lastAnchorIndexRef.current !== null) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
// Use DOM order so child rows (not in the `entries` array) participate
|
// Use DOM order so child rows (not in the `entries` array) participate
|
||||||
|
|
@ -268,7 +275,6 @@ export default function App() {
|
||||||
const anchorIdx = allNodes.findIndex(n => n.dataset.entryUid === lastAnchorIndexRef.current)
|
const anchorIdx = allNodes.findIndex(n => n.dataset.entryUid === lastAnchorIndexRef.current)
|
||||||
const clickIdx = allNodes.findIndex(n => n.dataset.entryUid === entry.entry_uid)
|
const clickIdx = allNodes.findIndex(n => n.dataset.entryUid === entry.entry_uid)
|
||||||
if (anchorIdx === -1 || clickIdx === -1) {
|
if (anchorIdx === -1 || clickIdx === -1) {
|
||||||
// anchor no longer visible — fall back to single select
|
|
||||||
lastAnchorIndexRef.current = entry.entry_uid
|
lastAnchorIndexRef.current = entry.entry_uid
|
||||||
setSelectedUids(new Set([entry.entry_uid]))
|
setSelectedUids(new Set([entry.entry_uid]))
|
||||||
selectEntry(entry)
|
selectEntry(entry)
|
||||||
|
|
@ -285,10 +291,18 @@ export default function App() {
|
||||||
if (next.has(entry.entry_uid)) next.delete(entry.entry_uid)
|
if (next.has(entry.entry_uid)) next.delete(entry.entry_uid)
|
||||||
else next.add(entry.entry_uid)
|
else next.add(entry.entry_uid)
|
||||||
setSelectedUids(next)
|
setSelectedUids(next)
|
||||||
// Auto-snap only restores root entries; explicitly drive selectEntry so
|
if (next.size === 0) {
|
||||||
// ctrl-clicking a single child row loads its detail and clears on multi.
|
selectEntry(null)
|
||||||
if (next.size === 1 && next.has(entry.entry_uid)) selectEntry(entry)
|
} else if (next.size === 1) {
|
||||||
else if (next.size !== 1) selectEntry(null)
|
// Resolve the remaining UID — may be a child not in root entries array.
|
||||||
|
const [remainingUid] = next
|
||||||
|
const cached = entryCacheRef.current.get(remainingUid)
|
||||||
|
?? entries.find(x => x.entry_uid === remainingUid)
|
||||||
|
?? null
|
||||||
|
selectEntry(cached)
|
||||||
|
} else {
|
||||||
|
selectEntry(null)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lastAnchorIndexRef.current = entry.entry_uid
|
lastAnchorIndexRef.current = entry.entry_uid
|
||||||
setSelectedUids(new Set([entry.entry_uid]))
|
setSelectedUids(new Set([entry.entry_uid]))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue