Refactor app orchestrator into Application with dependency injection

This commit is contained in:
thePR0M3TH3AN committed 2025-10-03 21:10:22 -04:00
1 parent ef6b8bf1cf
commit cf34e28a47
17 files changed
+525 -375

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
// js/utils/fakeDecrypt.js
/**
* Simple "decryption" placeholder for private videos.
*/
export function fakeDecrypt(str) {
if (typeof str !== "string") {
return "";
}
return str.split("").reverse().join("");
}
export default fakeDecrypt;
+59
View File
@@ -0,0 +1,59 @@
// js/utils/magnetValidators.js
import { safeDecodeMagnet } from "../magnetUtils.js";
/**
* Basic validation for BitTorrent magnet URIs.
*
* Returns `true` only when the value looks like a magnet link that WebTorrent
* understands (`magnet:` scheme with at least one `xt=urn:btih:<info-hash>`
* entry, where `<info-hash>` is either a 40-character hex digest or a
* 32-character base32 digest). Magnets that only contain BitTorrent v2 hashes
* (e.g. `btmh`) are treated as unsupported.
*/
export function isValidMagnetUri(magnet) {
const trimmed = typeof magnet === "string" ? magnet.trim() : "";
if (!trimmed) {
return false;
}
const decoded = safeDecodeMagnet(trimmed);
const candidate = decoded || trimmed;
if (/^[0-9a-f]{40}$/i.test(candidate)) {
return true;
}
try {
const parsed = new URL(candidate);
if (parsed.protocol.toLowerCase() !== "magnet:") {
return false;
}
const xtValues = parsed.searchParams.getAll("xt");
if (!xtValues.length) {
return false;
}
const hexPattern = /^[0-9a-f]{40}$/i;
const base32Pattern = /^[A-Z2-7]{32}$/;
return xtValues.some((value) => {
if (typeof value !== "string") return false;
const match = value.trim().match(/^urn:btih:([a-z0-9]+)$/i);
if (!match) return false;
const infoHash = match[1];
if (hexPattern.test(infoHash)) {
return true;
}
const upperHash = infoHash.toUpperCase();
return infoHash.length === 32 && base32Pattern.test(upperHash);
});
} catch (err) {
return false;
}
}
export default isValidMagnetUri;
+82
View File
@@ -0,0 +1,82 @@
// js/utils/mediaLoader.js
/**
* Simple IntersectionObserver-based lazy loader for images (or videos).
*
* Usage:
* const mediaLoader = new MediaLoader();
* mediaLoader.observe(imgElement);
*
* This will load the real image source from `imgElement.dataset.lazy`
* once the image enters the viewport.
*/
export class MediaLoader {
constructor(rootMargin = "50px") {
this.observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (!entry.isIntersecting) {
continue;
}
const el = entry.target;
const lazySrc =
typeof el.dataset.lazy === "string" ? el.dataset.lazy.trim() : "";
if (!lazySrc) {
continue;
}
const fallbackSrc =
(typeof el.dataset.fallbackSrc === "string"
? el.dataset.fallbackSrc.trim()
: "") ||
el.getAttribute("data-fallback-src") ||
"";
if (el.tagName === "IMG" || el.tagName === "IMAGE") {
el.src = lazySrc;
if (fallbackSrc) {
el.onerror = () => {
el.src = fallbackSrc;
};
}
} else if (el.tagName === "VIDEO") {
el.src = lazySrc;
if (fallbackSrc) {
el.poster = fallbackSrc;
}
} else {
el.style.backgroundImage = `url('${lazySrc}')`;
}
el.dataset.thumbnailLoaded = "true";
this.observer.unobserve(el);
}
}, {
rootMargin,
threshold: 0.01,
});
}
observe(el) {
if (!el || typeof el !== "object") {
return;
}
if ("decoding" in HTMLImageElement.prototype) {
el.decoding = el.decoding || "async";
}
const lazySrc =
typeof el.dataset.lazy === "string" ? el.dataset.lazy.trim() : "";
if (lazySrc) {
this.observer.observe(el);
}
}
disconnect() {
this.observer.disconnect();
}
}
export default MediaLoader;
+27
View File
@@ -0,0 +1,27 @@
// js/utils/pointer.js
export function pointerArrayToKey(pointer) {
if (!Array.isArray(pointer) || pointer.length < 2) {
return "";
}
const type = pointer[0] === "a" ? "a" : pointer[0] === "e" ? "e" : "";
if (!type) {
return "";
}
const value =
typeof pointer[1] === "string" ? pointer[1].trim().toLowerCase() : "";
if (!value) {
return "";
}
const relay =
pointer.length > 2 && typeof pointer[2] === "string"
? pointer[2].trim()
: "";
return relay ? `${type}:${value}:${relay}` : `${type}:${value}`;
}
export default pointerArrayToKey;
+29
View File
@@ -0,0 +1,29 @@
// js/utils/videoDeduper.js
/**
* Given an array of video objects, return only the newest (by created_at) for
* each videoRootId. If no videoRootId is present, treat the video’s own ID as
* its root.
*/
export function dedupeToNewestByRoot(videos) {
const map = new Map();
for (const vid of videos || []) {
if (!vid) {
continue;
}
const rootId = vid.videoRootId || vid.id;
if (!rootId) {
continue;
}
const existing = map.get(rootId);
if (!existing || vid.created_at > existing.created_at) {
map.set(rootId, vid);
}
}
return Array.from(map.values());
}
export default dedupeToNewestByRoot;