git-watchtower 2.3.13 → 2.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-watchtower",
3
- "version": "2.3.13",
3
+ "version": "2.3.14",
4
4
  "description": "Terminal-based Git branch monitor with activity sparklines and optional dev server with live reload",
5
5
  "main": "bin/git-watchtower.js",
6
6
  "bin": {
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  const { ansi, box } = require('../ui/ansi');
10
+ const sounds = require('./sounds');
10
11
 
11
12
  // ============================================================================
12
13
  // Casino Mode State
@@ -117,6 +118,11 @@ function disable() {
117
118
  // tests that re-use the casino module saw the previous test's callback
118
119
  // persist into the next setRenderCallback assignment.
119
120
  marqueeCallback = null;
121
+ // Cancel any pending sound timeouts (jackpot bell chains, multi-play
122
+ // mega-jackpot files) so audio doesn't continue after the user
123
+ // toggled casino mode off — and so child processes from the file-play
124
+ // path don't get spawned by a setTimeout that fires after shutdown.
125
+ sounds.cancelAll();
120
126
  }
121
127
 
122
128
  /**
@@ -9,6 +9,44 @@ const { execFile } = require('child_process');
9
9
  const path = require('path');
10
10
  const fs = require('fs');
11
11
 
12
+ /**
13
+ * Pending setTimeout handles for the multi-bell / multi-play chains used
14
+ * by playJackpot and playMegaJackpot. Tracked so casino.disable() (and
15
+ * shutdown) can cancel any in-flight chain instead of letting up to ~600
16
+ * ms of post-disable audio leak through.
17
+ * @type {Set<NodeJS.Timeout>}
18
+ */
19
+ const _pendingTimeouts = new Set();
20
+
21
+ /**
22
+ * Schedule a callback like setTimeout, but auto-track the handle so it
23
+ * can be cancelled by cancelAll() and auto-removes itself on fire.
24
+ * @param {Function} fn
25
+ * @param {number} delay
26
+ * @returns {NodeJS.Timeout}
27
+ * @private
28
+ */
29
+ function _scheduleTracked(fn, delay) {
30
+ const handle = setTimeout(() => {
31
+ _pendingTimeouts.delete(handle);
32
+ try { fn(); } catch (e) { /* sounds are optional */ }
33
+ }, delay);
34
+ _pendingTimeouts.add(handle);
35
+ return handle;
36
+ }
37
+
38
+ /**
39
+ * Cancel every pending sound timeout. Idempotent. Called from
40
+ * casino.disable() so a jackpot fired moments before the user toggled
41
+ * casino mode off doesn't keep playing afterward.
42
+ */
43
+ function cancelAll() {
44
+ for (const handle of _pendingTimeouts) {
45
+ clearTimeout(handle);
46
+ }
47
+ _pendingTimeouts.clear();
48
+ }
49
+
12
50
  // ============================================================================
13
51
  // Sound Configuration
14
52
  // ============================================================================
@@ -133,10 +171,11 @@ function playJackpot() {
133
171
  if (soundPath) {
134
172
  playFile(soundPath, VOLUME.jackpot);
135
173
  } else {
136
- // Multiple bells for jackpot!
174
+ // Multiple bells for jackpot! Tracked so casino.disable() can
175
+ // cancel mid-chain — see _scheduleTracked / cancelAll.
137
176
  playBell();
138
- setTimeout(playBell, 200);
139
- setTimeout(playBell, 400);
177
+ _scheduleTracked(playBell, 200);
178
+ _scheduleTracked(playBell, 400);
140
179
  }
141
180
  }
142
181
 
@@ -146,14 +185,14 @@ function playJackpot() {
146
185
  function playMegaJackpot() {
147
186
  const soundPath = getSoundPath('jackpot');
148
187
  if (soundPath) {
149
- // Play jackpot sound multiple times
188
+ // Play jackpot sound multiple times. Tracked for cancellation.
150
189
  playFile(soundPath, VOLUME.jackpot);
151
- setTimeout(() => playFile(soundPath, VOLUME.jackpot), 300);
152
- setTimeout(() => playFile(soundPath, VOLUME.jackpot), 600);
190
+ _scheduleTracked(() => playFile(soundPath, VOLUME.jackpot), 300);
191
+ _scheduleTracked(() => playFile(soundPath, VOLUME.jackpot), 600);
153
192
  } else {
154
193
  // Lots of bells!
155
194
  for (let i = 0; i < 5; i++) {
156
- setTimeout(playBell, i * 150);
195
+ _scheduleTracked(playBell, i * 150);
157
196
  }
158
197
  }
159
198
  }
@@ -240,6 +279,7 @@ module.exports = {
240
279
  playSpin,
241
280
  playLoss,
242
281
  playForWinLevel,
282
+ cancelAll,
243
283
  getSoundPath,
244
284
  SOUNDS_DIR,
245
285
  };