forked from abner/for-legacy-web
108 lines
2.8 KiB
TypeScript
108 lines
2.8 KiB
TypeScript
import { makeAutoObservable, computed, action } from "mobx";
|
|
|
|
import Settings from "../Settings";
|
|
import call_join from "./call_join.mp3";
|
|
import call_leave from "./call_leave.mp3";
|
|
import message from "./message.mp3";
|
|
import outbound from "./outbound.mp3";
|
|
|
|
export type Sounds = "message" | "outbound" | "call_join" | "call_leave";
|
|
|
|
export interface Sound {
|
|
enabled: boolean;
|
|
path: string;
|
|
}
|
|
|
|
export type SoundOptions = {
|
|
[key in Sounds]?: Partial<Sound>;
|
|
};
|
|
|
|
export const DefaultSoundPack: { [key in Sounds]: string } = {
|
|
message,
|
|
outbound,
|
|
call_join,
|
|
call_leave,
|
|
};
|
|
|
|
export const ALL_SOUNDS: Sounds[] = [
|
|
"message",
|
|
"outbound",
|
|
"call_join",
|
|
"call_leave",
|
|
];
|
|
export const DEFAULT_SOUNDS: Sounds[] = ["message", "call_join", "call_leave"];
|
|
|
|
/**
|
|
* Helper class for reading and writing themes.
|
|
*/
|
|
export default class SAudio {
|
|
private settings: Settings;
|
|
private cache: Map<string, HTMLAudioElement>;
|
|
|
|
/**
|
|
* Construct a new sound helper.
|
|
* @param settings Settings parent class
|
|
*/
|
|
constructor(settings: Settings) {
|
|
this.settings = settings;
|
|
makeAutoObservable(this);
|
|
|
|
this.cache = new Map();
|
|
|
|
// Asynchronously load Audio files into cache.
|
|
setTimeout(() => this.loadCache(), 0);
|
|
}
|
|
|
|
@action setEnabled(sound: Sounds, enabled: boolean) {
|
|
const obj = this.settings.get("notifications:sounds");
|
|
this.settings.set("notifications:sounds", {
|
|
...obj,
|
|
[sound]: {
|
|
...obj?.[sound],
|
|
enabled,
|
|
},
|
|
});
|
|
}
|
|
|
|
@computed getSound(sound: Sounds, options?: SoundOptions): Sound {
|
|
return {
|
|
path: DefaultSoundPack[sound],
|
|
enabled: DEFAULT_SOUNDS.includes(sound),
|
|
...(options ?? this.settings.get("notifications:sounds"))?.[sound],
|
|
};
|
|
}
|
|
|
|
@computed getState(): ({ id: Sounds } & Sound)[] {
|
|
const options = this.settings.get("notifications:sounds");
|
|
return ALL_SOUNDS.map((id) => {
|
|
return { id, ...this.getSound(id, options) };
|
|
});
|
|
}
|
|
|
|
getAudio(path: string) {
|
|
if (this.cache.has(path)) {
|
|
return this.cache.get(path)!;
|
|
} else {
|
|
const el = new Audio(path);
|
|
this.cache.set(path, el);
|
|
return el;
|
|
}
|
|
}
|
|
|
|
loadCache() {
|
|
this.getState().map(({ path }) => this.getAudio(path));
|
|
}
|
|
|
|
playSound(sound: Sounds) {
|
|
const definition = this.getSound(sound);
|
|
if (definition.enabled) {
|
|
const audio = this.getAudio(definition.path);
|
|
try {
|
|
audio.play();
|
|
} catch (err) {
|
|
console.error("Hit error while playing", sound + ":", err);
|
|
}
|
|
}
|
|
}
|
|
}
|