fix(theme-v2): ensure theme audio autoplays on load and handles unlock gesture
This commit is contained in:
1 parent
ad3fe7c586
commit
d38250a5e4
4 files changed
+36
-8
No files matched your search
@@ -76,6 +76,7 @@
|
|||||||
themeAssetName,
|
themeAssetName,
|
||||||
themeHasLaunchButton,
|
themeHasLaunchButton,
|
||||||
type ThemeV2Asset,
|
type ThemeV2Asset,
|
||||||
|
type ThemeV2Audio,
|
||||||
type ThemeV2Background,
|
type ThemeV2Background,
|
||||||
type ThemeV2BehaviorTarget,
|
type ThemeV2BehaviorTarget,
|
||||||
type ThemeV2ButtonAction,
|
type ThemeV2ButtonAction,
|
||||||
@@ -252,6 +253,7 @@
|
|||||||
let lastGradientBackground = $state<Extract<ThemeV2Background, { type: 'gradient' }> | undefined>(
|
let lastGradientBackground = $state<Extract<ThemeV2Background, { type: 'gradient' }> | undefined>(
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
|
let lastAudio = $state<ThemeV2Audio | undefined>(undefined);
|
||||||
let assetBase = $state('');
|
let assetBase = $state('');
|
||||||
let savedFolder = $state<string | undefined>(undefined);
|
let savedFolder = $state<string | undefined>(undefined);
|
||||||
let editorFolderPath = $state<string | undefined>(undefined);
|
let editorFolderPath = $state<string | undefined>(undefined);
|
||||||
@@ -1803,6 +1805,7 @@
|
|||||||
? normalizeThemeV2(JSON.parse(context.themeJson) as Partial<ThemeV2Definition>)
|
? normalizeThemeV2(JSON.parse(context.themeJson) as Partial<ThemeV2Definition>)
|
||||||
: createDefaultThemeV2();
|
: createDefaultThemeV2();
|
||||||
definition = ensureDefaults(parsed);
|
definition = ensureDefaults(parsed);
|
||||||
|
lastAudio = parsed.audio ? { ...parsed.audio } : undefined;
|
||||||
savedFolder = context.folderName ?? undefined;
|
savedFolder = context.folderName ?? undefined;
|
||||||
editorFolderPath = context.folderPath ?? undefined;
|
editorFolderPath = context.folderPath ?? undefined;
|
||||||
const httpBase = await themeAssetBase();
|
const httpBase = await themeAssetBase();
|
||||||
@@ -1992,6 +1995,9 @@
|
|||||||
color: current.type === 'color' ? current.color : (lastColorBackground?.color ?? '#181825'),
|
color: current.type === 'color' ? current.color : (lastColorBackground?.color ?? '#181825'),
|
||||||
opacity: lastColorBackground?.opacity ?? opacity,
|
opacity: lastColorBackground?.opacity ?? opacity,
|
||||||
};
|
};
|
||||||
|
if (!definition.audio && lastAudio) {
|
||||||
|
definition.audio = { ...lastAudio };
|
||||||
|
}
|
||||||
} else if (type === 'gradient') {
|
} else if (type === 'gradient') {
|
||||||
definition.background = {
|
definition.background = {
|
||||||
type: 'gradient',
|
type: 'gradient',
|
||||||
@@ -2004,6 +2010,9 @@
|
|||||||
: (lastGradientBackground?.angle ?? 135),
|
: (lastGradientBackground?.angle ?? 135),
|
||||||
opacity: lastGradientBackground?.opacity ?? opacity,
|
opacity: lastGradientBackground?.opacity ?? opacity,
|
||||||
};
|
};
|
||||||
|
if (!definition.audio && lastAudio) {
|
||||||
|
definition.audio = { ...lastAudio };
|
||||||
|
}
|
||||||
} else if (type === 'video') {
|
} else if (type === 'video') {
|
||||||
const candidateVideo =
|
const candidateVideo =
|
||||||
current.type === 'video' && current.src
|
current.type === 'video' && current.src
|
||||||
@@ -2024,6 +2033,9 @@
|
|||||||
if (candidateVideo) {
|
if (candidateVideo) {
|
||||||
lastVideoBackground = { ...definition.background };
|
lastVideoBackground = { ...definition.background };
|
||||||
}
|
}
|
||||||
|
if (definition.audio) {
|
||||||
|
lastAudio = { ...definition.audio };
|
||||||
|
}
|
||||||
definition.audio = undefined;
|
definition.audio = undefined;
|
||||||
} else {
|
} else {
|
||||||
const candidateImage =
|
const candidateImage =
|
||||||
@@ -2043,6 +2055,9 @@
|
|||||||
if (candidateImage) {
|
if (candidateImage) {
|
||||||
lastImageBackground = { ...definition.background };
|
lastImageBackground = { ...definition.background };
|
||||||
}
|
}
|
||||||
|
if (!definition.audio && lastAudio) {
|
||||||
|
definition.audio = { ...lastAudio };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2086,6 +2101,7 @@
|
|||||||
const asset = await chooseAsset('audio');
|
const asset = await chooseAsset('audio');
|
||||||
if (!asset) return;
|
if (!asset) return;
|
||||||
definition.audio = { src: asset.name, loop: definition.audio?.loop !== false };
|
definition.audio = { src: asset.name, loop: definition.audio?.loop !== false };
|
||||||
|
lastAudio = { ...definition.audio };
|
||||||
}
|
}
|
||||||
|
|
||||||
function uniqueFamily(label: string) {
|
function uniqueFamily(label: string) {
|
||||||
@@ -5622,7 +5638,10 @@
|
|||||||
size="icon"
|
size="icon"
|
||||||
class="size-8 text-muted-foreground"
|
class="size-8 text-muted-foreground"
|
||||||
title="Remove music"
|
title="Remove music"
|
||||||
onclick={() => (definition.audio = undefined)}
|
onclick={() => {
|
||||||
|
definition.audio = undefined;
|
||||||
|
lastAudio = undefined;
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<X class="size-3.5" />
|
<X class="size-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { custom_theme_volume } from '$lib/global';
|
import { custom_theme_volume } from '$lib/global';
|
||||||
import { themeMediaSource, themeVideoLifecycle } from '$lib/themeMedia';
|
import { playThemeMedia, themeMediaSource, themeVideoLifecycle } from '$lib/themeMedia';
|
||||||
import type { ThemeV2Definition } from '$lib/themeV2';
|
import type { ThemeV2Definition } from '$lib/themeV2';
|
||||||
import { themeAssetUrl } from '$lib/themeV2';
|
import { themeAssetUrl } from '$lib/themeV2';
|
||||||
import { reduceAnimations } from '$lib/userSettings';
|
import { reduceAnimations } from '$lib/userSettings';
|
||||||
@@ -64,6 +64,14 @@
|
|||||||
if (animFrame !== undefined) {
|
if (animFrame !== undefined) {
|
||||||
cancelAnimationFrame(animFrame);
|
cancelAnimationFrame(animFrame);
|
||||||
}
|
}
|
||||||
|
if (audioElement) {
|
||||||
|
try {
|
||||||
|
audioElement.pause();
|
||||||
|
audioElement.src = '';
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const assetUrl = (path: string | undefined) => {
|
const assetUrl = (path: string | undefined) => {
|
||||||
@@ -126,10 +134,8 @@
|
|||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (!audioElement || !definition.audio) return;
|
if (!audioElement || !definition.audio) return;
|
||||||
audioElement.volume = $custom_theme_volume;
|
audioElement.volume = $custom_theme_volume;
|
||||||
if (!preview) {
|
if (!preview && audioElement.paused) {
|
||||||
audioElement.play().catch(() => {
|
playThemeMedia(audioElement);
|
||||||
// Autoplay can be rejected until the window has been interacted with.
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -225,6 +231,8 @@
|
|||||||
use:themeMediaSource={assetUrl(definition.audio.src)}
|
use:themeMediaSource={assetUrl(definition.audio.src)}
|
||||||
loop={definition.audio.loop !== false}
|
loop={definition.audio.loop !== false}
|
||||||
autoplay
|
autoplay
|
||||||
|
preload="auto"
|
||||||
|
playsinline
|
||||||
></audio>
|
></audio>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ const armAutoplayRetry = (node: HTMLMediaElement) => {
|
|||||||
if (node.isConnected) {
|
if (node.isConnected) {
|
||||||
node.muted = false;
|
node.muted = false;
|
||||||
const targetVolume = get(custom_theme_volume);
|
const targetVolume = get(custom_theme_volume);
|
||||||
if (targetVolume > 0) node.volume = targetVolume;
|
if (targetVolume >= 0) node.volume = targetVolume;
|
||||||
void node.play().catch(() => {});
|
void node.play().catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -230,7 +230,7 @@ export const playThemeMedia = (node: HTMLMediaElement) => {
|
|||||||
|
|
||||||
node.muted = false;
|
node.muted = false;
|
||||||
const currentVolume = get(custom_theme_volume);
|
const currentVolume = get(custom_theme_volume);
|
||||||
if (node.volume === 0 && currentVolume > 0) {
|
if (currentVolume >= 0) {
|
||||||
node.volume = currentVolume;
|
node.volume = currentVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -434,6 +434,7 @@ export const loadTheme = async (theme: Theme, themeContainer: HTMLElement, volum
|
|||||||
if (theme.definition) {
|
if (theme.definition) {
|
||||||
setGlobalVolume(volume);
|
setGlobalVolume(volume);
|
||||||
disableMediaControls();
|
disableMediaControls();
|
||||||
|
void invoke('unlock_media_autoplay').catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (theme.scriptUrl.length > 0) {
|
if (theme.scriptUrl.length > 0) {
|
||||||
|
|||||||
Reference in new issue
Block a user