From e18c6538a33d072f0bdaf35337eac7e4fbe61cf3 Mon Sep 17 00:00:00 2001 From: DominicGBauer Date: Tue, 23 Apr 2024 13:48:17 +0200 Subject: [PATCH 1/3] feat(attachments): cater for subdirectorires in storage --- .../lib/attachments/photo_capture_widget.dart | 2 +- .../lib/attachments/queue.dart | 14 +++++++----- .../lib/widgets/todo_item_widget.dart | 2 +- demos/supabase-todolist/pubspec.lock | 2 +- .../powersync_attachments_helper/CHANGELOG.md | 5 +++++ .../powersync_attachments_helper/README.md | 14 ++++++------ .../example/getting_started.dart | 12 +++++----- .../lib/src/attachments_queue.dart | 22 ++++++++++++++----- .../powersync_attachments_helper/pubspec.yaml | 2 +- 9 files changed, 47 insertions(+), 28 deletions(-) diff --git a/demos/supabase-todolist/lib/attachments/photo_capture_widget.dart b/demos/supabase-todolist/lib/attachments/photo_capture_widget.dart index a4bad5a9..38838dd7 100644 --- a/demos/supabase-todolist/lib/attachments/photo_capture_widget.dart +++ b/demos/supabase-todolist/lib/attachments/photo_capture_widget.dart @@ -58,7 +58,7 @@ class _TakePhotoWidgetState extends State { int photoSize = await photo.length(); TodoItem.addPhoto(photoId, widget.todoId); - attachmentQueue.savePhoto(photoId, photoSize); + attachmentQueue.saveFile(photoId, photoSize); } catch (e) { log.info('Error taking photo: $e'); } diff --git a/demos/supabase-todolist/lib/attachments/queue.dart b/demos/supabase-todolist/lib/attachments/queue.dart index 75273309..365ee249 100644 --- a/demos/supabase-todolist/lib/attachments/queue.dart +++ b/demos/supabase-todolist/lib/attachments/queue.dart @@ -39,10 +39,11 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { } @override - Future savePhoto(String photoId, int size) async { - String filename = '$photoId.jpg'; + Future saveFile(String fileId, int size) async { + String filename = '$fileId.jpg'; + Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, mediaType: 'image/jpeg', @@ -54,10 +55,11 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { } @override - Future deletePhoto(String photoId) async { - String filename = '$photoId.jpg'; + Future deleteFile(String fileId) async { + String filename = '$fileId.jpg'; + Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedDelete.index); diff --git a/demos/supabase-todolist/lib/widgets/todo_item_widget.dart b/demos/supabase-todolist/lib/widgets/todo_item_widget.dart index efe64fcc..a59812ed 100644 --- a/demos/supabase-todolist/lib/widgets/todo_item_widget.dart +++ b/demos/supabase-todolist/lib/widgets/todo_item_widget.dart @@ -23,7 +23,7 @@ class TodoItemWidget extends StatelessWidget { Future deleteTodo(TodoItem todo) async { if (todo.photoId != null) { - attachmentQueue.deletePhoto(todo.photoId!); + attachmentQueue.deleteFile(todo.photoId!); } await todo.delete(); } diff --git a/demos/supabase-todolist/pubspec.lock b/demos/supabase-todolist/pubspec.lock index 6781d83b..977bbe99 100644 --- a/demos/supabase-todolist/pubspec.lock +++ b/demos/supabase-todolist/pubspec.lock @@ -429,7 +429,7 @@ packages: path: "../../packages/powersync_attachments_helper" relative: true source: path - version: "0.3.1" + version: "0.4.0" realtime_client: dependency: transitive description: diff --git a/packages/powersync_attachments_helper/CHANGELOG.md b/packages/powersync_attachments_helper/CHANGELOG.md index 1028766a..6f47f398 100644 --- a/packages/powersync_attachments_helper/CHANGELOG.md +++ b/packages/powersync_attachments_helper/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.4.1 + +- BREAKING CHANGE: Generalize naming so `savePhoto` and `deletePhoto` have been removed in favour of `saveFile` and `deleteFile` +- Added optional subDirectories argument when initializing the queue so that local subDirectories are created to match any subDirectories on the storage provider allowing files to be saved instead of an error being thrown. + ## 0.3.1 - Add periodic syncing and deleting of attachments diff --git a/packages/powersync_attachments_helper/README.md b/packages/powersync_attachments_helper/README.md index 032319f7..39cad969 100644 --- a/packages/powersync_attachments_helper/README.md +++ b/packages/powersync_attachments_helper/README.md @@ -32,10 +32,10 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { // This will create an item on the attachment queue to UPLOAD an image // to remote storage @override - Future savePhoto(String photoId, int size) async { - String filename = '$photoId.jpg'; + Future saveFile(String fileId, int size) async { + String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, mediaType: 'image/jpeg', @@ -46,13 +46,13 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { return attachmentsService.saveAttachment(photoAttachment); } - // This will create an item on the attachment queue to DELETE an image + // This will create an item on the attachment queue to DELETE a file // in local and remote storage @override - Future deletePhoto(String photoId) async { - String filename = '$photoId.jpg'; + Future deleteFile(String fileId) async { + String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedDelete.index); diff --git a/packages/powersync_attachments_helper/example/getting_started.dart b/packages/powersync_attachments_helper/example/getting_started.dart index 3f045b01..29437e0e 100644 --- a/packages/powersync_attachments_helper/example/getting_started.dart +++ b/packages/powersync_attachments_helper/example/getting_started.dart @@ -18,10 +18,10 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { : super(db: db, remoteStorage: remoteStorage); @override - Future savePhoto(String photoId, int size) async { - String filename = '$photoId.jpg'; + Future saveFile(String fileId, int size) async { + String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, mediaType: 'image/jpeg', @@ -33,10 +33,10 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { } @override - Future deletePhoto(String photoId) async { - String filename = '$photoId.jpg'; + Future deleteFile(String fileId) async { + String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedDelete.index); diff --git a/packages/powersync_attachments_helper/lib/src/attachments_queue.dart b/packages/powersync_attachments_helper/lib/src/attachments_queue.dart index f2f8e742..7ceb8208 100644 --- a/packages/powersync_attachments_helper/lib/src/attachments_queue.dart +++ b/packages/powersync_attachments_helper/lib/src/attachments_queue.dart @@ -37,6 +37,10 @@ abstract class AbstractAttachmentQueue { /// Default is 5 minutes int intervalInMinutes; + /// Provide the subdirectories located on external storage so that they are created + /// when the attachment queue is initialized. + List? subdirectories; + AbstractAttachmentQueue( {required this.db, required this.remoteStorage, @@ -44,7 +48,8 @@ abstract class AbstractAttachmentQueue { this.attachmentsQueueTableName = defaultAttachmentsQueueTableName, this.onDownloadError, this.onUploadError, - this.intervalInMinutes = 5}) { + this.intervalInMinutes = 5, + this.subdirectories}) { attachmentsService = AttachmentsService( db, localStorage, attachmentDirectoryName, attachmentsQueueTableName); syncingService = SyncingService( @@ -56,11 +61,11 @@ abstract class AbstractAttachmentQueue { /// Set the file extension if you are using a different file type StreamSubscription watchIds({String fileExtension = 'jpg'}); - /// Create a function to save photos using the attachment queue - Future savePhoto(String photoId, int size); + /// Create a function to save files using the attachment queue + Future saveFile(String fileId, int size); - /// Create a function to delete photos using the attachment queue - Future deletePhoto(String photoId); + /// Create a function to delete files using the attachment queue + Future deleteFile(String fileId); /// Initialize the attachment queue by /// 1. Creating attachments directory @@ -70,6 +75,13 @@ abstract class AbstractAttachmentQueue { // Ensure the directory where attachments are downloaded, exists await localStorage.makeDir(await getStorageDirectory()); + if (subdirectories != null) { + for (String subdirectory in subdirectories!) { + await localStorage + .makeDir('${await getStorageDirectory()}/$subdirectory'); + } + } + watchIds(); syncingService.watchAttachments(); syncingService.startPeriodicSync(intervalInMinutes); diff --git a/packages/powersync_attachments_helper/pubspec.yaml b/packages/powersync_attachments_helper/pubspec.yaml index bb599186..3492b627 100644 --- a/packages/powersync_attachments_helper/pubspec.yaml +++ b/packages/powersync_attachments_helper/pubspec.yaml @@ -1,6 +1,6 @@ name: powersync_attachments_helper description: A helper library for handling attachments when using PowerSync. -version: 0.3.1 +version: 0.4.0 repository: https://github.com/powersync-ja/powersync.dart homepage: https://www.powersync.com/ environment: From 8222ba205ba4fdde1a6fcdf6d5eb4493750458af Mon Sep 17 00:00:00 2001 From: DominicGBauer Date: Tue, 23 Apr 2024 14:02:11 +0200 Subject: [PATCH 2/3] fix: changelog --- packages/powersync_attachments_helper/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/powersync_attachments_helper/CHANGELOG.md b/packages/powersync_attachments_helper/CHANGELOG.md index 6f47f398..bb0e0d0a 100644 --- a/packages/powersync_attachments_helper/CHANGELOG.md +++ b/packages/powersync_attachments_helper/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.4.1 +## 0.4.0 - BREAKING CHANGE: Generalize naming so `savePhoto` and `deletePhoto` have been removed in favour of `saveFile` and `deleteFile` - Added optional subDirectories argument when initializing the queue so that local subDirectories are created to match any subDirectories on the storage provider allowing files to be saved instead of an error being thrown. From cb49a1d5abb3b8d39602fe0ef1f472eda9141bf5 Mon Sep 17 00:00:00 2001 From: DominicGBauer Date: Tue, 23 Apr 2024 15:01:54 +0200 Subject: [PATCH 3/3] chore: make mediaType configurable in example and demo --- demos/supabase-todolist/lib/attachments/queue.dart | 5 +++-- packages/powersync_attachments_helper/README.md | 4 ++-- .../example/getting_started.dart | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/demos/supabase-todolist/lib/attachments/queue.dart b/demos/supabase-todolist/lib/attachments/queue.dart index 365ee249..2a8dd9ca 100644 --- a/demos/supabase-todolist/lib/attachments/queue.dart +++ b/demos/supabase-todolist/lib/attachments/queue.dart @@ -39,14 +39,15 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { } @override - Future saveFile(String fileId, int size) async { + Future saveFile(String fileId, int size, + {mediaType = 'image/jpeg'}) async { String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, - mediaType: 'image/jpeg', + mediaType: mediaType, localUri: getLocalFilePathSuffix(filename), size: size, ); diff --git a/packages/powersync_attachments_helper/README.md b/packages/powersync_attachments_helper/README.md index 39cad969..a44f8c9d 100644 --- a/packages/powersync_attachments_helper/README.md +++ b/packages/powersync_attachments_helper/README.md @@ -32,13 +32,13 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { // This will create an item on the attachment queue to UPLOAD an image // to remote storage @override - Future saveFile(String fileId, int size) async { + Future saveFile(String fileId, int size, {mediaType = 'image/jpeg'}) async { String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, - mediaType: 'image/jpeg', + mediaType: mediaType, localUri: getLocalFilePathSuffix(filename), size: size, ); diff --git a/packages/powersync_attachments_helper/example/getting_started.dart b/packages/powersync_attachments_helper/example/getting_started.dart index 29437e0e..f5302508 100644 --- a/packages/powersync_attachments_helper/example/getting_started.dart +++ b/packages/powersync_attachments_helper/example/getting_started.dart @@ -18,13 +18,14 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { : super(db: db, remoteStorage: remoteStorage); @override - Future saveFile(String fileId, int size) async { + Future saveFile(String fileId, int size, + {mediaType = 'image/jpeg'}) async { String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, - mediaType: 'image/jpeg', + mediaType: mediaType, localUri: getLocalFilePathSuffix(filename), size: size, );