mirror of
https://github.com/RealKai42/qwerty-learner.git
synced 2026-04-05 14:29:04 +08:00
feat: implement ignore case setting (#386)
This commit is contained in:
@@ -5,7 +5,7 @@ import { LetterState } from './Letter'
|
|||||||
import style from './index.module.css'
|
import style from './index.module.css'
|
||||||
import WordSound from '../WordSound'
|
import WordSound from '../WordSound'
|
||||||
import { useAtomValue } from 'jotai'
|
import { useAtomValue } from 'jotai'
|
||||||
import { pronunciationIsOpenAtom } from '@/store'
|
import { isIgnoreCaseAtom, pronunciationIsOpenAtom } from '@/store'
|
||||||
import { WordStat } from '@/typings'
|
import { WordStat } from '@/typings'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { EXPLICIT_SPACE } from '@/constants'
|
import { EXPLICIT_SPACE } from '@/constants'
|
||||||
@@ -48,6 +48,7 @@ export default function Word({ word, onFinish }: WordProps) {
|
|||||||
const [wordState, setWordState] = useState<WordState>(initialWordState)
|
const [wordState, setWordState] = useState<WordState>(initialWordState)
|
||||||
const wordStat = useRef<WordStat>(initialStatInfo)
|
const wordStat = useRef<WordStat>(initialStatInfo)
|
||||||
const wordVisible = state.isWordVisible
|
const wordVisible = state.isWordVisible
|
||||||
|
const isIgnoreCase = useAtomValue(isIgnoreCaseAtom)
|
||||||
|
|
||||||
const displayWord = useMemo(() => {
|
const displayWord = useMemo(() => {
|
||||||
// run only when word changes
|
// run only when word changes
|
||||||
@@ -100,7 +101,9 @@ export default function Word({ word, onFinish }: WordProps) {
|
|||||||
|
|
||||||
const inputChar = wordState.inputWord[inputLength - 1]
|
const inputChar = wordState.inputWord[inputLength - 1]
|
||||||
const correctChar = displayWord[inputLength - 1]
|
const correctChar = displayWord[inputLength - 1]
|
||||||
if (inputChar === correctChar) {
|
const isEqual = isIgnoreCase ? inputChar.toLowerCase() === correctChar.toLowerCase() : inputChar === correctChar
|
||||||
|
|
||||||
|
if (isEqual) {
|
||||||
if (inputLength >= displayWord.length) {
|
if (inputLength >= displayWord.length) {
|
||||||
const isAllCorrect = wordState.statesList.slice(0, -1).every((t) => t === 'correct')
|
const isAllCorrect = wordState.statesList.slice(0, -1).every((t) => t === 'correct')
|
||||||
if (isAllCorrect) {
|
if (isAllCorrect) {
|
||||||
@@ -133,7 +136,7 @@ export default function Word({ word, onFinish }: WordProps) {
|
|||||||
wordStat.current.countTypo += 1
|
wordStat.current.countTypo += 1
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [wordState.inputWord, displayWord, dispatch])
|
}, [wordState.inputWord, displayWord, dispatch, isIgnoreCase])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (wordState.hasWrong) {
|
if (wordState.hasWrong) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { randomConfigAtom } from '@/store'
|
import { isIgnoreCaseAtom, randomConfigAtom } from '@/store'
|
||||||
import { Switch } from '@headlessui/react'
|
import { Switch } from '@headlessui/react'
|
||||||
import { useAtom } from 'jotai'
|
import { useAtom } from 'jotai'
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
@@ -6,6 +6,7 @@ import styles from './index.module.css'
|
|||||||
|
|
||||||
export default function AdvancedSetting() {
|
export default function AdvancedSetting() {
|
||||||
const [randomConfig, setRandomConfig] = useAtom(randomConfigAtom)
|
const [randomConfig, setRandomConfig] = useAtom(randomConfigAtom)
|
||||||
|
const [isIgnoreCase, setIsIgnoreCase] = useAtom(isIgnoreCaseAtom)
|
||||||
|
|
||||||
const onToggleRandom = useCallback(
|
const onToggleRandom = useCallback(
|
||||||
(checked: boolean) => {
|
(checked: boolean) => {
|
||||||
@@ -17,6 +18,13 @@ export default function AdvancedSetting() {
|
|||||||
[setRandomConfig],
|
[setRandomConfig],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const onToggleIgnoreCase = useCallback(
|
||||||
|
(checked: boolean) => {
|
||||||
|
setIsIgnoreCase(checked)
|
||||||
|
},
|
||||||
|
[setIsIgnoreCase],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.tabContent}>
|
<div className={styles.tabContent}>
|
||||||
<div className={styles.section}>
|
<div className={styles.section}>
|
||||||
@@ -31,6 +39,18 @@ export default function AdvancedSetting() {
|
|||||||
}`}</span>
|
}`}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={styles.section}>
|
||||||
|
<span className={styles.sectionLabel}>是否忽略大小写</span>
|
||||||
|
<span className={styles.sectionDescription}>开启后,输入时不区分大小写,如输入“hello”和“Hello”都会被认为是正确的</span>
|
||||||
|
<div className={styles.switchBlock}>
|
||||||
|
<Switch checked={isIgnoreCase} onChange={onToggleIgnoreCase} className="switch-root">
|
||||||
|
<span aria-hidden="true" className="switch-thumb" />
|
||||||
|
</Switch>
|
||||||
|
<span className="text-right text-xs font-normal leading-tight text-gray-600">{`忽略大小写已${
|
||||||
|
isIgnoreCase ? '开启' : '关闭'
|
||||||
|
}`}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ export const randomConfigAtom = atomWithStorage('randomConfig', {
|
|||||||
|
|
||||||
export const isLoopSingleWordAtom = atom(false)
|
export const isLoopSingleWordAtom = atom(false)
|
||||||
|
|
||||||
|
export const isIgnoreCaseAtom = atomWithStorage('isIgnoreCase', true)
|
||||||
|
|
||||||
export const phoneticConfigAtom = atomWithStorage('phoneticConfig', {
|
export const phoneticConfigAtom = atomWithStorage('phoneticConfig', {
|
||||||
isOpen: true,
|
isOpen: true,
|
||||||
type: 'us' as PhoneticType,
|
type: 'us' as PhoneticType,
|
||||||
|
|||||||
Reference in New Issue
Block a user