mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
The real reason every tab looked identical: VideoListView.render re-sorts displayVideos by date UNLESS metadata.preserveOrder is set, and only Explore set it. So For You's tiering, Trending's view-count ranking, and Kids' scoring were all discarded at render and shown in plain chronological order — i.e. the #21 feed-identity work was invisible. Set preserveOrder for For You, Trending, and Kids so their feed-engine order survives to the grid. Also per request: - Sidebar: Trending now sits above Recently Added. - Default homepage: logged-out users land on Trending (gated by FEATURE_TRENDING_FEED, falls back to Recent); logged-in stays For You. The logout-from-For-You redirect follows the same rule. Co-Authored-By: Claude Opus 4.8 <[email protected]>
143 lines
3.8 KiB
JavaScript
143 lines
3.8 KiB
JavaScript
import { devLogger as defaultDevLogger, userLogger as defaultUserLogger } from "./utils/logger.js";
|
|
import { FEED_TYPES, FEATURE_TRENDING_FEED } from "./constants.js";
|
|
|
|
const LEGACY_DOCS_VIEWS = {
|
|
about: "about",
|
|
"community-guidelines": "community-guidelines",
|
|
"getting-started": "getting-started",
|
|
"upload-content": "upload-content",
|
|
roadmap: "roadmap",
|
|
links: "links"
|
|
};
|
|
|
|
const createLoggerFacade = (logger, fallback) => {
|
|
if (logger && typeof logger === "object") {
|
|
return {
|
|
log: typeof logger.log === "function" ? logger.log.bind(logger) : fallback.log,
|
|
warn:
|
|
typeof logger.warn === "function" ? logger.warn.bind(logger) : fallback.warn,
|
|
error:
|
|
typeof logger.error === "function"
|
|
? logger.error.bind(logger)
|
|
: fallback.error,
|
|
};
|
|
}
|
|
|
|
return fallback;
|
|
};
|
|
|
|
const noopLogger = {
|
|
log() {},
|
|
warn() {},
|
|
error() {},
|
|
};
|
|
|
|
export function createHashChangeHandler({
|
|
getApplication,
|
|
getApplicationReady,
|
|
loadView,
|
|
viewInitRegistry,
|
|
devLogger = defaultDevLogger,
|
|
userLogger = defaultUserLogger,
|
|
} = {}) {
|
|
const devLog = createLoggerFacade(devLogger, noopLogger);
|
|
const userLog = createLoggerFacade(userLogger, noopLogger);
|
|
let currentViewName = null;
|
|
|
|
const getReadyPromise = () => {
|
|
if (typeof getApplicationReady === "function") {
|
|
return getApplicationReady();
|
|
}
|
|
return Promise.resolve();
|
|
};
|
|
|
|
const resolveIsLoggedIn = () => {
|
|
if (typeof getApplication !== "function") {
|
|
return false;
|
|
}
|
|
const app = getApplication();
|
|
if (!app || typeof app.isUserLoggedIn !== "function") {
|
|
return false;
|
|
}
|
|
return Boolean(app.isUserLoggedIn());
|
|
};
|
|
|
|
return async function handleHashChange() {
|
|
const currentHash =
|
|
typeof window !== "undefined" && window.location
|
|
? window.location.hash
|
|
: undefined;
|
|
devLog.log("handleHashChange called, current hash =", currentHash);
|
|
|
|
try {
|
|
await getReadyPromise();
|
|
} catch (error) {
|
|
userLog.warn(
|
|
"Proceeding with hash handling despite application initialization failure:",
|
|
error,
|
|
);
|
|
}
|
|
|
|
const hash =
|
|
typeof window !== "undefined" && window.location && window.location.hash
|
|
? window.location.hash
|
|
: "";
|
|
if (hash === `#${FEED_TYPES.KIDS}`) {
|
|
window.location.hash = `#view=${FEED_TYPES.KIDS}`;
|
|
return;
|
|
}
|
|
const match = hash.match(/^#view=([^&]+)/);
|
|
|
|
try {
|
|
if (!match || !match[1]) {
|
|
// Logged in → personalized For You; logged out → Trending (the best
|
|
// not-personalized landing), falling back to Recent if Trending is off.
|
|
const defaultViewName = resolveIsLoggedIn()
|
|
? FEED_TYPES.FOR_YOU
|
|
: FEATURE_TRENDING_FEED
|
|
? FEED_TYPES.TRENDING
|
|
: FEED_TYPES.RECENT;
|
|
|
|
if (defaultViewName === currentViewName) {
|
|
return;
|
|
}
|
|
|
|
await loadView(`views/${defaultViewName}.html`);
|
|
currentViewName = defaultViewName;
|
|
|
|
const initFn = viewInitRegistry?.[defaultViewName];
|
|
if (typeof initFn === "function") {
|
|
await initFn();
|
|
}
|
|
return;
|
|
}
|
|
|
|
const viewName = match[1];
|
|
|
|
if (Object.prototype.hasOwnProperty.call(LEGACY_DOCS_VIEWS, viewName)) {
|
|
const docSlug = LEGACY_DOCS_VIEWS[viewName];
|
|
window.location.hash = `#view=docs&doc=${docSlug}`;
|
|
return;
|
|
}
|
|
|
|
if (viewName === currentViewName) {
|
|
return;
|
|
}
|
|
|
|
if (typeof viewName === "string" && viewName.toLowerCase() === FEED_TYPES.HISTORY) {
|
|
}
|
|
const viewUrl = `views/${viewName}.html`;
|
|
|
|
await loadView(viewUrl);
|
|
currentViewName = viewName;
|
|
|
|
const initFn = viewInitRegistry?.[viewName];
|
|
if (typeof initFn === "function") {
|
|
await initFn();
|
|
}
|
|
} catch (error) {
|
|
userLog.error("Failed to handle hash change:", error);
|
|
}
|
|
};
|
|
}
|