From 286651c1b3a671e8bc9125044b4182ef569d4893 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sun, 30 Nov 2025 18:19:00 -0800 Subject: [PATCH] remove settings from analytics --- .../analytics/hooks/use-app-tracker.ts | 294 +++++++++--------- 1 file changed, 142 insertions(+), 152 deletions(-) diff --git a/src/renderer/features/analytics/hooks/use-app-tracker.ts b/src/renderer/features/analytics/hooks/use-app-tracker.ts index a43e969bb..a6daa8502 100644 --- a/src/renderer/features/analytics/hooks/use-app-tracker.ts +++ b/src/renderer/features/analytics/hooks/use-app-tracker.ts @@ -1,34 +1,19 @@ import { mutationOptions, useMutation } from '@tanstack/react-query'; import dayjs from 'dayjs'; -import timezone from 'dayjs/plugin/timezone'; import utc from 'dayjs/plugin/utc'; import isElectron from 'is-electron'; -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; dayjs.extend(utc); -dayjs.extend(timezone); import packageJson from '../../../../../package.json'; import { isAnalyticsDisabled } from '/@/renderer/features/analytics/hooks/use-analytics-disabled'; -import { - BarAlign, - PlayerbarSliderType, - SideQueueType, - useAuthStore, - usePlayerStore, - useSettingsStore, -} from '/@/renderer/store'; +import { useAuthStore } from '/@/renderer/store'; import { LogCategory, logFn } from '/@/renderer/utils/logger'; import { logMsg } from '/@/renderer/utils/logger-message'; import { ServerType } from '/@/shared/types/domain-types'; -import { - FontType, - Platform, - PlayerQueueType, - PlayerStyle, - PlayerType, -} from '/@/shared/types/types'; +import { Platform } from '/@/shared/types/types'; const utils = isElectron() ? window.api.utils : null; @@ -59,143 +44,135 @@ const getPlatform = (): AppTrackerProperties['_platform'] => { type AppTrackerProperties = { _platform: 'unknown' | Platform; _version: string; - player: { - mediaSession: boolean; - playerQueueType: PlayerQueueType; - playerStyle: PlayerStyle; - playerType: PlayerType; - transcoding: boolean; - webAudio: boolean; - }; + // player: { + // mediaSession: boolean; + // playerQueueType: PlayerQueueType; + // playerStyle: PlayerStyle; + // playerType: PlayerType; + // transcoding: boolean; + // webAudio: boolean; + // }; server: { - [ServerType.JELLYFIN]: number; - [ServerType.NAVIDROME]: number; - [ServerType.SUBSONIC]: number; - }; - settings: { - albumBackground: boolean; - albumBackgroundBlur: number; - artistBackground: boolean; - artistBackgroundBlur: number; - customCss: boolean; - disableAutoUpdate: boolean; - discord: boolean; - exitToTray: boolean; - fontType: FontType; - globalHotkeys: boolean; - homeFeature: boolean; - language: string; - lastFM: boolean; - lyricsEnableAutoTranslation: boolean; - lyricsEnableNeteaseTranslation: boolean; - lyricsFetch: boolean; - minimizeToTray: boolean; - musicBrainz: boolean; - nativeAspectRatio: boolean; - playerbarSliderType: PlayerbarSliderType; - playerbarWaveformAlign: BarAlign; - playerbarWaveformBarWidth: number; - playerbarWaveformGap: number; - playerbarWaveformRadius: number; - preventSleepOnPlayback: boolean; - releaseChannel: string; - resume: boolean; - scrobbleEnabled: boolean; - sideQueueType: SideQueueType; - skipBackwardSeconds: number; - skipButtons: boolean; - skipForwardSeconds: number; - startMinimized: boolean; - theme: string; - tray: boolean; - windowBarStyle: Platform; - zoomFactor: number; + [ServerType.JELLYFIN]?: boolean; + [ServerType.NAVIDROME]?: boolean; + [ServerType.SUBSONIC]?: boolean; }; + // settings: { + // albumBackground: boolean; + // albumBackgroundBlur: number; + // artistBackground: boolean; + // artistBackgroundBlur: number; + // customCss: boolean; + // disableAutoUpdate: boolean; + // discord: boolean; + // exitToTray: boolean; + // fontType: FontType; + // globalHotkeys: boolean; + // homeFeature: boolean; + // language: string; + // lastFM: boolean; + // lyricsEnableAutoTranslation: boolean; + // lyricsEnableNeteaseTranslation: boolean; + // lyricsFetch: boolean; + // minimizeToTray: boolean; + // musicBrainz: boolean; + // nativeAspectRatio: boolean; + // playerbarSliderType: PlayerbarSliderType; + // playerbarWaveformAlign: BarAlign; + // playerbarWaveformBarWidth: number; + // playerbarWaveformGap: number; + // playerbarWaveformRadius: number; + // preventSleepOnPlayback: boolean; + // releaseChannel: string; + // resume: boolean; + // scrobbleEnabled: boolean; + // sideQueueType: SideQueueType; + // skipBackwardSeconds: number; + // skipButtons: boolean; + // skipForwardSeconds: number; + // startMinimized: boolean; + // theme: string; + // tray: boolean; + // windowBarStyle: Platform; + // zoomFactor: number; + // }; }; -const getPlayerProperties = (): AppTrackerProperties['player'] => { - const player = usePlayerStore.getState(); - const playbackSettings = useSettingsStore.getState().playback; +// const getPlayerProperties = (): AppTrackerProperties['player'] => { +// const player = usePlayerStore.getState(); +// const playbackSettings = useSettingsStore.getState().playback; - return { - mediaSession: playbackSettings.mediaSession, - playerQueueType: player.player.queueType, - playerStyle: player.player.transitionType, - playerType: playbackSettings.type, - transcoding: playbackSettings.transcode.enabled, - webAudio: playbackSettings.webAudio, - }; -}; +// return { +// mediaSession: playbackSettings.mediaSession, +// playerQueueType: player.player.queueType, +// playerStyle: player.player.transitionType, +// playerType: playbackSettings.type, +// transcoding: playbackSettings.transcode.enabled, +// webAudio: playbackSettings.webAudio, +// }; +// }; -const getSettingsProperties = (): AppTrackerProperties['settings'] => { - const settings = useSettingsStore.getState(); +// const getSettingsProperties = (): AppTrackerProperties['settings'] => { +// const settings = useSettingsStore.getState(); - return { - albumBackground: settings.general.albumBackground, - albumBackgroundBlur: settings.general.albumBackgroundBlur, - artistBackground: settings.general.artistBackground, - artistBackgroundBlur: settings.general.artistBackgroundBlur, - customCss: settings.css.enabled, - disableAutoUpdate: settings.window.disableAutoUpdate, - discord: settings.discord.enabled, - exitToTray: settings.window.exitToTray, - fontType: settings.font.type, - globalHotkeys: settings.hotkeys.globalMediaHotkeys, - homeFeature: settings.general.homeFeature, - language: settings.general.language, - lastFM: settings.general.lastFM, - lyricsEnableAutoTranslation: settings.lyrics.enableAutoTranslation, - lyricsEnableNeteaseTranslation: settings.lyrics.enableNeteaseTranslation, - lyricsFetch: settings.lyrics.fetch, - minimizeToTray: settings.window.minimizeToTray, - musicBrainz: settings.general.musicBrainz, - nativeAspectRatio: settings.general.nativeAspectRatio, - playerbarSliderType: settings.general.playerbarSlider.type as PlayerbarSliderType, - playerbarWaveformAlign: settings.general.playerbarSlider.barAlign as BarAlign, - playerbarWaveformBarWidth: settings.general.playerbarSlider.barWidth, - playerbarWaveformGap: settings.general.playerbarSlider.barGap, - playerbarWaveformRadius: settings.general.playerbarSlider.barRadius, - preventSleepOnPlayback: settings.window.preventSleepOnPlayback, - releaseChannel: settings.window.releaseChannel, - resume: settings.general.resume, - scrobbleEnabled: settings.playback.scrobble.enabled, - sideQueueType: settings.general.sideQueueType, - skipBackwardSeconds: settings.general.skipButtons.skipBackwardSeconds, - skipButtons: settings.general.skipButtons.enabled, - skipForwardSeconds: settings.general.skipButtons.skipForwardSeconds, - startMinimized: settings.window.startMinimized, - theme: settings.general.theme, - tray: settings.window.tray, - windowBarStyle: settings.window.windowBarStyle, - zoomFactor: settings.general.zoomFactor, - }; -}; +// return { +// albumBackground: settings.general.albumBackground, +// albumBackgroundBlur: settings.general.albumBackgroundBlur, +// artistBackground: settings.general.artistBackground, +// artistBackgroundBlur: settings.general.artistBackgroundBlur, +// customCss: settings.css.enabled, +// disableAutoUpdate: settings.window.disableAutoUpdate, +// discord: settings.discord.enabled, +// exitToTray: settings.window.exitToTray, +// fontType: settings.font.type, +// globalHotkeys: settings.hotkeys.globalMediaHotkeys, +// homeFeature: settings.general.homeFeature, +// language: settings.general.language, +// lastFM: settings.general.lastFM, +// lyricsEnableAutoTranslation: settings.lyrics.enableAutoTranslation, +// lyricsEnableNeteaseTranslation: settings.lyrics.enableNeteaseTranslation, +// lyricsFetch: settings.lyrics.fetch, +// minimizeToTray: settings.window.minimizeToTray, +// musicBrainz: settings.general.musicBrainz, +// nativeAspectRatio: settings.general.nativeAspectRatio, +// playerbarSliderType: settings.general.playerbarSlider.type as PlayerbarSliderType, +// playerbarWaveformAlign: settings.general.playerbarSlider.barAlign as BarAlign, +// playerbarWaveformBarWidth: settings.general.playerbarSlider.barWidth, +// playerbarWaveformGap: settings.general.playerbarSlider.barGap, +// playerbarWaveformRadius: settings.general.playerbarSlider.barRadius, +// preventSleepOnPlayback: settings.window.preventSleepOnPlayback, +// releaseChannel: settings.window.releaseChannel, +// resume: settings.general.resume, +// scrobbleEnabled: settings.playback.scrobble.enabled, +// sideQueueType: settings.general.sideQueueType, +// skipBackwardSeconds: settings.general.skipButtons.skipBackwardSeconds, +// skipButtons: settings.general.skipButtons.enabled, +// skipForwardSeconds: settings.general.skipButtons.skipForwardSeconds, +// startMinimized: settings.window.startMinimized, +// theme: settings.general.theme, +// tray: settings.window.tray, +// windowBarStyle: settings.window.windowBarStyle, +// zoomFactor: settings.general.zoomFactor, +// }; +// }; const getServerProperties = (): AppTrackerProperties['server'] => { const auth = useAuthStore.getState(); const serverList = auth.serverList; - return Object.entries(serverList).reduce( - (acc, [, server]) => { - if (server.type === ServerType.JELLYFIN) { - acc[ServerType.JELLYFIN] += 1; - } else if (server.type === ServerType.NAVIDROME) { - acc[ServerType.NAVIDROME] += 1; - } else if (server.type === ServerType.SUBSONIC) { - acc[ServerType.SUBSONIC] += 1; - } - return acc; - }, - { - [ServerType.JELLYFIN]: 0, - [ServerType.NAVIDROME]: 0, - [ServerType.SUBSONIC]: 0, - }, - ); + const properties: AppTrackerProperties['server'] = {}; + + Object.values(serverList).forEach((server) => { + properties[server.type] = true; + }); + + return properties; }; export const useAppTracker = () => { const { mutate: trackAppMutation } = useMutation(appTrackerMutation); + const isTrackingInProgressRef = useRef(false); + const hasRunOnMountRef = useRef(false); useEffect(() => { if (!window.umami || isAnalyticsDisabled()) { @@ -205,47 +182,60 @@ export const useAppTracker = () => { const getProperties = () => { const platform = getPlatform(); const version = getVersion(); - const playerProperties = getPlayerProperties(); const serverProperties = getServerProperties(); - const settingsProperties = getSettingsProperties(); + // const playerProperties = getPlayerProperties(); + // const settingsProperties = getSettingsProperties(); const properties: AppTrackerProperties = { _platform: platform, _version: version, - player: playerProperties, server: serverProperties, - settings: settingsProperties, + // player: playerProperties, + // settings: settingsProperties, }; return properties; }; const checkAndTrack = () => { - const lastSentDate = localStorage.getItem('analytics_app_tracker_timestamp'); - const todayPST = dayjs().tz('America/Los_Angeles').format('YYYY-MM-DD'); + // Prevent multiple simultaneous requests + if (isTrackingInProgressRef.current) { + return; + } - // Only send if it's a new day in PST - if (lastSentDate !== todayPST) { + const lastSentDate = localStorage.getItem('analytics_app_tracker_timestamp'); + const todayUTC = dayjs.utc().format('YYYY-MM-DD'); + + // Only send if it's a new day in UTC (ensures once per 24 hours) + if (lastSentDate !== todayUTC) { + isTrackingInProgressRef.current = true; const properties = getProperties(); trackAppMutation(properties, { + onError: () => {}, onSettled: () => { + isTrackingInProgressRef.current = false; + }, + onSuccess: () => { + // Only update timestamp on success to ensure we only send once per 24 hours + const utcDate = dayjs.utc().format('YYYY-MM-DD'); + localStorage.setItem('analytics_app_tracker_timestamp', utcDate); + logFn.debug(logMsg[LogCategory.ANALYTICS].appTracked, { category: LogCategory.ANALYTICS, meta: { properties }, }); - - const pstDate = dayjs().tz('America/Los_Angeles').format('YYYY-MM-DD'); - localStorage.setItem('analytics_app_tracker_timestamp', pstDate); }, }); } }; // Check immediately on mount - checkAndTrack(); + if (!hasRunOnMountRef.current) { + hasRunOnMountRef.current = true; + checkAndTrack(); + } - // Then check every hour const interval = setInterval(checkAndTrack, 1000 * 60 * 60); return () => clearInterval(interval);