From f7bb9d5974638aa446fed7252c02225fdf599c48 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 23 May 2025 16:31:28 +0530 Subject: [PATCH] Remove db to track download tasks --- mobile/lib/module/download/db.dart | 64 ------------------------- mobile/lib/module/download/manager.dart | 56 ++++++++++++---------- 2 files changed, 31 insertions(+), 89 deletions(-) delete mode 100644 mobile/lib/module/download/db.dart diff --git a/mobile/lib/module/download/db.dart b/mobile/lib/module/download/db.dart deleted file mode 100644 index a6fcbfe163..0000000000 --- a/mobile/lib/module/download/db.dart +++ /dev/null @@ -1,64 +0,0 @@ -import "package:path/path.dart"; -import "package:photos/module/download/task.dart"; -import "package:sqflite/sqflite.dart"; - -class DatabaseHelper { - static final _instance = DatabaseHelper._internal(); - static Database? _database; - - factory DatabaseHelper() => _instance; - DatabaseHelper._internal(); - - Future get database async { - _database ??= await _initDatabase(); - return _database!; - } - - Future _initDatabase() async { - final path = join(await getDatabasesPath(), 'download_manager.db'); - - return await openDatabase( - path, - version: 1, - onCreate: (db, version) async { - await db.execute(''' - CREATE TABLE downloads ( - id INTEGER PRIMARY KEY, - filename TEXT NOT NULL, - totalBytes INTEGER NOT NULL, - bytesDownloaded INTEGER DEFAULT 0, - status TEXT NOT NULL, - error TEXT, - filePath TEXT - ) - '''); - }, - ); - } - - Future save(DownloadTask task) async { - final db = await database; - await db.insert( - 'downloads', - task.toMap(), - conflictAlgorithm: ConflictAlgorithm.replace, - ); - } - - Future get(int id) async { - final db = await database; - final maps = await db.query('downloads', where: 'id = ?', whereArgs: [id]); - return maps.isNotEmpty ? DownloadTask.fromMap(maps.first) : null; - } - - Future> getAll() async { - final db = await database; - final maps = await db.query('downloads'); - return maps.map(DownloadTask.fromMap).toList(); - } - - Future delete(int id) async { - final db = await database; - await db.delete('downloads', where: 'id = ?', whereArgs: [id]); - } -} diff --git a/mobile/lib/module/download/manager.dart b/mobile/lib/module/download/manager.dart index 503df3756b..31207cd757 100644 --- a/mobile/lib/module/download/manager.dart +++ b/mobile/lib/module/download/manager.dart @@ -5,23 +5,25 @@ import "package:dio/dio.dart"; import "package:logging/logging.dart"; import "package:photos/core/configuration.dart"; -import 'package:photos/module/download/db.dart'; import "package:photos/module/download/file_url.dart"; import "package:photos/module/download/task.dart"; class DownloadManager { + final _logger = Logger('DownloadManager'); static const int downloadChunkSize = 40 * 1024 * 1024; - final _db = DatabaseHelper(); final Dio _dio; - final _logger = Logger('DownloadManager'); - DownloadManager(this._dio); + + // In-memory storage for download tasks + final Map _tasks = {}; // Active downloads with their completers and streams final Map> _completers = {}; final Map> _streams = {}; final Map _cancelTokens = {}; + DownloadManager(this._dio); + /// Subscribe to download progress updates for a specific file ID Stream watchDownload(int fileId) { _streams[fileId] ??= StreamController.broadcast(); @@ -43,13 +45,17 @@ class DownloadManager { _completers[fileId] = completer; // Get or create task - final task = await _db.get(fileId) ?? + final existingTask = _tasks[fileId]; + final task = existingTask ?? DownloadTask( id: fileId, filename: filename, totalBytes: totalBytes, ); + // Store task in memory + _tasks[fileId] = task; + // Don't restart if already completed if (task.isCompleted) { // ensure that the file exists @@ -64,7 +70,7 @@ class DownloadManager { error: 'File not found', filePath: null, ); - await _updateTask(updatedTask); + _updateTask(updatedTask); } else { _logger.info( 'Download already completed for ${task.filename} (${task.bytesDownloaded}/${task.totalBytes} bytes)', @@ -85,9 +91,9 @@ class DownloadManager { token.cancel('paused'); } - final task = await _db.get(fileId); + final task = _tasks[fileId]; if (task != null && task.isActive) { - await _updateTask(task.copyWith(status: DownloadStatus.paused)); + _updateTask(task.copyWith(status: DownloadStatus.paused)); } } @@ -95,21 +101,21 @@ class DownloadManager { Future cancel(int fileId) async { await pause(fileId); - final task = await _db.get(fileId); + final task = _tasks[fileId]; if (task != null) { await _deleteFiles(task); - await _updateTask(task.copyWith(status: DownloadStatus.cancelled)); - await _db.delete(fileId); + _updateTask(task.copyWith(status: DownloadStatus.cancelled)); + _tasks.remove(fileId); } _cleanup(fileId); } /// Get current download status - Future getDownload(int fileId) => _db.get(fileId); + Future getDownload(int fileId) async => _tasks[fileId]; /// Get all downloads - Future> getAllDownloads() => _db.getAll(); + Future> getAllDownloads() async => _tasks.values.toList(); Future _startDownload( DownloadTask task, @@ -117,7 +123,7 @@ class DownloadManager { ) async { try { task = task.copyWith(status: DownloadStatus.downloading); - await _updateTask(task); + _updateTask(task); final cancelToken = CancelToken(); _cancelTokens[task.id] = cancelToken; @@ -137,7 +143,7 @@ class DownloadManager { totalChunks, ), ); - await _updateTask(task); + _updateTask(task); // Download missing chunks // log existing progress and download bytes @@ -159,7 +165,7 @@ class DownloadManager { filePath: finalPath, bytesDownloaded: task.totalBytes, ); - await _updateTask(task); + _updateTask(task); completer.complete(DownloadResult(task, true)); } } catch (e) { @@ -169,7 +175,7 @@ class DownloadManager { } task = task.copyWith(status: DownloadStatus.error, error: e.toString()); - await _updateTask(task); + _updateTask(task); completer.complete(DownloadResult(task, false)); } finally { _cleanup(task.id); @@ -177,7 +183,7 @@ class DownloadManager { } String _getChunkPath(String basePath, int part) { - return '$basePath.${part}_part}'; + return '$basePath.${part}_part'; } Future> _validateExistingChunks( @@ -197,7 +203,7 @@ class DownloadManager { final actualSize = await chunkFile.length(); if (actualSize == expectedSize) { - _logger.info('exiging chunk ${i + 1} is valid'); + _logger.info('existing chunk ${i + 1} is valid'); existingChunks[i] = true; } else { _logger.warning( @@ -262,13 +268,12 @@ class DownloadManager { // Update progress after chunk completion final chunkFileSize = await File(chunkPath).length(); task = task.copyWith(bytesDownloaded: task.bytesDownloaded + chunkFileSize); - await _updateTask(task); + _updateTask(task); } Future _combineChunks(String basePath, int totalChunks) async { final finalFile = File(basePath); final sink = finalFile.openWrite(); - try { for (int i = 1; i <= totalChunks; i++) { final chunkFile = File(_getChunkPath(basePath, i)); @@ -279,14 +284,13 @@ class DownloadManager { } finally { await sink.close(); } - return finalFile.path; } Future _deleteFiles(DownloadTask task) async { try { final directory = Configuration.instance.getTempDirectory(); - final basePath = '$directory${task.id}_${task.filename}'; + final basePath = '$directory${task.id}.encrypted'; // Delete final file final finalFile = File(basePath); if (await finalFile.exists()) await finalFile.delete(); @@ -302,8 +306,8 @@ class DownloadManager { } } - Future _updateTask(DownloadTask task) async { - await _db.save(task); + void _updateTask(DownloadTask task) { + _tasks[task.id] = task; _notifyProgress(task); } @@ -342,5 +346,7 @@ class DownloadManager { await stream.close(); } _streams.clear(); + + _tasks.clear(); } }