refactor(logging): route frontend console calls through the logger
TRACES: | DR-204 484 ungated `console.*` calls across 63 non-test frontend files shipped to end users with no way to turn them off. Mechanical substitution, no control flow, error handling or message semantics changed: console.log / console.debug -> log.debug console.info -> log.info console.warn -> log.warn console.error -> log.error Hand-written `"[Scope] …"` prefixes are dropped where the logger's scope now carries them; scope names that already existed are preserved verbatim (`[Auth]`, `[VideoPlayer]`, `[PiP]`, …) and inferred from the filename where a file had none. `src/routes/player/[id]/+page.svelte` keeps its `NextEpisode` and `AutoPlay` sub-scopes as separate loggers rather than flattening them into the page scope. `grep -rn 'console\.' src/` now matches nothing outside the tests and the facade itself.
This commit is contained in:
+42
-39
@@ -13,6 +13,9 @@ import type { User, AuthResult } from "$lib/api/types";
|
||||
import type { Session, AuthServerInfo as ServerInfo } from "$lib/api/bindings";
|
||||
import { connectivity } from "./connectivity";
|
||||
import { getDeviceId, clearCache as clearDeviceIdCache } from "$lib/services/deviceId";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("Auth");
|
||||
|
||||
interface AuthState {
|
||||
isAuthenticated: boolean;
|
||||
@@ -70,7 +73,7 @@ function createAuthStore() {
|
||||
|
||||
try {
|
||||
unlistenSessionVerified = await listen<{ user: User }>("auth:session-verified", (event) => {
|
||||
console.log("[Auth] Session verified:", event.payload.user.name);
|
||||
log.debug("Session verified:", event.payload.user.name);
|
||||
update((s) => ({
|
||||
...s,
|
||||
sessionVerified: true,
|
||||
@@ -80,12 +83,12 @@ function createAuthStore() {
|
||||
}));
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("[Auth] Failed to listen to session-verified event:", e);
|
||||
log.error("Failed to listen to session-verified event:", e);
|
||||
}
|
||||
|
||||
try {
|
||||
unlistenNeedsReauth = await listen<{ reason: string }>("auth:needs-reauth", (event) => {
|
||||
console.log("[Auth] Session needs re-authentication:", event.payload.reason);
|
||||
log.debug("Session needs re-authentication:", event.payload.reason);
|
||||
update((s) => ({
|
||||
...s,
|
||||
sessionVerified: false,
|
||||
@@ -95,17 +98,17 @@ function createAuthStore() {
|
||||
}));
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("[Auth] Failed to listen to needs-reauth event:", e);
|
||||
log.error("Failed to listen to needs-reauth event:", e);
|
||||
}
|
||||
|
||||
try {
|
||||
unlistenNetworkError = await listen<{ message: string }>("auth:network-error", (event) => {
|
||||
console.log("[Auth] Network error during verification:", event.payload.message);
|
||||
log.debug("Network error during verification:", event.payload.message);
|
||||
// Network errors don't trigger re-auth - just log them
|
||||
update((s) => ({ ...s, isVerifying: false }));
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("[Auth] Failed to listen to network-error event:", e);
|
||||
log.error("Failed to listen to network-error event:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +147,7 @@ function createAuthStore() {
|
||||
void (async () => {
|
||||
try {
|
||||
const securityStatus = await commands.storageGetSecurityStatus();
|
||||
console.log("[Auth] Security status:", securityStatus);
|
||||
log.debug("Security status:", securityStatus);
|
||||
if (!securityStatus.usingKeyring) {
|
||||
update((s) => ({
|
||||
...s,
|
||||
@@ -153,17 +156,17 @@ function createAuthStore() {
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[Auth] Failed to get security status:", error);
|
||||
log.warn("Failed to get security status:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
// Initialize auth manager and get session
|
||||
console.log("[Auth] Initializing auth manager...");
|
||||
log.debug("Initializing auth manager...");
|
||||
const session = await commands.authInitialize();
|
||||
console.log("[Auth] Session retrieval result:", session ? "Session found" : "No session found");
|
||||
log.debug("Session retrieval result:", session ? "Session found" : "No session found");
|
||||
|
||||
if (session) {
|
||||
console.log("[Auth] Restoring session for user:", session.username, "on server:", session.serverUrl);
|
||||
log.debug("Restoring session for user:", session.username, "on server:", session.serverUrl);
|
||||
|
||||
// Create RepositoryClient for cache-first access. This IS required before
|
||||
// we mark authenticated — the first screen (library overview) reads
|
||||
@@ -184,9 +187,9 @@ function createAuthStore() {
|
||||
session.userId,
|
||||
deviceId
|
||||
);
|
||||
console.log("[Auth] Rust player configured for automatic playback reporting");
|
||||
log.debug("Rust player configured for automatic playback reporting");
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to configure Rust player:", error);
|
||||
log.error("Failed to configure Rust player:", error);
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -205,7 +208,7 @@ function createAuthStore() {
|
||||
});
|
||||
|
||||
// Start connectivity monitoring early to avoid appearing offline on startup
|
||||
console.log("[Auth] Starting early connectivity monitoring...");
|
||||
log.debug("Starting early connectivity monitoring...");
|
||||
connectivity.startMonitoring(session.serverUrl, {
|
||||
onServerReconnected: () => {
|
||||
// Retry session verification when server becomes reachable
|
||||
@@ -214,10 +217,10 @@ function createAuthStore() {
|
||||
// Lazy import to avoid an auth <-> offlineCatalog import cycle.
|
||||
import("$lib/services/offlineCatalog")
|
||||
.then((m) => m.onReconnected())
|
||||
.catch((err) => console.warn("[Auth] Catalog reconnect failed:", err));
|
||||
.catch((err) => log.warn("Catalog reconnect failed:", err));
|
||||
},
|
||||
}).catch((error) => {
|
||||
console.error("[Auth] Failed to start connectivity monitoring:", error);
|
||||
log.error("Failed to start connectivity monitoring:", error);
|
||||
});
|
||||
|
||||
// Start background session verification — fire-and-forget. This is
|
||||
@@ -228,14 +231,14 @@ function createAuthStore() {
|
||||
try {
|
||||
const verifyDeviceId = await getDeviceId();
|
||||
await commands.authStartVerification(verifyDeviceId);
|
||||
console.log("[Auth] Background verification started");
|
||||
log.debug("Background verification started");
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to start verification:", error);
|
||||
log.error("Failed to start verification:", error);
|
||||
}
|
||||
})();
|
||||
} else {
|
||||
// No stored session
|
||||
console.log("[Auth] No active session found");
|
||||
log.debug("No active session found");
|
||||
set({
|
||||
isAuthenticated: false,
|
||||
isLoading: false,
|
||||
@@ -250,7 +253,7 @@ function createAuthStore() {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to initialize:", error);
|
||||
log.error("Failed to initialize:", error);
|
||||
update((s) => ({
|
||||
...s,
|
||||
isLoading: false,
|
||||
@@ -269,15 +272,15 @@ function createAuthStore() {
|
||||
update((s) => ({ ...s, isLoading: true, error: null }));
|
||||
|
||||
try {
|
||||
console.log("[Auth] Connecting to server:", serverUrl);
|
||||
log.debug("Connecting to server:", serverUrl);
|
||||
const serverInfo = await commands.authConnectToServer(serverUrl);
|
||||
console.log("[Auth] Connected to server:", serverInfo.name, serverInfo.version);
|
||||
console.log("[Auth] Normalized URL:", serverInfo.normalizedUrl);
|
||||
log.debug("Connected to server:", serverInfo.name, serverInfo.version);
|
||||
log.debug("Normalized URL:", serverInfo.normalizedUrl);
|
||||
|
||||
update((s) => ({ ...s, isLoading: false }));
|
||||
return serverInfo;
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to connect to server:", error);
|
||||
log.error("Failed to connect to server:", error);
|
||||
update((s) => ({
|
||||
...s,
|
||||
isLoading: false,
|
||||
@@ -297,11 +300,11 @@ function createAuthStore() {
|
||||
|
||||
try {
|
||||
const deviceId = await getDeviceId();
|
||||
console.log("[Auth] Logging in as:", username);
|
||||
log.debug("Logging in as:", username);
|
||||
|
||||
const authResult = await commands.authLogin(serverUrl, username, password, deviceId);
|
||||
|
||||
console.log("[Auth] Login successful:", authResult.user);
|
||||
log.debug("Login successful:", authResult.user);
|
||||
|
||||
// Save to storage
|
||||
await commands.storageSaveServer(authResult.serverId, serverName, serverUrl, null);
|
||||
@@ -340,9 +343,9 @@ function createAuthStore() {
|
||||
authResult.user.id,
|
||||
playerDeviceId
|
||||
);
|
||||
console.log("[Auth] Rust player configured for playback reporting");
|
||||
log.debug("Rust player configured for playback reporting");
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to configure Rust player:", error);
|
||||
log.error("Failed to configure Rust player:", error);
|
||||
}
|
||||
|
||||
// Update state
|
||||
@@ -364,12 +367,12 @@ function createAuthStore() {
|
||||
const verifyDeviceId = await getDeviceId();
|
||||
await commands.authStartVerification(verifyDeviceId);
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to start verification:", error);
|
||||
log.error("Failed to start verification:", error);
|
||||
}
|
||||
|
||||
return authResult;
|
||||
} catch (error) {
|
||||
console.error("[Auth] Login failed:", error);
|
||||
log.error("Login failed:", error);
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
update((s) => ({ ...s, isLoading: false, error: errorMessage }));
|
||||
throw error;
|
||||
@@ -384,11 +387,11 @@ function createAuthStore() {
|
||||
|
||||
try {
|
||||
const deviceId = await getDeviceId();
|
||||
console.log("[Auth] Re-authenticating...");
|
||||
log.debug("Re-authenticating...");
|
||||
|
||||
const authResult = await commands.authReauthenticate(password, deviceId);
|
||||
|
||||
console.log("[Auth] Re-authentication successful");
|
||||
log.debug("Re-authentication successful");
|
||||
|
||||
// Update storage
|
||||
await commands.storageSaveUser(
|
||||
@@ -417,7 +420,7 @@ function createAuthStore() {
|
||||
playerDeviceId
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to reconfigure player:", error);
|
||||
log.error("Failed to reconfigure player:", error);
|
||||
}
|
||||
|
||||
// Update state
|
||||
@@ -432,7 +435,7 @@ function createAuthStore() {
|
||||
|
||||
return authResult;
|
||||
} catch (error) {
|
||||
console.error("[Auth] Re-authentication failed:", error);
|
||||
log.error("Re-authentication failed:", error);
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
update((s) => ({ ...s, isLoading: false, error: errorMessage }));
|
||||
throw error;
|
||||
@@ -456,7 +459,7 @@ function createAuthStore() {
|
||||
try {
|
||||
await commands.playerDisableJellyfin();
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to disable player reporting:", error);
|
||||
log.error("Failed to disable player reporting:", error);
|
||||
}
|
||||
|
||||
// Clear repository
|
||||
@@ -481,7 +484,7 @@ function createAuthStore() {
|
||||
// Clear device ID cache on logout
|
||||
clearDeviceIdCache();
|
||||
} catch (error) {
|
||||
console.error("[Auth] Logout error (continuing anyway):", error);
|
||||
log.error("Logout error (continuing anyway):", error);
|
||||
set(initialState);
|
||||
clearDeviceIdCache();
|
||||
}
|
||||
@@ -501,7 +504,7 @@ function createAuthStore() {
|
||||
try {
|
||||
return await commands.authGetSession();
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to get current session:", error);
|
||||
log.error("Failed to get current session:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -536,10 +539,10 @@ function createAuthStore() {
|
||||
async function retryVerification() {
|
||||
try {
|
||||
const deviceId = await getDeviceId();
|
||||
console.log("[Auth] Retrying session verification after reconnection");
|
||||
log.debug("Retrying session verification after reconnection");
|
||||
await commands.authStartVerification(deviceId);
|
||||
} catch (error) {
|
||||
console.error("[Auth] Failed to retry verification:", error);
|
||||
log.error("Failed to retry verification:", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ import { writable, derived } from "svelte/store";
|
||||
import { browser } from "$app/environment";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { commands } from "$lib/api/bindings";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("ConnectivityStore");
|
||||
|
||||
export interface ConnectivityState {
|
||||
/** Browser's navigator.onLine status */
|
||||
@@ -76,7 +79,7 @@ function createConnectivityStore() {
|
||||
update((s) => ({ ...s, isOnline: true }));
|
||||
// Device regained network — ask the backend to re-verify the server now.
|
||||
checkServerReachable().catch((err) => {
|
||||
console.debug("[ConnectivityStore] Recheck after 'online' failed:", err);
|
||||
log.debug("Recheck after 'online' failed:", err);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -85,7 +88,7 @@ function createConnectivityStore() {
|
||||
// decide whether the server is actually reachable.
|
||||
update((s) => ({ ...s, isOnline: false }));
|
||||
checkServerReachable().catch((err) => {
|
||||
console.debug("[ConnectivityStore] Recheck after 'offline' failed:", err);
|
||||
log.debug("Recheck after 'offline' failed:", err);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -132,7 +135,7 @@ function createConnectivityStore() {
|
||||
|
||||
return isReachable;
|
||||
} catch (error) {
|
||||
console.error("[ConnectivityStore] Failed to check server:", error);
|
||||
log.error("Failed to check server:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -145,7 +148,7 @@ function createConnectivityStore() {
|
||||
isMonitoring = true;
|
||||
|
||||
try {
|
||||
console.log("[ConnectivityStore] Starting monitoring for:", url);
|
||||
log.debug("Starting monitoring for:", url);
|
||||
|
||||
// Set the server URL
|
||||
await commands.connectivitySetServerUrl(url);
|
||||
@@ -163,10 +166,10 @@ function createConnectivityStore() {
|
||||
isChecking: status.isChecking,
|
||||
}));
|
||||
|
||||
console.log("[ConnectivityStore] Started monitoring. Initial status:",
|
||||
log.debug("Started monitoring. Initial status:",
|
||||
status.isServerReachable ? "ONLINE" : "OFFLINE");
|
||||
} catch (error) {
|
||||
console.error("[ConnectivityStore] Failed to start monitoring:", error);
|
||||
log.error("Failed to start monitoring:", error);
|
||||
update((s) => ({
|
||||
...s,
|
||||
isServerReachable: false,
|
||||
@@ -185,9 +188,9 @@ function createConnectivityStore() {
|
||||
await commands.connectivityStopMonitoring();
|
||||
isMonitoring = false;
|
||||
eventHandlers = {};
|
||||
console.log("[ConnectivityStore] Stopped monitoring");
|
||||
log.debug("Stopped monitoring");
|
||||
} catch (error) {
|
||||
console.error("[ConnectivityStore] Failed to stop monitoring:", error);
|
||||
log.error("Failed to stop monitoring:", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +201,7 @@ function createConnectivityStore() {
|
||||
try {
|
||||
await commands.connectivitySetServerUrl(url);
|
||||
} catch (error) {
|
||||
console.error("[ConnectivityStore] Failed to set server URL:", error);
|
||||
log.error("Failed to set server URL:", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+45
-42
@@ -3,6 +3,9 @@
|
||||
import { writable, derived, get } from 'svelte/store';
|
||||
import { commands } from '$lib/api/bindings';
|
||||
import { listen, type UnlistenFn } from '@tauri-apps/api/event';
|
||||
import { createLogger } from '$lib/utils/logger';
|
||||
|
||||
const log = createLogger('Downloads');
|
||||
|
||||
// Event listener state
|
||||
let unlistenFn: UnlistenFn | null = null;
|
||||
@@ -103,7 +106,7 @@ function createDownloadsStore() {
|
||||
async function refreshDownloads(userId: string, statusFilter?: string[]): Promise<void> {
|
||||
// If a refresh is already in progress, queue this request instead
|
||||
if (refreshInProgress) {
|
||||
console.debug('🔄 Refresh already in progress, queuing request for user:', userId);
|
||||
log.debug('🔄 Refresh already in progress, queuing request for user:', userId);
|
||||
pendingRefreshRequest = { userId, statusFilter };
|
||||
return;
|
||||
}
|
||||
@@ -111,13 +114,13 @@ function createDownloadsStore() {
|
||||
refreshInProgress = true;
|
||||
|
||||
try {
|
||||
console.log('🔄 Refreshing downloads for user:', userId);
|
||||
log.debug('🔄 Refreshing downloads for user:', userId);
|
||||
const response = (await commands.getDownloads(
|
||||
userId,
|
||||
statusFilter ?? null
|
||||
)) as unknown as { downloads: DownloadInfo[]; stats: DownloadStats };
|
||||
console.log(' Got', response.downloads.length, 'downloads from backend');
|
||||
console.log(' Stats:', response.stats);
|
||||
log.debug(' Got', response.downloads.length, 'downloads from backend');
|
||||
log.debug(' Stats:', response.stats);
|
||||
|
||||
update((state) => {
|
||||
const downloadsMap: Record<number, DownloadInfo> = {};
|
||||
@@ -133,7 +136,7 @@ function createDownloadsStore() {
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh downloads:', error);
|
||||
log.error('Failed to refresh downloads:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
refreshInProgress = false;
|
||||
@@ -164,7 +167,7 @@ function createDownloadsStore() {
|
||||
albumName?: string
|
||||
): Promise<number> {
|
||||
try {
|
||||
console.log('📥 downloadItem called:', { itemId, userId, filePath, itemName, artistName, albumName });
|
||||
log.debug('📥 downloadItem called:', { itemId, userId, filePath, itemName, artistName, albumName });
|
||||
const downloadId = await commands.downloadItem({
|
||||
itemId,
|
||||
userId,
|
||||
@@ -176,16 +179,16 @@ function createDownloadsStore() {
|
||||
albumName: albumName ?? null,
|
||||
expectedSize: null
|
||||
});
|
||||
console.log(' Got download ID from backend:', downloadId);
|
||||
log.debug(' Got download ID from backend:', downloadId);
|
||||
|
||||
// Fetch download info and add to store
|
||||
console.log(' Refreshing downloads...');
|
||||
log.debug(' Refreshing downloads...');
|
||||
await refreshDownloads(userId);
|
||||
console.log(' Refresh complete. Store state:', get({ subscribe }));
|
||||
log.debug(' Refresh complete. Store state:', get({ subscribe }));
|
||||
|
||||
return downloadId;
|
||||
} catch (error) {
|
||||
console.error('Failed to queue download:', error);
|
||||
log.error('Failed to queue download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -206,16 +209,16 @@ function createDownloadsStore() {
|
||||
basePath: string
|
||||
): Promise<number[]> {
|
||||
try {
|
||||
console.log('📥 downloadAlbum called:', { albumId, userId, basePath });
|
||||
log.debug('📥 downloadAlbum called:', { albumId, userId, basePath });
|
||||
const downloadIds = await commands.downloadAlbum(handle, albumId, userId, basePath);
|
||||
console.log(' Got download IDs from backend:', downloadIds);
|
||||
log.debug(' Got download IDs from backend:', downloadIds);
|
||||
|
||||
// Refresh downloads
|
||||
await refreshDownloads(userId);
|
||||
|
||||
return downloadIds;
|
||||
} catch (error) {
|
||||
console.error('Failed to queue album download:', error);
|
||||
log.error('Failed to queue album download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -237,7 +240,7 @@ function createDownloadsStore() {
|
||||
seasonNumber?: number
|
||||
): Promise<number> {
|
||||
try {
|
||||
console.log('🎬 downloadVideo called:', {
|
||||
log.debug('🎬 downloadVideo called:', {
|
||||
itemId,
|
||||
userId,
|
||||
filePath,
|
||||
@@ -258,14 +261,14 @@ function createDownloadsStore() {
|
||||
episodeNumber: episodeNumber ?? null,
|
||||
seasonNumber: seasonNumber ?? null
|
||||
});
|
||||
console.log(' Got download ID from backend:', downloadId);
|
||||
log.debug(' Got download ID from backend:', downloadId);
|
||||
|
||||
// Refresh downloads
|
||||
await refreshDownloads(userId);
|
||||
|
||||
return downloadId;
|
||||
} catch (error) {
|
||||
console.error('Failed to queue video download:', error);
|
||||
log.error('Failed to queue video download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -281,7 +284,7 @@ function createDownloadsStore() {
|
||||
qualityPreset?: string
|
||||
): Promise<number[]> {
|
||||
try {
|
||||
console.log('📺 downloadSeries called:', {
|
||||
log.debug('📺 downloadSeries called:', {
|
||||
seriesId,
|
||||
seriesName,
|
||||
userId,
|
||||
@@ -295,14 +298,14 @@ function createDownloadsStore() {
|
||||
basePath,
|
||||
qualityPreset ?? null
|
||||
);
|
||||
console.log(' Queued', downloadIds.length, 'episodes for download');
|
||||
log.debug(' Queued', downloadIds.length, 'episodes for download');
|
||||
|
||||
// Refresh downloads
|
||||
await refreshDownloads(userId);
|
||||
|
||||
return downloadIds;
|
||||
} catch (error) {
|
||||
console.error('Failed to queue series download:', error);
|
||||
log.error('Failed to queue series download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -320,7 +323,7 @@ function createDownloadsStore() {
|
||||
qualityPreset?: string
|
||||
): Promise<number[]> {
|
||||
try {
|
||||
console.log('📺 downloadSeason called:', {
|
||||
log.debug('📺 downloadSeason called:', {
|
||||
seasonId,
|
||||
seriesName,
|
||||
seasonName,
|
||||
@@ -336,14 +339,14 @@ function createDownloadsStore() {
|
||||
basePath,
|
||||
qualityPreset ?? null
|
||||
);
|
||||
console.log(' Queued', downloadIds.length, 'episodes for download');
|
||||
log.debug(' Queued', downloadIds.length, 'episodes for download');
|
||||
|
||||
// Refresh downloads
|
||||
await refreshDownloads(userId);
|
||||
|
||||
return downloadIds;
|
||||
} catch (error) {
|
||||
console.error('Failed to queue season download:', error);
|
||||
log.error('Failed to queue season download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -355,7 +358,7 @@ function createDownloadsStore() {
|
||||
try {
|
||||
await commands.pinItem(itemId);
|
||||
} catch (error) {
|
||||
console.error('Failed to pin item:', error);
|
||||
log.error('Failed to pin item:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -367,7 +370,7 @@ function createDownloadsStore() {
|
||||
try {
|
||||
await commands.unpinItem(itemId);
|
||||
} catch (error) {
|
||||
console.error('Failed to unpin item:', error);
|
||||
log.error('Failed to unpin item:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -379,7 +382,7 @@ function createDownloadsStore() {
|
||||
try {
|
||||
return await commands.isItemPinned(itemId);
|
||||
} catch (error) {
|
||||
console.error('Failed to check pin status:', error);
|
||||
log.error('Failed to check pin status:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@@ -391,7 +394,7 @@ function createDownloadsStore() {
|
||||
try {
|
||||
await commands.pauseDownload(downloadId);
|
||||
} catch (error) {
|
||||
console.error('Failed to pause download:', error);
|
||||
log.error('Failed to pause download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -403,7 +406,7 @@ function createDownloadsStore() {
|
||||
try {
|
||||
await commands.resumeDownload(downloadId);
|
||||
} catch (error) {
|
||||
console.error('Failed to resume download:', error);
|
||||
log.error('Failed to resume download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -415,7 +418,7 @@ function createDownloadsStore() {
|
||||
try {
|
||||
await commands.cancelDownload(downloadId);
|
||||
} catch (error) {
|
||||
console.error('Failed to cancel download:', error);
|
||||
log.error('Failed to cancel download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -431,7 +434,7 @@ function createDownloadsStore() {
|
||||
return { ...state, downloads: remaining };
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to delete download:', error);
|
||||
log.error('Failed to delete download:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -448,14 +451,14 @@ function createDownloadsStore() {
|
||||
update((state) => {
|
||||
const download = state.downloads[downloadId];
|
||||
if (!download) {
|
||||
console.log(' Download not in store:', downloadId);
|
||||
log.debug(' Download not in store:', downloadId);
|
||||
return state;
|
||||
}
|
||||
|
||||
const updatedDownload = { ...download, ...updates };
|
||||
const newDownloads = { ...state.downloads, [downloadId]: updatedDownload };
|
||||
|
||||
console.log(' Store updated for download', downloadId, ':', updates);
|
||||
log.debug(' Store updated for download', downloadId, ':', updates);
|
||||
// No count calculation - stats remain as-is until next refresh
|
||||
return {
|
||||
downloads: newDownloads,
|
||||
@@ -515,30 +518,30 @@ export const audioDownloads = derived(downloads, ($d) =>
|
||||
*/
|
||||
export async function initDownloadEvents(): Promise<void> {
|
||||
if (isEventsInitialized) {
|
||||
console.warn('Download events already initialized');
|
||||
log.warn('Download events already initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('🎧 Setting up download event listener...');
|
||||
log.debug('🎧 Setting up download event listener...');
|
||||
unlistenFn = await listen<DownloadEvent>('download-event', (event) => {
|
||||
const payload = event.payload;
|
||||
console.log('📬 Received download event:', payload.type, 'for download:', payload.downloadId);
|
||||
console.log(' Full event payload:', JSON.stringify(payload));
|
||||
log.debug('📬 Received download event:', payload.type, 'for download:', payload.downloadId);
|
||||
log.debug(' Full event payload:', JSON.stringify(payload));
|
||||
|
||||
// Update the store based on event type
|
||||
downloads.subscribe((state) => {
|
||||
const download = state.downloads[payload.downloadId];
|
||||
console.log(' Current download state:', download ? download.status : 'NOT IN STORE');
|
||||
log.debug(' Current download state:', download ? download.status : 'NOT IN STORE');
|
||||
})(); // Immediately unsubscribe after reading
|
||||
|
||||
handleDownloadEvent(payload);
|
||||
});
|
||||
|
||||
isEventsInitialized = true;
|
||||
console.log('✅ Download event listener registered successfully');
|
||||
log.debug('✅ Download event listener registered successfully');
|
||||
} catch (err) {
|
||||
console.error('❌ Failed to register download event listener:', err);
|
||||
log.error('❌ Failed to register download event listener:', err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,7 +602,7 @@ function handleDownloadEvent(payload: DownloadEvent): void {
|
||||
payload.downloadId,
|
||||
payload.totalBytes || download.fileSize || download.bytesDownloaded,
|
||||
payload.filePath || download.filePath
|
||||
).catch((err) => console.error('Failed to persist download completion:', err));
|
||||
).catch((err) => log.error('Failed to persist download completion:', err));
|
||||
|
||||
updateDownloadInStore(payload.downloadId, {
|
||||
status: 'completed',
|
||||
@@ -616,7 +619,7 @@ function handleDownloadEvent(payload: DownloadEvent): void {
|
||||
commands.markDownloadFailed(
|
||||
payload.downloadId,
|
||||
payload.error || 'Unknown error'
|
||||
).catch((err) => console.error('Failed to persist download failure:', err));
|
||||
).catch((err) => log.error('Failed to persist download failure:', err));
|
||||
|
||||
updateDownloadInStore(payload.downloadId, {
|
||||
status: 'failed',
|
||||
@@ -654,7 +657,7 @@ function handleDownloadEvent(payload: DownloadEvent): void {
|
||||
* Helper to update a download in the store.
|
||||
*/
|
||||
function updateDownloadInStore(downloadId: number, updates: Partial<DownloadInfo>): void {
|
||||
console.log(' updateDownloadInStore:', downloadId, updates);
|
||||
log.debug(' updateDownloadInStore:', downloadId, updates);
|
||||
downloads.updateDownload(downloadId, updates);
|
||||
}
|
||||
|
||||
@@ -662,6 +665,6 @@ function updateDownloadInStore(downloadId: number, updates: Partial<DownloadInfo
|
||||
* Helper to remove a download from the store.
|
||||
*/
|
||||
function removeDownloadFromStore(downloadId: number): void {
|
||||
console.log(' removeDownloadFromStore:', downloadId);
|
||||
log.debug(' removeDownloadFromStore:', downloadId);
|
||||
downloads.removeDownload(downloadId);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ import {
|
||||
filterSupersededResumeItems,
|
||||
filterInProgressNextUpItems,
|
||||
} from "./continueWatchingFilter";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("HomeStore");
|
||||
|
||||
interface HomeState {
|
||||
heroItems: MediaItem[];
|
||||
@@ -103,7 +106,7 @@ function createHomeStore() {
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Failed to load home sections";
|
||||
update(s => ({ ...s, isLoading: false, error: message }));
|
||||
console.error("Failed to load home sections:", error);
|
||||
log.error("Failed to load home sections:", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-10
@@ -7,6 +7,9 @@ import type { Library, MediaItem, SearchResult, Genre } from "$lib/api/types";
|
||||
import type { SearchOptions } from "$lib/api/bindings";
|
||||
import type { SearchScope } from "$lib/utils/searchScope";
|
||||
import { auth } from "./auth";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("LibraryStore");
|
||||
|
||||
/**
|
||||
* Payload of the backend `search-event` (mirrors Rust `SearchUpdateEvent`).
|
||||
@@ -84,16 +87,16 @@ function createLibraryStore() {
|
||||
const startTime = performance.now();
|
||||
const repo = auth.getRepository();
|
||||
|
||||
console.log("📚 [LibraryStore] Loading libraries...");
|
||||
log.debug("📚 Loading libraries...");
|
||||
|
||||
const libraries = await repo.getLibraries();
|
||||
|
||||
const loadTime = Math.round(performance.now() - startTime);
|
||||
|
||||
if (loadTime < 100) {
|
||||
console.log(`🚀 [LibraryStore] CACHE HIT! Loaded ${libraries.length} libraries in ${loadTime}ms (instant)`);
|
||||
log.debug(`🚀 CACHE HIT! Loaded ${libraries.length} libraries in ${loadTime}ms (instant)`);
|
||||
} else {
|
||||
console.log(`⏳ [LibraryStore] Loaded ${libraries.length} libraries in ${loadTime}ms (from server)`);
|
||||
log.debug(`⏳ Loaded ${libraries.length} libraries in ${loadTime}ms (from server)`);
|
||||
}
|
||||
|
||||
update((s) => ({
|
||||
@@ -120,7 +123,7 @@ function createLibraryStore() {
|
||||
const startTime = performance.now();
|
||||
const repo = auth.getRepository();
|
||||
|
||||
console.log(`📚 [LibraryStore] Loading items for parent: ${parentId.substring(0, 8)}...`);
|
||||
log.debug(`📚 Loading items for parent: ${parentId.substring(0, 8)}...`);
|
||||
|
||||
const result = await repo.getItems(parentId, {
|
||||
startIndex: options.startIndex ?? 0,
|
||||
@@ -134,9 +137,9 @@ function createLibraryStore() {
|
||||
const loadTime = Math.round(performance.now() - startTime);
|
||||
|
||||
if (loadTime < 100) {
|
||||
console.log(`🚀 [LibraryStore] CACHE HIT! Loaded ${result.items.length} items in ${loadTime}ms (instant)`);
|
||||
log.debug(`🚀 CACHE HIT! Loaded ${result.items.length} items in ${loadTime}ms (instant)`);
|
||||
} else {
|
||||
console.log(`⏳ [LibraryStore] Loaded ${result.items.length} items in ${loadTime}ms (from server)`);
|
||||
log.debug(`⏳ Loaded ${result.items.length} items in ${loadTime}ms (from server)`);
|
||||
}
|
||||
|
||||
update((s) => ({
|
||||
@@ -202,11 +205,11 @@ function createLibraryStore() {
|
||||
const repo = auth.getRepository();
|
||||
const item = await repo.getItem(itemId);
|
||||
|
||||
console.log(`[LibraryStore] loadItem(${itemId}): ${item.name} (${item.kind})`);
|
||||
console.log(`[LibraryStore] - Has people? ${item.people ? `YES (${item.people.length})` : 'NO'}`);
|
||||
log.debug(`loadItem(${itemId}): ${item.name} (${item.kind})`);
|
||||
log.debug(`- Has people? ${item.people ? `YES (${item.people.length})` : 'NO'}`);
|
||||
if (item.people && item.people.length > 0) {
|
||||
item.people.forEach((p, i) => {
|
||||
console.log(`[LibraryStore] [${i}] ${p.name} (type: "${p.type}", id: "${p.id}")`);
|
||||
log.debug(` [${i}] ${p.name} (type: "${p.type}", id: "${p.id}")`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -319,7 +322,7 @@ function createLibraryStore() {
|
||||
update((s) => ({ ...s, genres }));
|
||||
return genres;
|
||||
} catch (error) {
|
||||
console.error("Failed to load genres:", error);
|
||||
log.error("Failed to load genres:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ import { writable, get } from "svelte/store";
|
||||
import { commands } from "$lib/api/bindings";
|
||||
import type { Session } from "$lib/api/types";
|
||||
import type { LmsSyncGroup } from "$lib/api/bindings";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("LmsSync");
|
||||
|
||||
const LMS_DEVICE_PREFIX = "lms-";
|
||||
|
||||
@@ -51,7 +54,7 @@ function createLmsSyncStore() {
|
||||
update((s) => ({ ...s, groups, error: null }));
|
||||
} catch (error) {
|
||||
// The plugin may not be installed; treat as "no groups" rather than fatal.
|
||||
console.warn("[LmsSync] Failed to load sync groups:", error);
|
||||
log.warn("Failed to load sync groups:", error);
|
||||
update((s) => ({ ...s, groups: [] }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import { writable, derived } from "svelte/store";
|
||||
import type { MediaItem } from "$lib/api/types";
|
||||
import { auth } from "./auth";
|
||||
import { buildHeroMix } from "$lib/utils/heroMix";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("MoviesStore");
|
||||
|
||||
/** A single "by genre" row: the genre name plus the movies in it. */
|
||||
export interface GenreRow {
|
||||
@@ -91,7 +94,7 @@ function createMoviesStore() {
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Failed to load movie sections";
|
||||
update(s => ({ ...s, isLoading: false, error: message }));
|
||||
console.error("Failed to load movie sections:", error);
|
||||
log.error("Failed to load movie sections:", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +123,7 @@ function createMoviesStore() {
|
||||
});
|
||||
return { id: genre.id, name: genre.name, items: result.items };
|
||||
} catch (e) {
|
||||
console.warn(`Failed to load genre row "${genre.name}":`, e);
|
||||
log.warn(`Failed to load genre row "${genre.name}":`, e);
|
||||
return { id: genre.id, name: genre.name, items: [] };
|
||||
}
|
||||
})
|
||||
@@ -133,7 +136,7 @@ function createMoviesStore() {
|
||||
|
||||
update(s => ({ ...s, genreRows }));
|
||||
} catch (e) {
|
||||
console.warn("Failed to load movie genre rows:", e);
|
||||
log.warn("Failed to load movie genre rows:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ import { auth } from "./auth";
|
||||
import { excludePodcasts } from "$lib/utils/podcastFilter";
|
||||
import { selectDiverseGenres, sampleAcross } from "$lib/utils/genreDiversity";
|
||||
import { buildHeroMix } from "$lib/utils/heroMix";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("MusicStore");
|
||||
|
||||
/** A single "by genre" row: the genre name plus the albums in it. */
|
||||
export interface GenreRow {
|
||||
@@ -124,7 +127,7 @@ function createMusicStore() {
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Failed to load music sections";
|
||||
update(s => ({ ...s, isLoading: false, error: message }));
|
||||
console.error("Failed to load music sections:", error);
|
||||
log.error("Failed to load music sections:", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +146,7 @@ function createMusicStore() {
|
||||
// HACK: drop the "Podcasts" folder that lives in the music library.
|
||||
return { id: genre.id, name: genre.name, items: excludePodcasts(result.items) };
|
||||
} catch (e) {
|
||||
console.warn(`Failed to load genre row "${genre.name}":`, e);
|
||||
log.warn(`Failed to load genre row "${genre.name}":`, e);
|
||||
return { id: genre.id, name: genre.name, items: [] };
|
||||
}
|
||||
}
|
||||
@@ -205,7 +208,7 @@ function createMusicStore() {
|
||||
|
||||
update(s => ({ ...s, genreRows }));
|
||||
} catch (e) {
|
||||
console.warn("Failed to load music genre rows:", e);
|
||||
log.warn("Failed to load music genre rows:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ import { commands, events } from "$lib/api/bindings";
|
||||
import { sessions, selectedSession } from "./sessions";
|
||||
import { auth } from "./auth";
|
||||
import { ticksToSeconds } from "$lib/utils/playbackUnits";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("PlaybackMode");
|
||||
|
||||
export type PlaybackMode = "local" | "remote" | "idle";
|
||||
|
||||
@@ -59,7 +62,7 @@ function createPlaybackModeStore() {
|
||||
// authoritative mode.
|
||||
sessions.selectSession(remoteSessionId);
|
||||
} catch (error) {
|
||||
console.error("Failed to get playback mode:", error);
|
||||
log.error("Failed to get playback mode:", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +84,7 @@ function createPlaybackModeStore() {
|
||||
sessionId: string | null | undefined,
|
||||
currentPosition?: number,
|
||||
): Promise<void> {
|
||||
console.log("[PlaybackMode] Transferring to remote session:", sessionId);
|
||||
log.debug("Transferring to remote session:", sessionId);
|
||||
update((s) => ({ ...s, isTransferring: true, transferError: null }));
|
||||
|
||||
let aborted = false;
|
||||
@@ -104,12 +107,12 @@ function createPlaybackModeStore() {
|
||||
|
||||
// Rust handles everything - just wait for it to complete
|
||||
// It includes its own 5-second timeout for track loading
|
||||
console.log("[PlaybackMode] About to invoke playback_mode_transfer_to_remote with sessionId:", sessionId, "position:", positionOverride);
|
||||
log.debug("About to invoke playback_mode_transfer_to_remote with sessionId:", sessionId, "position:", positionOverride);
|
||||
await commands.playbackModeTransferToRemote(sessionId ?? "", positionOverride);
|
||||
console.log("[PlaybackMode] Invoke completed successfully");
|
||||
log.debug("Invoke completed successfully");
|
||||
|
||||
if (aborted) {
|
||||
console.log("[PlaybackMode] Transfer was cancelled");
|
||||
log.debug("Transfer was cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,10 +125,10 @@ function createPlaybackModeStore() {
|
||||
isTransferring: false,
|
||||
}));
|
||||
|
||||
console.log("[PlaybackMode] Successfully transferred to remote");
|
||||
log.debug("Successfully transferred to remote");
|
||||
} catch (error) {
|
||||
if (aborted) {
|
||||
console.log("[PlaybackMode] Transfer was cancelled");
|
||||
log.debug("Transfer was cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -135,7 +138,7 @@ function createPlaybackModeStore() {
|
||||
isTransferring: false,
|
||||
transferError: message,
|
||||
}));
|
||||
console.error("Transfer to remote failed:", error);
|
||||
log.error("Transfer to remote failed:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
currentTransferAbort = null;
|
||||
@@ -154,7 +157,7 @@ function createPlaybackModeStore() {
|
||||
* Will be fully migrated to Rust after Phase 3.
|
||||
*/
|
||||
async function transferToLocal(): Promise<void> {
|
||||
console.log("[PlaybackMode] Transferring to local");
|
||||
log.debug("Transferring to local");
|
||||
update((s) => ({ ...s, isTransferring: true, transferError: null }));
|
||||
|
||||
let aborted = false;
|
||||
@@ -195,7 +198,7 @@ function createPlaybackModeStore() {
|
||||
const itemId = (nowPlaying as any).id || (nowPlaying as any).Id;
|
||||
const itemName = (nowPlaying as any).name || (nowPlaying as any).Name;
|
||||
|
||||
console.log("[PlaybackMode] Current remote item:", itemName, "position:", positionSeconds, "id:", itemId);
|
||||
log.debug("Current remote item:", itemName, "position:", positionSeconds, "id:", itemId);
|
||||
|
||||
if (!itemId) {
|
||||
throw new Error("Cannot transfer: remote item has no ID");
|
||||
@@ -246,10 +249,10 @@ function createPlaybackModeStore() {
|
||||
isTransferring: false,
|
||||
}));
|
||||
|
||||
console.log("[PlaybackMode] Successfully transferred to local");
|
||||
log.debug("Successfully transferred to local");
|
||||
} catch (error) {
|
||||
if (aborted) {
|
||||
console.log("[PlaybackMode] Transfer was cancelled");
|
||||
log.debug("Transfer was cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -259,7 +262,7 @@ function createPlaybackModeStore() {
|
||||
isTransferring: false,
|
||||
transferError: message,
|
||||
}));
|
||||
console.error("Transfer to local failed:", error);
|
||||
log.error("Transfer to local failed:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Always lower the Rust transferring flag so it can't stick on if any step
|
||||
@@ -268,7 +271,7 @@ function createPlaybackModeStore() {
|
||||
try {
|
||||
await commands.playbackModeSetTransferring(false);
|
||||
} catch (e) {
|
||||
console.warn("[PlaybackMode] Failed to clear transferring flag:", e);
|
||||
log.warn("Failed to clear transferring flag:", e);
|
||||
}
|
||||
currentTransferAbort = null;
|
||||
// Reconcile to the authoritative Rust mode in case a step above threw and
|
||||
@@ -294,9 +297,9 @@ function createPlaybackModeStore() {
|
||||
if (event.payload.type === "remote_disconnect_requested") {
|
||||
const currentState = get({ subscribe });
|
||||
if (currentState.mode === "remote") {
|
||||
console.log("[PlaybackMode] Lockscreen requested disconnect; transferring to local");
|
||||
log.debug("Lockscreen requested disconnect; transferring to local");
|
||||
transferToLocal().catch((e) =>
|
||||
console.error("[PlaybackMode] Lockscreen-triggered transfer failed:", e),
|
||||
log.error("Lockscreen-triggered transfer failed:", e),
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -331,7 +334,7 @@ function createPlaybackModeStore() {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[PlaybackMode] Backend mode changed →", mode, remoteSessionId);
|
||||
log.debug("Backend mode changed →", mode, remoteSessionId);
|
||||
update((s) => ({ ...s, mode, remoteSessionId }));
|
||||
// Keep the selected session in step so the merged UI stores follow, but
|
||||
// only touch the selection when it actually differs — re-selecting the
|
||||
@@ -352,10 +355,10 @@ function createPlaybackModeStore() {
|
||||
if (currentState.mode === "remote" && currentState.remoteSessionId && !currentState.isTransferring) {
|
||||
if (!session || session.id !== currentState.remoteSessionId || !session.supportsMediaControl) {
|
||||
consecutiveMisses++;
|
||||
console.warn(`[PlaybackMode] Remote session miss ${consecutiveMisses}/${DISCONNECT_THRESHOLD}`);
|
||||
log.warn(`Remote session miss ${consecutiveMisses}/${DISCONNECT_THRESHOLD}`);
|
||||
|
||||
if (consecutiveMisses >= DISCONNECT_THRESHOLD) {
|
||||
console.warn("[PlaybackMode] Remote session lost after sustained disconnection");
|
||||
log.warn("Remote session lost after sustained disconnection");
|
||||
consecutiveMisses = 0;
|
||||
update((s) => ({
|
||||
...s,
|
||||
@@ -367,7 +370,7 @@ function createPlaybackModeStore() {
|
||||
} else {
|
||||
// Session is healthy, reset counter
|
||||
if (consecutiveMisses > 0) {
|
||||
console.log("[PlaybackMode] Remote session recovered after", consecutiveMisses, "misses");
|
||||
log.debug("Remote session recovered after", consecutiveMisses, "misses");
|
||||
}
|
||||
consecutiveMisses = 0;
|
||||
}
|
||||
@@ -389,7 +392,7 @@ function createPlaybackModeStore() {
|
||||
*/
|
||||
function cancelTransfer(): void {
|
||||
if (currentTransferAbort) {
|
||||
console.log("[PlaybackMode] Cancelling transfer");
|
||||
log.debug("Cancelling transfer");
|
||||
currentTransferAbort();
|
||||
}
|
||||
}
|
||||
@@ -399,11 +402,11 @@ function createPlaybackModeStore() {
|
||||
* This stops controlling the remote device and returns to idle/local state
|
||||
*/
|
||||
async function disconnect(): Promise<void> {
|
||||
console.log("[PlaybackMode] Disconnecting from remote session");
|
||||
log.debug("Disconnecting from remote session");
|
||||
|
||||
const currentState = get({ subscribe });
|
||||
if (currentState.mode !== "remote") {
|
||||
console.log("[PlaybackMode] Not in remote mode, nothing to disconnect");
|
||||
log.debug("Not in remote mode, nothing to disconnect");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -420,10 +423,10 @@ function createPlaybackModeStore() {
|
||||
transferError: null,
|
||||
}));
|
||||
|
||||
console.log("[PlaybackMode] Successfully disconnected");
|
||||
log.debug("Successfully disconnected");
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Failed to disconnect";
|
||||
console.error("[PlaybackMode] Disconnect failed:", error);
|
||||
log.error("Disconnect failed:", error);
|
||||
update((s) => ({
|
||||
...s,
|
||||
transferError: message,
|
||||
|
||||
@@ -10,6 +10,9 @@ import { writable, derived, get } from "svelte/store";
|
||||
import { commands, events } from "$lib/api/bindings";
|
||||
import type { MediaItem } from "$lib/api/types";
|
||||
import { auth } from "$lib/stores/auth";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("Queue");
|
||||
|
||||
export type RepeatMode = "off" | "all" | "one";
|
||||
|
||||
@@ -72,7 +75,7 @@ function createQueueStore() {
|
||||
async function syncFromRust(): Promise<void> {
|
||||
try {
|
||||
const rustQueue = (await commands.playerGetQueue()) as unknown as QueueChangedEvent;
|
||||
console.log("[Queue] Synced from Rust - items:", rustQueue.items.length);
|
||||
log.debug("Synced from Rust - items:", rustQueue.items.length);
|
||||
set({
|
||||
items: rustQueue.items,
|
||||
currentIndex: rustQueue.currentIndex,
|
||||
@@ -82,7 +85,7 @@ function createQueueStore() {
|
||||
hasPrevious: rustQueue.hasPrevious,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("[Queue] Failed to sync from Rust:", error);
|
||||
log.error("Failed to sync from Rust:", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-23
@@ -4,6 +4,9 @@
|
||||
import { writable, derived } from "svelte/store";
|
||||
import { commands, events } from "$lib/api/bindings";
|
||||
import type { Session } from "$lib/api/types";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("Sessions");
|
||||
|
||||
interface SessionsState {
|
||||
sessions: Session[];
|
||||
@@ -28,9 +31,9 @@ function createSessionsStore() {
|
||||
events.playerStatusEvent.listen((event) => {
|
||||
if (event.payload.type === "sessions_updated") {
|
||||
const sessions = event.payload.sessions as unknown as Session[];
|
||||
console.log(`[Sessions] Received ${sessions.length} sessions from backend`);
|
||||
log.debug(`Received ${sessions.length} sessions from backend`);
|
||||
sessions.forEach((s, i) => {
|
||||
console.log(`[Sessions] Session ${i}: id=${s.id}, device=${s.deviceName}, supportsRemoteControl=${s.supportsRemoteControl}`);
|
||||
log.debug(`Session ${i}: id=${s.id}, device=${s.deviceName}, supportsRemoteControl=${s.supportsRemoteControl}`);
|
||||
});
|
||||
update((s) => ({
|
||||
...s,
|
||||
@@ -50,9 +53,9 @@ function createSessionsStore() {
|
||||
|
||||
const sessions = await commands.sessionsPollNow();
|
||||
|
||||
console.log(`[Sessions] Manual refresh returned ${sessions.length} sessions`);
|
||||
log.debug(`Manual refresh returned ${sessions.length} sessions`);
|
||||
sessions.forEach((s, i) => {
|
||||
console.log(`[Sessions] Session ${i}: id=${s.id}, device=${s.deviceName}, supportsRemoteControl=${s.supportsRemoteControl}`);
|
||||
log.debug(`Session ${i}: id=${s.id}, device=${s.deviceName}, supportsRemoteControl=${s.supportsRemoteControl}`);
|
||||
});
|
||||
|
||||
update((s) => ({
|
||||
@@ -69,7 +72,7 @@ function createSessionsStore() {
|
||||
isLoading: false,
|
||||
error: message,
|
||||
}));
|
||||
console.error("Failed to fetch sessions:", error);
|
||||
log.error("Failed to fetch sessions:", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +93,7 @@ function createSessionsStore() {
|
||||
// Refresh after command to get updated state
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
console.error("Failed to send play/pause command:", error);
|
||||
log.error("Failed to send play/pause command:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +106,7 @@ function createSessionsStore() {
|
||||
await commands.remoteSendCommand(sessionId ?? "", "Stop");
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
console.error("Failed to send stop command:", error);
|
||||
log.error("Failed to send stop command:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -116,7 +119,7 @@ function createSessionsStore() {
|
||||
await commands.remoteSendCommand(sessionId ?? "", "NextTrack");
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
console.error("Failed to send next track command:", error);
|
||||
log.error("Failed to send next track command:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -129,7 +132,7 @@ function createSessionsStore() {
|
||||
await commands.remoteSendCommand(sessionId ?? "", "PreviousTrack");
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
console.error("Failed to send previous track command:", error);
|
||||
log.error("Failed to send previous track command:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -142,7 +145,7 @@ function createSessionsStore() {
|
||||
await commands.remoteSessionSeek(sessionId ?? "", positionTicks);
|
||||
// Don't refresh immediately for seek to avoid UI lag
|
||||
} catch (error) {
|
||||
console.error("Failed to send seek command:", error);
|
||||
log.error("Failed to send seek command:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -155,7 +158,7 @@ function createSessionsStore() {
|
||||
await commands.remoteSessionSetVolume(sessionId ?? "", volume);
|
||||
// Don't refresh immediately for volume to avoid UI lag
|
||||
} catch (error) {
|
||||
console.error("Failed to send volume command:", error);
|
||||
log.error("Failed to send volume command:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -168,7 +171,7 @@ function createSessionsStore() {
|
||||
await commands.remoteSendCommand(sessionId ?? "", "ToggleMute");
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
console.error("Failed to toggle mute:", error);
|
||||
log.error("Failed to toggle mute:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -181,20 +184,20 @@ function createSessionsStore() {
|
||||
itemIds: string[],
|
||||
startIndex = 0
|
||||
): Promise<void> {
|
||||
console.log("[SESSIONS] ========== playOnSession called ==========");
|
||||
console.log("[SESSIONS] sessionId:", sessionId);
|
||||
console.log("[SESSIONS] itemIds array:", itemIds);
|
||||
console.log("[SESSIONS] itemIds.length:", itemIds.length);
|
||||
console.log("[SESSIONS] itemIds JSON:", JSON.stringify(itemIds));
|
||||
console.log("[SESSIONS] startIndex:", startIndex);
|
||||
console.log("[SESSIONS] About to call commands.remotePlayOnSession");
|
||||
log.debug("========== playOnSession called ==========");
|
||||
log.debug("sessionId:", sessionId);
|
||||
log.debug("itemIds array:", itemIds);
|
||||
log.debug("itemIds.length:", itemIds.length);
|
||||
log.debug("itemIds JSON:", JSON.stringify(itemIds));
|
||||
log.debug("startIndex:", startIndex);
|
||||
log.debug("About to call commands.remotePlayOnSession");
|
||||
try {
|
||||
// Use Rust player's Jellyfin client for remote playback
|
||||
const result = await commands.remotePlayOnSession(sessionId ?? "", itemIds, startIndex);
|
||||
console.log("[SESSIONS] invoke succeeded, result:", result);
|
||||
log.debug("invoke succeeded, result:", result);
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
console.error("[SESSIONS] Failed to play on session:", error);
|
||||
log.error("Failed to play on session:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -242,10 +245,10 @@ export const controllableSessions = derived(
|
||||
sessions,
|
||||
($sessions) => {
|
||||
const controllable = $sessions.sessions.filter((s) => s.supportsRemoteControl);
|
||||
console.log(`[Sessions] Filtering ${$sessions.sessions.length} total sessions, ${controllable.length} are controllable`);
|
||||
log.debug(`Filtering ${$sessions.sessions.length} total sessions, ${controllable.length} are controllable`);
|
||||
$sessions.sessions.forEach((s, i) => {
|
||||
const status = s.supportsRemoteControl ? "✓ CONTROLLABLE" : "✗ NOT CONTROLLABLE";
|
||||
console.log(`[Sessions] ${status}: ${s.deviceName} (id=${s.id}, supportsRemoteControl=${s.supportsRemoteControl})`);
|
||||
log.debug(` ${status}: ${s.deviceName} (id=${s.id}, supportsRemoteControl=${s.supportsRemoteControl})`);
|
||||
});
|
||||
return controllable;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ import {
|
||||
filterSupersededResumeItems,
|
||||
filterInProgressNextUpItems,
|
||||
} from "./continueWatchingFilter";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger("TvStore");
|
||||
|
||||
/** A single "by genre" row: the genre name plus the series in it. */
|
||||
export interface GenreRow {
|
||||
@@ -114,7 +117,7 @@ function createTvStore() {
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Failed to load TV sections";
|
||||
update(s => ({ ...s, isLoading: false, error: message }));
|
||||
console.error("Failed to load TV sections:", error);
|
||||
log.error("Failed to load TV sections:", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +146,7 @@ function createTvStore() {
|
||||
});
|
||||
return { id: genre.id, name: genre.name, items: result.items };
|
||||
} catch (e) {
|
||||
console.warn(`Failed to load genre row "${genre.name}":`, e);
|
||||
log.warn(`Failed to load genre row "${genre.name}":`, e);
|
||||
return { id: genre.id, name: genre.name, items: [] };
|
||||
}
|
||||
})
|
||||
@@ -156,7 +159,7 @@ function createTvStore() {
|
||||
|
||||
update(s => ({ ...s, genreRows }));
|
||||
} catch (e) {
|
||||
console.warn("Failed to load TV genre rows:", e);
|
||||
log.warn("Failed to load TV genre rows:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user