mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
feat: improvements to background music plugin
This commit is contained in:
@@ -24,10 +24,11 @@
|
|||||||
async function handleFiles(files: FileList | null) {
|
async function handleFiles(files: FileList | null) {
|
||||||
const file = files?.[0]
|
const file = files?.[0]
|
||||||
if (!file) return
|
if (!file) return
|
||||||
// Restrict to WAV only for best responsiveness
|
// Accept WAV and MP3 files
|
||||||
const isWav = file.type === 'audio/wav' || file.name.toLowerCase().endsWith('.wav')
|
const isSupported = file.type === 'audio/wav' || file.type === 'audio/mpeg' ||
|
||||||
if (!isWav) {
|
file.name.toLowerCase().endsWith('.wav') || file.name.toLowerCase().endsWith('.mp3')
|
||||||
alert('Please select a .wav audio file')
|
if (!isSupported) {
|
||||||
|
alert('Please select a .wav or .mp3 audio file')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="flex relative justify-between items-center rounded-lg px-3 py-2 cursor-pointer select-none border border-zinc-300 dark:border-zinc-600 bg-white/20 dark:bg-zinc-800/30"
|
class="relative cursor-pointer select-none"
|
||||||
onclick={() => triggerSelect()}
|
onclick={() => triggerSelect()}
|
||||||
ondragover={(e) => { e.stopPropagation(); dragging = true }}
|
ondragover={(e) => { e.stopPropagation(); dragging = true }}
|
||||||
ondragleave={() => dragging = false}
|
ondragleave={() => dragging = false}
|
||||||
@@ -90,25 +91,27 @@
|
|||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex gap-3 items-center">
|
||||||
<div class="flex gap-2 items-center px-3 py-1 text-xs rounded-lg border border-dashed transition border-zinc-300 dark:border-zinc-600 text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300">
|
|
||||||
<span class="text-lg font-IconFamily">{'\ued47'}</span>
|
|
||||||
<span>{filename ? 'Change audio' : 'Upload audio'}</span>
|
|
||||||
</div>
|
|
||||||
{#if filename}
|
{#if filename}
|
||||||
|
<div class="flex items-center px-3 py-1 rounded-lg bg-zinc-200 dark:bg-zinc-800">
|
||||||
<div class="text-xs text-zinc-600 dark:text-zinc-300">
|
<div class="text-xs text-zinc-600 dark:text-zinc-300">
|
||||||
{filename}{#if durationText} • {durationText}{/if}
|
{filename}
|
||||||
|
<p>{durationText}</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{#if filename}
|
|
||||||
<button
|
<button
|
||||||
class="flex justify-center items-center m-1 text-lg dark:text-white size-7"
|
class="flex justify-center items-center m-1 text-lg dark:text-white size-7"
|
||||||
onclick={(e) => { e.stopPropagation(); removeAudio() }}
|
onclick={(e) => { e.stopPropagation(); removeAudio() }}
|
||||||
aria-label="Remove audio"
|
aria-label="Remove audio"
|
||||||
>×</button>
|
>×</button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="flex gap-2 items-center px-3 py-1 text-xs rounded-lg border border-dashed transition border-zinc-300 dark:border-zinc-600 text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 text-nowrap">
|
||||||
|
<span class="text-lg font-IconFamily">{'\ued47'}</span>
|
||||||
|
<span>Upload audio</span>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<input type="file" accept="audio/wav" class="hidden" bind:this={fileInput} onchange={onFileChange} />
|
</div>
|
||||||
|
<input type="file" accept="audio/wav,audio/mpeg" class="hidden" bind:this={fileInput} onchange={onFileChange} />
|
||||||
{#if dragging}
|
{#if dragging}
|
||||||
<div class="absolute inset-0 rounded-lg bg-zinc-200/40 dark:bg-zinc-700/40"></div>
|
<div class="absolute inset-0 rounded-lg bg-zinc-200/40 dark:bg-zinc-700/40"></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Plugin } from "@/plugins/core/types";
|
import type { Plugin } from "@/plugins/core/types";
|
||||||
import { componentSetting, defineSettings, numberSetting } from "@/plugins/core/settingsHelpers";
|
import { componentSetting, defineSettings, numberSetting, booleanSetting } from "@/plugins/core/settingsHelpers";
|
||||||
import styles from "./styles.css?inline";
|
import styles from "./styles.css?inline";
|
||||||
import BackgroundMusicSetting from "./BackgroundMusicSetting.svelte";
|
import BackgroundMusicSetting from "./BackgroundMusicSetting.svelte";
|
||||||
import localforage from "localforage";
|
import localforage from "localforage";
|
||||||
@@ -7,7 +7,7 @@ import localforage from "localforage";
|
|||||||
const settings = defineSettings({
|
const settings = defineSettings({
|
||||||
uploader: componentSetting({
|
uploader: componentSetting({
|
||||||
title: "Background Music",
|
title: "Background Music",
|
||||||
description: "Upload a .wav audio file to play in the background.",
|
description: "Upload a .wav or .mp3 audio file to play in the background.",
|
||||||
component: BackgroundMusicSetting,
|
component: BackgroundMusicSetting,
|
||||||
}),
|
}),
|
||||||
volume: numberSetting({
|
volume: numberSetting({
|
||||||
@@ -18,6 +18,11 @@ const settings = defineSettings({
|
|||||||
max: 1,
|
max: 1,
|
||||||
step: 0.05,
|
step: 0.05,
|
||||||
}),
|
}),
|
||||||
|
pauseOnHidden: booleanSetting({
|
||||||
|
title: "Pause when tab hidden",
|
||||||
|
description: "Pause music when switching to another tab or minimizing the browser",
|
||||||
|
default: true,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const store = localforage.createInstance({
|
const store = localforage.createInstance({
|
||||||
@@ -110,6 +115,14 @@ const backgroundMusicPlugin: Plugin<typeof settings> = {
|
|||||||
if (currentAudio) currentAudio.volume = Math.max(0, Math.min(1, vol));
|
if (currentAudio) currentAudio.volume = Math.max(0, Math.min(1, vol));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api.settings.onChange("pauseOnHidden" as any, (value: any) => {
|
||||||
|
const pauseOnHidden = (typeof value === "boolean" ? value : true) as boolean;
|
||||||
|
// If the setting is disabled and audio is currently paused due to tab being hidden, resume it
|
||||||
|
if (!pauseOnHidden && currentAudio && currentAudio.paused && document.visibilityState === "hidden") {
|
||||||
|
currentAudio.play().catch(() => {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Note: Stop button/event removed by user; no stop handling needed
|
// Note: Stop button/event removed by user; no stop handling needed
|
||||||
|
|
||||||
// Start if we have audio and autoplay is enabled
|
// Start if we have audio and autoplay is enabled
|
||||||
@@ -124,9 +137,12 @@ const backgroundMusicPlugin: Plugin<typeof settings> = {
|
|||||||
(window as any).__betterseqta_bg_music_cancel__ = cancel;
|
(window as any).__betterseqta_bg_music_cancel__ = cancel;
|
||||||
tryStart();
|
tryStart();
|
||||||
|
|
||||||
// Pause on tab hide, resume on show with a small delay
|
// Pause on tab hide, resume on show with a small delay (if enabled)
|
||||||
const visHandler = () => {
|
const visHandler = () => {
|
||||||
if (!currentAudio) return;
|
if (!currentAudio) return;
|
||||||
|
const pauseOnHidden = (api.settings as any).pauseOnHidden ?? true;
|
||||||
|
if (!pauseOnHidden) return;
|
||||||
|
|
||||||
if (document.visibilityState === "hidden") {
|
if (document.visibilityState === "hidden") {
|
||||||
if (visibilityResumeTimeout !== null) {
|
if (visibilityResumeTimeout !== null) {
|
||||||
clearTimeout(visibilityResumeTimeout);
|
clearTimeout(visibilityResumeTimeout);
|
||||||
|
|||||||
Reference in New Issue
Block a user