Custom drawing implementation

This commit is contained in:
2026-02-05 17:47:03 +01:00
parent e1d72de718
commit d4d6e41a9d
14 changed files with 1291 additions and 147 deletions

View File

@@ -9,12 +9,14 @@ enum SecureStorageKey { url, jwt, email }
/// Service for managing local storage operations.
///
/// Uses [FlutterSecureStorage] for sensitive data (credentials, tokens)
/// and [Hive] for general app data (config, sheet access times, change queue).
/// and [Hive] for general app data (config, sheet access times, change queue,
/// and PDF annotations).
class StorageService {
// Hive box names
static const String _sheetAccessTimesBox = 'sheetAccessTimes';
static const String _configBox = 'config';
static const String _changeQueueBox = 'changeQueue';
static const String _annotationsBox = 'annotations';
late final FlutterSecureStorage _secureStorage;
@@ -75,8 +77,9 @@ class StorageService {
Future<Map<String, DateTime>> readSheetAccessTimes() async {
final box = await Hive.openBox(_sheetAccessTimesBox);
return box.toMap().map(
(key, value) => MapEntry(key as String, DateTime.parse(value as String)),
);
(key, value) =>
MapEntry(key as String, DateTime.parse(value as String)),
);
}
/// Records when a sheet was last accessed.
@@ -116,4 +119,75 @@ class StorageService {
await box.deleteAt(0);
}
}
// ---------------------------------------------------------------------------
// Annotations (PDF Drawing Persistence)
// ---------------------------------------------------------------------------
/// Generates a storage key for a specific page's annotations.
String _annotationKey(String sheetUuid, int pageNumber) {
return '${sheetUuid}_page_$pageNumber';
}
/// Reads annotations for a specific sheet page.
///
/// Returns the JSON string of annotations, or null if none exist.
Future<String?> readAnnotations(String sheetUuid, int pageNumber) async {
final box = await Hive.openBox(_annotationsBox);
return box.get(_annotationKey(sheetUuid, pageNumber));
}
/// Writes annotations for a specific sheet page.
///
/// Pass null or empty string to delete annotations for that page.
Future<void> writeAnnotations(
String sheetUuid,
int pageNumber,
String? annotationsJson,
) async {
final box = await Hive.openBox(_annotationsBox);
final key = _annotationKey(sheetUuid, pageNumber);
if (annotationsJson == null || annotationsJson.isEmpty) {
await box.delete(key);
} else {
await box.put(key, annotationsJson);
}
}
/// Reads all annotations for a sheet (all pages).
///
/// Returns a map of page number to JSON string.
Future<Map<int, String>> readAllAnnotations(String sheetUuid) async {
final box = await Hive.openBox(_annotationsBox);
final prefix = '${sheetUuid}_page_';
final result = <int, String>{};
for (final key in box.keys) {
if (key is String && key.startsWith(prefix)) {
final pageStr = key.substring(prefix.length);
final pageNumber = int.tryParse(pageStr);
if (pageNumber != null) {
final value = box.get(key);
if (value != null && value is String && value.isNotEmpty) {
result[pageNumber] = value;
}
}
}
}
return result;
}
/// Deletes all annotations for a sheet.
Future<void> deleteAllAnnotations(String sheetUuid) async {
final box = await Hive.openBox(_annotationsBox);
final prefix = '${sheetUuid}_page_';
final keysToDelete =
box.keys.where((key) => key is String && key.startsWith(prefix));
for (final key in keysToDelete.toList()) {
await box.delete(key);
}
}
}