Skip to content

Commit

Permalink
Add copy ruby
Browse files Browse the repository at this point in the history
  • Loading branch information
hockyy committed Sep 6, 2024
1 parent 53e558a commit 4bbc72d
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 39 deletions.
92 changes: 63 additions & 29 deletions renderer/components/Subtitle/Subtitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const PrimarySubtitle = ({
timeCache,
setTimeCache,
setExternalContent,
setRubyCopyContent
}: {
currentTime: number,
subtitle: SubtitleContainer,
Expand All @@ -27,7 +28,8 @@ export const PrimarySubtitle = ({
getLearningStateClass?: (newMeaning: string) => string,
timeCache?: number[],
setTimeCache?: (cache: number[]) => void,
setExternalContent?: (content: any[]) => void;
setExternalContent?: (content: any[]) => void,
setRubyCopyContent: any;
}
) => {
const [caption, setCaption] = useState([]);
Expand All @@ -36,7 +38,8 @@ export const PrimarySubtitle = ({
const setFromContent = useCallback((content, wordMeaning = []) => {
if (setExternalContent) setExternalContent(content);
if (content === '' || content.length === 0) {
setCaption([])
setCaption([]);
setRubyCopyContent('');
return;
}
if (typeof content === 'string') {
Expand All @@ -49,37 +52,68 @@ export const PrimarySubtitle = ({
extraClass={"subtitle"}
subtitleStyling={subtitleStyling}
wordMeaning={''}/>]);
setRubyCopyContent(content);
return;
}
let rubyCopyContent = '';
const current = content.map((val, index) => {
const validBasicForm = val.basicForm != '' && val.basicForm != '*';
return <> {(val.jyutping || val.pinyin) ? <ChineseSentence
key={index}
origin={val.origin}
separation={val.separation}
setMeaning={setMeaning}
extraClass={"subtitle"}
subtitleStyling={subtitleStyling}
basicForm={validBasicForm ? val.basicForm : ''}
wordMeaning={wordMeaning[index]}
getLearningStateClass={getLearningStateClass}
changeLearningState={changeLearningState}/> : <JapaneseSentence
key={index}
origin={val.origin}
separation={val.separation}
setMeaning={setMeaning}
extraClass={"subtitle"}
subtitleStyling={subtitleStyling}
basicForm={validBasicForm ? val.basicForm : ''}
wordMeaning={wordMeaning[index]}
getLearningStateClass={getLearningStateClass}
changeLearningState={changeLearningState}/>}{
index + 1 < content.length
&& subtitleStyling.showSpace ? " " : " "
}</>
})
setCaption(current)
}, [setExternalContent, subtitleStyling, setMeaning, getLearningStateClass, changeLearningState]);
const isChineseSentence = val.jyutping || val.pinyin;
const isJapaneseSentence = val.hiragana !== undefined;

// Generate ruby HTML for copying
const rubyHtml = val.separation.map(part => {
let reading;
if (isChineseSentence) {
reading = part.jyutping || part.pinyin;
} else if (isJapaneseSentence) {
reading = part.hiragana || part.romaji;
} else {
reading = '';
}
return `<ruby>${part.main}<rt>${reading || ''}</rt></ruby>`;
}).join('');
rubyCopyContent += rubyHtml;

if (index + 1 < content.length && subtitleStyling.showSpace) {
rubyCopyContent += ' ';
}

return (
<React.Fragment key={index}>
{isChineseSentence ? (
<ChineseSentence
origin={val.origin}
separation={val.separation}
setMeaning={setMeaning}
extraClass={"subtitle"}
subtitleStyling={subtitleStyling}
basicForm={validBasicForm ? val.basicForm : ''}
wordMeaning={wordMeaning[index]}
getLearningStateClass={getLearningStateClass}
changeLearningState={changeLearningState}
/>
) : (
<JapaneseSentence
origin={val.origin}
separation={val.separation}
setMeaning={setMeaning}
extraClass={"subtitle"}
subtitleStyling={subtitleStyling}
basicForm={validBasicForm ? val.basicForm : ''}
wordMeaning={wordMeaning[index]}
getLearningStateClass={getLearningStateClass}
changeLearningState={changeLearningState}
/>
)}
{index + 1 < content.length && subtitleStyling.showSpace ? " " : " "}
</React.Fragment>
);
});

setCaption(current);
setRubyCopyContent(rubyCopyContent);
}, [setExternalContent, setRubyCopyContent, subtitleStyling, setMeaning, getLearningStateClass, changeLearningState]);

const setSubtitle = useCallback((currentAdjustedTime) => {
try {
Expand Down
17 changes: 15 additions & 2 deletions renderer/components/VideoPlayer/KeyboardHelp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ const shortcutInformation = [
}, {
key: "X",
description: "Toggle Sidebar"
}, {
key: "Ctrl + X",
description: "Toggle Vocab Sidebar"
}, {
key: "Ctrl + H",
description: "Back to Home"
}, {
key: "Esc",
description: "Exit From CJK Information Box"
description: "Exit From CJK Information Box / Undo"
}, {
key: "D",
description: "Go Back to Previous Meaning Box"
Expand Down Expand Up @@ -50,6 +53,12 @@ const shortcutInformation = [
}, {
key: "Ctrl + Shift + L",
description: "Toggle Learning Mode"
}, {
key: "Ctrl + K",
description: "Open Flash Cards"
}, {
key: "Ctrl + Shift + K",
description: "Open Database"
}, {
key: "[",
description: "Shift CJK Subtitle Slower"
Expand All @@ -62,7 +71,11 @@ const shortcutInformation = [
}, {
key: "Ctrl + ]",
description: "Shift Main Subtitle Faster"
}]
}, {
key: "C",
description: "Copy Ruby Content"
}
]

export const Key = ({
value,
Expand Down
14 changes: 12 additions & 2 deletions renderer/hooks/useKeyBind.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export default function useKeyBind(
openGoogleTranslate,
reloadLastPrimarySubtitle,
reloadLastSecondarySubtitle,
setShowVocabSidebar
setShowVocabSidebar,
rubyContent
) {
const router = useRouter();
useEffect(() => {
Expand Down Expand Up @@ -85,6 +86,15 @@ export default function useKeyBind(
} else if (event.code === "KeyA") {
reloadLastSecondarySubtitle();
reloadLastPrimarySubtitle();
} else if (event.code === "KeyC") {
// New copy functionality
if (rubyContent) {
try {
await navigator.clipboard.writeText(rubyContent);
} catch (err) {
console.error("Failed to copy text: ", err);
}
}
}
};

Expand All @@ -93,6 +103,6 @@ export default function useKeyBind(
return () => {
window.removeEventListener('keydown', handleKeyPress);
};
}, [router, setMeaning, setShowController, setShowSidebar, setPrimarySub, setSecondarySub, setPrimaryStyling, primarySub.id, setShowPrimarySub, setShowSecondarySub, undo, primaryStyling, openGoogleTranslate, openDeepL, reloadLastSecondarySubtitle, reloadLastPrimarySubtitle, setShowVocabSidebar]);
}, [router, setMeaning, setShowController, setShowSidebar, setPrimarySub, setSecondarySub, setPrimaryStyling, primarySub.id, setShowPrimarySub, setShowSecondarySub, undo, primaryStyling, openGoogleTranslate, openDeepL, reloadLastSecondarySubtitle, reloadLastPrimarySubtitle, setShowVocabSidebar, rubyContent]);

}
9 changes: 7 additions & 2 deletions renderer/hooks/useLearningKeyBind.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {useRouter} from "next/router";
export default function useLearningKeyBind(
setMeaning,
setShowSidebar,
undo
undo,
rubyContent: any = ''
) {
const router = useRouter();
useEffect(() => {
Expand All @@ -21,6 +22,10 @@ export default function useLearningKeyBind(
setShowSidebar((old) => {
return !old;
});
} else if (event.code === "KeyC" && event.ctrlKey) {
if (rubyContent) {
await navigator.clipboard.writeText(rubyContent);
}
}
};

Expand All @@ -29,6 +34,6 @@ export default function useLearningKeyBind(
return () => {
window.removeEventListener('keydown', handleKeyPress);
};
}, [router, setMeaning, setShowSidebar, undo]);
}, [router, rubyContent, setMeaning, setShowSidebar, undo]);

}
8 changes: 8 additions & 0 deletions renderer/hooks/useRubyCopy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {useState} from 'react';

const useRubyCopy = () => {
const [rubyContent, setRubyContent] = useState('');
return [rubyContent, setRubyContent];
};

export default useRubyCopy;
8 changes: 6 additions & 2 deletions renderer/pages/learn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import useTranslationLinks from "../hooks/useTranslationLinks";
import 'react-awesome-button/dist/styles.css';
import useGoogleTranslator from "../hooks/useGoogleTranslator";
import TranslationDisplay from "../components/Subtitle/TranslationDisplay";
import useRubyCopy from "../hooks/useRubyCopy";

function Learn() {
const {
Expand All @@ -31,7 +32,8 @@ function Learn() {
const [directInput, setDirectInput] = useState('');
const [showSidebar, setShowSidebar] = useState(0)
const [primaryStyling, setPrimaryStyling] = useStoreData('user.styling.learning', defaultLearningStyling);
useLearningKeyBind(setMeaning, setShowSidebar, undo)
const [rubyContent, setRubyCopyContent] = useRubyCopy();
useLearningKeyBind(setMeaning, setShowSidebar, undo, rubyContent);
const router = useRouter();
const {
tokenizerMode,
Expand Down Expand Up @@ -133,7 +135,8 @@ function Learn() {
<AwesomeButton type={'primary'} onPress={() => handleTranslate(true)}>
Translate Now
</AwesomeButton>
<AwesomeButton type={isAutoTranslating ? 'secondary' : 'primary'} onPress={toggleAutoTranslate}>
<AwesomeButton type={isAutoTranslating ? 'secondary' : 'primary'}
onPress={toggleAutoTranslate}>
{isAutoTranslating ? 'Stop Auto Translate' : 'Start Auto Translate'}
</AwesomeButton>
</div>
Expand All @@ -154,6 +157,7 @@ function Learn() {
subtitleStyling={primaryStyling}
getLearningStateClass={getLearningStateClass}
changeLearningState={changeLearningState}
setRubyCopyContent={setRubyCopyContent}
/>
</div>
</ContainerHome>
Expand Down
8 changes: 6 additions & 2 deletions renderer/pages/video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import useTranslationLinks from "../hooks/useTranslationLinks";
import useContentString from "../hooks/useContentString";
import useVocabSidebar from "../hooks/useVocabSidebar";
import VocabSidebar from "../components/VideoPlayer/VocabSidebar";
import useRubyCopy from "../hooks/useRubyCopy";

function Video() {
const {
Expand Down Expand Up @@ -120,11 +121,13 @@ function Video() {
showSidebar,
setShowSidebar
} = useMenuDisplay();

const [rubyContent, setRubyCopyContent] = useRubyCopy();
useKeyBind(setMeaning, setShowController, setShowSidebar,
setPrimarySub, setSecondarySub, primarySub, undo,
setShowPrimarySub, setShowSecondarySub, primaryStyling, setPrimaryStyling,
openDeepL, openGoogleTranslate, reloadLastPrimarySubtitle, reloadLastSecondarySubtitle,
setShowVocabSidebar);
setShowVocabSidebar, rubyContent);
const {
togglePlay,
isPlaying,
Expand Down Expand Up @@ -184,7 +187,8 @@ function Video() {
changeLearningState={changeLearningState}
timeCache={primaryTimeCache}
setTimeCache={setPrimaryTimeCache}
setExternalContent={setExternalContent}/>}
setExternalContent={setExternalContent}
setRubyCopyContent={setRubyCopyContent}/>}
{showSecondarySub && <SecondarySubtitle
currentTime={currentTime}
subtitle={secondarySub}
Expand Down

0 comments on commit 4bbc72d

Please sign in to comment.