Merge pull request #573 from PR0M3TH3AN/codex/refactor-logging-to-use-logger-module

Refactor JS logging to use shared loggers
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2025-10-15 14:38:30 -04:00
commit e23a2c462d
54 files changed
+940 -1197

No files matched your search

+2 -1
View File
@@ -8,6 +8,7 @@ import {
ADMIN_WHITELIST_MODE_STORAGE_KEY,
} from "./config.js";
import { loadAdminState, persistAdminState } from "./adminListStore.js";
import { userLogger } from "./utils/logger.js";
function normalizeNpub(value) {
return typeof value === "string" ? value.trim() : "";
@@ -126,7 +127,7 @@ class AccessControl {
const operation = this._performRefresh();
const tracked = operation.catch((error) => {
console.error("Failed to refresh admin lists:", error);
userLogger.error("Failed to refresh admin lists:", error);
throw error;
});
this._refreshPromise = tracked;
+25 -38
View File
@@ -9,6 +9,7 @@ import {
} from "./config.js";
import { nostrClient } from "./nostr.js";
import {
import { devLogger, userLogger } from "./utils/logger.js";
buildAdminListEvent,
ADMIN_LIST_IDENTIFIERS,
} from "./nostrEventSchemas.js";
@@ -150,8 +151,7 @@ function readJsonListFromStorage(key) {
const parsed = JSON.parse(raw);
return Array.isArray(parsed) ? parsed : null;
} catch (error) {
if (isDevMode) {
console.warn(`[adminListStore] Failed to parse legacy list for ${key}:`, error);
devLogger.warn(`[adminListStore] Failed to parse legacy list for ${key:`, error);
}
return null;
}
@@ -198,8 +198,7 @@ function clearLegacyStorageFor(listKey) {
try {
localStorage.removeItem(key);
} catch (error) {
if (isDevMode) {
console.warn(`[adminListStore] Failed to clear legacy storage for ${key}:`, error);
devLogger.warn(`[adminListStore] Failed to clear legacy storage for ${key:`, error);
}
}
}
@@ -244,9 +243,7 @@ function encodeHexToNpub(hex) {
try {
return window?.NostrTools?.nip19?.npubEncode(hex) || "";
} catch (error) {
if (isDevMode) {
console.warn("Failed to encode hex pubkey to npub:", error);
}
devLogger.warn("Failed to encode hex pubkey to npub:", error);
return "";
}
}
@@ -333,12 +330,10 @@ async function loadNostrList(identifier) {
events = combined;
}
} catch (error) {
if (isDevMode) {
console.warn(
`[adminListStore] Combined relay fetch failed for ${identifier}:`,
error
);
}
devLogger.warn(
`[adminListStore] Combined relay fetch failed for ${identifier}:`,
error
);
}
if (!events.length) {
@@ -348,12 +343,10 @@ async function loadNostrList(identifier) {
const result = await nostrClient.pool.list([url], [filter]);
return Array.isArray(result) ? result : [];
} catch (error) {
if (isDevMode) {
console.warn(
`[adminListStore] Relay fetch failed for ${identifier} on ${url}:`,
error
);
}
devLogger.warn(
`[adminListStore] Relay fetch failed for ${identifier} on ${url}:`,
error
);
return [];
}
})
@@ -394,12 +387,10 @@ function buildListEvent(listKey, npubs, actorHex) {
try {
return decodeNpubToHex(npub);
} catch (error) {
if (isDevMode) {
console.warn(
`[adminListStore] Failed to decode npub while publishing ${listKey}:`,
error
);
}
devLogger.warn(
`[adminListStore] Failed to decode npub while publishing ${listKey}:`,
error
);
return "";
}
}).filter((hex) => !!hex))
@@ -412,9 +403,7 @@ function buildListEvent(listKey, npubs, actorHex) {
hexPubkeys.push(superHex);
}
} catch (error) {
if (isDevMode) {
console.warn("Failed to ensure super admin presence:", error);
}
devLogger.warn("Failed to ensure super admin presence:", error);
}
}
@@ -457,12 +446,10 @@ function publishToRelay(url, signedEvent, listKey) {
pub.on(eventName, handler);
return true;
} catch (error) {
if (isDevMode) {
console.warn(
`[adminListStore] Relay publish rejected ${eventName} listener:`,
error
);
}
devLogger.warn(
`[adminListStore] Relay publish rejected ${eventName} listener:`,
error
);
return false;
}
};
@@ -500,7 +487,7 @@ function publishToRelay(url, signedEvent, listKey) {
finalize(true);
}).then((result) => {
if (!result.success && isDevMode) {
console.warn(
userLogger.warn(
`[adminListStore] Publish failed for ${listKey} on ${result.url}:`,
result.error
);
@@ -605,7 +592,7 @@ async function persistNostrState(actorNpub, updates = {}) {
export async function loadAdminState() {
if (ADMIN_LIST_MODE !== "nostr" && isDevMode) {
console.warn(
userLogger.warn(
`[adminListStore] ADMIN_LIST_MODE "${ADMIN_LIST_MODE}" is deprecated. Defaulting to remote Nostr lists.`
);
}
@@ -614,7 +601,7 @@ export async function loadAdminState() {
if (!hasAnyEntries(state)) {
const legacy = loadLegacyAdminState();
if (legacy && isDevMode) {
console.warn(
userLogger.warn(
"[adminListStore] Ignoring legacy admin lists because remote mode is enforced. Publish them to Nostr to retain access.",
legacy
);
@@ -626,7 +613,7 @@ export async function loadAdminState() {
export async function persistAdminState(actorNpub, updates) {
if (ADMIN_LIST_MODE !== "nostr" && isDevMode) {
console.warn(
userLogger.warn(
`[adminListStore] ADMIN_LIST_MODE "${ADMIN_LIST_MODE}" is deprecated. Remote lists are enforced.`
);
}
+3 -2
View File
@@ -1,5 +1,6 @@
// js/analytics.js
import { ANALYTICS_CONFIG } from "./analyticsConfig.js";
import { userLogger } from "./utils/logger.js";
const SCRIPT_ATTR = "data-bitvid-analytics";
const SCRIPT_IDENTIFIER = "umami";
@@ -30,7 +31,7 @@ function flushPendingCalls() {
try {
fn.apply(umami, args);
} catch (err) {
console.warn("[analytics] Failed to call", method, err);
userLogger.warn("[analytics] Failed to call", method, err);
}
}
}
@@ -103,7 +104,7 @@ function invokeUmami(method, args) {
try {
umami[method].apply(umami, args);
} catch (err) {
console.warn("[analytics] Failed to call", method, err);
userLogger.warn("[analytics] Failed to call", method, err);
}
return;
}
+2 -1
View File
@@ -1,3 +1,4 @@
import { userLogger } from "../utils/logger.js";
function toArray(value) {
if (!value) {
return [];
@@ -196,7 +197,7 @@ export function destroyCarousel(state) {
try {
dispose();
} catch (error) {
console.warn('Failed to dispose carousel listener', error);
userLogger.warn('Failed to dispose carousel listener', error);
}
});
state.cleanup = [];
+9 -8
View File
@@ -1,6 +1,7 @@
import { createCarousel, advanceSlide, destroyCarousel } from './carousel.js';
import { mountProgressBar } from './progressBar.js';
import { initZapthreadsEmbed as defaultInitZapthreadsEmbed } from './zapthreadsEmbed.js';
import { userLogger } from "../utils/logger.js";
const CAROUSEL_AUTOPLAY_INTERVAL = 8000;
@@ -499,7 +500,7 @@ function initializeZapthreads({ registerCleanup, isDestroyed, initZapthreadsEmbe
try {
dispose();
} catch (error) {
console.error('[blog] zapthreads cleanup failed', error);
userLogger.error('[blog] zapthreads cleanup failed', error);
}
return;
}
@@ -507,12 +508,12 @@ function initializeZapthreads({ registerCleanup, isDestroyed, initZapthreadsEmbe
try {
dispose();
} catch (error) {
console.error('[blog] zapthreads cleanup failed', error);
userLogger.error('[blog] zapthreads cleanup failed', error);
}
});
})
.catch((error) => {
console.error('[blog] failed to initialise zapthreads embed', error);
userLogger.error('[blog] failed to initialise zapthreads embed', error);
});
return;
}
@@ -522,7 +523,7 @@ function initializeZapthreads({ registerCleanup, isDestroyed, initZapthreadsEmbe
try {
maybeDispose();
} catch (error) {
console.error('[blog] zapthreads cleanup failed', error);
userLogger.error('[blog] zapthreads cleanup failed', error);
}
return;
}
@@ -530,12 +531,12 @@ function initializeZapthreads({ registerCleanup, isDestroyed, initZapthreadsEmbe
try {
maybeDispose();
} catch (error) {
console.error('[blog] zapthreads cleanup failed', error);
userLogger.error('[blog] zapthreads cleanup failed', error);
}
});
}
} catch (error) {
console.error('[blog] failed to start zapthreads embed', error);
userLogger.error('[blog] failed to start zapthreads embed', error);
}
});
}
@@ -555,7 +556,7 @@ function mountBlogApp({ initZapthreadsEmbed = defaultInitZapthreadsEmbed } = {})
try {
callback();
} catch (error) {
console.error('[blog] cleanup callback failed', error);
userLogger.error('[blog] cleanup callback failed', error);
}
return () => {};
}
@@ -574,7 +575,7 @@ function mountBlogApp({ initZapthreadsEmbed = defaultInitZapthreadsEmbed } = {})
try {
callback();
} catch (error) {
console.error('[blog] cleanup callback failed', error);
userLogger.error('[blog] cleanup callback failed', error);
}
});
runtime.cleanupCallbacks.clear();
+5 -4
View File
@@ -1,4 +1,5 @@
import { escapeHTML } from '../utils/domUtils.js';
import { userLogger } from "../utils/logger.js";
/**
* Responsibilities mirrored from the legacy DS component that ships inside
@@ -492,7 +493,7 @@ export function parseRelayList(relayList = '') {
try {
relays.push(new URL(trimmed).toString());
} catch (error) {
console.warn('[zapthreads] ignored invalid relay input', trimmed, error);
userLogger.warn('[zapthreads] ignored invalid relay input', trimmed, error);
}
}
@@ -1161,7 +1162,7 @@ export async function initZapthreadsEmbed({
try {
callback();
} catch (error) {
console.error('[zapthreads] cleanup failed', error);
userLogger.error('[zapthreads] cleanup failed', error);
}
});
disposeCallbacks.clear();
@@ -1194,7 +1195,7 @@ export async function initZapthreadsEmbed({
try {
currentSubscription.close();
} catch (error) {
console.error('[zapthreads] failed to close subscription', error);
userLogger.error('[zapthreads] failed to close subscription', error);
}
}
currentSubscription = null;
@@ -1276,7 +1277,7 @@ export async function initZapthreadsEmbed({
try {
callback();
} catch (error) {
console.error('[zapthreads] cleanup failed', error);
userLogger.error('[zapthreads] cleanup failed', error);
}
});
disposeCallbacks.clear();
+24 -23
View File
@@ -41,6 +41,7 @@ import {
} from "./payments/lnurl.js";
import { getPlatformLightningAddress } from "./payments/platformAddress.js";
import {
import { userLogger } from "./utils/logger.js";
ensureWallet,
sendPayment as sendWalletPayment
} from "./payments/nwcClient.js";
@@ -109,7 +110,7 @@ function logZapError(stage, details = {}, error) {
? details.retryAttempt
: undefined
};
console.error("[zap] Channel zap failure", summary, error);
userLogger.error("[zap] Channel zap failure", summary, error);
}
let currentChannelProfileEvent = null;
@@ -1289,7 +1290,7 @@ function buildChannelShareUrl() {
url.hash = `#view=channel-profile&npub=${currentChannelNpub}`;
return url.toString();
} catch (error) {
console.warn("Falling back to basic channel share URL:", error);
userLogger.warn("Falling back to basic channel share URL:", error);
const origin = window.location?.origin || "";
const pathname = window.location?.pathname || "";
if (!origin && !pathname) {
@@ -1361,7 +1362,7 @@ async function updateChannelMenuState() {
try {
await accessControl.ensureReady();
} catch (error) {
console.warn("Failed to refresh moderation lists for channel menu:", error);
userLogger.warn("Failed to refresh moderation lists for channel menu:", error);
}
const canBlacklist =
@@ -1431,7 +1432,7 @@ export async function initChannelProfileView() {
const hashParams = new URLSearchParams(window.location.hash.slice(1));
const npub = hashParams.get("npub");
if (!npub) {
console.error(
userLogger.error(
"No npub found in hash (e.g. #view=channel-profile&npub=...)"
);
return;
@@ -1456,7 +1457,7 @@ export async function initChannelProfileView() {
throw new Error("Invalid npub decoding result.");
}
} catch (err) {
console.error("Error decoding npub:", err);
userLogger.error("Error decoding npub:", err);
return;
}
@@ -1469,7 +1470,7 @@ export async function initChannelProfileView() {
setupChannelMoreMenu();
const initialMenuRefresh = updateChannelMenuState().catch((error) => {
console.error("Failed to prepare channel menu state:", error);
userLogger.error("Failed to prepare channel menu state:", error);
});
let subscriptionsTask = null;
@@ -1478,7 +1479,7 @@ export async function initChannelProfileView() {
subscriptionsTask = subscriptions
.loadSubscriptions(app.pubkey)
.catch((error) => {
console.error("Failed to load subscriptions for channel view:", error);
userLogger.error("Failed to load subscriptions for channel view:", error);
})
.finally(() => {
renderSubscribeButton(hexPub);
@@ -1495,14 +1496,14 @@ export async function initChannelProfileView() {
const profilePromise = loadUserProfile(hexPub)
.then(() => updateChannelMenuState())
.catch((error) => {
console.error("Failed to load channel profile:", error);
userLogger.error("Failed to load channel profile:", error);
})
.finally(() => {
syncChannelShareButtonState();
});
const videosPromise = loadUserVideos(hexPub).catch((error) => {
console.error("Failed to load channel videos:", error);
userLogger.error("Failed to load channel videos:", error);
});
const pendingTasks = [profilePromise, videosPromise];
@@ -1609,7 +1610,7 @@ function renderSubscribeButton(channelHex) {
if (toggleBtn) {
toggleBtn.addEventListener("click", async () => {
if (!app?.pubkey) {
console.error("Not logged in => cannot subscribe/unsubscribe.");
userLogger.error("Not logged in => cannot subscribe/unsubscribe.");
return;
}
try {
@@ -1621,7 +1622,7 @@ function renderSubscribeButton(channelHex) {
// Re-render the button so it toggles state
renderSubscribeButton(channelHex);
} catch (err) {
console.error("Failed to update subscription:", err);
userLogger.error("Failed to update subscription:", err);
}
});
}
@@ -1905,7 +1906,7 @@ function renderChannelVideosFromList({
description: detail.video?.description
})
).catch((error) => {
console.error("Failed to play channel video via event id:", error);
userLogger.error("Failed to play channel video via event id:", error);
if (typeof app?.playVideoWithFallback === "function") {
app.playVideoWithFallback({
url: detail.url,
@@ -1920,7 +1921,7 @@ function renderChannelVideosFromList({
Promise.resolve(
app.playVideoWithFallback({ url: detail.url, magnet: detail.magnet })
).catch((error) => {
console.error(
userLogger.error(
"Failed to start fallback playback for channel video:",
error
);
@@ -2235,7 +2236,7 @@ async function fetchChannelProfileFromRelays(pubkey) {
try {
await nostrClient.ensurePool();
} catch (error) {
console.error("Failed to initialize relay pool for channel profile:", error);
userLogger.error("Failed to initialize relay pool for channel profile:", error);
return { event: null, profile: {} };
}
@@ -2271,7 +2272,7 @@ async function fetchChannelProfileFromRelays(pubkey) {
const meta = JSON.parse(newestEvent.content);
return { event: newestEvent, profile: meta };
} catch (error) {
console.warn("Failed to parse channel metadata payload:", error);
userLogger.warn("Failed to parse channel metadata payload:", error);
return { event: newestEvent, profile: {} };
}
}
@@ -2343,7 +2344,7 @@ async function loadUserProfile(pubkey) {
""
});
} catch (error) {
console.warn(
userLogger.warn(
"Failed to persist channel profile metadata to cache:",
error
);
@@ -2359,7 +2360,7 @@ async function loadUserProfile(pubkey) {
});
} catch (error) {
if (loadToken === currentProfileLoadToken) {
console.error("Failed to fetch user profile data:", error);
userLogger.error("Failed to fetch user profile data:", error);
const lnEl = document.getElementById("channelLightning");
if (lnEl && !currentChannelLightningAddress) {
lnEl.textContent = "No lightning address found.";
@@ -2416,7 +2417,7 @@ async function loadUserVideos(pubkey) {
}
const ensureAccessPromise = accessControl.ensureReady().catch((error) => {
console.warn(
userLogger.warn(
"Failed to ensure admin lists were loaded before channel fetch:",
error
);
@@ -2448,7 +2449,7 @@ async function loadUserVideos(pubkey) {
events.push(...fallbackEvents);
}
} catch (error) {
console.error("Relay error (default pool):", error);
userLogger.error("Relay error (default pool):", error);
}
} else {
const relayPromises = relayList.map((url) =>
@@ -2466,7 +2467,7 @@ async function loadUserVideos(pubkey) {
}
if (result.reason) {
console.error(`Relay error (${relayUrl}):`, result.reason);
userLogger.error(`Relay error (${relayUrl}):`, result.reason);
}
});
}
@@ -2478,7 +2479,7 @@ async function loadUserVideos(pubkey) {
}
if (!container) {
console.warn("channelVideoList element not found in DOM.");
userLogger.warn("channelVideoList element not found in DOM.");
return;
}
@@ -2503,7 +2504,7 @@ async function loadUserVideos(pubkey) {
<p class="text-critical">Failed to load videos. Please try again.</p>
`;
}
console.error("Error loading user videos:", err);
userLogger.error("Error loading user videos:", err);
} finally {
await ensureAccessPromise;
if (loadToken === currentVideoLoadToken && container) {
@@ -2528,7 +2529,7 @@ window.addEventListener("bitvid:access-control-updated", () => {
}
loadUserVideos(currentChannelHex).catch((error) => {
console.error(
userLogger.error(
"Failed to refresh channel videos after admin update:",
error
);
+3 -2
View File
@@ -1,6 +1,7 @@
// js/config.js
import {
import { userLogger } from "./utils/logger.js";
IS_DEV_MODE,
ADMIN_SUPER_NPUB,
ADMIN_DM_IMAGE_URL,
@@ -61,7 +62,7 @@ export function getWhitelistMode() {
}
return raw === "true";
} catch (error) {
console.warn("Failed to read whitelist mode from storage:", error);
userLogger.warn("Failed to read whitelist mode from storage:", error);
return DEFAULT_WHITELIST_ENABLED;
}
}
@@ -70,7 +71,7 @@ export function setWhitelistMode(enabled) {
try {
localStorage.setItem(WHITELIST_MODE_KEY, enabled ? "true" : "false");
} catch (error) {
console.warn("Failed to persist whitelist mode to storage:", error);
userLogger.warn("Failed to persist whitelist mode to storage:", error);
}
}
+2 -3
View File
@@ -1,3 +1,4 @@
import { userLogger } from "./utils/logger.js";
const NEW_MODE = "new";
const FALLBACK_CONTEXT = Object.freeze({
@@ -87,9 +88,7 @@ export function applyDesignSystemAttributes(root = null) {
try {
element.setAttribute("data-ds", mode);
} catch (error) {
if (typeof console !== "undefined" && console && console.warn) {
console.warn("[design-system] Failed to set data-ds attribute:", error);
}
userLogger.warn("[design-system] Failed to set data-ds attribute:", error);
}
});
+5 -4
View File
@@ -1,3 +1,4 @@
import { userLogger } from "../utils/logger.js";
const DEFAULT_CARD_SELECTOR = ".card[data-video-id]";
function defaultIsCardVisible(entry) {
@@ -78,7 +79,7 @@ export function createCardObserver(options = {}) {
return prepared;
}
} catch (err) {
console.warn("[cardObserver] prepareEntries failed", err);
userLogger.warn("[cardObserver] prepareEntries failed", err);
}
}
@@ -122,7 +123,7 @@ export function createCardObserver(options = {}) {
state: state.customState,
}));
} catch (err) {
console.warn("[cardObserver] isCardVisible failed", err);
userLogger.warn("[cardObserver] isCardVisible failed", err);
visible = false;
}
@@ -142,7 +143,7 @@ export function createCardObserver(options = {}) {
},
});
} catch (err) {
console.warn("[cardObserver] onCardVisible failed", err);
userLogger.warn("[cardObserver] onCardVisible failed", err);
}
});
}
@@ -170,7 +171,7 @@ export function createCardObserver(options = {}) {
context: { container },
});
} catch (err) {
console.warn("[cardObserver] onCardRegister failed", err);
userLogger.warn("[cardObserver] onCardRegister failed", err);
}
}
state.observer.observe(card);
+2 -1
View File
@@ -1,6 +1,7 @@
// js/feedEngine/engine.js
import { isPlainObject } from "./utils.js";
import { userLogger } from "../utils/logger.js";
const DEFAULT_FEED_CONFIG = Object.freeze({
timeWindow: null,
@@ -93,7 +94,7 @@ function createExecutionContext(entry, { config, hooks, runtime, logger }) {
try {
resolvedLogger(`[feed:${entry.name}]`, ...args);
} catch (error) {
console.warn(`[feed:${entry.name}] logger threw`, error);
userLogger.warn(`[feed:${entry.name}] logger threw`, error);
}
},
addWhy: (detail) => {
+3 -2
View File
@@ -2,6 +2,7 @@ import { createCardObserver } from "./dom/cardObserver.js";
import { infoHashFromMagnet } from "./magnets.js";
import { updateVideoCardSourceVisibility } from "./utils/cardSourceVisibility.js";
import { TorrentClient, torrentClient } from "./webtorrent.js";
import { userLogger } from "./utils/logger.js";
const badgeUpdateListeners = new Set();
@@ -17,7 +18,7 @@ function notifyBadgeUpdate(payload) {
try {
listener(payload);
} catch (err) {
console.warn("[gridHealth] badge listener failed", err);
userLogger.warn("[gridHealth] badge listener failed", err);
}
});
}
@@ -581,7 +582,7 @@ function handleCardVisible({ card, pendingByCard, priority = 0 }) {
setBadge(card, "unhealthy", result);
})
.catch((err) => {
console.warn("[gridHealth] probe failed", err);
userLogger.warn("[gridHealth] probe failed", err);
pendingByCard.delete(card);
if (!card.isConnected) {
return;
+2 -1
View File
@@ -2,6 +2,7 @@ import PQueue from "https://esm.sh/[email protected]";
import { trackerPing } from "./trackerPing.js";
import { infoHashFromMagnet } from "./magnets.js";
import { HEALTH_TTL_MS, CONCURRENCY } from "./trackerConfig.js";
import { userLogger } from "./utils/logger.js";
const queue = new PQueue({ concurrency: CONCURRENCY });
const cache = new Map();
@@ -72,7 +73,7 @@ export function queueHealthCheck(magnet, onResult) {
setHealthCache(infoHash, health);
return health;
} catch (err) {
console.warn("trackerPing failed", err);
userLogger.warn("trackerPing failed", err);
return getDefaultHealth();
}
})
+17 -16
View File
@@ -12,6 +12,7 @@ import {
WATCH_HISTORY_BATCH_PAGE_SIZE
} from "./config.js";
import { getApplication } from "./applicationContext.js";
import { userLogger } from "./utils/logger.js";
export const WATCH_HISTORY_EMPTY_COPY =
"Your watch history is empty. Watch some videos to populate this list.";
@@ -53,7 +54,7 @@ function resolveElement(selector) {
try {
return document.querySelector(selector);
} catch (error) {
console.warn("[historyView] Failed to query selector:", selector, error);
userLogger.warn("[historyView] Failed to query selector:", selector, error);
return null;
}
}
@@ -264,7 +265,7 @@ async function defaultRemoveHandler({
}
} catch (error) {
if (isDevEnv) {
console.warn("[historyView] Failed to update watch history list:", error);
userLogger.warn("[historyView] Failed to update watch history list:", error);
}
throw error;
}
@@ -307,7 +308,7 @@ function writePreference(key, value) {
storage.setItem(key, value);
} catch (error) {
if (isDevEnv) {
console.warn("[historyView] Failed to persist preference:", error);
userLogger.warn("[historyView] Failed to persist preference:", error);
}
}
}
@@ -732,7 +733,7 @@ export function createWatchHistoryRenderer(config = {}) {
unsubscribe();
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to unsubscribe from watch history event:",
error
);
@@ -1133,7 +1134,7 @@ export function createWatchHistoryRenderer(config = {}) {
return result.trim();
}
} catch (error) {
console.warn(
userLogger.warn(
"[historyView] Failed to resolve actor via getActor:",
error
);
@@ -1177,7 +1178,7 @@ export function createWatchHistoryRenderer(config = {}) {
watchHistoryService.getLocalMetadata(pointerKeyValue) || null;
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to read stored metadata for pointer:",
pointerKeyValue,
error
@@ -1213,7 +1214,7 @@ export function createWatchHistoryRenderer(config = {}) {
});
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to persist metadata for pointer:",
pointerKeyValue,
error
@@ -1227,7 +1228,7 @@ export function createWatchHistoryRenderer(config = {}) {
watchHistoryService.removeLocalMetadata(pointerKeyValue);
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to remove cached metadata for pointer:",
pointerKeyValue,
error
@@ -1268,7 +1269,7 @@ export function createWatchHistoryRenderer(config = {}) {
} catch (error) {
state.isRendering = false;
if (isDevEnv) {
console.warn("[historyView] Failed to hydrate batch:", error);
userLogger.warn("[historyView] Failed to hydrate batch:", error);
}
return;
}
@@ -1441,7 +1442,7 @@ export function createWatchHistoryRenderer(config = {}) {
watchHistoryService.clearLocalMetadata?.();
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to clear stored metadata while resetting progress:",
error
);
@@ -1484,7 +1485,7 @@ export function createWatchHistoryRenderer(config = {}) {
const app = getAppInstance();
app?.showError?.("Failed to publish watch history. Try again later.");
if (isDevEnv) {
console.warn("[historyView] Republish failed:", error);
userLogger.warn("[historyView] Republish failed:", error);
}
}
};
@@ -1560,7 +1561,7 @@ export function createWatchHistoryRenderer(config = {}) {
}
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to set metadata preference:",
error
);
@@ -1576,7 +1577,7 @@ export function createWatchHistoryRenderer(config = {}) {
watchHistoryService.clearLocalMetadata?.();
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to clear stored metadata after disabling preference:",
error
);
@@ -1909,7 +1910,7 @@ export function createWatchHistoryRenderer(config = {}) {
watchHistoryService.removeLocalMetadata?.(pointerKeyValue);
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to drop cached metadata for pointer:",
pointerKeyValue,
error
@@ -1948,7 +1949,7 @@ export function createWatchHistoryRenderer(config = {}) {
app?.showError?.("Failed to remove from history. Reloading list.");
}
if (isDevEnv) {
console.warn("[historyView] Removal failed:", error);
userLogger.warn("[historyView] Removal failed:", error);
}
} finally {
if (parentDay instanceof HTMLElement) {
@@ -1959,7 +1960,7 @@ export function createWatchHistoryRenderer(config = {}) {
await this.refresh({ force: true });
} catch (error) {
if (isDevEnv) {
console.warn(
userLogger.warn(
"[historyView] Failed to refresh watch history after removal:",
error
);
+20 -19
View File
@@ -14,6 +14,7 @@ import {
refreshThemeControls,
} from "./themeController.js";
import {
import { devLogger, userLogger } from "./utils/logger.js";
prepareStaticModal,
openStaticModal,
closeStaticModal,
@@ -53,7 +54,7 @@ function startApplication() {
setApplicationReady(startupPromise);
startupPromise.catch((error) => {
console.error("Application failed to initialize:", error);
userLogger.error("Application failed to initialize:", error);
});
return startupPromise;
@@ -149,9 +150,9 @@ async function loadModal(url) {
applyDesignSystemAttributes(modalContainer);
refreshThemeControls(modalContainer);
}
console.log(url, "loaded");
devLogger.log(url, "loaded");
} catch (err) {
console.error(err);
userLogger.error(err);
}
}
@@ -165,9 +166,9 @@ async function loadSidebar(url, containerId) {
applyDesignSystemAttributes(container);
refreshThemeControls(container);
}
console.log(url, "loaded into", containerId);
devLogger.log(url, "loaded into", containerId);
} catch (err) {
console.error(err);
userLogger.error(err);
}
}
@@ -181,9 +182,9 @@ async function loadDisclaimer(url, containerId) {
applyDesignSystemAttributes(container);
refreshThemeControls(container);
}
console.log(url, "disclaimer loaded into", containerId);
devLogger.log(url, "disclaimer loaded into", containerId);
} catch (err) {
console.error(err);
userLogger.error(err);
}
}
@@ -197,7 +198,7 @@ async function bootstrapInterface() {
loadModal("components/bug-fix-form.html"),
]);
console.log("Modals loaded.");
devLogger.log("Modals loaded.");
[
"loginModal",
@@ -211,7 +212,7 @@ async function bootstrapInterface() {
});
await loadSidebar("components/sidebar.html", "sidebarContainer");
console.log("Sidebar loaded.");
devLogger.log("Sidebar loaded.");
const sidebar = document.getElementById("sidebar");
const collapseToggle = document.getElementById("sidebarCollapseToggle");
@@ -219,7 +220,7 @@ async function bootstrapInterface() {
sidebar.setAttribute("data-footer-state", "collapsed");
}
if (!collapseToggle) {
console.warn("Sidebar collapse toggle not found; skipping density controls.");
userLogger.warn("Sidebar collapse toggle not found; skipping density controls.");
}
const mobileMenuBtn = document.getElementById("mobileMenuBtn");
@@ -241,7 +242,7 @@ async function bootstrapInterface() {
}
return storedValue === "true";
} catch (error) {
console.warn("Unable to read sidebar collapse state from storage:", error);
userLogger.warn("Unable to read sidebar collapse state from storage:", error);
return DEFAULT_SIDEBAR_COLLAPSED;
}
};
@@ -253,7 +254,7 @@ async function bootstrapInterface() {
collapsed ? "true" : "false",
);
} catch (error) {
console.warn("Unable to persist sidebar collapse state:", error);
userLogger.warn("Unable to persist sidebar collapse state:", error);
}
};
@@ -469,11 +470,11 @@ async function bootstrapInterface() {
sidebarModule.setupSidebarNavigation({ closeSidebar });
}
} catch (error) {
console.error("Failed to set up sidebar navigation:", error);
userLogger.error("Failed to set up sidebar navigation:", error);
}
await loadDisclaimer("components/disclaimer.html", "modalContainer");
console.log("Disclaimer loaded.");
devLogger.log("Disclaimer loaded.");
prepareStaticModal({ id: "disclaimerModal" });
const loginNavBtn = document.getElementById("loginButton");
@@ -538,13 +539,13 @@ async function initializeInterface() {
try {
await bootstrapInterface();
} catch (error) {
console.error("Failed to bootstrap bitvid interface:", error);
userLogger.error("Failed to bootstrap bitvid interface:", error);
}
}
function onDomReady() {
initializeInterface().catch((error) => {
console.error("Unhandled error during bitvid initialization:", error);
userLogger.error("Unhandled error during bitvid initialization:", error);
});
}
@@ -676,12 +677,12 @@ function handleQueryParams() {
}
async function handleHashChange() {
console.log("handleHashChange called, current hash =", window.location.hash);
devLogger.log("handleHashChange called, current hash =", window.location.hash);
try {
await applicationReadyPromise;
} catch (error) {
console.warn(
userLogger.warn(
"Proceeding with hash handling despite application initialization failure:",
error
);
@@ -715,6 +716,6 @@ async function handleHashChange() {
await initFn();
}
} catch (error) {
console.error("Failed to handle hash change:", error);
userLogger.error("Failed to handle hash change:", error);
}
}
+299 -483
View File
File diff suppressed because it is too large. Load diff
+14 -20
View File
@@ -1,4 +1,5 @@
import {
import { devLogger } from "./utils/logger.js";
ADMIN_LIST_NAMESPACE,
isDevMode,
WATCH_HISTORY_KIND,
@@ -46,12 +47,10 @@ function ensureValidUtf8Content(value) {
const stringified = JSON.stringify(value);
normalized = typeof stringified === "string" ? stringified : "";
} catch (error) {
if (isDevMode) {
console.warn(
"[nostrEventSchemas] Failed to serialize view event content:",
error
);
}
devLogger.warn(
"[nostrEventSchemas] Failed to serialize view event content:",
error
);
normalized = "";
}
} else {
@@ -66,12 +65,10 @@ function ensureValidUtf8Content(value) {
try {
cachedUtf8Encoder.encode(normalized);
} catch (error) {
if (isDevMode) {
console.warn(
"[nostrEventSchemas] Dropping invalid UTF-8 characters from event content",
error
);
}
devLogger.warn(
"[nostrEventSchemas] Dropping invalid UTF-8 characters from event content",
error
);
const sanitized = Array.from(normalized)
.filter((char) => {
const code = char.charCodeAt(0);
@@ -82,12 +79,10 @@ function ensureValidUtf8Content(value) {
cachedUtf8Encoder.encode(sanitized);
normalized = sanitized;
} catch (encodeError) {
if (isDevMode) {
console.warn(
"[nostrEventSchemas] Failed to normalize view event content; defaulting to empty string",
encodeError
);
}
devLogger.warn(
"[nostrEventSchemas] Failed to normalize view event content; defaulting to empty string",
encodeError
);
normalized = "";
}
}
@@ -835,8 +830,7 @@ function resolveAdminNoteType(listKey) {
export function buildAdminListEvent(listKey, { pubkey, created_at, hexPubkeys = [] }) {
const schema = getNostrEventSchema(resolveAdminNoteType(listKey));
if (!schema) {
if (isDevMode) {
console.warn(`[nostrEventSchemas] Unknown admin list key: ${listKey}`);
devLogger.warn(`[nostrEventSchemas] Unknown admin list key: ${listKey`);
}
return {
kind: 30000,
+5 -6
View File
@@ -1,4 +1,5 @@
import { isDevMode } from "./config.js";
import { devLogger } from "./utils/logger.js";
export const RELAY_PUBLISH_TIMEOUT_MS = 10_000;
@@ -88,12 +89,10 @@ export function publishEventToRelay(pool, url, event, options = {}) {
pub.on(eventName, handler);
return true;
} catch (error) {
if (isDevMode) {
console.warn(
`[nostrPublish] Relay publish handle rejected ${eventName} listener:`,
error,
);
}
devLogger.warn(
`[nostrPublish] Relay publish handle rejected ${eventName} listener:`,
error,
);
return false;
}
};
+5 -4
View File
@@ -1,3 +1,4 @@
import { devLogger, userLogger } from "./utils/logger.js";
const REMOTE_IMPORT_TIMEOUT = 4500;
const LOCAL_IMPORT_TIMEOUT = 2500;
const NODE_IMPORT_TIMEOUT = 1500;
@@ -416,7 +417,7 @@ export function bootstrapNostrTools() {
reason: "Failed to resolve any nostr-tools helpers.",
attempts,
};
console.warn("[bitvid] nostr-tools bootstrap failed", failure);
userLogger.warn("[bitvid] nostr-tools bootstrap failed", failure);
return failure;
}
@@ -446,9 +447,9 @@ export function bootstrapNostrTools() {
if (resolvedNip04) {
canonicalTools.nip04 = resolvedNip04;
console.info("[bitvid] Initialized nostr nip04 helpers.");
devLogger.info("[bitvid] Initialized nostr nip04 helpers.");
} else {
console.warn(
userLogger.warn(
"[bitvid] NIP-04 helpers unavailable after bootstrap attempts."
);
}
@@ -507,7 +508,7 @@ export function bootstrapNostrTools() {
},
});
} catch (error) {
console.warn("[bitvid] Failed to install NostrTools guard.", error);
userLogger.warn("[bitvid] Failed to install NostrTools guard.", error);
}
applyActive(existingGlobalTools);
+4 -3
View File
@@ -1,3 +1,4 @@
import { userLogger } from "./utils/logger.js";
const DB_NAME = "bitvidSettings";
const DB_VERSION = 1;
const STORE_NAME = "kv";
@@ -183,20 +184,20 @@ function emitToast(message, { variant = "error", error } = {}) {
})
);
} catch (eventError) {
console.warn("[nwcSettings] Failed to dispatch toast event", eventError);
userLogger.warn("[nwcSettings] Failed to dispatch toast event", eventError);
}
}
}
function notifyFailure(message, error) {
const text = message || "NWC settings storage error.";
console.warn(`[nwcSettings] ${text}`, error);
userLogger.warn(`[nwcSettings] ${text}`, error);
emitToast(text, { variant: "error", error });
}
function notifyWarning(message, error) {
const text = message || "NWC settings storage warning.";
console.warn(`[nwcSettings] ${text}`, error);
userLogger.warn(`[nwcSettings] ${text}`, error);
emitToast(text, { variant: "warning", error });
}
+16 -15
View File
@@ -1,6 +1,7 @@
// js/payments/nwcClient.js
import { nostrToolsReady } from "../nostrToolsBootstrap.js";
import { userLogger } from "../utils/logger.js";
const HEX64_REGEX = /^[0-9a-f]{64}$/i;
const URI_SCHEMES = [
@@ -119,7 +120,7 @@ let cachedNostrTools = __nwcNostrToolsBootstrap.toolkit || null;
const nostrToolsInitializationFailure = __nwcNostrToolsBootstrap.failure || null;
if (!cachedNostrTools && nostrToolsInitializationFailure) {
console.warn(
userLogger.warn(
"[nwcClient] nostr-tools helpers unavailable after bootstrap.",
nostrToolsInitializationFailure
);
@@ -150,7 +151,7 @@ async function ensureNostrTools() {
const result = await nostrToolsReadySource;
rememberNostrTools(result);
} catch (error) {
console.warn("[nwcClient] Failed to resolve nostr-tools helpers.", error);
userLogger.warn("[nwcClient] Failed to resolve nostr-tools helpers.", error);
}
if (!cachedNostrTools) {
rememberNostrTools(readToolkitFromScope());
@@ -200,15 +201,15 @@ function assertNostrTools(methods = []) {
const available = Array.isArray(Object.keys(tools))
? Object.keys(tools)
: [];
console.error(
userLogger.error(
"[nwcClient] Required NostrTools capability is missing.",
{
missingMethod: method,
availableMethods: available,
missingMethod: method,
availableMethods: available,
}
);
} catch (loggingError) {
console.error(
userLogger.error(
"[nwcClient] Failed to enumerate available NostrTools methods.",
loggingError
);
@@ -454,7 +455,7 @@ function createNip44Encryption(context) {
const secretBytes = hexToBytesCompat(context.secretKey);
cachedKey = resolved.getConversationKey(secretBytes, context.walletPubkey);
} catch (error) {
console.warn("[nwcClient] Failed to derive nip44 conversation key", error);
userLogger.warn("[nwcClient] Failed to derive nip44 conversation key", error);
throw error;
}
}
@@ -527,7 +528,7 @@ function settleInfoRequest(result) {
try {
resolver(result || null);
} catch (error) {
console.warn("[nwcClient] Failed to resolve wallet info request", error);
userLogger.warn("[nwcClient] Failed to resolve wallet info request", error);
}
}
}
@@ -571,7 +572,7 @@ function requestInfoEvent(context) {
try {
socket.send(JSON.stringify(["REQ", infoSubscriptionId, filters]));
} catch (error) {
console.warn("[nwcClient] Failed to request wallet info event", error);
userLogger.warn("[nwcClient] Failed to request wallet info event", error);
settleInfoRequest(null);
return Promise.resolve(null);
}
@@ -619,7 +620,7 @@ async function ensureEncryption(context) {
try {
infoEvent = await requestInfoEvent(context);
} catch (error) {
console.warn("[nwcClient] Failed to load wallet info event", error);
userLogger.warn("[nwcClient] Failed to load wallet info event", error);
}
if (infoEvent) {
context.infoEvent = infoEvent;
@@ -735,12 +736,12 @@ function isSocketOpen() {
}
function handleSocketError(error) {
console.warn("[nwcClient] WebSocket error", error);
userLogger.warn("[nwcClient] WebSocket error", error);
closeSocket({ keepState: true });
}
function handleSocketClose() {
console.warn("[nwcClient] Wallet connection closed.");
userLogger.warn("[nwcClient] Wallet connection closed.");
closeSocket({ keepState: true });
}
@@ -782,7 +783,7 @@ async function handleSocketMessage(messageEvent) {
try {
payload = JSON.parse(messageEvent.data);
} catch (error) {
console.warn("[nwcClient] Failed to parse relay message", error);
userLogger.warn("[nwcClient] Failed to parse relay message", error);
return;
}
@@ -815,7 +816,7 @@ async function handleSocketMessage(messageEvent) {
finalizePendingRequest(pending);
pending.reject(error);
} else {
console.warn("[nwcClient] Failed to decrypt wallet response", error);
userLogger.warn("[nwcClient] Failed to decrypt wallet response", error);
}
return;
}
@@ -860,7 +861,7 @@ async function handleSocketMessage(messageEvent) {
}
if (type === "NOTICE" && payload.length >= 2) {
console.warn("[nwcClient] Relay notice:", payload[1]);
userLogger.warn("[nwcClient] Relay notice:", payload[1]);
return;
}
}
+7 -6
View File
@@ -4,6 +4,7 @@ import { PLATFORM_LUD16_OVERRIDE, ADMIN_SUPER_NPUB } from "../config.js";
import { nostrClient } from "../nostr.js";
import { setProfileCacheEntry } from "../state/cache.js";
import { nostrToolsReady } from "../nostrToolsBootstrap.js";
import { userLogger } from "../utils/logger.js";
const HEX64_REGEX = /^[0-9a-f]{64}$/i;
const CACHE_TTL_MS = 10 * 60 * 1000;
@@ -106,7 +107,7 @@ const nostrToolsInitializationFailure =
__platformNostrToolsBootstrap.failure || null;
if (!cachedNostrTools && nostrToolsInitializationFailure) {
console.warn(
userLogger.warn(
"[platformAddress] nostr-tools helpers unavailable after bootstrap.",
nostrToolsInitializationFailure
);
@@ -137,7 +138,7 @@ async function ensureNostrTools() {
const result = await nostrToolsReadySource;
rememberNostrTools(result);
} catch (error) {
console.warn(
userLogger.warn(
"[platformAddress] Failed to resolve nostr-tools helpers.",
error
);
@@ -198,7 +199,7 @@ function decodeAdminPubkey() {
}
}
} catch (error) {
console.warn("[platformAddress] Failed to decode ADMIN_SUPER_NPUB", error);
userLogger.warn("[platformAddress] Failed to decode ADMIN_SUPER_NPUB", error);
}
}
@@ -233,7 +234,7 @@ async function fetchAdminMetadata(adminPubkey) {
try {
pool = await nostrClient.ensurePool();
} catch (error) {
console.warn("[platformAddress] Failed to initialize Nostr pool", error);
userLogger.warn("[platformAddress] Failed to initialize Nostr pool", error);
return null;
}
@@ -245,7 +246,7 @@ async function fetchAdminMetadata(adminPubkey) {
? nostrClient.relays
: [];
if (relayUrls.length === 0) {
console.warn("[platformAddress] Nostr client is not ready.");
userLogger.warn("[platformAddress] Nostr client is not ready.");
return null;
}
@@ -286,7 +287,7 @@ async function fetchAdminMetadata(adminPubkey) {
return lightningAddress || null;
} catch (error) {
console.warn("[platformAddress] Failed to fetch admin metadata", error);
userLogger.warn("[platformAddress] Failed to fetch admin metadata", error);
return null;
}
}
+3 -2
View File
@@ -11,6 +11,7 @@ import {
import { ensureWallet, sendPayment } from "./nwcClient.js";
import { getPlatformLightningAddress } from "./platformAddress.js";
import {
import { userLogger } from "../utils/logger.js";
clampPercent,
parsePercentValue,
resolvePlatformFeePercent,
@@ -124,7 +125,7 @@ let cachedNostrTools = __zapNostrToolsBootstrap.toolkit || null;
const nostrToolsInitializationFailure = __zapNostrToolsBootstrap.failure || null;
if (!cachedNostrTools && nostrToolsInitializationFailure) {
console.warn(
userLogger.warn(
"[zapSplit] nostr-tools helpers unavailable after bootstrap.",
nostrToolsInitializationFailure
);
@@ -155,7 +156,7 @@ async function ensureNostrTools() {
const result = await nostrToolsReadySource;
rememberNostrTools(result);
} catch (error) {
console.warn("[zapSplit] Failed to resolve nostr-tools helpers.", error);
userLogger.warn("[zapSplit] Failed to resolve nostr-tools helpers.", error);
}
if (!cachedNostrTools) {
rememberNostrTools(readToolkitFromScope());
+9 -8
View File
@@ -7,6 +7,7 @@ import {
setManagedDomain,
} from "./storage/r2-mgmt.js";
import { makeR2Client, multipartUpload } from "./storage/r2-s3.js";
import { userLogger } from "./utils/logger.js";
const STORAGE_KEY = "bitvid:quickR2Settings";
const STATUS_CLASSNAMES = [
@@ -46,7 +47,7 @@ function loadSavedSettings() {
}
return parsed;
} catch (err) {
console.warn("Failed to read quick R2 settings:", err);
userLogger.warn("Failed to read quick R2 settings:", err);
return null;
}
}
@@ -55,7 +56,7 @@ function persistSettings(settings) {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
} catch (err) {
console.warn("Failed to store quick R2 settings:", err);
userLogger.warn("Failed to store quick R2 settings:", err);
}
}
@@ -63,7 +64,7 @@ function clearSavedSettings() {
try {
localStorage.removeItem(STORAGE_KEY);
} catch (err) {
console.warn("Failed to clear quick R2 settings:", err);
userLogger.warn("Failed to clear quick R2 settings:", err);
}
}
@@ -258,7 +259,7 @@ export function initQuickR2Upload(app) {
origins: getCorsOrigins(),
});
} catch (corsErr) {
console.warn("Quick R2 CORS update failed:", corsErr);
userLogger.warn("Quick R2 CORS update failed:", corsErr);
}
}
@@ -292,7 +293,7 @@ export function initQuickR2Upload(app) {
enabled: false,
});
} catch (disableErr) {
console.warn("Quick R2 managed domain disable failed:", disableErr);
userLogger.warn("Quick R2 managed domain disable failed:", disableErr);
}
} else {
setStatus(
@@ -302,7 +303,7 @@ export function initQuickR2Upload(app) {
);
}
} catch (err) {
console.warn("Quick R2 custom domain error:", err);
userLogger.warn("Quick R2 custom domain error:", err);
setStatus(
elements.status,
err?.message
@@ -332,7 +333,7 @@ export function initQuickR2Upload(app) {
usedManagedFallback = true;
}
} catch (err) {
console.warn("Quick R2 managed domain enable failed:", err);
userLogger.warn("Quick R2 managed domain enable failed:", err);
setStatus(
elements.status,
err?.message
@@ -393,7 +394,7 @@ export function initQuickR2Upload(app) {
elements.form.requestSubmit();
}
} catch (err) {
console.error("Quick R2 upload failed:", err);
userLogger.error("Quick R2 upload failed:", err);
setStatus(
elements.status,
err?.message ? `Upload failed: ${err.message}` : "Upload failed.",
+6 -5
View File
@@ -1,3 +1,4 @@
import { userLogger } from "./utils/logger.js";
const DB_NAME = "bitvidSettings";
const DB_VERSION = 1;
const STORE_NAME = "kv";
@@ -104,7 +105,7 @@ export async function loadR2Settings() {
});
}
} catch (err) {
console.warn("Failed to open IndexedDB for settings, falling back:", err);
userLogger.warn("Failed to open IndexedDB for settings, falling back:", err);
}
try {
@@ -115,7 +116,7 @@ export async function loadR2Settings() {
}
}
} catch (err) {
console.warn("Failed to read fallback settings:", err);
userLogger.warn("Failed to read fallback settings:", err);
}
return normalizeSettings(null);
@@ -128,7 +129,7 @@ export async function saveR2Settings(settings) {
try {
db = await openSettingsDb();
} catch (err) {
console.warn("Unable to open IndexedDB, continuing with fallback:", err);
userLogger.warn("Unable to open IndexedDB, continuing with fallback:", err);
}
if (db) {
@@ -165,7 +166,7 @@ export async function clearR2Settings() {
cleared = true;
}
} catch (err) {
console.warn("Failed to clear IndexedDB settings:", err);
userLogger.warn("Failed to clear IndexedDB settings:", err);
}
try {
@@ -174,7 +175,7 @@ export async function clearR2Settings() {
cleared = true;
}
} catch (err) {
console.warn("Failed to clear fallback settings:", err);
userLogger.warn("Failed to clear fallback settings:", err);
}
return cleared;
+12 -19
View File
@@ -2,6 +2,7 @@ import { isDevMode } from "./config.js";
import { DEFAULT_RELAY_URLS, nostrClient } from "./nostr.js";
import { buildRelayListEvent } from "./nostrEventSchemas.js";
import {
import { devLogger, userLogger } from "./utils/logger.js";
publishEventToRelays,
assertAnyRelayAccepted,
} from "./nostrPublish.js";
@@ -537,17 +538,13 @@ class RelayPreferencesManager {
} else {
const reason = outcome.reason;
if (reason?.code === "timeout") {
if (isDevMode) {
console.warn(
`[relayManager] Relay ${reason.relay} timed out while loading relay list (${reason.timeoutMs}ms)`
);
}
} else if (isDevMode) {
console.warn(
`[relayManager] Relay ${reason?.relay || "unknown"} failed while loading relay list:`,
reason
devLogger.warn(
`[relayManager] Relay ${reason.relay} timed out while loading relay list (${reason.timeoutMs}ms)`
);
}
} else devLogger.warn(
`[relayManager] Relay ${reason?.relay || "unknown"} failed while loading relay list:`,
reason
);
}
});
@@ -558,9 +555,7 @@ class RelayPreferencesManager {
applyEvents(aggregated, { skipIfEmpty: true });
})
.catch((error) => {
if (isDevMode) {
console.warn("[relayManager] Background relay refresh failed", error);
}
devLogger.warn("[relayManager] Background relay refresh failed", error);
});
let fastResult = null;
@@ -571,14 +566,12 @@ class RelayPreferencesManager {
if (error instanceof AggregateError) {
error.errors?.forEach((err) => {
if (err?.code === "timeout" && isDevMode) {
console.warn(
userLogger.warn(
`[relayManager] Relay ${err.relay} timed out while loading relay list (${err.timeoutMs}ms)`
);
}
});
} else if (isDevMode) {
console.warn("[relayManager] Fast relay fetch failed", error);
}
} else devLogger.warn("[relayManager] Fast relay fetch failed", error);
}
}
@@ -657,7 +650,7 @@ class RelayPreferencesManager {
if (publishError?.relayFailures?.length) {
publishError.relayFailures.forEach(
({ url, error: relayError, reason }) => {
console.error(
userLogger.error(
`[RelayPreferencesManager] Relay ${url} rejected relay list: ${reason}`,
relayError || reason
);
@@ -675,7 +668,7 @@ class RelayPreferencesManager {
: relayError
? String(relayError)
: "publish failed";
console.warn(
userLogger.warn(
`[RelayPreferencesManager] Relay ${url} did not acknowledge relay list: ${reason}`,
relayError
);
+3 -2
View File
@@ -7,6 +7,7 @@ import {
getCurrentUserNpub,
} from "../state/appState.js";
import {
import { userLogger } from "../utils/logger.js";
getSavedProfiles,
getActiveProfilePubkey,
setActiveProfilePubkey,
@@ -94,7 +95,7 @@ export default class AuthService {
try {
this.logger(message, error);
} catch (logError) {
console.warn("[AuthService] logger threw", logError);
userLogger.warn("[AuthService] logger threw", logError);
}
});
}
@@ -103,7 +104,7 @@ export default class AuthService {
try {
this.logger(...args);
} catch (error) {
console.warn("[AuthService] logger threw", error);
userLogger.warn("[AuthService] logger threw", error);
}
}
+4 -4
View File
@@ -1,4 +1,4 @@
import { isDevMode } from "../config.js";
import { devLogger } from "../utils/logger.js";
const DEFAULT_MAX_DISCUSSION_COUNT_VIDEOS = 24;
const COUNT_UNSUPPORTED_TITLE = "Relay does not support NIP-45 COUNT queries.";
@@ -14,10 +14,10 @@ function toPositiveInteger(value, fallback) {
export default class DiscussionCountService {
constructor({
maxVideos = DEFAULT_MAX_DISCUSSION_COUNT_VIDEOS,
logger = typeof console !== "undefined" ? console : null,
logger = devLogger,
} = {}) {
this.maxVideos = toPositiveInteger(maxVideos, DEFAULT_MAX_DISCUSSION_COUNT_VIDEOS);
this.logger = logger;
this.logger = logger && typeof logger.warn === "function" ? logger : devLogger;
this.videoDiscussionCountCache = new Map();
this.inFlightDiscussionCounts = new Map();
}
@@ -104,7 +104,7 @@ export default class DiscussionCountService {
return result;
})
.catch((error) => {
if (isDevMode && this.logger?.warn) {
if (this.logger?.warn) {
this.logger.warn(
`[counts] Failed to fetch discussion count for ${video.id}:`,
error
+12 -11
View File
@@ -5,6 +5,7 @@ import {
import { accessControl } from "../accessControl.js";
import { ALLOW_NSFW_CONTENT } from "../config.js";
import {
import { userLogger } from "../utils/logger.js";
getVideosMap as getStoredVideosMap,
setVideosMap as setStoredVideosMap,
getVideoSubscription as getStoredVideoSubscription,
@@ -53,7 +54,7 @@ class SimpleEventEmitter {
try {
this.logger(`nostrService listener for "${eventName}" threw`, error);
} catch (logError) {
console.warn("[nostrService] listener logger threw", logError);
userLogger.warn("[nostrService] listener logger threw", logError);
}
}
}
@@ -108,7 +109,7 @@ export class NostrService {
try {
this.logger(message, error);
} catch (logError) {
console.warn("[nostrService] logger threw", logError);
userLogger.warn("[nostrService] logger threw", logError);
}
});
this.videosMap = null;
@@ -118,7 +119,7 @@ export class NostrService {
try {
this.logger(...args);
} catch (error) {
console.warn("[nostrService] logger threw", error);
userLogger.warn("[nostrService] logger threw", error);
}
}
@@ -164,7 +165,7 @@ export class NostrService {
try {
current.unsub();
} catch (error) {
console.warn("[nostrService] Failed to unsubscribe from video feed:", error);
userLogger.warn("[nostrService] Failed to unsubscribe from video feed:", error);
}
}
this.setVideoSubscription(null);
@@ -209,7 +210,7 @@ export class NostrService {
return false;
}
} catch (error) {
console.warn("[nostrService] isAuthorBlocked handler threw", error);
userLogger.warn("[nostrService] isAuthorBlocked handler threw", error);
}
}
@@ -223,7 +224,7 @@ export class NostrService {
return false;
}
} catch (error) {
console.warn("[nostrService] access control check failed", error);
userLogger.warn("[nostrService] access control check failed", error);
return false;
}
}
@@ -254,7 +255,7 @@ export class NostrService {
try {
await this.accessControl.ensureReady();
} catch (error) {
console.warn(
userLogger.warn(
"[nostrService] Failed to ensure access control lists are ready:",
error
);
@@ -288,7 +289,7 @@ export class NostrService {
try {
onVideos(filtered, { reason });
} catch (error) {
console.warn("[nostrService] onVideos handler threw", error);
userLogger.warn("[nostrService] onVideos handler threw", error);
}
}
this.emit("videos:updated", { videos: filtered, reason });
@@ -318,7 +319,7 @@ export class NostrService {
this.emit("videos:fetched", { videos: filtered });
return filtered;
} catch (error) {
console.error("[nostrService] Failed to fetch videos:", error);
userLogger.error("[nostrService] Failed to fetch videos:", error);
return [];
}
}
@@ -362,11 +363,11 @@ export class NostrService {
collected.set(video.id, video);
this.nostrClient.allEvents.set(video.id, video);
} catch (error) {
console.warn("[nostrService] Failed to convert older event", error);
userLogger.warn("[nostrService] Failed to convert older event", error);
}
}
} catch (error) {
console.error("[nostrService] Failed to load older videos:", error);
userLogger.error("[nostrService] Failed to load older videos:", error);
return [];
}
+19 -16
View File
@@ -5,6 +5,7 @@ import {
createDefaultNwcSettings,
} from "../nwcSettings.js";
import { MAX_WALLET_DEFAULT_ZAP } from "../config.js";
import { devLogger, userLogger } from "../utils/logger.js";
const NWC_URI_SCHEME = "nostr+walletconnect://";
@@ -17,7 +18,7 @@ export default class NwcSettingsService {
normalizeHexPubkey,
getActivePubkey,
payments = null,
logger = console,
logger = { dev: devLogger, user: userLogger },
notifyError,
maxWalletDefaultZap = MAX_WALLET_DEFAULT_ZAP,
loadSettings = loadNwcSettings,
@@ -32,7 +33,9 @@ export default class NwcSettingsService {
? getActivePubkey
: () => null;
this.payments = payments || null;
this.logger = logger || console;
const devChannel = logger?.dev && typeof logger.dev.warn === "function" ? logger.dev : devLogger;
const userChannel = logger?.user && typeof logger.user.warn === "function" ? logger.user : userLogger;
this.logger = { dev: devChannel, user: userChannel };
this.notifyError = isFunction(notifyError) ? notifyError : null;
this.maxWalletDefaultZap =
Number.isFinite(maxWalletDefaultZap) && maxWalletDefaultZap > 0
@@ -78,8 +81,8 @@ export default class NwcSettingsService {
try {
return this.normalizeHexPubkey(pubkey);
} catch (error) {
if (this.logger && isFunction(this.logger.warn)) {
this.logger.warn("[nwcSettings] Failed to normalize pubkey:", error);
if (isFunction(this.logger.user?.warn)) {
this.logger.user.warn("[nwcSettings] Failed to normalize pubkey:", error);
}
return null;
}
@@ -100,8 +103,8 @@ export default class NwcSettingsService {
this.cache.set(normalized, record);
return this.cloneSettings(record);
} catch (error) {
if (this.logger && isFunction(this.logger.warn)) {
this.logger.warn(
if (isFunction(this.logger.user?.warn)) {
this.logger.user.warn(
`[nwcSettings] Failed to load settings for ${normalized}:`,
error,
);
@@ -160,8 +163,8 @@ export default class NwcSettingsService {
async updateActiveNwcSettings(partial = {}) {
const normalized = this.getNormalizedPubkey(this.getActivePubkey());
if (!normalized) {
if (this.logger && isFunction(this.logger.warn)) {
this.logger.warn(
if (isFunction(this.logger.user?.warn)) {
this.logger.user.warn(
"[nwcSettings] Cannot update settings without an active pubkey.",
);
}
@@ -177,8 +180,8 @@ export default class NwcSettingsService {
this.cache.set(normalized, record);
return this.cloneSettings(record);
} catch (error) {
if (this.logger && isFunction(this.logger.warn)) {
this.logger.warn(
if (isFunction(this.logger.user?.warn)) {
this.logger.user.warn(
`[nwcSettings] Failed to save settings for ${normalized}:`,
error,
);
@@ -239,8 +242,8 @@ export default class NwcSettingsService {
return this.payments.ensureWallet({ settings: merged });
}
if (this.logger && isFunction(this.logger.warn)) {
this.logger.warn(
if (isFunction(this.logger.dev?.warn)) {
this.logger.dev.warn(
"[wallet] Falling back to stub ensureWallet implementation. Returning settings without performing a connection test.",
);
}
@@ -256,8 +259,8 @@ export default class NwcSettingsService {
try {
await this.clearSettings(normalized);
} catch (error) {
if (this.logger && isFunction(this.logger.warn)) {
this.logger.warn(
if (isFunction(this.logger.user?.warn)) {
this.logger.user.warn(
`[nwcSettings] Failed to clear settings for ${normalized}:`,
error,
);
@@ -268,8 +271,8 @@ export default class NwcSettingsService {
try {
await this.saveSettings(normalized, this.createDefaultNwcSettings());
} catch (persistError) {
if (this.logger && isFunction(this.logger.warn)) {
this.logger.warn(
if (isFunction(this.logger.user?.warn)) {
this.logger.user.warn(
`[nwcSettings] Failed to overwrite settings for ${normalized}:`,
persistError,
);
+2 -1
View File
@@ -1,3 +1,4 @@
import { userLogger } from "../utils/logger.js";
// js/services/playbackService.js
class SimpleEventEmitter {
@@ -73,7 +74,7 @@ export class PlaybackService {
try {
this.logger(...args);
} catch (err) {
console.warn("[PlaybackService] logger threw", err);
userLogger.warn("[PlaybackService] logger threw", err);
}
}
+16 -15
View File
@@ -21,6 +21,7 @@ import {
ensureBucketCors,
} from "../storage/r2-s3.js";
import { truncateMiddle } from "../utils/formatters.js";
import { userLogger } from "../utils/logger.js";
const STATUS_VARIANTS = new Set(["info", "success", "error", "warning"]);
@@ -69,7 +70,7 @@ class R2Service {
try {
handler(detail);
} catch (err) {
console.error("[r2Service] Listener error for", event, err);
userLogger.error("[r2Service] Listener error for", event, err);
}
}
}
@@ -225,7 +226,7 @@ class R2Service {
this.populateCloudflareSettingsInputs(settings);
return settings;
} catch (err) {
console.error("Failed to load Cloudflare settings:", err);
userLogger.error("Failed to load Cloudflare settings:", err);
this.setSettings(createDefaultSettings());
this.populateCloudflareSettingsInputs(this.getSettings());
this.setCloudflareSettingsStatus(
@@ -285,7 +286,7 @@ class R2Service {
}
return true;
} catch (err) {
console.error("Failed to save Cloudflare settings:", err);
userLogger.error("Failed to save Cloudflare settings:", err);
if (!quiet) {
this.setCloudflareSettingsStatus(
"Failed to save settings. Check console for details.",
@@ -310,7 +311,7 @@ class R2Service {
this.setCloudflareSettingsStatus("Settings cleared.", "success");
return true;
} catch (err) {
console.error("Failed to clear Cloudflare settings:", err);
userLogger.error("Failed to clear Cloudflare settings:", err);
this.setCloudflareSettingsStatus("Failed to clear settings.", "error");
return false;
}
@@ -338,7 +339,7 @@ class R2Service {
try {
return deriveShortSubdomain(npub);
} catch (err) {
console.warn("Failed to derive short subdomain, falling back:", err);
userLogger.warn("Failed to derive short subdomain, falling back:", err);
}
const base = String(npub || "user")
@@ -382,7 +383,7 @@ class R2Service {
origins: corsOrigins,
});
} catch (err) {
console.warn("Failed to refresh bucket configuration:", err);
userLogger.warn("Failed to refresh bucket configuration:", err);
}
} else if (accessKeyId && secretAccessKey && corsOrigins.length > 0) {
try {
@@ -397,7 +398,7 @@ class R2Service {
origins: corsOrigins,
});
} catch (err) {
console.warn("Failed to refresh bucket CORS via access keys:", err);
userLogger.warn("Failed to refresh bucket CORS via access keys:", err);
}
}
return {
@@ -444,7 +445,7 @@ class R2Service {
origins: corsOrigins,
});
} catch (corsErr) {
console.warn(
userLogger.warn(
"Failed to ensure R2 CORS rules via access keys. Configure the bucket's CORS policy manually if uploads continue to fail.",
corsErr
);
@@ -485,7 +486,7 @@ class R2Service {
origins: corsOrigins,
});
} catch (err) {
console.warn("Failed to apply R2 CORS rules:", err);
userLogger.warn("Failed to apply R2 CORS rules:", err);
}
let publicBaseUrl = entry?.publicBaseUrl || "";
@@ -517,7 +518,7 @@ class R2Service {
enabled: false,
});
} catch (disableErr) {
console.warn("Failed to disable managed domain:", disableErr);
userLogger.warn("Failed to disable managed domain:", disableErr);
}
} else {
usedManagedFallback = true;
@@ -535,10 +536,10 @@ class R2Service {
enabled: false,
});
} catch (disableErr) {
console.warn("Failed to disable managed domain:", disableErr);
userLogger.warn("Failed to disable managed domain:", disableErr);
}
} else {
console.warn("Failed to attach custom domain, falling back:", err);
userLogger.warn("Failed to attach custom domain, falling back:", err);
usedManagedFallback = true;
customDomainStatus = "error";
}
@@ -699,7 +700,7 @@ class R2Service {
try {
bucketResult = await this.ensureBucketConfigForNpub(npub);
} catch (err) {
console.error("Failed to prepare R2 bucket:", err);
userLogger.error("Failed to prepare R2 bucket:", err);
this.setCloudflareUploadStatus(
err?.message ? `Bucket setup failed: ${err.message}` : "Bucket setup failed.",
"error"
@@ -760,7 +761,7 @@ class R2Service {
let publishOutcome = true;
if (typeof publishVideoNote !== "function") {
console.warn(
userLogger.warn(
"publishVideoNote handler missing; skipping publish step."
);
publishOutcome = false;
@@ -805,7 +806,7 @@ class R2Service {
return publishOutcome;
} catch (err) {
console.error("Cloudflare upload failed:", err);
userLogger.error("Cloudflare upload failed:", err);
this.setCloudflareUploadStatus(
err?.message ? `Upload failed: ${err.message}` : "Upload failed.",
"error"
+45 -64
View File
@@ -1,6 +1,7 @@
import { isDevMode } from "../config.js";
import { pointerArrayToKey } from "../utils/pointer.js";
import {
import { devLogger, userLogger } from "../utils/logger.js";
ingestLocalViewEvent as defaultIngestLocalViewEvent,
} from "../viewCounter.js";
@@ -108,12 +109,10 @@ export default class WatchHistoryTelemetry {
try {
this.watchHistoryService?.clearLocalMetadata?.();
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Failed to clear cached metadata after toggle off:",
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Failed to clear cached metadata after toggle off:",
error,
);
}
}
},
@@ -122,12 +121,10 @@ export default class WatchHistoryTelemetry {
this.watchHistoryPreferenceUnsubscribe = unsubscribe;
}
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Failed to subscribe to metadata preference changes:",
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Failed to subscribe to metadata preference changes:",
error,
);
}
}
@@ -153,12 +150,10 @@ export default class WatchHistoryTelemetry {
enabled = this.watchHistoryService.shouldStoreMetadata() !== false;
}
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Failed to read metadata settings:",
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Failed to read metadata settings:",
error,
);
enabled = true;
}
@@ -168,12 +163,10 @@ export default class WatchHistoryTelemetry {
try {
this.watchHistoryService?.clearLocalMetadata?.();
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Failed to purge metadata cache while preference disabled:",
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Failed to purge metadata cache while preference disabled:",
error,
);
}
}
@@ -205,13 +198,11 @@ export default class WatchHistoryTelemetry {
try {
this.watchHistoryService.setLocalMetadata(pointerInfo.key, metadata);
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Failed to persist local metadata for pointer:",
pointerInfo.key,
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Failed to persist local metadata for pointer:",
pointerInfo.key,
error,
);
}
}
@@ -227,13 +218,11 @@ export default class WatchHistoryTelemetry {
try {
this.watchHistoryService.removeLocalMetadata(pointerKey);
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Failed to remove cached metadata for pointer:",
pointerKey,
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Failed to remove cached metadata for pointer:",
pointerKey,
error,
);
}
}
@@ -277,12 +266,10 @@ export default class WatchHistoryTelemetry {
try {
state.videoEl.removeEventListener(eventName, handler);
} catch (error) {
if (isDevMode) {
console.warn(
`[watchHistoryTelemetry] Failed to detach ${eventName} listener:`,
error,
);
}
devLogger.warn(
`[watchHistoryTelemetry] Failed to detach ${eventName} listener:`,
error,
);
}
}
}
@@ -423,12 +410,10 @@ export default class WatchHistoryTelemetry {
viewResult = { ok: false, error: "view-logging-unavailable" };
}
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Exception while recording video view:",
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Exception while recording video view:",
error,
);
}
const viewOk = !!viewResult?.ok;
@@ -451,27 +436,23 @@ export default class WatchHistoryTelemetry {
pointer: thresholdPointer,
});
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Failed to ingest local view event:",
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Failed to ingest local view event:",
error,
);
}
}
} else if (isDevMode && viewResult) {
console.warn(
userLogger.warn(
"[watchHistoryTelemetry] View event rejected by relays:",
viewResult,
);
}
})().catch((error) => {
if (isDevMode) {
console.warn(
"[watchHistoryTelemetry] Unexpected error while recording video view:",
error,
);
}
devLogger.warn(
"[watchHistoryTelemetry] Unexpected error while recording video view:",
error,
);
});
};
@@ -581,7 +562,7 @@ export default class WatchHistoryTelemetry {
try {
this.watchHistoryPreferenceUnsubscribe();
} catch (error) {
console.warn(
userLogger.warn(
"[watchHistoryTelemetry] Failed to unsubscribe watch history preference:",
error,
);
+4 -3
View File
@@ -1,3 +1,4 @@
import { userLogger } from "../utils/logger.js";
const state = {
pubkey: null,
currentUserNpub: null,
@@ -29,7 +30,7 @@ function notifyKey(key, value, previousValue) {
try {
callback(value, previousValue, createSnapshot());
} catch (error) {
console.warn(`[appState] subscriber for key "${key}" threw:`, error);
userLogger.warn(`[appState] subscriber for key "${key}" threw:`, error);
}
}
}
@@ -40,7 +41,7 @@ function notifyKey(key, value, previousValue) {
try {
callback(snapshot, { key, value, previousValue });
} catch (error) {
console.warn("[appState] global subscriber threw:", error);
userLogger.warn("[appState] global subscriber threw:", error);
}
}
}
@@ -158,7 +159,7 @@ function notifyModal(name, value, previousValue) {
try {
callback(value, previousValue, createSnapshot());
} catch (error) {
console.warn(`[appState] modal subscriber for "${name}" threw:`, error);
userLogger.warn(`[appState] modal subscriber for "${name}" threw:`, error);
}
}
}
+9 -8
View File
@@ -1,4 +1,5 @@
import {
import { userLogger } from "../utils/logger.js";
readUrlHealthFromStorage,
removeUrlHealthFromStorage,
writeUrlHealthToStorage,
@@ -187,7 +188,7 @@ export function readSavedProfilesPayloadFromStorage() {
}
return parsed;
} catch (error) {
console.warn(
userLogger.warn(
"[cache.readSavedProfilesPayloadFromStorage] Failed to parse payload:",
error
);
@@ -210,12 +211,12 @@ function writeSavedProfilesPayloadToStorage(payload) {
error.code === 22 ||
error.code === 1014);
if (isQuotaError) {
console.warn(
userLogger.warn(
"[cache.writeSavedProfilesPayloadToStorage] Storage quota exceeded; keeping in-memory copy only.",
error
);
} else {
console.warn(
userLogger.warn(
"[cache.writeSavedProfilesPayloadToStorage] Failed to persist saved profiles:",
error
);
@@ -232,7 +233,7 @@ export function persistSavedProfiles({ persistActive = true } = {}) {
try {
localStorage.removeItem(SAVED_PROFILES_STORAGE_KEY);
} catch (error) {
console.warn(
userLogger.warn(
"[cache.persistSavedProfiles] Failed to remove empty payload:",
error
);
@@ -349,7 +350,7 @@ export function loadSavedProfilesFromStorage() {
needsRewrite = true;
}
} catch (error) {
console.warn("[cache.loadSavedProfilesFromStorage] Failed to parse payload:", error);
userLogger.warn("[cache.loadSavedProfilesFromStorage] Failed to parse payload:", error);
needsRewrite = true;
}
@@ -493,7 +494,7 @@ export function loadProfileCacheFromStorage() {
});
}
} catch (error) {
console.warn("[cache.loadProfileCacheFromStorage] Failed to parse payload:", error);
userLogger.warn("[cache.loadProfileCacheFromStorage] Failed to parse payload:", error);
}
}
@@ -532,7 +533,7 @@ export function persistProfileCacheToStorage() {
try {
localStorage.removeItem(PROFILE_CACHE_STORAGE_KEY);
} catch (error) {
console.warn(
userLogger.warn(
"[cache.persistProfileCacheToStorage] Failed to clear storage:",
error
);
@@ -543,7 +544,7 @@ export function persistProfileCacheToStorage() {
try {
localStorage.setItem(PROFILE_CACHE_STORAGE_KEY, JSON.stringify(payload));
} catch (error) {
console.warn("[cache.persistProfileCacheToStorage] Failed to persist cache:", error);
userLogger.warn("[cache.persistProfileCacheToStorage] Failed to persist cache:", error);
}
}
+24 -27
View File
@@ -15,6 +15,7 @@ import {
import { getApplication } from "./applicationContext.js";
import { VideoListView } from "./ui/views/VideoListView.js";
import { ALLOW_NSFW_CONTENT } from "./config.js";
import { devLogger, userLogger } from "./utils/logger.js";
const getApp = () => getApplication();
@@ -40,7 +41,7 @@ class SubscriptionsManager {
*/
async loadSubscriptions(userPubkey) {
if (!userPubkey) {
console.warn("[SubscriptionsManager] No pubkey => cannot load subs.");
userLogger.warn("[SubscriptionsManager] No pubkey => cannot load subs.");
return;
}
try {
@@ -59,7 +60,7 @@ class SubscriptionsManager {
events.push(...result);
}
} catch (err) {
console.error(`[SubscriptionsManager] Relay error at ${url}`, err);
userLogger.error(`[SubscriptionsManager] Relay error at ${url}`, err);
}
}
@@ -82,7 +83,7 @@ class SubscriptionsManager {
newest.content
);
} catch (errDecrypt) {
console.error("[SubscriptionsManager] Decryption failed:", errDecrypt);
userLogger.error("[SubscriptionsManager] Decryption failed:", errDecrypt);
this.subscribedPubkeys.clear();
this.subsEventId = null;
this.loaded = true;
@@ -97,7 +98,7 @@ class SubscriptionsManager {
this.loaded = true;
} catch (err) {
console.error("[SubscriptionsManager] Failed to load subs:", err);
userLogger.error("[SubscriptionsManager] Failed to load subs:", err);
}
}
@@ -114,18 +115,16 @@ class SubscriptionsManager {
throw new Error("No user pubkey => cannot addChannel.");
}
if (this.subscribedPubkeys.has(channelHex)) {
console.log("Already subscribed to", channelHex);
devLogger.log("Already subscribed to", channelHex);
return;
}
this.subscribedPubkeys.add(channelHex);
await this.publishSubscriptionList(userPubkey);
this.refreshActiveFeed({ reason: "subscription-update" }).catch((error) => {
if (typeof console !== "undefined") {
console.warn(
"[SubscriptionsManager] Failed to refresh after adding subscription:",
error
);
}
userLogger.warn(
"[SubscriptionsManager] Failed to refresh after adding subscription:",
error
);
});
}
@@ -134,18 +133,16 @@ class SubscriptionsManager {
throw new Error("No user pubkey => cannot removeChannel.");
}
if (!this.subscribedPubkeys.has(channelHex)) {
console.log("Channel not found in subscription list:", channelHex);
devLogger.log("Channel not found in subscription list:", channelHex);
return;
}
this.subscribedPubkeys.delete(channelHex);
await this.publishSubscriptionList(userPubkey);
this.refreshActiveFeed({ reason: "subscription-update" }).catch((error) => {
if (typeof console !== "undefined") {
console.warn(
"[SubscriptionsManager] Failed to refresh after removing subscription:",
error
);
}
userLogger.warn(
"[SubscriptionsManager] Failed to refresh after removing subscription:",
error
);
});
}
@@ -173,7 +170,7 @@ class SubscriptionsManager {
try {
cipherText = await window.nostr.nip04.encrypt(userPubkey, plainStr);
} catch (err) {
console.error("Encryption failed:", err);
userLogger.error("Encryption failed:", err);
throw err;
}
@@ -187,7 +184,7 @@ class SubscriptionsManager {
try {
signedEvent = await window.nostr.signEvent(evt);
} catch (signErr) {
console.error("Failed to sign subscription list:", signErr);
userLogger.error("Failed to sign subscription list:", signErr);
throw signErr;
}
@@ -206,7 +203,7 @@ class SubscriptionsManager {
if (publishError?.relayFailures?.length) {
publishError.relayFailures.forEach(
({ url, error: relayError, reason }) => {
console.error(
userLogger.error(
`[SubscriptionsManager] Subscription list rejected by ${url}: ${reason}`,
relayError || reason
);
@@ -224,7 +221,7 @@ class SubscriptionsManager {
: relayError
? String(relayError)
: "publish failed";
console.warn(
userLogger.warn(
`[SubscriptionsManager] Subscription list not accepted by ${url}: ${reason}`,
relayError
);
@@ -233,7 +230,7 @@ class SubscriptionsManager {
this.subsEventId = signedEvent.id;
const acceptedUrls = publishSummary.accepted.map(({ url }) => url);
console.log(
devLogger.log(
"Subscription list published, event id:",
signedEvent.id,
"accepted relays:",
@@ -348,7 +345,7 @@ class SubscriptionsManager {
this.renderSameGridStyle(result, containerId, { limit, reason });
return result;
} catch (error) {
console.error(
userLogger.error(
"[SubscriptionsManager] Failed to run subscriptions feed:",
error
);
@@ -365,7 +362,7 @@ class SubscriptionsManager {
try {
app.registerSubscriptionsFeed();
} catch (error) {
console.warn(
userLogger.warn(
"[SubscriptionsManager] Failed to register subscriptions feed:",
error
);
@@ -607,7 +604,7 @@ class SubscriptionsManager {
magnet: detail.magnet
})
).catch((error) => {
console.error(
userLogger.error(
"[SubscriptionsManager] Failed to play by event id:",
error
);
@@ -617,7 +614,7 @@ class SubscriptionsManager {
Promise.resolve(
app?.playVideoWithFallback?.({ url: detail.url, magnet: detail.magnet })
).catch((error) => {
console.error(
userLogger.error(
"[SubscriptionsManager] Failed to start playback:",
error
);
+5 -4
View File
@@ -1,3 +1,4 @@
import { userLogger } from "./utils/logger.js";
const STORAGE_KEY = "bitvid:theme";
const FALLBACK_THEME = "dark";
const VALID_THEMES = new Set(["light", "dark"]);
@@ -42,7 +43,7 @@ const readStoredTheme = () => {
const stored = window.localStorage.getItem(STORAGE_KEY);
return normalizeTheme(stored);
} catch (error) {
console.warn("Unable to read stored theme preference:", error);
userLogger.warn("Unable to read stored theme preference:", error);
return null;
}
};
@@ -54,7 +55,7 @@ const persistTheme = (theme) => {
try {
window.localStorage.setItem(STORAGE_KEY, theme);
} catch (error) {
console.warn("Unable to persist theme preference:", error);
userLogger.warn("Unable to persist theme preference:", error);
}
};
@@ -92,7 +93,7 @@ const updateThemeColorMeta = (theme) => {
.trim();
}
} catch (error) {
console.warn("Unable to compute theme color token:", error);
userLogger.warn("Unable to compute theme color token:", error);
}
const fallback = FALLBACK_META_COLORS[theme] || FALLBACK_META_COLORS[FALLBACK_THEME];
@@ -179,7 +180,7 @@ const collectToggleElements = (root = document) => {
}
});
} catch (error) {
console.warn(`Invalid selector for theme toggle: ${selector}`, error);
userLogger.warn(`Invalid selector for theme toggle: ${selector}`, error);
}
});
+7 -6
View File
@@ -2,6 +2,7 @@
import { createModalAccessibility } from "./modalAccessibility.js";
import { Nip71FormManager } from "./nip71FormManager.js";
import { userLogger } from "../../utils/logger.js";
export class UploadModal {
constructor({
@@ -439,7 +440,7 @@ export class UploadModal {
unsubscribe();
}
} catch (error) {
console.warn("[UploadModal] Failed to remove R2 listener", error);
userLogger.warn("[UploadModal] Failed to remove R2 listener", error);
}
});
}
@@ -855,7 +856,7 @@ export class UploadModal {
await this.refreshCloudflareBucketPreview();
}
} catch (error) {
console.error("[UploadModal] Failed to save Cloudflare settings", error);
userLogger.error("[UploadModal] Failed to save Cloudflare settings", error);
}
}
@@ -869,7 +870,7 @@ export class UploadModal {
await this.refreshCloudflareBucketPreview();
}
} catch (error) {
console.error("[UploadModal] Failed to clear Cloudflare settings", error);
userLogger.error("[UploadModal] Failed to clear Cloudflare settings", error);
}
}
@@ -934,7 +935,7 @@ export class UploadModal {
onReset: () => this.resetCloudflareUploadForm()
});
} catch (error) {
console.error("[UploadModal] Cloudflare upload failed", error);
userLogger.error("[UploadModal] Cloudflare upload failed", error);
}
}
@@ -953,7 +954,7 @@ export class UploadModal {
cleanup();
}
} catch (error) {
console.warn("[UploadModal] Failed to remove handler", error);
userLogger.warn("[UploadModal] Failed to remove handler", error);
}
});
this.cleanupHandlers = [];
@@ -966,7 +967,7 @@ export class UploadModal {
unsubscribe();
}
} catch (error) {
console.warn("[UploadModal] Failed to cleanup R2 listener", error);
userLogger.warn("[UploadModal] Failed to cleanup R2 listener", error);
}
});
}
+3 -2
View File
@@ -3,6 +3,7 @@ import { updateVideoCardSourceVisibility } from "../../utils/cardSourceVisibilit
import positionFloatingPanel from "../utils/positionFloatingPanel.js";
import { createFloatingPanelStyles } from "../utils/floatingPanelStyles.js";
import {
import { userLogger } from "../../utils/logger.js";
getPopupOffsetPx,
getPopupViewportPaddingPx,
} from "../../designSystem/metrics.js";
@@ -1566,8 +1567,8 @@ export class VideoCard {
const formatted = this.formatters.formatTimeAgo(normalized);
return typeof formatted === "string" ? formatted : "";
} catch (error) {
if (this.window?.console?.warn) {
this.window.console.warn(
if (this.window?.userLogger?.warn) {
this.window.userLogger.warn(
"[VideoCard] formatTimeAgo formatter threw",
error
);
+11 -3
View File
@@ -2,6 +2,7 @@ import { createModalAccessibility } from "./modalAccessibility.js";
import positionFloatingPanel from "../utils/positionFloatingPanel.js";
import { createFloatingPanelStyles } from "../utils/floatingPanelStyles.js";
import { applyDesignSystemAttributes } from "../../designSystem.js";
import { devLogger } from "../../utils/logger.js";
import {
getPopupOffsetPx,
getPopupViewportPaddingPx,
@@ -12,7 +13,7 @@ export class VideoModal {
removeTrackingScripts,
setGlobalModalState,
document: doc,
logger
logger,
} = {}) {
if (!doc) {
throw new Error("VideoModal requires a document reference.");
@@ -28,7 +29,14 @@ export class VideoModal {
? removeTrackingScripts
: () => {};
this.setGlobalModalState = setGlobalModalState;
this.logger = logger || console;
const providedLogger = logger ?? devLogger;
if (typeof providedLogger === "function") {
this.logger = { log: providedLogger };
} else if (providedLogger && typeof providedLogger.log === "function") {
this.logger = providedLogger;
} else {
this.logger = devLogger;
}
this.eventTarget = new EventTarget();
this.loaded = false;
@@ -101,7 +109,7 @@ export class VideoModal {
this.logger(message, ...args);
return;
}
console.log(message, ...args);
devLogger.log(message, ...args);
}
addEventListener(type, listener, options) {
+2 -1
View File
@@ -1,3 +1,4 @@
import { userLogger } from "../../utils/logger.js";
// NOTE: Keep the Upload, Edit, and Revert modals in lockstep when updating NIP-71 form features.
const REPEATER_KEYS = ["imeta", "text-track", "segment", "t", "p", "r"];
@@ -36,7 +37,7 @@ export class Nip71FormManager {
try {
store.root.removeEventListener("click", store.handlers.click);
} catch (error) {
console.warn("[Nip71FormManager] Failed to detach previous handler", error);
userLogger.warn("[Nip71FormManager] Failed to detach previous handler", error);
}
}
+8 -7
View File
@@ -2,6 +2,7 @@ import { normalizeDesignSystemContext } from "../designSystem.js";
import positionFloatingPanel from "./utils/positionFloatingPanel.js";
import { createFloatingPanelStyles } from "./utils/floatingPanelStyles.js";
import {
import { userLogger } from "../utils/logger.js";
getPopupOffsetPx,
getPopupViewportPaddingPx,
} from "../designSystem/metrics.js";
@@ -460,7 +461,7 @@ export default class MoreMenuController {
await this.clipboard.writeText(valueToCopy);
this.callbacks.showSuccess("Channel npub copied to clipboard!");
} catch (error) {
console.error("Failed to copy npub:", error);
userLogger.error("Failed to copy npub:", error);
this.callbacks.showError("Failed to copy the npub.");
}
break;
@@ -477,7 +478,7 @@ export default class MoreMenuController {
try {
await this.accessControl?.ensureReady?.();
} catch (error) {
console.warn(
userLogger.warn(
"Failed to refresh moderation state before blacklisting:",
error,
);
@@ -521,7 +522,7 @@ export default class MoreMenuController {
});
} catch (error) {
if (this.isDevMode) {
console.warn(
userLogger.warn(
"[Subscriptions] Failed to refresh after blacklist update:",
error,
);
@@ -552,7 +553,7 @@ export default class MoreMenuController {
}
}
} catch (error) {
console.error("Failed to add creator to blacklist:", error);
userLogger.error("Failed to add creator to blacklist:", error);
this.callbacks.showError(
"Failed to update the blacklist. Please try again.",
);
@@ -608,7 +609,7 @@ export default class MoreMenuController {
try {
this.callbacks.onUserBlocksUpdated();
} catch (error) {
console.warn(
userLogger.warn(
"[MoreMenu] Failed to refresh blocked list after update:",
error,
);
@@ -621,14 +622,14 @@ export default class MoreMenuController {
});
} catch (error) {
if (this.isDevMode) {
console.warn(
userLogger.warn(
"[Subscriptions] Failed to refresh after user block update:",
error,
);
}
}
} catch (error) {
console.error("Failed to update personal block list:", error);
userLogger.error("Failed to update personal block list:", error);
const message =
error?.code === "nip04-missing"
? "Your Nostr extension must support NIP-04 to manage private lists."
+34 -35
View File
@@ -6,6 +6,7 @@ import {
MAX_WALLET_DEFAULT_ZAP as CONFIG_MAX_WALLET_DEFAULT_ZAP,
} from "../config.js";
import { normalizeDesignSystemContext } from "../designSystem.js";
import { devLogger, userLogger } from "../utils/logger.js";
const noop = () => {};
@@ -940,7 +941,7 @@ export class ProfileModalController {
try {
this.profileHistoryRenderer = this.createWatchHistoryRenderer(config);
} catch (error) {
console.error(
userLogger.error(
"[profileModal] Failed to create watch history renderer:",
error,
);
@@ -1372,7 +1373,7 @@ export class ProfileModalController {
try {
await this.switchProfile(entry.pubkey, { entry });
} catch (error) {
console.error("Failed to switch profile:", error);
userLogger.error("Failed to switch profile:", error);
} finally {
button.dataset.loading = "false";
button.setAttribute("aria-busy", "false");
@@ -1427,7 +1428,7 @@ export class ProfileModalController {
try {
this.profileHistoryRenderer?.pause();
} catch (error) {
console.warn("[profileModal] Failed to pause history renderer:", error);
userLogger.warn("[profileModal] Failed to pause history renderer:", error);
}
}
@@ -1990,7 +1991,7 @@ export class ProfileModalController {
}
this.populateBlockedList();
} catch (error) {
console.error("Failed to add creator to personal block list:", error);
userLogger.error("Failed to add creator to personal block list:", error);
context.error = error;
context.reason = error?.code || "service-error";
const message =
@@ -2026,7 +2027,7 @@ export class ProfileModalController {
}
if (!targetHex) {
console.warn("No valid pubkey to remove from block list:", candidate);
userLogger.warn("No valid pubkey to remove from block list:", candidate);
return;
}
@@ -2055,7 +2056,7 @@ export class ProfileModalController {
this.populateBlockedList();
} catch (error) {
console.error(
userLogger.error(
"Failed to remove creator from personal block list:",
error,
);
@@ -2111,7 +2112,7 @@ export class ProfileModalController {
renderer.resume();
}
} catch (error) {
console.error(
userLogger.error(
"[profileModal] Failed to populate watch history pane:",
error,
);
@@ -2769,11 +2770,11 @@ export class ProfileModalController {
if (loadError) {
if (loadError?.code === "nostr-unavailable") {
console.info("Moderation lists are still syncing with relays.");
devLogger.info("Moderation lists are still syncing with relays.");
return;
}
console.error("Failed to load admin lists:", loadError);
userLogger.error("Failed to load admin lists:", loadError);
this.showStatus(null);
this.showError("Unable to load moderation lists. Please try again.");
this.clearAdminLists();
@@ -2866,7 +2867,7 @@ export class ProfileModalController {
}
} catch (error) {
preloadError = error;
console.error("Failed to load admin lists before adding moderator:", error);
userLogger.error("Failed to load admin lists before adding moderator:", error);
}
if (preloadError) {
@@ -2970,7 +2971,7 @@ export class ProfileModalController {
}
} catch (error) {
preloadError = error;
console.error("Failed to load admin lists before removing moderator:", error);
userLogger.error("Failed to load admin lists before removing moderator:", error);
}
if (preloadError) {
@@ -3077,7 +3078,7 @@ export class ProfileModalController {
}
} catch (error) {
preloadError = error;
console.error("Failed to load admin lists before updating entries:", error);
userLogger.error("Failed to load admin lists before updating entries:", error);
}
if (preloadError) {
@@ -3162,7 +3163,7 @@ export class ProfileModalController {
this.showError(errorMessage);
}
if (isDevMode && notifyResult?.error) {
console.warn(
userLogger.warn(
"[admin] Failed to send list notification DM:",
notifyResult,
);
@@ -3178,13 +3179,11 @@ export class ProfileModalController {
}
} catch (error) {
context.notificationError = error;
console.error("Failed to send list notification DM:", error);
if (isDevMode) {
console.warn(
"List update succeeded, but DM notification threw an unexpected error.",
error,
);
}
userLogger.error("Failed to send list notification DM:", error);
devLogger.warn(
"List update succeeded, but DM notification threw an unexpected error.",
error,
);
this.notifyAdminError({
listType,
action,
@@ -3468,7 +3467,7 @@ export class ProfileModalController {
targetHex,
});
} catch (refreshError) {
console.warn(
userLogger.warn(
"[ProfileModalController] Failed to refresh videos after blocklist mutation:",
refreshError,
);
@@ -3776,7 +3775,7 @@ export class ProfileModalController {
try {
await this.refreshAdminPaneState();
} catch (error) {
console.error(
userLogger.error(
"Failed to refresh admin pane while opening profile modal:",
error,
);
@@ -3793,7 +3792,7 @@ export class ProfileModalController {
const activeHex = this.normalizeHexPubkey(this.getActivePubkey());
await this.services.userBlocks.ensureLoaded(activeHex);
} catch (error) {
console.warn(
userLogger.warn(
"Failed to refresh user block list while opening profile modal:",
error,
);
@@ -3886,7 +3885,7 @@ export class ProfileModalController {
this.profileHistoryRenderer.destroy();
}
} catch (error) {
console.warn(
userLogger.warn(
"[profileModal] Failed to reset watch history renderer on close:",
error,
);
@@ -3913,7 +3912,7 @@ export class ProfileModalController {
try {
previous.focus();
} catch (error) {
console.warn(
userLogger.warn(
"[profileModal] Failed to restore focus after closing modal:",
error,
);
@@ -3926,7 +3925,7 @@ export class ProfileModalController {
try {
this.callbacks.onClose(this);
} catch (error) {
console.warn(
userLogger.warn(
"[profileModal] onClose callback threw while hiding modal:",
error,
);
@@ -3950,7 +3949,7 @@ export class ProfileModalController {
persistActive: false,
});
} catch (error) {
console.warn(
userLogger.warn(
"[profileModal] Failed to sync saved profiles during login:",
error,
);
@@ -3970,7 +3969,7 @@ export class ProfileModalController {
try {
await this.refreshAdminPaneState();
} catch (error) {
console.warn("Failed to refresh admin pane after login:", error);
userLogger.warn("Failed to refresh admin pane after login:", error);
}
this.populateBlockedList();
@@ -3984,7 +3983,7 @@ export class ProfileModalController {
this.refreshWalletPaneState();
})
.catch((error) => {
console.warn(
userLogger.warn(
"[profileModal] Failed to hydrate deferred login data:",
error,
);
@@ -4004,7 +4003,7 @@ export class ProfileModalController {
persistActive: false,
});
} catch (error) {
console.warn(
userLogger.warn(
"[profileModal] Failed to sync saved profiles during logout:",
error,
);
@@ -4023,7 +4022,7 @@ export class ProfileModalController {
try {
await this.refreshAdminPaneState();
} catch (error) {
console.warn("Failed to refresh admin pane after logout:", error);
userLogger.warn("Failed to refresh admin pane after logout:", error);
}
this.populateBlockedList();
@@ -4041,7 +4040,7 @@ export class ProfileModalController {
persistActive: false,
});
} catch (error) {
console.warn(
userLogger.warn(
"[profileModal] Failed to sync saved profiles after profile update:",
error,
);
@@ -4066,7 +4065,7 @@ export class ProfileModalController {
try {
result = this.services.removeSavedProfile(pubkey) || { removed: false };
} catch (error) {
console.error("Failed to remove saved profile:", error);
userLogger.error("Failed to remove saved profile:", error);
result = { removed: false, error };
}
@@ -4099,7 +4098,7 @@ export class ProfileModalController {
try {
return await hydrate(normalized);
} catch (error) {
console.warn(
userLogger.warn(
`[ProfileModalController] Failed to hydrate wallet settings for ${normalized}:`,
error,
);
@@ -4155,7 +4154,7 @@ export class ProfileModalController {
try {
return this.services.persistSavedProfiles(...args);
} catch (error) {
console.warn(
userLogger.warn(
"[ProfileModalController] Persist saved profiles service threw:",
error,
);
+6 -5
View File
@@ -4,6 +4,7 @@ import {
unsubscribeFromVideoViewCount,
} from "../../viewCounter.js";
import { normalizeDesignSystemContext } from "../../designSystem.js";
import { userLogger } from "../../utils/logger.js";
const EMPTY_VIDEO_LIST_SIGNATURE = "__EMPTY__";
@@ -539,8 +540,8 @@ export class VideoListView {
videoCard.updatePostedAt(Math.floor(resolvedPostedAt));
})
.catch((error) => {
if (this.window?.console?.warn) {
this.window.console.warn(
if (this.window?.userLogger?.warn) {
this.window.userLogger.warn(
"[VideoListView] Failed to resolve posted timestamp:",
error
);
@@ -766,7 +767,7 @@ export class VideoListView {
try {
unsubscribeFromVideoViewCount(entry.pointer, entry.token);
} catch (error) {
console.warn(
userLogger.warn(
`[viewCount] Failed to unsubscribe from stale pointer ${key}:`,
error
);
@@ -920,7 +921,7 @@ export class VideoListView {
this.viewCountSubscriptions.set(pointerInfo.key, entry);
return entry;
} catch (error) {
console.warn("[viewCount] Failed to subscribe to view counter:", error);
userLogger.warn("[viewCount] Failed to subscribe to view counter:", error);
return null;
}
}
@@ -972,7 +973,7 @@ export class VideoListView {
try {
unsubscribeFromVideoViewCount(entry.pointer, entry.token);
} catch (error) {
console.warn(
userLogger.warn(
`[viewCount] Failed to unsubscribe from pointer ${key}:`,
error
);
+15 -22
View File
@@ -4,6 +4,7 @@ import {
pointerKey as derivePointerKey,
} from "../nostr.js";
import { normalizeDesignSystemContext } from "../designSystem.js";
import { devLogger } from "../utils/logger.js";
const noop = () => {};
@@ -22,12 +23,10 @@ function safeInvoke(callback, payload) {
try {
callback(payload);
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryController] onStateChange handler failed:",
error,
);
}
devLogger.warn(
"[watchHistoryController] onStateChange handler failed:",
error,
);
}
}
@@ -104,12 +103,10 @@ export default class WatchHistoryController {
try {
return derivePointerKey(normalized) || "";
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryController] Failed to derive pointer key:",
error,
);
}
devLogger.warn(
"[watchHistoryController] Failed to derive pointer key:",
error,
);
return "";
}
}
@@ -321,12 +318,10 @@ export default class WatchHistoryController {
source: reason,
});
} catch (updateError) {
if (isDevMode) {
console.warn(
"[watchHistoryController] Failed to update local watch history list:",
updateError,
);
}
devLogger.warn(
"[watchHistoryController] Failed to update local watch history list:",
updateError,
);
}
this.showSuccess(
@@ -355,14 +350,12 @@ export default class WatchHistoryController {
try {
const result = this.watchHistoryService.snapshot(undefined, { reason });
return Promise.resolve(result).catch((error) => {
if (isDevMode) {
console.warn(`[${context}] Watch history flush failed:`, error);
devLogger.warn(`[${context] Watch history flush failed:`, error);
}
throw error;
});
} catch (error) {
if (isDevMode) {
console.warn(`[${context}] Failed to queue watch history flush:`, error);
devLogger.warn(`[${context] Failed to queue watch history flush:`, error);
}
return Promise.reject(error);
}
+19 -26
View File
@@ -19,6 +19,7 @@ import {
} from "../payments/lnurl.js";
import { getPlatformLightningAddress } from "../payments/platformAddress.js";
import {
import { devLogger, userLogger } from "../utils/logger.js";
ensureWallet as ensureWalletDefault,
sendPayment as sendPaymentDefault,
} from "../payments/nwcClient.js";
@@ -118,9 +119,7 @@ export default class ZapController {
this.resetFeedback();
this.applyDefaultAmount();
this.preloadLightningMetadata().catch((error) => {
if (isDevMode) {
console.warn("[zap] Preload metadata error:", error);
}
devLogger.warn("[zap] Preload metadata error:", error);
});
}
@@ -238,7 +237,7 @@ export default class ZapController {
Promise.resolve()
.then(() => this.requestWalletPane())
.catch((error) => {
console.error("Failed to open wallet pane:", error);
userLogger.error("Failed to open wallet pane:", error);
});
}
}
@@ -312,9 +311,7 @@ export default class ZapController {
try {
await fetchLightningMetadata(lightningAddress);
} catch (error) {
if (isDevMode) {
console.warn("[zap] Failed to preload creator metadata:", error);
}
devLogger.warn("[zap] Failed to preload creator metadata:", error);
}
}
@@ -333,18 +330,14 @@ export default class ZapController {
});
setCachedPlatformLightningAddress(platformAddress || "");
} catch (error) {
if (isDevMode) {
console.warn("[zap] Failed to load platform Lightning address:", error);
}
devLogger.warn("[zap] Failed to load platform Lightning address:", error);
}
}
if (platformAddress) {
try {
await fetchLightningMetadata(platformAddress);
} catch (error) {
if (isDevMode) {
console.warn("[zap] Failed to preload platform metadata:", error);
}
devLogger.warn("[zap] Failed to preload platform metadata:", error);
}
}
}
@@ -428,7 +421,7 @@ export default class ZapController {
? details.retryAttempt
: undefined,
};
console.error("[zap] Modal zap failure", summary, error);
userLogger.error("[zap] Modal zap failure", summary, error);
};
const lightningAddress = this.getCurrentVideo()?.lightningAddress || "";
@@ -675,17 +668,17 @@ export default class ZapController {
overrideFee,
});
} catch (error) {
console.error(
userLogger.error(
"[zap] Modal lightning context failed",
{
amount,
overrideFee,
commentLength: typeof comment === "string" ? comment.length : undefined,
wallet: {
hasUri: Boolean(settings?.nwcUri),
type:
settings?.type || settings?.name || settings?.client || undefined,
},
amount,
overrideFee,
commentLength: typeof comment === "string" ? comment.length : undefined,
wallet: {
hasUri: Boolean(settings?.nwcUri),
type:
settings?.type || settings?.name || settings?.client || undefined,
},
},
error
);
@@ -720,7 +713,7 @@ export default class ZapController {
if (Array.isArray(shareTracker) && shareTracker.length) {
error.__zapShareTracker = shareTracker;
}
console.error(
userLogger.error(
"[zap] splitAndZap failed",
{
amount,
@@ -818,7 +811,7 @@ export default class ZapController {
const tracker = Array.isArray(error?.__zapShareTracker)
? error.__zapShareTracker
: [];
console.error(
userLogger.error(
"[zap] Modal zap retry failed",
{
shareType: share?.type || "unknown",
@@ -908,7 +901,7 @@ export default class ZapController {
const tracker = Array.isArray(error?.__zapShareTracker)
? error.__zapShareTracker
: [];
console.error(
userLogger.error(
"[zap] Modal zap attempt failed",
{
amount,
+2 -1
View File
@@ -1,5 +1,6 @@
import { createCardObserver } from "./dom/cardObserver.js";
import { safeDecodeURIComponent } from "./utils/safeDecode.js";
import { userLogger } from "./utils/logger.js";
const ROOT_MARGIN = "0px";
const THRESHOLD = 0.25;
@@ -49,7 +50,7 @@ const urlCardObserver = createCardObserver({
try {
state.onCheck({ card, badgeEl, url, eventId });
} catch (err) {
console.warn("[urlHealthObserver] onCheck handler failed", err);
userLogger.warn("[urlHealthObserver] onCheck handler failed", err);
}
},
});
+12 -11
View File
@@ -2,6 +2,7 @@
import { nostrClient } from "./nostr.js";
import { buildBlockListEvent, BLOCK_LIST_IDENTIFIER } from "./nostrEventSchemas.js";
import {
import { userLogger } from "./utils/logger.js";
publishEventToRelays,
assertAnyRelayAccepted,
} from "./nostrPublish.js";
@@ -74,7 +75,7 @@ class UserBlockListManager {
}
if (!window?.nostr?.nip04?.decrypt) {
console.warn(
userLogger.warn(
"[UserBlockList] nip04.decrypt is unavailable; treating block list as empty."
);
this.reset();
@@ -202,7 +203,7 @@ class UserBlockListManager {
try {
decrypted = await window.nostr.nip04.decrypt(normalized, newest.content);
} catch (err) {
console.error("[UserBlockList] Failed to decrypt block list:", err);
userLogger.error("[UserBlockList] Failed to decrypt block list:", err);
this.blockedPubkeys.clear();
return;
}
@@ -225,7 +226,7 @@ class UserBlockListManager {
});
this.blockedPubkeys = new Set(sanitized);
} catch (err) {
console.error("[UserBlockList] Failed to parse block list:", err);
userLogger.error("[UserBlockList] Failed to parse block list:", err);
this.blockedPubkeys.clear();
}
};
@@ -247,12 +248,12 @@ class UserBlockListManager {
} else {
const reason = outcome.reason;
if (reason?.code === "timeout") {
console.warn(
userLogger.warn(
`[UserBlockList] Relay ${reason.relay} timed out while loading block list (${reason.timeoutMs}ms)`
);
} else {
const relay = reason?.relay || reason?.relayUrl;
console.error(
userLogger.error(
`[UserBlockList] Relay error at ${relay}:`,
reason?.error ?? reason
);
@@ -267,7 +268,7 @@ class UserBlockListManager {
await applyEvents(aggregated, { skipIfEmpty: true });
})
.catch((error) => {
console.error("[UserBlockList] background block list refresh failed:", error);
userLogger.error("[UserBlockList] background block list refresh failed:", error);
});
let fastResult = null;
@@ -278,13 +279,13 @@ class UserBlockListManager {
if (error instanceof AggregateError) {
error.errors?.forEach((err) => {
if (err?.code === "timeout") {
console.warn(
userLogger.warn(
`[UserBlockList] Relay ${err.relay} timed out while loading block list (${err.timeoutMs}ms)`
);
}
});
} else {
console.error("[UserBlockList] Fast block list fetch failed:", error);
userLogger.error("[UserBlockList] Fast block list fetch failed:", error);
}
}
}
@@ -299,7 +300,7 @@ class UserBlockListManager {
this.blockEventId = null;
background.catch(() => {});
} catch (error) {
console.error("[UserBlockList] loadBlocks failed:", error);
userLogger.error("[UserBlockList] loadBlocks failed:", error);
this.blockedPubkeys.clear();
} finally {
this.loaded = true;
@@ -431,7 +432,7 @@ class UserBlockListManager {
if (publishError?.relayFailures?.length) {
publishError.relayFailures.forEach(
({ url, error: relayError, reason }) => {
console.error(
userLogger.error(
`[UserBlockList] Block list rejected by ${url}: ${reason}`,
relayError || reason
);
@@ -449,7 +450,7 @@ class UserBlockListManager {
: relayError
? String(relayError)
: "publish failed";
console.warn(
userLogger.warn(
`[UserBlockList] Block list not accepted by ${url}: ${reason}`,
relayError
);
+4 -3
View File
@@ -1,3 +1,4 @@
import { userLogger } from "./logger.js";
// js/utils/storage.js
const URL_HEALTH_STORAGE_PREFIX = "bitvid:urlHealth:";
@@ -21,7 +22,7 @@ export function readUrlHealthFromStorage(eventId) {
return parsed;
}
} catch (err) {
console.warn(`Failed to parse stored URL health for ${eventId}:`, err);
userLogger.warn(`Failed to parse stored URL health for ${eventId}:`, err);
}
removeUrlHealthFromStorage(eventId);
@@ -39,7 +40,7 @@ export function writeUrlHealthToStorage(eventId, entry) {
JSON.stringify(entry)
);
} catch (err) {
console.warn(`Failed to persist URL health for ${eventId}:`, err);
userLogger.warn(`Failed to persist URL health for ${eventId}:`, err);
}
}
@@ -51,6 +52,6 @@ export function removeUrlHealthFromStorage(eventId) {
try {
localStorage.removeItem(getUrlHealthStorageKey(eventId));
} catch (err) {
console.warn(`Failed to remove URL health for ${eventId}:`, err);
userLogger.warn(`Failed to remove URL health for ${eventId}:`, err);
}
}
+12 -11
View File
@@ -17,6 +17,7 @@ import {
VIEW_COUNT_DEDUPE_WINDOW_SECONDS,
} from "./config.js";
import {
import { userLogger } from "./utils/logger.js";
countVideoViewEvents,
listVideoViewEvents,
subscribeVideoViewEvents,
@@ -164,7 +165,7 @@ function normalizePointer(pointer) {
}
}
} catch (error) {
console.warn("[viewCounter] Failed to decode NIP-19 pointer:", error);
userLogger.warn("[viewCounter] Failed to decode NIP-19 pointer:", error);
}
}
}
@@ -279,7 +280,7 @@ function restoreCacheSnapshot() {
});
}
} catch (error) {
console.warn("[viewCounter] Failed to restore cached view counts:", error);
userLogger.warn("[viewCounter] Failed to restore cached view counts:", error);
}
}
@@ -307,7 +308,7 @@ function persistCacheSnapshot() {
};
localStorage.setItem(VIEW_COUNTER_STORAGE_KEY, JSON.stringify(payload));
} catch (error) {
console.warn("[viewCounter] Failed to persist view count cache:", error);
userLogger.warn("[viewCounter] Failed to persist view count cache:", error);
}
}
@@ -376,7 +377,7 @@ function notifyHandlers(key) {
try {
handler(snapshot);
} catch (error) {
console.warn("[viewCounter] View handler threw:", error);
userLogger.warn("[viewCounter] View handler threw:", error);
}
}
}
@@ -468,15 +469,15 @@ async function hydratePointer(key, listeners) {
try {
listResult = await listPromise;
} catch (error) {
console.warn("[viewCounter] Failed to hydrate view events via list:", error);
userLogger.warn("[viewCounter] Failed to hydrate view events via list:", error);
}
try {
countResult = await countPromise;
} catch (error) {
if (error?.name === "AbortError") {
console.warn("[viewCounter] View count hydration aborted:", error);
userLogger.warn("[viewCounter] View count hydration aborted:", error);
} else {
console.warn("[viewCounter] Failed to count view events:", error);
userLogger.warn("[viewCounter] Failed to count view events:", error);
}
}
let mutated = false;
@@ -549,7 +550,7 @@ function ensureLiveSubscription(key, listeners) {
try {
unsubscribe();
} catch (error) {
console.warn("[viewCounter] Failed to unsubscribe from view events:", error);
userLogger.warn("[viewCounter] Failed to unsubscribe from view events:", error);
}
listeners.liveUnsub = null;
if (!listeners.hydrationPromise) {
@@ -558,7 +559,7 @@ function ensureLiveSubscription(key, listeners) {
};
setPointerStatus(key, "live");
} catch (error) {
console.warn("[viewCounter] Failed to open live view subscription:", error);
userLogger.warn("[viewCounter] Failed to open live view subscription:", error);
}
}
@@ -583,7 +584,7 @@ export function subscribeToVideoViewCount(pointerInput, handler, options = {}) {
status: state.status,
});
} catch (error) {
console.warn("[viewCounter] Initial handler invocation threw:", error);
userLogger.warn("[viewCounter] Initial handler invocation threw:", error);
}
ensureHydration(key, listeners);
ensureLiveSubscription(key, listeners);
@@ -617,7 +618,7 @@ export function ingestLocalViewEvent({ event, pointer }) {
notifyHandlers(key);
}
} catch (error) {
console.warn("[viewCounter] Failed to ingest local view event:", error);
userLogger.warn("[viewCounter] Failed to ingest local view event:", error);
}
}
+5 -4
View File
@@ -4,6 +4,7 @@ import { subscriptions } from "./subscriptions.js";
import { getApplication } from "./applicationContext.js";
import { ASSET_VERSION } from "../config/asset-version.js";
import { applyDesignSystemAttributes } from "./designSystem.js";
import { devLogger, userLogger } from "./utils/logger.js";
const TRACKING_SCRIPT_PATTERN = /(?:^|\/)tracking\.js(?:$|\?)/;
@@ -55,7 +56,7 @@ export async function loadView(viewUrl) {
container.appendChild(newScript);
});
} catch (err) {
console.error("View loading error:", err);
userLogger.error("View loading error:", err);
const fallbackMarkup = `
<div class="bv-stack">
<article class="card p-md" data-state="critical">
@@ -92,7 +93,7 @@ export const viewInitRegistry = {
}
},
explore: () => {
console.log("Explore view loaded.");
devLogger.log("Explore view loaded.");
},
history: async () => {
try {
@@ -101,7 +102,7 @@ export const viewInitRegistry = {
await module.initHistoryView();
}
} catch (error) {
console.error("Failed to initialize history view:", error);
userLogger.error("Failed to initialize history view:", error);
}
},
@@ -111,7 +112,7 @@ export const viewInitRegistry = {
* which loads subs if needed and renders the video grid in #subscriptionsVideoList
*/
subscriptions: async () => {
console.log("Subscriptions view loaded.");
devLogger.log("Subscriptions view loaded.");
const app = getApplication();
if (!app?.pubkey) {
+10 -20
View File
@@ -1,5 +1,7 @@
// js/watchHistoryDebug.js
import { devLogger } from "./utils/logger.js";
const WATCH_HISTORY_DEBUG_STORAGE_KEY =
"bitvid:debug:watch-history";
@@ -168,36 +170,24 @@ export function logWatchHistoryDebug(namespace, level, message, details) {
return;
}
const scopeConsole =
(globalScope && globalScope.console) || (typeof console !== "undefined" ? console : null);
if (!scopeConsole) {
return;
}
const methodName =
typeof level === "string" && level && typeof scopeConsole[level] === "function"
typeof level === "string" && level && typeof devLogger[level] === "function"
? level
: typeof scopeConsole.info === "function"
? "info"
: "log";
: typeof devLogger.info === "function"
? "info"
: "log";
const prefix = namespace ? `[${namespace}] ${message}` : message;
try {
if (details && typeof details === "object") {
scopeConsole[methodName](prefix, details);
devLogger[methodName](prefix, details);
} else {
scopeConsole[methodName](prefix);
devLogger[methodName](prefix);
}
} catch (error) {
try {
if (details && typeof details === "object") {
scopeConsole.log(prefix, details);
} else {
scopeConsole.log(prefix);
}
} catch (fallbackError) {
// Swallow logging errors entirely.
if (typeof devLogger.log === "function") {
devLogger.log(prefix);
}
}
}
+138 -185
View File
@@ -16,6 +16,7 @@ import {
} from "./constants.js";
import { isDevMode } from "./config.js";
import { getApplication } from "./applicationContext.js";
import { devLogger, userLogger } from "./utils/logger.js";
const SESSION_STORAGE_KEY = "bitvid:watch-history:session:v1";
const SESSION_STORAGE_VERSION = 1;
@@ -43,12 +44,10 @@ function resolveFlagEnabled() {
return getWatchHistoryV2Enabled() === true;
}
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to read FEATURE_WATCH_HISTORY_V2 flag:",
error,
);
}
devLogger.warn(
"[watchHistoryService] Failed to read FEATURE_WATCH_HISTORY_V2 flag:",
error,
);
}
return FEATURE_WATCH_HISTORY_V2 === true;
}
@@ -72,12 +71,10 @@ function getLoggedInActorKey() {
return normalizeActorKey(normalized);
}
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to normalize app login pubkey:",
error
);
}
devLogger.warn(
"[watchHistoryService] Failed to normalize app login pubkey:",
error
);
}
}
@@ -168,9 +165,7 @@ function getSessionStorage() {
return window.sessionStorage;
}
} catch (error) {
if (isDevMode) {
console.warn("[watchHistoryService] sessionStorage unavailable:", error);
}
devLogger.warn("[watchHistoryService] sessionStorage unavailable:", error);
}
return null;
}
@@ -181,9 +176,7 @@ function getLocalStorage() {
return window.localStorage;
}
} catch (error) {
if (isDevMode) {
console.warn("[watchHistoryService] localStorage unavailable:", error);
}
devLogger.warn("[watchHistoryService] localStorage unavailable:", error);
}
return null;
}
@@ -205,12 +198,10 @@ function ensureMetadataPreference() {
state.metadata.preference = stored === "true";
}
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to read metadata preference:",
error,
);
}
devLogger.warn(
"[watchHistoryService] Failed to read metadata preference:",
error,
);
state.metadata.preference = true;
}
return state.metadata.preference;
@@ -228,12 +219,10 @@ function persistMetadataPreference(value) {
storage.setItem(METADATA_PREFERENCE_KEY, "false");
}
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to persist metadata preference:",
error,
);
}
devLogger.warn(
"[watchHistoryService] Failed to persist metadata preference:",
error,
);
}
}
@@ -315,12 +304,10 @@ function restoreMetadataCache() {
try {
raw = storage.getItem(METADATA_STORAGE_KEY);
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to read metadata cache:",
error,
);
}
devLogger.warn(
"[watchHistoryService] Failed to read metadata cache:",
error,
);
return;
}
@@ -332,21 +319,17 @@ function restoreMetadataCache() {
try {
parsed = JSON.parse(raw);
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to parse metadata cache:",
error,
);
}
devLogger.warn(
"[watchHistoryService] Failed to parse metadata cache:",
error,
);
try {
storage.removeItem(METADATA_STORAGE_KEY);
} catch (cleanupError) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to clear corrupt metadata cache:",
cleanupError,
);
}
devLogger.warn(
"[watchHistoryService] Failed to clear corrupt metadata cache:",
cleanupError,
);
}
return;
}
@@ -355,12 +338,10 @@ function restoreMetadataCache() {
try {
storage.removeItem(METADATA_STORAGE_KEY);
} catch (cleanupError) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to clear outdated metadata cache:",
cleanupError,
);
}
devLogger.warn(
"[watchHistoryService] Failed to clear outdated metadata cache:",
cleanupError,
);
}
return;
}
@@ -428,12 +409,10 @@ function persistMetadataCache() {
try {
storage.removeItem(METADATA_STORAGE_KEY);
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to clear metadata cache:",
error,
);
}
devLogger.warn(
"[watchHistoryService] Failed to clear metadata cache:",
error,
);
}
return;
}
@@ -449,12 +428,10 @@ function persistMetadataCache() {
try {
storage.setItem(METADATA_STORAGE_KEY, JSON.stringify(payload));
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to persist metadata cache:",
error,
);
}
devLogger.warn(
"[watchHistoryService] Failed to persist metadata cache:",
error,
);
}
}
@@ -550,12 +527,10 @@ function emit(eventName, payload) {
try {
callback(payload);
} catch (error) {
if (isDevMode) {
console.warn(
`[watchHistoryService] Listener for ${eventName} failed:`,
error
);
}
devLogger.warn(
`[watchHistoryService] Listener for ${eventName} failed:`,
error
);
}
}
}
@@ -566,12 +541,10 @@ function emit(eventName, payload) {
try {
callback({ event: eventName, payload });
} catch (error) {
if (isDevMode) {
console.warn(
`[watchHistoryService] Wildcard listener error for ${eventName}:`,
error
);
}
devLogger.warn(
`[watchHistoryService] Wildcard listener error for ${eventName}:`,
error
);
}
}
}
@@ -582,12 +555,10 @@ function emit(eventName, payload) {
const evt = new CustomEvent("bitvid:watchHistory", { detail });
window.dispatchEvent(evt);
} catch (error) {
if (isDevMode) {
console.warn(
`[watchHistoryService] Failed to dispatch window event for ${eventName}:`,
error
);
}
devLogger.warn(
`[watchHistoryService] Failed to dispatch window event for ${eventName}:`,
error
);
}
}
}
@@ -639,9 +610,7 @@ function restoreQueueState() {
try {
raw = storage.getItem(SESSION_STORAGE_KEY);
} catch (error) {
if (isDevMode) {
console.warn("[watchHistoryService] Failed to read session cache:", error);
}
devLogger.warn("[watchHistoryService] Failed to read session cache:", error);
return;
}
@@ -653,18 +622,14 @@ function restoreQueueState() {
try {
parsed = JSON.parse(raw);
} catch (error) {
if (isDevMode) {
console.warn("[watchHistoryService] Failed to parse session cache:", error);
}
devLogger.warn("[watchHistoryService] Failed to parse session cache:", error);
try {
storage.removeItem(SESSION_STORAGE_KEY);
} catch (cleanupError) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to clear corrupt session cache:",
cleanupError
);
}
devLogger.warn(
"[watchHistoryService] Failed to clear corrupt session cache:",
cleanupError
);
}
return;
}
@@ -673,12 +638,10 @@ function restoreQueueState() {
try {
storage.removeItem(SESSION_STORAGE_KEY);
} catch (cleanupError) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to clear outdated session cache:",
cleanupError
);
}
devLogger.warn(
"[watchHistoryService] Failed to clear outdated session cache:",
cleanupError
);
}
return;
}
@@ -770,12 +733,10 @@ function persistQueueState() {
try {
storage.removeItem(SESSION_STORAGE_KEY);
} catch (error) {
if (isDevMode) {
console.warn(
"[watchHistoryService] Failed to clear empty session cache:",
error
);
}
devLogger.warn(
"[watchHistoryService] Failed to clear empty session cache:",
error
);
}
return;
}
@@ -783,9 +744,7 @@ function persistQueueState() {
try {
storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(payload));
} catch (error) {
if (isDevMode) {
console.warn("[watchHistoryService] Failed to persist session cache:", error);
}
devLogger.warn("[watchHistoryService] Failed to persist session cache:", error);
}
}
@@ -978,18 +937,18 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
const viewResult = await nostrClient.recordVideoView(pointerInput, recordOptions);
console.info(
devLogger.info(
"[watchHistoryService] Video view recorded. Preparing watch list update.",
{
pointer: pointerInput,
createdAt,
hasMetadata: !!metadata,
pointer: pointerInput,
createdAt,
hasMetadata: !!metadata,
}
);
const pointer = normalizePointerInput(pointerInput);
if (!pointer) {
console.warn(
userLogger.warn(
"[watchHistoryService] Skipping watch list update because pointer normalization failed.",
{ pointerInput }
);
@@ -1004,7 +963,7 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
"";
const actorKey = normalizeActorKey(actorCandidate);
if (!actorKey) {
console.warn(
userLogger.warn(
"[watchHistoryService] Unable to resolve actor for watch list update.",
{ actorCandidate }
);
@@ -1013,7 +972,7 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
const queue = ensureQueue(actorKey);
if (!queue) {
console.warn(
userLogger.warn(
"[watchHistoryService] Failed to resolve queue for actor.",
{ actorKey }
);
@@ -1024,7 +983,7 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
const normalizedPointer = normalizePointerInput(pointer);
if (!normalizedPointer) {
console.warn(
userLogger.warn(
"[watchHistoryService] Pointer normalization failed during queue preparation.",
{ pointerInput }
);
@@ -1064,14 +1023,14 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
}
const key = pointerKey(normalizedPointer);
console.info(
devLogger.info(
"[watchHistoryService] Watch list process triggered by video view.",
{
actor: actorKey,
pointerKey: key,
watchedAt: normalizedPointer.watchedAt,
sessionEvent: normalizedPointer.session === true,
remoteSyncEnabled: remoteEnabled,
actor: actorKey,
pointerKey: key,
watchedAt: normalizedPointer.watchedAt,
sessionEvent: normalizedPointer.session === true,
remoteSyncEnabled: remoteEnabled,
}
);
@@ -1084,7 +1043,7 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
}
if (!key) {
console.warn(
userLogger.warn(
"[watchHistoryService] Pointer key generation failed. Skipping queue update.",
{ pointer: normalizedPointer }
);
@@ -1114,12 +1073,12 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
queue.throttle.set(key, now);
persistQueueState();
notifyQueueChange(actorKey);
console.info(
devLogger.info(
"[watchHistoryService] Updated existing watch list entry.",
{
actor: actorKey,
pointerKey: key,
watchedAt: existing.pointer.watchedAt,
actor: actorKey,
pointerKey: key,
watchedAt: existing.pointer.watchedAt,
}
);
return viewResult;
@@ -1127,11 +1086,9 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
if (throttled) {
queue.throttle.set(key, now);
if (isDevMode) {
console.info(
`[watchHistoryService] Throttled pointer ${key} for actor ${actorKey}.`
);
}
devLogger.info(
`[watchHistoryService] Throttled pointer ${key} for actor ${actorKey}.`
);
return viewResult;
}
@@ -1144,17 +1101,17 @@ async function publishView(pointerInput, createdAt, metadata = {}) {
persistQueueState();
notifyQueueChange(actorKey);
console.info(
devLogger.info(
"[watchHistoryService] Added pointer to pending watch list snapshot queue.",
{
actor: actorKey,
pointerKey: key,
queueSize: queue.items.size,
actor: actorKey,
pointerKey: key,
queueSize: queue.items.size,
}
);
if (!remoteEnabled) {
console.info(
devLogger.info(
"[watchHistoryService] Watch history sync unavailable for this actor; retaining pointer in local session queue only.",
{
actor: actorKey,
@@ -1175,12 +1132,12 @@ async function snapshot(items, options = {}) {
}
if (!isFeatureEnabled(actorKey)) {
console.info(
devLogger.info(
"[watchHistoryService] Snapshot skipped because watch history sync is unavailable for this actor.",
{
actor: actorKey,
requestedItems: Array.isArray(items) ? items.length : 0,
reason,
actor: actorKey,
requestedItems: Array.isArray(items) ? items.length : 0,
reason,
}
);
return { ok: true, skipped: true, reason: "feature-disabled" };
@@ -1207,13 +1164,13 @@ async function snapshot(items, options = {}) {
const queue = ensureQueue(actorKey);
console.info(
devLogger.info(
"[watchHistoryService] Initiating watch list snapshot publish.",
{
actor: actorKey,
reason,
itemCount: payloadItems.length,
queued: queue?.items?.size ?? 0,
actor: actorKey,
reason,
itemCount: payloadItems.length,
queued: queue?.items?.size ?? 0,
}
);
@@ -1227,14 +1184,14 @@ async function snapshot(items, options = {}) {
}
);
console.info(
devLogger.info(
"[watchHistoryService] Watch list snapshot publish completed.",
{
actor: actorKey,
reason,
success: !!publishResult?.ok,
snapshotId: publishResult?.snapshotId || null,
retryable: !!publishResult?.retryable,
actor: actorKey,
reason,
success: !!publishResult?.ok,
snapshotId: publishResult?.snapshotId || null,
retryable: !!publishResult?.retryable,
}
);
@@ -1264,20 +1221,18 @@ async function snapshot(items, options = {}) {
await updateFingerprintCache(actorKey, publishResult.items || payloadItems);
emit("snapshot-complete", { actor: actorKey, reason, result: publishResult });
console.info(
devLogger.info(
"[watchHistoryService] Watch list snapshot processed and fingerprint cache updated.",
{
actor: actorKey,
reason,
fingerprintUpdated: true,
actor: actorKey,
reason,
fingerprintUpdated: true,
}
);
return publishResult;
})()
.catch((error) => {
if (isDevMode) {
console.warn("[watchHistoryService] Snapshot failed:", error);
}
devLogger.warn("[watchHistoryService] Snapshot failed:", error);
throw error;
})
.finally(() => {
@@ -1305,9 +1260,7 @@ function scheduleWatchHistoryRefresh(actorKey, cacheEntry = {}) {
return latest?.items || [];
})
.catch((error) => {
if (isDevMode) {
console.warn("[watchHistoryService] Failed to load watch history:", error);
}
devLogger.warn("[watchHistoryService] Failed to load watch history:", error);
throw error;
})
.finally(() => {
@@ -1317,9 +1270,9 @@ function scheduleWatchHistoryRefresh(actorKey, cacheEntry = {}) {
}
});
console.info("[watchHistoryService] Triggered nostr watch list refresh.", {
devLogger.info("[watchHistoryService] Triggered nostr watch list refresh.", {
actor: actorKey,
});
});
const baseEntry = cacheEntry && typeof cacheEntry === "object" ? cacheEntry : {};
state.fingerprintCache.set(actorKey, {
@@ -1348,11 +1301,11 @@ async function loadLatest(actorInput, options = {}) {
restoreQueueState();
}
const items = collectQueueItems(actorKey);
console.info(
devLogger.info(
"[watchHistoryService] loadLatest returning local-only watch history queue.",
{
actor: actorKey,
itemCount: items.length,
actor: actorKey,
itemCount: items.length,
}
);
return items;
@@ -1360,12 +1313,12 @@ async function loadLatest(actorInput, options = {}) {
const now = Date.now();
const cacheEntry = state.fingerprintCache.get(actorKey);
console.info(
devLogger.info(
"[watchHistoryService] loadLatest invoked.",
{
actor: actorKey,
cacheHasItems: Array.isArray(cacheEntry?.items),
cacheExpiresAt: cacheEntry?.expiresAt || null,
actor: actorKey,
cacheHasItems: Array.isArray(cacheEntry?.items),
cacheExpiresAt: cacheEntry?.expiresAt || null,
}
);
const hasCachedItems = Array.isArray(cacheEntry?.items);
@@ -1375,29 +1328,29 @@ async function loadLatest(actorInput, options = {}) {
cacheEntry.expiresAt > now;
if (cacheIsFresh) {
console.info(
devLogger.info(
"[watchHistoryService] Returning cached watch list items.",
{
actor: actorKey,
itemCount: cacheEntry.items.length,
actor: actorKey,
itemCount: cacheEntry.items.length,
}
);
return cacheEntry.items;
}
if (cacheEntry?.promise) {
console.info(
devLogger.info(
"[watchHistoryService] Awaiting in-flight watch list refresh.",
{
actor: actorKey,
actor: actorKey,
}
);
if (allowStale && hasCachedItems) {
console.info(
devLogger.info(
"[watchHistoryService] Returning stale watch list items while refresh completes.",
{
actor: actorKey,
itemCount: cacheEntry.items.length,
actor: actorKey,
itemCount: cacheEntry.items.length,
}
);
return cacheEntry.items;
@@ -1412,11 +1365,11 @@ async function loadLatest(actorInput, options = {}) {
const refreshPromise = scheduleWatchHistoryRefresh(actorKey, cacheEntry);
refreshPromise.catch(() => {});
console.info(
devLogger.info(
"[watchHistoryService] Returning stale watch list items while refresh is pending.",
{
actor: actorKey,
itemCount: cacheEntry?.items?.length || 0,
actor: actorKey,
itemCount: cacheEntry?.items?.length || 0,
}
);
+5 -4
View File
@@ -3,6 +3,7 @@
import WebTorrent from "./webtorrent.min.js";
import { WSS_TRACKERS } from "./constants.js";
import { safeDecodeURIComponent } from "./utils/safeDecode.js";
import { devLogger, userLogger } from "./utils/logger.js";
const DEFAULT_PROBE_TRACKERS = Object.freeze([...WSS_TRACKERS]);
@@ -288,7 +289,7 @@ export class TorrentClient {
}
log(msg) {
console.log(msg);
devLogger.log(msg);
}
async isBrave() {
@@ -608,20 +609,20 @@ export class TorrentClient {
err.message.includes("CORS") ||
err.message.includes("Access-Control-Allow-Origin")
) {
console.warn(
userLogger.warn(
"CORS warning detected. Attempting to remove the failing webseed/tracker."
);
if (torrent._opts?.urlList?.length) {
torrent._opts.urlList = torrent._opts.urlList.filter((url) => {
return !url.includes("distribution.bbb3d.renderfarming.net");
});
console.warn("Cleaned up webseeds =>", torrent._opts.urlList);
userLogger.warn("Cleaned up webseeds =>", torrent._opts.urlList);
}
if (torrent._opts?.announce?.length) {
torrent._opts.announce = torrent._opts.announce.filter((url) => {
return !url.includes("fastcast.nz");
});
console.warn("Cleaned up trackers =>", torrent._opts.announce);
userLogger.warn("Cleaned up trackers =>", torrent._opts.announce);
}
}
}