Skip to content

Commit 470078a

Browse files
committed
Sorting optimizations fix
1 parent 836b737 commit 470078a

2 files changed

Lines changed: 34 additions & 63 deletions

File tree

resources/logic_pipeline.js

Lines changed: 20 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,20 @@
77
const ASYNC_PIPELINE_THRESHOLD = 500;
88

99
// RESTORED: Helper to update index map
10-
// OPTIMIZED: Avoid creating a full sorted copy for large datasets
10+
// Maps each item's ID to its sequential position (1-based) when sorted by ID.
11+
// This provides a stable "original order" number for each card regardless of
12+
// current sort/filter, used for "Go To Card #" and the #N tag on cards.
1113
function refreshIndices() {
1214
if (!activeData) return;
13-
14-
if (activeData.length > ASYNC_PIPELINE_THRESHOLD) {
15-
// For large datasets, build the map by finding min ID and computing offsets
16-
// Since IDs are sequential integers, we can avoid sorting entirely
17-
let minId = Infinity;
18-
for (let i = 0; i < activeData.length; i++) {
19-
if (activeData[i].id < minId) minId = activeData[i].id;
20-
}
21-
idToIndexMap = new Map();
22-
for (let i = 0; i < activeData.length; i++) {
23-
idToIndexMap.set(activeData[i].id, activeData[i].id - minId + 1);
24-
}
25-
} else {
26-
const sorted = activeData.slice().sort((a, b) => a.id - b.id);
27-
idToIndexMap = new Map(sorted.map((item, index) => [item.id, index + 1]));
28-
}
15+
const sorted = activeData.slice().sort((a, b) => a.id - b.id);
16+
idToIndexMap = new Map(sorted.map((item, index) => [item.id, index + 1]));
2917
}
3018

3119
// Generate cache key from current filters
3220
function getFilterKey() {
3321
const parts = [
3422
currentSort,
23+
currentSecondarySort,
3524
topFilters.showFavorites ? '1' : '0',
3625
topFilters.showNonFavorited ? '1' : '0',
3726
topFilters.showRejected ? '1' : '0',
@@ -323,48 +312,25 @@ function executePipeline() {
323312
return true;
324313
});
325314

326-
// For large datasets, use async sorting to avoid blocking the UI
327-
if (processedData.length > ASYNC_PIPELINE_THRESHOLD) {
328-
// Cancel any previous async sort
329-
const thisRunId = ++pipelineAbortId;
330-
331-
// For "oldest" and "newest" sorts, we can use a fast path since items from
332-
// activeData are already ordered by insertion (id order)
333-
if ((currentSort === 'oldest' || currentSort === 'newest') && currentSecondarySort === 'none') {
334-
// Fast path: items from activeData are already in insertion order
335-
// For oldest: a.id - b.id (natural order from activeData)
336-
// For newest: reverse
337-
if (currentSort === 'newest') {
338-
processedData.reverse();
339-
}
340-
// No expensive sort needed!
341-
} else {
342-
// Async sort: sort in a yielding fashion to keep UI responsive
343-
runMultiSort(processedData);
344-
}
345-
346-
const elapsed = (performance.now() - startTime).toFixed(1);
347-
console.log(`[Pipeline] Processed ${processedData.length} items in ${elapsed}ms (large dataset mode)`);
348-
updateJSONs(processedData);
349-
350-
if (filtersChanged) {
351-
if(typeof renderDOM === 'function') renderDOM();
352-
} else {
353-
if (typeof updateVisibleItems === 'function') updateVisibleItems();
315+
// Apply sorting
316+
// Fast path: for oldest/newest with no secondary sort, items from activeData.filter()
317+
// are already in ID order — just reverse for newest
318+
if ((currentSort === 'oldest' || currentSort === 'newest') && currentSecondarySort === 'none') {
319+
if (currentSort === 'newest') {
320+
processedData.reverse();
354321
}
355322
} else {
356-
// Small dataset: synchronous sort (fast enough)
357323
runMultiSort(processedData);
324+
}
358325

359-
const elapsed = (performance.now() - startTime).toFixed(1);
360-
console.log(`[Pipeline] Processed ${processedData.length} items in ${elapsed}ms`);
361-
updateJSONs(processedData);
326+
const elapsed = (performance.now() - startTime).toFixed(1);
327+
console.log(`[Pipeline] Processed ${processedData.length} items in ${elapsed}ms`);
328+
updateJSONs(processedData);
362329

363-
if (filtersChanged) {
364-
if(typeof renderDOM === 'function') renderDOM();
365-
} else {
366-
if (typeof updateVisibleItems === 'function') updateVisibleItems();
367-
}
330+
if (filtersChanged) {
331+
if(typeof renderDOM === 'function') renderDOM();
332+
} else {
333+
if (typeof updateVisibleItems === 'function') updateVisibleItems();
368334
}
369335
}
370336

resources/logic_virtual.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ function renderVisibleItems(forcePositionUpdate = false) {
242242

243243
itemsToShow.forEach((data, offsetIndex) => {
244244
const globalIndex = visibleRange.start + offsetIndex;
245+
const displayNumber = globalIndex + 1; // 1-based position in current sorted view
245246

246247
const row = Math.floor(globalIndex / columnsCount);
247248
const col = globalIndex % columnsCount;
@@ -258,6 +259,10 @@ function renderVisibleItems(forcePositionUpdate = false) {
258259
card.style.width = `${itemWidth - 10}px`;
259260
card.style.zIndex = globalIndex;
260261

262+
// Update card number to reflect sorted position
263+
const indexTag = card.querySelector('.index-tag');
264+
if (indexTag) indexTag.textContent = `#${displayNumber}`;
265+
261266
nodeMap.set(data.id, card);
262267
fragment.appendChild(card);
263268
newCardsAdded++;
@@ -278,6 +283,10 @@ function renderVisibleItems(forcePositionUpdate = false) {
278283
card.style.top = `${y}px`;
279284
card.style.zIndex = globalIndex;
280285
positionsUpdated++;
286+
287+
// Update card number when position changes (sort/filter changed)
288+
const indexTag = card.querySelector('.index-tag');
289+
if (indexTag) indexTag.textContent = `#${displayNumber}`;
281290
}
282291
}
283292
});
@@ -434,19 +443,15 @@ function goToImage(imageNumber) {
434443
let targetItem = null;
435444
let targetIndex = -1;
436445

437-
for (let i = 0; i < processedData.length; i++) {
438-
const item = processedData[i];
439-
const itemIndex = idToIndexMap.get(item.id) || 0;
440-
if (itemIndex === imageNumber) {
441-
targetItem = item;
442-
targetIndex = i;
443-
break;
444-
}
446+
// Card numbers reflect sorted position (1-based), so #N = processedData[N-1]
447+
if (imageNumber >= 1 && imageNumber <= processedData.length) {
448+
targetIndex = imageNumber - 1;
449+
targetItem = processedData[targetIndex];
445450
}
446451

447452
if (!targetItem || targetIndex === -1) {
448453
console.log(`[Grid] Image #${imageNumber} not found`);
449-
alert(`Image #${imageNumber} not found in current view`);
454+
alert(`Image #${imageNumber} not found in current view (${processedData.length} items visible)`);
450455
return;
451456
}
452457

0 commit comments

Comments
 (0)