// ═══════════════════════════════════════════════════════════ // session-manager.js // إدارة الجلسة: قاعدة 5 دقائق + حالات الجلسة + نبضة النشاط // ═══════════════════════════════════════════════════════════ (function(){ 'use strict'; var CFG = window.WaziriConfig; var currentSessionId = null; var activityTimer = null; var lastTouchTime = 0; var pendingReason = null; // ═══ استعد ID الجلسة المحفوظ ═══ try { currentSessionId = localStorage.getItem(CFG.KEY_SUPABASE_SESSION_ID) || null; } catch(e) {} // ═══ حفظ جلسة جديدة ═══ function save(code, isCreator, mode) { try { localStorage.setItem(CFG.KEY_SESSION, JSON.stringify({ code: code, isCreator: !!isCreator, mode: mode || 'internet', time: Date.now() })); } catch (e) {} } // ═══ جلب الجلسة (فقط إن كانت < 5 دقائق) ═══ function get() { try { var s = JSON.parse(localStorage.getItem(CFG.KEY_SESSION) || 'null'); if (!s || !s.code) return null; if (Date.now() - (s.time || 0) > 5 * 60 * 1000) { localStorage.removeItem(CFG.KEY_SESSION); return null; } return s; } catch (e) { return null; } } function getRaw() { try { return JSON.parse(localStorage.getItem(CFG.KEY_SESSION) || 'null'); } catch (e) { return null; } } // ═══ تحديث وقت النشاط المحلي + إرسال لـ Supabase (كل 30 ثانية) ═══ function touch() { try { var s = JSON.parse(localStorage.getItem(CFG.KEY_SESSION) || 'null'); if (s && s.code) { s.time = Date.now(); localStorage.setItem(CFG.KEY_SESSION, JSON.stringify(s)); } } catch (e) {} var now = Date.now(); if (now - lastTouchTime > 30000 && currentSessionId && window.WaziriStats) { lastTouchTime = now; window.WaziriStats.touchSession(currentSessionId); } } // ═══ بدء نبضة النشاط الدورية (كل 30 ثانية أثناء الجلسة) ═══ function startActivityPulse() { stopActivityPulse(); activityTimer = setInterval(function(){ if (currentSessionId && window.WaziriStats) { window.WaziriStats.touchSession(currentSessionId); } }, 30000); } function stopActivityPulse() { if (activityTimer) { clearInterval(activityTimer); activityTimer = null; } } // ═══ مسح الجلسة ═══ // reason: 'completed' | 'cancelled' | 'abandoned' | 'connectio function clear(reason, opts) { opts = opts || {}; var finalReason = pendingReason || reason || 'completed'; pendingReason = null; stopActivityPulse(); try { if (window.WaziriStats && currentSessionId) { window.WaziriStats.recordSessionEnd(currentSessionId, { endReason: finalReason, durationSeconds: opts.durationSeconds || 0, filesSentCount: opts.filesSentCount || 0, filesSentBytes: opts.filesSentBytes || 0, filesRecvCount: opts.filesRecvCount || 0, filesRecvBytes: opts.filesRecvBytes || 0 }); } currentSessionId = null; try { localStorage.removeItem(CFG.KEY_SUPABASE_SESSION_ID); } catch(e) {} localStorage.removeItem(CFG.KEY_SESSION); } catch (e) {} } // ═══ تعيين ID الجلسة ═══ function setSupabaseId(id) { currentSessionId = id; try { if (id) { localStorage.setItem(CFG.KEY_SUPABASE_SESSION_ID, id); startActivityPulse(); } else { localStorage.removeItem(CFG.KEY_SUPABASE_SESSION_ID); stopActivityPulse(); } } catch(e) {} } // ═══ زر إنهاء الجلسة (ناجح) ═══ function endWithConfirm(onConfirm) { var msg = '✅ إنهاء الجلسة بشكل طبيعي\n\n' + 'سيتم:\n' + '• قطع الاتصال الحالي\n' + '• تسجيل الجلسة كـ«منتهية بنجاح»\n' + '• عدم ظهورها في «آخر جلسة»\n\n' + 'هل أنت متأكد؟'; if (confirm(msg)) { pendingReason = 'completed'; if (typeof onConfirm === 'function') { try { onConfirm(); } catch(e) {} } return true; } return false; } // ═══ زر إلغاء الجلسة ═══ function cancelWithConfirm(onConfirm) { var msg = '❌ إلغاء الجلسة\n\n' + 'سيتم:\n' + '• قطع الاتصال فورًا\n' + '• تسجيل الجلسة كـ«ملغاة»\n' + '• عدم إمكانية العودة إليها\n\n' + 'هل أنت متأكد؟'; if (confirm(msg)) { pendingReason = 'cancelled'; if (typeof onConfirm === 'function') { try { onConfirm(); } catch(e) {} } return true; } return false; } // ═══ الواجهة العامة ═══ window.WaziriSession = { save: save, get: get, getRaw: getRaw, touch: touch, clear: clear, setSupabaseId: setSupabaseId, endWithConfirm: endWithConfirm, cancelWithConfirm: cancelWithConfirm, startActivityPulse: startActivityPulse, stopActivityPulse: stopActivityPulse, hasActive: function(){ return currentSessionId !== null; }, getCurrentId: function(){ return currentSessionId; } }; })();