lyrics-transcriber 0.46.0__py3-none-any.whl → 0.48.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lyrics_transcriber/frontend/dist/assets/{index-BXOpmKq-.js → index-BvRLUQmZ.js} +374 -279
- lyrics_transcriber/frontend/dist/assets/index-BvRLUQmZ.js.map +1 -0
- lyrics_transcriber/frontend/dist/index.html +1 -1
- lyrics_transcriber/frontend/src/components/EditModal.tsx +36 -36
- lyrics_transcriber/frontend/src/components/EditWordList.tsx +73 -2
- lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +28 -6
- lyrics_transcriber/frontend/src/components/ModeSelector.tsx +35 -16
- lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +26 -1
- lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +3 -2
- lyrics_transcriber/frontend/src/components/shared/types.ts +1 -0
- lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +45 -8
- lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +47 -0
- lyrics_transcriber/frontend/src/types.ts +1 -1
- {lyrics_transcriber-0.46.0.dist-info → lyrics_transcriber-0.48.0.dist-info}/METADATA +1 -1
- {lyrics_transcriber-0.46.0.dist-info → lyrics_transcriber-0.48.0.dist-info}/RECORD +18 -18
- lyrics_transcriber/frontend/dist/assets/index-BXOpmKq-.js.map +0 -1
- {lyrics_transcriber-0.46.0.dist-info → lyrics_transcriber-0.48.0.dist-info}/LICENSE +0 -0
- {lyrics_transcriber-0.46.0.dist-info → lyrics_transcriber-0.48.0.dist-info}/WHEEL +0 -0
- {lyrics_transcriber-0.46.0.dist-info → lyrics_transcriber-0.48.0.dist-info}/entry_points.txt +0 -0
@@ -33018,7 +33018,7 @@ function useWordClick({
|
|
33018
33018
|
gap2 = matchingGap2;
|
33019
33019
|
}
|
33020
33020
|
}
|
33021
|
-
if (mode === "highlight" || mode === "edit") {
|
33021
|
+
if (mode === "highlight" || mode === "edit" || mode === "delete_word") {
|
33022
33022
|
if (belongsToAnchor && anchor) {
|
33023
33023
|
onWordClick == null ? void 0 : onWordClick({
|
33024
33024
|
word_id: wordId,
|
@@ -33050,7 +33050,7 @@ function useWordClick({
|
|
33050
33050
|
gap: void 0
|
33051
33051
|
});
|
33052
33052
|
}
|
33053
|
-
} else
|
33053
|
+
} else {
|
33054
33054
|
if (belongsToAnchor && anchor) {
|
33055
33055
|
onElementClick({
|
33056
33056
|
type: "anchor",
|
@@ -33650,6 +33650,243 @@ function SegmentDetailsModal({
|
|
33650
33650
|
const PlayCircleOutlineIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
33651
33651
|
d: "m10 16.5 6-4.5-6-4.5zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8"
|
33652
33652
|
}), "PlayCircleOutline");
|
33653
|
+
const DeleteOutlineIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
33654
|
+
d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM8 9h8v10H8zm7.5-5-1-1h-5l-1 1H5v2h14V4z"
|
33655
|
+
}), "DeleteOutline");
|
33656
|
+
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
33657
|
+
let nanoid = (size = 21) => {
|
33658
|
+
let id = "";
|
33659
|
+
let bytes = crypto.getRandomValues(new Uint8Array(size |= 0));
|
33660
|
+
while (size--) {
|
33661
|
+
id += urlAlphabet[bytes[size] & 63];
|
33662
|
+
}
|
33663
|
+
return id;
|
33664
|
+
};
|
33665
|
+
const addSegmentBefore = (data, beforeIndex) => {
|
33666
|
+
const newData = { ...data };
|
33667
|
+
const beforeSegment = newData.corrected_segments[beforeIndex];
|
33668
|
+
const newStartTime = Math.max(0, (beforeSegment.start_time ?? 1) - 1);
|
33669
|
+
const newEndTime = newStartTime + 1;
|
33670
|
+
const newSegment = {
|
33671
|
+
id: nanoid(),
|
33672
|
+
text: "REPLACE",
|
33673
|
+
start_time: newStartTime,
|
33674
|
+
end_time: newEndTime,
|
33675
|
+
words: [{
|
33676
|
+
id: nanoid(),
|
33677
|
+
text: "REPLACE",
|
33678
|
+
start_time: newStartTime,
|
33679
|
+
end_time: newEndTime,
|
33680
|
+
confidence: 1
|
33681
|
+
}]
|
33682
|
+
};
|
33683
|
+
newData.corrected_segments.splice(beforeIndex, 0, newSegment);
|
33684
|
+
return newData;
|
33685
|
+
};
|
33686
|
+
const splitSegment = (data, segmentIndex, afterWordIndex) => {
|
33687
|
+
const newData = { ...data };
|
33688
|
+
const segment = newData.corrected_segments[segmentIndex];
|
33689
|
+
const firstHalfWords = segment.words.slice(0, afterWordIndex + 1);
|
33690
|
+
const secondHalfWords = segment.words.slice(afterWordIndex + 1);
|
33691
|
+
if (secondHalfWords.length === 0) return null;
|
33692
|
+
const lastFirstWord = firstHalfWords[firstHalfWords.length - 1];
|
33693
|
+
const firstSecondWord = secondHalfWords[0];
|
33694
|
+
const lastSecondWord = secondHalfWords[secondHalfWords.length - 1];
|
33695
|
+
const firstSegment = {
|
33696
|
+
...segment,
|
33697
|
+
words: firstHalfWords,
|
33698
|
+
text: firstHalfWords.map((w) => w.text).join(" "),
|
33699
|
+
end_time: lastFirstWord.end_time ?? null
|
33700
|
+
};
|
33701
|
+
const secondSegment = {
|
33702
|
+
id: nanoid(),
|
33703
|
+
words: secondHalfWords,
|
33704
|
+
text: secondHalfWords.map((w) => w.text).join(" "),
|
33705
|
+
start_time: firstSecondWord.start_time ?? null,
|
33706
|
+
end_time: lastSecondWord.end_time ?? null
|
33707
|
+
};
|
33708
|
+
newData.corrected_segments.splice(segmentIndex, 1, firstSegment, secondSegment);
|
33709
|
+
return newData;
|
33710
|
+
};
|
33711
|
+
const deleteSegment = (data, segmentIndex) => {
|
33712
|
+
const newData = { ...data };
|
33713
|
+
const deletedSegment = newData.corrected_segments[segmentIndex];
|
33714
|
+
newData.corrected_segments = newData.corrected_segments.filter((_, index) => index !== segmentIndex);
|
33715
|
+
newData.anchor_sequences = newData.anchor_sequences.map((anchor) => ({
|
33716
|
+
...anchor,
|
33717
|
+
transcribed_word_ids: anchor.transcribed_word_ids.filter(
|
33718
|
+
(wordId) => !deletedSegment.words.some((deletedWord) => deletedWord.id === wordId)
|
33719
|
+
)
|
33720
|
+
}));
|
33721
|
+
newData.gap_sequences = newData.gap_sequences.map((gap2) => ({
|
33722
|
+
...gap2,
|
33723
|
+
transcribed_word_ids: gap2.transcribed_word_ids.filter(
|
33724
|
+
(wordId) => !deletedSegment.words.some((deletedWord) => deletedWord.id === wordId)
|
33725
|
+
)
|
33726
|
+
}));
|
33727
|
+
return newData;
|
33728
|
+
};
|
33729
|
+
const updateSegment = (data, segmentIndex, updatedSegment) => {
|
33730
|
+
const newData = { ...data };
|
33731
|
+
updatedSegment.words = updatedSegment.words.map((word) => ({
|
33732
|
+
...word,
|
33733
|
+
id: word.id || nanoid()
|
33734
|
+
}));
|
33735
|
+
newData.corrected_segments[segmentIndex] = updatedSegment;
|
33736
|
+
return newData;
|
33737
|
+
};
|
33738
|
+
function mergeSegment(data, segmentIndex, mergeWithNext) {
|
33739
|
+
const segments = [...data.corrected_segments];
|
33740
|
+
const targetIndex = mergeWithNext ? segmentIndex + 1 : segmentIndex - 1;
|
33741
|
+
if (targetIndex < 0 || targetIndex >= segments.length) {
|
33742
|
+
return data;
|
33743
|
+
}
|
33744
|
+
const baseSegment = segments[segmentIndex];
|
33745
|
+
const targetSegment = segments[targetIndex];
|
33746
|
+
const mergedSegment = {
|
33747
|
+
id: nanoid(),
|
33748
|
+
words: mergeWithNext ? [...baseSegment.words, ...targetSegment.words] : [...targetSegment.words, ...baseSegment.words],
|
33749
|
+
text: mergeWithNext ? `${baseSegment.text} ${targetSegment.text}` : `${targetSegment.text} ${baseSegment.text}`,
|
33750
|
+
start_time: Math.min(
|
33751
|
+
baseSegment.start_time ?? Infinity,
|
33752
|
+
targetSegment.start_time ?? Infinity
|
33753
|
+
),
|
33754
|
+
end_time: Math.max(
|
33755
|
+
baseSegment.end_time ?? -Infinity,
|
33756
|
+
targetSegment.end_time ?? -Infinity
|
33757
|
+
)
|
33758
|
+
};
|
33759
|
+
const minIndex = Math.min(segmentIndex, targetIndex);
|
33760
|
+
segments.splice(minIndex, 2, mergedSegment);
|
33761
|
+
return {
|
33762
|
+
...data,
|
33763
|
+
corrected_segments: segments
|
33764
|
+
};
|
33765
|
+
}
|
33766
|
+
function findAndReplace(data, findText, replaceText, options = {
|
33767
|
+
caseSensitive: false,
|
33768
|
+
useRegex: false,
|
33769
|
+
fullTextMode: false
|
33770
|
+
}) {
|
33771
|
+
const newData = { ...data };
|
33772
|
+
if (options.fullTextMode) {
|
33773
|
+
newData.corrected_segments = data.corrected_segments.map((segment) => {
|
33774
|
+
let pattern;
|
33775
|
+
if (options.useRegex) {
|
33776
|
+
pattern = new RegExp(findText, options.caseSensitive ? "g" : "gi");
|
33777
|
+
} else {
|
33778
|
+
const escapedFindText = findText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
33779
|
+
pattern = new RegExp(escapedFindText, options.caseSensitive ? "g" : "gi");
|
33780
|
+
}
|
33781
|
+
const segmentText = segment.text;
|
33782
|
+
if (!pattern.test(segmentText)) {
|
33783
|
+
return segment;
|
33784
|
+
}
|
33785
|
+
pattern.lastIndex = 0;
|
33786
|
+
const newSegmentText = segmentText.replace(pattern, replaceText);
|
33787
|
+
const newWordTexts = newSegmentText.trim().split(/\s+/).filter((text) => text.length > 0);
|
33788
|
+
const newWords = [];
|
33789
|
+
if (newWordTexts.length === segment.words.length) {
|
33790
|
+
for (let i = 0; i < newWordTexts.length; i++) {
|
33791
|
+
newWords.push({
|
33792
|
+
...segment.words[i],
|
33793
|
+
text: newWordTexts[i]
|
33794
|
+
});
|
33795
|
+
}
|
33796
|
+
} else if (newWordTexts.length < segment.words.length) {
|
33797
|
+
let oldWordIndex = 0;
|
33798
|
+
for (let i = 0; i < newWordTexts.length; i++) {
|
33799
|
+
while (oldWordIndex < segment.words.length && segment.words[oldWordIndex].text.trim() === "") {
|
33800
|
+
oldWordIndex++;
|
33801
|
+
}
|
33802
|
+
if (oldWordIndex < segment.words.length) {
|
33803
|
+
newWords.push({
|
33804
|
+
...segment.words[oldWordIndex],
|
33805
|
+
text: newWordTexts[i]
|
33806
|
+
});
|
33807
|
+
oldWordIndex++;
|
33808
|
+
} else {
|
33809
|
+
newWords.push({
|
33810
|
+
id: nanoid(),
|
33811
|
+
text: newWordTexts[i],
|
33812
|
+
start_time: null,
|
33813
|
+
end_time: null
|
33814
|
+
});
|
33815
|
+
}
|
33816
|
+
}
|
33817
|
+
} else {
|
33818
|
+
for (let i = 0; i < newWordTexts.length; i++) {
|
33819
|
+
if (i < segment.words.length) {
|
33820
|
+
newWords.push({
|
33821
|
+
...segment.words[i],
|
33822
|
+
text: newWordTexts[i]
|
33823
|
+
});
|
33824
|
+
} else {
|
33825
|
+
newWords.push({
|
33826
|
+
id: nanoid(),
|
33827
|
+
text: newWordTexts[i],
|
33828
|
+
start_time: null,
|
33829
|
+
end_time: null
|
33830
|
+
});
|
33831
|
+
}
|
33832
|
+
}
|
33833
|
+
}
|
33834
|
+
return {
|
33835
|
+
...segment,
|
33836
|
+
words: newWords,
|
33837
|
+
text: newSegmentText
|
33838
|
+
};
|
33839
|
+
});
|
33840
|
+
} else {
|
33841
|
+
newData.corrected_segments = data.corrected_segments.map((segment) => {
|
33842
|
+
let newWords = segment.words.map((word) => {
|
33843
|
+
let pattern;
|
33844
|
+
if (options.useRegex) {
|
33845
|
+
pattern = new RegExp(findText, options.caseSensitive ? "g" : "gi");
|
33846
|
+
} else {
|
33847
|
+
const escapedFindText = findText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
33848
|
+
pattern = new RegExp(escapedFindText, options.caseSensitive ? "g" : "gi");
|
33849
|
+
}
|
33850
|
+
return {
|
33851
|
+
...word,
|
33852
|
+
text: word.text.replace(pattern, replaceText)
|
33853
|
+
};
|
33854
|
+
});
|
33855
|
+
newWords = newWords.filter((word) => word.text.trim() !== "");
|
33856
|
+
return {
|
33857
|
+
...segment,
|
33858
|
+
words: newWords,
|
33859
|
+
text: newWords.map((w) => w.text).join(" ")
|
33860
|
+
};
|
33861
|
+
});
|
33862
|
+
}
|
33863
|
+
newData.corrected_segments = newData.corrected_segments.filter((segment) => segment.words.length > 0);
|
33864
|
+
return newData;
|
33865
|
+
}
|
33866
|
+
function deleteWord(data, wordId) {
|
33867
|
+
const segmentIndex = data.corrected_segments.findIndex(
|
33868
|
+
(segment2) => segment2.words.some((word) => word.id === wordId)
|
33869
|
+
);
|
33870
|
+
if (segmentIndex === -1) {
|
33871
|
+
return data;
|
33872
|
+
}
|
33873
|
+
const segment = data.corrected_segments[segmentIndex];
|
33874
|
+
const wordIndex = segment.words.findIndex((word) => word.id === wordId);
|
33875
|
+
if (wordIndex === -1) {
|
33876
|
+
return data;
|
33877
|
+
}
|
33878
|
+
const updatedWords = segment.words.filter((_, index) => index !== wordIndex);
|
33879
|
+
if (updatedWords.length > 0) {
|
33880
|
+
const updatedSegment = {
|
33881
|
+
...segment,
|
33882
|
+
words: updatedWords,
|
33883
|
+
text: updatedWords.map((w) => w.text).join(" ")
|
33884
|
+
};
|
33885
|
+
return updateSegment(data, segmentIndex, updatedSegment);
|
33886
|
+
} else {
|
33887
|
+
return deleteSegment(data, segmentIndex);
|
33888
|
+
}
|
33889
|
+
}
|
33653
33890
|
const SegmentIndex = styled(Typography)(({ theme: theme2 }) => ({
|
33654
33891
|
color: theme2.palette.text.secondary,
|
33655
33892
|
width: "1.8em",
|
@@ -33688,9 +33925,16 @@ function TranscriptionView({
|
|
33688
33925
|
mode,
|
33689
33926
|
onPlaySegment,
|
33690
33927
|
currentTime = 0,
|
33691
|
-
anchors = []
|
33928
|
+
anchors = [],
|
33929
|
+
onDataChange
|
33692
33930
|
}) {
|
33693
33931
|
const [selectedSegmentIndex, setSelectedSegmentIndex] = reactExports.useState(null);
|
33932
|
+
const handleDeleteSegment = (segmentIndex) => {
|
33933
|
+
if (onDataChange) {
|
33934
|
+
const updatedData = deleteSegment(data, segmentIndex);
|
33935
|
+
onDataChange(updatedData);
|
33936
|
+
}
|
33937
|
+
};
|
33694
33938
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Paper, { sx: { p: 0.8 }, children: [
|
33695
33939
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 0.5 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { variant: "h6", sx: { fontSize: "0.9rem", mb: 0 }, children: "Corrected Transcription" }) }),
|
33696
33940
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 0.2 }, children: data.corrected_segments.map((segment, segmentIndex) => {
|
@@ -33745,6 +33989,22 @@ function TranscriptionView({
|
|
33745
33989
|
children: segmentIndex
|
33746
33990
|
}
|
33747
33991
|
),
|
33992
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
33993
|
+
IconButton,
|
33994
|
+
{
|
33995
|
+
size: "small",
|
33996
|
+
onClick: () => handleDeleteSegment(segmentIndex),
|
33997
|
+
sx: {
|
33998
|
+
padding: "1px",
|
33999
|
+
height: "18px",
|
34000
|
+
width: "18px",
|
34001
|
+
minHeight: "18px",
|
34002
|
+
minWidth: "18px"
|
34003
|
+
},
|
34004
|
+
title: "Delete segment",
|
34005
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(DeleteOutlineIcon, { sx: { fontSize: "0.9rem", color: "error.main" } })
|
34006
|
+
}
|
34007
|
+
),
|
33748
34008
|
segment.start_time !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
33749
34009
|
IconButton,
|
33750
34010
|
{
|
@@ -33757,6 +34017,7 @@ function TranscriptionView({
|
|
33757
34017
|
minHeight: "18px",
|
33758
34018
|
minWidth: "18px"
|
33759
34019
|
},
|
34020
|
+
title: "Play segment",
|
33760
34021
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(PlayCircleOutlineIcon, { sx: { fontSize: "0.9rem" } })
|
33761
34022
|
}
|
33762
34023
|
)
|
@@ -33794,15 +34055,6 @@ function TranscriptionView({
|
|
33794
34055
|
const StopIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
33795
34056
|
d: "M6 6h12v12H6z"
|
33796
34057
|
}), "Stop");
|
33797
|
-
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
33798
|
-
let nanoid = (size = 21) => {
|
33799
|
-
let id = "";
|
33800
|
-
let bytes = crypto.getRandomValues(new Uint8Array(size |= 0));
|
33801
|
-
while (size--) {
|
33802
|
-
id += urlAlphabet[bytes[size] & 63];
|
33803
|
-
}
|
33804
|
-
return id;
|
33805
|
-
};
|
33806
34058
|
const TAP_THRESHOLD_MS = 200;
|
33807
34059
|
const DEFAULT_WORD_DURATION = 1;
|
33808
34060
|
const OVERLAP_BUFFER = 0.01;
|
@@ -34766,9 +35018,16 @@ const WordRow = reactExports.memo(function WordRow2({
|
|
34766
35018
|
onWordUpdate,
|
34767
35019
|
onSplitWord,
|
34768
35020
|
onRemoveWord,
|
34769
|
-
wordsLength
|
35021
|
+
wordsLength,
|
35022
|
+
onTabNavigation
|
34770
35023
|
}) {
|
34771
35024
|
var _a, _b;
|
35025
|
+
const handleKeyDown = (e) => {
|
35026
|
+
if (e.key === "Tab" && !e.shiftKey) {
|
35027
|
+
e.preventDefault();
|
35028
|
+
onTabNavigation(index);
|
35029
|
+
}
|
35030
|
+
};
|
34772
35031
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: {
|
34773
35032
|
display: "flex",
|
34774
35033
|
gap: 2,
|
@@ -34781,8 +35040,10 @@ const WordRow = reactExports.memo(function WordRow2({
|
|
34781
35040
|
label: `Word ${index}`,
|
34782
35041
|
value: word.text,
|
34783
35042
|
onChange: (e) => onWordUpdate(index, { text: e.target.value }),
|
35043
|
+
onKeyDown: handleKeyDown,
|
34784
35044
|
fullWidth: true,
|
34785
|
-
size: "small"
|
35045
|
+
size: "small",
|
35046
|
+
id: `word-text-${index}`
|
34786
35047
|
}
|
34787
35048
|
),
|
34788
35049
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -34844,7 +35105,8 @@ const WordItem = reactExports.memo(function WordItem2({
|
|
34844
35105
|
onAddSegment,
|
34845
35106
|
onMergeSegment,
|
34846
35107
|
wordsLength,
|
34847
|
-
isGlobal
|
35108
|
+
isGlobal,
|
35109
|
+
onTabNavigation
|
34848
35110
|
}) {
|
34849
35111
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { children: [
|
34850
35112
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -34855,7 +35117,8 @@ const WordItem = reactExports.memo(function WordItem2({
|
|
34855
35117
|
onWordUpdate,
|
34856
35118
|
onSplitWord,
|
34857
35119
|
onRemoveWord,
|
34858
|
-
wordsLength
|
35120
|
+
wordsLength,
|
35121
|
+
onTabNavigation
|
34859
35122
|
}
|
34860
35123
|
),
|
34861
35124
|
!isGlobal && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -34915,6 +35178,33 @@ function EditWordList({
|
|
34915
35178
|
const handlePageChange = (_event, value) => {
|
34916
35179
|
setPage(value);
|
34917
35180
|
};
|
35181
|
+
const handleTabNavigation = (currentIndex) => {
|
35182
|
+
const nextIndex = (currentIndex + 1) % words.length;
|
35183
|
+
if (isGlobal && (nextIndex < startIndex || nextIndex >= endIndex)) {
|
35184
|
+
const nextPage = Math.floor(nextIndex / pageSize) + 1;
|
35185
|
+
setPage(nextPage);
|
35186
|
+
setTimeout(() => {
|
35187
|
+
focusWordTextField(nextIndex);
|
35188
|
+
}, 50);
|
35189
|
+
} else {
|
35190
|
+
focusWordTextField(nextIndex);
|
35191
|
+
}
|
35192
|
+
};
|
35193
|
+
const focusWordTextField = (index) => {
|
35194
|
+
const element = document.getElementById(`word-text-${index}`);
|
35195
|
+
if (element) {
|
35196
|
+
let input = element.querySelector("input");
|
35197
|
+
if (!input) {
|
35198
|
+
input = element.querySelector(".MuiInputBase-input");
|
35199
|
+
}
|
35200
|
+
if (input) {
|
35201
|
+
input.focus();
|
35202
|
+
input.select();
|
35203
|
+
} else {
|
35204
|
+
element.focus();
|
35205
|
+
}
|
35206
|
+
}
|
35207
|
+
};
|
34918
35208
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: 1, flexGrow: 1, minHeight: 0 }, children: [
|
34919
35209
|
!isGlobal && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
34920
35210
|
WordDivider,
|
@@ -34966,7 +35256,8 @@ function EditWordList({
|
|
34966
35256
|
onAddSegment,
|
34967
35257
|
onMergeSegment,
|
34968
35258
|
wordsLength: words.length,
|
34969
|
-
isGlobal
|
35259
|
+
isGlobal,
|
35260
|
+
onTabNavigation: handleTabNavigation
|
34970
35261
|
},
|
34971
35262
|
word.id
|
34972
35263
|
);
|
@@ -35179,15 +35470,6 @@ function EditModal({
|
|
35179
35470
|
isGlobal = false,
|
35180
35471
|
isLoading = false
|
35181
35472
|
}) {
|
35182
|
-
console.log("EditModal - Render", {
|
35183
|
-
open,
|
35184
|
-
isGlobal,
|
35185
|
-
isLoading,
|
35186
|
-
hasSegment: !!segment,
|
35187
|
-
segmentIndex,
|
35188
|
-
hasOriginalSegment: !!originalSegment,
|
35189
|
-
hasOriginalTranscribedSegment: !!originalTranscribedSegment
|
35190
|
-
});
|
35191
35473
|
const [editedSegment, setEditedSegment] = reactExports.useState(segment);
|
35192
35474
|
const [isPlaying, setIsPlaying] = reactExports.useState(false);
|
35193
35475
|
const updateSegment2 = reactExports.useCallback((newWords) => {
|
@@ -35218,19 +35500,12 @@ function EditModal({
|
|
35218
35500
|
updateSegment: updateSegment2
|
35219
35501
|
});
|
35220
35502
|
const handleClose = reactExports.useCallback(() => {
|
35221
|
-
console.log("EditModal - handleClose called");
|
35222
35503
|
cleanupManualSync();
|
35223
35504
|
onClose();
|
35224
35505
|
}, [onClose, cleanupManualSync]);
|
35225
35506
|
reactExports.useEffect(() => {
|
35226
35507
|
const spacebarHandler = handleSpacebar;
|
35227
35508
|
if (open) {
|
35228
|
-
console.log("EditModal - Setting up modal spacebar handler", {
|
35229
|
-
hasPlaySegment: !!onPlaySegment,
|
35230
|
-
editedSegmentId: editedSegment == null ? void 0 : editedSegment.id,
|
35231
|
-
handlerFunction: spacebarHandler.toString().slice(0, 100),
|
35232
|
-
isLoading
|
35233
|
-
});
|
35234
35509
|
const handleKeyEvent = (e) => {
|
35235
35510
|
if (e.code === "Space") {
|
35236
35511
|
spacebarHandler(e);
|
@@ -35239,7 +35514,6 @@ function EditModal({
|
|
35239
35514
|
setModalSpacebarHandler(() => handleKeyEvent);
|
35240
35515
|
return () => {
|
35241
35516
|
if (!open) {
|
35242
|
-
console.log("EditModal - Cleanup: clearing modal spacebar handler");
|
35243
35517
|
setModalSpacebarHandler(void 0);
|
35244
35518
|
}
|
35245
35519
|
};
|
@@ -35261,11 +35535,6 @@ function EditModal({
|
|
35261
35535
|
}
|
35262
35536
|
}, [currentTime, editedSegment]);
|
35263
35537
|
reactExports.useEffect(() => {
|
35264
|
-
console.log("EditModal - segment changed", {
|
35265
|
-
hasSegment: !!segment,
|
35266
|
-
segmentId: segment == null ? void 0 : segment.id,
|
35267
|
-
wordCount: segment == null ? void 0 : segment.words.length
|
35268
|
-
});
|
35269
35538
|
setEditedSegment(segment);
|
35270
35539
|
}, [segment]);
|
35271
35540
|
reactExports.useEffect(() => {
|
@@ -35273,7 +35542,6 @@ function EditModal({
|
|
35273
35542
|
if (!editedSegment) return;
|
35274
35543
|
const endTime = editedSegment.end_time ?? 0;
|
35275
35544
|
if (window.isAudioPlaying && currentTime > endTime) {
|
35276
|
-
console.log("Stopping playback: current time exceeded end time");
|
35277
35545
|
(_a = window.toggleAudioPlayback) == null ? void 0 : _a.call(window);
|
35278
35546
|
cleanupManualSync();
|
35279
35547
|
}
|
@@ -35436,7 +35704,6 @@ function EditModal({
|
|
35436
35704
|
return getSafeTimeRange(editedSegment);
|
35437
35705
|
}, [getSafeTimeRange, editedSegment]);
|
35438
35706
|
const dialogTitle = reactExports.useMemo(() => {
|
35439
|
-
console.log("EditModal - Rendering dialog title", { isLoading, isGlobal });
|
35440
35707
|
if (isLoading) {
|
35441
35708
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
|
35442
35709
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { flex: 1, display: "flex", alignItems: "center", gap: 1 }, children: [
|
@@ -35466,23 +35733,11 @@ function EditModal({
|
|
35466
35733
|
] });
|
35467
35734
|
}, [isGlobal, segmentIndex, segment, onPlaySegment, handlePlayButtonClick, isPlaying, onClose, isLoading]);
|
35468
35735
|
if (!isLoading && (!segment || !editedSegment || !originalSegment)) {
|
35469
|
-
console.log("EditModal - Early return: missing required data", {
|
35470
|
-
hasSegment: !!segment,
|
35471
|
-
hasEditedSegment: !!editedSegment,
|
35472
|
-
hasOriginalSegment: !!originalSegment,
|
35473
|
-
isLoading
|
35474
|
-
});
|
35475
35736
|
return null;
|
35476
35737
|
}
|
35477
35738
|
if (!isLoading && !isGlobal && segmentIndex === null) {
|
35478
|
-
console.log("EditModal - Early return: non-global mode with null segmentIndex");
|
35479
35739
|
return null;
|
35480
35740
|
}
|
35481
|
-
console.log("EditModal - Rendering dialog content", {
|
35482
|
-
isLoading,
|
35483
|
-
hasEditedSegment: !!editedSegment,
|
35484
|
-
hasOriginalSegment: !!originalSegment
|
35485
|
-
});
|
35486
35741
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
35487
35742
|
Dialog,
|
35488
35743
|
{
|
@@ -35964,207 +36219,6 @@ function ReviewChangesModal({
|
|
35964
36219
|
}
|
35965
36220
|
);
|
35966
36221
|
}
|
35967
|
-
const addSegmentBefore = (data, beforeIndex) => {
|
35968
|
-
const newData = { ...data };
|
35969
|
-
const beforeSegment = newData.corrected_segments[beforeIndex];
|
35970
|
-
const newStartTime = Math.max(0, (beforeSegment.start_time ?? 1) - 1);
|
35971
|
-
const newEndTime = newStartTime + 1;
|
35972
|
-
const newSegment = {
|
35973
|
-
id: nanoid(),
|
35974
|
-
text: "REPLACE",
|
35975
|
-
start_time: newStartTime,
|
35976
|
-
end_time: newEndTime,
|
35977
|
-
words: [{
|
35978
|
-
id: nanoid(),
|
35979
|
-
text: "REPLACE",
|
35980
|
-
start_time: newStartTime,
|
35981
|
-
end_time: newEndTime,
|
35982
|
-
confidence: 1
|
35983
|
-
}]
|
35984
|
-
};
|
35985
|
-
newData.corrected_segments.splice(beforeIndex, 0, newSegment);
|
35986
|
-
return newData;
|
35987
|
-
};
|
35988
|
-
const splitSegment = (data, segmentIndex, afterWordIndex) => {
|
35989
|
-
const newData = { ...data };
|
35990
|
-
const segment = newData.corrected_segments[segmentIndex];
|
35991
|
-
const firstHalfWords = segment.words.slice(0, afterWordIndex + 1);
|
35992
|
-
const secondHalfWords = segment.words.slice(afterWordIndex + 1);
|
35993
|
-
if (secondHalfWords.length === 0) return null;
|
35994
|
-
const lastFirstWord = firstHalfWords[firstHalfWords.length - 1];
|
35995
|
-
const firstSecondWord = secondHalfWords[0];
|
35996
|
-
const lastSecondWord = secondHalfWords[secondHalfWords.length - 1];
|
35997
|
-
const firstSegment = {
|
35998
|
-
...segment,
|
35999
|
-
words: firstHalfWords,
|
36000
|
-
text: firstHalfWords.map((w) => w.text).join(" "),
|
36001
|
-
end_time: lastFirstWord.end_time ?? null
|
36002
|
-
};
|
36003
|
-
const secondSegment = {
|
36004
|
-
id: nanoid(),
|
36005
|
-
words: secondHalfWords,
|
36006
|
-
text: secondHalfWords.map((w) => w.text).join(" "),
|
36007
|
-
start_time: firstSecondWord.start_time ?? null,
|
36008
|
-
end_time: lastSecondWord.end_time ?? null
|
36009
|
-
};
|
36010
|
-
newData.corrected_segments.splice(segmentIndex, 1, firstSegment, secondSegment);
|
36011
|
-
return newData;
|
36012
|
-
};
|
36013
|
-
const deleteSegment = (data, segmentIndex) => {
|
36014
|
-
const newData = { ...data };
|
36015
|
-
const deletedSegment = newData.corrected_segments[segmentIndex];
|
36016
|
-
newData.corrected_segments = newData.corrected_segments.filter((_, index) => index !== segmentIndex);
|
36017
|
-
newData.anchor_sequences = newData.anchor_sequences.map((anchor) => ({
|
36018
|
-
...anchor,
|
36019
|
-
transcribed_word_ids: anchor.transcribed_word_ids.filter(
|
36020
|
-
(wordId) => !deletedSegment.words.some((deletedWord) => deletedWord.id === wordId)
|
36021
|
-
)
|
36022
|
-
}));
|
36023
|
-
newData.gap_sequences = newData.gap_sequences.map((gap2) => ({
|
36024
|
-
...gap2,
|
36025
|
-
transcribed_word_ids: gap2.transcribed_word_ids.filter(
|
36026
|
-
(wordId) => !deletedSegment.words.some((deletedWord) => deletedWord.id === wordId)
|
36027
|
-
)
|
36028
|
-
}));
|
36029
|
-
return newData;
|
36030
|
-
};
|
36031
|
-
const updateSegment = (data, segmentIndex, updatedSegment) => {
|
36032
|
-
const newData = { ...data };
|
36033
|
-
updatedSegment.words = updatedSegment.words.map((word) => ({
|
36034
|
-
...word,
|
36035
|
-
id: word.id || nanoid()
|
36036
|
-
}));
|
36037
|
-
newData.corrected_segments[segmentIndex] = updatedSegment;
|
36038
|
-
return newData;
|
36039
|
-
};
|
36040
|
-
function mergeSegment(data, segmentIndex, mergeWithNext) {
|
36041
|
-
const segments = [...data.corrected_segments];
|
36042
|
-
const targetIndex = mergeWithNext ? segmentIndex + 1 : segmentIndex - 1;
|
36043
|
-
if (targetIndex < 0 || targetIndex >= segments.length) {
|
36044
|
-
return data;
|
36045
|
-
}
|
36046
|
-
const baseSegment = segments[segmentIndex];
|
36047
|
-
const targetSegment = segments[targetIndex];
|
36048
|
-
const mergedSegment = {
|
36049
|
-
id: nanoid(),
|
36050
|
-
words: mergeWithNext ? [...baseSegment.words, ...targetSegment.words] : [...targetSegment.words, ...baseSegment.words],
|
36051
|
-
text: mergeWithNext ? `${baseSegment.text} ${targetSegment.text}` : `${targetSegment.text} ${baseSegment.text}`,
|
36052
|
-
start_time: Math.min(
|
36053
|
-
baseSegment.start_time ?? Infinity,
|
36054
|
-
targetSegment.start_time ?? Infinity
|
36055
|
-
),
|
36056
|
-
end_time: Math.max(
|
36057
|
-
baseSegment.end_time ?? -Infinity,
|
36058
|
-
targetSegment.end_time ?? -Infinity
|
36059
|
-
)
|
36060
|
-
};
|
36061
|
-
const minIndex = Math.min(segmentIndex, targetIndex);
|
36062
|
-
segments.splice(minIndex, 2, mergedSegment);
|
36063
|
-
return {
|
36064
|
-
...data,
|
36065
|
-
corrected_segments: segments
|
36066
|
-
};
|
36067
|
-
}
|
36068
|
-
function findAndReplace(data, findText, replaceText, options = {
|
36069
|
-
caseSensitive: false,
|
36070
|
-
useRegex: false,
|
36071
|
-
fullTextMode: false
|
36072
|
-
}) {
|
36073
|
-
const newData = { ...data };
|
36074
|
-
if (options.fullTextMode) {
|
36075
|
-
newData.corrected_segments = data.corrected_segments.map((segment) => {
|
36076
|
-
let pattern;
|
36077
|
-
if (options.useRegex) {
|
36078
|
-
pattern = new RegExp(findText, options.caseSensitive ? "g" : "gi");
|
36079
|
-
} else {
|
36080
|
-
const escapedFindText = findText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
36081
|
-
pattern = new RegExp(escapedFindText, options.caseSensitive ? "g" : "gi");
|
36082
|
-
}
|
36083
|
-
const segmentText = segment.text;
|
36084
|
-
if (!pattern.test(segmentText)) {
|
36085
|
-
return segment;
|
36086
|
-
}
|
36087
|
-
pattern.lastIndex = 0;
|
36088
|
-
const newSegmentText = segmentText.replace(pattern, replaceText);
|
36089
|
-
const newWordTexts = newSegmentText.trim().split(/\s+/).filter((text) => text.length > 0);
|
36090
|
-
const newWords = [];
|
36091
|
-
if (newWordTexts.length === segment.words.length) {
|
36092
|
-
for (let i = 0; i < newWordTexts.length; i++) {
|
36093
|
-
newWords.push({
|
36094
|
-
...segment.words[i],
|
36095
|
-
text: newWordTexts[i]
|
36096
|
-
});
|
36097
|
-
}
|
36098
|
-
} else if (newWordTexts.length < segment.words.length) {
|
36099
|
-
let oldWordIndex = 0;
|
36100
|
-
for (let i = 0; i < newWordTexts.length; i++) {
|
36101
|
-
while (oldWordIndex < segment.words.length && segment.words[oldWordIndex].text.trim() === "") {
|
36102
|
-
oldWordIndex++;
|
36103
|
-
}
|
36104
|
-
if (oldWordIndex < segment.words.length) {
|
36105
|
-
newWords.push({
|
36106
|
-
...segment.words[oldWordIndex],
|
36107
|
-
text: newWordTexts[i]
|
36108
|
-
});
|
36109
|
-
oldWordIndex++;
|
36110
|
-
} else {
|
36111
|
-
newWords.push({
|
36112
|
-
id: nanoid(),
|
36113
|
-
text: newWordTexts[i],
|
36114
|
-
start_time: null,
|
36115
|
-
end_time: null
|
36116
|
-
});
|
36117
|
-
}
|
36118
|
-
}
|
36119
|
-
} else {
|
36120
|
-
for (let i = 0; i < newWordTexts.length; i++) {
|
36121
|
-
if (i < segment.words.length) {
|
36122
|
-
newWords.push({
|
36123
|
-
...segment.words[i],
|
36124
|
-
text: newWordTexts[i]
|
36125
|
-
});
|
36126
|
-
} else {
|
36127
|
-
newWords.push({
|
36128
|
-
id: nanoid(),
|
36129
|
-
text: newWordTexts[i],
|
36130
|
-
start_time: null,
|
36131
|
-
end_time: null
|
36132
|
-
});
|
36133
|
-
}
|
36134
|
-
}
|
36135
|
-
}
|
36136
|
-
return {
|
36137
|
-
...segment,
|
36138
|
-
words: newWords,
|
36139
|
-
text: newSegmentText
|
36140
|
-
};
|
36141
|
-
});
|
36142
|
-
} else {
|
36143
|
-
newData.corrected_segments = data.corrected_segments.map((segment) => {
|
36144
|
-
let newWords = segment.words.map((word) => {
|
36145
|
-
let pattern;
|
36146
|
-
if (options.useRegex) {
|
36147
|
-
pattern = new RegExp(findText, options.caseSensitive ? "g" : "gi");
|
36148
|
-
} else {
|
36149
|
-
const escapedFindText = findText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
36150
|
-
pattern = new RegExp(escapedFindText, options.caseSensitive ? "g" : "gi");
|
36151
|
-
}
|
36152
|
-
return {
|
36153
|
-
...word,
|
36154
|
-
text: word.text.replace(pattern, replaceText)
|
36155
|
-
};
|
36156
|
-
});
|
36157
|
-
newWords = newWords.filter((word) => word.text.trim() !== "");
|
36158
|
-
return {
|
36159
|
-
...segment,
|
36160
|
-
words: newWords,
|
36161
|
-
text: newWords.map((w) => w.text).join(" ")
|
36162
|
-
};
|
36163
|
-
});
|
36164
|
-
}
|
36165
|
-
newData.corrected_segments = newData.corrected_segments.filter((segment) => segment.words.length > 0);
|
36166
|
-
return newData;
|
36167
|
-
}
|
36168
36222
|
const generateStorageKey = (data) => {
|
36169
36223
|
var _a;
|
36170
36224
|
const text = ((_a = data.original_segments[0]) == null ? void 0 : _a.text) || "";
|
@@ -36238,6 +36292,12 @@ const setModalHandler = (handler, open) => {
|
|
36238
36292
|
};
|
36239
36293
|
const setupKeyboardHandlers = (state) => {
|
36240
36294
|
Math.random().toString(36).substr(2, 9);
|
36295
|
+
const resetModifierStates = () => {
|
36296
|
+
var _a;
|
36297
|
+
state.setIsShiftPressed(false);
|
36298
|
+
(_a = state.setIsCtrlPressed) == null ? void 0 : _a.call(state, false);
|
36299
|
+
document.body.style.userSelect = "";
|
36300
|
+
};
|
36241
36301
|
const handleKeyDown = (e) => {
|
36242
36302
|
var _a;
|
36243
36303
|
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
@@ -36246,7 +36306,7 @@ const setupKeyboardHandlers = (state) => {
|
|
36246
36306
|
if (e.key === "Shift") {
|
36247
36307
|
state.setIsShiftPressed(true);
|
36248
36308
|
document.body.style.userSelect = "none";
|
36249
|
-
} else if (e.key === "Meta") {
|
36309
|
+
} else if (e.key === "Control" || e.key === "Ctrl" || e.key === "Meta") {
|
36250
36310
|
(_a = state.setIsCtrlPressed) == null ? void 0 : _a.call(state, true);
|
36251
36311
|
} else if (e.key === " " || e.code === "Space") {
|
36252
36312
|
e.preventDefault();
|
@@ -36258,20 +36318,30 @@ const setupKeyboardHandlers = (state) => {
|
|
36258
36318
|
}
|
36259
36319
|
};
|
36260
36320
|
const handleKeyUp = (e) => {
|
36261
|
-
|
36262
|
-
if (e.key === "
|
36263
|
-
state.setIsShiftPressed(false);
|
36264
|
-
document.body.style.userSelect = "";
|
36265
|
-
} else if (e.key === "Meta") {
|
36266
|
-
(_a = state.setIsCtrlPressed) == null ? void 0 : _a.call(state, false);
|
36267
|
-
} else if (e.key === " " || e.code === "Space") {
|
36321
|
+
resetModifierStates();
|
36322
|
+
if (e.key === " " || e.code === "Space") {
|
36268
36323
|
e.preventDefault();
|
36269
36324
|
if (isModalOpen && currentModalHandler) {
|
36270
36325
|
currentModalHandler(e);
|
36271
36326
|
}
|
36272
36327
|
}
|
36273
36328
|
};
|
36274
|
-
|
36329
|
+
const handleWindowBlur = () => {
|
36330
|
+
resetModifierStates();
|
36331
|
+
};
|
36332
|
+
const handleWindowFocus = () => {
|
36333
|
+
resetModifierStates();
|
36334
|
+
};
|
36335
|
+
window.addEventListener("blur", handleWindowBlur);
|
36336
|
+
window.addEventListener("focus", handleWindowFocus);
|
36337
|
+
return {
|
36338
|
+
handleKeyDown,
|
36339
|
+
handleKeyUp,
|
36340
|
+
cleanup: () => {
|
36341
|
+
window.removeEventListener("blur", handleWindowBlur);
|
36342
|
+
window.removeEventListener("focus", handleWindowFocus);
|
36343
|
+
}
|
36344
|
+
};
|
36275
36345
|
};
|
36276
36346
|
function ModeSelector({ effectiveMode, onChange }) {
|
36277
36347
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1.2, height: "32px" }, children: [
|
@@ -36281,7 +36351,7 @@ function ModeSelector({ effectiveMode, onChange }) {
|
|
36281
36351
|
{
|
36282
36352
|
value: effectiveMode,
|
36283
36353
|
exclusive: true,
|
36284
|
-
onChange: (_, newMode) => newMode && onChange(newMode),
|
36354
|
+
onChange: (_, newMode) => newMode === "edit" && onChange(newMode),
|
36285
36355
|
size: "small",
|
36286
36356
|
sx: {
|
36287
36357
|
height: "32px",
|
@@ -36292,28 +36362,38 @@ function ModeSelector({ effectiveMode, onChange }) {
|
|
36292
36362
|
}
|
36293
36363
|
},
|
36294
36364
|
children: [
|
36295
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36365
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { title: "Default mode; click words to edit that lyrics segment", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36296
36366
|
ToggleButton,
|
36297
36367
|
{
|
36298
36368
|
value: "edit",
|
36299
|
-
title: "Click to edit segments and make corrections in the transcription view",
|
36300
36369
|
children: [
|
36301
36370
|
/* @__PURE__ */ jsxRuntimeExports.jsx(EditIcon, { sx: { mr: 0.5, fontSize: "1rem" } }),
|
36302
36371
|
"Edit"
|
36303
36372
|
]
|
36304
36373
|
}
|
36305
|
-
),
|
36306
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36374
|
+
) }),
|
36375
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { title: "Hold SHIFT and click words to highlight the matching anchor sequence in the reference lyrics", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36307
36376
|
ToggleButton,
|
36308
36377
|
{
|
36309
36378
|
value: "highlight",
|
36310
|
-
|
36379
|
+
disabled: true,
|
36311
36380
|
children: [
|
36312
36381
|
/* @__PURE__ */ jsxRuntimeExports.jsx(HighlightIcon, { sx: { mr: 0.5, fontSize: "1rem" } }),
|
36313
36382
|
"Highlight"
|
36314
36383
|
]
|
36315
36384
|
}
|
36316
|
-
)
|
36385
|
+
) }) }),
|
36386
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { title: "Hold CTRL and click words to delete them", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36387
|
+
ToggleButton,
|
36388
|
+
{
|
36389
|
+
value: "delete_word",
|
36390
|
+
disabled: true,
|
36391
|
+
children: [
|
36392
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DeleteIcon, { sx: { mr: 0.5, fontSize: "1rem" } }),
|
36393
|
+
"Delete"
|
36394
|
+
]
|
36395
|
+
}
|
36396
|
+
) }) })
|
36317
36397
|
]
|
36318
36398
|
}
|
36319
36399
|
)
|
@@ -37105,7 +37185,8 @@ const MemoizedTranscriptionView = reactExports.memo(function MemoizedTranscripti
|
|
37105
37185
|
onPlaySegment,
|
37106
37186
|
currentTime,
|
37107
37187
|
anchors,
|
37108
|
-
disableHighlighting
|
37188
|
+
disableHighlighting,
|
37189
|
+
onDataChange
|
37109
37190
|
}) {
|
37110
37191
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
37111
37192
|
TranscriptionView,
|
@@ -37119,7 +37200,8 @@ const MemoizedTranscriptionView = reactExports.memo(function MemoizedTranscripti
|
|
37119
37200
|
highlightInfo,
|
37120
37201
|
onPlaySegment,
|
37121
37202
|
currentTime: disableHighlighting ? void 0 : currentTime,
|
37122
|
-
anchors
|
37203
|
+
anchors,
|
37204
|
+
onDataChange
|
37123
37205
|
}
|
37124
37206
|
);
|
37125
37207
|
});
|
@@ -37209,6 +37291,7 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37209
37291
|
const [originalData] = reactExports.useState(() => JSON.parse(JSON.stringify(initialData)));
|
37210
37292
|
const [interactionMode, setInteractionMode] = reactExports.useState("edit");
|
37211
37293
|
const [isShiftPressed, setIsShiftPressed] = reactExports.useState(false);
|
37294
|
+
const [isCtrlPressed, setIsCtrlPressed] = reactExports.useState(false);
|
37212
37295
|
const [editModalSegment, setEditModalSegment] = reactExports.useState(null);
|
37213
37296
|
const [isEditAllModalOpen, setIsEditAllModalOpen] = reactExports.useState(false);
|
37214
37297
|
const [globalEditSegment, setGlobalEditSegment] = reactExports.useState(null);
|
@@ -37239,27 +37322,30 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37239
37322
|
}
|
37240
37323
|
}, [data, isReadOnly, initialData]);
|
37241
37324
|
reactExports.useEffect(() => {
|
37242
|
-
const { handleKeyDown, handleKeyUp } = setupKeyboardHandlers({
|
37243
|
-
setIsShiftPressed
|
37325
|
+
const { handleKeyDown, handleKeyUp, cleanup } = setupKeyboardHandlers({
|
37326
|
+
setIsShiftPressed,
|
37327
|
+
setIsCtrlPressed
|
37244
37328
|
});
|
37245
37329
|
window.addEventListener("keydown", handleKeyDown);
|
37246
37330
|
window.addEventListener("keyup", handleKeyUp);
|
37247
37331
|
if (isAnyModalOpen) {
|
37248
37332
|
setIsShiftPressed(false);
|
37333
|
+
setIsCtrlPressed(false);
|
37249
37334
|
}
|
37250
37335
|
return () => {
|
37251
37336
|
window.removeEventListener("keydown", handleKeyDown);
|
37252
37337
|
window.removeEventListener("keyup", handleKeyUp);
|
37253
37338
|
document.body.style.userSelect = "";
|
37339
|
+
cleanup();
|
37254
37340
|
};
|
37255
|
-
}, [setIsShiftPressed, isAnyModalOpen]);
|
37341
|
+
}, [setIsShiftPressed, setIsCtrlPressed, isAnyModalOpen]);
|
37256
37342
|
reactExports.useEffect(() => {
|
37257
37343
|
const modalOpen = Boolean(
|
37258
37344
|
modalContent || editModalSegment || isReviewModalOpen || isAddLyricsModalOpen || isFindReplaceModalOpen || isEditAllModalOpen
|
37259
37345
|
);
|
37260
37346
|
setIsAnyModalOpen(modalOpen);
|
37261
37347
|
}, [modalContent, editModalSegment, isReviewModalOpen, isAddLyricsModalOpen, isFindReplaceModalOpen, isEditAllModalOpen]);
|
37262
|
-
const effectiveMode = isShiftPressed ? "highlight" : interactionMode;
|
37348
|
+
const effectiveMode = isCtrlPressed ? "delete_word" : isShiftPressed ? "highlight" : interactionMode;
|
37263
37349
|
const handleFlash = reactExports.useCallback((type, info) => {
|
37264
37350
|
setFlashingType(null);
|
37265
37351
|
setHighlightInfo(null);
|
@@ -37278,6 +37364,12 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37278
37364
|
}, []);
|
37279
37365
|
const handleWordClick = reactExports.useCallback((info) => {
|
37280
37366
|
var _a, _b, _c, _d, _e, _f, _g;
|
37367
|
+
if (effectiveMode === "delete_word") {
|
37368
|
+
const newData = deleteWord(data, info.word_id);
|
37369
|
+
setData(newData);
|
37370
|
+
handleFlash("word");
|
37371
|
+
return;
|
37372
|
+
}
|
37281
37373
|
if (effectiveMode === "highlight") {
|
37282
37374
|
const correction = (_a = data.corrections) == null ? void 0 : _a.find(
|
37283
37375
|
(c) => c.corrected_word_id === info.word_id || c.word_id === info.word_id
|
@@ -37385,7 +37477,7 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37385
37477
|
});
|
37386
37478
|
}
|
37387
37479
|
}
|
37388
|
-
}, [data, effectiveMode, setModalContent]);
|
37480
|
+
}, [data, effectiveMode, setModalContent, handleFlash, deleteWord]);
|
37389
37481
|
const handleUpdateSegment = reactExports.useCallback((updatedSegment) => {
|
37390
37482
|
if (!editModalSegment) return;
|
37391
37483
|
const newData = updateSegment(data, editModalSegment.index, updatedSegment);
|
@@ -37676,7 +37768,10 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37676
37768
|
onPlaySegment: handlePlaySegment,
|
37677
37769
|
currentTime: currentAudioTime,
|
37678
37770
|
anchors: data.anchor_sequences,
|
37679
|
-
disableHighlighting: isAnyModalOpenMemo
|
37771
|
+
disableHighlighting: isAnyModalOpenMemo,
|
37772
|
+
onDataChange: (updatedData) => {
|
37773
|
+
setData(updatedData);
|
37774
|
+
}
|
37680
37775
|
}
|
37681
37776
|
),
|
37682
37777
|
!isReadOnly && apiClient && /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: {
|
@@ -38158,4 +38253,4 @@ ReactDOM$1.createRoot(document.getElementById("root")).render(
|
|
38158
38253
|
/* @__PURE__ */ jsxRuntimeExports.jsx(App, {})
|
38159
38254
|
] })
|
38160
38255
|
);
|
38161
|
-
//# sourceMappingURL=index-
|
38256
|
+
//# sourceMappingURL=index-BvRLUQmZ.js.map
|