git-watchtower 1.14.13 → 1.14.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": "1.14.13",
3
+ "version": "1.14.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": {
@@ -41,6 +41,7 @@ let slotResultFlashFrame = 0; // Flash animation frame
41
41
  let slotResultInterval = null; // Interval for result display/flash
42
42
  let slotResultRenderCallback = null; // Callback for re-rendering
43
43
  let slotResultLabel = null; // "NOTHING", "WIN", "BIG WIN", "JACKPOT" etc
44
+ let slotResultClearTimeout = null; // No-win 2s auto-clear timer handle
44
45
 
45
46
  // Win animation state
46
47
  let winAnimationFrame = 0;
@@ -98,10 +99,42 @@ function enable() {
98
99
  function disable() {
99
100
  casinoEnabled = false;
100
101
  stopMarquee();
101
- stopSlotReels();
102
+ // resetSlotState — not stopSlotReels — because stopSlotReels() runs the
103
+ // end-of-poll result animation (labels a "NOTHING" panel and schedules a
104
+ // 2s auto-clear). Calling that during disable paints a brand-new casino
105
+ // effect on the way out, which the user just asked to stop.
106
+ resetSlotState();
102
107
  stopWinAnimation();
103
108
  }
104
109
 
110
+ /**
111
+ * Clear all slot reel state and timers without scheduling any new effects.
112
+ * Safe to call from disable() — unlike stopSlotReels(), it does not kick
113
+ * off a result display or a delayed clear timer.
114
+ * @private
115
+ */
116
+ function resetSlotState() {
117
+ if (slotReelInterval) {
118
+ clearInterval(slotReelInterval);
119
+ slotReelInterval = null;
120
+ }
121
+ if (slotResultInterval) {
122
+ clearInterval(slotResultInterval);
123
+ slotResultInterval = null;
124
+ }
125
+ if (slotResultClearTimeout) {
126
+ clearTimeout(slotResultClearTimeout);
127
+ slotResultClearTimeout = null;
128
+ }
129
+ isSpinning = false;
130
+ slotReelFrame = 0;
131
+ slotResult = null;
132
+ slotResultIsWin = false;
133
+ slotResultFlashFrame = 0;
134
+ slotResultLabel = null;
135
+ slotResultRenderCallback = null;
136
+ }
137
+
105
138
  /**
106
139
  * Toggle casino mode
107
140
  * @returns {boolean} New state
@@ -312,8 +345,11 @@ function stopSlotReels(hadUpdates = false, renderCallback = null, winLevel = nul
312
345
  slotResult.push(SLOT_SYMBOLS[idx]);
313
346
  }
314
347
 
315
- // Display for 2 seconds then fade
316
- setTimeout(() => {
348
+ // Display for 2 seconds then fade. Store the handle so disable() /
349
+ // resetSlotState() can cancel it — otherwise a delayed clear fires
350
+ // mid-way through the next enabled session and nulls live state.
351
+ slotResultClearTimeout = setTimeout(() => {
352
+ slotResultClearTimeout = null;
317
353
  slotResult = null;
318
354
  slotResultLabel = null;
319
355
  if (slotResultRenderCallback) slotResultRenderCallback();
@@ -326,6 +362,7 @@ function stopSlotReels(hadUpdates = false, renderCallback = null, winLevel = nul
326
362
  * @returns {Object|null}
327
363
  */
328
364
  function getSlotResultLabel() {
365
+ if (!casinoEnabled) return null;
329
366
  return slotResultLabel;
330
367
  }
331
368
 
@@ -334,6 +371,7 @@ function getSlotResultLabel() {
334
371
  * @returns {boolean}
335
372
  */
336
373
  function isSlotSpinning() {
374
+ if (!casinoEnabled) return false;
337
375
  return isSpinning;
338
376
  }
339
377
 
@@ -342,6 +380,7 @@ function isSlotSpinning() {
342
380
  * @returns {boolean}
343
381
  */
344
382
  function hasSlotResult() {
383
+ if (!casinoEnabled) return false;
345
384
  return slotResult !== null;
346
385
  }
347
386
 
@@ -350,6 +389,7 @@ function hasSlotResult() {
350
389
  * @returns {boolean}
351
390
  */
352
391
  function isSlotsActive() {
392
+ if (!casinoEnabled) return false;
353
393
  return isSpinning || slotResult !== null;
354
394
  }
355
395
 
@@ -358,6 +398,10 @@ function isSlotsActive() {
358
398
  * @returns {string}
359
399
  */
360
400
  function getSlotReelDisplay() {
401
+ // Defense-in-depth: even if stale state survived a disable/enable cycle,
402
+ // don't paint casino UI when the mode is off.
403
+ if (!casinoEnabled) return '';
404
+
361
405
  // Show result if we have one
362
406
  if (slotResult) {
363
407
  const reels = [];