Skip to content

Commit 79adec5

Browse files
updt
1 parent 4a39ad6 commit 79adec5

27 files changed

+75
-5883
lines changed

src/components/controls/Transport.tsx

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,21 @@ import {
1010
StepBack,
1111
StepForward,
1212
} from "lucide-react";
13-
import React from "react";
13+
import React, { useCallback, useEffect } from "react";
1414

1515
import { useI18n } from "@/i18n";
1616
// import { LogCategory, logger } from "@/services/monitoring";
1717
import { cn } from "@/utils";
1818

19+
// Speed marker configuration
20+
const SPEED_MARKERS = [
21+
{ position: "0%", value: "0.1×", emphasized: false },
22+
{ position: "23.08%", value: "1×", emphasized: true },
23+
{ position: "48.72%", value: "2×", emphasized: false },
24+
{ position: "74.36%", value: "3×", emphasized: false },
25+
{ position: "100%", value: "4×", emphasized: false },
26+
] as const;
27+
1928
type Props = {
2029
playing: boolean;
2130
direction: 1 | -1;
@@ -52,20 +61,56 @@ export default function Transport(p: Props) {
5261
onSeek,
5362
} = p;
5463

55-
const formatSpeed = (speed: number): string => {
64+
const formatSpeed = useCallback((speed: number): string => {
5665
if (speed < 1) {
5766
return `${Math.round(speed * 100)}%`;
5867
}
5968
return `${speed.toFixed(1)}×`;
60-
};
69+
}, []);
6170

62-
const getSpeedColor = (speed: number): string => {
71+
const getSpeedColor = useCallback((speed: number): string => {
6372
if (speed < 0.5) return "text-blue-600";
6473
if (speed < 1) return "text-green-600";
6574
if (speed === 1) return "text-slate-900 dark:text-slate-100 font-semibold";
6675
if (speed <= 2) return "text-orange-600";
6776
return "text-red-600";
68-
};
77+
}, []);
78+
79+
const handlePlayPause = useCallback(() => {
80+
const _action = playing ? "pause" : "play_forward";
81+
// logger.info(
82+
// LogCategory.USER_INTERACTION,
83+
// `Transport ${_action} clicked`,
84+
// {
85+
// currentStep: idx,
86+
// totalSteps: total,
87+
// currentSpeed: speed,
88+
// direction: playing ? direction : 1,
89+
// timestamp: new Date().toISOString(),
90+
// }
91+
// );
92+
93+
if (playing) {
94+
onPause();
95+
} else {
96+
onPlayForward();
97+
}
98+
}, [playing, onPause, onPlayForward]);
99+
100+
// Development-time prop validation
101+
useEffect(() => {
102+
if (process.env.NODE_ENV === "development") {
103+
if (total < 0) {
104+
console.warn("Transport: total should not be negative", { total });
105+
}
106+
if (idx < 0 || (total > 0 && idx >= total)) {
107+
console.warn("Transport: idx is out of bounds", { idx, total });
108+
}
109+
if (speed <= 0) {
110+
console.warn("Transport: speed should be positive", { speed });
111+
}
112+
}
113+
}, [total, idx, speed]);
69114

70115
// Calculate progress percentage
71116
const progress = total > 1 ? (idx / (total - 1)) * 100 : 0;
@@ -145,26 +190,7 @@ export default function Transport(p: Props) {
145190

146191
{/* Play/Pause */}
147192
<button
148-
onClick={() => {
149-
const _action = playing ? "pause" : "play_forward";
150-
// logger.info(
151-
// LogCategory.USER_INTERACTION,
152-
// `Transport ${_action} clicked`,
153-
// {
154-
// currentStep: idx,
155-
// totalSteps: total,
156-
// currentSpeed: speed,
157-
// direction: playing ? direction : 1,
158-
// timestamp: new Date().toISOString(),
159-
// }
160-
// );
161-
162-
if (playing) {
163-
onPause();
164-
} else {
165-
onPlayForward();
166-
}
167-
}}
193+
onClick={handlePlayPause}
168194
className={cn(
169195
"rounded-lg p-3 transition-all duration-200",
170196
"bg-primary-600 hover:bg-primary-700 text-white shadow-sm",
@@ -294,26 +320,26 @@ export default function Transport(p: Props) {
294320

295321
{/* Speed markers */}
296322
<div className="relative mt-1 h-4">
297-
<span className="absolute left-0 text-xs text-slate-400">0.1×</span>
298-
<span
299-
className="absolute text-xs font-semibold text-slate-600 dark:text-slate-300"
300-
style={{ left: "23.08%", transform: "translateX(-50%)" }}
301-
>
302-
303-
</span>
304-
<span
305-
className="absolute text-xs text-slate-400"
306-
style={{ left: "48.72%", transform: "translateX(-50%)" }}
307-
>
308-
309-
</span>
310-
<span
311-
className="absolute text-xs text-slate-400"
312-
style={{ left: "74.36%", transform: "translateX(-50%)" }}
313-
>
314-
315-
</span>
316-
<span className="absolute right-0 text-xs text-slate-400"></span>
323+
{SPEED_MARKERS.map((marker, index) => (
324+
<span
325+
key={marker.value}
326+
className={cn(
327+
"absolute text-xs",
328+
marker.emphasized
329+
? "font-semibold text-slate-600 dark:text-slate-300"
330+
: "text-slate-400"
331+
)}
332+
style={
333+
index === 0
334+
? { left: marker.position }
335+
: index === SPEED_MARKERS.length - 1
336+
? { right: "0" }
337+
: { left: marker.position, transform: "translateX(-50%)" }
338+
}
339+
>
340+
{marker.value}
341+
</span>
342+
))}
317343
</div>
318344
</div>
319345
</div>

0 commit comments

Comments
 (0)