mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
fix selection (for good?)
This commit is contained in:
@@ -4,7 +4,6 @@ import { useEffect, useRef, useState } from "react";
|
||||
import { Participant } from "../../../../api";
|
||||
import getApi from "../../../../lib/getApi";
|
||||
import { UseParticipants } from "../../useParticipants";
|
||||
import { unescapeLeadingUnderscores } from "typescript";
|
||||
|
||||
type ParticipantList = {
|
||||
participants: UseParticipants;
|
||||
@@ -27,6 +26,7 @@ const ParticipantList = ({
|
||||
const [participantInput, setParticipantInput] = useState("");
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [selectedSpeaker, setSelectedSpeaker] = stateSelectedSpeaker;
|
||||
const [selectedParticipant, setSelectedParticipant] = useState<Participant>();
|
||||
const [action, setAction] = useState<
|
||||
"Create" | "Create to rename" | "Create and assign" | "Rename" | null
|
||||
>(null);
|
||||
@@ -47,9 +47,11 @@ const ParticipantList = ({
|
||||
);
|
||||
if (participant) {
|
||||
setParticipantInput(participant.name);
|
||||
setSelectedParticipant(participant);
|
||||
inputRef.current?.focus();
|
||||
setAction("Rename");
|
||||
} else {
|
||||
} else if (!selectedParticipant) {
|
||||
setSelectedParticipant(undefined);
|
||||
setParticipantInput("");
|
||||
inputRef.current?.focus();
|
||||
setAction("Create to rename");
|
||||
@@ -59,6 +61,10 @@ const ParticipantList = ({
|
||||
setParticipantInput("");
|
||||
inputRef.current?.focus();
|
||||
setAction("Create and assign");
|
||||
setSelectedParticipant(undefined);
|
||||
}
|
||||
if (!selectedTime && !selectedSpeaker) {
|
||||
setAction(null);
|
||||
}
|
||||
}
|
||||
}, [selectedTime, selectedSpeaker]);
|
||||
@@ -78,6 +84,12 @@ const ParticipantList = ({
|
||||
setOneMatch(undefined);
|
||||
}
|
||||
}
|
||||
if (participantInput && !action) {
|
||||
setAction("Create");
|
||||
}
|
||||
if (!participantInput) {
|
||||
setAction(null);
|
||||
}
|
||||
}, [participantInput]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -88,11 +100,15 @@ const ParticipantList = ({
|
||||
setOneMatch(undefined);
|
||||
setParticipantInput("");
|
||||
}
|
||||
} else if (e.key === "Enter") {
|
||||
doAction();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const doAction = (e) => {
|
||||
const doAction = (e?) => {
|
||||
e?.preventDefault();
|
||||
e?.stopPropagation();
|
||||
if (!participants.response) return;
|
||||
if (action == "Rename") {
|
||||
const participant = participants.response.find(
|
||||
@@ -124,6 +140,7 @@ const ParticipantList = ({
|
||||
})
|
||||
.then(() => {
|
||||
participants.refetch();
|
||||
setParticipantInput("");
|
||||
});
|
||||
} else if (action == "Create and assign") {
|
||||
setLoading(true);
|
||||
@@ -138,11 +155,22 @@ const ParticipantList = ({
|
||||
.then((participant) => {
|
||||
assignTo(participant)();
|
||||
participants.refetch();
|
||||
setParticipantInput("");
|
||||
});
|
||||
} else if (action == "Create") {
|
||||
setLoading(true);
|
||||
api
|
||||
?.v1TranscriptAddParticipant({
|
||||
createParticipant: {
|
||||
name: participantInput,
|
||||
},
|
||||
transcriptId,
|
||||
})
|
||||
.then(() => {
|
||||
participants.refetch();
|
||||
setParticipantInput("");
|
||||
});
|
||||
}
|
||||
e.preventDefault();
|
||||
console.log(e);
|
||||
console.log(action);
|
||||
};
|
||||
|
||||
const deleteParticipant = (participantId) => () => {
|
||||
@@ -162,6 +190,7 @@ const ParticipantList = ({
|
||||
(participant) => (e?: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e?.preventDefault();
|
||||
e?.stopPropagation();
|
||||
// fix participant that doesnt have a speaker (wait API)
|
||||
if (selectedTime?.start == undefined || selectedTime?.end == undefined)
|
||||
return;
|
||||
api
|
||||
@@ -179,22 +208,29 @@ const ParticipantList = ({
|
||||
};
|
||||
|
||||
const selectParticipant = (participant) => (e) => {
|
||||
console.log(participant, e);
|
||||
setSelectedParticipant(participant);
|
||||
setSelectedSpeaker(participant.speaker);
|
||||
setAction("Rename");
|
||||
setParticipantInput(participant.name);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<form onSubmit={doAction}>
|
||||
<div>
|
||||
<input
|
||||
ref={inputRef}
|
||||
onChange={(e) => setParticipantInput(e.target.value)}
|
||||
value={participantInput}
|
||||
/>
|
||||
<button type="submit">
|
||||
<FontAwesomeIcon icon={faArrowTurnDown} className="rotate-90 mr-2" />
|
||||
{action}
|
||||
</button>
|
||||
</form>
|
||||
{action && (
|
||||
<button onClick={doAction}>
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowTurnDown}
|
||||
className="rotate-90 mr-2"
|
||||
/>
|
||||
{action}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{participants.loading && (
|
||||
<FontAwesomeIcon
|
||||
@@ -214,7 +250,7 @@ const ParticipantList = ({
|
||||
participant.name.startsWith(participantInput)
|
||||
? "bg-blue-100 "
|
||||
: "") +
|
||||
(participant.speaker == selectedSpeaker
|
||||
(participant.id == selectedParticipant?.id
|
||||
? "border-blue-400 border"
|
||||
: "")
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ const TopicPlayer = ({ transcriptId, selectedTime, topicTime }) => {
|
||||
useState<() => void>();
|
||||
|
||||
//TODO shortcuts
|
||||
// TODO if selection changes while playing, don't play
|
||||
|
||||
useEffect(() => {
|
||||
setEndTopicCallback(
|
||||
|
||||
@@ -12,7 +12,7 @@ type Word = {
|
||||
|
||||
type WordBySpeaker = { speaker: number; words: Word[] }[];
|
||||
|
||||
// TODO shortcuts
|
||||
// TODO shortcuts ?
|
||||
// TODO fix key (using indexes might act up, not sure as we don't re-order per say)
|
||||
|
||||
type TopicWordsProps = {
|
||||
@@ -63,6 +63,25 @@ const topicWords = ({
|
||||
}
|
||||
}, [topicWithWords.response]);
|
||||
|
||||
const getStartTimeFromFirstNode = (node, offset, reverse) => {
|
||||
// if the first element is a word
|
||||
return node.parentElement?.dataset["start"]
|
||||
? // but after of the word (like on the blank space right of the word)
|
||||
node.textContent?.length == offset
|
||||
? // if next element is a word, we need the start of it
|
||||
(node.parentElement?.nextElementSibling as any)?.dataset?.["start"] ||
|
||||
// otherwise we get the start of the first word of the next paragraph
|
||||
(
|
||||
node.parentElement?.parentElement?.nextElementSibling
|
||||
?.childNodes[1] as any
|
||||
)?.dataset?.["start"] ||
|
||||
(reverse ? 0 : 99)
|
||||
: // otherwise it's just somewhere in the word and we get the start of the word
|
||||
node.parentElement?.dataset["start"]
|
||||
: // otherwise selection start is on a name and we get the start of the next word
|
||||
(node.parentElement?.nextElementSibling as any)?.dataset["start"];
|
||||
};
|
||||
|
||||
const onMouseUp = (e) => {
|
||||
let selection = window.getSelection();
|
||||
if (
|
||||
@@ -102,35 +121,47 @@ const topicWords = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const anchorStart = anchorIsWord
|
||||
? anchorNode.parentElement?.dataset["start"]
|
||||
: (selection.anchorNode.parentElement?.nextElementSibling as any)
|
||||
?.dataset["start"];
|
||||
const anchorStart = getStartTimeFromFirstNode(
|
||||
anchorNode,
|
||||
selection.anchorOffset,
|
||||
false,
|
||||
);
|
||||
// if selection end on a word, we get the end time from the span that contains it
|
||||
const focusEnd =
|
||||
selection.focusNode.parentElement?.dataset["end"] ||
|
||||
// otherwise it was a name and we get the end of the last word of the previous paragraph
|
||||
(
|
||||
selection.focusNode.parentElement?.parentElement
|
||||
?.previousElementSibling?.lastElementChild as any
|
||||
)?.dataset["end"];
|
||||
)?.dataset["end"] ||
|
||||
0;
|
||||
|
||||
const reverse = parseFloat(anchorStart) > parseFloat(focusEnd);
|
||||
|
||||
if (!reverse) {
|
||||
setSelectedTime({ start: anchorStart, end: focusEnd });
|
||||
setSelectedTime({
|
||||
start: parseFloat(anchorStart),
|
||||
end: parseFloat(focusEnd),
|
||||
});
|
||||
console.log("setting right");
|
||||
} else {
|
||||
const anchorEnd = anchorIsWord
|
||||
? anchorNode.parentElement?.dataset["end"]
|
||||
: (selection.anchorNode.parentElement?.nextElementSibling as any)
|
||||
?.dataset["end"];
|
||||
const focusStart =
|
||||
selection.focusNode.parentElement?.dataset["start"] ||
|
||||
const anchorEnd =
|
||||
anchorNode.parentElement?.dataset["end"] ||
|
||||
(
|
||||
selection.focusNode.parentElement?.parentElement
|
||||
selection.anchorNode.parentElement?.parentElement
|
||||
?.previousElementSibling?.lastElementChild as any
|
||||
)?.dataset["start"];
|
||||
)?.dataset["end"];
|
||||
|
||||
const focusStart = getStartTimeFromFirstNode(
|
||||
focusNode,
|
||||
selection.focusOffset,
|
||||
true,
|
||||
);
|
||||
|
||||
setSelectedTime({ start: focusStart, end: anchorEnd });
|
||||
console.log("setting reverse");
|
||||
}
|
||||
|
||||
setSelectedSpeaker();
|
||||
selection.empty();
|
||||
}
|
||||
@@ -147,7 +178,7 @@ const topicWords = ({
|
||||
|
||||
if (!topicWithWords.loading && wordsBySpeaker && participants.response) {
|
||||
return (
|
||||
<div onMouseUp={onMouseUp} onBlur={(e) => console.log(e)}>
|
||||
<div onMouseUp={onMouseUp} className="p-5 h-full w-full">
|
||||
{wordsBySpeaker?.map((speakerWithWords, index) => (
|
||||
<p key={index}>
|
||||
<span
|
||||
|
||||
Reference in New Issue
Block a user