diff --git a/packages/app/constants/defaultSettings.json b/packages/app/constants/defaultSettings.json index f1cde562..3b2c9387 100755 --- a/packages/app/constants/defaultSettings.json +++ b/packages/app/constants/defaultSettings.json @@ -1,6 +1,7 @@ { - "themeVariant": "dark", "forceMobileMode": false, + "ui.effects": true, + "ui.general_volume": 50, "notifications_sound": true, "notifications_vibrate": true, "notifications_sound_volume": 50, @@ -10,11 +11,8 @@ "haptic_feedback": false, "collapseOnLooseFocus": true, "style.auto_darkMode": true, - "compactWidth": false, - "postCard_carrusel_auto": true, - "postCard_expansible_actions": true, "feed_max_fetch": 20, "style.compactMode": false, - "sidebar.floating": true, + "sidebar.floating": false, "language": "en" } \ No newline at end of file diff --git a/packages/app/constants/defaultSoundPack.json b/packages/app/constants/defaultSoundPack.json index 467a491d..c7fb1e78 100755 --- a/packages/app/constants/defaultSoundPack.json +++ b/packages/app/constants/defaultSoundPack.json @@ -1,5 +1,11 @@ { - "crash": "/sounds/crash.wav", - "error": "/sounds/error.wav", - "notification": "/sounds/notification.wav" + "id": "default", + "name": "Default Soundpack", + "author": "RageStudio", + "version": "1.0.0", + "sounds": { + "crash": "/sounds/crash.wav", + "error": "/sounds/error.wav", + "notification": "/sounds/notification.wav" + } } \ No newline at end of file diff --git a/packages/app/constants/settings/general/index.jsx b/packages/app/constants/settings/general/index.jsx index 8af7f8d7..de930446 100755 --- a/packages/app/constants/settings/general/index.jsx +++ b/packages/app/constants/settings/general/index.jsx @@ -74,6 +74,33 @@ export default { "description": "Enable low performance mode to reduce the memory usage and improve the performance in low-end devices. This will disable some animations and other decorative features.", "emitEvent": "app.lowPerformanceMode" }, + { + id: "ui.effects", + storaged: true, + group: "ui_sounds", + component: "Switch", + icon: "MdVolumeUp", + title: "UI effects", + description: "Enable the UI effects.", + }, + { + id: "ui.general_volume", + storaged: true, + group: "ui_sounds", + component: "Slider", + icon: "MdVolumeUp", + title: "UI volume", + description: "Set the volume of the app sounds.", + props: { + tipFormatter: (value) => { + return `${value}%` + }, + min: 0, + max: 100, + step: 10, + }, + emitEvent: "change:app.general_ui_volume" + }, { "id": "notifications_sound", "storaged": true, diff --git a/packages/app/src/App.jsx b/packages/app/src/App.jsx index 247cb8b8..0aadc223 100755 --- a/packages/app/src/App.jsx +++ b/packages/app/src/App.jsx @@ -202,6 +202,8 @@ class ComtyApp extends React.Component { }) }, openSearcher: (options) => { + app.cores.sound.useUIAudio("navigation.search") + window.app.ModalController.open((props) => ) }, openNavigationMenu: () => window.app.DrawerController.open("navigation", Navigation), @@ -252,6 +254,8 @@ class ComtyApp extends React.Component { return app.setLocation(config.app.mainPath ?? "/home") }, goToSettings: (setting_id) => { + app.cores.sound.useUIAudio("navigation.settings") + return app.setLocation(`/settings`, { query: { setting: setting_id @@ -484,6 +488,8 @@ class ComtyApp extends React.Component { }) } + //app.cores.sound.useUIAudio("splash_out") + app.eventBus.emit("app.initialization.start") await this.initialization() diff --git a/packages/app/src/components/Layout/sidebar/index.jsx b/packages/app/src/components/Layout/sidebar/index.jsx index fff64309..43993c8e 100755 --- a/packages/app/src/components/Layout/sidebar/index.jsx +++ b/packages/app/src/components/Layout/sidebar/index.jsx @@ -274,6 +274,8 @@ export default class Sidebar extends React.Component { return onClickHandlers[e.key](e) } + window.app.cores.sound.useUIAudio("sidebar.switch_tab") + if (typeof this.state.pathResolvers === "object") { if (typeof this.state.pathResolvers[e.key] !== "undefined") { return window.app.setLocation(`/${this.state.pathResolvers[e.key]}`, 150) diff --git a/packages/app/src/components/Layout/sidedrawer/index.jsx b/packages/app/src/components/Layout/sidedrawer/index.jsx index 090cf0cc..e10c85b4 100755 --- a/packages/app/src/components/Layout/sidedrawer/index.jsx +++ b/packages/app/src/components/Layout/sidedrawer/index.jsx @@ -153,8 +153,12 @@ export default class SidedrawerController extends React.Component { const drawerClasses = drawer.classList if (to) { + app.cores.sound.useUIAudio("sidebar.expand") + drawerClasses.remove("hided") } else { + app.cores.sound.useUIAudio("sidebar.collapse") + drawerClasses.add("hided") } } @@ -226,10 +230,10 @@ export default class SidedrawerController extends React.Component { return
{this.state.drawers}
diff --git a/packages/app/src/cores/notifications/index.jsx b/packages/app/src/cores/notifications/index.jsx index 2cfb2213..096f8e8a 100755 --- a/packages/app/src/cores/notifications/index.jsx +++ b/packages/app/src/cores/notifications/index.jsx @@ -7,7 +7,7 @@ import { Haptics } from "@capacitor/haptics" export default class NotificationCore extends Core { static refName = "notifications" - + onEvents = { "changeNotificationsSoundVolume": (value) => { this.playAudio({ soundVolume: value }) @@ -117,8 +117,8 @@ export default class NotificationCore extends Core { const soundVolume = options.soundVolume ? options.soundVolume / 100 : this.getSoundVolume() if (soundEnabled) { - if (typeof window.app.sound?.play === "function") { - window.app.sound.play("notification", { + if (typeof window.app.cores.sound?.play === "function") { + window.app.cores.sound.play("notification", { volume: soundVolume, }) } diff --git a/packages/app/src/cores/sound/index.js b/packages/app/src/cores/sound/index.js index 5a22e91a..d0798911 100755 --- a/packages/app/src/cores/sound/index.js +++ b/packages/app/src/cores/sound/index.js @@ -12,22 +12,40 @@ export default class SoundCore extends Core { soundsPool = {} public = { - play: this.play, - getSounds: this.getSounds, + play: this.play.bind(this), + loadSoundpack: this.loadSoundpack.bind(this), + useUIAudio: function (audio_id) { + try { + if (window.app.cores.settings.is("ui.effects", true)) { + this.play(audio_id) + } + } catch (error) { + console.error(error) + } + }.bind(this) } - async initialize() { + listenEvents = { + "change:app.general_ui_volume": (volume) => { + // play a sound to test volume + this.play("test", { + volume: volume / 100, + }) + } + } + + async loadSoundpack(manifest) { let soundpack = config.defaultSoundPack ?? {} - const storedCustomSoundpack = store.get("soundpack_manifest") + const storedCustomSoundpack = manifest ?? store.get("soundpack_manifest") if (storedCustomSoundpack) { // check if is valid url with regex const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/; - + if (urlRegex.test(storedCustomSoundpack)) { - // load with axios - const { data } = await axios.get(storedCustomSoundpack) + // load with axios + const { data } = await axios.get(storedCustomSoundpack) soundpack = data } else { @@ -36,26 +54,66 @@ export default class SoundCore extends Core { } } - for (const [name, path] of Object.entries(soundpack)) { + if (typeof soundpack.sounds !== "object") { + console.error(`Soundpack [${soundpack.id}] is not a valid soundpack.`) + return false + } + + console.log(`Loading soundpack [${soundpack.id} | ${soundpack.name}] by ${soundpack.author} (${soundpack.version})`) + + for (const [name, path] of Object.entries(soundpack.sounds)) { this.soundsPool[name] = new Howl({ - volume: window.app.cores.settings.get("generalAudioVolume") ?? 0.5, + volume: 0.5, src: [path], }) } - - console.log(this.soundsPool) } - async play(name, options) { - if (this.soundsPool[name]) { - return new Howl({ - volume: window.app.cores.settings.get("generalAudioVolume") ?? 0.5, - ...options, - src: [soundPack[name]], - }).play() - } else { + async injectUseUIAudio() { + const injectOnButtons = (event) => { + // search for closest button + const button = event.target.closest("button") + + // if button exist and has aria-checked attribute then play switch_on or switch_off + if (button) { + if (button.hasAttribute("aria-checked")) { + return this.public.useUIAudio(button.getAttribute("aria-checked") === "true" ? "component.slider_down" : "component.slider_up") + } + + return this.public.useUIAudio("generic_click") + } + } + + document.addEventListener("click", (event) => { + injectOnButtons(event) + }, true) + } + + async play(name, options = {}) { + const audioInstance = this.soundsPool[name] + + if (!audioInstance) { console.error(`Sound [${name}] not found or is not available.`) return false } + + if (typeof options.volume !== "undefined") { + audioInstance.volume(options.volume) + } else { + audioInstance.volume((window.app.cores.settings.get("ui.general_volume") ?? 0) / 100) + } + + audioInstance.play() + } + + async onInitialize() { + await this.loadSoundpack() + + // listen eventBus + for (const [eventName, callback] of Object.entries(this.listenEvents)) { + window.app.eventBus.on(eventName, callback) + } + + this.injectUseUIAudio() } } \ No newline at end of file diff --git a/packages/app/src/pages/settings/index.jsx b/packages/app/src/pages/settings/index.jsx index 5f441613..acd2086e 100755 --- a/packages/app/src/pages/settings/index.jsx +++ b/packages/app/src/pages/settings/index.jsx @@ -551,6 +551,8 @@ export default () => { return menuEvents[event.key]() } + app.cores.sound.useUIAudio("navigation") + setActiveKey(event.key) }