Update Saqel Platform: 2026-09-04 21:26:55
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/**
|
||||
* ==============================================================================
|
||||
* SAQEL EDTECH 2.0 - LOCAL DOCUMENT & TEXTBOOK STORAGE SERVICE
|
||||
* ==============================================================================
|
||||
*
|
||||
* خدمة التخزين المحلي للكتب والمذكرات وأوراق العمل:
|
||||
* - حفظ محتوى الكتاب/المذكرة كاملاً في ذاكرة الجهاز (Offline Local Storage).
|
||||
* - تمكين الطالب من تصفح الكتب وقراءتها في أي وقت دون اتصال بالإنترنت (Zero Network Dependency).
|
||||
* - إدارة قائمة المستندات المحفوظة وحجمها وإمكانية حذفها أو تحديثها.
|
||||
*/
|
||||
class LocalDocumentStorageService {
|
||||
static const String _prefix = 'saqel_doc_cache_';
|
||||
static const String _savedListKey = 'saqel_saved_documents_list';
|
||||
|
||||
static String _buildKey(String subjectId, String type, String filePath) {
|
||||
final cleanPath = filePath.replaceAll(RegExp(r'[^a-zA-Z0-9_]'), '_');
|
||||
return '$_prefix${subjectId}_${type}_$cleanPath';
|
||||
}
|
||||
|
||||
/// Check if a document is already saved on the device
|
||||
static Future<bool> isDocumentSaved({
|
||||
required String subjectId,
|
||||
required String type,
|
||||
required String filePath,
|
||||
}) async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final key = _buildKey(subjectId, type, filePath);
|
||||
return prefs.containsKey(key);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve locally stored document markdown content
|
||||
static Future<String?> getSavedDocument({
|
||||
required String subjectId,
|
||||
required String type,
|
||||
required String filePath,
|
||||
}) async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final key = _buildKey(subjectId, type, filePath);
|
||||
return prefs.getString(key);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Save document markdown content locally on the device
|
||||
static Future<bool> saveDocumentLocally({
|
||||
required String subjectId,
|
||||
required String type,
|
||||
required String filePath,
|
||||
required String title,
|
||||
required String content,
|
||||
}) async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final key = _buildKey(subjectId, type, filePath);
|
||||
|
||||
// Save document body
|
||||
await prefs.setString(key, content);
|
||||
|
||||
// Register in saved documents catalog
|
||||
final savedList = prefs.getStringList(_savedListKey) ?? [];
|
||||
final record = '$subjectId|$type|$filePath|$title|${DateTime.now().toIso8601String()}';
|
||||
|
||||
savedList.removeWhere((item) => item.startsWith('$subjectId|$type|$filePath|'));
|
||||
savedList.add(record);
|
||||
await prefs.setStringList(_savedListKey, savedList);
|
||||
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete locally saved document to free up space
|
||||
static Future<bool> removeSavedDocument({
|
||||
required String subjectId,
|
||||
required String type,
|
||||
required String filePath,
|
||||
}) async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final key = _buildKey(subjectId, type, filePath);
|
||||
await prefs.remove(key);
|
||||
|
||||
final savedList = prefs.getStringList(_savedListKey) ?? [];
|
||||
savedList.removeWhere((item) => item.startsWith('$subjectId|$type|$filePath|'));
|
||||
await prefs.setStringList(_savedListKey, savedList);
|
||||
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get list of all locally saved offline documents on this device
|
||||
static Future<List<Map<String, String>>> getAllSavedDocuments() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final savedList = prefs.getStringList(_savedListKey) ?? [];
|
||||
final List<Map<String, String>> docs = [];
|
||||
|
||||
for (var record in savedList) {
|
||||
final parts = record.split('|');
|
||||
if (parts.length >= 4) {
|
||||
docs.add({
|
||||
'subject_id': parts[0],
|
||||
'type': parts[1],
|
||||
'file_path': parts[2],
|
||||
'title': parts[3],
|
||||
'saved_at': parts.length > 4 ? parts[4] : '',
|
||||
});
|
||||
}
|
||||
}
|
||||
return docs;
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user