Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/components/AMLL/LyricPlayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ const syncPlaybackTime = (time: number) => {
const player = getInternalPlayer();
if (!player) return;

const previousHotLines = new Set(player.hotLines ?? []);
const previousHotLines: Set<number> = new Set(player.hotLines ?? []);
player.setCurrentTime(time, false);
syncNewHotLineAnimations(player, previousHotLines, time);
};
Expand Down Expand Up @@ -262,7 +262,9 @@ onMounted(() => {
const wrapper = wrapperRef.value;
if (wrapper) {
playerRef.value = new CoreLyricPlayer();
wrapper.appendChild(playerRef.value.getElement());
const el = playerRef.value.getElement();
el.style.touchAction = "none";
wrapper.appendChild(el);
playerRef.value.addEventListener("line-click", lineClickHandler);
playerRef.value.addEventListener("line-contextmenu", lineContextMenuHandler);
}
Expand All @@ -278,23 +280,36 @@ onUnmounted(() => {
}
});

// 动画帧更新
// 限制单帧最大时间步长,避免后台恢复后动画突跳
// 设为 120ms 兼顾低端机偶发卡顿(≈30fps 下 33ms/帧),同时防止可见性切换前累计的大 delta 一次注入
const MAX_FRAME_DELTA = 120;

watchEffect((onCleanup) => {
if (!props.disabled) {
let canceled = false;
let lastTime = -1;
const resetLastTime = () => {
lastTime = -1;
};
const onVisibility = () => {
resetLastTime();
};
document.addEventListener("visibilitychange", onVisibility);
const onFrame = (time: number) => {
if (canceled) return;
if (lastTime === -1) {
lastTime = time;
}
playerRef.value?.update(time - lastTime);
const rawDelta = time - lastTime;
const delta = rawDelta > MAX_FRAME_DELTA ? MAX_FRAME_DELTA : rawDelta;
playerRef.value?.update(delta);
lastTime = time;
requestAnimationFrame(onFrame);
};
requestAnimationFrame(onFrame);
onCleanup(() => {
canceled = true;
document.removeEventListener("visibilitychange", onVisibility);
});
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/List/SongList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
? handlePointerDown($event, index, item.data.name || '未知曲目')
: undefined
"
@touchstart="
@touchstart.passive="
draggable
? handlePointerDown($event, index, item.data.name || '未知曲目')
: undefined
Expand Down
10 changes: 2 additions & 8 deletions src/components/Player/FullPlayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ const onMobileEnter = (el: Element, done: () => void) => {
parent.style.transform = "translate3d(0, 100vh, 0) scale(0.92)";
parent.style.borderRadius = "28px";
parent.style.backfaceVisibility = "hidden";
parent.style.backdropFilter = "blur(48px)";
parent.style.contain = "paint";
// 强制重排,确保起始状态生效
parent.getBoundingClientRect();
requestAnimationFrame(() => {
Expand All @@ -148,8 +146,6 @@ const onMobileEnter = (el: Element, done: () => void) => {
parent.style.willChange = "";
parent.style.transformOrigin = "";
parent.style.backfaceVisibility = "";
parent.style.backdropFilter = "";
parent.style.contain = "";
done();
}, 380);
};
Expand All @@ -165,8 +161,6 @@ const onMobileLeave = (el: Element, done: () => void) => {
parent.style.transition = MOBILE_CARD_LEAVE;
parent.style.borderRadius = "28px";
parent.style.backfaceVisibility = "hidden";
parent.style.backdropFilter = "blur(48px)";
parent.style.contain = "paint";
requestAnimationFrame(() => {
parent.style.transform = "translate3d(0, 100vh, 0) scale(0.92)";
});
Expand Down Expand Up @@ -339,13 +333,13 @@ watch(
onMounted(() => {
mainCoverColor.value = statusStore.mainColor;
if (isElectron && settingStore.preventSleep) {
window.electron.ipcRenderer.send("prevent-sleep", true);
window.electron?.ipcRenderer.send("prevent-sleep", true);
}
});

onBeforeUnmount(() => {
stopShow();
if (isElectron) window.electron.ipcRenderer.send("prevent-sleep", false);
if (isElectron) window.electron?.ipcRenderer.send("prevent-sleep", false);
});
</script>

Expand Down
19 changes: 14 additions & 5 deletions src/components/Player/FullPlayerMobile.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<script lang="ts">
let savedPageIndex = 0;
</script>

<template>
<div
ref="mobileStart"
Expand Down Expand Up @@ -179,17 +183,18 @@ const player = usePlayerController();
const { timeDisplay, toggleTimeFormat } = useTimeFormat();

const LYRIC_HEADER_MAX_PADDING = 60;
const AMLL_LINE_PADDING_MOBILE = 20;

const mobileStart = ref<HTMLElement | null>(null);
const topBarRef = ref<HTMLElement | null>(null);
const dragHandleRef = ref<HTMLElement | null>(null);
const pageIndex = ref(0);
// 当前歌曲无歌词时强制初始化为信息页,否则恢复模块级缓存
// 避免「上次停在歌词页 → 切到无歌词歌曲再打开」时 watch 不触发导致空白歌词页
const pageIndex = ref(
musicStore.isHasLrc && musicStore.playSong.type !== "radio" ? savedPageIndex : 0,
);

const lyricHeaderHorizontalPadding = computed(() => {
const padding =
Math.max(0, settingStore.lyricHorizontalOffset) +
(settingStore.useAMLyrics ? AMLL_LINE_PADDING_MOBILE : 0);
const padding = Math.max(0, settingStore.lyricHorizontalOffset);
return `${Math.min(padding, LYRIC_HEADER_MAX_PADDING)}px`;
});

Expand Down Expand Up @@ -381,6 +386,10 @@ watch(hasLyric, (value) => {
if (!value) pageIndex.value = 0;
});

watch(pageIndex, (value) => {
savedPageIndex = value;
});

const { direction, isSwiping, lengthX, lengthY } = useSwipe(mobileStart, {
threshold: 5,
onSwipeEnd: () => {
Expand Down
Loading