feat: Implement Dual Video Pipeline (Direct Server API Upload & Bunny.net Stream Cloud CDN + DRM) with Socratic interactive player

This commit is contained in:
Hamza-Ayed
2026-08-27 19:18:51 +03:00
parent 70176deb3b
commit 8044f86798
5 changed files with 1054 additions and 25 deletions
+80 -1
View File
@@ -859,7 +859,8 @@ class StudentPortal
video.addEventListener('timeupdate', () => {
const cur = Math.floor(video.currentTime);
const dur = Math.floor(video.duration || 596);
document.getElementById('video_time_display').textContent = `${formatTime(cur)} / ${formatTime(dur)}`;
const timeEl = document.getElementById('video_time_display');
if (timeEl) timeEl.textContent = `${formatTime(cur)} / ${formatTime(dur)}`;
// Trigger checkpoint at second 15 automatically once
if (cur === 15 && !checkpointTriggered) {
@@ -877,6 +878,84 @@ class StudentPortal
return `${m}:${s}`;
}
function triggerCheckpointDemo() {
const video = document.getElementById('lesson_video_player');
if (video) {
video.currentTime = 14;
video.play();
checkpointTriggered = false;
}
}
function handleCheckpointAnswer(btn, isCorrect) {
const feedback = document.getElementById('checkpoint_feedback');
const video = document.getElementById('lesson_video_player');
const btns = document.querySelectorAll('#socratic_quiz_modal .quiz-option-btn');
if (isCorrect) {
btn.style.background = 'rgba(16, 185, 129, 0.25)';
btn.style.borderColor = '#10B981';
feedback.style.color = '#34D399';
feedback.style.display = 'block';
feedback.innerHTML = '✓ إجابة ممتازة وصحيحة 100%! سيتم استئناف الشرح فوراً...';
playChimeNotification();
setTimeout(() => {
document.getElementById('socratic_quiz_modal').style.display = 'none';
feedback.style.display = 'none';
btns.forEach(b => {
b.style.background = '';
b.style.borderColor = '';
});
if (video) video.play();
}, 1500);
} else {
btn.style.background = 'rgba(239, 68, 68, 0.25)';
btn.style.borderColor = '#EF4444';
feedback.style.color = '#F87171';
feedback.style.display = 'block';
feedback.innerHTML = '⚠️ إجابة غير دقيقة. سيتم إرجاعك 45 ثانية لمراجعة الفكرة وتثبيت الفهم!';
setTimeout(() => {
document.getElementById('socratic_quiz_modal').style.display = 'none';
feedback.style.display = 'none';
btns.forEach(b => {
b.style.background = '';
b.style.borderColor = '';
});
if (video) {
video.currentTime = Math.max(0, video.currentTime - 45);
video.play();
checkpointTriggered = false;
}
}, 2200);
}
}
async function loadStudentLessonPlayback(lessonId = 1) {
const token = localStorage.getItem('saqel_student_jwt');
if (!token) return;
try {
const res = await fetch(`/api/lessons/${lessonId}/playback`, {
headers: { 'Authorization': 'Bearer ' + token }
});
const data = await res.json();
if (res.ok && data.status === 'success' && data.data?.playback) {
const pb = data.data.playback;
const video = document.getElementById('lesson_video_player');
if (video) {
if (pb.storage_type === 'api_upload' && pb.stream_url) {
video.src = pb.stream_url;
} else if (pb.hls_url) {
video.src = pb.hls_url;
}
}
}
} catch (e) {
console.error('Load lesson playback notice:', e);
}
}
let wsPingInterval = null;
// 1. Initialize Real-time WebSocket (Workerman)