Update Saqel Platform: 2026-09-02 00:55:56

This commit is contained in:
Hamza-Ayed
2026-09-02 00:55:56 +03:00
parent 1c0cd88a98
commit f4ab43d49a
18 changed files with 409 additions and 214 deletions
@@ -87,50 +87,8 @@ class VideoPlaybackCubit extends Cubit<VideoPlaybackState> {
isPlaying: true,
));
} catch (e) {
AppLogger.log('Playback API notice for ${lesson.title}: $e (Generating dynamic Socratic session)', tag: 'VIDEO_CUBIT');
// Create dynamic fallback Socratic session with lesson checkpoints
final fallbackPlayback = LessonPlaybackData(
lessonId: 1,
title: lesson.title,
durationSeconds: lesson.durationSeconds > 0 ? lesson.durationSeconds : 600,
videoUrl: 'https://saqel.intaleqapp.com/api/videos/stream/demo-vector-lesson',
availableVersions: const [
LessonVersionModel(
lessonId: 1,
isAi: true,
teacherName: 'المعلم الافتراضي بالذكاء الاصطناعي',
schoolName: 'وزارة التربية والتعليم',
label: 'شرح المنهاج المعتمد 🤖',
isRecommended: true,
videoUrl: '',
),
],
checkpoints: [
SocraticCheckpointModel(
id: 1,
questionText: lesson.outcomes.isNotEmpty
? 'وفقاً لنتاجات هذا الدرس (${lesson.outcomes.first}): ما هو المفهوم الجوهري الواجب إتقانه هنا؟'
: 'ما هو المبدأ الأساسي المشروح في هذا المبحث؟',
timestampSeconds: 15,
rewindSecondsOnFail: 20,
hint: 'راجع نتاجات التعلم الموضحة أسفل الفيديو بدقة.',
pedagogicalExplanation: 'الإتقان السقراطي يتطلب الفهم المفاهيمي العميق قبل الانتقال للمسائل الحسابية.',
options: const [
SocraticOptionModel(id: 1, text: 'الفهم المنهجي والتطبيق المباشر للقواعد', isCorrect: true),
SocraticOptionModel(id: 2, text: 'الحفظ المجرد دون فهم', isCorrect: false),
SocraticOptionModel(id: 3, text: 'تخطي المفهوم', isCorrect: false),
],
),
],
);
emit(VideoPlaybackReady(
playbackData: fallbackPlayback,
lessonItem: lesson,
subject: subject,
currentPositionSeconds: 0,
isPlaying: true,
));
AppLogger.log('Playback API failed for ${lesson.title}: $e', tag: 'VIDEO_CUBIT');
emit(VideoPlaybackError('لا يوجد فيديو منشور لهذا الدرس حاليًا. يرجى المحاولة لاحقًا.'));
}
}
@@ -170,6 +128,20 @@ class VideoPlaybackCubit extends Cubit<VideoPlaybackState> {
}
}
Future<void> saveProgress({required int positionSeconds, required int watchedSeconds}) async {
final currentState = state;
if (currentState is! VideoPlaybackReady || currentState.playbackData.lessonId <= 0) return;
try {
await _repo.saveProgress(
lessonId: currentState.playbackData.lessonId,
positionSeconds: positionSeconds,
watchedSeconds: watchedSeconds,
);
} catch (e) {
AppLogger.log('Progress sync deferred: $e', tag: 'VIDEO_CUBIT');
}
}
/// Submit Socratic Checkpoint Answer
bool submitCheckpointAnswer(SocraticOptionModel selectedOption) {
final currentState = state;
@@ -187,6 +159,11 @@ class VideoPlaybackCubit extends Cubit<VideoPlaybackState> {
passedCheckpointIds: updatedPassed,
remediationNotice: 'إجابة نموذجية ممتازة! تم تعزيز مؤشر الجاهزية (+0.5%) 🚀',
));
if (cp.id > 0) {
_repo.submitCheckpoint(examId: cp.id, questionId: cp.questionId, optionId: selectedOption.id).catchError((e) {
AppLogger.log('Checkpoint sync deferred: $e', tag: 'VIDEO_CUBIT');
});
}
return true;
} else {
// Wrong Answer -> Socratic Productive Struggle: Rewind video by N seconds
@@ -198,6 +175,11 @@ class VideoPlaybackCubit extends Cubit<VideoPlaybackState> {
isPlaying: true,
remediationNotice: 'تعثرت في هذا المفهوم. تم إرجاع الفيديو ${cp.rewindSecondsOnFail} ثانية لإعادة الاستماع بتركيز 🔄',
));
if (cp.id > 0 && cp.questionId > 0) {
_repo.submitCheckpoint(examId: cp.id, questionId: cp.questionId, optionId: selectedOption.id).catchError((e) {
AppLogger.log('Checkpoint sync deferred: $e', tag: 'VIDEO_CUBIT');
});
}
return false;
}
}