Skip to content

Commit 95c4732

Browse files
committed
feat: use centralized logger
1 parent 3a48cf8 commit 95c4732

File tree

11 files changed

+110
-129
lines changed

11 files changed

+110
-129
lines changed

src/components/Fullscreen.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { useStore } from 'zustand';
1313

1414
const exitFullScreen = () => {
1515
document.exitFullscreen().catch((err) => {
16-
console.error('Failed to exit fullscreen:', err);
16+
logger.error('Failed to exit fullscreen:', err);
1717
});
1818
tempStore.getState().setFullscreenMode('compact');
1919
};
@@ -79,7 +79,7 @@ const Fullscreen: React.FC = () => {
7979
useEffect(() => {
8080
if (fullscreenMode === 'fullscreen') {
8181
document.documentElement.requestFullscreen().catch((err) => {
82-
console.error('Failed to enter fullscreen:', err);
82+
logger.error('Failed to enter fullscreen:', err);
8383
});
8484
} else if (fullscreenMode === 'compact') {
8585
exitFullScreen();

src/components/background/AnimatedColorBackground.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { FragmentShader, GetShaderUniforms, VertexShader } from '@/shaders/color.ts';
22
import appStore from '@/store/appStore.ts';
33
import tempStore from '@/store/tempStore.ts';
4+
import { logger } from '@logger';
45
import { useEffect, useRef } from 'react';
56
import {
67
Color,
@@ -136,7 +137,7 @@ const AnimatedBackground: React.FC<AnimatedBackgroundProps> = ({ timeScale = 50
136137
material.dispose();
137138
renderer.dispose();
138139
} catch (e) {
139-
console.warn('Error disposing renderer resources:', e);
140+
logger.warn('Error disposing renderer resources:', e);
140141
}
141142
};
142143
}, [colors, timeScale]);

src/components/background/helper/loadAndProcessImage.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { CSSFilter } from '@/types/styles.ts';
2+
import { logger } from '@logger';
23
import { serializeFilters } from '@utils/dom';
34
import { CanvasTexture, type Texture } from 'three';
45

56
async function loadAndProcessImage(url: string, filter: CSSFilter): Promise<Texture | null> {
67
try {
78
if (!url) {
8-
console.warn('No image URL provided');
9+
logger.warn('No image URL provided');
910
return null;
1011
}
1112

@@ -22,7 +23,7 @@ async function loadAndProcessImage(url: string, filter: CSSFilter): Promise<Text
2223
const circleCanvas = new OffscreenCanvas(originalSize, originalSize);
2324
const ctx = circleCanvas.getContext('2d');
2425
if (!ctx) {
25-
console.error('Failed to get 2D context for circleCanvas');
26+
logger.error('Failed to get 2D context for circleCanvas');
2627
return null;
2728
}
2829

@@ -45,7 +46,7 @@ async function loadAndProcessImage(url: string, filter: CSSFilter): Promise<Text
4546
const blurredCanvas = new OffscreenCanvas(expandedSize, expandedSize);
4647
const blurredCtx = blurredCanvas.getContext('2d');
4748
if (!blurredCtx) {
48-
console.error('Failed to get 2D context for blurredCanvas');
49+
logger.error('Failed to get 2D context for blurredCanvas');
4950
return null;
5051
}
5152

@@ -56,7 +57,7 @@ async function loadAndProcessImage(url: string, filter: CSSFilter): Promise<Text
5657
texture.needsUpdate = true;
5758
return texture;
5859
} catch (err) {
59-
console.error('Failed to load/process image:', err);
60+
logger.error('Failed to load/process image:', err);
6061
return null;
6162
}
6263
}

src/components/ui/Dropdown.tsx

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,75 @@
1-
/** biome-ignore-all lint/a11y: no a11y for now */
2-
31
import { Tippy } from '@/components/ui';
42
import { ChevronDown } from 'lucide-react';
53
import { createContext, useContext, useEffect, useRef, useState } from 'react';
64
import { createPortal } from 'react-dom';
75

8-
// Context
96
type DropdownContextType = {
107
open: boolean;
118
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
129
buttonRef: React.RefObject<HTMLButtonElement | null>;
1310
};
1411

15-
const DropdownContext = createContext<DropdownContextType>({
16-
open: false,
17-
setOpen: () => {},
18-
buttonRef: { current: null },
19-
});
12+
const DropdownContext = createContext<DropdownContextType | null>(null);
13+
14+
function useDropdownContext() {
15+
const context = useContext(DropdownContext);
16+
if (!context) {
17+
throw new Error('Dropdown components must be used within a Dropdown');
18+
}
19+
return context;
20+
}
2021

21-
// Dropdown Root
22+
// Dropdown Component
2223
type DropdownProps = {
2324
children: React.ReactNode;
2425
};
2526

2627
const Dropdown = ({ children }: DropdownProps) => {
2728
const [open, setOpen] = useState(false);
28-
const dropdownRef = useRef<HTMLDivElement>(null);
2929
const buttonRef = useRef<HTMLButtonElement>(null);
3030

3131
return (
3232
<DropdownContext.Provider value={{ open, setOpen, buttonRef }}>
33-
<div ref={dropdownRef} className="dropdown">
34-
{children}
35-
</div>
33+
<div className="dropdown">{children}</div>
3634
</DropdownContext.Provider>
3735
);
3836
};
3937

4038
// Dropdown Button
4139
type DropdownButtonProps = {
4240
children: React.ReactNode;
43-
icon?: React.ReactNode;
4441
};
4542

46-
function DropdownButton({ children }: DropdownButtonProps) {
47-
const { open, setOpen, buttonRef } = useContext(DropdownContext);
43+
const DropdownButton = ({ children }: DropdownButtonProps) => {
44+
const { open, setOpen, buttonRef } = useDropdownContext();
4845

4946
const toggleOpen = () => setOpen(!open);
5047

5148
return (
5249
<Tippy label={open ? 'Close' : 'Open'}>
53-
<button ref={buttonRef} onClick={toggleOpen} className="dropdown-button" type="button">
50+
<button
51+
ref={buttonRef}
52+
onClick={(e) => {
53+
e.stopPropagation();
54+
toggleOpen();
55+
}}
56+
className="dropdown-button"
57+
type="button"
58+
>
5459
{children}
5560
<ChevronDown className={`dropdown-icon ${open ? 'rotate' : ''}`} />
5661
</button>
5762
</Tippy>
5863
);
59-
}
64+
};
6065

66+
// Dropdown Content
6167
type DropdownContentProps = {
6268
children: React.ReactNode;
6369
};
6470

65-
function DropdownContent({ children }: DropdownContentProps) {
66-
const { open, buttonRef, setOpen } = useContext(DropdownContext);
71+
const DropdownContent = ({ children }: DropdownContentProps) => {
72+
const { open, buttonRef, setOpen } = useDropdownContext();
6773
const contentRef = useRef<HTMLDivElement>(null);
6874
const [coords, setCoords] = useState({ top: 0, left: 0, width: 0 });
6975
const [ready, setReady] = useState(false);
@@ -72,7 +78,6 @@ function DropdownContent({ children }: DropdownContentProps) {
7278
const updatePosition = () => {
7379
const button = buttonRef.current;
7480
const content = contentRef.current;
75-
7681
if (button && content) {
7782
const buttonRect = button.getBoundingClientRect();
7883
const contentWidth = content.offsetWidth || buttonRect.width;
@@ -104,24 +109,22 @@ function DropdownContent({ children }: DropdownContentProps) {
104109
}
105110
};
106111

107-
useEffect(() => {
108-
document.body.classList.toggle('dropdown-open', open);
109-
}, [open]);
110-
111112
useEffect(() => {
112113
if (open) {
113114
setReady(false);
114115
setShow(false);
115116
updatePosition();
116-
117117
window.addEventListener('resize', updatePosition);
118-
119118
return () => {
120119
window.removeEventListener('resize', updatePosition);
121120
};
122121
}
123122
}, [open]);
124123

124+
useEffect(() => {
125+
document.body.classList.toggle('dropdown-open', open);
126+
}, [open]);
127+
125128
if (!open) return null;
126129

127130
return createPortal(
@@ -137,43 +140,51 @@ function DropdownContent({ children }: DropdownContentProps) {
137140
left: coords.left,
138141
minWidth: coords.width,
139142
}}
143+
onClick={(e) => e.stopPropagation()}
140144
>
141145
{children}
142146
</div>
143147
</div>,
144148
document.body
145149
);
146-
}
150+
};
147151

148152
// Dropdown List
149153
type DropdownListProps = React.HTMLAttributes<HTMLUListElement> & {
150154
children: React.ReactNode;
151155
};
152156

153-
function DropdownList({ children, ...props }: DropdownListProps) {
154-
const { setOpen } = useContext(DropdownContext);
157+
const DropdownList = ({ children, ...props }: DropdownListProps) => {
158+
const { setOpen } = useDropdownContext();
155159

156160
return (
157-
<ul onClick={() => setOpen(false)} className="dropdown-list" {...props}>
161+
<ul
162+
className="dropdown-list"
163+
{...props}
164+
onClick={(e) => {
165+
e.stopPropagation();
166+
setOpen(false);
167+
}}
168+
>
158169
{children}
159170
</ul>
160171
);
161-
}
172+
};
162173

163174
// Dropdown Item
164175
type DropdownItemProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
165176
children: React.ReactNode;
166177
};
167178

168-
function DropdownItem({ children, ...props }: DropdownItemProps) {
179+
const DropdownItem = ({ children, ...props }: DropdownItemProps) => {
169180
return (
170181
<li className="dropdown-item">
171182
<button className="dropdown-item-button" {...props}>
172183
{children}
173184
</button>
174185
</li>
175186
);
176-
}
187+
};
177188

178189
// Attach subcomponents
179190
Dropdown.Button = DropdownButton;

src/components/ui/RomanizationButton.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { LetterA } from '@/components/icons';
2-
import { Button } from '@/components/ui';
3-
import appStore from '@/store/appStore.ts';
4-
import tempStore from '@/store/tempStore.ts';
5-
import { Languages } from 'lucide-react';
6-
import { useStore } from 'zustand';
1+
import { LetterA } from "@/components/icons";
2+
import { Button } from "@/components/ui";
3+
import appStore from "@/store/appStore.ts";
4+
import tempStore from "@/store/tempStore.ts";
5+
import { Languages } from "lucide-react";
6+
import { useStore } from "zustand";
77

88
const RomanizationButton = () => {
99
const hasRomanizedText = useStore(
@@ -18,7 +18,9 @@ const RomanizationButton = () => {
1818
onClick={appStore.getState().toggleRomanization}
1919
variant="icon"
2020
show={hasRomanizedText ?? false}
21-
tippyContent={forceRomanized ? 'Disable Romanization' : 'Enable Romanization'}
21+
tippyContent={
22+
forceRomanized ? "Disable Romanization" : "Enable Romanization"
23+
}
2224
>
2325
{forceRomanized ? <LetterA /> : <Languages />}
2426
</Button>

src/components/ui/Tippy.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,29 @@ const Tippy: React.FC<TippyProps> = ({ label = null, children, hasIcon = false,
2121
const containerRef = useRef<HTMLDivElement>(null);
2222
const disableTippy = useStore(appStore, (s) => s.disableTippy);
2323

24-
const showTooltip = () => {
25-
if (disableTippy) return;
26-
if (containerRef.current) {
27-
const rect = containerRef.current.getBoundingClientRect();
28-
setCoords({
29-
top: rect.top + window.scrollY,
30-
left: rect.left + window.scrollX + rect.width / 2,
31-
});
32-
setVisible(true);
33-
}
34-
};
35-
36-
const hideTooltip = () => {
37-
if (disableTippy) return;
38-
setVisible(false);
39-
};
40-
4124
useEffect(() => {
4225
if (disableTippy) return;
4326

4427
const container = containerRef.current;
4528
if (!container) return;
4629

30+
const showTooltip = () => {
31+
if (disableTippy) return;
32+
if (containerRef.current) {
33+
const rect = containerRef.current.getBoundingClientRect();
34+
setCoords({
35+
top: rect.top + window.scrollY,
36+
left: rect.left + window.scrollX + rect.width / 2,
37+
});
38+
setVisible(true);
39+
}
40+
};
41+
42+
const hideTooltip = () => {
43+
if (disableTippy) return;
44+
setVisible(false);
45+
};
46+
4747
container.addEventListener('mouseenter', showTooltip);
4848
container.addEventListener('mouseleave', hideTooltip);
4949

src/lib/logger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import appStore from '@/store/appStore.ts';
22

33
export const createLogger = (prefix: string = '') => ({
4-
log: (...args: any[]) => console.log('[Lucid-Lyrics]', prefix, ...args),
4+
info: (...args: any[]) => console.log('[Lucid-Lyrics]', prefix, ...args),
55
debug: (...args: any[]) =>
66
appStore.getState().isDevMode ? console.debug('[Lucid-Lyrics]', prefix, ...args) : null,
77
warn: (...args: any[]) => console.trace('[Lucid-Lyrics]', prefix, ...args),

0 commit comments

Comments
 (0)