Update Saqel Platform: 2026-09-02 08:59:54
This commit is contained in:
@@ -31,6 +31,7 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
late AnimationController _watermarkController;
|
||||
VideoPlayerController? _videoController;
|
||||
bool _isVideoInitialized = false;
|
||||
int _lastSyncedPosition = -1;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -43,14 +44,21 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
duration: const Duration(seconds: 18),
|
||||
)..repeat(reverse: true);
|
||||
|
||||
// Read the real player clock and periodically persist progress.
|
||||
// Keep the UI clock responsive, but sync progress to the API every 15s.
|
||||
_playbackTicker = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
final cubit = context.read<VideoPlaybackCubit>();
|
||||
final state = cubit.state;
|
||||
if (state is VideoPlaybackReady && _videoController?.value.isInitialized == true) {
|
||||
final position = _videoController!.value.position.inSeconds;
|
||||
if (state.activeCheckpoint == null) cubit.updatePosition(position);
|
||||
cubit.saveProgress(positionSeconds: position, watchedSeconds: position);
|
||||
final duration = _videoController!.value.duration.inSeconds;
|
||||
final shouldSync = _lastSyncedPosition < 0 ||
|
||||
position - _lastSyncedPosition >= 15 ||
|
||||
(duration > 0 && position >= duration - 1);
|
||||
if (shouldSync && position != _lastSyncedPosition) {
|
||||
_lastSyncedPosition = position;
|
||||
cubit.saveProgress(positionSeconds: position, watchedSeconds: position);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -104,7 +112,7 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
Icon(CupertinoIcons.shield_lefthalf_fill, color: AppColors.saqelCyan, size: 14),
|
||||
SizedBox(width: 6),
|
||||
Text(
|
||||
'حماية جنائية DRM',
|
||||
'محتوى محمي',
|
||||
style: TextStyle(color: AppColors.saqelCyan, fontSize: 11, fontWeight: FontWeight.w700),
|
||||
),
|
||||
],
|
||||
@@ -150,7 +158,7 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
onOptionSelected: (opt) {
|
||||
final isCorrect = context.read<VideoPlaybackCubit>().submitCheckpointAnswer(opt);
|
||||
if (isCorrect) {
|
||||
SaqelToast.showSuccess(context, 'إجابة نموذجية! تم تعزيز الجاهزية (+0.5%)', title: 'فحص الفهم السقراطي ✨');
|
||||
SaqelToast.showSuccess(context, 'إجابة صحيحة، تم تسجيل تقدمك.', title: 'نقاط الفهم ✨');
|
||||
} else {
|
||||
SaqelToast.showError(context, 'تم إرجاع الفيديو لإعادة الاستماع للنقطة الجوهرية 🔄', title: 'سد الثغرة العلاجية');
|
||||
}
|
||||
@@ -321,7 +329,7 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
state.isPlaying ? 'جاري البث والشرح التفاعلي ⚡' : 'الشرح متوقف مؤقتاً',
|
||||
state.isPlaying ? 'جاري الشرح التفاعلي ⚡' : 'الفيديو متوقف مؤقتاً',
|
||||
style: const TextStyle(
|
||||
color: AppColors.textSecondaryDark,
|
||||
fontSize: 12,
|
||||
@@ -350,7 +358,7 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
Icon(CupertinoIcons.sparkles, color: AppColors.saqelCyan, size: 12),
|
||||
SizedBox(width: 6),
|
||||
Text(
|
||||
'الشرح السقراطي المعزز 🤖',
|
||||
'نقاط الفهم',
|
||||
style: TextStyle(color: AppColors.saqelCyan, fontSize: 11, fontWeight: FontWeight.w700),
|
||||
),
|
||||
],
|
||||
@@ -404,7 +412,7 @@ class _SocraticVideoPlayerScreenState extends State<SocraticVideoPlayerScreen> w
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Socratic Timeline Progress Bar with Checkpoint Markers
|
||||
// Understanding checkpoints on the timeline
|
||||
Stack(
|
||||
alignment: Alignment.centerLeft,
|
||||
children: [
|
||||
|
||||
Reference in New Issue
Block a user