mirror of
https://github.com/RealKai42/qwerty-learner.git
synced 2026-04-04 22:09:04 +08:00
feat: add isTextSelectable switcher
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { phoneticConfigAtom } from '@/store'
|
||||
import { isTextSelectableAtom, phoneticConfigAtom } from '@/store'
|
||||
import { Word } from '@/typings'
|
||||
import { useAtomValue } from 'jotai'
|
||||
|
||||
@@ -8,9 +8,14 @@ export type PhoneticProps = {
|
||||
|
||||
function Phonetic({ word }: PhoneticProps) {
|
||||
const phoneticConfig = useAtomValue(phoneticConfigAtom)
|
||||
const isTextSelectable = useAtomValue(isTextSelectableAtom)
|
||||
|
||||
return (
|
||||
<div className="space-x-5 pt-1 text-center text-sm font-normal text-gray-600 transition-colors duration-300 dark:text-gray-400">
|
||||
<div
|
||||
className={`space-x-5 pt-1 text-center text-sm font-normal text-gray-600 transition-colors duration-300 dark:text-gray-400 ${
|
||||
!isTextSelectable && 'select-none'
|
||||
}`}
|
||||
>
|
||||
{phoneticConfig.type === 'us' && word.usphone && word.usphone.length > 1 && <span>{`AmE: [${word.usphone}]`}</span>}
|
||||
{phoneticConfig.type === 'uk' && word.ukphone && word.ukphone.length > 1 && <span>{`BrE: [${word.ukphone}]`}</span>}
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import { isTextSelectableAtom } from '@/store'
|
||||
import { useAtomValue } from 'jotai'
|
||||
|
||||
export type TranslationProps = {
|
||||
trans: string
|
||||
}
|
||||
export default function Translation({ trans }: TranslationProps) {
|
||||
const isTextSelectable = useAtomValue(isTextSelectableAtom)
|
||||
return (
|
||||
<div className="max-w-4xl pb-4 pt-5 font-sans text-lg transition-colors duration-300 dark:text-white dark:text-opacity-80">{trans}</div>
|
||||
<div
|
||||
className={`max-w-4xl pb-4 pt-5 font-sans text-lg transition-colors duration-300 dark:text-white dark:text-opacity-80 ${
|
||||
!isTextSelectable && 'select-none'
|
||||
}`}
|
||||
>
|
||||
{trans}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export type LetterProps = {
|
||||
|
||||
const Letter: React.FC<LetterProps> = ({ letter, state = 'normal', visible = true }) => (
|
||||
<span
|
||||
className={`m-0 select-none p-0 font-mono text-5xl font-normal ${
|
||||
className={`m-0 p-0 font-mono text-5xl font-normal ${
|
||||
stateClassNameMap[(letter === EXPLICIT_SPACE) as unknown as string][state]
|
||||
} pr-0.8 duration-0 dark:text-opacity-80`}
|
||||
>
|
||||
|
||||
@@ -6,7 +6,7 @@ import style from './index.module.css'
|
||||
import { EXPLICIT_SPACE } from '@/constants'
|
||||
import useKeySounds from '@/hooks/useKeySounds'
|
||||
import { TypingContext, TypingStateActionType } from '@/pages/Typing/store'
|
||||
import { isIgnoreCaseAtom, pronunciationIsOpenAtom } from '@/store'
|
||||
import { isIgnoreCaseAtom, isTextSelectableAtom, pronunciationIsOpenAtom } from '@/store'
|
||||
import { useMixPanelWordLogUploader } from '@/utils'
|
||||
import { useSaveWordRecord } from '@/utils/db'
|
||||
import { LetterMistakes } from '@/utils/db/record'
|
||||
@@ -55,6 +55,7 @@ export default function Word({ word, onFinish }: { word: string; onFinish: () =>
|
||||
const { state, dispatch } = useContext(TypingContext)!
|
||||
const [wordState, setWordState] = useImmer<WordState>(structuredClone(initialWordState))
|
||||
|
||||
const isTextSelectable = useAtomValue(isTextSelectableAtom)
|
||||
const isIgnoreCase = useAtomValue(isIgnoreCaseAtom)
|
||||
const saveWordRecord = useSaveWordRecord()
|
||||
const wordLogUploader = useMixPanelWordLogUploader(state)
|
||||
@@ -208,7 +209,9 @@ export default function Word({ word, onFinish }: { word: string; onFinish: () =>
|
||||
<InputHandler updateInput={updateInput} />
|
||||
<div className="flex justify-center pb-1 pt-4">
|
||||
<div className="relative">
|
||||
<div className={`flex items-center justify-center ${wordState.hasWrong ? style.wrong : ''}`}>
|
||||
<div
|
||||
className={`flex items-center ${!isTextSelectable && 'select-none'} justify-center ${wordState.hasWrong ? style.wrong : ''}`}
|
||||
>
|
||||
{wordState.displayWord.split('').map((t, index) => {
|
||||
return (
|
||||
<Letter
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import styles from './index.module.css'
|
||||
import { isIgnoreCaseAtom, randomConfigAtom } from '@/store'
|
||||
import { isIgnoreCaseAtom, isTextSelectableAtom, randomConfigAtom } from '@/store'
|
||||
import { Switch } from '@headlessui/react'
|
||||
import { useAtom } from 'jotai'
|
||||
import { useCallback } from 'react'
|
||||
@@ -7,6 +7,7 @@ import { useCallback } from 'react'
|
||||
export default function AdvancedSetting() {
|
||||
const [randomConfig, setRandomConfig] = useAtom(randomConfigAtom)
|
||||
const [isIgnoreCase, setIsIgnoreCase] = useAtom(isIgnoreCaseAtom)
|
||||
const [isTextSelectable, setIsTextSelectable] = useAtom(isTextSelectableAtom)
|
||||
|
||||
const onToggleRandom = useCallback(
|
||||
(checked: boolean) => {
|
||||
@@ -25,6 +26,13 @@ export default function AdvancedSetting() {
|
||||
[setIsIgnoreCase],
|
||||
)
|
||||
|
||||
const onToggleTextSelectable = useCallback(
|
||||
(checked: boolean) => {
|
||||
setIsTextSelectable(checked)
|
||||
},
|
||||
[setIsTextSelectable],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={styles.tabContent}>
|
||||
<div className={styles.section}>
|
||||
@@ -51,6 +59,18 @@ export default function AdvancedSetting() {
|
||||
}`}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.section}>
|
||||
<span className={styles.sectionLabel}>是否允许选择文本</span>
|
||||
<span className={styles.sectionDescription}>开启后,可以通过鼠标选择文本 </span>
|
||||
<div className={styles.switchBlock}>
|
||||
<Switch checked={isTextSelectable} onChange={onToggleTextSelectable} className="switch-root">
|
||||
<span aria-hidden="true" className="switch-thumb" />
|
||||
</Switch>
|
||||
<span className="text-right text-xs font-normal leading-tight text-gray-600">{`选择文本已${
|
||||
isTextSelectable ? '开启' : '关闭'
|
||||
}`}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ export const isLoopSingleWordAtom = atom(false)
|
||||
|
||||
export const isIgnoreCaseAtom = atomWithStorage('isIgnoreCase', true)
|
||||
|
||||
export const isTextSelectableAtom = atomWithStorage('isTextSelectable', false)
|
||||
|
||||
export const phoneticConfigAtom = atomWithStorage('phoneticConfig', {
|
||||
isOpen: true,
|
||||
type: 'us' as PhoneticType,
|
||||
|
||||
Reference in New Issue
Block a user