diff --git a/bun.lockb b/bun.lockb index ef47415..9febfb2 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index db822f6..d203dc2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": false, "module": "index.ts", "type": "module", - "workspaces": ["packages/web", "packages/core", "packages/electron"], + "workspaces": ["packages/web", "packages/core"], "scripts": { "electron:dev": "bun --filter 'electron' dev", "web:dev": "bun --filter 'web' dev", @@ -37,7 +37,6 @@ "concurrently": "^9.0.1", "cross-env": "^7.0.3" }, - "dependencies": {}, "trustedDependencies": [ "svelte-preprocess" ] diff --git a/packages/core/components/displayFPS.svelte b/packages/core/components/displayFPS.svelte new file mode 100644 index 0000000..8ee6ca0 --- /dev/null +++ b/packages/core/components/displayFPS.svelte @@ -0,0 +1,135 @@ + + +

+ {fps} fps
+ Frame Time: {frameTime.toFixed(2)} ms
+ 1% Low: {onePercentLow} fps +

+fps + +frametime + diff --git a/packages/core/components/lyrics/lyricLine.svelte b/packages/core/components/lyrics/lyricLine.svelte index ed1684c..55317aa 100644 --- a/packages/core/components/lyrics/lyricLine.svelte +++ b/packages/core/components/lyrics/lyricLine.svelte @@ -38,6 +38,7 @@ let isCurrentLyric = false; function updateY(timestamp: number) { + if (stopped) return; if (lastUpdateY === undefined) { lastUpdateY = new Date().getTime(); } @@ -52,6 +53,7 @@ } function updateX(timestamp: number) { + if (stopped) return; if (lastUpdateX === undefined) { lastUpdateX = timestamp; } @@ -70,6 +72,7 @@ * @param {number} pos - X offset, in pixels */ export const setX = (pos: number) => { + stopped = true; positionX = pos; }; @@ -78,6 +81,7 @@ * @param {number} pos - Y offset, in pixels */ export const setY = (pos: number) => { + stopped = true; positionY = pos; }; diff --git a/packages/core/components/lyrics/newLyrics.svelte b/packages/core/components/lyrics/newLyrics.svelte index 55463a2..45d5644 100644 --- a/packages/core/components/lyrics/newLyrics.svelte +++ b/packages/core/components/lyrics/newLyrics.svelte @@ -4,6 +4,7 @@ import LyricLine from './lyricLine.svelte'; import createLyricsSearcher from '@core/lyrics/lyricSearcher'; import userAdjustingProgress from '@core/state/userAdjustingProgress'; + import DisplayFps from '../displayFPS.svelte'; // constants const viewportHeight = document.documentElement.clientHeight; @@ -16,11 +17,16 @@ document.body.style.overflow = 'hidden'; // Props - let { originalLyrics, progress, player, showInteractiveBox } : { - originalLyrics: LyricData, - progress: number, - player: HTMLAudioElement | null, - showInteractiveBox: boolean + let { + originalLyrics, + progress, + player, + showInteractiveBox + }: { + originalLyrics: LyricData; + progress: number; + player: HTMLAudioElement | null; + showInteractiveBox: boolean; } = $props(); // States @@ -76,15 +82,28 @@ for (let i = 0; i < lyricElements.length; i++) { const currentLyricComponent = lyricComponents[i]; const lyric = originalLyrics.scripts[i]; + const lyricBeforeProgress = lyric.end < progress; + const lyricInProgress = lyric.start <= progress && progress <= lyric.end; + const lyricWillHigherThanViewport = lyricTopList[i + 3] - relativeOrigin < 0; + const lyricWillLowerThanViewport = lyricTopList[i - 3] - relativeOrigin > lyricsContainer?.getBoundingClientRect().height!; + let delay = 0; - if (progress > lyric.end) { + if (lyricBeforeProgress) { delay = 0; - } else if (lyric.start <= progress && progress <= lyric.end) { - delay = 0.042; + } else if (lyricInProgress) { + delay = 0.03; } else { delay = Math.min(Math.min(currentLyricDuration, 0.6), 0.067 * (i - currentLyricIndex + 1.2)); } - currentLyricComponent.update({ x: 0, y: lyricTopList[i] - relativeOrigin }, delay); + + // if it's not in the viewport, we need to use animations + if (lyricWillHigherThanViewport || lyricWillLowerThanViewport) { + currentLyricComponent.update({ x: 0, y: lyricTopList[i] - relativeOrigin }, delay); + } + // if it's still in the viewport, we need to use spring animation + else { + currentLyricComponent.update({ x: 0, y: lyricTopList[i] - relativeOrigin }, delay); + } } } @@ -111,11 +130,16 @@ }); function handleScroll(deltaY: number) { + if (lyricComponents[0].getInfo().y > 0 && deltaY < 0) { + deltaY = 0; + } + if (lyricComponents[lyricComponents.length - 1].getInfo().y < 100 && deltaY > 0) { + deltaY = 0; + } for (let i = 0; i < lyricElements.length; i++) { const currentLyricComponent = lyricComponents[i]; const currentY = currentLyricComponent.getInfo().y; scrolling = true; - currentLyricComponent.stop(); currentLyricComponent.setY(currentY - deltaY); currentLyricComponent.syncSpringWithDelta(deltaY); } @@ -200,21 +224,19 @@ lastEventProgress = progress; if (!lyricChanged || scrolling) return; if (!lyricIndexDeltaTooBig && deltaInRange) { - console.log("Event: regular move"); + console.log('Event: regular move'); console.log(new Date().getTime(), lastSeekForward); computeLayout(); - } - else if ($userAdjustingProgress) { + } else if ($userAdjustingProgress) { if (deltaTooBig && lyricChanged) { - console.log("Event: seek forward"); + console.log('Event: seek forward'); seekForward(); } else if (deltaIsNegative && lyricChanged) { - console.log("Event: seek backward"); + console.log('Event: seek backward'); seekForward(); } - } - else { - console.log("Event: regular move"); + } else { + console.log('Event: regular move'); computeLayout(); } }); @@ -253,16 +275,23 @@ {#if debugMode} + right-0 font-mono" + > progress: {progress.toFixed(2)}, nextUpdate: {nextUpdate}, scrolling: {scrolling}, current: {currentLyricIndex}, uap: {$userAdjustingProgress} +
+ +
{/if} {#if originalLyrics && originalLyrics.scripts}
{#each lyricLines as lyric, i} - + {/each}
{/if} diff --git a/packages/core/package.json b/packages/core/package.json index a4831a4..9893000 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -27,13 +27,12 @@ }, "dependencies": { "@alikia/aqualyrics": "npm:@jsr/alikia__aqualyrics", - "@applemusic-like-lyrics/core": "^0.1.3", - "@applemusic-like-lyrics/lyric": "^0.2.2", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-node-resolve": "^15.3.0", "@types/bun": "^1.1.6", "bezier-easing": "^2.1.0", + "chart.js": "^4.4.7", "jotai": "^2.8.0", "jotai-svelte": "^0.0.2", "jss": "^10.10.0", diff --git a/packages/web/package.json b/packages/web/package.json index 5b613dd..f8f03ee 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -37,8 +37,6 @@ }, "dependencies": { "@alikia/aqualyrics": "npm:@jsr/alikia__aqualyrics", - "@applemusic-like-lyrics/core": "^0.1.3", - "@applemusic-like-lyrics/lyric": "^0.2.4", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-node-resolve": "^15.3.0", diff --git a/packages/web/src/routes/play/[id]/+page.svelte b/packages/web/src/routes/play/[id]/+page.svelte index 59ec353..0db0d20 100644 --- a/packages/web/src/routes/play/[id]/+page.svelte +++ b/packages/web/src/routes/play/[id]/+page.svelte @@ -209,7 +209,7 @@ if (audioPlayer === null) return; if ($userAdjustingProgress === false) currentProgress = audioPlayer.currentTime; progressBarRaw.set(audioPlayer.currentTime); - }, 50); + }, 20); } onMount(() => { diff --git a/tsconfig.base.json b/tsconfig.base.json index a768407..75dbf4d 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -13,7 +13,8 @@ "sourceMap": true, "strict": true, "types": ["bun"] - } + }, + "exclude": ["node_modules", "build", "dist", "tmp"] // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files //