Skip to content

Commit

Permalink
Merge branch 'main' into unit-test/summary
Browse files Browse the repository at this point in the history
  • Loading branch information
Nauxscript committed Feb 26, 2024
2 parents 922d6b8 + 318a165 commit 42def0f
Show file tree
Hide file tree
Showing 7 changed files with 636 additions and 65 deletions.
2 changes: 1 addition & 1 deletion apps/client/components/main/Game.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</template>

<script setup lang="ts">
import Question from "./Question.vue";
import Question from './Question.vue';
import Answer from "./Answer.vue";
import Summary from "./Summary.vue";
import Tips from "./Tips.vue";
Expand Down
124 changes: 64 additions & 60 deletions apps/client/components/main/Question.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,28 @@
<div
class="h-[4.8rem] border-solid rounded-[2px] border-b-2 text-[3.2em] transition-all"
:class="[
i === activeInputIndex && focusing
? 'text-fuchsia-500 border-b-fuchsia-500'
: 'text-[#20202099] border-b-gray-300 dark:text-gray-300 dark:border-b-gray-400',
userInputWords[i]['incorrect']
? 'text-red-500 border-b-red-500'
: userInputWords[i]?.['isActive'] && focusing
? 'text-fuchsia-500 border-b-fuchsia-500'
: 'text-[#20202099] border-b-gray-300 dark:text-gray-300 dark:border-b-gray-400',
]"
:style="{ width: `${w.length}ch` }"
>
{{ userInputWords[i] }}
{{ userInputWords[i]["userInput"] }}
</div>
</template>
<input ref="inputEl" class="absolute h-full w-full opacity-0" type="text" v-model="inputValue" @keyup="handleKeyup"
@keydown="handleKeydown" @focus="handleInputFocus" @blur="handleBlur" autoFocus />
<input
ref="inputEl"
class="absolute h-full w-full opacity-0"
type="text"
v-model="inputValue"
@keyup="handleKeyup"
@keydown="handleKeydown"
@focus="handleInputFocus"
@blur="handleBlur"
autoFocus
/>
</div>
<div class="mt-12 text-xl dark:text-gray-50">
{{
Expand All @@ -28,77 +39,71 @@
<script setup lang="ts">
import { useCourseStore } from "~/store/course";
import { useGameMode } from "~/composables/main/game";
import { ref, computed, onMounted } from "vue";
import { ref, onMounted, watch } from "vue";
import { useInput } from "~/composables/main/question";
const courseStore = useCourseStore();
const { userInputWords, activeInputIndex, inputValue } = useInput();
const { handleKeyup, handleKeydown } = registerShortcutKeyForInputEl();
const { inputEl, focusing, handleInputFocus, handleBlur } = useFocus();
const inputEl = ref<HTMLInputElement>();
const { setInputCursorPosition, getInputCursorPosition } = useCursor();
const { focusing, handleInputFocus, handleBlur } = useFocus();
const { showAnswer } = useGameMode();
function useInput() {
const inputValue = ref("");
const {
inputValue,
userInputWords,
preventInput,
submitAnswer,
setInputValue,
fixIncorrectWord,
fixFirstIncorrectWord,
} = useInput({
source: () => courseStore.currentStatement?.english!,
setInputCursorPosition,
getInputCursorPosition,
});
const userInputWords = computed(() => {
return inputValue.value.trimStart().split(" ");
});
const activeInputIndex = computed(() => {
return Math.min(userInputWords.value.length - 1, courseStore.words.length - 1);
});
watch(
() => inputValue.value,
(val) => {
setInputValue(val);
}
);
return {
inputValue,
userInputWords,
activeInputIndex,
};
function handleKeyup(e: KeyboardEvent) {
if (e.code === "Enter") {
e.stopPropagation();
submitAnswer(() => {
showAnswer();
});
} else if (e.code === "Backspace") {
fixFirstIncorrectWord();
} else if (e.code === "Space") {
fixIncorrectWord();
}
}
function registerShortcutKeyForInputEl() {
const { showAnswer } = useGameMode();
function handleKeyup(e: KeyboardEvent) {
if (e.code === "Enter") {
e.stopPropagation();
function handleKeydown(e: KeyboardEvent) {
preventInput(e);
}
if (courseStore.checkCorrect(inputValue.value.trim())) {
showAnswer();
}
inputValue.value = "";
}
function useCursor() {
function setInputCursorPosition(position: number) {
inputEl.value?.setSelectionRange(position, position);
}
function handleKeydown(e: KeyboardEvent) {
const inputLastStr = inputValue.value[inputValue.value.length - 1];
if (e.code === "Space" && inputLastStr === " ") {
// prevent input multiple spaces
e.preventDefault();
}
if (
e.code === "Backspace" &&
userInputWords.value.length - courseStore.words.length === 1 &&
inputLastStr === " "
) {
// remove the last space and the last letter
e.preventDefault();
inputValue.value = inputValue.value.slice(0, -2);
}
// 新增逻辑:阻止在最后一个单词后添加空格
const words = inputValue.value.trim().split(" ");
const isLastWord = words.length === courseStore.wordCount;
if (e.code === "Space" && isLastWord) {
e.preventDefault();
}
function getInputCursorPosition() {
return inputEl.value?.selectionStart || 0;
}
return {
handleKeyup,
handleKeydown,
setInputCursorPosition,
getInputCursorPosition,
};
}
function useFocus() {
const focusing = ref(true);
const inputEl = ref<HTMLInputElement>();
onMounted(() => {
inputEl.value?.focus();
});
Expand All @@ -112,7 +117,6 @@ function useFocus() {
}
return {
inputEl,
focusing,
handleInputFocus,
handleBlur,
Expand Down
9 changes: 8 additions & 1 deletion apps/client/components/main/Tips.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@
</button>
<span class="ml-2">play sound</span>
</div>
<div class="w-[210px]">
<div class="w-[210px] mb-4">
<button class="tip-btn" @click="toggleGameMode">
⌃ {{ shortcutKeys.answer }}
</button>
<span class="ml-2">{{ toggleTipText }}</span>
</div>

<div class="w-[210px]">
<button class="tip-btn" @click="toggleGameMode">
Space
</button>
<span class="ml-2">fix incorrect word</span>
</div>
</div>
</template>

Expand Down
Loading

0 comments on commit 42def0f

Please sign in to comment.