mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-04-16 06:32:54 +00:00
Fix: Issue with media files required to be reuploaded
This commit is contained in:
parent
48b0715b18
commit
4b1e6a9a44
36 changed files with 48309 additions and 26402 deletions
|
|
@ -8,6 +8,7 @@
|
|||
- Improve: Video compression with progress updates
|
||||
- Improve: Show message "Flames restored"
|
||||
- Improve: Show toast message if user was added via QR
|
||||
- Fix: Issue with media files required to be reuploaded
|
||||
- Fix: Problem during contact requests
|
||||
- Fix: Problem with deleting a contact
|
||||
- Fix: Problem with restoring from backup
|
||||
|
|
|
|||
|
|
@ -131,6 +131,10 @@ PODS:
|
|||
- google_mlkit_commons (0.11.1):
|
||||
- Flutter
|
||||
- MLKitVision (~> 10.0.0)
|
||||
- google_mlkit_face_detection (0.13.2):
|
||||
- Flutter
|
||||
- google_mlkit_commons
|
||||
- GoogleMLKit/FaceDetection (~> 9.0.0)
|
||||
- GoogleAdsOnDeviceConversion (3.2.0):
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
|
|
@ -164,6 +168,9 @@ PODS:
|
|||
- GoogleMLKit/BarcodeScanning (9.0.0):
|
||||
- GoogleMLKit/MLKitCore
|
||||
- MLKitBarcodeScanning (~> 8.0.0)
|
||||
- GoogleMLKit/FaceDetection (9.0.0):
|
||||
- GoogleMLKit/MLKitCore
|
||||
- MLKitFaceDetection (~> 8.0.0)
|
||||
- GoogleMLKit/MLKitCore (9.0.0):
|
||||
- MLKitCommon (~> 14.0.0)
|
||||
- GoogleToolboxForMac/Defines (4.2.1)
|
||||
|
|
@ -246,6 +253,9 @@ PODS:
|
|||
- GoogleUtilities/Logger (~> 8.0)
|
||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 3.3.2)
|
||||
- MLKitFaceDetection (8.0.0):
|
||||
- MLKitCommon (~> 14.0)
|
||||
- MLKitVision (~> 10.0)
|
||||
- MLKitVision (10.0.0):
|
||||
- GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)"
|
||||
|
|
@ -348,6 +358,7 @@ DEPENDENCIES:
|
|||
- gal (from `.symlinks/plugins/gal/darwin`)
|
||||
- google_mlkit_barcode_scanning (from `.symlinks/plugins/google_mlkit_barcode_scanning/ios`)
|
||||
- google_mlkit_commons (from `.symlinks/plugins/google_mlkit_commons/ios`)
|
||||
- google_mlkit_face_detection (from `.symlinks/plugins/google_mlkit_face_detection/ios`)
|
||||
- GoogleUtilities
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
|
||||
|
|
@ -389,6 +400,7 @@ SPEC REPOS:
|
|||
- MLImage
|
||||
- MLKitBarcodeScanning
|
||||
- MLKitCommon
|
||||
- MLKitFaceDetection
|
||||
- MLKitVision
|
||||
- nanopb
|
||||
- PromisesObjC
|
||||
|
|
@ -442,6 +454,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/google_mlkit_barcode_scanning/ios"
|
||||
google_mlkit_commons:
|
||||
:path: ".symlinks/plugins/google_mlkit_commons/ios"
|
||||
google_mlkit_face_detection:
|
||||
:path: ".symlinks/plugins/google_mlkit_face_detection/ios"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
in_app_purchase_storekit:
|
||||
|
|
@ -505,6 +519,7 @@ SPEC CHECKSUMS:
|
|||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||
google_mlkit_barcode_scanning: 12d8422d8f7b00726dedf9cac00188a2b98750c2
|
||||
google_mlkit_commons: a5e4ffae5bc59ea4c7b9025dc72cb6cb79dc1166
|
||||
google_mlkit_face_detection: ee4b72cfae062b4c972204be955d83055a4bfd36
|
||||
GoogleAdsOnDeviceConversion: d68c69dd9581a0f5da02617b6f377e5be483970f
|
||||
GoogleAppMeasurement: fce7c1c90640d2f9f5c56771f71deacb2ba3f98c
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
|
|
@ -520,6 +535,7 @@ SPEC CHECKSUMS:
|
|||
MLImage: 0de5c6c2bf9e93b80ef752e2797f0836f03b58c0
|
||||
MLKitBarcodeScanning: 39de223e7b1b8a8fbf10816a536dd292d8a39343
|
||||
MLKitCommon: 47d47b50a031d00db62f1b0efe5a1d8b09a3b2e6
|
||||
MLKitFaceDetection: 32549f1e70e6e7731261bf9cea2b74095e2531cb
|
||||
MLKitVision: 39a5a812db83c4a0794445088e567f3631c11961
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
no_screenshot: 03c8ac6586f9652cd45e3d12d74e5992256403ac
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
GroupsDao(super.db);
|
||||
|
||||
Future<bool> isContactInGroup(int contactId, String groupId) async {
|
||||
final entry = await (select(groupMembers)..where(
|
||||
// ignore: require_trailing_commas
|
||||
(t) => t.contactId.equals(contactId) & t.groupId.equals(groupId)))
|
||||
.getSingleOrNull();
|
||||
final entry =
|
||||
await (select(groupMembers)..where(
|
||||
(t) => t.contactId.equals(contactId) & t.groupId.equals(groupId),
|
||||
))
|
||||
.getSingleOrNull();
|
||||
return entry != null;
|
||||
}
|
||||
|
||||
|
|
@ -38,30 +39,31 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
String groupId,
|
||||
GroupsCompanion updates,
|
||||
) async {
|
||||
await (update(groups)..where((c) => c.groupId.equals(groupId)))
|
||||
.write(updates);
|
||||
await (update(
|
||||
groups,
|
||||
)..where((c) => c.groupId.equals(groupId))).write(updates);
|
||||
}
|
||||
|
||||
Future<List<GroupMember>> getGroupNonLeftMembers(String groupId) async {
|
||||
return (select(groupMembers)
|
||||
..where(
|
||||
(t) =>
|
||||
t.groupId.equals(groupId) &
|
||||
(t.memberState.equals(MemberState.leftGroup.name).not() |
|
||||
t.memberState.isNull()),
|
||||
))
|
||||
return (select(groupMembers)..where(
|
||||
(t) =>
|
||||
t.groupId.equals(groupId) &
|
||||
(t.memberState.equals(MemberState.leftGroup.name).not() |
|
||||
t.memberState.isNull()),
|
||||
))
|
||||
.get();
|
||||
}
|
||||
|
||||
Future<List<GroupMember>> getAllGroupMembers(String groupId) async {
|
||||
return (select(groupMembers)..where((t) => t.groupId.equals(groupId)))
|
||||
.get();
|
||||
return (select(
|
||||
groupMembers,
|
||||
)..where((t) => t.groupId.equals(groupId))).get();
|
||||
}
|
||||
|
||||
Future<GroupMember?> getGroupMemberByPublicKey(Uint8List publicKey) async {
|
||||
return (select(groupMembers)
|
||||
..where((t) => t.groupPublicKey.equals(publicKey)))
|
||||
.getSingleOrNull();
|
||||
return (select(
|
||||
groupMembers,
|
||||
)..where((t) => t.groupPublicKey.equals(publicKey))).getSingleOrNull();
|
||||
}
|
||||
|
||||
Future<Group?> createNewGroup(GroupsCompanion group) async {
|
||||
|
|
@ -94,18 +96,16 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
int contactId,
|
||||
GroupMembersCompanion updates,
|
||||
) async {
|
||||
await (update(groupMembers)
|
||||
..where(
|
||||
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
|
||||
))
|
||||
await (update(groupMembers)..where(
|
||||
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
|
||||
))
|
||||
.write(updates);
|
||||
}
|
||||
|
||||
Future<void> removeMember(String groupId, int contactId) async {
|
||||
await (delete(groupMembers)
|
||||
..where(
|
||||
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
|
||||
))
|
||||
await (delete(groupMembers)..where(
|
||||
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
|
||||
))
|
||||
.go();
|
||||
}
|
||||
|
||||
|
|
@ -138,9 +138,9 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
Future<Group?> _insertGroup(GroupsCompanion group) async {
|
||||
try {
|
||||
await into(groups).insert(group);
|
||||
return await (select(groups)
|
||||
..where((t) => t.groupId.equals(group.groupId.value)))
|
||||
.getSingle();
|
||||
return await (select(
|
||||
groups,
|
||||
)..where((t) => t.groupId.equals(group.groupId.value))).getSingle();
|
||||
} catch (e) {
|
||||
Log.error('Could not insert group: $e');
|
||||
return null;
|
||||
|
|
@ -148,69 +148,71 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
}
|
||||
|
||||
Future<List<Contact>> getGroupContact(String groupId) async {
|
||||
final query = (select(contacts).join([
|
||||
leftOuterJoin(
|
||||
groupMembers,
|
||||
groupMembers.contactId.equalsExp(contacts.userId),
|
||||
useColumns: false,
|
||||
),
|
||||
])
|
||||
..orderBy([OrderingTerm.desc(groupMembers.lastMessage)])
|
||||
..where(groupMembers.groupId.equals(groupId)));
|
||||
final query =
|
||||
(select(contacts).join([
|
||||
leftOuterJoin(
|
||||
groupMembers,
|
||||
groupMembers.contactId.equalsExp(contacts.userId),
|
||||
useColumns: false,
|
||||
),
|
||||
])
|
||||
..orderBy([OrderingTerm.desc(groupMembers.lastMessage)])
|
||||
..where(groupMembers.groupId.equals(groupId)));
|
||||
return query.map((row) => row.readTable(contacts)).get();
|
||||
}
|
||||
|
||||
Stream<List<Contact>> watchGroupContact(String groupId) {
|
||||
final query = (select(contacts).join([
|
||||
leftOuterJoin(
|
||||
groupMembers,
|
||||
groupMembers.contactId.equalsExp(contacts.userId),
|
||||
useColumns: false,
|
||||
),
|
||||
])
|
||||
..orderBy([OrderingTerm.desc(groupMembers.lastMessage)])
|
||||
..where(groupMembers.groupId.equals(groupId)));
|
||||
final query =
|
||||
(select(contacts).join([
|
||||
leftOuterJoin(
|
||||
groupMembers,
|
||||
groupMembers.contactId.equalsExp(contacts.userId),
|
||||
useColumns: false,
|
||||
),
|
||||
])
|
||||
..orderBy([OrderingTerm.desc(groupMembers.lastMessage)])
|
||||
..where(groupMembers.groupId.equals(groupId)));
|
||||
return query.map((row) => row.readTable(contacts)).watch();
|
||||
}
|
||||
|
||||
Stream<List<(Contact, GroupMember)>> watchGroupMembers(String groupId) {
|
||||
final query =
|
||||
(select(groupMembers)..where((t) => t.groupId.equals(groupId))).join([
|
||||
leftOuterJoin(
|
||||
contacts,
|
||||
contacts.userId.equalsExp(groupMembers.contactId),
|
||||
),
|
||||
]);
|
||||
leftOuterJoin(
|
||||
contacts,
|
||||
contacts.userId.equalsExp(groupMembers.contactId),
|
||||
),
|
||||
]);
|
||||
return query
|
||||
.map((row) => (row.readTable(contacts), row.readTable(groupMembers)))
|
||||
.watch();
|
||||
}
|
||||
|
||||
Stream<List<Group>> watchGroupsForShareImage() {
|
||||
return (select(groups)
|
||||
..where(
|
||||
(g) => g.leftGroup.equals(false) & g.deletedContent.equals(false),
|
||||
))
|
||||
return (select(groups)..where(
|
||||
(g) => g.leftGroup.equals(false) & g.deletedContent.equals(false),
|
||||
))
|
||||
.watch();
|
||||
}
|
||||
|
||||
Stream<List<GroupMember>> watchContactGroupMember(int contactId) {
|
||||
return (select(groupMembers)
|
||||
..where(
|
||||
(g) => g.contactId.equals(contactId),
|
||||
))
|
||||
return (select(groupMembers)..where(
|
||||
(g) => g.contactId.equals(contactId),
|
||||
))
|
||||
.watch();
|
||||
}
|
||||
|
||||
Stream<Group?> watchGroup(String groupId) {
|
||||
return (select(groups)..where((t) => t.groupId.equals(groupId)))
|
||||
.watchSingleOrNull();
|
||||
return (select(
|
||||
groups,
|
||||
)..where((t) => t.groupId.equals(groupId))).watchSingleOrNull();
|
||||
}
|
||||
|
||||
Stream<Group?> watchDirectChat(int contactId) {
|
||||
final groupId = getUUIDforDirectChat(contactId, gUser.userId);
|
||||
return (select(groups)..where((t) => t.groupId.equals(groupId)))
|
||||
.watchSingleOrNull();
|
||||
return (select(
|
||||
groups,
|
||||
)..where((t) => t.groupId.equals(groupId))).watchSingleOrNull();
|
||||
}
|
||||
|
||||
Stream<List<Group>> watchGroupsForChatList() {
|
||||
|
|
@ -228,18 +230,18 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
}
|
||||
|
||||
Future<Group?> getGroup(String groupId) {
|
||||
return (select(groups)..where((t) => t.groupId.equals(groupId)))
|
||||
.getSingleOrNull();
|
||||
return (select(
|
||||
groups,
|
||||
)..where((t) => t.groupId.equals(groupId))).getSingleOrNull();
|
||||
}
|
||||
|
||||
Stream<int> watchFlameCounter(String groupId) {
|
||||
return (select(groups)
|
||||
..where(
|
||||
(u) =>
|
||||
u.groupId.equals(groupId) &
|
||||
u.lastMessageReceived.isNotNull() &
|
||||
u.lastMessageSend.isNotNull(),
|
||||
))
|
||||
return (select(groups)..where(
|
||||
(u) =>
|
||||
u.groupId.equals(groupId) &
|
||||
u.lastMessageReceived.isNotNull() &
|
||||
u.lastMessageSend.isNotNull(),
|
||||
))
|
||||
.watchSingleOrNull()
|
||||
.asyncMap(getFlameCounterFromGroup);
|
||||
}
|
||||
|
|
@ -253,24 +255,23 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
}
|
||||
|
||||
Future<List<Group>> getAllNotJoinedGroups() {
|
||||
return (select(groups)
|
||||
..where(
|
||||
(t) => t.joinedGroup.equals(false) & t.isDirectChat.equals(false),
|
||||
))
|
||||
return (select(groups)..where(
|
||||
(t) => t.joinedGroup.equals(false) & t.isDirectChat.equals(false),
|
||||
))
|
||||
.get();
|
||||
}
|
||||
|
||||
Future<List<GroupMember>> getAllGroupMemberWithoutPublicKey() async {
|
||||
try {
|
||||
final query = ((select(groupMembers)
|
||||
..where((t) => t.groupPublicKey.isNull()))
|
||||
.join([
|
||||
leftOuterJoin(
|
||||
groups,
|
||||
groups.groupId.equalsExp(groupMembers.groupId),
|
||||
),
|
||||
])
|
||||
..where(groups.isDirectChat.isNull()));
|
||||
final query =
|
||||
((select(groupMembers)..where((t) => t.groupPublicKey.isNull())).join(
|
||||
[
|
||||
leftOuterJoin(
|
||||
groups,
|
||||
groups.groupId.equalsExp(groupMembers.groupId),
|
||||
),
|
||||
],
|
||||
)..where(groups.isDirectChat.isNull()));
|
||||
return query.map((row) => row.readTable(groupMembers)).get();
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
|
|
@ -281,12 +282,11 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
Future<Group?> getDirectChat(int userId) async {
|
||||
final query =
|
||||
((select(groups)..where((t) => t.isDirectChat.equals(true))).join([
|
||||
leftOuterJoin(
|
||||
groupMembers,
|
||||
groupMembers.groupId.equalsExp(groups.groupId),
|
||||
),
|
||||
])
|
||||
..where(groupMembers.contactId.equals(userId)));
|
||||
leftOuterJoin(
|
||||
groupMembers,
|
||||
groupMembers.groupId.equalsExp(groups.groupId),
|
||||
),
|
||||
])..where(groupMembers.contactId.equals(userId)));
|
||||
|
||||
return query.map((row) => row.readTable(groups)).getSingleOrNull();
|
||||
}
|
||||
|
|
@ -304,12 +304,11 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
|||
String groupId,
|
||||
DateTime newLastMessage,
|
||||
) async {
|
||||
await (update(groups)
|
||||
..where(
|
||||
(t) =>
|
||||
t.groupId.equals(groupId) &
|
||||
(t.lastMessageExchange.isSmallerThanValue(newLastMessage)),
|
||||
))
|
||||
await (update(groups)..where(
|
||||
(t) =>
|
||||
t.groupId.equals(groupId) &
|
||||
(t.lastMessageExchange.isSmallerThanValue(newLastMessage)),
|
||||
))
|
||||
.write(GroupsCompanion(lastMessageExchange: Value(newLastMessage)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,5 +22,7 @@ class GroupsDaoManager {
|
|||
$$GroupMembersTableTableManager(_db.attachedDatabase, _db.groupMembers);
|
||||
$$GroupHistoriesTableTableManager get groupHistories =>
|
||||
$$GroupHistoriesTableTableManager(
|
||||
_db.attachedDatabase, _db.groupHistories);
|
||||
_db.attachedDatabase,
|
||||
_db.groupHistories,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
|||
mediaFiles.downloadState
|
||||
.equals(DownloadState.reuploadRequested.name)
|
||||
.not() &
|
||||
mediaFiles.uploadState
|
||||
.equals(UploadState.fileLimitReached.name)
|
||||
.not() &
|
||||
mediaFiles.uploadState
|
||||
.equals(UploadState.uploadLimitReached.name)
|
||||
.not() &
|
||||
mediaFiles.type.equals(MediaType.audio.name).not() &
|
||||
messages.openedAt.isNull() &
|
||||
messages.groupId.equals(groupId) &
|
||||
|
|
|
|||
|
|
@ -31,10 +31,14 @@ class MessagesDaoManager {
|
|||
$$ReactionsTableTableManager(_db.attachedDatabase, _db.reactions);
|
||||
$$MessageHistoriesTableTableManager get messageHistories =>
|
||||
$$MessageHistoriesTableTableManager(
|
||||
_db.attachedDatabase, _db.messageHistories);
|
||||
_db.attachedDatabase,
|
||||
_db.messageHistories,
|
||||
);
|
||||
$$GroupMembersTableTableManager get groupMembers =>
|
||||
$$GroupMembersTableTableManager(_db.attachedDatabase, _db.groupMembers);
|
||||
$$MessageActionsTableTableManager get messageActions =>
|
||||
$$MessageActionsTableTableManager(
|
||||
_db.attachedDatabase, _db.messageActions);
|
||||
_db.attachedDatabase,
|
||||
_db.messageActions,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
|||
ReceiptsDao(super.db);
|
||||
|
||||
Future<void> confirmReceipt(String receiptId, int fromUserId) async {
|
||||
final receipt = await (select(receipts)
|
||||
..where(
|
||||
(t) =>
|
||||
t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId),
|
||||
))
|
||||
.getSingleOrNull();
|
||||
final receipt =
|
||||
await (select(receipts)..where(
|
||||
(t) =>
|
||||
t.receiptId.equals(receiptId) &
|
||||
t.contactId.equals(fromUserId),
|
||||
))
|
||||
.getSingleOrNull();
|
||||
|
||||
if (receipt == null) return;
|
||||
|
||||
|
|
@ -37,31 +38,27 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
|||
await handleMediaRelatedResponseFromReceiver(receipt.messageId!);
|
||||
}
|
||||
|
||||
await (delete(receipts)
|
||||
..where(
|
||||
(t) =>
|
||||
t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId),
|
||||
))
|
||||
await (delete(receipts)..where(
|
||||
(t) => t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId),
|
||||
))
|
||||
.go();
|
||||
}
|
||||
|
||||
Future<void> deleteReceipt(String receiptId) async {
|
||||
await (delete(receipts)
|
||||
..where(
|
||||
(t) => t.receiptId.equals(receiptId),
|
||||
))
|
||||
await (delete(receipts)..where(
|
||||
(t) => t.receiptId.equals(receiptId),
|
||||
))
|
||||
.go();
|
||||
}
|
||||
|
||||
Future<void> purgeReceivedReceipts() async {
|
||||
await (delete(receivedReceipts)
|
||||
..where(
|
||||
(t) => (t.createdAt.isSmallerThanValue(
|
||||
clock.now().subtract(
|
||||
const Duration(days: 25),
|
||||
),
|
||||
)),
|
||||
))
|
||||
await (delete(receivedReceipts)..where(
|
||||
(t) => (t.createdAt.isSmallerThanValue(
|
||||
clock.now().subtract(
|
||||
const Duration(days: 25),
|
||||
),
|
||||
)),
|
||||
))
|
||||
.go();
|
||||
}
|
||||
|
||||
|
|
@ -74,8 +71,9 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
|||
);
|
||||
}
|
||||
final id = await into(receipts).insert(insertEntry);
|
||||
return await (select(receipts)..where((t) => t.rowId.equals(id)))
|
||||
.getSingle();
|
||||
return await (select(
|
||||
receipts,
|
||||
)..where((t) => t.rowId.equals(id))).getSingle();
|
||||
} catch (e) {
|
||||
// ignore error, receipts is already in the database...
|
||||
return null;
|
||||
|
|
@ -84,10 +82,9 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
|||
|
||||
Future<Receipt?> getReceiptById(String receiptId) async {
|
||||
try {
|
||||
return await (select(receipts)
|
||||
..where(
|
||||
(t) => t.receiptId.equals(receiptId),
|
||||
))
|
||||
return await (select(receipts)..where(
|
||||
(t) => t.receiptId.equals(receiptId),
|
||||
))
|
||||
.getSingleOrNull();
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
|
|
@ -97,19 +94,20 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
|||
|
||||
Future<List<Receipt>> getReceiptsForRetransmission() async {
|
||||
final markedRetriesTime = clock.now().subtract(
|
||||
const Duration(
|
||||
// give the server time to transmit all messages to the client
|
||||
seconds: 20,
|
||||
),
|
||||
);
|
||||
return (select(receipts)
|
||||
..where(
|
||||
(t) =>
|
||||
t.ackByServerAt.isNull() |
|
||||
t.markForRetry.isSmallerThanValue(markedRetriesTime) |
|
||||
t.markForRetryAfterAccepted
|
||||
.isSmallerThanValue(markedRetriesTime),
|
||||
))
|
||||
const Duration(
|
||||
// give the server time to transmit all messages to the client
|
||||
seconds: 20,
|
||||
),
|
||||
);
|
||||
return (select(receipts)..where(
|
||||
(t) =>
|
||||
(t.ackByServerAt.isNull() |
|
||||
t.markForRetry.isSmallerThanValue(markedRetriesTime) |
|
||||
t.markForRetryAfterAccepted.isSmallerThanValue(
|
||||
markedRetriesTime,
|
||||
)) &
|
||||
t.willBeRetriedByMediaUpload.equals(false),
|
||||
))
|
||||
.get();
|
||||
}
|
||||
|
||||
|
|
@ -121,8 +119,9 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
|||
String receiptId,
|
||||
ReceiptsCompanion updates,
|
||||
) async {
|
||||
await (update(receipts)..where((c) => c.receiptId.equals(receiptId)))
|
||||
.write(updates);
|
||||
await (update(
|
||||
receipts,
|
||||
)..where((c) => c.receiptId.equals(receiptId))).write(updates);
|
||||
}
|
||||
|
||||
Future<void> updateReceiptWidthUserId(
|
||||
|
|
@ -130,31 +129,35 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
|||
String receiptId,
|
||||
ReceiptsCompanion updates,
|
||||
) async {
|
||||
await (update(receipts)
|
||||
..where(
|
||||
(c) =>
|
||||
c.receiptId.equals(receiptId) & c.contactId.equals(fromUserId),
|
||||
))
|
||||
await (update(receipts)..where(
|
||||
(c) => c.receiptId.equals(receiptId) & c.contactId.equals(fromUserId),
|
||||
))
|
||||
.write(updates);
|
||||
}
|
||||
|
||||
Future<void> markMessagesForRetry(int contactId) async {
|
||||
await (update(receipts)..where((c) => c.contactId.equals(contactId))).write(
|
||||
ReceiptsCompanion(
|
||||
markForRetry: Value(clock.now()),
|
||||
),
|
||||
);
|
||||
await (update(receipts)..where(
|
||||
(c) =>
|
||||
c.contactId.equals(contactId) &
|
||||
c.willBeRetriedByMediaUpload.equals(false),
|
||||
))
|
||||
.write(
|
||||
ReceiptsCompanion(
|
||||
markForRetry: Value(clock.now()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> isDuplicated(String receiptId) async {
|
||||
return await (select(receivedReceipts)
|
||||
..where((t) => t.receiptId.equals(receiptId)))
|
||||
.getSingleOrNull() !=
|
||||
return await (select(
|
||||
receivedReceipts,
|
||||
)..where((t) => t.receiptId.equals(receiptId))).getSingleOrNull() !=
|
||||
null;
|
||||
}
|
||||
|
||||
Future<void> gotReceipt(String receiptId) async {
|
||||
await into(receivedReceipts)
|
||||
.insert(ReceivedReceiptsCompanion(receiptId: Value(receiptId)));
|
||||
await into(
|
||||
receivedReceipts,
|
||||
).insert(ReceivedReceiptsCompanion(receiptId: Value(receiptId)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,12 @@ class ReceiptsDaoManager {
|
|||
$$ReceiptsTableTableManager(_db.attachedDatabase, _db.receipts);
|
||||
$$MessageActionsTableTableManager get messageActions =>
|
||||
$$MessageActionsTableTableManager(
|
||||
_db.attachedDatabase, _db.messageActions);
|
||||
_db.attachedDatabase,
|
||||
_db.messageActions,
|
||||
);
|
||||
$$ReceivedReceiptsTableTableManager get receivedReceipts =>
|
||||
$$ReceivedReceiptsTableTableManager(
|
||||
_db.attachedDatabase, _db.receivedReceipts);
|
||||
_db.attachedDatabase,
|
||||
_db.receivedReceipts,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
2075
lib/src/database/schemas/twonly_db/drift_schema_v10.json
Normal file
2075
lib/src/database/schemas/twonly_db/drift_schema_v10.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -20,6 +20,9 @@ class Receipts extends Table {
|
|||
BoolColumn get contactWillSendsReceipt =>
|
||||
boolean().withDefault(const Constant(true))();
|
||||
|
||||
BoolColumn get willBeRetriedByMediaUpload =>
|
||||
boolean().withDefault(const Constant(false))();
|
||||
|
||||
DateTimeColumn get markForRetry => dateTime().nullable()();
|
||||
DateTimeColumn get markForRetryAfterAccepted => dateTime().nullable()();
|
||||
|
||||
|
|
|
|||
|
|
@ -54,15 +54,15 @@ part 'twonly.db.g.dart';
|
|||
)
|
||||
class TwonlyDB extends _$TwonlyDB {
|
||||
TwonlyDB([QueryExecutor? e])
|
||||
: super(
|
||||
e ?? _openConnection(),
|
||||
);
|
||||
: super(
|
||||
e ?? _openConnection(),
|
||||
);
|
||||
|
||||
// ignore: matching_super_parameters
|
||||
TwonlyDB.forTesting(DatabaseConnection super.connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 9;
|
||||
int get schemaVersion => 10;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return driftDatabase(
|
||||
|
|
@ -137,6 +137,12 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
schema.mediaFiles.preProgressingProcess,
|
||||
);
|
||||
},
|
||||
from9To10: (m, schema) async {
|
||||
await m.addColumn(
|
||||
schema.receipts,
|
||||
schema.receipts.willBeRetriedByMediaUpload,
|
||||
);
|
||||
},
|
||||
)(m, from, to);
|
||||
},
|
||||
);
|
||||
|
|
@ -160,21 +166,20 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
}
|
||||
|
||||
Future<void> deleteDataForTwonlySafe() async {
|
||||
await (delete(messages)
|
||||
..where(
|
||||
(t) => (t.mediaStored.equals(false) &
|
||||
t.isDeletedFromSender.equals(false)),
|
||||
))
|
||||
await (delete(messages)..where(
|
||||
(t) =>
|
||||
(t.mediaStored.equals(false) &
|
||||
t.isDeletedFromSender.equals(false)),
|
||||
))
|
||||
.go();
|
||||
await update(messages).write(
|
||||
const MessagesCompanion(
|
||||
downloadToken: Value(null),
|
||||
),
|
||||
);
|
||||
await (delete(mediaFiles)
|
||||
..where(
|
||||
(t) => (t.stored.equals(false)),
|
||||
))
|
||||
await (delete(mediaFiles)..where(
|
||||
(t) => (t.stored.equals(false)),
|
||||
))
|
||||
.go();
|
||||
await delete(receipts).go();
|
||||
await delete(receivedReceipts).go();
|
||||
|
|
@ -184,14 +189,13 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
senderProfileCounter: Value(0),
|
||||
),
|
||||
);
|
||||
await (delete(signalPreKeyStores)
|
||||
..where(
|
||||
(t) => (t.createdAt.isSmallerThanValue(
|
||||
clock.now().subtract(
|
||||
const Duration(days: 25),
|
||||
),
|
||||
)),
|
||||
))
|
||||
await (delete(signalPreKeyStores)..where(
|
||||
(t) => (t.createdAt.isSmallerThanValue(
|
||||
clock.now().subtract(
|
||||
const Duration(days: 25),
|
||||
),
|
||||
)),
|
||||
))
|
||||
.go();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -64,7 +64,7 @@ import 'app_localizations_sv.dart';
|
|||
/// property.
|
||||
abstract class AppLocalizations {
|
||||
AppLocalizations(String locale)
|
||||
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
|
||||
final String localeName;
|
||||
|
||||
|
|
@ -87,17 +87,17 @@ abstract class AppLocalizations {
|
|||
/// of delegates is preferred or required.
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
|
||||
<LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
|
||||
/// A list of this localizations delegate's supported locales.
|
||||
static const List<Locale> supportedLocales = <Locale>[
|
||||
Locale('de'),
|
||||
Locale('en'),
|
||||
Locale('sv')
|
||||
Locale('sv'),
|
||||
];
|
||||
|
||||
/// No description provided for @registerTitle.
|
||||
|
|
@ -3088,8 +3088,9 @@ AppLocalizations lookupAppLocalizations(Locale locale) {
|
|||
}
|
||||
|
||||
throw FlutterError(
|
||||
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
|
||||
'an issue with the localizations generation tool. Please file an issue '
|
||||
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||
'that was used.');
|
||||
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
|
||||
'an issue with the localizations generation tool. Please file an issue '
|
||||
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||
'that was used.',
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,16 @@ part of 'signal_identity.dart';
|
|||
|
||||
SignalIdentity _$SignalIdentityFromJson(Map<String, dynamic> json) =>
|
||||
SignalIdentity(
|
||||
identityKeyPairU8List: const Uint8ListConverter()
|
||||
.fromJson(json['identityKeyPairU8List'] as String),
|
||||
identityKeyPairU8List: const Uint8ListConverter().fromJson(
|
||||
json['identityKeyPairU8List'] as String,
|
||||
),
|
||||
registrationId: (json['registrationId'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SignalIdentityToJson(SignalIdentity instance) =>
|
||||
<String, dynamic>{
|
||||
'registrationId': instance.registrationId,
|
||||
'identityKeyPairU8List':
|
||||
const Uint8ListConverter().toJson(instance.identityKeyPairU8List),
|
||||
'identityKeyPairU8List': const Uint8ListConverter().toJson(
|
||||
instance.identityKeyPairU8List,
|
||||
),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ part of 'userdata.dart';
|
|||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
||||
userId: (json['userId'] as num).toInt(),
|
||||
username: json['username'] as String,
|
||||
displayName: json['displayName'] as String,
|
||||
subscriptionPlan: json['subscriptionPlan'] as String? ?? 'Free',
|
||||
)
|
||||
UserData _$UserDataFromJson(Map<String, dynamic> json) =>
|
||||
UserData(
|
||||
userId: (json['userId'] as num).toInt(),
|
||||
username: json['username'] as String,
|
||||
displayName: json['displayName'] as String,
|
||||
subscriptionPlan: json['subscriptionPlan'] as String? ?? 'Free',
|
||||
)
|
||||
..avatarSvg = json['avatarSvg'] as String?
|
||||
..avatarJson = json['avatarJson'] as String?
|
||||
..appVersion = (json['appVersion'] as num?)?.toInt() ?? 0
|
||||
|
|
@ -25,7 +26,7 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
|||
..todaysImageCounter = (json['todaysImageCounter'] as num?)?.toInt()
|
||||
..themeMode =
|
||||
$enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ??
|
||||
ThemeMode.system
|
||||
ThemeMode.system
|
||||
..defaultShowTime = (json['defaultShowTime'] as num?)?.toInt()
|
||||
..requestedAudioPermission =
|
||||
json['requestedAudioPermission'] as bool? ?? false
|
||||
|
|
@ -38,9 +39,11 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
|||
.toList()
|
||||
..autoDownloadOptions =
|
||||
(json['autoDownloadOptions'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) =>
|
||||
MapEntry(k, (e as List<dynamic>).map((e) => e as String).toList()),
|
||||
)
|
||||
(k, e) => MapEntry(
|
||||
k,
|
||||
(e as List<dynamic>).map((e) => e as String).toList(),
|
||||
),
|
||||
)
|
||||
..storeMediaFilesInGallery =
|
||||
json['storeMediaFilesInGallery'] as bool? ?? false
|
||||
..autoStoreAllSendUnlimitedMediaFiles =
|
||||
|
|
@ -53,8 +56,8 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
|||
..myBestFriendGroupId = json['myBestFriendGroupId'] as String?
|
||||
..signalLastSignedPreKeyUpdated =
|
||||
json['signalLastSignedPreKeyUpdated'] == null
|
||||
? null
|
||||
: DateTime.parse(json['signalLastSignedPreKeyUpdated'] as String)
|
||||
? null
|
||||
: DateTime.parse(json['signalLastSignedPreKeyUpdated'] as String)
|
||||
..allowErrorTrackingViaSentry =
|
||||
json['allowErrorTrackingViaSentry'] as bool? ?? false
|
||||
..currentPreKeyIndexStart =
|
||||
|
|
@ -75,7 +78,8 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
|||
..twonlySafeBackup = json['twonlySafeBackup'] == null
|
||||
? null
|
||||
: TwonlySafeBackup.fromJson(
|
||||
json['twonlySafeBackup'] as Map<String, dynamic>)
|
||||
json['twonlySafeBackup'] as Map<String, dynamic>,
|
||||
)
|
||||
..askedForUserStudyPermission =
|
||||
json['askedForUserStudyPermission'] as bool? ?? false
|
||||
..userStudyParticipantsToken =
|
||||
|
|
@ -85,52 +89,51 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
|||
: DateTime.parse(json['lastUserStudyDataUpload'] as String);
|
||||
|
||||
Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
|
||||
'userId': instance.userId,
|
||||
'username': instance.username,
|
||||
'displayName': instance.displayName,
|
||||
'avatarSvg': instance.avatarSvg,
|
||||
'avatarJson': instance.avatarJson,
|
||||
'appVersion': instance.appVersion,
|
||||
'avatarCounter': instance.avatarCounter,
|
||||
'isDeveloper': instance.isDeveloper,
|
||||
'deviceId': instance.deviceId,
|
||||
'subscriptionPlan': instance.subscriptionPlan,
|
||||
'subscriptionPlanIdStore': instance.subscriptionPlanIdStore,
|
||||
'lastImageSend': instance.lastImageSend?.toIso8601String(),
|
||||
'todaysImageCounter': instance.todaysImageCounter,
|
||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
||||
'defaultShowTime': instance.defaultShowTime,
|
||||
'requestedAudioPermission': instance.requestedAudioPermission,
|
||||
'showFeedbackShortcut': instance.showFeedbackShortcut,
|
||||
'showShowImagePreviewWhenSending':
|
||||
instance.showShowImagePreviewWhenSending,
|
||||
'startWithCameraOpen': instance.startWithCameraOpen,
|
||||
'preSelectedEmojies': instance.preSelectedEmojies,
|
||||
'autoDownloadOptions': instance.autoDownloadOptions,
|
||||
'storeMediaFilesInGallery': instance.storeMediaFilesInGallery,
|
||||
'autoStoreAllSendUnlimitedMediaFiles':
|
||||
instance.autoStoreAllSendUnlimitedMediaFiles,
|
||||
'lastPlanBallance': instance.lastPlanBallance,
|
||||
'additionalUserInvites': instance.additionalUserInvites,
|
||||
'tutorialDisplayed': instance.tutorialDisplayed,
|
||||
'myBestFriendGroupId': instance.myBestFriendGroupId,
|
||||
'signalLastSignedPreKeyUpdated':
|
||||
instance.signalLastSignedPreKeyUpdated?.toIso8601String(),
|
||||
'allowErrorTrackingViaSentry': instance.allowErrorTrackingViaSentry,
|
||||
'currentPreKeyIndexStart': instance.currentPreKeyIndexStart,
|
||||
'currentSignedPreKeyIndexStart': instance.currentSignedPreKeyIndexStart,
|
||||
'lastChangeLogHash': instance.lastChangeLogHash,
|
||||
'hideChangeLog': instance.hideChangeLog,
|
||||
'updateFCMToken': instance.updateFCMToken,
|
||||
'nextTimeToShowBackupNotice':
|
||||
instance.nextTimeToShowBackupNotice?.toIso8601String(),
|
||||
'backupServer': instance.backupServer,
|
||||
'twonlySafeBackup': instance.twonlySafeBackup,
|
||||
'askedForUserStudyPermission': instance.askedForUserStudyPermission,
|
||||
'userStudyParticipantsToken': instance.userStudyParticipantsToken,
|
||||
'lastUserStudyDataUpload':
|
||||
instance.lastUserStudyDataUpload?.toIso8601String(),
|
||||
};
|
||||
'userId': instance.userId,
|
||||
'username': instance.username,
|
||||
'displayName': instance.displayName,
|
||||
'avatarSvg': instance.avatarSvg,
|
||||
'avatarJson': instance.avatarJson,
|
||||
'appVersion': instance.appVersion,
|
||||
'avatarCounter': instance.avatarCounter,
|
||||
'isDeveloper': instance.isDeveloper,
|
||||
'deviceId': instance.deviceId,
|
||||
'subscriptionPlan': instance.subscriptionPlan,
|
||||
'subscriptionPlanIdStore': instance.subscriptionPlanIdStore,
|
||||
'lastImageSend': instance.lastImageSend?.toIso8601String(),
|
||||
'todaysImageCounter': instance.todaysImageCounter,
|
||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
||||
'defaultShowTime': instance.defaultShowTime,
|
||||
'requestedAudioPermission': instance.requestedAudioPermission,
|
||||
'showFeedbackShortcut': instance.showFeedbackShortcut,
|
||||
'showShowImagePreviewWhenSending': instance.showShowImagePreviewWhenSending,
|
||||
'startWithCameraOpen': instance.startWithCameraOpen,
|
||||
'preSelectedEmojies': instance.preSelectedEmojies,
|
||||
'autoDownloadOptions': instance.autoDownloadOptions,
|
||||
'storeMediaFilesInGallery': instance.storeMediaFilesInGallery,
|
||||
'autoStoreAllSendUnlimitedMediaFiles':
|
||||
instance.autoStoreAllSendUnlimitedMediaFiles,
|
||||
'lastPlanBallance': instance.lastPlanBallance,
|
||||
'additionalUserInvites': instance.additionalUserInvites,
|
||||
'tutorialDisplayed': instance.tutorialDisplayed,
|
||||
'myBestFriendGroupId': instance.myBestFriendGroupId,
|
||||
'signalLastSignedPreKeyUpdated': instance.signalLastSignedPreKeyUpdated
|
||||
?.toIso8601String(),
|
||||
'allowErrorTrackingViaSentry': instance.allowErrorTrackingViaSentry,
|
||||
'currentPreKeyIndexStart': instance.currentPreKeyIndexStart,
|
||||
'currentSignedPreKeyIndexStart': instance.currentSignedPreKeyIndexStart,
|
||||
'lastChangeLogHash': instance.lastChangeLogHash,
|
||||
'hideChangeLog': instance.hideChangeLog,
|
||||
'updateFCMToken': instance.updateFCMToken,
|
||||
'nextTimeToShowBackupNotice': instance.nextTimeToShowBackupNotice
|
||||
?.toIso8601String(),
|
||||
'backupServer': instance.backupServer,
|
||||
'twonlySafeBackup': instance.twonlySafeBackup,
|
||||
'askedForUserStudyPermission': instance.askedForUserStudyPermission,
|
||||
'userStudyParticipantsToken': instance.userStudyParticipantsToken,
|
||||
'lastUserStudyDataUpload': instance.lastUserStudyDataUpload
|
||||
?.toIso8601String(),
|
||||
};
|
||||
|
||||
const _$ThemeModeEnumMap = {
|
||||
ThemeMode.system: 'system',
|
||||
|
|
@ -140,16 +143,18 @@ const _$ThemeModeEnumMap = {
|
|||
|
||||
TwonlySafeBackup _$TwonlySafeBackupFromJson(Map<String, dynamic> json) =>
|
||||
TwonlySafeBackup(
|
||||
backupId: (json['backupId'] as List<dynamic>)
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
encryptionKey: (json['encryptionKey'] as List<dynamic>)
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
)
|
||||
backupId: (json['backupId'] as List<dynamic>)
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
encryptionKey: (json['encryptionKey'] as List<dynamic>)
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
)
|
||||
..lastBackupSize = (json['lastBackupSize'] as num).toInt()
|
||||
..backupUploadState =
|
||||
$enumDecode(_$LastBackupUploadStateEnumMap, json['backupUploadState'])
|
||||
..backupUploadState = $enumDecode(
|
||||
_$LastBackupUploadStateEnumMap,
|
||||
json['backupUploadState'],
|
||||
)
|
||||
..lastBackupDone = json['lastBackupDone'] == null
|
||||
? null
|
||||
: DateTime.parse(json['lastBackupDone'] as String);
|
||||
|
|
@ -172,10 +177,10 @@ const _$LastBackupUploadStateEnumMap = {
|
|||
};
|
||||
|
||||
BackupServer _$BackupServerFromJson(Map<String, dynamic> json) => BackupServer(
|
||||
serverUrl: json['serverUrl'] as String,
|
||||
retentionDays: (json['retentionDays'] as num).toInt(),
|
||||
maxBackupBytes: (json['maxBackupBytes'] as num).toInt(),
|
||||
);
|
||||
serverUrl: json['serverUrl'] as String,
|
||||
retentionDays: (json['retentionDays'] as num).toInt(),
|
||||
maxBackupBytes: (json['maxBackupBytes'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BackupServerToJson(BackupServer instance) =>
|
||||
<String, dynamic>{
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import 'package:twonly/src/utils/misc.dart';
|
|||
import 'package:workmanager/workmanager.dart' hide TaskStatus;
|
||||
|
||||
Future<void> finishStartedPreprocessing() async {
|
||||
final mediaFiles =
|
||||
await twonlyDB.mediaFilesDao.getAllMediaFilesPendingUpload();
|
||||
final mediaFiles = await twonlyDB.mediaFilesDao
|
||||
.getAllMediaFilesPendingUpload();
|
||||
|
||||
Log.info('There are ${mediaFiles.length} media files pending');
|
||||
|
||||
|
|
@ -62,8 +62,9 @@ Future<void> finishStartedPreprocessing() async {
|
|||
/// For example because the background_downloader plugin has not yet reported the finished upload.
|
||||
/// In case the the message receipts or a reaction was received, mark the media file as been uploaded.
|
||||
Future<void> handleMediaRelatedResponseFromReceiver(String messageId) async {
|
||||
final message =
|
||||
await twonlyDB.messagesDao.getMessageById(messageId).getSingleOrNull();
|
||||
final message = await twonlyDB.messagesDao
|
||||
.getMessageById(messageId)
|
||||
.getSingleOrNull();
|
||||
if (message == null || message.mediaId == null) return;
|
||||
final media = await twonlyDB.mediaFilesDao.getMediaFileById(message.mediaId!);
|
||||
if (media == null) return;
|
||||
|
|
@ -84,11 +85,13 @@ Future<void> markUploadAsSuccessful(MediaFile media) async {
|
|||
|
||||
/// As the messages where send in a bulk acknowledge all messages.
|
||||
|
||||
final messages =
|
||||
await twonlyDB.messagesDao.getMessagesByMediaId(media.mediaId);
|
||||
final messages = await twonlyDB.messagesDao.getMessagesByMediaId(
|
||||
media.mediaId,
|
||||
);
|
||||
for (final message in messages) {
|
||||
final contacts =
|
||||
await twonlyDB.groupsDao.getGroupNonLeftMembers(message.groupId);
|
||||
final contacts = await twonlyDB.groupsDao.getGroupNonLeftMembers(
|
||||
message.groupId,
|
||||
);
|
||||
for (final contact in contacts) {
|
||||
await twonlyDB.messagesDao.handleMessageAckByServer(
|
||||
contact.contactId,
|
||||
|
|
@ -147,8 +150,9 @@ Future<void> insertMediaFileInMessagesTable(
|
|||
groupId: Value(groupId),
|
||||
mediaId: Value(mediaService.mediaFile.mediaId),
|
||||
type: Value(MessageType.media.name),
|
||||
additionalMessageData:
|
||||
Value.absentIfNull(additionalData?.writeToBuffer()),
|
||||
additionalMessageData: Value.absentIfNull(
|
||||
additionalData?.writeToBuffer(),
|
||||
),
|
||||
),
|
||||
);
|
||||
await twonlyDB.groupsDao.increaseLastMessageExchange(groupId, clock.now());
|
||||
|
|
@ -236,8 +240,9 @@ Future<void> _encryptMediaFiles(MediaFileService mediaService) async {
|
|||
|
||||
await mediaService.setEncryptedMac(Uint8List.fromList(secretBox.mac.bytes));
|
||||
|
||||
mediaService.encryptedPath
|
||||
.writeAsBytesSync(Uint8List.fromList(secretBox.cipherText));
|
||||
mediaService.encryptedPath.writeAsBytesSync(
|
||||
Uint8List.fromList(secretBox.cipherText),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _createUploadRequest(MediaFileService media) async {
|
||||
|
|
@ -245,8 +250,9 @@ Future<void> _createUploadRequest(MediaFileService media) async {
|
|||
|
||||
final messagesOnSuccess = <TextMessage>[];
|
||||
|
||||
final messages =
|
||||
await twonlyDB.messagesDao.getMessagesByMediaId(media.mediaFile.mediaId);
|
||||
final messages = await twonlyDB.messagesDao.getMessagesByMediaId(
|
||||
media.mediaFile.mediaId,
|
||||
);
|
||||
|
||||
if (messages.isEmpty) {
|
||||
// There where no user selected who should receive the image, so waiting with this step...
|
||||
|
|
@ -254,8 +260,9 @@ Future<void> _createUploadRequest(MediaFileService media) async {
|
|||
}
|
||||
|
||||
for (final message in messages) {
|
||||
final groupMembers =
|
||||
await twonlyDB.groupsDao.getGroupNonLeftMembers(message.groupId);
|
||||
final groupMembers = await twonlyDB.groupsDao.getGroupNonLeftMembers(
|
||||
message.groupId,
|
||||
);
|
||||
|
||||
if (media.mediaFile.reuploadRequestedBy == null) {
|
||||
await incFlameCounter(message.groupId, false, message.createdAt);
|
||||
|
|
@ -264,8 +271,9 @@ Future<void> _createUploadRequest(MediaFileService media) async {
|
|||
for (final groupMember in groupMembers) {
|
||||
/// only send the upload to the users
|
||||
if (media.mediaFile.reuploadRequestedBy != null) {
|
||||
if (!media.mediaFile.reuploadRequestedBy!
|
||||
.contains(groupMember.contactId)) {
|
||||
if (!media.mediaFile.reuploadRequestedBy!.contains(
|
||||
groupMember.contactId,
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -304,8 +312,9 @@ Future<void> _createUploadRequest(MediaFileService media) async {
|
|||
);
|
||||
|
||||
if (media.mediaFile.displayLimitInMilliseconds != null) {
|
||||
notEncryptedContent.media.displayLimitInMilliseconds =
|
||||
Int64(media.mediaFile.displayLimitInMilliseconds!);
|
||||
notEncryptedContent.media.displayLimitInMilliseconds = Int64(
|
||||
media.mediaFile.displayLimitInMilliseconds!,
|
||||
);
|
||||
}
|
||||
|
||||
final cipherText = await sendCipherText(
|
||||
|
|
@ -345,6 +354,14 @@ Future<void> _createUploadRequest(MediaFileService media) async {
|
|||
|
||||
if (uploadRequestBytes.length > 49_000_000) {
|
||||
await media.setUploadState(UploadState.fileLimitReached);
|
||||
|
||||
await twonlyDB.messagesDao.updateMessagesByMediaId(
|
||||
media.mediaFile.mediaId,
|
||||
MessagesCompanion(
|
||||
openedAt: Value(DateTime.now()),
|
||||
ackByServer: Value(DateTime.now()),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -355,8 +372,9 @@ Mutex protectUpload = Mutex();
|
|||
|
||||
Future<void> _uploadUploadRequest(MediaFileService media) async {
|
||||
await protectUpload.protect(() async {
|
||||
final currentMedia =
|
||||
await twonlyDB.mediaFilesDao.getMediaFileById(media.mediaFile.mediaId);
|
||||
final currentMedia = await twonlyDB.mediaFilesDao.getMediaFileById(
|
||||
media.mediaFile.mediaId,
|
||||
);
|
||||
|
||||
if (currentMedia == null ||
|
||||
currentMedia.uploadState == UploadState.backgroundUploadTaskStarted) {
|
||||
|
|
@ -364,8 +382,9 @@ Future<void> _uploadUploadRequest(MediaFileService media) async {
|
|||
return null;
|
||||
}
|
||||
|
||||
final apiAuthTokenRaw = await const FlutterSecureStorage()
|
||||
.read(key: SecureStorageKeys.apiAuthToken);
|
||||
final apiAuthTokenRaw = await const FlutterSecureStorage().read(
|
||||
key: SecureStorageKeys.apiAuthToken,
|
||||
);
|
||||
|
||||
if (apiAuthTokenRaw == null) {
|
||||
Log.error('api auth token not defined.');
|
||||
|
|
|
|||
|
|
@ -79,8 +79,9 @@ Future<(Uint8List, Uint8List?)?> tryToSendCompleteMessage({
|
|||
// ignore: parameter_assignments
|
||||
receiptId = receipt.receiptId;
|
||||
|
||||
final contact =
|
||||
await twonlyDB.contactsDao.getContactById(receipt.contactId);
|
||||
final contact = await twonlyDB.contactsDao.getContactById(
|
||||
receipt.contactId,
|
||||
);
|
||||
if (contact == null || contact.accountDeleted) {
|
||||
Log.warn('Will not send message again as user does not exist anymore.');
|
||||
await twonlyDB.receiptsDao.deleteReceipt(receiptId);
|
||||
|
|
@ -99,8 +100,9 @@ Future<(Uint8List, Uint8List?)?> tryToSendCompleteMessage({
|
|||
final message = pb.Message.fromBuffer(receipt.message)
|
||||
..receiptId = receiptId;
|
||||
|
||||
final encryptedContent =
|
||||
pb.EncryptedContent.fromBuffer(message.encryptedContent);
|
||||
final encryptedContent = pb.EncryptedContent.fromBuffer(
|
||||
message.encryptedContent,
|
||||
);
|
||||
|
||||
final pushNotification = await getPushNotificationFromEncryptedContent(
|
||||
receipt.contactId,
|
||||
|
|
@ -111,8 +113,10 @@ Future<(Uint8List, Uint8List?)?> tryToSendCompleteMessage({
|
|||
Uint8List? pushData;
|
||||
if (pushNotification != null && receipt.retryCount <= 3) {
|
||||
/// In case the message has to be resend more than three times, do not show a notification again...
|
||||
pushData =
|
||||
await encryptPushNotification(receipt.contactId, pushNotification);
|
||||
pushData = await encryptPushNotification(
|
||||
receipt.contactId,
|
||||
pushNotification,
|
||||
);
|
||||
}
|
||||
|
||||
if (message.type == pb.Message_Type.TEST_NOTIFICATION) {
|
||||
|
|
@ -331,7 +335,7 @@ Future<(Uint8List, Uint8List?)?> sendCipherText(
|
|||
contactId: Value(contactId),
|
||||
message: Value(response.writeToBuffer()),
|
||||
messageId: Value(messageId),
|
||||
ackByServerAt: Value(onlyReturnEncryptedData ? clock.now() : null),
|
||||
willBeRetriedByMediaUpload: Value(onlyReturnEncryptedData),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class FilterSkeleton extends StatelessWidget {
|
|||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(child: Container()),
|
||||
if (child != null) child!,
|
||||
?child,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -89,10 +89,11 @@ class _FilterLayerState extends State<FilterLayer> {
|
|||
}
|
||||
|
||||
Future<void> initAsync() async {
|
||||
final stickers = (await getStickerIndex())
|
||||
.where((x) => x.imageSrc.contains('/imagefilter/'))
|
||||
.toList()
|
||||
..sortBy((x) => x.imageSrc);
|
||||
final stickers =
|
||||
(await getStickerIndex())
|
||||
.where((x) => x.imageSrc.contains('/imagefilter/'))
|
||||
.toList()
|
||||
..sortBy((x) => x.imageSrc);
|
||||
|
||||
for (final sticker in stickers) {
|
||||
pages.insert(pages.length - 1, ImageFilter(imagePath: sticker.imageSrc));
|
||||
|
|
|
|||
|
|
@ -26,15 +26,17 @@ class _ShareAdditionalViewState extends State<ShareAdditionalView> {
|
|||
}
|
||||
|
||||
Future<void> openShareContactView() async {
|
||||
final selectedContacts = await context.navPush(
|
||||
SelectContactsView(
|
||||
text: SelectedContactViewText(
|
||||
title: context.lang.shareContactsTitle,
|
||||
submitButton: (_, __) => context.lang.shareContactsSubmit,
|
||||
submitIcon: FontAwesomeIcons.shareNodes,
|
||||
),
|
||||
),
|
||||
) as List<int>?;
|
||||
final selectedContacts =
|
||||
await context.navPush(
|
||||
SelectContactsView(
|
||||
text: SelectedContactViewText(
|
||||
title: context.lang.shareContactsTitle,
|
||||
submitButton: (_, _) => context.lang.shareContactsSubmit,
|
||||
submitIcon: FontAwesomeIcons.shareNodes,
|
||||
),
|
||||
),
|
||||
)
|
||||
as List<int>?;
|
||||
if (selectedContacts != null && selectedContacts.isNotEmpty) {
|
||||
await insertAndSendContactShareMessage(
|
||||
widget.group.groupId,
|
||||
|
|
|
|||
|
|
@ -101,8 +101,9 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
|||
|
||||
final mediaFile = message.mediaId == null
|
||||
? null
|
||||
: widget.mediaFiles
|
||||
.firstWhereOrNull((t) => t.mediaId == message.mediaId);
|
||||
: widget.mediaFiles.firstWhereOrNull(
|
||||
(t) => t.mediaId == message.mediaId,
|
||||
);
|
||||
|
||||
final color = getMessageColorFromType(message, mediaFile, context);
|
||||
|
||||
|
|
@ -144,8 +145,11 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
|||
}
|
||||
}
|
||||
case MessageSendState.send:
|
||||
icon =
|
||||
FaIcon(FontAwesomeIcons.solidPaperPlane, size: 12, color: color);
|
||||
icon = FaIcon(
|
||||
FontAwesomeIcons.solidPaperPlane,
|
||||
size: 12,
|
||||
color: color,
|
||||
);
|
||||
text = context.lang.messageSendState_Send;
|
||||
case MessageSendState.sending:
|
||||
icon = getLoaderIcon(color);
|
||||
|
|
@ -163,22 +167,9 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
|||
context.lang.uploadLimitReached,
|
||||
style: const TextStyle(fontSize: 9),
|
||||
);
|
||||
}
|
||||
|
||||
if (mediaFile.uploadState == UploadState.fileLimitReached) {
|
||||
icon = FaIcon(
|
||||
FontAwesomeIcons.triangleExclamation,
|
||||
size: 12,
|
||||
color: color,
|
||||
);
|
||||
|
||||
textWidget = Text(
|
||||
context.lang.fileLimitReached,
|
||||
style: const TextStyle(fontSize: 9),
|
||||
);
|
||||
|
||||
onTap = () => context.push(Routes.settingsSubscription);
|
||||
}
|
||||
|
||||
if (mediaFile.uploadState == UploadState.initialized) {
|
||||
text = context.lang.inProcess;
|
||||
}
|
||||
|
|
@ -211,13 +202,28 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
|||
}
|
||||
|
||||
if (mediaFile.downloadState == DownloadState.reuploadRequested) {
|
||||
icon =
|
||||
FaIcon(FontAwesomeIcons.clockRotateLeft, size: 12, color: color);
|
||||
icon = FaIcon(
|
||||
FontAwesomeIcons.clockRotateLeft,
|
||||
size: 12,
|
||||
color: color,
|
||||
);
|
||||
textWidget = Text(
|
||||
context.lang.retransmissionRequested,
|
||||
style: const TextStyle(fontSize: 9),
|
||||
);
|
||||
}
|
||||
if (mediaFile.uploadState == UploadState.fileLimitReached) {
|
||||
icon = FaIcon(
|
||||
FontAwesomeIcons.triangleExclamation,
|
||||
size: 12,
|
||||
color: color,
|
||||
);
|
||||
|
||||
textWidget = Text(
|
||||
context.lang.fileLimitReached,
|
||||
style: const TextStyle(fontSize: 9),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (message.isDeletedFromSender) {
|
||||
|
|
@ -240,10 +246,12 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
|||
if (!widget.messages.any((t) => t.openedAt == null)) {
|
||||
if (widget.lastReaction != null) {
|
||||
/// No messages are still open, so check if the reaction is the last message received.
|
||||
if (!widget.messages
|
||||
.any((m) => m.createdAt.isAfter(widget.lastReaction!.createdAt))) {
|
||||
if (EmojiAnimation.animatedIcons
|
||||
.containsKey(widget.lastReaction!.emoji)) {
|
||||
if (!widget.messages.any(
|
||||
(m) => m.createdAt.isAfter(widget.lastReaction!.createdAt),
|
||||
)) {
|
||||
if (EmojiAnimation.animatedIcons.containsKey(
|
||||
widget.lastReaction!.emoji,
|
||||
)) {
|
||||
icons = [
|
||||
SizedBox(
|
||||
height: 18,
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ class _AvatarIconState extends State<AvatarIcon> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
// ignore: strict_top_level_inference
|
||||
Widget errorBuilder(_, __, ___) {
|
||||
Widget errorBuilder(_, _, _) {
|
||||
return const SvgPicture(
|
||||
AssetBytesLoader('assets/images/default_avatar.svg.vec'),
|
||||
);
|
||||
|
|
@ -81,20 +80,20 @@ class _AvatarIconState extends State<AvatarIcon> {
|
|||
groupStream = twonlyDB.groupsDao
|
||||
.watchGroupContact(widget.group!.groupId)
|
||||
.listen((contacts) {
|
||||
_avatarContacts = [];
|
||||
if (contacts.length == 1) {
|
||||
if (contacts.first.avatarSvgCompressed != null) {
|
||||
_avatarContacts.add(contacts.first);
|
||||
}
|
||||
} else {
|
||||
for (final contact in contacts) {
|
||||
if (contact.avatarSvgCompressed != null) {
|
||||
_avatarContacts.add(contact);
|
||||
_avatarContacts = [];
|
||||
if (contacts.length == 1) {
|
||||
if (contacts.first.avatarSvgCompressed != null) {
|
||||
_avatarContacts.add(contacts.first);
|
||||
}
|
||||
} else {
|
||||
for (final contact in contacts) {
|
||||
if (contact.avatarSvgCompressed != null) {
|
||||
_avatarContacts.add(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(() {});
|
||||
});
|
||||
setState(() {});
|
||||
});
|
||||
} else if (widget.myAvatar) {
|
||||
_globalUserDataCallBackId = 'avatar_${getRandomString(10)}';
|
||||
globalUserDataChangedCallBack[_globalUserDataCallBackId!] = () {
|
||||
|
|
@ -113,11 +112,11 @@ class _AvatarIconState extends State<AvatarIcon> {
|
|||
contactStream = twonlyDB.contactsDao
|
||||
.watchContact(widget.contactId!)
|
||||
.listen((contact) {
|
||||
if (contact != null && contact.avatarSvgCompressed != null) {
|
||||
_avatarContacts = [contact];
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
if (contact != null && contact.avatarSvgCompressed != null) {
|
||||
_avatarContacts = [contact];
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class _ThreeRotatingDotsState extends State<ThreeRotatingDots>
|
|||
height: size,
|
||||
child: AnimatedBuilder(
|
||||
animation: _animationController,
|
||||
builder: (_, __) => Transform.translate(
|
||||
builder: (_, _) => Transform.translate(
|
||||
offset: Offset(0, size / 12),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
|
|
@ -110,7 +110,6 @@ class _ThreeRotatingDotsState extends State<ThreeRotatingDots>
|
|||
),
|
||||
|
||||
/// Next 3 dots
|
||||
|
||||
_BuildDot.second(
|
||||
controller: _animationController,
|
||||
beginAngle: 0,
|
||||
|
|
@ -217,9 +216,9 @@ class DrawDot extends StatelessWidget {
|
|||
required double dotSize,
|
||||
required this.color,
|
||||
super.key,
|
||||
}) : width = dotSize,
|
||||
height = dotSize,
|
||||
circular = true;
|
||||
}) : width = dotSize,
|
||||
height = dotSize,
|
||||
circular = true;
|
||||
|
||||
const DrawDot.elliptical({
|
||||
required this.width,
|
||||
|
|
|
|||
|
|
@ -569,8 +569,8 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: e8b6a650b9fbe76a077539272bbdd422509e6e44
|
||||
ref: "fix/lStar-not-found-error"
|
||||
resolved-ref: e926724e0c7e62bce4f94905f9805a264b736d11
|
||||
url: "https://github.com/yenchieh/flutter_android_volume_keydown.git"
|
||||
source: git
|
||||
version: "1.0.1"
|
||||
|
|
|
|||
10
pubspec.yaml
10
pubspec.yaml
|
|
@ -6,7 +6,7 @@ publish_to: 'none'
|
|||
version: 0.0.97+97
|
||||
|
||||
environment:
|
||||
sdk: ^3.6.0
|
||||
sdk: ^3.11.0
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
|
@ -161,13 +161,7 @@ dependency_overrides:
|
|||
flutter_android_volume_keydown:
|
||||
git:
|
||||
url: https://github.com/yenchieh/flutter_android_volume_keydown.git
|
||||
branch: fix/lStar-not-found-error
|
||||
# flutter_secure_storage_darwin:
|
||||
# git:
|
||||
# url: https://github.com/juliansteenbakker/flutter_secure_storage.git
|
||||
# ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
|
||||
# path: flutter_secure_storage_darwin/
|
||||
# hardcoding the mirror mode of the VideCapture to MIRROR_MODE_ON_FRONT_ONLY
|
||||
ref: fix/lStar-not-found-error
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.15
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import 'schema_v6.dart' as v6;
|
|||
import 'schema_v7.dart' as v7;
|
||||
import 'schema_v8.dart' as v8;
|
||||
import 'schema_v9.dart' as v9;
|
||||
import 'schema_v10.dart' as v10;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
|
|
@ -36,10 +37,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
|||
return v8.DatabaseAtV8(db);
|
||||
case 9:
|
||||
return v9.DatabaseAtV9(db);
|
||||
case 10:
|
||||
return v10.DatabaseAtV10(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
7318
test/drift/twonly_db/generated/schema_v10.dart
Normal file
7318
test/drift/twonly_db/generated/schema_v10.dart
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue