OpenCode commited on
Commit ·
042d03e
1
Parent(s): bd462d7
Prioritize visible records within the viewport storage budget
Browse files- static/app.js +15 -2
- tests/test_position_window.py +20 -0
static/app.js
CHANGED
|
@@ -290,8 +290,21 @@ function saveSearchViewport(position, view) {
|
|
| 290 |
if (view.results[index]) records.push([index, cloneSearchResult(view.results[index]), VSCROLL.heights[index] || VSCROLL.estimatedHeight]);
|
| 291 |
}
|
| 292 |
const viewport = { key: position.key, savedAt: position.savedAt, anchorId: position.anchorId, index: position.index,
|
| 293 |
-
total: view.total, estimatedHeight: VSCROLL.estimatedHeight, measurementKey: getHeightMeasurementKey(), records };
|
| 294 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
searchViewportSnapshots.delete(viewport.key);
|
| 296 |
searchViewportSnapshots.set(viewport.key, viewport);
|
| 297 |
while (searchViewportSnapshots.size > SEARCH_VIEWPORT_MAX) searchViewportSnapshots.delete(searchViewportSnapshots.keys().next().value);
|
|
|
|
| 290 |
if (view.results[index]) records.push([index, cloneSearchResult(view.results[index]), VSCROLL.heights[index] || VSCROLL.estimatedHeight]);
|
| 291 |
}
|
| 292 |
const viewport = { key: position.key, savedAt: position.savedAt, anchorId: position.anchorId, index: position.index,
|
| 293 |
+
total: view.total, estimatedHeight: VSCROLL.estimatedHeight, measurementKey: getHeightMeasurementKey(), records: [] };
|
| 294 |
+
// API records can include long URLs. Spend the budget on the visible screen
|
| 295 |
+
// first, then its nearest neighbors, rather than discarding the whole preview.
|
| 296 |
+
const visibleEnd = findVirtualIndex(DOM.resultsContainer.scrollTop + DOM.resultsContainer.clientHeight);
|
| 297 |
+
const distance = index => Math.max(position.index - index, index - visibleEnd, 0);
|
| 298 |
+
records.sort((a, b) => distance(a[0]) - distance(b[0]) || a[0] - b[0]);
|
| 299 |
+
const encoder = new TextEncoder();
|
| 300 |
+
let bytes = encoder.encode(JSON.stringify(viewport)).byteLength;
|
| 301 |
+
for (const record of records) {
|
| 302 |
+
const cost = encoder.encode(JSON.stringify(record)).byteLength + 1;
|
| 303 |
+
if (bytes + cost > SEARCH_VIEWPORT_BYTES_MAX) continue;
|
| 304 |
+
viewport.records.push(record); bytes += cost;
|
| 305 |
+
}
|
| 306 |
+
viewport.records.sort((a, b) => a[0] - b[0]);
|
| 307 |
+
if (!viewport.records.some(([index]) => index === position.index)) return;
|
| 308 |
searchViewportSnapshots.delete(viewport.key);
|
| 309 |
searchViewportSnapshots.set(viewport.key, viewport);
|
| 310 |
while (searchViewportSnapshots.size > SEARCH_VIEWPORT_MAX) searchViewportSnapshots.delete(searchViewportSnapshots.keys().next().value);
|
tests/test_position_window.py
CHANGED
|
@@ -212,3 +212,23 @@ class PositionWindowTests(unittest.TestCase):
|
|
| 212 |
self.assertFalse(self.page.evaluate('!!positionRestore.preview'))
|
| 213 |
self.page.evaluate('releaseWindow()')
|
| 214 |
self.wait_anchor(49850)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
self.assertFalse(self.page.evaluate('!!positionRestore.preview'))
|
| 213 |
self.page.evaluate('releaseWindow()')
|
| 214 |
self.wait_anchor(49850)
|
| 215 |
+
|
| 216 |
+
def test_large_api_records_prioritize_visible_content_within_storage_budget(self):
|
| 217 |
+
self.page.evaluate('''() => {
|
| 218 |
+
STATE.results.forEach(record=>record.Metadata='中'.repeat(900));
|
| 219 |
+
const original=fetchPositionPage;
|
| 220 |
+
fetchPositionPage=async (...args)=>{
|
| 221 |
+
const data=await original(...args);data.results.forEach(record=>record.Metadata='中'.repeat(900));return data;
|
| 222 |
+
};
|
| 223 |
+
}''')
|
| 224 |
+
self.persist_viewport()
|
| 225 |
+
self.assertTrue(self.page.evaluate('''() => {
|
| 226 |
+
const saved=searchViewportSnapshots.get(originalWindowKey);
|
| 227 |
+
return saved.records.length<80 && new TextEncoder().encode(JSON.stringify(saved)).byteLength<=SEARCH_VIEWPORT_BYTES_MAX;
|
| 228 |
+
}'''))
|
| 229 |
+
self.page.evaluate("STATE.query='paging-other';doSearch()")
|
| 230 |
+
self.page.wait_for_function('!STATE.isLoading')
|
| 231 |
+
self.page.evaluate("searchViewSnapshots.clear();searchViewportSnapshots.clear();windowStall=1;STATE.query='paging-original';doSearch()")
|
| 232 |
+
self.assert_cached_viewport()
|
| 233 |
+
self.page.evaluate('releaseWindow()')
|
| 234 |
+
self.wait_anchor(49850)
|