lyrics-transcriber 0.45.0__py3-none-any.whl → 0.47.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/.yarn/releases/{yarn-4.6.0.cjs → yarn-4.7.0.cjs} +292 -291
- lyrics_transcriber/frontend/.yarnrc.yml +1 -1
- lyrics_transcriber/frontend/dist/assets/{index-ZCT0s9MG.js → index-2vK-qVJS.js} +231 -151
- lyrics_transcriber/frontend/dist/assets/index-2vK-qVJS.js.map +1 -0
- lyrics_transcriber/frontend/dist/index.html +1 -1
- lyrics_transcriber/frontend/package.json +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/Header.tsx +1 -16
- lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +26 -8
- lyrics_transcriber/frontend/src/components/ModeSelector.tsx +35 -16
- lyrics_transcriber/frontend/src/components/ReferenceView.tsx +3 -1
- lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +4 -2
- lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +26 -3
- lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +2 -1
- lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +3 -2
- lyrics_transcriber/frontend/src/components/shared/types.ts +2 -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.45.0.dist-info → lyrics_transcriber-0.47.0.dist-info}/METADATA +1 -1
- {lyrics_transcriber-0.45.0.dist-info → lyrics_transcriber-0.47.0.dist-info}/RECORD +25 -25
- lyrics_transcriber/frontend/dist/assets/index-ZCT0s9MG.js.map +0 -1
- {lyrics_transcriber-0.45.0.dist-info → lyrics_transcriber-0.47.0.dist-info}/LICENSE +0 -0
- {lyrics_transcriber-0.45.0.dist-info → lyrics_transcriber-0.47.0.dist-info}/WHEEL +0 -0
- {lyrics_transcriber-0.45.0.dist-info → lyrics_transcriber-0.47.0.dist-info}/entry_points.txt +0 -0
@@ -32843,25 +32843,53 @@ function calculateReferenceLinePositions(corrected_segments, anchors, currentSou
|
|
32843
32843
|
}
|
32844
32844
|
return { linePositions };
|
32845
32845
|
}
|
32846
|
-
|
32847
|
-
|
32848
|
-
|
32849
|
-
|
32850
|
-
|
32851
|
-
|
32852
|
-
|
32853
|
-
|
32854
|
-
|
32855
|
-
|
32856
|
-
|
32857
|
-
|
32858
|
-
|
32859
|
-
|
32846
|
+
const AddIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
32847
|
+
d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"
|
32848
|
+
}), "Add");
|
32849
|
+
function SourceSelector({ currentSource, onSourceChange, availableSources, onAddLyrics }) {
|
32850
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", flexWrap: "wrap", gap: 0.3, alignItems: "center" }, children: [
|
32851
|
+
availableSources.map((source) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
32852
|
+
Button,
|
32853
|
+
{
|
32854
|
+
size: "small",
|
32855
|
+
variant: currentSource === source ? "contained" : "outlined",
|
32856
|
+
onClick: () => onSourceChange(source),
|
32857
|
+
sx: {
|
32858
|
+
mr: 0,
|
32859
|
+
py: 0.2,
|
32860
|
+
px: 0.8,
|
32861
|
+
minWidth: "auto",
|
32862
|
+
fontSize: "0.7rem",
|
32863
|
+
lineHeight: 1.2
|
32864
|
+
},
|
32865
|
+
children: source.charAt(0).toUpperCase() + source.slice(1)
|
32860
32866
|
},
|
32861
|
-
|
32862
|
-
|
32863
|
-
|
32864
|
-
|
32867
|
+
source
|
32868
|
+
)),
|
32869
|
+
onAddLyrics && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
32870
|
+
Button,
|
32871
|
+
{
|
32872
|
+
size: "small",
|
32873
|
+
variant: "outlined",
|
32874
|
+
onClick: onAddLyrics,
|
32875
|
+
startIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(AddIcon, { sx: { fontSize: "0.9rem" } }),
|
32876
|
+
sx: {
|
32877
|
+
mr: 0,
|
32878
|
+
py: 0.2,
|
32879
|
+
px: 0.8,
|
32880
|
+
minWidth: "auto",
|
32881
|
+
fontSize: "0.7rem",
|
32882
|
+
lineHeight: 1.2,
|
32883
|
+
"& .MuiButton-startIcon": {
|
32884
|
+
marginLeft: "-5px",
|
32885
|
+
marginRight: "1px",
|
32886
|
+
marginTop: "-1px"
|
32887
|
+
}
|
32888
|
+
},
|
32889
|
+
children: "New"
|
32890
|
+
}
|
32891
|
+
)
|
32892
|
+
] });
|
32865
32893
|
}
|
32866
32894
|
const HighlightedWord = styled$1("span")(
|
32867
32895
|
({ shouldFlash }) => ({
|
@@ -32922,7 +32950,11 @@ const WordComponent = React.memo(function Word({
|
|
32922
32950
|
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
32923
32951
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Corrected by:" }),
|
32924
32952
|
" ",
|
32925
|
-
correction.handler
|
32953
|
+
correction.handler,
|
32954
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
32955
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Source:" }),
|
32956
|
+
" ",
|
32957
|
+
correction.source
|
32926
32958
|
] });
|
32927
32959
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { title: tooltipContent, arrow: true, placement: "top", children: wordElement });
|
32928
32960
|
}
|
@@ -32986,7 +33018,7 @@ function useWordClick({
|
|
32986
33018
|
gap2 = matchingGap2;
|
32987
33019
|
}
|
32988
33020
|
}
|
32989
|
-
if (mode === "highlight" || mode === "edit") {
|
33021
|
+
if (mode === "highlight" || mode === "edit" || mode === "delete_word") {
|
32990
33022
|
if (belongsToAnchor && anchor) {
|
32991
33023
|
onWordClick == null ? void 0 : onWordClick({
|
32992
33024
|
word_id: wordId,
|
@@ -33018,7 +33050,7 @@ function useWordClick({
|
|
33018
33050
|
gap: void 0
|
33019
33051
|
});
|
33020
33052
|
}
|
33021
|
-
} else
|
33053
|
+
} else {
|
33022
33054
|
if (belongsToAnchor && anchor) {
|
33023
33055
|
onElementClick({
|
33024
33056
|
type: "anchor",
|
@@ -33186,7 +33218,8 @@ function HighlightedText({
|
|
33186
33218
|
return correction ? {
|
33187
33219
|
originalWord: correction.original_word,
|
33188
33220
|
handler: correction.handler,
|
33189
|
-
confidence: correction.confidence
|
33221
|
+
confidence: correction.confidence,
|
33222
|
+
source: correction.source
|
33190
33223
|
} : null;
|
33191
33224
|
})()
|
33192
33225
|
},
|
@@ -33215,7 +33248,8 @@ function HighlightedText({
|
|
33215
33248
|
const correctionInfo = correction ? {
|
33216
33249
|
originalWord: correction.original_word,
|
33217
33250
|
handler: correction.handler,
|
33218
|
-
confidence: correction.confidence
|
33251
|
+
confidence: correction.confidence,
|
33252
|
+
source: correction.source
|
33219
33253
|
} : null;
|
33220
33254
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(React.Fragment, { children: [
|
33221
33255
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -33386,7 +33420,8 @@ function ReferenceView({
|
|
33386
33420
|
highlightInfo,
|
33387
33421
|
mode,
|
33388
33422
|
gaps,
|
33389
|
-
corrections
|
33423
|
+
corrections,
|
33424
|
+
onAddLyrics
|
33390
33425
|
}) {
|
33391
33426
|
var _a;
|
33392
33427
|
const availableSources = reactExports.useMemo(
|
@@ -33496,7 +33531,8 @@ function ReferenceView({
|
|
33496
33531
|
{
|
33497
33532
|
availableSources,
|
33498
33533
|
currentSource: effectiveCurrentSource,
|
33499
|
-
onSourceChange
|
33534
|
+
onSourceChange,
|
33535
|
+
onAddLyrics
|
33500
33536
|
}
|
33501
33537
|
)
|
33502
33538
|
] }),
|
@@ -34563,9 +34599,6 @@ const SplitIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
|
34563
34599
|
const AutoFixHighIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
34564
34600
|
d: "M7.5 5.6 10 7 8.6 4.5 10 2 7.5 3.4 5 2l1.4 2.5L5 7zm12 9.8L17 14l1.4 2.5L17 19l2.5-1.4L22 19l-1.4-2.5L22 14zM22 2l-2.5 1.4L17 2l1.4 2.5L17 7l2.5-1.4L22 7l-1.4-2.5zm-7.63 5.29a.996.996 0 0 0-1.41 0L1.29 18.96c-.39.39-.39 1.02 0 1.41l2.34 2.34c.39.39 1.02.39 1.41 0L16.7 11.05c.39-.39.39-1.02 0-1.41zm-1.03 5.49-2.12-2.12 2.44-2.44 2.12 2.12z"
|
34565
34601
|
}), "AutoFixHigh");
|
34566
|
-
const AddIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
34567
|
-
d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"
|
34568
|
-
}), "Add");
|
34569
34602
|
const MergeIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
34570
34603
|
d: "M17 20.41 18.41 19 15 15.59 13.59 17zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5z"
|
34571
34604
|
}), "CallMerge");
|
@@ -34733,9 +34766,16 @@ const WordRow = reactExports.memo(function WordRow2({
|
|
34733
34766
|
onWordUpdate,
|
34734
34767
|
onSplitWord,
|
34735
34768
|
onRemoveWord,
|
34736
|
-
wordsLength
|
34769
|
+
wordsLength,
|
34770
|
+
onTabNavigation
|
34737
34771
|
}) {
|
34738
34772
|
var _a, _b;
|
34773
|
+
const handleKeyDown = (e) => {
|
34774
|
+
if (e.key === "Tab" && !e.shiftKey) {
|
34775
|
+
e.preventDefault();
|
34776
|
+
onTabNavigation(index);
|
34777
|
+
}
|
34778
|
+
};
|
34739
34779
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: {
|
34740
34780
|
display: "flex",
|
34741
34781
|
gap: 2,
|
@@ -34748,8 +34788,10 @@ const WordRow = reactExports.memo(function WordRow2({
|
|
34748
34788
|
label: `Word ${index}`,
|
34749
34789
|
value: word.text,
|
34750
34790
|
onChange: (e) => onWordUpdate(index, { text: e.target.value }),
|
34791
|
+
onKeyDown: handleKeyDown,
|
34751
34792
|
fullWidth: true,
|
34752
|
-
size: "small"
|
34793
|
+
size: "small",
|
34794
|
+
id: `word-text-${index}`
|
34753
34795
|
}
|
34754
34796
|
),
|
34755
34797
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -34811,7 +34853,8 @@ const WordItem = reactExports.memo(function WordItem2({
|
|
34811
34853
|
onAddSegment,
|
34812
34854
|
onMergeSegment,
|
34813
34855
|
wordsLength,
|
34814
|
-
isGlobal
|
34856
|
+
isGlobal,
|
34857
|
+
onTabNavigation
|
34815
34858
|
}) {
|
34816
34859
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { children: [
|
34817
34860
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -34822,7 +34865,8 @@ const WordItem = reactExports.memo(function WordItem2({
|
|
34822
34865
|
onWordUpdate,
|
34823
34866
|
onSplitWord,
|
34824
34867
|
onRemoveWord,
|
34825
|
-
wordsLength
|
34868
|
+
wordsLength,
|
34869
|
+
onTabNavigation
|
34826
34870
|
}
|
34827
34871
|
),
|
34828
34872
|
!isGlobal && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -34882,6 +34926,33 @@ function EditWordList({
|
|
34882
34926
|
const handlePageChange = (_event, value) => {
|
34883
34927
|
setPage(value);
|
34884
34928
|
};
|
34929
|
+
const handleTabNavigation = (currentIndex) => {
|
34930
|
+
const nextIndex = (currentIndex + 1) % words.length;
|
34931
|
+
if (isGlobal && (nextIndex < startIndex || nextIndex >= endIndex)) {
|
34932
|
+
const nextPage = Math.floor(nextIndex / pageSize) + 1;
|
34933
|
+
setPage(nextPage);
|
34934
|
+
setTimeout(() => {
|
34935
|
+
focusWordTextField(nextIndex);
|
34936
|
+
}, 50);
|
34937
|
+
} else {
|
34938
|
+
focusWordTextField(nextIndex);
|
34939
|
+
}
|
34940
|
+
};
|
34941
|
+
const focusWordTextField = (index) => {
|
34942
|
+
const element = document.getElementById(`word-text-${index}`);
|
34943
|
+
if (element) {
|
34944
|
+
let input = element.querySelector("input");
|
34945
|
+
if (!input) {
|
34946
|
+
input = element.querySelector(".MuiInputBase-input");
|
34947
|
+
}
|
34948
|
+
if (input) {
|
34949
|
+
input.focus();
|
34950
|
+
input.select();
|
34951
|
+
} else {
|
34952
|
+
element.focus();
|
34953
|
+
}
|
34954
|
+
}
|
34955
|
+
};
|
34885
34956
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: 1, flexGrow: 1, minHeight: 0 }, children: [
|
34886
34957
|
!isGlobal && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
34887
34958
|
WordDivider,
|
@@ -34933,7 +35004,8 @@ function EditWordList({
|
|
34933
35004
|
onAddSegment,
|
34934
35005
|
onMergeSegment,
|
34935
35006
|
wordsLength: words.length,
|
34936
|
-
isGlobal
|
35007
|
+
isGlobal,
|
35008
|
+
onTabNavigation: handleTabNavigation
|
34937
35009
|
},
|
34938
35010
|
word.id
|
34939
35011
|
);
|
@@ -35146,15 +35218,6 @@ function EditModal({
|
|
35146
35218
|
isGlobal = false,
|
35147
35219
|
isLoading = false
|
35148
35220
|
}) {
|
35149
|
-
console.log("EditModal - Render", {
|
35150
|
-
open,
|
35151
|
-
isGlobal,
|
35152
|
-
isLoading,
|
35153
|
-
hasSegment: !!segment,
|
35154
|
-
segmentIndex,
|
35155
|
-
hasOriginalSegment: !!originalSegment,
|
35156
|
-
hasOriginalTranscribedSegment: !!originalTranscribedSegment
|
35157
|
-
});
|
35158
35221
|
const [editedSegment, setEditedSegment] = reactExports.useState(segment);
|
35159
35222
|
const [isPlaying, setIsPlaying] = reactExports.useState(false);
|
35160
35223
|
const updateSegment2 = reactExports.useCallback((newWords) => {
|
@@ -35185,19 +35248,12 @@ function EditModal({
|
|
35185
35248
|
updateSegment: updateSegment2
|
35186
35249
|
});
|
35187
35250
|
const handleClose = reactExports.useCallback(() => {
|
35188
|
-
console.log("EditModal - handleClose called");
|
35189
35251
|
cleanupManualSync();
|
35190
35252
|
onClose();
|
35191
35253
|
}, [onClose, cleanupManualSync]);
|
35192
35254
|
reactExports.useEffect(() => {
|
35193
35255
|
const spacebarHandler = handleSpacebar;
|
35194
35256
|
if (open) {
|
35195
|
-
console.log("EditModal - Setting up modal spacebar handler", {
|
35196
|
-
hasPlaySegment: !!onPlaySegment,
|
35197
|
-
editedSegmentId: editedSegment == null ? void 0 : editedSegment.id,
|
35198
|
-
handlerFunction: spacebarHandler.toString().slice(0, 100),
|
35199
|
-
isLoading
|
35200
|
-
});
|
35201
35257
|
const handleKeyEvent = (e) => {
|
35202
35258
|
if (e.code === "Space") {
|
35203
35259
|
spacebarHandler(e);
|
@@ -35206,7 +35262,6 @@ function EditModal({
|
|
35206
35262
|
setModalSpacebarHandler(() => handleKeyEvent);
|
35207
35263
|
return () => {
|
35208
35264
|
if (!open) {
|
35209
|
-
console.log("EditModal - Cleanup: clearing modal spacebar handler");
|
35210
35265
|
setModalSpacebarHandler(void 0);
|
35211
35266
|
}
|
35212
35267
|
};
|
@@ -35228,11 +35283,6 @@ function EditModal({
|
|
35228
35283
|
}
|
35229
35284
|
}, [currentTime, editedSegment]);
|
35230
35285
|
reactExports.useEffect(() => {
|
35231
|
-
console.log("EditModal - segment changed", {
|
35232
|
-
hasSegment: !!segment,
|
35233
|
-
segmentId: segment == null ? void 0 : segment.id,
|
35234
|
-
wordCount: segment == null ? void 0 : segment.words.length
|
35235
|
-
});
|
35236
35286
|
setEditedSegment(segment);
|
35237
35287
|
}, [segment]);
|
35238
35288
|
reactExports.useEffect(() => {
|
@@ -35240,7 +35290,6 @@ function EditModal({
|
|
35240
35290
|
if (!editedSegment) return;
|
35241
35291
|
const endTime = editedSegment.end_time ?? 0;
|
35242
35292
|
if (window.isAudioPlaying && currentTime > endTime) {
|
35243
|
-
console.log("Stopping playback: current time exceeded end time");
|
35244
35293
|
(_a = window.toggleAudioPlayback) == null ? void 0 : _a.call(window);
|
35245
35294
|
cleanupManualSync();
|
35246
35295
|
}
|
@@ -35403,7 +35452,6 @@ function EditModal({
|
|
35403
35452
|
return getSafeTimeRange(editedSegment);
|
35404
35453
|
}, [getSafeTimeRange, editedSegment]);
|
35405
35454
|
const dialogTitle = reactExports.useMemo(() => {
|
35406
|
-
console.log("EditModal - Rendering dialog title", { isLoading, isGlobal });
|
35407
35455
|
if (isLoading) {
|
35408
35456
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
|
35409
35457
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { flex: 1, display: "flex", alignItems: "center", gap: 1 }, children: [
|
@@ -35433,23 +35481,11 @@ function EditModal({
|
|
35433
35481
|
] });
|
35434
35482
|
}, [isGlobal, segmentIndex, segment, onPlaySegment, handlePlayButtonClick, isPlaying, onClose, isLoading]);
|
35435
35483
|
if (!isLoading && (!segment || !editedSegment || !originalSegment)) {
|
35436
|
-
console.log("EditModal - Early return: missing required data", {
|
35437
|
-
hasSegment: !!segment,
|
35438
|
-
hasEditedSegment: !!editedSegment,
|
35439
|
-
hasOriginalSegment: !!originalSegment,
|
35440
|
-
isLoading
|
35441
|
-
});
|
35442
35484
|
return null;
|
35443
35485
|
}
|
35444
35486
|
if (!isLoading && !isGlobal && segmentIndex === null) {
|
35445
|
-
console.log("EditModal - Early return: non-global mode with null segmentIndex");
|
35446
35487
|
return null;
|
35447
35488
|
}
|
35448
|
-
console.log("EditModal - Rendering dialog content", {
|
35449
|
-
isLoading,
|
35450
|
-
hasEditedSegment: !!editedSegment,
|
35451
|
-
hasOriginalSegment: !!originalSegment
|
35452
|
-
});
|
35453
35489
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
35454
35490
|
Dialog,
|
35455
35491
|
{
|
@@ -35674,9 +35710,6 @@ const PauseIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
|
35674
35710
|
const PlayArrowIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
35675
35711
|
d: "M8 5v14l11-7z"
|
35676
35712
|
}), "PlayArrow");
|
35677
|
-
const TextSnippetIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
35678
|
-
d: "m20.41 8.41-4.83-4.83c-.37-.37-.88-.58-1.41-.58H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9.83c0-.53-.21-1.04-.59-1.42M7 7h7v2H7zm10 10H7v-2h10zm0-4H7v-2h10z"
|
35679
|
-
}), "TextSnippet");
|
35680
35713
|
const normalizeWordForComparison = (word) => ({
|
35681
35714
|
text: word.text,
|
35682
35715
|
start_time: word.start_time ?? 0,
|
@@ -36135,6 +36168,30 @@ function findAndReplace(data, findText, replaceText, options = {
|
|
36135
36168
|
newData.corrected_segments = newData.corrected_segments.filter((segment) => segment.words.length > 0);
|
36136
36169
|
return newData;
|
36137
36170
|
}
|
36171
|
+
function deleteWord(data, wordId) {
|
36172
|
+
const segmentIndex = data.corrected_segments.findIndex(
|
36173
|
+
(segment2) => segment2.words.some((word) => word.id === wordId)
|
36174
|
+
);
|
36175
|
+
if (segmentIndex === -1) {
|
36176
|
+
return data;
|
36177
|
+
}
|
36178
|
+
const segment = data.corrected_segments[segmentIndex];
|
36179
|
+
const wordIndex = segment.words.findIndex((word) => word.id === wordId);
|
36180
|
+
if (wordIndex === -1) {
|
36181
|
+
return data;
|
36182
|
+
}
|
36183
|
+
const updatedWords = segment.words.filter((_, index) => index !== wordIndex);
|
36184
|
+
if (updatedWords.length > 0) {
|
36185
|
+
const updatedSegment = {
|
36186
|
+
...segment,
|
36187
|
+
words: updatedWords,
|
36188
|
+
text: updatedWords.map((w) => w.text).join(" ")
|
36189
|
+
};
|
36190
|
+
return updateSegment(data, segmentIndex, updatedSegment);
|
36191
|
+
} else {
|
36192
|
+
return deleteSegment(data, segmentIndex);
|
36193
|
+
}
|
36194
|
+
}
|
36138
36195
|
const generateStorageKey = (data) => {
|
36139
36196
|
var _a;
|
36140
36197
|
const text = ((_a = data.original_segments[0]) == null ? void 0 : _a.text) || "";
|
@@ -36208,6 +36265,12 @@ const setModalHandler = (handler, open) => {
|
|
36208
36265
|
};
|
36209
36266
|
const setupKeyboardHandlers = (state) => {
|
36210
36267
|
Math.random().toString(36).substr(2, 9);
|
36268
|
+
const resetModifierStates = () => {
|
36269
|
+
var _a;
|
36270
|
+
state.setIsShiftPressed(false);
|
36271
|
+
(_a = state.setIsCtrlPressed) == null ? void 0 : _a.call(state, false);
|
36272
|
+
document.body.style.userSelect = "";
|
36273
|
+
};
|
36211
36274
|
const handleKeyDown = (e) => {
|
36212
36275
|
var _a;
|
36213
36276
|
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
@@ -36216,7 +36279,7 @@ const setupKeyboardHandlers = (state) => {
|
|
36216
36279
|
if (e.key === "Shift") {
|
36217
36280
|
state.setIsShiftPressed(true);
|
36218
36281
|
document.body.style.userSelect = "none";
|
36219
|
-
} else if (e.key === "Meta") {
|
36282
|
+
} else if (e.key === "Control" || e.key === "Ctrl" || e.key === "Meta") {
|
36220
36283
|
(_a = state.setIsCtrlPressed) == null ? void 0 : _a.call(state, true);
|
36221
36284
|
} else if (e.key === " " || e.code === "Space") {
|
36222
36285
|
e.preventDefault();
|
@@ -36228,20 +36291,30 @@ const setupKeyboardHandlers = (state) => {
|
|
36228
36291
|
}
|
36229
36292
|
};
|
36230
36293
|
const handleKeyUp = (e) => {
|
36231
|
-
|
36232
|
-
if (e.key === "
|
36233
|
-
state.setIsShiftPressed(false);
|
36234
|
-
document.body.style.userSelect = "";
|
36235
|
-
} else if (e.key === "Meta") {
|
36236
|
-
(_a = state.setIsCtrlPressed) == null ? void 0 : _a.call(state, false);
|
36237
|
-
} else if (e.key === " " || e.code === "Space") {
|
36294
|
+
resetModifierStates();
|
36295
|
+
if (e.key === " " || e.code === "Space") {
|
36238
36296
|
e.preventDefault();
|
36239
36297
|
if (isModalOpen && currentModalHandler) {
|
36240
36298
|
currentModalHandler(e);
|
36241
36299
|
}
|
36242
36300
|
}
|
36243
36301
|
};
|
36244
|
-
|
36302
|
+
const handleWindowBlur = () => {
|
36303
|
+
resetModifierStates();
|
36304
|
+
};
|
36305
|
+
const handleWindowFocus = () => {
|
36306
|
+
resetModifierStates();
|
36307
|
+
};
|
36308
|
+
window.addEventListener("blur", handleWindowBlur);
|
36309
|
+
window.addEventListener("focus", handleWindowFocus);
|
36310
|
+
return {
|
36311
|
+
handleKeyDown,
|
36312
|
+
handleKeyUp,
|
36313
|
+
cleanup: () => {
|
36314
|
+
window.removeEventListener("blur", handleWindowBlur);
|
36315
|
+
window.removeEventListener("focus", handleWindowFocus);
|
36316
|
+
}
|
36317
|
+
};
|
36245
36318
|
};
|
36246
36319
|
function ModeSelector({ effectiveMode, onChange }) {
|
36247
36320
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1.2, height: "32px" }, children: [
|
@@ -36251,7 +36324,7 @@ function ModeSelector({ effectiveMode, onChange }) {
|
|
36251
36324
|
{
|
36252
36325
|
value: effectiveMode,
|
36253
36326
|
exclusive: true,
|
36254
|
-
onChange: (_, newMode) => newMode && onChange(newMode),
|
36327
|
+
onChange: (_, newMode) => newMode === "edit" && onChange(newMode),
|
36255
36328
|
size: "small",
|
36256
36329
|
sx: {
|
36257
36330
|
height: "32px",
|
@@ -36262,28 +36335,38 @@ function ModeSelector({ effectiveMode, onChange }) {
|
|
36262
36335
|
}
|
36263
36336
|
},
|
36264
36337
|
children: [
|
36265
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36338
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { title: "Default mode; click words to edit that lyrics segment", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36266
36339
|
ToggleButton,
|
36267
36340
|
{
|
36268
36341
|
value: "edit",
|
36269
|
-
title: "Click to edit segments and make corrections in the transcription view",
|
36270
36342
|
children: [
|
36271
36343
|
/* @__PURE__ */ jsxRuntimeExports.jsx(EditIcon, { sx: { mr: 0.5, fontSize: "1rem" } }),
|
36272
36344
|
"Edit"
|
36273
36345
|
]
|
36274
36346
|
}
|
36275
|
-
),
|
36276
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36347
|
+
) }),
|
36348
|
+
/* @__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(
|
36277
36349
|
ToggleButton,
|
36278
36350
|
{
|
36279
36351
|
value: "highlight",
|
36280
|
-
|
36352
|
+
disabled: true,
|
36281
36353
|
children: [
|
36282
36354
|
/* @__PURE__ */ jsxRuntimeExports.jsx(HighlightIcon, { sx: { mr: 0.5, fontSize: "1rem" } }),
|
36283
36355
|
"Highlight"
|
36284
36356
|
]
|
36285
36357
|
}
|
36286
|
-
)
|
36358
|
+
) }) }),
|
36359
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { title: "Hold CTRL and click words to delete them", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
36360
|
+
ToggleButton,
|
36361
|
+
{
|
36362
|
+
value: "delete_word",
|
36363
|
+
disabled: true,
|
36364
|
+
children: [
|
36365
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DeleteIcon, { sx: { mr: 0.5, fontSize: "1rem" } }),
|
36366
|
+
"Delete"
|
36367
|
+
]
|
36368
|
+
}
|
36369
|
+
) }) })
|
36287
36370
|
]
|
36288
36371
|
}
|
36289
36372
|
)
|
@@ -36435,7 +36518,6 @@ function Header({
|
|
36435
36518
|
onHandlerToggle,
|
36436
36519
|
isUpdatingHandlers,
|
36437
36520
|
onHandlerClick,
|
36438
|
-
onAddLyrics,
|
36439
36521
|
onFindReplace,
|
36440
36522
|
onEditAll
|
36441
36523
|
}) {
|
@@ -36581,71 +36663,58 @@ function Header({
|
|
36581
36663
|
}
|
36582
36664
|
) })
|
36583
36665
|
] }),
|
36584
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Paper, { sx: { p: 0.8, mb: 1 }, children: /* @__PURE__ */ jsxRuntimeExports.
|
36666
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Paper, { sx: { p: 0.8, mb: 1 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: {
|
36585
36667
|
display: "flex",
|
36586
36668
|
flexDirection: isMobile ? "column" : "row",
|
36587
36669
|
gap: 1,
|
36588
36670
|
alignItems: isMobile ? "flex-start" : "center",
|
36589
36671
|
justifyContent: "space-between",
|
36590
36672
|
width: "100%"
|
36673
|
+
}, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: {
|
36674
|
+
display: "flex",
|
36675
|
+
gap: 1,
|
36676
|
+
flexDirection: isMobile ? "column" : "row",
|
36677
|
+
alignItems: isMobile ? "flex-start" : "center",
|
36678
|
+
height: "32px"
|
36591
36679
|
}, children: [
|
36592
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
36593
|
-
|
36594
|
-
|
36595
|
-
|
36596
|
-
|
36597
|
-
|
36598
|
-
|
36599
|
-
|
36600
|
-
|
36601
|
-
|
36602
|
-
|
36603
|
-
|
36604
|
-
|
36605
|
-
|
36606
|
-
|
36607
|
-
|
36608
|
-
|
36609
|
-
|
36610
|
-
|
36611
|
-
onClick: onFindReplace,
|
36612
|
-
startIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(FindReplaceIcon, {}),
|
36613
|
-
sx: { minWidth: "fit-content", height: "32px" },
|
36614
|
-
children: "Find/Replace"
|
36615
|
-
}
|
36616
|
-
),
|
36617
|
-
!isReadOnly && onEditAll && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
36618
|
-
Button,
|
36619
|
-
{
|
36620
|
-
variant: "outlined",
|
36621
|
-
size: "small",
|
36622
|
-
onClick: onEditAll,
|
36623
|
-
startIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(EditIcon, {}),
|
36624
|
-
sx: { minWidth: "fit-content", height: "32px" },
|
36625
|
-
children: "Edit All"
|
36626
|
-
}
|
36627
|
-
),
|
36628
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
36629
|
-
AudioPlayer,
|
36630
|
-
{
|
36631
|
-
apiClient,
|
36632
|
-
onTimeUpdate,
|
36633
|
-
audioHash
|
36634
|
-
}
|
36635
|
-
)
|
36636
|
-
] }),
|
36637
|
-
!isReadOnly && apiClient && onAddLyrics && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
36680
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
36681
|
+
ModeSelector,
|
36682
|
+
{
|
36683
|
+
effectiveMode,
|
36684
|
+
onChange: onModeChange
|
36685
|
+
}
|
36686
|
+
),
|
36687
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
36688
|
+
Button,
|
36689
|
+
{
|
36690
|
+
variant: "outlined",
|
36691
|
+
size: "small",
|
36692
|
+
onClick: onFindReplace,
|
36693
|
+
startIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(FindReplaceIcon, {}),
|
36694
|
+
sx: { minWidth: "fit-content", height: "32px" },
|
36695
|
+
children: "Find/Replace"
|
36696
|
+
}
|
36697
|
+
),
|
36698
|
+
!isReadOnly && onEditAll && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
36638
36699
|
Button,
|
36639
36700
|
{
|
36640
36701
|
variant: "outlined",
|
36641
36702
|
size: "small",
|
36642
|
-
onClick:
|
36643
|
-
startIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
36703
|
+
onClick: onEditAll,
|
36704
|
+
startIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(EditIcon, {}),
|
36644
36705
|
sx: { minWidth: "fit-content", height: "32px" },
|
36645
|
-
children: "
|
36706
|
+
children: "Edit All"
|
36707
|
+
}
|
36708
|
+
),
|
36709
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
36710
|
+
AudioPlayer,
|
36711
|
+
{
|
36712
|
+
apiClient,
|
36713
|
+
onTimeUpdate,
|
36714
|
+
audioHash
|
36646
36715
|
}
|
36647
36716
|
)
|
36648
|
-
] }) })
|
36717
|
+
] }) }) })
|
36649
36718
|
] });
|
36650
36719
|
}
|
36651
36720
|
function AddLyricsModal({
|
@@ -37119,7 +37188,8 @@ const MemoizedReferenceView = reactExports.memo(function MemoizedReferenceView2(
|
|
37119
37188
|
currentSource,
|
37120
37189
|
onSourceChange,
|
37121
37190
|
corrected_segments,
|
37122
|
-
corrections
|
37191
|
+
corrections,
|
37192
|
+
onAddLyrics
|
37123
37193
|
}) {
|
37124
37194
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
37125
37195
|
ReferenceView,
|
@@ -37135,7 +37205,8 @@ const MemoizedReferenceView = reactExports.memo(function MemoizedReferenceView2(
|
|
37135
37205
|
currentSource,
|
37136
37206
|
onSourceChange,
|
37137
37207
|
corrected_segments,
|
37138
|
-
corrections
|
37208
|
+
corrections,
|
37209
|
+
onAddLyrics
|
37139
37210
|
}
|
37140
37211
|
);
|
37141
37212
|
});
|
@@ -37152,7 +37223,6 @@ const MemoizedHeader = reactExports.memo(function MemoizedHeader2({
|
|
37152
37223
|
onHandlerToggle,
|
37153
37224
|
isUpdatingHandlers,
|
37154
37225
|
onHandlerClick,
|
37155
|
-
onAddLyrics,
|
37156
37226
|
onFindReplace,
|
37157
37227
|
onEditAll
|
37158
37228
|
}) {
|
@@ -37171,7 +37241,6 @@ const MemoizedHeader = reactExports.memo(function MemoizedHeader2({
|
|
37171
37241
|
onHandlerToggle,
|
37172
37242
|
isUpdatingHandlers,
|
37173
37243
|
onHandlerClick,
|
37174
|
-
onAddLyrics,
|
37175
37244
|
onFindReplace,
|
37176
37245
|
onEditAll
|
37177
37246
|
}
|
@@ -37193,6 +37262,7 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37193
37262
|
const [originalData] = reactExports.useState(() => JSON.parse(JSON.stringify(initialData)));
|
37194
37263
|
const [interactionMode, setInteractionMode] = reactExports.useState("edit");
|
37195
37264
|
const [isShiftPressed, setIsShiftPressed] = reactExports.useState(false);
|
37265
|
+
const [isCtrlPressed, setIsCtrlPressed] = reactExports.useState(false);
|
37196
37266
|
const [editModalSegment, setEditModalSegment] = reactExports.useState(null);
|
37197
37267
|
const [isEditAllModalOpen, setIsEditAllModalOpen] = reactExports.useState(false);
|
37198
37268
|
const [globalEditSegment, setGlobalEditSegment] = reactExports.useState(null);
|
@@ -37223,27 +37293,30 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37223
37293
|
}
|
37224
37294
|
}, [data, isReadOnly, initialData]);
|
37225
37295
|
reactExports.useEffect(() => {
|
37226
|
-
const { handleKeyDown, handleKeyUp } = setupKeyboardHandlers({
|
37227
|
-
setIsShiftPressed
|
37296
|
+
const { handleKeyDown, handleKeyUp, cleanup } = setupKeyboardHandlers({
|
37297
|
+
setIsShiftPressed,
|
37298
|
+
setIsCtrlPressed
|
37228
37299
|
});
|
37229
37300
|
window.addEventListener("keydown", handleKeyDown);
|
37230
37301
|
window.addEventListener("keyup", handleKeyUp);
|
37231
37302
|
if (isAnyModalOpen) {
|
37232
37303
|
setIsShiftPressed(false);
|
37304
|
+
setIsCtrlPressed(false);
|
37233
37305
|
}
|
37234
37306
|
return () => {
|
37235
37307
|
window.removeEventListener("keydown", handleKeyDown);
|
37236
37308
|
window.removeEventListener("keyup", handleKeyUp);
|
37237
37309
|
document.body.style.userSelect = "";
|
37310
|
+
cleanup();
|
37238
37311
|
};
|
37239
|
-
}, [setIsShiftPressed, isAnyModalOpen]);
|
37312
|
+
}, [setIsShiftPressed, setIsCtrlPressed, isAnyModalOpen]);
|
37240
37313
|
reactExports.useEffect(() => {
|
37241
37314
|
const modalOpen = Boolean(
|
37242
37315
|
modalContent || editModalSegment || isReviewModalOpen || isAddLyricsModalOpen || isFindReplaceModalOpen || isEditAllModalOpen
|
37243
37316
|
);
|
37244
37317
|
setIsAnyModalOpen(modalOpen);
|
37245
37318
|
}, [modalContent, editModalSegment, isReviewModalOpen, isAddLyricsModalOpen, isFindReplaceModalOpen, isEditAllModalOpen]);
|
37246
|
-
const effectiveMode = isShiftPressed ? "highlight" : interactionMode;
|
37319
|
+
const effectiveMode = isCtrlPressed ? "delete_word" : isShiftPressed ? "highlight" : interactionMode;
|
37247
37320
|
const handleFlash = reactExports.useCallback((type, info) => {
|
37248
37321
|
setFlashingType(null);
|
37249
37322
|
setHighlightInfo(null);
|
@@ -37262,6 +37335,12 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37262
37335
|
}, []);
|
37263
37336
|
const handleWordClick = reactExports.useCallback((info) => {
|
37264
37337
|
var _a, _b, _c, _d, _e, _f, _g;
|
37338
|
+
if (effectiveMode === "delete_word") {
|
37339
|
+
const newData = deleteWord(data, info.word_id);
|
37340
|
+
setData(newData);
|
37341
|
+
handleFlash("word");
|
37342
|
+
return;
|
37343
|
+
}
|
37265
37344
|
if (effectiveMode === "highlight") {
|
37266
37345
|
const correction = (_a = data.corrections) == null ? void 0 : _a.find(
|
37267
37346
|
(c) => c.corrected_word_id === info.word_id || c.word_id === info.word_id
|
@@ -37369,7 +37448,7 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37369
37448
|
});
|
37370
37449
|
}
|
37371
37450
|
}
|
37372
|
-
}, [data, effectiveMode, setModalContent]);
|
37451
|
+
}, [data, effectiveMode, setModalContent, handleFlash, deleteWord]);
|
37373
37452
|
const handleUpdateSegment = reactExports.useCallback((updatedSegment) => {
|
37374
37453
|
if (!editModalSegment) return;
|
37375
37454
|
const newData = updateSegment(data, editModalSegment.index, updatedSegment);
|
@@ -37706,7 +37785,8 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37706
37785
|
currentSource,
|
37707
37786
|
onSourceChange: setCurrentSource,
|
37708
37787
|
corrected_segments: data.corrected_segments,
|
37709
|
-
corrections: data.corrections
|
37788
|
+
corrections: data.corrections,
|
37789
|
+
onAddLyrics: () => setIsAddLyricsModalOpen(true)
|
37710
37790
|
}
|
37711
37791
|
) })
|
37712
37792
|
] }),
|
@@ -38141,4 +38221,4 @@ ReactDOM$1.createRoot(document.getElementById("root")).render(
|
|
38141
38221
|
/* @__PURE__ */ jsxRuntimeExports.jsx(App, {})
|
38142
38222
|
] })
|
38143
38223
|
);
|
38144
|
-
//# sourceMappingURL=index-
|
38224
|
+
//# sourceMappingURL=index-2vK-qVJS.js.map
|