Skip to content

Commit f66fbdb

Browse files
Merge branch 'attachment-package-refactor' of github.com:powersync-ja/powersync.dart into attachment-package-refactor
1 parent a701f7d commit f66fbdb

File tree

11 files changed

+166
-165
lines changed

11 files changed

+166
-165
lines changed

demos/supabase-todolist-new-attachment/lib/attachments/photo_widget.dart

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class _PhotoWidgetState extends State<PhotoWidget> {
3636
final log = Logger('PhotoWidget');
3737

3838
Future<_ResolvedPhotoState> _getPhotoState(photoId) async {
39-
log.info('getPhotoState: $photoId');
4039
if (photoId == null) {
4140
return _ResolvedPhotoState(photoPath: null, fileExists: false);
4241
}
@@ -45,25 +44,13 @@ class _PhotoWidgetState extends State<PhotoWidget> {
4544

4645
bool fileExists = await File(photoPath).exists();
4746

48-
log.info('fileExists: $fileExists');
49-
5047
final row = await attachmentQueue.db
5148
.getOptional('SELECT * FROM attachments_queue WHERE id = ?', [photoId]);
5249

5350
log.info('row: $row');
5451

5552
if (row != null) {
5653
Attachment attachment = Attachment.fromRow(row);
57-
// Attachment attachment = Attachment.fromMap(row);
58-
59-
// Log as JSON using logging package
60-
// ignore: avoid_print
61-
attachmentQueue.logger.info({
62-
'event': 'attachment_object',
63-
'photoPath': photoPath,
64-
'fileExists': fileExists,
65-
'attachment': '',
66-
});
6754

6855
return _ResolvedPhotoState(
6956
photoPath: photoPath, fileExists: fileExists, attachment: attachment);

demos/supabase-todolist-new-attachment/lib/attachments/remote_storage_adapter.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class SupabaseStorageAdapter implements RemoteStorage {
2525
fileOptions: FileOptions(
2626
contentType:
2727
attachment.mediaType ?? 'application/octet-stream'));
28-
print('uploadFile: ${attachment.filename}');
28+
2929
} catch (error) {
3030
throw Exception(error);
3131
} finally {

demos/supabase-todolist-new-attachment/pubspec.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -566,14 +566,14 @@ packages:
566566
path: "../../packages/powersync"
567567
relative: true
568568
source: path
569-
version: "1.14.1"
569+
version: "1.15.0"
570570
powersync_attachments_helper:
571571
dependency: "direct overridden"
572572
description:
573573
path: "../../packages/powersync_attachments_helper"
574574
relative: true
575575
source: path
576-
version: "0.6.18+10"
576+
version: "0.6.18+11"
577577
powersync_attachments_stream:
578578
dependency: "direct main"
579579
description:
@@ -587,14 +587,14 @@ packages:
587587
path: "../../packages/powersync_core"
588588
relative: true
589589
source: path
590-
version: "1.4.1"
590+
version: "1.5.0"
591591
powersync_flutter_libs:
592592
dependency: "direct overridden"
593593
description:
594594
path: "../../packages/powersync_flutter_libs"
595595
relative: true
596596
source: path
597-
version: "0.4.9"
597+
version: "0.4.10"
598598
pub_semver:
599599
dependency: transitive
600600
description:
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
/// Default exports for native platforms (dart:io). For web, use 'common.dart'.
22
export 'common.dart';
33
export 'src/storage/io_local_storage.dart';
4-
export 'src/attachment_queue_service.dart';
5-
export 'src/implementations/attachment_service.dart';
6-
export 'src/implementations/attachment_context.dart';
7-
export 'src/abstractions/remote_storage.dart';
4+
export 'src/attachment_queue_service.dart';

packages/powersync_attachments_stream/lib/src/attachment.dart

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@ enum AttachmentState {
1515
synced,
1616

1717
/// The attachment is archived and no longer actively synchronized.
18-
archived,
19-
}
18+
archived;
2019

21-
extension AttachmentStateX on AttachmentState {
2220
static AttachmentState fromInt(int value) {
2321
if (value < 0 || value >= AttachmentState.values.length) {
2422
throw ArgumentError('Invalid value for AttachmentState: $value');
@@ -54,22 +52,6 @@ class Attachment {
5452
this.metaData,
5553
});
5654

57-
/// Factory constructor to create an Attachment from a database map.
58-
/// [map] should be a `Map<String, dynamic>` from your database query.
59-
// factory Attachment.fromMap(Map<String, dynamic> map) {
60-
// return Attachment(
61-
// id: map['id'] as String,
62-
// timestamp: map['timestamp'] as int? ?? 0,
63-
// filename: map['filename'] as String,
64-
// localUri: map['local_uri'] as String?,
65-
// mediaType: map['media_type'] as String?,
66-
// size: map['size'] as int?,
67-
// state: AttachmentStateX.fromInt(map['state'] as int),
68-
// hasSynced: (map['has_synced'] as int? ?? 0) > 0,
69-
// metaData: map['meta_data'] as String?,
70-
// );
71-
// }
72-
7355
factory Attachment.fromRow(Row row) {
7456
return Attachment(
7557
id: row['id'] as String,
@@ -78,15 +60,8 @@ class Attachment {
7860
localUri: row['local_uri'] as String?,
7961
mediaType: row['media_type'] as String?,
8062
size: row['size'] as int?,
81-
// state: AttachmentState.queuedDownload,
82-
state: AttachmentStateX.fromInt(row['state'] as int),
83-
// state: AttachmentStateX.fromInt(row['state'] as int? ?? AttachmentState.queuedDownload.index),
84-
// state: AttachmentState.values.firstWhere(
85-
// (e) => e.index == row['state'],
86-
// orElse: () => AttachmentState.queuedDownload,
87-
// ),
63+
state: AttachmentState.fromInt(row['state'] as int),
8864
hasSynced: (row['has_synced'] as int? ?? 0) > 0,
89-
// metaData: 'test',
9065
metaData: row['meta_data']?.toString(),
9166
);
9267
}
@@ -115,26 +90,6 @@ class Attachment {
11590
metaData: metaData ?? this.metaData,
11691
);
11792
}
118-
119-
/// Converts this Attachment to a JSON-compatible map.
120-
Map<String, dynamic> toJson() {
121-
try {
122-
return {
123-
'id': id,
124-
'timestamp': timestamp,
125-
'filename': filename,
126-
'state': state.index,
127-
'local_uri': localUri,
128-
'media_type': mediaType,
129-
'size': size,
130-
'has_synced': hasSynced ? 1 : 0,
131-
'meta_data': metaData,
132-
};
133-
} catch (e) {
134-
print('toJson error: $e');
135-
return {};
136-
}
137-
}
13893
}
13994

14095
class AttachmentsQueueTable extends Table {

packages/powersync_attachments_stream/lib/src/attachment_queue_service.dart

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:async';
22
import 'dart:typed_data';
33
import 'package:logging/logging.dart';
4+
import 'package:powersync_core/powersync_core.dart';
45
import 'package:sqlite_async/mutex.dart';
56
import 'attachment.dart';
67
import 'abstractions/attachment_service.dart';
@@ -33,7 +34,7 @@ class WatchedAttachmentItem {
3334
/// Class used to implement the attachment queue.
3435
/// Requires a database client, remote storage adapter, and an attachment directory name.
3536
class AttachmentQueue {
36-
final dynamic db;
37+
final PowerSyncDatabase db;
3738
final RemoteStorage remoteStorage;
3839
final String attachmentsDirectory;
3940
final Stream<List<WatchedAttachmentItem>> Function() watchAttachments;
@@ -43,7 +44,6 @@ class AttachmentQueue {
4344
final Duration syncInterval;
4445
final int archivedCacheLimit;
4546
final Duration syncThrottleDuration;
46-
final List<String>? subdirectories;
4747
final bool downloadAttachments;
4848
final Logger logger;
4949

@@ -66,7 +66,6 @@ class AttachmentQueue {
6666
this.syncInterval = const Duration(seconds: 30),
6767
this.archivedCacheLimit = 100,
6868
this.syncThrottleDuration = const Duration(seconds: 1),
69-
this.subdirectories,
7069
this.downloadAttachments = true,
7170
Logger? logger,
7271
}) : logger = logger ?? Logger('AttachmentQueue') {
@@ -101,13 +100,8 @@ class AttachmentQueue {
101100

102101
await _stopSyncingInternal();
103102

104-
logger.info('startSync attachmentsDirectory: $attachmentsDirectory');
105103
await localStorage.makeDir(attachmentsDirectory);
106104

107-
subdirectories?.forEach((subdirectory) async {
108-
await localStorage.makeDir('$attachmentsDirectory/$subdirectory');
109-
});
110-
111105
await attachmentsService.withContext((context) async {
112106
await _verifyAttachments(context);
113107
});
@@ -197,8 +191,16 @@ class AttachmentQueue {
197191
filename: filename,
198192
state: AttachmentState.queuedDownload,
199193
metaData: item.metaData,
194+
// hasSynced: existingQueueItem.hasSynced;
200195
),
201196
);
197+
198+
// attachmentUpdates.add(
199+
// existingQueueItem.copyWith(
200+
// filename: filename,
201+
// state: AttachmentState.queuedDownload,
202+
// ),
203+
// );
202204
} else if (existingQueueItem.state == AttachmentState.archived) {
203205
// The attachment is present again. Need to queue it for sync.
204206
if (existingQueueItem.hasSynced) {

packages/powersync_attachments_stream/lib/src/implementations/attachment_context.dart

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -47,27 +47,9 @@ class AttachmentContextImpl implements AttachmentContext {
4747

4848
@override
4949
Future<Attachment> saveAttachment(Attachment attachment) async {
50-
Attachment updatedRecord = attachment.copyWith(
51-
timestamp: DateTime.now().millisecondsSinceEpoch,
52-
);
53-
54-
await db.execute(
55-
'''
56-
INSERT OR REPLACE INTO $table
57-
(id, timestamp, filename, local_uri, media_type, size, state) VALUES (?, ?, ?, ?, ?, ?, ?)
58-
''',
59-
[
60-
updatedRecord.id,
61-
updatedRecord.timestamp,
62-
updatedRecord.filename,
63-
updatedRecord.localUri,
64-
updatedRecord.mediaType,
65-
updatedRecord.size,
66-
updatedRecord.state.index,
67-
],
68-
);
69-
70-
return updatedRecord;
50+
return await db.writeLock((ctx) async {
51+
return await upsertAttachment(attachment, ctx);
52+
});
7153
}
7254

7355
@override
@@ -76,28 +58,11 @@ class AttachmentContextImpl implements AttachmentContext {
7658
log.info('No attachments to save.');
7759
return;
7860
}
79-
80-
final updatedRecords = attachments.map((attachment) {
81-
final updated = attachment.copyWith(
82-
timestamp: DateTime.now().millisecondsSinceEpoch,
83-
);
84-
return [
85-
updated.id,
86-
updated.filename,
87-
updated.localUri,
88-
updated.mediaType,
89-
updated.size,
90-
updated.timestamp,
91-
updated.state.index,
92-
];
93-
}).toList();
94-
95-
log.info('Saving ${updatedRecords.length} attachments...');
96-
97-
await db.executeBatch('''
98-
INSERT OR REPLACE INTO $table
99-
(id, filename, local_uri, media_type, size, timestamp, state) VALUES (?, ?, ?, ?, ?, ?, ?)
100-
''', updatedRecords);
61+
await db.writeTransaction((tx) async {
62+
for (final attachment in attachments) {
63+
await upsertAttachment(attachment, tx);
64+
}
65+
});
10166
}
10267

10368
@override
@@ -181,11 +146,11 @@ class AttachmentContextImpl implements AttachmentContext {
181146
attachment.mediaType,
182147
attachment.size,
183148
attachment.state.index,
184-
// attachment.state,
185149
attachment.hasSynced ? 1 : 0,
186150
attachment.metaData,
187151
],
188152
);
153+
189154
return attachment;
190155
}
191156
}

packages/powersync_attachments_stream/lib/src/sync/syncing_service.dart

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,6 @@ class SyncingService {
172172
if (attachment.localUri == null) {
173173
throw Exception('No localUri for attachment $attachment');
174174
}
175-
_log.info(
176-
'SyncingService: Calling remoteStorage.uploadFile for ${attachment.id}',
177-
);
178175
await remoteStorage.uploadFile(
179176
localStorage.readFile(attachment.localUri!),
180177
attachment,
@@ -211,9 +208,6 @@ class SyncingService {
211208
);
212209
final attachmentPath = await getLocalUri(attachment.filename);
213210
try {
214-
_log.info(
215-
'SyncingService: Calling remoteStorage.downloadFile for ${attachment.id}',
216-
);
217211
final fileStream = await remoteStorage.downloadFile(attachment);
218212
await localStorage.saveFile(
219213
attachmentPath,
@@ -222,6 +216,9 @@ class SyncingService {
222216
_log.info(
223217
'SyncingService: Successfully downloaded file "${attachment.id}"',
224218
);
219+
220+
_log.info('downloadAttachmentXY $attachment');
221+
225222
return attachment.copyWith(
226223
localUri: attachmentPath,
227224
state: AttachmentState.synced,

packages/powersync_attachments_stream/pubspec.lock

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ packages:
2626
source: hosted
2727
version: "2.7.0"
2828
async:
29-
dependency: transitive
29+
dependency: "direct main"
3030
description:
3131
name: async
3232
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
@@ -398,10 +398,9 @@ packages:
398398
powersync_core:
399399
dependency: "direct main"
400400
description:
401-
name: powersync_core
402-
sha256: d8ae292bc77f0a96f44c6cc2911d1b781760a87a919e5045e75458cba83bb759
403-
url: "https://pub.dev"
404-
source: hosted
401+
path: "../powersync_core"
402+
relative: true
403+
source: path
405404
version: "1.5.0"
406405
pub_semver:
407406
dependency: transitive
@@ -568,6 +567,14 @@ packages:
568567
url: "https://pub.dev"
569568
source: hosted
570569
version: "0.6.8"
570+
test_descriptor:
571+
dependency: "direct dev"
572+
description:
573+
name: test_descriptor
574+
sha256: "9ce468c97ae396e8440d26bb43763f84e2a2a5331813ee5a397cb4da481aaf9a"
575+
url: "https://pub.dev"
576+
source: hosted
577+
version: "2.0.2"
571578
typed_data:
572579
dependency: transitive
573580
description:

packages/powersync_attachments_stream/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ dependencies:
1212
sdk: flutter
1313
path: ^1.8.0
1414
async: ^2.11.0
15-
1615
powersync_core: ^1.4.1
1716
logging: ^1.2.0
1817
sqlite_async: ^0.11.0
@@ -21,5 +20,6 @@ dependencies:
2120
dev_dependencies:
2221
flutter_test:
2322
sdk: flutter
24-
flutter_lints: ^5.0.0
2523
test: ^1.25.15
24+
test_descriptor: ^2.0.2
25+
flutter_lints: ^5.0.0

0 commit comments

Comments
 (0)