Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions mods/features/adblock.js
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,15 @@ function processResponsePayload(payload, detectedPage) {
hasMore: !!plc.continuations,
});
}
// Same accumulator hook as the object-root handler above. Confirmed
// necessary on-device: three continuations arrived through that path, all
// with hasContinuation:true, and the FINAL batch (8 of 68 items, the one
// carrying no continuation token) only ever came through here. Without
// this the accumulator never sees a completion and full_cache.from_native
// never fires, so the slow re-download stays on the critical path.
// Must run BEFORE filterContinuationItems, which reduces an all-watched
// batch to the single kept helper.
noteContinuationBatch(String(window.location?.hash || ''), plc.contents, !!plc?.continuations);
plc.contents = filterContinuationItems(plc.contents, detectedPage, !!plc?.continuations, 'arrayPayload.playlist.continuation');
}
const arrayTopPlaylistRenderer = payload?.contents?.tvBrowseRenderer?.content?.tvSurfaceContentRenderer?.content?.twoColumnRenderer?.rightColumn?.playlistVideoListRenderer;
Expand Down
19 changes: 14 additions & 5 deletions mods/features/playlistBatchCollect.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
* Load → "Load All at Once".
*/

import { appendFileOnlyLog } from './hideWatched.js';
import { appendFileOnlyLog, getItemVideoId } from './hideWatched.js';
import { configRead } from '../config.js';

function _log(label, payload) {
Expand Down Expand Up @@ -490,11 +490,20 @@ export function noteContinuationBatch(key, contents, hasMore) {
if (!Array.isArray(contents) || !contents.length) return;
if (getCachedFullPlaylist(key)) return; // already complete; this is the reloaded pass

// Dedupe by video id. Two handlers feed this (object-root and array-root),
// and a batch that reached both would otherwise be counted twice, putting
// duplicate tiles in the cached playlist.
if (!window.__ttContinuationAcc || window.__ttContinuationAcc.key !== key) {
window.__ttContinuationAcc = { key, contents: [], seen: {} };
}
const acc = window.__ttContinuationAcc;
if (!acc || acc.key !== key) {
window.__ttContinuationAcc = { key, contents: contents.slice() };
} else {
acc.contents = acc.contents.concat(contents);
for (const item of contents) {
const id = getItemVideoId(item);
if (id) {
if (acc.seen[id]) continue;
acc.seen[id] = true;
}
acc.contents.push(item);
}

if (hasMore) return;
Expand Down