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..2a8dd9ca 100644 --- a/demos/supabase-todolist/lib/attachments/queue.dart +++ b/demos/supabase-todolist/lib/attachments/queue.dart @@ -39,13 +39,15 @@ class PhotoAttachmentQueue extends AbstractAttachmentQueue { } @override - Future savePhoto(String photoId, int size) async { - String filename = '$photoId.jpg'; + Future saveFile(String fileId, int size, + {mediaType = 'image/jpeg'}) async { + String filename = '$fileId.jpg'; + Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, - mediaType: 'image/jpeg', + mediaType: mediaType, localUri: getLocalFilePathSuffix(filename), size: size, ); @@ -54,10 +56,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 9946071a..2b215540 100644 --- a/demos/supabase-todolist/pubspec.lock +++ b/demos/supabase-todolist/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: app_links - sha256: "4e392b5eba997df356ca6021f28431ce1cfeb16758699553a94b13add874a3bb" + sha256: "0fd41f0501f131d931251e0942ac63d6216096a0052aeca037915c2c1deeb121" url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "5.0.0" archive: dependency: transitive description: name: archive - sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + sha256: "0763b45fa9294197a2885c8567927e2830ade852e5c896fd4ab7e0e348d0f373" url: "https://pub.dev" source: hosted - version: "3.4.10" + version: "3.5.0" async: dependency: transitive description: @@ -45,34 +45,34 @@ packages: dependency: transitive description: name: camera_android - sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371" + sha256: "7b0aba6398afa8475e2bc9115d976efb49cf8db781e922572d443795c04a4f4f" url: "https://pub.dev" source: hosted - version: "0.10.8+16" + version: "0.10.9+1" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - sha256: "7d0763dfcbf060f56aa254a68c103210280bee9e97bbe4fdef23e257a4f70ab9" + sha256: "7d021e8cd30d9b71b8b92b4ad669e80af432d722d18d6aac338572754a786c15" url: "https://pub.dev" source: hosted - version: "0.9.14" + version: "0.9.16" camera_platform_interface: dependency: transitive description: name: camera_platform_interface - sha256: fceb2c36038b6392317b1d5790c6ba9e6ca9f1da3031181b8bea03882bf9387a + sha256: a250314a48ea337b35909a4c9d5416a208d736dcb01d0b02c6af122be66660b0 url: "https://pub.dev" source: hosted - version: "2.7.3" + version: "2.7.4" camera_web: dependency: transitive description: name: camera_web - sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d + sha256: "9e9aba2fbab77ce2472924196ff8ac4dd8f9126c4f9a3096171cd1d870d6b26c" url: "https://pub.dev" source: hosted - version: "0.3.2+4" + version: "0.3.3" characters: dependency: transitive description: @@ -97,22 +97,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5" + sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" url: "https://pub.dev" source: hosted - version: "0.3.3+7" + version: "0.3.4+1" crypto: dependency: transitive description: @@ -162,18 +154,18 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.19" flutter_test: dependency: "direct dev" description: flutter @@ -188,18 +180,18 @@ packages: dependency: transitive description: name: functions_client - sha256: "9a0ab83a525c8691a6724746e642de755a299afa04158807787364cd9e718001" + sha256: a70b0dd9a1c35d05d1141557f7e49ffe4de5f450ffde31755a9eeeadca03b8ee url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" gotrue: dependency: transitive description: name: gotrue - sha256: "1bf6354278a98b8a1867263e94921da8a239de07e9babceab2b4e80af651a098" + sha256: c9c984f088320a5c5e87c7a34571e3de3982cca4cbd8b978e59d36baf748edfb url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.1" gtk: dependency: transitive description: @@ -236,10 +228,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" jwt_decode: dependency: transitive description: @@ -332,18 +324,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.4" path_provider_foundation: dependency: transitive description: @@ -400,14 +392,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" - url: "https://pub.dev" - source: hosted - version: "3.7.4" postgrest: dependency: transitive description: @@ -429,15 +413,15 @@ packages: path: "../../packages/powersync_attachments_helper" relative: true source: path - version: "0.3.2" + version: "0.4.0" realtime_client: dependency: transitive description: name: realtime_client - sha256: "41d6c5e0327d6c270b98b79bfed672928244af60e2856770f3eff697f9efe459" + sha256: "492a1ab568b3812cb345aad8dd09b3936877edba81a6ab6f5fdf365c155797e1" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.4" retry: dependency: transitive description: @@ -458,18 +442,18 @@ packages: dependency: transitive description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_foundation: dependency: transitive description: @@ -498,10 +482,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" shared_preferences_windows: dependency: transitive description: @@ -535,18 +519,18 @@ packages: dependency: transitive description: name: sqlite3 - sha256: "072128763f1547e3e9b4735ce846bfd226d68019ccda54db4cd427b12dfdedc9" + sha256: "1abbeb84bf2b1a10e5e1138c913123c8aa9d83cd64e5f9a0dd847b3c83063202" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" sqlite3_flutter_libs: dependency: transitive description: name: sqlite3_flutter_libs - sha256: d6c31c8511c441d1f12f20b607343df1afe4eddf24a1cf85021677c8eea26060 + sha256: fb2a106a2ea6042fe57de2c47074cc31539a941819c91e105b864744605da3f5 url: "https://pub.dev" source: hosted - version: "0.5.20" + version: "0.5.21" sqlite_async: dependency: "direct main" description: @@ -599,18 +583,18 @@ packages: dependency: transitive description: name: supabase - sha256: f431753d2a4cb9dacd72c7378154f806c2b2cef23859bd9cee1add23821e874d + sha256: ef407187b18c440f4a5c3f3cf30eb5cc1daadd4ff5616febf445a37e0e0ed34e url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.1.2" supabase_flutter: dependency: "direct main" description: name: supabase_flutter - sha256: "30e966b89ee61dc9de845e2d7e1c60967b3189c410d105c6d42f09b6259f4cb6" + sha256: "6a77bd6ef6dc451bb2561de0334d68d620b84d7df1de1448dd7962ed5d1a79ea" url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.5.2" term_glyph: dependency: transitive description: @@ -639,26 +623,26 @@ packages: dependency: transitive description: name: url_launcher - sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.6" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 + sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: @@ -687,10 +671,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" url_launcher_windows: dependency: transitive description: @@ -703,10 +687,10 @@ packages: dependency: transitive description: name: uuid - sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" url: "https://pub.dev" source: hosted - version: "4.3.3" + version: "4.4.0" vector_math: dependency: transitive description: @@ -727,26 +711,26 @@ packages: dependency: transitive description: name: web - sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad" + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" + sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.5" win32: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.5.0" xdg_directories: dependency: transitive description: @@ -773,4 +757,4 @@ packages: version: "2.0.0" sdks: dart: ">=3.3.0 <4.0.0" - flutter: ">=3.16.6" + flutter: ">=3.19.0" diff --git a/packages/powersync_attachments_helper/CHANGELOG.md b/packages/powersync_attachments_helper/CHANGELOG.md index c1f4bde4..e5b69882 100644 --- a/packages/powersync_attachments_helper/CHANGELOG.md +++ b/packages/powersync_attachments_helper/CHANGELOG.md @@ -1,3 +1,8 @@ +## 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. + ## 0.3.2 - Fix sync not resetting after an error is thrown diff --git a/packages/powersync_attachments_helper/README.md b/packages/powersync_attachments_helper/README.md index 032319f7..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 savePhoto(String photoId, int size) async { - String filename = '$photoId.jpg'; + Future saveFile(String fileId, int size, {mediaType = 'image/jpeg'}) async { + String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, - mediaType: 'image/jpeg', + mediaType: mediaType, localUri: getLocalFilePathSuffix(filename), size: size, ); @@ -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..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 savePhoto(String photoId, int size) async { - String filename = '$photoId.jpg'; + Future saveFile(String fileId, int size, + {mediaType = 'image/jpeg'}) async { + String filename = '$fileId.jpg'; Attachment photoAttachment = Attachment( - id: photoId, + id: fileId, filename: filename, state: AttachmentState.queuedUpload.index, - mediaType: 'image/jpeg', + mediaType: mediaType, localUri: getLocalFilePathSuffix(filename), size: size, ); @@ -33,10 +34,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 0f00f8cc..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.2 +version: 0.4.0 repository: https://github.com/powersync-ja/powersync.dart homepage: https://www.powersync.com/ environment: diff --git a/pubspec.lock b/pubspec.lock index 4c2d22b2..8dd75e5a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.0" http_multi_server: dependency: transitive description: @@ -485,18 +485,18 @@ packages: dependency: transitive description: name: web - sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad" + sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.4.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" + sha256: "939ab60734a4f8fa95feacb55804fa278de28bdeef38e616dc08e44a84adea23" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.3" webkit_inspection_protocol: dependency: transitive description: @@ -522,4 +522,4 @@ packages: source: hosted version: "2.1.1" sdks: - dart: ">=3.3.0 <4.0.0" + dart: ">=3.2.3 <4.0.0"