pixi-rainman-game-engine 0.3.31-b → 0.3.32
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/dist/SettingsUI/components/AutoplaySettings/index.jsx +5 -62
- package/dist/application/SoundManager/SoundManager.d.ts +12 -0
- package/dist/application/SoundManager/SoundManager.js +31 -6
- package/dist/controllers/AbstractController.d.ts +2 -0
- package/dist/controllers/AbstractController.js +28 -12
- package/dist/stores/SettingsStore.d.ts +0 -6
- package/dist/stores/SettingsStore.js +1 -16
- package/dist/utils/common/sound.d.ts +1 -2
- package/dist/utils/common/sound.js +60 -10
- package/package.json +1 -1
|
@@ -2,87 +2,30 @@ import "react-custom-scroll/dist/customScroll.css";
|
|
|
2
2
|
import "./autoplaySettings.css";
|
|
3
3
|
import i18next from "i18next";
|
|
4
4
|
import { observer } from "mobx-react-lite";
|
|
5
|
-
import React
|
|
5
|
+
import React from "react";
|
|
6
6
|
import { COMPONENTS } from "../../../components";
|
|
7
7
|
import { UI_ITEMS } from "../../../utils";
|
|
8
8
|
import { useStores } from "../../hooks";
|
|
9
9
|
import { CloseModalButton } from "../CloseModalButton";
|
|
10
10
|
import { RichLimitingSlider } from "../RichLimitingSlider";
|
|
11
11
|
import { SpeedButtonWithHeader, SwitchWithHeader } from "../SwitchWithHeader";
|
|
12
|
+
const initialAutoSpinCount = 10;
|
|
13
|
+
const availableAutoSpinLimits = [10, 20, 50, 70, 100];
|
|
12
14
|
export const AutoplaySettings = observer(() => {
|
|
13
|
-
const [limitNumbers, setLimitNumbers] = useState([0]);
|
|
14
|
-
const initialAutoSpinCount = 50;
|
|
15
|
-
const availableAutoSpinLimits = [10, 20, 50, 100, 150, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000];
|
|
16
15
|
const { settingStore } = useStores();
|
|
17
|
-
const calculateLimitBounds = (indexOfSelectedLimit) => {
|
|
18
|
-
let bottomLimitIndex = indexOfSelectedLimit - 2;
|
|
19
|
-
let topLimitIndex = indexOfSelectedLimit + 1;
|
|
20
|
-
if (bottomLimitIndex < 0) {
|
|
21
|
-
bottomLimitIndex = availableAutoSpinLimits.length - -bottomLimitIndex;
|
|
22
|
-
}
|
|
23
|
-
if (topLimitIndex === availableAutoSpinLimits.length) {
|
|
24
|
-
topLimitIndex = 0;
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
bottomLimitIndex,
|
|
28
|
-
topLimitIndex
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
16
|
const updateLimitsBounds = (newLimit) => {
|
|
32
17
|
setAutoSpinsCount(newLimit);
|
|
33
|
-
const indexOfSelectedSpinsLimit = availableAutoSpinLimits.findIndex((limitCount) => limitCount === newLimit);
|
|
34
|
-
if (indexOfSelectedSpinsLimit === -1) {
|
|
35
|
-
}
|
|
36
|
-
const { bottomLimitIndex, topLimitIndex } = calculateLimitBounds(indexOfSelectedSpinsLimit);
|
|
37
|
-
const limitNumbersIndexes = [];
|
|
38
|
-
for (let index = bottomLimitIndex; index !== topLimitIndex + 1; index++) {
|
|
39
|
-
if (index === availableAutoSpinLimits.length) {
|
|
40
|
-
index = 0;
|
|
41
|
-
}
|
|
42
|
-
limitNumbersIndexes.push(availableAutoSpinLimits[index]);
|
|
43
|
-
if (limitNumbersIndexes.length === 4) {
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
setLimitNumbers(limitNumbersIndexes);
|
|
48
18
|
};
|
|
49
|
-
|
|
50
|
-
updateLimitsBounds(initialAutoSpinCount);
|
|
51
|
-
}, []);
|
|
52
|
-
const { singleWinExceeds, balancedIncreased, balancedDecreased, howManyAutoSpinsLeft, infinitySpinsEnabled, setSingleWinExceeds, setBalancedIncreased, setBalancedDecreased, setAutoSpinsCount, flipInfinitySpinsFlag, resetAutoplaySettings } = settingStore;
|
|
19
|
+
const { singleWinExceeds, balancedIncreased, balancedDecreased, howManyAutoSpinsLeft, infinitySpinsEnabled, setSingleWinExceeds, setBalancedIncreased, setBalancedDecreased, setAutoSpinsCount, resetAutoplaySettings } = settingStore;
|
|
53
20
|
return (<div className="autoplay-settings">
|
|
54
21
|
<CloseModalButton layerId={UI_ITEMS.autoplay}/>
|
|
55
22
|
<div className="autoplay-settings__title">
|
|
56
23
|
<h2>{i18next.t("autoPlay")}</h2>
|
|
57
24
|
</div>
|
|
58
25
|
<div className="autoplay-settings__stop-limits">
|
|
59
|
-
<button className={`autoplay-settings__limit
|
|
60
|
-
let indexOfSelectedSpinsLimit = availableAutoSpinLimits.findIndex((limitCount) => limitCount === howManyAutoSpinsLeft);
|
|
61
|
-
indexOfSelectedSpinsLimit -= 1;
|
|
62
|
-
if (indexOfSelectedSpinsLimit === -1) {
|
|
63
|
-
indexOfSelectedSpinsLimit = availableAutoSpinLimits.length - 1;
|
|
64
|
-
}
|
|
65
|
-
updateLimitsBounds(availableAutoSpinLimits[indexOfSelectedSpinsLimit]);
|
|
66
|
-
}}>
|
|
67
|
-
<p>-</p>
|
|
68
|
-
</button>
|
|
69
|
-
{limitNumbers.map((limiter, index) => (<button key={`${limiter}${index}`} value={limiter} className={`autoplay-settings__limit ${limiter === howManyAutoSpinsLeft ? "autoplay-settings__limit--active" : ""} middle ${infinitySpinsEnabled ? "autoplay-settings__limit--infinity" : ""}`} disabled={settingStore.infinitySpinsEnabled} onClick={(event) => updateLimitsBounds(Number(event.currentTarget.value))}>
|
|
26
|
+
{availableAutoSpinLimits.map((limiter, index) => (<button key={`${limiter}${index}`} value={limiter} className={`autoplay-settings__limit ${limiter === howManyAutoSpinsLeft ? "autoplay-settings__limit--active" : ""} middle ${infinitySpinsEnabled ? "autoplay-settings__limit--infinity" : ""}`} disabled={settingStore.infinitySpinsEnabled} onClick={(event) => updateLimitsBounds(Number(event.currentTarget.value))}>
|
|
70
27
|
<p>{limiter}</p>
|
|
71
28
|
</button>))}
|
|
72
|
-
<button className={`autoplay-settings__limit right ${infinitySpinsEnabled ? "autoplay-settings__limit--infinity" : ""}`} onClick={() => {
|
|
73
|
-
let indexOfSelectedSpinsLimit = availableAutoSpinLimits.findIndex((limitCount) => limitCount === howManyAutoSpinsLeft);
|
|
74
|
-
indexOfSelectedSpinsLimit += 1;
|
|
75
|
-
if (indexOfSelectedSpinsLimit === availableAutoSpinLimits.length) {
|
|
76
|
-
indexOfSelectedSpinsLimit = 0;
|
|
77
|
-
}
|
|
78
|
-
const newAutoSpinsLimitNumber = availableAutoSpinLimits[indexOfSelectedSpinsLimit];
|
|
79
|
-
updateLimitsBounds(newAutoSpinsLimitNumber);
|
|
80
|
-
}}>
|
|
81
|
-
<p>+</p>
|
|
82
|
-
</button>
|
|
83
|
-
<button className={`autoplay-settings__limit circle ${infinitySpinsEnabled ? "autoplay-settings__limit--active" : ""}`} onClick={() => flipInfinitySpinsFlag()}>
|
|
84
|
-
<p>∞</p>
|
|
85
|
-
</button>
|
|
86
29
|
</div>
|
|
87
30
|
<div className="separator"/>
|
|
88
31
|
<div className="autoplay-settings__title">
|
|
@@ -64,6 +64,12 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
64
64
|
* @returns {void}
|
|
65
65
|
*/
|
|
66
66
|
resumeAll(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Restores currently active ambient loop if browser dropped it while page was inactive.
|
|
69
|
+
* @public
|
|
70
|
+
* @returns {void}
|
|
71
|
+
*/
|
|
72
|
+
restoreAmbientPlayback(): void;
|
|
67
73
|
/**
|
|
68
74
|
* Function for pausing all sounds in game
|
|
69
75
|
* If sound is not playing, it will be skipped
|
|
@@ -112,5 +118,11 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
112
118
|
* @returns {void}
|
|
113
119
|
*/
|
|
114
120
|
resumeOnFocus(): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Returns information if audio context is ready to play sounds.
|
|
123
|
+
* @public
|
|
124
|
+
* @returns {boolean} True when audio context is in running state.
|
|
125
|
+
*/
|
|
126
|
+
isAudioContextRunning(): boolean;
|
|
115
127
|
}
|
|
116
128
|
export declare const SoundManager: SoundManagerInstance;
|
|
@@ -170,6 +170,28 @@ export class SoundManagerInstance {
|
|
|
170
170
|
}
|
|
171
171
|
});
|
|
172
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Restores currently active ambient loop if browser dropped it while page was inactive.
|
|
175
|
+
* @public
|
|
176
|
+
* @returns {void}
|
|
177
|
+
*/
|
|
178
|
+
restoreAmbientPlayback() {
|
|
179
|
+
if (!RainMan.settingsStore.shouldPlayAmbientMusic) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const ambientTrack = RainMan.settingsStore.isFreeSpinsPlayEnabled
|
|
183
|
+
? SoundTracks.freeSpinsMusic
|
|
184
|
+
: SoundTracks.music;
|
|
185
|
+
const ambientMusic = this.musicCatalogue.get(ambientTrack);
|
|
186
|
+
if (!ambientMusic || ambientMusic.isPlaying) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (ambientMusic.paused) {
|
|
190
|
+
ambientMusic.resume();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
this.play(ambientTrack);
|
|
194
|
+
}
|
|
173
195
|
/**
|
|
174
196
|
* Function for pausing all sounds in game
|
|
175
197
|
* If sound is not playing, it will be skipped
|
|
@@ -240,13 +262,16 @@ export class SoundManagerInstance {
|
|
|
240
262
|
catch (error) {
|
|
241
263
|
console.error("Could not resume audio");
|
|
242
264
|
}
|
|
243
|
-
const ambientMusic = this.musicCatalogue.get(RainMan.settingsStore.isFreeSpinsPlayEnabled ? "freeSpinsMusic" : "music");
|
|
244
|
-
if (ambientMusic !== undefined &&
|
|
245
|
-
ambientMusic.isPlaying !== true &&
|
|
246
|
-
RainMan.settingsStore.shouldPlayAmbientMusic) {
|
|
247
|
-
ambientMusic.resume();
|
|
248
|
-
}
|
|
249
265
|
}
|
|
266
|
+
this.restoreAmbientPlayback();
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Returns information if audio context is ready to play sounds.
|
|
270
|
+
* @public
|
|
271
|
+
* @returns {boolean} True when audio context is in running state.
|
|
272
|
+
*/
|
|
273
|
+
isAudioContextRunning() {
|
|
274
|
+
return sound.context.audioContext.state === "running";
|
|
250
275
|
}
|
|
251
276
|
}
|
|
252
277
|
export const SoundManager = SoundManagerInstance.getInstance();
|
|
@@ -58,6 +58,7 @@ export declare abstract class AbstractController<T> {
|
|
|
58
58
|
protected buttonHeldSince: number;
|
|
59
59
|
shouldStopMobileSpin: boolean;
|
|
60
60
|
disableMessageBoxChange: boolean;
|
|
61
|
+
shouldClearQuickReelsStopAfterSpin: boolean;
|
|
61
62
|
protected resolveBigWin?: () => void;
|
|
62
63
|
protected resolveMysteryWin?: () => void;
|
|
63
64
|
protected resolveBonusWin?: () => void;
|
|
@@ -384,6 +385,7 @@ export declare abstract class AbstractController<T> {
|
|
|
384
385
|
* @returns {Promise<void>}
|
|
385
386
|
*/
|
|
386
387
|
private spin;
|
|
388
|
+
private cleanupDeferredQuickStop;
|
|
387
389
|
/**
|
|
388
390
|
* Function for invoking free spin plate, invoked in mainContainer
|
|
389
391
|
* ```ts
|
|
@@ -58,6 +58,7 @@ export class AbstractController {
|
|
|
58
58
|
buttonHeldSince = 0;
|
|
59
59
|
shouldStopMobileSpin = false;
|
|
60
60
|
disableMessageBoxChange = false;
|
|
61
|
+
shouldClearQuickReelsStopAfterSpin = false;
|
|
61
62
|
resolveBigWin;
|
|
62
63
|
resolveMysteryWin;
|
|
63
64
|
resolveBonusWin;
|
|
@@ -191,6 +192,10 @@ export class AbstractController {
|
|
|
191
192
|
keyboardEvent.preventDefault();
|
|
192
193
|
this.buttonHeldSince = 0;
|
|
193
194
|
this.columnsContainer.clearQuickReelsStop();
|
|
195
|
+
if (this.gamePhase === gamePhases.HANDLING_ACTIONS ||
|
|
196
|
+
this.gamePhase === gamePhases.STOPPING_HANDLING_ACTIONS) {
|
|
197
|
+
this.shouldPlayNextSpin = false;
|
|
198
|
+
}
|
|
194
199
|
}
|
|
195
200
|
});
|
|
196
201
|
window.addEventListener("blur", () => {
|
|
@@ -430,25 +435,26 @@ export class AbstractController {
|
|
|
430
435
|
initSpinButton() {
|
|
431
436
|
const refreshButton = RainMan.componentRegistry.get(RefreshButton.registryName);
|
|
432
437
|
this.clearMobileSpinTimeout = () => {
|
|
433
|
-
this.buttonHeldSince = 0;
|
|
434
438
|
const isSpinning = this.gamePhase === gamePhases.SPINNING ||
|
|
435
439
|
this.gamePhase === gamePhases.CONFIGURING_SPIN ||
|
|
436
440
|
this.gamePhase === gamePhases.DATA_FETCH;
|
|
437
|
-
|
|
438
|
-
this.columnsContainer.clearQuickReelsStop();
|
|
439
|
-
}
|
|
441
|
+
this.buttonHeldSince = 0;
|
|
440
442
|
if (this.mobileSpinTimeout) {
|
|
441
443
|
clearInterval(this.mobileSpinTimeout);
|
|
442
|
-
this.quickStopController.setQuickStopCounterLock(false);
|
|
443
444
|
this.mobileSpinTimeout = null;
|
|
444
|
-
if (!isSpinning) {
|
|
445
|
-
this.columnsContainer.clearQuickReelsStop();
|
|
446
|
-
}
|
|
447
445
|
}
|
|
448
446
|
if (this.mobileSpinDelay) {
|
|
449
447
|
clearTimeout(this.mobileSpinDelay);
|
|
450
448
|
this.mobileSpinDelay = null;
|
|
451
449
|
}
|
|
450
|
+
if (isSpinning) {
|
|
451
|
+
this.shouldClearQuickReelsStopAfterSpin = true;
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
455
|
+
this.quickStopController.setQuickStopCounterLock(false);
|
|
456
|
+
this.shouldClearQuickReelsStopAfterSpin = false;
|
|
457
|
+
}
|
|
452
458
|
};
|
|
453
459
|
refreshButton.setOnClick(() => {
|
|
454
460
|
this.handleSpinLogic();
|
|
@@ -726,10 +732,10 @@ export class AbstractController {
|
|
|
726
732
|
this.handleDisablingButtons(true);
|
|
727
733
|
RainMan.globals.shouldShowModals = false;
|
|
728
734
|
RainMan.settingsStore.closeCurrentlyOpenModal?.();
|
|
729
|
-
const realTime = Date.now() - this.buttonHeldSince;
|
|
730
|
-
if (realTime <= 500) {
|
|
731
|
-
|
|
732
|
-
}
|
|
735
|
+
// const realTime = Date.now() - this.buttonHeldSince;
|
|
736
|
+
// if (realTime <= 500) {
|
|
737
|
+
// this.columnsContainer.clearQuickReelsStop();
|
|
738
|
+
// }
|
|
733
739
|
if (this.mainContainer.freeSpinPlate) {
|
|
734
740
|
if (this.mainContainer.freeSpinPlate.shownAt === null ||
|
|
735
741
|
performance.now() - this.mainContainer.freeSpinPlate.shownAt <
|
|
@@ -810,6 +816,7 @@ export class AbstractController {
|
|
|
810
816
|
}
|
|
811
817
|
this.prepareBoughtFreeSpins();
|
|
812
818
|
if (RainMan.settingsStore.isAutoplayEnabled && !this.spinning) {
|
|
819
|
+
this.cleanupDeferredQuickStop();
|
|
813
820
|
this.changeGamePhase(gamePhases.IDLE);
|
|
814
821
|
this.spin();
|
|
815
822
|
return;
|
|
@@ -819,6 +826,7 @@ export class AbstractController {
|
|
|
819
826
|
this.changeGamePhase(gamePhases.IDLE);
|
|
820
827
|
}
|
|
821
828
|
if (this.gamePhase === gamePhases.IDLE || this.gamePhase === gamePhases.HANDLING_ACTIONS) {
|
|
829
|
+
this.cleanupDeferredQuickStop();
|
|
822
830
|
this.spin();
|
|
823
831
|
}
|
|
824
832
|
this.spinThrottlerTimeout = setTimeout(() => (this.spinThrottlerTimeout = null), 100);
|
|
@@ -1252,6 +1260,14 @@ export class AbstractController {
|
|
|
1252
1260
|
}, 0);
|
|
1253
1261
|
}
|
|
1254
1262
|
}
|
|
1263
|
+
cleanupDeferredQuickStop() {
|
|
1264
|
+
if (!this.shouldClearQuickReelsStopAfterSpin) {
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
this.columnsContainer.clearQuickReelsStop();
|
|
1268
|
+
this.quickStopController.setQuickStopCounterLock(false);
|
|
1269
|
+
this.shouldClearQuickReelsStopAfterSpin = false;
|
|
1270
|
+
}
|
|
1255
1271
|
/**
|
|
1256
1272
|
* Function for invoking free spin plate, invoked in mainContainer
|
|
1257
1273
|
* ```ts
|
|
@@ -327,12 +327,6 @@ export declare class SettingsStore {
|
|
|
327
327
|
* @returns {void}
|
|
328
328
|
*/
|
|
329
329
|
setAutoSpinsCount(count: number): void;
|
|
330
|
-
/**
|
|
331
|
-
* Flip the infinity spins flag
|
|
332
|
-
* @public
|
|
333
|
-
* @returns {void}
|
|
334
|
-
*/
|
|
335
|
-
flipInfinitySpinsFlag(): void;
|
|
336
330
|
/**
|
|
337
331
|
* Setter for the autoplay enabled flag
|
|
338
332
|
* @public
|
|
@@ -72,7 +72,6 @@ export class SettingsStore {
|
|
|
72
72
|
enableButtons;
|
|
73
73
|
useTakeAction;
|
|
74
74
|
initialAutoplaySettingsState = {
|
|
75
|
-
infinitySpinsEnabled: false,
|
|
76
75
|
onAnyWin: false,
|
|
77
76
|
howManyAutoSpinsLeft: INITIAL_AUTO_SPIN_COUNT,
|
|
78
77
|
singleWinExceeds: 0,
|
|
@@ -108,7 +107,6 @@ export class SettingsStore {
|
|
|
108
107
|
resetDataForSymbolPaytablePopup: action.bound,
|
|
109
108
|
decreaseAutoSpinsCount: action.bound,
|
|
110
109
|
setAutoSpinsCount: action.bound,
|
|
111
|
-
flipInfinitySpinsFlag: action.bound,
|
|
112
110
|
resetAutoplaySettings: action.bound,
|
|
113
111
|
setAutoPlayEnabledFlag: action.bound,
|
|
114
112
|
setNumberOfFreeSpin: action.bound,
|
|
@@ -541,7 +539,7 @@ export class SettingsStore {
|
|
|
541
539
|
* @returns {void}
|
|
542
540
|
*/
|
|
543
541
|
decreaseAutoSpinsCount() {
|
|
544
|
-
if (this.
|
|
542
|
+
if (this.isFreeSpinsPlayEnabled) {
|
|
545
543
|
return;
|
|
546
544
|
}
|
|
547
545
|
this.howManyAutoSpinsLeft -= 1;
|
|
@@ -553,20 +551,8 @@ export class SettingsStore {
|
|
|
553
551
|
* @returns {void}
|
|
554
552
|
*/
|
|
555
553
|
setAutoSpinsCount(count) {
|
|
556
|
-
if (this.infinitySpinsEnabled) {
|
|
557
|
-
this.setAutoSpinsCount(-1);
|
|
558
|
-
this.flipInfinitySpinsFlag();
|
|
559
|
-
}
|
|
560
554
|
this.howManyAutoSpinsLeft = count;
|
|
561
555
|
}
|
|
562
|
-
/**
|
|
563
|
-
* Flip the infinity spins flag
|
|
564
|
-
* @public
|
|
565
|
-
* @returns {void}
|
|
566
|
-
*/
|
|
567
|
-
flipInfinitySpinsFlag() {
|
|
568
|
-
this.infinitySpinsEnabled = !this.infinitySpinsEnabled;
|
|
569
|
-
}
|
|
570
556
|
/**
|
|
571
557
|
* Setter for the autoplay enabled flag
|
|
572
558
|
* @public
|
|
@@ -702,7 +688,6 @@ export class SettingsStore {
|
|
|
702
688
|
* @returns {void}
|
|
703
689
|
*/
|
|
704
690
|
resetAutoplaySettings() {
|
|
705
|
-
this.infinitySpinsEnabled = this.initialAutoplaySettingsState.infinitySpinsEnabled;
|
|
706
691
|
this.onAnyWin = this.initialAutoplaySettingsState.onAnyWin;
|
|
707
692
|
this.howManyAutoSpinsLeft = this.initialAutoplaySettingsState.howManyAutoSpinsLeft;
|
|
708
693
|
this.singleWinExceeds = this.initialAutoplaySettingsState.singleWinExceeds;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* This is using the visibilitychange event
|
|
2
|
+
* Sets up audio states for tab switches and iOS app interruptions.
|
|
4
3
|
* @returns {void}
|
|
5
4
|
*/
|
|
6
5
|
export declare const loadSoundsOnTabChange: () => void;
|
|
@@ -1,26 +1,76 @@
|
|
|
1
1
|
import { SoundManager } from "../../application";
|
|
2
2
|
import { RainMan } from "../../Rainman";
|
|
3
|
+
let shouldResumeAudioOnInterruption = false;
|
|
4
|
+
const removeInterruptedAudioResumeListeners = () => {
|
|
5
|
+
window.removeEventListener("pointerdown", resumeAudioOnInterruption);
|
|
6
|
+
window.removeEventListener("touchend", resumeAudioOnInterruption);
|
|
7
|
+
};
|
|
8
|
+
const interruptedAudioResume = () => {
|
|
9
|
+
if (shouldResumeAudioOnInterruption) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
shouldResumeAudioOnInterruption = true;
|
|
13
|
+
window.addEventListener("pointerdown", resumeAudioOnInterruption, { once: true });
|
|
14
|
+
window.addEventListener("touchend", resumeAudioOnInterruption, { once: true, passive: true });
|
|
15
|
+
};
|
|
3
16
|
/**
|
|
4
|
-
*
|
|
5
|
-
* If any time the sounds was enable than this will be resumed
|
|
6
|
-
* If the sounds was disabled than this will be not triggered
|
|
17
|
+
* Pauses audio when the page goes to the background.
|
|
7
18
|
* @returns {void}
|
|
8
19
|
*/
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
20
|
+
const pauseAudio = () => {
|
|
21
|
+
shouldResumeAudioOnInterruption = false;
|
|
22
|
+
removeInterruptedAudioResumeListeners();
|
|
23
|
+
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
24
|
+
SoundManager.pauseAll();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Restores audio when the page becomes active again.
|
|
29
|
+
* @returns {Promise<void>}
|
|
30
|
+
*/
|
|
31
|
+
const resumeAudio = async () => {
|
|
32
|
+
if (document.hidden || !RainMan.settingsStore.isSoundEnabled()) {
|
|
12
33
|
return;
|
|
13
34
|
}
|
|
14
|
-
if (RainMan.settingsStore.isSoundEnabled()
|
|
35
|
+
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
36
|
+
await SoundManager.resumeOnFocus();
|
|
15
37
|
SoundManager.resumeAll();
|
|
38
|
+
}
|
|
39
|
+
if (SoundManager.isAudioContextRunning()) {
|
|
40
|
+
shouldResumeAudioOnInterruption = false;
|
|
41
|
+
removeInterruptedAudioResumeListeners();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
interruptedAudioResume();
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Restore audio on the next user action if browser blocked it earlier.
|
|
48
|
+
* @returns {void}
|
|
49
|
+
*/
|
|
50
|
+
function resumeAudioOnInterruption() {
|
|
51
|
+
shouldResumeAudioOnInterruption = false;
|
|
52
|
+
removeInterruptedAudioResumeListeners();
|
|
53
|
+
resumeAudio();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if visibility is changed to pause or restore audio.
|
|
57
|
+
* @returns {void}
|
|
58
|
+
*/
|
|
59
|
+
const handleVisibilityChange = () => {
|
|
60
|
+
if (document.hidden) {
|
|
61
|
+
pauseAudio();
|
|
16
62
|
return;
|
|
17
63
|
}
|
|
64
|
+
resumeAudio();
|
|
18
65
|
};
|
|
19
66
|
/**
|
|
20
|
-
*
|
|
21
|
-
* This is using the visibilitychange event
|
|
67
|
+
* Sets up audio states for tab switches and iOS app interruptions.
|
|
22
68
|
* @returns {void}
|
|
23
69
|
*/
|
|
24
70
|
export const loadSoundsOnTabChange = () => {
|
|
25
|
-
document.addEventListener("visibilitychange",
|
|
71
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
72
|
+
window.addEventListener("pagehide", pauseAudio);
|
|
73
|
+
window.addEventListener("blur", pauseAudio);
|
|
74
|
+
window.addEventListener("pageshow", () => resumeAudio());
|
|
75
|
+
window.addEventListener("focus", () => resumeAudio());
|
|
26
76
|
};
|
package/package.json
CHANGED