Skip to content

Commit

Permalink
feat: undo mastered element
Browse files Browse the repository at this point in the history
  • Loading branch information
cuixiaorui committed Aug 16, 2024
1 parent 4f70eb1 commit 5385777
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 31 deletions.
24 changes: 2 additions & 22 deletions apps/client/components/main/MasteredBtn.vue
Original file line number Diff line number Diff line change
@@ -1,36 +1,16 @@
<template>
<button
class="btn btn-outline btn-sm"
@click="handleMastered"
@click="markStatementAsMastered"
>
掌握
</button>
</template>

<script setup lang="ts">
import { toast } from "vue-sonner";
import { useMastered } from "~/composables/main/useMastered";
import { isAuthenticated } from "~/services/auth";
const { handleMastered } = useMasteredShortcut();
function useMasteredShortcut() {
const { markStatementAsMastered } = useMastered();
function handleMastered() {
if (!isAuthenticated()) {
toast.warning("需要登录哦");
return;
}
markStatementAsMastered();
}
return {
handleMastered,
};
}
const { markStatementAsMastered } = useMastered();
</script>

<style scoped></style>
7 changes: 0 additions & 7 deletions apps/client/components/main/Tips.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@

<script setup lang="ts">
import { computed, onMounted, onUnmounted } from "vue";
import { toast } from "vue-sonner";
import { useAnswerTip } from "~/composables/main/answerTip";
import { useCurrentStatementEnglishSound } from "~/composables/main/englishSound";
import { useGameMode } from "~/composables/main/game";
import { useSummary } from "~/composables/main/summary";
import { useMastered } from "~/composables/main/useMastered";
import { useShortcutKeyMode } from "~/composables/user/shortcutKey";
import { isAuthenticated } from "~/services/auth";
import { cancelShortcut, parseShortcutKeys, registerShortcut } from "~/utils/keyboardShortcuts";
import { useAnswer } from "./QuestionInput/useAnswer";
import { useWrapperQuestionInput } from "./QuestionInput/useWrapperQuestionInput";
Expand Down Expand Up @@ -106,11 +104,6 @@ function useMasteredShortcut() {
const { markStatementAsMastered } = useMastered();
function handleMastered() {
if (!isAuthenticated()) {
toast.warning("需要登录哦");
return;
}
markStatementAsMastered();
}
Expand Down
48 changes: 46 additions & 2 deletions apps/client/composables/main/useMastered.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
import { ref } from "vue";
import { toast } from "vue-sonner";

import { useGameMode } from "~/composables/main/game";
import { useSummary } from "~/composables/main/summary";
import { isAuthenticated } from "~/services/auth";
import { useCourseStore } from "~/store/course";
import { useMasteredElementsStore } from "~/store/masteredElements";
import { cancelShortcut, registerShortcut } from "~/utils/keyboardShortcuts";
import { isWindows } from "~/utils/platform";

const undoShortcut = isWindows() ? "ctrl+z" : "command+z";

export function useMastered() {
let toastId: string | number | undefined;
const courseStore = useCourseStore();
const masteredElements = useMasteredElementsStore();
const { showQuestion } = useGameMode();
const { showSummary } = useSummary();

const addLoading = ref(false);
async function markStatementAsMastered() {
if (!isAuthenticated()) {
toast.warning("需要登录哦");
return;
}

// updateMarketedStatements 会影响 isLastStatement 返回的结果
// 所以我们提前调用 isLastStatement 来记录好值
if (addLoading.value) return;
const isLastStatement = courseStore.isLastStatement();
addLoading.value = true;
await masteredElements.addElement({
const undoMasteredElements = await masteredElements.addElement({
english: courseStore.currentStatement?.english!,
});
addLoading.value = false;

handleMasteredToast(undoMasteredElements);
addLoading.value = false;
courseStore.updateMarketedStatements();

if (isLastStatement) {
Expand All @@ -38,6 +51,37 @@ export function useMastered() {
courseStore.toNextStatement();
showQuestion();
}

function handleMasteredToast(undoMasteredElements: () => void) {
function handleUndo(e: KeyboardEvent) {
e.preventDefault();
e.stopPropagation();
undoMasteredElements();
courseStore.updateMarketedStatements();
cancelShortcut(undoShortcut, handleUndo);
dismissToastIfExists();
}

dismissToastIfExists();
cancelShortcut(undoShortcut);
registerShortcut(undoShortcut, handleUndo);

toastId = toast("成功添加到掌握列表中", {
action: {
label: "撤销",
onClick: () => handleUndo(new KeyboardEvent("keydown")),
},
onAutoClose() {
cancelShortcut(undoShortcut, handleUndo);
},
});
}

function dismissToastIfExists() {
if (toastId !== undefined) {
toast.dismiss(toastId);
}
}
}

return {
Expand Down
6 changes: 6 additions & 0 deletions apps/client/store/masteredElements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ export const useMasteredElementsStore = defineStore("masteredElements", () => {

async function addElement(content: MasteredElementContent) {
const result = await fetchAddMasteredElement(content);
const previousElements = [...masteredElements.value];
masteredElements.value.unshift(result);

return () => {
masteredElements.value = previousElements;
fetchRemoveMasteredElements(result.id).catch(console.error);
};
}

async function removeElement(elementId: string) {
Expand Down

0 comments on commit 5385777

Please sign in to comment.