clean
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { Text, View } from "react-native";
|
||||
import { Palette } from "../styles";
|
||||
import { FONT_FAMILY } from "../styles/Fonts";
|
||||
|
||||
export function groupAlignedWordsToLines(alignedWords = [], { removeTags = true } = {}) {
|
||||
const out = [];
|
||||
let buf = [];
|
||||
let start = null;
|
||||
const clean = (txt) =>
|
||||
String(txt || "")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
const isSentenceEnd = (txt) => /[.!?]$/.test((txt || "").trim());
|
||||
const isSectionTag = (txt) => /^\s*\[[^\]]+\]\s*$/i.test((txt || "").trim());
|
||||
|
||||
for (let i = 0; i < alignedWords.length; i++) {
|
||||
const w = alignedWords[i] || {};
|
||||
const original = String(w.word || "");
|
||||
const textNoNewline = original.replace(/\n/g, " ");
|
||||
const textNoTag = removeTags
|
||||
? textNoNewline.replace(/^\s*\[[^\]]+\]\s*/i, "")
|
||||
: textNoNewline;
|
||||
const next = alignedWords[i + 1] || null;
|
||||
const gapToNext = next
|
||||
? Math.max(0, Number(next.startS || 0) - Number(w.endS || 0))
|
||||
: 0;
|
||||
|
||||
if (buf.length === 0) start = Number(w.startS || 0);
|
||||
|
||||
if (isSectionTag(textNoNewline)) {
|
||||
if (!removeTags) {
|
||||
const joined = clean(textNoNewline);
|
||||
if (joined)
|
||||
out.push({
|
||||
text: joined,
|
||||
startS: start ?? Number(w.startS || 0),
|
||||
endS: Number(w.endS || 0),
|
||||
});
|
||||
}
|
||||
buf = [];
|
||||
start = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!clean(textNoTag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf.push(textNoTag);
|
||||
|
||||
const eolByNewline = /\n/.test(original);
|
||||
const eolByPause = gapToNext >= 0.6; // threshold for a logical break
|
||||
const eolByPunct = isSentenceEnd(textNoTag);
|
||||
const isLast = i === alignedWords.length - 1;
|
||||
|
||||
if (eolByNewline || eolByPause || eolByPunct || isLast) {
|
||||
const joined = clean(buf.join(" "));
|
||||
if (joined)
|
||||
out.push({
|
||||
text: joined,
|
||||
startS: start ?? Number(w.startS || 0),
|
||||
endS: Number(w.endS || 0),
|
||||
});
|
||||
buf = [];
|
||||
start = null;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export default function KaraokeLyrics({
|
||||
alignedWords = [],
|
||||
currentTimeS = 0,
|
||||
showContext = true,
|
||||
removeTags = true,
|
||||
}) {
|
||||
const lines = useMemo(
|
||||
() => groupAlignedWordsToLines(alignedWords, { removeTags }),
|
||||
[alignedWords, removeTags]
|
||||
);
|
||||
|
||||
const currentLineIdx = useMemo(() => {
|
||||
if (!lines || lines.length === 0) return -1;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const L = lines[i];
|
||||
if (currentTimeS >= (L.startS || 0) && currentTimeS <= (L.endS || 0))
|
||||
return i;
|
||||
}
|
||||
if (currentTimeS > (lines[lines.length - 1]?.endS || 0))
|
||||
return lines.length - 1;
|
||||
return -1;
|
||||
}, [lines, currentTimeS]);
|
||||
|
||||
if (!lines.length) return null;
|
||||
|
||||
const prev =
|
||||
showContext && currentLineIdx > 0 ? lines[currentLineIdx - 1]?.text : "";
|
||||
const curr =
|
||||
currentLineIdx >= 0 ? lines[currentLineIdx]?.text : lines[0]?.text;
|
||||
const next =
|
||||
showContext && currentLineIdx + 1 < lines.length
|
||||
? lines[currentLineIdx + 1]?.text
|
||||
: "";
|
||||
|
||||
return (
|
||||
<View style={{ gap: 4 }}>
|
||||
{/* {prev ? (
|
||||
<Text
|
||||
style={{
|
||||
color: "#FFFFFF99",
|
||||
fontSize: 14,
|
||||
textAlign: "center",
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
}}
|
||||
>
|
||||
{prev}
|
||||
</Text>
|
||||
) : null} */}
|
||||
<Text
|
||||
style={{
|
||||
color: Palette.white,
|
||||
fontSize: 18,
|
||||
textAlign: "center",
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
}}
|
||||
>
|
||||
{curr}
|
||||
</Text>
|
||||
{next ? (
|
||||
<Text
|
||||
style={{
|
||||
color: "#FFFFFF99",
|
||||
fontSize: 14,
|
||||
textAlign: "center",
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
}}
|
||||
>
|
||||
{next}
|
||||
</Text>
|
||||
) : null}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user