forked from abner/for-legacy-web
feat(mobx): migrate audio settings
This commit is contained in:
@@ -4,17 +4,13 @@ import { mapToRecord } from "../../lib/conversion";
|
||||
|
||||
import { Fonts, MonospaceFonts, Overrides } from "../../context/Theme";
|
||||
|
||||
import { Sounds } from "../../assets/sounds/Audio";
|
||||
import { EmojiPack } from "../../components/common/Emoji";
|
||||
|
||||
import Persistent from "../interfaces/Persistent";
|
||||
import Store from "../interfaces/Store";
|
||||
import SAudio, { SoundOptions } from "./helpers/SAudio";
|
||||
import STheme from "./helpers/STheme";
|
||||
|
||||
export type SoundOptions = {
|
||||
[key in Sounds]?: boolean;
|
||||
};
|
||||
|
||||
export type EmojiPack = "mutant" | "twemoji" | "noto" | "openmoji";
|
||||
|
||||
interface ISettings {
|
||||
"notifications:desktop": boolean;
|
||||
"notifications:sounds": SoundOptions;
|
||||
@@ -37,6 +33,7 @@ export default class Settings implements Store, Persistent<ISettings> {
|
||||
private data: ObservableMap<string, unknown>;
|
||||
|
||||
theme: STheme;
|
||||
sounds: SAudio;
|
||||
|
||||
/**
|
||||
* Construct new Settings store.
|
||||
@@ -46,6 +43,7 @@ export default class Settings implements Store, Persistent<ISettings> {
|
||||
makeAutoObservable(this);
|
||||
|
||||
this.theme = new STheme(this);
|
||||
this.sounds = new SAudio(this);
|
||||
}
|
||||
|
||||
get id() {
|
||||
|
||||
107
src/mobx/stores/helpers/SAudio.ts
Normal file
107
src/mobx/stores/helpers/SAudio.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user