enhance lesson generation and focus mode functionality
This commit is contained in:
parent
507bc15dcc
commit
5a4caaf1d0
2 changed files with 47 additions and 6 deletions
|
|
@ -529,6 +529,7 @@ const focusMode = ref(false);
|
|||
const currentChunk = ref<{ text: string; start: number; end: number } | null>(null);
|
||||
const karaokeAudioEl = ref<HTMLAudioElement | null>(null);
|
||||
const questionPlaying = ref(false);
|
||||
const focusEverActivated = ref(false);
|
||||
|
||||
if (import.meta.client) {
|
||||
const stored = localStorage.getItem("revisione-focus-mode");
|
||||
|
|
@ -543,8 +544,10 @@ const hasAudio = computed(() => {
|
|||
const showKaraoke = computed(() => {
|
||||
if (!focusMode.value) return false;
|
||||
const ds = displayStep.value;
|
||||
return (lessonState.mode === "main" || lessonState.mode === "branch") &&
|
||||
(ds?.type === "concept" || ds?.type === "example");
|
||||
if (!((lessonState.mode === "main" || lessonState.mode === "branch") &&
|
||||
(ds?.type === "concept" || ds?.type === "example"))) return false;
|
||||
// dont show overlay if this step has no audio — avoids perma-"..." with missing TTS
|
||||
return !!(ds?.audioPath && ds?.audioChunks && (ds.audioChunks as any[]).length > 0);
|
||||
});
|
||||
|
||||
const showQuestionOverlay = computed(() =>
|
||||
|
|
@ -554,10 +557,24 @@ const showQuestionOverlay = computed(() =>
|
|||
questionPlaying.value
|
||||
);
|
||||
|
||||
function toggleFocusMode() {
|
||||
async function toggleFocusMode() {
|
||||
focusMode.value = !focusMode.value;
|
||||
if (import.meta.client) localStorage.setItem("revisione-focus-mode", String(focusMode.value));
|
||||
|
||||
if (focusMode.value) {
|
||||
// on first activation, re-fetch lesson so we have the latest audio paths from the DB
|
||||
if (!focusEverActivated.value) {
|
||||
focusEverActivated.value = true;
|
||||
try {
|
||||
const fresh = await $fetch<any>(`/api/topics/${topicId}/lesson`);
|
||||
lesson.value = fresh;
|
||||
const s0 = fresh?.content?.steps?.[0];
|
||||
console.log("[focus] step 0 audioPath:", s0?.audioPath, "| chunks:", s0?.audioChunks?.length ?? "none");
|
||||
} catch (e) {
|
||||
console.warn("[focus] re-fetch failed, using cached lesson data", e);
|
||||
}
|
||||
}
|
||||
|
||||
nextTick(() => startStepAudio());
|
||||
} else {
|
||||
stopAllAudio();
|
||||
|
|
@ -686,7 +703,16 @@ function startStepAudio() {
|
|||
if (!s) return;
|
||||
|
||||
if (s.type === "concept" || s.type === "example" || s.type === "summary") {
|
||||
if (!s.audioPath || !s.audioChunks) return;
|
||||
if (!s.audioPath || !s.audioChunks || (s.audioChunks as any[]).length === 0) {
|
||||
// no usable audio for this step — skip it automatically so focus mode stays alive
|
||||
if (!isLastMainStep.value) {
|
||||
lessonState.stepIndex++;
|
||||
nextTick(() => startStepAudio());
|
||||
} else {
|
||||
completeLesson();
|
||||
}
|
||||
return;
|
||||
}
|
||||
const audio = karaokeAudioEl.value;
|
||||
if (!audio) return;
|
||||
audio.src = s.audioPath;
|
||||
|
|
@ -705,7 +731,10 @@ function startStepAudio() {
|
|||
}
|
||||
} else if (lessonState.mode === "branch") {
|
||||
const bs = currentBranchStep.value;
|
||||
if (!bs?.audioPath || !bs.audioChunks) return;
|
||||
if (!bs?.audioPath || !bs.audioChunks || (bs.audioChunks as any[]).length === 0) {
|
||||
advanceBranchStep();
|
||||
return;
|
||||
}
|
||||
const audio = karaokeAudioEl.value;
|
||||
if (!audio) return;
|
||||
audio.src = bs.audioPath;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { db } from "../../../db/index";
|
||||
import { topics, lessons } from "../../../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { generateLesson } from "../../../utils/generateLesson";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
|
|
@ -19,6 +19,18 @@ export default defineEventHandler(async (event) => {
|
|||
|
||||
try {
|
||||
await generateLesson(id);
|
||||
|
||||
// pre-generate the next topic silently
|
||||
const currentTopic = await db.query.topics.findFirst({ where: eq(topics.id, id) });
|
||||
const nextTopic = await db.query.topics.findFirst({
|
||||
where: and(
|
||||
eq(topics.courseId, currentTopic!.courseId),
|
||||
eq(topics.order, currentTopic!.order + 1),
|
||||
eq(topics.status, "pending")
|
||||
)
|
||||
});
|
||||
if (nextTopic) generateLesson(nextTopic.id);
|
||||
|
||||
return { status: "ready" };
|
||||
} catch (err: any) {
|
||||
console.error(`[generate.post] topic ${id} failed: ${err?.message ?? err}`);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue