The main application window instance for IPC communication
export function setupStatisticsIPC(mainWindow: BrowserWindow) {
// Collection service controls
// Handler to check if metrics collection is active
ipcMain.handle("statistics:isCollectionActive", () => {
return isSkipMetricsCollectionActive();
});
// Handler to start metrics collection
ipcMain.handle(
"statistics:startCollection",
async (_event, intervalMinutes = DEFAULT_COLLECTION_INTERVAL) => {
try {
await startSkipMetricsCollection(intervalMinutes);
return { success: true };
} catch (error: unknown) {
saveLog(`Error starting metrics collection: ${String(error)}`, "ERROR");
return { success: false, error: String(error) };
}
},
);
// Handler to stop metrics collection
ipcMain.handle("statistics:stopCollection", () => {
try {
stopSkipMetricsCollection();
return { success: true };
} catch (error: unknown) {
saveLog(`Error stopping metrics collection: ${String(error)}`, "ERROR");
return { success: false, error: String(error) };
}
});
// Handler to manually trigger aggregation
ipcMain.handle("statistics:triggerAggregation", async () => {
try {
await triggerManualAggregation();
return { success: true };
} catch (error: unknown) {
saveLog(`Error during manual aggregation: ${String(error)}`, "ERROR");
return { success: false, error: String(error) };
}
});
// Handler for daily skip metrics
ipcMain.handle("statistics:getDailySkipMetrics", async () => {
try {
const dailyMetricsFilePath = join(
app.getPath("userData"),
"data",
"daily_skip_metrics.json",
);
if (!existsSync(dailyMetricsFilePath)) {
return { success: false, error: "Daily metrics file not found" };
}
const dailyMetrics =
readJsonSync(dailyMetricsFilePath, { throws: false }) || {};
return { success: true, data: dailyMetrics };
} catch (error: unknown) {
saveLog(`Error retrieving daily skip metrics: ${String(error)}`, "ERROR");
return { success: false, error: String(error) };
}
});
// Handler for weekly skip metrics
ipcMain.handle("statistics:getWeeklySkipMetrics", async () => {
try {
const weeklyMetricsFilePath = join(
app.getPath("userData"),
"data",
"weekly_skip_metrics.json",
);
if (!existsSync(weeklyMetricsFilePath)) {
return { success: false, error: "Weekly metrics file not found" };
}
const weeklyMetrics =
readJsonSync(weeklyMetricsFilePath, { throws: false }) || {};
return { success: true, data: weeklyMetrics };
} catch (error: unknown) {
saveLog(
`Error retrieving weekly skip metrics: ${String(error)}`,
"ERROR",
);
return { success: false, error: String(error) };
}
});
// Handler for aggregating artist metrics
ipcMain.handle("statistics:getArtistSkipMetrics", async () => {
try {
const artistMetrics = await aggregateArtistSkipMetrics();
return { success: true, data: artistMetrics };
} catch (error: unknown) {
console.error("Error aggregating artist metrics:", error);
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
});
// Get all statistics data
ipcMain.handle("statistics:getAll", async () => {
return await getStatistics();
});
// Get unique artist count
ipcMain.handle("statistics:getUniqueArtistCount", async () => {
const statistics = await getStatistics();
return calculateUniqueArtistCount(statistics);
});
// Get skipped tracks
ipcMain.handle("statistics:getSkippedTracks", async () => {
return await getSkippedTracks();
});
// Aggregate daily metrics
ipcMain.handle("statistics:getDailyMetrics", async () => {
if (existsSync(DAILY_METRICS_FILE)) {
return JSON.parse(readFileSync(DAILY_METRICS_FILE, "utf-8"));
}
return await aggregateDailySkipMetrics();
});
// Aggregate weekly metrics
ipcMain.handle("statistics:getWeeklyMetrics", async () => {
if (existsSync(WEEKLY_METRICS_FILE)) {
return JSON.parse(readFileSync(WEEKLY_METRICS_FILE, "utf-8"));
}
return await aggregateWeeklySkipMetrics();
});
// Aggregate artist metrics
ipcMain.handle("statistics:getArtistMetrics", async () => {
if (existsSync(ARTIST_METRICS_FILE)) {
return JSON.parse(readFileSync(ARTIST_METRICS_FILE, "utf-8"));
}
return await aggregateArtistSkipMetrics();
});
// Calculate library statistics
ipcMain.handle("statistics:getLibraryStats", async () => {
if (existsSync(LIBRARY_STATS_FILE)) {
return JSON.parse(readFileSync(LIBRARY_STATS_FILE, "utf-8"));
}
return await calculateLibrarySkipStatistics();
});
// Analyze time-based patterns
ipcMain.handle("statistics:getTimePatterns", async () => {
if (existsSync(TIME_PATTERNS_FILE)) {
return JSON.parse(readFileSync(TIME_PATTERNS_FILE, "utf-8"));
}
return await analyzeTimeBasedPatterns();
});
// Detect skip patterns
ipcMain.handle("statistics:getSkipPatterns", async () => {
if (existsSync(SKIP_PATTERNS_FILE)) {
return JSON.parse(readFileSync(SKIP_PATTERNS_FILE, "utf-8"));
}
return await detectSkipPatterns();
});
// Get artist insights
ipcMain.handle("statistics:getArtistInsights", async () => {
if (existsSync(ARTIST_INSIGHTS_FILE)) {
return JSON.parse(readFileSync(ARTIST_INSIGHTS_FILE, "utf-8"));
}
return await calculateArtistInsights();
});
// Export skipped tracks to CSV
ipcMain.handle("statistics:exportSkippedTracksToCSV", async () => {
return await exportSkippedTracksToCSV(mainWindow);
});
// Export artist metrics to CSV
ipcMain.handle("statistics:exportArtistMetricsToCSV", async () => {
return await exportArtistMetricsToCSV(mainWindow);
});
// Export daily metrics to CSV
ipcMain.handle("statistics:exportDailyMetricsToCSV", async () => {
return await exportDailyMetricsToCSV(mainWindow);
});
// Export weekly metrics to CSV
ipcMain.handle("statistics:exportWeeklyMetricsToCSV", async () => {
return await exportWeeklyMetricsToCSV(mainWindow);
});
// Export library statistics to CSV
ipcMain.handle("statistics:exportLibraryStatisticsToCSV", async () => {
return await exportLibraryStatisticsToCSV(mainWindow);
});
// Export time patterns to CSV
ipcMain.handle("statistics:exportTimePatternsToCSV", async () => {
return await exportTimePatternsToCSV(mainWindow);
});
// Export detected patterns to CSV
ipcMain.handle("statistics:exportDetectedPatternsToCSV", async () => {
return await exportDetectedPatternsToCSV(mainWindow);
});
// Export all statistics to JSON
ipcMain.handle("statistics:exportAllToJSON", async () => {
return await exportAllStatisticsToJSON(mainWindow);
});
// Copy statistics summary to clipboard
ipcMain.handle("statistics:copyToClipboard", async () => {
const statistics = await getStatistics();
return copyStatisticsToClipboard(statistics);
});
}
Set up IPC handlers for statistics functionality
Establishes all IPC channels needed for statistics collection, retrieval, and management between the renderer process and main process.