refactor progress

This commit is contained in:
Hampus Kraft
2026-02-17 12:22:36 +00:00
parent cb31608523
commit d5abd1a7e4
8257 changed files with 1190207 additions and 761040 deletions

View File

@@ -17,17 +17,23 @@
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import {Logger} from '@app/lib/Logger';
import {makePersistent} from '@app/lib/MobXPersistence';
import * as SoundUtils from '@app/utils/SoundUtils';
import {SoundType} from '@app/utils/SoundUtils';
import {makeAutoObservable, runInAction} from 'mobx';
import {makePersistent} from '~/lib/MobXPersistence';
import * as SoundUtils from '~/utils/SoundUtils';
import {SoundType} from '~/utils/SoundUtils';
interface SoundSettings {
export interface SoundSettings {
allSoundsDisabled: boolean;
disabledSounds: Partial<Record<SoundType, boolean>>;
}
class SoundStore {
private logger = new Logger('SoundStore');
private inFlightLoopSounds = new Set<SoundType>();
private pendingLoopSounds = new Set<SoundType>();
private loopPlayTokens = new Map<SoundType, number>();
private unlockListenersAttached = false;
currentlyPlaying = new Set<SoundType>();
volume = 0.7;
incomingCallActive = false;
@@ -37,10 +43,17 @@ class SoundStore {
};
constructor() {
makeAutoObservable(
makeAutoObservable<
SoundStore,
'inFlightLoopSounds' | 'pendingLoopSounds' | 'loopPlayTokens' | 'unlockListenersAttached'
>(
this,
{
currentlyPlaying: false,
inFlightLoopSounds: false,
pendingLoopSounds: false,
loopPlayTokens: false,
unlockListenersAttached: false,
},
{autoBind: true},
);
@@ -56,9 +69,30 @@ class SoundStore {
return;
}
SoundUtils.playSound(sound, loop, this.volume)
if (loop) {
if (this.isPlayingSound(sound) || this.inFlightLoopSounds.has(sound) || this.pendingLoopSounds.has(sound)) {
return;
}
this.inFlightLoopSounds.add(sound);
}
const token = loop ? this.bumpLoopToken(sound) : 0;
SoundUtils.playSound(sound, loop, this.volume, () => {
if (loop) {
this.queuePendingLoopSound(sound);
}
})
.then((result) => {
if (loop) {
this.inFlightLoopSounds.delete(sound);
}
if (result) {
if (loop && this.getLoopToken(sound) !== token) {
void SoundUtils.stopSound(sound);
return;
}
this.clearPendingLoopSound(sound);
runInAction(() => {
const newPlaying = new Set(this.currentlyPlaying);
newPlaying.add(sound);
@@ -66,10 +100,18 @@ class SoundStore {
});
}
})
.catch((error) => console.warn('Failed to play sound:', error));
.catch((error) => {
if (loop) {
this.inFlightLoopSounds.delete(sound);
}
this.logger.warn('Failed to play sound:', error);
});
}
stopSound(sound: SoundType): void {
this.bumpLoopToken(sound);
this.inFlightLoopSounds.delete(sound);
this.clearPendingLoopSound(sound);
SoundUtils.stopSound(sound);
const newPlaying = new Set(this.currentlyPlaying);
newPlaying.delete(sound);
@@ -77,14 +119,23 @@ class SoundStore {
}
stopAllSounds(): void {
this.clearPendingLoopSounds();
this.inFlightLoopSounds.clear();
this.loopPlayTokens.clear();
SoundUtils.stopAllSounds();
this.currentlyPlaying = new Set();
this.incomingCallActive = false;
}
startIncomingRing(): void {
this.playSound(SoundType.IncomingRing, true);
this.incomingCallActive = true;
if (this.isPlayingSound(SoundType.IncomingRing) || this.inFlightLoopSounds.has(SoundType.IncomingRing)) {
return;
}
if (this.pendingLoopSounds.has(SoundType.IncomingRing)) {
return;
}
this.playSound(SoundType.IncomingRing, true);
}
stopIncomingRing(): void {
@@ -102,7 +153,7 @@ class SoundStore {
allSoundsDisabled: !this.settings.allSoundsDisabled,
};
if (this.settings.allSoundsDisabled) {
SoundUtils.stopAllSounds();
this.stopAllSounds();
}
}
@@ -129,6 +180,9 @@ class SoundStore {
...this.settings,
disabledSounds: newDisabledSounds,
};
if (!enabled) {
this.clearPendingLoopSound(soundType);
}
}
}
@@ -159,6 +213,90 @@ class SoundStore {
isPlayingSound(sound: SoundType): boolean {
return this.currentlyPlaying.has(sound);
}
private bumpLoopToken(sound: SoundType): number {
const nextToken = (this.loopPlayTokens.get(sound) ?? 0) + 1;
this.loopPlayTokens.set(sound, nextToken);
return nextToken;
}
private getLoopToken(sound: SoundType): number {
return this.loopPlayTokens.get(sound) ?? 0;
}
private queuePendingLoopSound(sound: SoundType): void {
if (this.pendingLoopSounds.has(sound)) {
return;
}
this.pendingLoopSounds.add(sound);
this.attachUnlockListeners();
}
private clearPendingLoopSound(sound: SoundType): void {
if (this.pendingLoopSounds.delete(sound)) {
this.detachUnlockListenersIfIdle();
}
}
private clearPendingLoopSounds(): void {
this.pendingLoopSounds.clear();
this.detachUnlockListeners();
}
private attachUnlockListeners(): void {
if (this.unlockListenersAttached) {
return;
}
this.unlockListenersAttached = true;
window.addEventListener('pointerdown', this.handleAutoplayUnlock, {passive: true});
window.addEventListener('keydown', this.handleAutoplayUnlock);
}
private detachUnlockListenersIfIdle(): void {
if (this.pendingLoopSounds.size > 0) {
return;
}
this.detachUnlockListeners();
}
private detachUnlockListeners(): void {
if (!this.unlockListenersAttached) {
return;
}
window.removeEventListener('pointerdown', this.handleAutoplayUnlock);
window.removeEventListener('keydown', this.handleAutoplayUnlock);
this.unlockListenersAttached = false;
}
private handleAutoplayUnlock(): void {
this.retryPendingLoopSounds();
}
private retryPendingLoopSounds(): void {
if (this.pendingLoopSounds.size === 0) {
this.detachUnlockListeners();
return;
}
for (const sound of Array.from(this.pendingLoopSounds)) {
if (!this.isSoundEnabled(sound)) {
this.pendingLoopSounds.delete(sound);
continue;
}
if (sound === SoundType.IncomingRing && !this.incomingCallActive) {
this.pendingLoopSounds.delete(sound);
continue;
}
if (this.isPlayingSound(sound) || this.inFlightLoopSounds.has(sound)) {
this.pendingLoopSounds.delete(sound);
continue;
}
this.pendingLoopSounds.delete(sound);
this.playSound(sound, true);
}
this.detachUnlockListenersIfIdle();
}
}
export default new SoundStore();