diff --git a/renderer/components/Meaning/MeaningBox.tsx b/renderer/components/Meaning/MeaningBox.tsx index 43b6e4f..0b85642 100644 --- a/renderer/components/Meaning/MeaningBox.tsx +++ b/renderer/components/Meaning/MeaningBox.tsx @@ -36,7 +36,9 @@ const OutlinedStar = ({color, size, outlineColor = 'black', outlineWidth = 1}) = const initialContentState = { id: "", sense: [], - single: [] + single: [], + content: '', + simplified: '' }; const initialCharacterContentState = {literal: null}; @@ -118,17 +120,26 @@ const MeaningBox = ({ useEffect(() => { const fetchRomajiedData = async () => { - const data = await Promise.all( - meaningContent.single.map(async (val) => ({ - key: val.key, - romajied: await tokenizeMiteiru(val.text) - })) - ); - setRomajiedData(data); + console.log(meaningContent); + if (lang === videoConstants.japaneseLang) { + const data = await Promise.all( + meaningContent.single.map(async (val) => { + return ({ + key: val.key, + romajied: await tokenizeMiteiru(val.text) + }); + }) + ); + setRomajiedData(data); + } else if (lang === videoConstants.cantoneseLang || videoConstants.chineseLang) { + const usedData = (meaningContent.simplified.includes(meaning)) ? meaningContent.simplified : meaningContent.content; + const data = [{key: 0, romajied: (await tokenizeMiteiru(usedData))}]; + setRomajiedData(data); + } }; if (meaningContent.single.length) fetchRomajiedData(); - }, [meaningContent.single, tokenizeMiteiru]); + }, [lang, meaning, meaningContent, tokenizeMiteiru]); const handleBGClick = useCallback(() => setMeaning(''), [setMeaning]); @@ -234,7 +245,6 @@ const MeaningContent = ({meaningContent, lang, tags}) => { const RomajiedContent = ({romajied, lang, setMeaning, subtitleStyling}) => { const queryText = romajied.reduce((acc, next) => acc + next.origin, ""); - return (
{ extraClass="unselectable meaning-kanji text-md" subtitleStyling={subtitleStyling}/> ))} - {(lang === videoConstants.chineseLang || lang === videoConstants.cantoneseLang) && romajied.map((val, idx) => ( - - ))} + {(lang === videoConstants.chineseLang || lang === videoConstants.cantoneseLang) && romajied.map((val, idx) => { + return ( + + + ); + })}
diff --git a/renderer/components/VideoPlayer/VocabSidebar.tsx b/renderer/components/VideoPlayer/VocabSidebar.tsx index 6626de2..f9f395a 100644 --- a/renderer/components/VideoPlayer/VocabSidebar.tsx +++ b/renderer/components/VideoPlayer/VocabSidebar.tsx @@ -3,10 +3,21 @@ import React, {useState, useEffect, useCallback} from 'react'; import {ipcRenderer} from 'electron'; import {getColorGradient, getRelativeTime} from '../../utils/utils'; import {ArrowRight} from "./Icons"; -import {AwesomeButton} from "react-awesome-button"; +import {HanziSentence, KanjiSentence} from "../Subtitle/Sentence"; +import {videoConstants} from "../../utils/constants"; +import {defaultLearningStyling, defaultMeaningBoxStyling} from "../../utils/CJKStyling"; +import SmoothCollapse from "react-smooth-collapse"; -const VocabSidebar = ({showVocabSidebar, setShowVocabSidebar, lang, setMeaning}) => { +const VocabSidebar = ({ + showVocabSidebar, + setShowVocabSidebar, + lang, + setMeaning, + tokenizeMiteiru + }) => { const [sortedVocab, setSortedVocab] = useState([]); + const [hoveredWord, setHoveredWord] = useState(null); + const [tokenizedWord, setTokenizedWord] = useState(null); const loadVocabulary = useCallback(async () => { try { @@ -26,22 +37,28 @@ const VocabSidebar = ({showVocabSidebar, setShowVocabSidebar, lang, setMeaning}) setMeaning(word); }, [setMeaning]); - const saveVocabHandler = useCallback(() => { - ipcRenderer.invoke('loadLearningState', lang).then((val) => { - ipcRenderer.invoke("saveFile", ["json"], JSON.stringify(val)) - }) - }, [lang]); + const handleMouseEnter = useCallback(async (word) => { + setHoveredWord(word); + const tokenized = await tokenizeMiteiru(word); + setTokenizedWord(tokenized); + }, [tokenizeMiteiru]); - const loadVocabHandler = useCallback(() => { - ipcRenderer.invoke("readFile", ["json"]).then((val) => { - try { - const parsed = JSON.parse(val); - ipcRenderer.invoke("updateContentBatch", parsed, lang) - } catch (e) { - console.error(e) - } - }) - }, [lang]); + const handleMouseLeave = useCallback(() => { + setHoveredWord(null); + setTokenizedWord(null); + }, []); + + const renderTokenizedWord = useCallback(() => { + if (!tokenizedWord) return null; + + if (lang === videoConstants.japaneseLang) { + return (tokenizedWord); + } else if (lang === videoConstants.chineseLang || lang === videoConstants.cantoneseLang) { + return (tokenizedWord.map(t => t.pinyin || t.jyutping)); + } + + return null; + }, [tokenizedWord, lang]); return (
-
- - Save Vocabulary - - - Load Vocabulary - -
{sortedVocab.map((word) => (
jumpToWord(word[0])} + onMouseEnter={() => handleMouseEnter(word[0])} + onMouseLeave={handleMouseLeave} style={{backgroundColor: getColorGradient(word[1].updTime)}} > - {word[0]} - {getRelativeTime(word[1].updTime)} +
+ {word[0]} + {getRelativeTime(word[1].updTime)} +
+ {hoveredWord === word[0] && renderTokenizedWord()}
))}
diff --git a/renderer/pages/video.tsx b/renderer/pages/video.tsx index 9296f6f..6974622 100644 --- a/renderer/pages/video.tsx +++ b/renderer/pages/video.tsx @@ -225,6 +225,7 @@ function Video() { setShowVocabSidebar={setShowVocabSidebar} lang={lang} setMeaning={setMeaning} + tokenizeMiteiru={tokenizeMiteiru} /> );