diff --git a/src/interface/components/Select.svelte b/src/interface/components/Select.svelte index 93b88fc6..007e16c3 100644 --- a/src/interface/components/Select.svelte +++ b/src/interface/components/Select.svelte @@ -131,7 +131,7 @@ right: 0; z-index: 50; margin: 0; - padding: 0.35rem; + padding: 0.5rem; list-style: none; border: 1px solid var(--theme-offset-bg, var(--theme-secondary, #e5e7eb)); border-radius: 14px; @@ -139,8 +139,11 @@ box-shadow: 0 10px 25px -5px rgb(0 0 0 / 0.25), 0 8px 10px -6px rgb(0 0 0 / 0.2); - max-height: 16rem; + max-height: 18rem; overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.125rem; } .select-option { @@ -150,9 +153,10 @@ border-radius: 10px; background: transparent; color: var(--text-primary); - padding: 0.5rem 0.75rem; + padding: 0.625rem 0.875rem; font-size: 0.875rem; font-weight: 500; + line-height: 1.35; text-align: left; cursor: pointer; transition: background-color 150ms ease; diff --git a/src/plugins/built-in/backgroundMusic/index.ts b/src/plugins/built-in/backgroundMusic/index.ts index 8c30a839..7e573f99 100644 --- a/src/plugins/built-in/backgroundMusic/index.ts +++ b/src/plugins/built-in/backgroundMusic/index.ts @@ -1,5 +1,10 @@ import type { Plugin } from "@/plugins/core/types"; -import { booleanSetting, componentSetting, defineSettings, numberSetting } from "@/plugins/core/settingsHelpers"; +import { + booleanSetting, + componentSetting, + defineSettings, + numberSetting, +} from "@/plugins/core/settingsHelpers"; import styles from "./styles.css?inline"; import BackgroundMusicSetting from "./BackgroundMusicSetting.svelte"; import localforage from "localforage"; @@ -20,7 +25,8 @@ const settings = defineSettings({ }), pauseOnHidden: booleanSetting({ title: "Pause when tab hidden", - description: "Pause music when switching to another tab or minimizing the browser", + description: + "Pause music when switching to another tab or minimizing the browser", default: true, }), }); @@ -30,10 +36,14 @@ const store = localforage.createInstance({ storeName: "music", }); +const HINT_ID = "bsplus-bg-music-hint"; + let currentAudio: HTMLAudioElement | null = null; let currentObjectUrl: string | null = null; let pendingGestureCancel: (() => void) | null = null; let visibilityResumeTimeout: number | null = null; +let hintElement: HTMLElement | null = null; +let isPlaying = false; async function loadAudioBlob(): Promise { const blob = await store.getItem("audio-blob"); @@ -51,6 +61,29 @@ function stopAndCleanupAudio(): void { URL.revokeObjectURL(currentObjectUrl); currentObjectUrl = null; } + isPlaying = false; +} + +function hideAutoplayHint(): void { + if (hintElement) { + hintElement.remove(); + hintElement = null; + } +} + +function showAutoplayHint(onActivate: () => void): void { + hideAutoplayHint(); + const hint = document.createElement("button"); + hint.id = HINT_ID; + hint.type = "button"; + hint.className = "bsplus-bg-music-hint"; + hint.textContent = "Tap to start background music"; + hint.addEventListener("pointerdown", (event) => { + event.preventDefault(); + onActivate(); + }); + document.body.appendChild(hint); + hintElement = hint; } function disarmGesturePlayback(): void { @@ -60,26 +93,14 @@ function disarmGesturePlayback(): void { } } -function armGesturePlayback(handler: () => void): void { - disarmGesturePlayback(); - const eventTypes = ["pointerdown", "keydown", "touchstart"] as const; - const listener = () => { - disarmGesturePlayback(); - handler(); - }; - for (const type of eventTypes) { - window.addEventListener(type, listener, { once: true, passive: true }); - } - pendingGestureCancel = () => { - for (const type of eventTypes) { - window.removeEventListener(type, listener); - } - }; -} - -async function startPlayback(volume: number): Promise { +/** Prepare