Skip to content

Commit 898ca8f

Browse files
committed
feat: add timeOffset and update icon
1 parent e3e9176 commit 898ca8f

File tree

13 files changed

+77
-31
lines changed

13 files changed

+77
-31
lines changed

src/components/icons/Brand.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Icon source: mic by iqonica from Noun Project (CC BY 3.0)
2+
// https://thenounproject.com/icon/mic-7993205/
3+
4+
const BrandIcon: React.FC<{ size: number }> = ({ size = 32 }) => {
5+
return (
6+
<svg
7+
xmlns="http://www.w3.org/2000/svg"
8+
viewBox="0 0 32 32"
9+
height={size}
10+
width={size}
11+
fill="currentColor"
12+
>
13+
<path d="M 29.922 22.449 L 27.591 21.605 C 27.117 21.433 26.762 21.071 26.576 20.606 L 25.629 18.11 C 25.342 17.368 24.7 17.008 24.057 17.008 C 23.414 17.008 22.756 17.368 22.486 18.11 L 21.538 20.606 C 21.354 21.071 20.997 21.433 20.523 21.605 L 18.19 22.449 C 16.686 22.983 16.686 25.152 18.19 25.705 L 20.523 26.547 C 20.997 26.721 21.354 27.083 21.538 27.546 L 22.486 30.045 C 22.773 30.784 23.414 31.147 24.057 31.147 C 24.7 31.147 25.359 30.784 25.629 30.045 L 26.576 27.546 C 26.762 27.083 27.117 26.721 27.591 26.547 L 29.922 25.705 C 31.429 25.17 31.429 23 29.922 22.449 Z M 26.729 24.102 C 25.562 24.517 24.647 25.428 24.192 26.6 L 24.022 27.03 L 23.852 26.6 C 23.413 25.43 22.484 24.517 21.315 24.102 L 21.232 24.068 L 21.315 24.034 C 22.484 23.622 23.396 22.709 23.852 21.537 L 24.022 21.106 L 24.192 21.537 C 24.63 22.708 25.562 23.622 26.729 24.034 L 26.811 24.068 L 26.729 24.102 Z" />
14+
<path d="M 7.589 3.304 L 8.233 3.53 C 8.366 3.581 8.467 3.683 8.519 3.805 L 8.79 4.494 C 8.875 4.701 9.042 4.804 9.228 4.804 C 9.414 4.804 9.584 4.701 9.669 4.494 L 9.939 3.805 C 9.99 3.667 10.091 3.581 10.226 3.53 L 10.868 3.304 C 11.291 3.15 11.291 2.564 10.868 2.408 L 10.226 2.184 C 10.091 2.132 9.99 2.029 9.939 1.909 L 9.669 1.219 C 9.584 1.012 9.414 0.909 9.228 0.909 C 9.042 0.909 8.875 1.012 8.79 1.219 L 8.519 1.909 C 8.467 2.045 8.366 2.132 8.233 2.184 L 7.589 2.408 C 7.168 2.564 7.168 3.15 7.589 3.304 Z" />
15+
<path d="M 2.684 10.793 C 2.921 10.879 3.124 11.07 3.21 11.309 L 3.7 12.603 C 3.852 12.982 4.174 13.172 4.511 13.172 C 4.849 13.172 5.189 12.982 5.323 12.603 L 5.813 11.309 C 5.898 11.07 6.099 10.879 6.337 10.793 L 7.556 10.363 C 8.333 10.088 8.333 8.969 7.556 8.676 L 6.337 8.246 C 6.101 8.16 5.899 7.969 5.813 7.728 L 5.323 6.438 C 5.17 6.058 4.849 5.869 4.511 5.869 C 4.174 5.869 3.835 6.058 3.7 6.438 L 3.21 7.728 C 3.126 7.969 2.923 8.16 2.684 8.246 L 1.467 8.676 C 0.69 8.952 0.69 10.072 1.467 10.363 L 2.684 10.793 Z" />
16+
<path d="M 13.964 25.446 C 12.931 25.135 11.815 25.135 10.785 25.446 C 9.618 25.789 8.621 26.512 7.86 27.081 C 7.15 27.596 6.474 28.079 5.78 28.322 C 5.156 28.527 4.531 28.493 4.157 28.235 C 3.903 28.061 3.752 27.754 3.735 27.442 L 3.735 27.357 C 4.224 27.563 4.716 27.667 5.224 27.667 C 6.102 27.667 6.981 27.341 7.658 26.702 C 9.839 24.793 12.291 22.829 14.674 20.951 C 16.128 19.798 17.583 18.646 18.985 17.472 C 19.054 17.472 19.139 17.491 19.206 17.491 C 21.253 17.491 23.248 16.664 24.718 15.167 C 27.761 12.067 27.761 7.023 24.718 3.906 C 21.659 0.807 16.705 0.825 13.661 3.906 C 12.037 5.559 11.244 7.849 11.412 10.156 C 9.907 12.049 8.234 13.978 6.593 15.838 C 5.038 17.612 3.431 19.453 1.994 21.244 C 0.948 22.465 0.878 24.187 1.708 25.582 C 1.37 26.185 1.167 26.857 1.199 27.562 C 1.251 28.664 1.809 29.698 2.688 30.352 C 3.331 30.818 4.143 31.056 4.987 31.056 C 5.513 31.056 6.036 30.97 6.562 30.8 C 7.627 30.438 8.521 29.785 9.368 29.164 C 10.112 28.613 10.789 28.147 11.482 27.944 C 12.039 27.769 12.667 27.769 13.224 27.944 C 14.306 28.27 15.269 29.251 16.132 30.093 C 16.621 30.592 17.433 30.592 17.924 30.093 C 18.414 29.596 18.414 28.77 17.924 28.269 C 16.91 27.252 15.66 25.996 13.968 25.479 L 13.964 25.446 Z M 15.467 5.713 C 16.5 4.662 17.852 4.146 19.203 4.146 C 20.555 4.146 21.91 4.662 22.94 5.713 C 24.986 7.814 25.003 11.241 22.94 13.324 C 21.907 14.375 20.506 14.892 19.051 14.856 L 18.816 14.823 C 17.598 14.65 16.5 14.118 15.62 13.29 C 14.776 12.499 14.217 11.465 13.996 10.347 C 13.743 8.662 14.284 6.938 15.467 5.732 L 15.467 5.713 Z M 3.936 22.897 C 5.376 21.122 6.964 19.298 8.503 17.542 C 9.753 16.114 11.04 14.632 12.256 13.172 C 12.628 13.892 13.086 14.564 13.658 15.152 C 14.302 15.805 15.046 16.321 15.841 16.701 C 14.926 17.423 14.015 18.164 13.101 18.886 C 10.7 20.799 8.214 22.779 5.966 24.742 C 5.493 25.188 4.75 25.138 4.174 24.604 C 3.616 24.107 3.498 23.366 3.92 22.882 L 3.936 22.897 Z" />
17+
</svg>
18+
);
19+
};
20+
21+
export default BrandIcon;

src/components/settings/helper/getBackgroundSettings.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type appStore from '@/store/appStore.ts';
33
import type { SectionProps } from '@/types/settingSchema.ts';
44
import { DEFAULT_APP_STATE } from '@constants';
55
import z from 'zod';
6+
import { BackgroundStateSchema } from '../../../schemas/appStoreSchema.ts';
67

78
export const getBackgroundSettings = (
89
state: ReturnType<typeof appStore.getState>
@@ -87,7 +88,8 @@ export const getBackgroundSettings = (
8788
value: options.customUrl ?? undefined,
8889
placeholder: 'Paste your image URL here...',
8990
visible: () => imageMode === 'custom',
90-
validation: (value) => z.url({ error: 'Invalid URL' }).safeParse(value),
91+
validation: (value) =>
92+
BackgroundStateSchema.shape.options.shape.customUrl.safeParse(value),
9193
onChange: (customUrl) => state.setBgOptions({ customUrl }),
9294
},
9395
],

src/components/settings/helper/getInterfaceSettings.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type appStore from '@/store/appStore.ts';
22
import type { SectionProps } from '@/types/settingSchema.ts';
3+
import { LyricsStateSchema } from '@/schemas/appStoreSchema.ts';
34

45
export const getInterfaceSettings = (state: ReturnType<typeof appStore.getState>): SectionProps =>
56
({
@@ -9,6 +10,17 @@ export const getInterfaceSettings = (state: ReturnType<typeof appStore.getState>
910
{
1011
id: 'interface',
1112
components: [
13+
{
14+
id: 'time-offset',
15+
type: 'Input',
16+
label: 'Time offset',
17+
inputType: 'number',
18+
tippy: 'Time Offset in ms',
19+
value: state.lyrics.timeOffset,
20+
placeholder: 'Offset in ms...',
21+
validation: (value) => LyricsStateSchema.shape.timeOffset.safeParse(value),
22+
onChange: (timeOffset) => state.setLyrics('timeOffset', timeOffset),
23+
},
1224
{
1325
id: 'is-encore-font',
1426
type: 'Toggle',

src/constants/Icons.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
type IconName = 'Mic16';
1+
type IconName = 'Brand16';
22
export const Icons: Record<IconName, string> = {
3-
Mic16: `<svg height="16" width="16" viewBox="0 0 16 16" fill="currentColor"><path d="M13.426 2.574a2.831 2.831 0 0 0-4.797 1.55l3.247 3.247a2.831 2.831 0 0 0 1.55-4.797zM10.5 8.118l-2.619-2.62A63303.13 63303.13 0 0 0 4.74 9.075L2.065 12.12a1.287 1.287 0 0 0 1.816 1.816l3.06-2.688 3.56-3.129zM7.12 4.094a4.331 4.331 0 1 1 4.786 4.786l-3.974 3.493-3.06 2.689a2.787 2.787 0 0 1-3.933-3.933l2.676-3.045 3.505-3.99z" /></svg>`,
3+
Brand16: `
4+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" height="18" width="18" fill="currentColor">
5+
<path d="M 29.922 22.449 L 27.591 21.605 C 27.117 21.433 26.762 21.071 26.576 20.606 L 25.629 18.11 C 25.342 17.368 24.7 17.008 24.057 17.008 C 23.414 17.008 22.756 17.368 22.486 18.11 L 21.538 20.606 C 21.354 21.071 20.997 21.433 20.523 21.605 L 18.19 22.449 C 16.686 22.983 16.686 25.152 18.19 25.705 L 20.523 26.547 C 20.997 26.721 21.354 27.083 21.538 27.546 L 22.486 30.045 C 22.773 30.784 23.414 31.147 24.057 31.147 C 24.7 31.147 25.359 30.784 25.629 30.045 L 26.576 27.546 C 26.762 27.083 27.117 26.721 27.591 26.547 L 29.922 25.705 C 31.429 25.17 31.429 23 29.922 22.449 Z M 26.729 24.102 C 25.562 24.517 24.647 25.428 24.192 26.6 L 24.022 27.03 L 23.852 26.6 C 23.413 25.43 22.484 24.517 21.315 24.102 L 21.232 24.068 L 21.315 24.034 C 22.484 23.622 23.396 22.709 23.852 21.537 L 24.022 21.106 L 24.192 21.537 C 24.63 22.708 25.562 23.622 26.729 24.034 L 26.811 24.068 L 26.729 24.102 Z" />
6+
<path d="M 7.589 3.304 L 8.233 3.53 C 8.366 3.581 8.467 3.683 8.519 3.805 L 8.79 4.494 C 8.875 4.701 9.042 4.804 9.228 4.804 C 9.414 4.804 9.584 4.701 9.669 4.494 L 9.939 3.805 C 9.99 3.667 10.091 3.581 10.226 3.53 L 10.868 3.304 C 11.291 3.15 11.291 2.564 10.868 2.408 L 10.226 2.184 C 10.091 2.132 9.99 2.029 9.939 1.909 L 9.669 1.219 C 9.584 1.012 9.414 0.909 9.228 0.909 C 9.042 0.909 8.875 1.012 8.79 1.219 L 8.519 1.909 C 8.467 2.045 8.366 2.132 8.233 2.184 L 7.589 2.408 C 7.168 2.564 7.168 3.15 7.589 3.304 Z" />
7+
<path d="M 2.684 10.793 C 2.921 10.879 3.124 11.07 3.21 11.309 L 3.7 12.603 C 3.852 12.982 4.174 13.172 4.511 13.172 C 4.849 13.172 5.189 12.982 5.323 12.603 L 5.813 11.309 C 5.898 11.07 6.099 10.879 6.337 10.793 L 7.556 10.363 C 8.333 10.088 8.333 8.969 7.556 8.676 L 6.337 8.246 C 6.101 8.16 5.899 7.969 5.813 7.728 L 5.323 6.438 C 5.17 6.058 4.849 5.869 4.511 5.869 C 4.174 5.869 3.835 6.058 3.7 6.438 L 3.21 7.728 C 3.126 7.969 2.923 8.16 2.684 8.246 L 1.467 8.676 C 0.69 8.952 0.69 10.072 1.467 10.363 L 2.684 10.793 Z" />
8+
<path d="M 13.964 25.446 C 12.931 25.135 11.815 25.135 10.785 25.446 C 9.618 25.789 8.621 26.512 7.86 27.081 C 7.15 27.596 6.474 28.079 5.78 28.322 C 5.156 28.527 4.531 28.493 4.157 28.235 C 3.903 28.061 3.752 27.754 3.735 27.442 L 3.735 27.357 C 4.224 27.563 4.716 27.667 5.224 27.667 C 6.102 27.667 6.981 27.341 7.658 26.702 C 9.839 24.793 12.291 22.829 14.674 20.951 C 16.128 19.798 17.583 18.646 18.985 17.472 C 19.054 17.472 19.139 17.491 19.206 17.491 C 21.253 17.491 23.248 16.664 24.718 15.167 C 27.761 12.067 27.761 7.023 24.718 3.906 C 21.659 0.807 16.705 0.825 13.661 3.906 C 12.037 5.559 11.244 7.849 11.412 10.156 C 9.907 12.049 8.234 13.978 6.593 15.838 C 5.038 17.612 3.431 19.453 1.994 21.244 C 0.948 22.465 0.878 24.187 1.708 25.582 C 1.37 26.185 1.167 26.857 1.199 27.562 C 1.251 28.664 1.809 29.698 2.688 30.352 C 3.331 30.818 4.143 31.056 4.987 31.056 C 5.513 31.056 6.036 30.97 6.562 30.8 C 7.627 30.438 8.521 29.785 9.368 29.164 C 10.112 28.613 10.789 28.147 11.482 27.944 C 12.039 27.769 12.667 27.769 13.224 27.944 C 14.306 28.27 15.269 29.251 16.132 30.093 C 16.621 30.592 17.433 30.592 17.924 30.093 C 18.414 29.596 18.414 28.77 17.924 28.269 C 16.91 27.252 15.66 25.996 13.968 25.479 L 13.964 25.446 Z M 15.467 5.713 C 16.5 4.662 17.852 4.146 19.203 4.146 C 20.555 4.146 21.91 4.662 22.94 5.713 C 24.986 7.814 25.003 11.241 22.94 13.324 C 21.907 14.375 20.506 14.892 19.051 14.856 L 18.816 14.823 C 17.598 14.65 16.5 14.118 15.62 13.29 C 14.776 12.499 14.217 11.465 13.996 10.347 C 13.743 8.662 14.284 6.938 15.467 5.732 L 15.467 5.713 Z M 3.936 22.897 C 5.376 21.122 6.964 19.298 8.503 17.542 C 9.753 16.114 11.04 14.632 12.256 13.172 C 12.628 13.892 13.086 14.564 13.658 15.152 C 14.302 15.805 15.046 16.321 15.841 16.701 C 14.926 17.423 14.015 18.164 13.101 18.886 C 10.7 20.799 8.214 22.779 5.966 24.742 C 5.493 25.188 4.75 25.138 4.174 24.604 C 3.616 24.107 3.498 23.366 3.92 22.882 L 3.936 22.897 Z" />
9+
</svg>`,
410
};

src/constants/Store.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const DEFAULT_APP_STATE: AppState = {
2727
scrollOffset: 16,
2828
forceRomanized: false,
2929
showMetadata: true,
30+
timeOffset: -50,
3031
metadataPosition: 'left',
3132
fullScreenMetadataPosition: 'left',
3233
},

src/hooks/useTrackPosition.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import getProgress from '@/utils/player/getProgress.ts';
22
import { useEffect, useRef } from 'react';
3+
import { useStore } from 'zustand';
4+
import appStore from '@/store/appStore.ts';
35

46
export default function useTrackProgress() {
57
const progress = useRef(-1);
8+
const timeOffset = useStore(appStore, (s) => s.lyrics.timeOffset);
69
const rafRef = useRef<number | null>(null);
710

811
useEffect(() => {
912
const update = () => {
10-
const newProgress = getProgress();
13+
const newProgress = getProgress() + timeOffset;
1114
if (progress.current !== newProgress) progress.current = newProgress;
1215
rafRef.current = requestAnimationFrame(update);
1316
};
@@ -17,7 +20,7 @@ export default function useTrackProgress() {
1720
return () => {
1821
if (rafRef.current) cancelAnimationFrame(rafRef.current);
1922
};
20-
}, []);
23+
}, [timeOffset]);
2124

2225
return progress;
2326
}

src/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const main = async () => {
4747

4848
// setup player button
4949
const playerButton = await createButton({
50-
icon: Icons.Mic16,
50+
icon: Icons.Brand16,
5151
label: 'Lucid Lyrics',
5252
className: 'lucid-lyrics-btn',
5353
active: tempStore.getState().mainPageInstance?.isActive,
@@ -78,7 +78,7 @@ main();
7878
async function addThemeSpecificStyles() {
7979
const timeout = 20000;
8080
const isGlassifyTheme = await waitForElement('.glassify-bg', { timeout });
81-
const isLucidTheme = await waitForElement('.lucid-bg', { timeout });
81+
const isLucidTheme = await waitForElement('.lucid-bg,#lucid-bg', { timeout });
8282
if (isGlassifyTheme) document.documentElement.classList.add('glassify-theme-present');
8383
if (isLucidTheme) document.documentElement.classList.add('lucid-theme-present');
8484
}

src/schemas/appStoreSchema.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import CSSFilterSchema from '@/schemas/cssFilterSchema.ts';
22
import z from 'zod';
3+
import { boundedNumber } from '../utils/schema.ts';
34

45
export const ColorStateSchema = z.object({
56
mode: z.enum(['default', 'dynamic', 'custom']),
@@ -19,22 +20,23 @@ export const BackgroundStateSchema = z.object({
1920
options: z.object({
2021
filter: CSSFilterSchema,
2122
imageMode: z.enum(['custom', 'player', 'page']),
22-
customUrl: z.string().nullable(),
23+
customUrl: z.url({ error: 'Invalid URL' }),
2324
color: z.string(),
2425
autoStopAnimation: z.boolean(),
2526
}),
2627
});
2728

2829
export const LyricsStateSchema = z.object({
2930
isSpotifyFont: z.boolean(),
30-
splitThresholdMs: z.number(),
31-
maxTranslateUpWord: z.number(),
32-
maxTranslateUpLetter: z.number(),
33-
scaleCoefficientWord: z.number(),
34-
scaleCoefficientLetter: z.number(),
35-
scrollOffset: z.number(),
31+
splitThresholdMs: boundedNumber({ name: 'Split Threshold', min: 0, max: 10000 }),
32+
maxTranslateUpWord: boundedNumber({ name: 'Max Translate Up Word', min: 0, max: 500 }),
33+
maxTranslateUpLetter: boundedNumber({ name: 'Max Translate Up Letter', min: 0, max: 500 }),
34+
scaleCoefficientWord: boundedNumber({ name: 'Scale Coefficient Word', min: 0, max: 10 }),
35+
scaleCoefficientLetter: boundedNumber({ name: 'Scale Coefficient Letter', min: 0, max: 10 }),
36+
scrollOffset: boundedNumber({ name: 'Scroll Offset', min: -1000, max: 1000 }),
3637
forceRomanized: z.boolean(),
3738
showMetadata: z.boolean(),
39+
timeOffset: boundedNumber({ min: -9999, max: 9999, name: 'Time Offset' }),
3840
metadataPosition: z.enum(['left', 'right']),
3941
fullScreenMetadataPosition: z.enum(['left', 'right']),
4042
});

src/styles/theme-specific.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@
1212
.player-floating .lucid-config-container {
1313
margin-bottom: calc(var(--player-height) - var(--panel-gap));
1414
}
15+
.dropdown-overlay {
16+
z-index: 99992 !important;
17+
}
1518
}

src/types/store.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export type LyricsState = {
8989
scrollOffset: number;
9090
forceRomanized: boolean;
9191
showMetadata: boolean;
92+
timeOffset: number;
9293
metadataPosition: 'left' | 'right';
9394
fullScreenMetadataPosition: 'left' | 'right';
9495
};

0 commit comments

Comments
 (0)