@@ -4,11 +4,63 @@ import type { SetActivity } from "@xhayper/discord-rpc";
44import { fmtStr , getStatusText } from "./activityTextHelpers" ;
55import { setActivity , StatusDisplayTypeEnum } from "./discord.native" ;
66import { settings } from "./Settings" ;
7+ import { trace , errSignal } from "./index" ;
78
89// Proxy this so we dont try import a node native module
910const StatusDisplayType = await StatusDisplayTypeEnum ( ) ;
1011
11- export const updateActivity = async ( mediaItem ?: MediaItem ) => {
12+ // Debounce state
13+ const DEBOUNCE_MS = 300 ;
14+ let debounceTimer : ReturnType < typeof setTimeout > | null = null ;
15+ let isUpdating = false ;
16+ let pendingUpdate : MediaItem | undefined | null = null ; // null = no pending, undefined = pending with no mediaItem
17+
18+ /**
19+ * Debounced wrapper for _updateActivity
20+ * - Waits DEBOUNCE_MS after last call before executing
21+ * - If already updating, queues the next update
22+ */
23+ export const updateActivity = ( mediaItem ?: MediaItem ) => {
24+ // If currently updating, mark that we need another update after
25+ if ( isUpdating ) {
26+ pendingUpdate = mediaItem ;
27+ return ;
28+ }
29+
30+ // Clear existing timer
31+ if ( debounceTimer ) clearTimeout ( debounceTimer ) ;
32+
33+ // Set new debounce timer
34+ debounceTimer = setTimeout ( async ( ) => {
35+ debounceTimer = null ;
36+ await executeUpdate ( mediaItem ) ;
37+ } , DEBOUNCE_MS ) ;
38+ } ;
39+
40+ /**
41+ * Execute the actual update with mutex protection
42+ */
43+ const executeUpdate = async ( mediaItem ?: MediaItem ) => {
44+ isUpdating = true ;
45+ try {
46+ await _updateActivity ( mediaItem ) ;
47+ errSignal ! . _ = undefined ;
48+ } catch ( e ) {
49+ trace . err . withContext ( "Failed to set activity" ) ( e ) ;
50+ } finally {
51+ isUpdating = false ;
52+ if ( pendingUpdate !== null ) {
53+ const pending = pendingUpdate ;
54+ pendingUpdate = null ;
55+ updateActivity ( pending ) ;
56+ }
57+ }
58+ } ;
59+
60+ /**
61+ * Internal update implementation (no debounce/mutex)
62+ */
63+ const _updateActivity = async ( mediaItem ?: MediaItem ) => {
1264 if ( ! PlayState . playing && ! settings . displayOnPause ) return await setActivity ( ) ;
1365
1466 mediaItem ??= await MediaItem . fromPlaybackContext ( ) ;
0 commit comments