From 0b084f795ac2280fdfcd09d9c914f64bebdc965a Mon Sep 17 00:00:00 2001 From: otsmr Date: Sun, 16 Mar 2025 20:51:38 +0100 Subject: [PATCH] move signal to drift --- lib/globals.dart | 4 +- lib/main.dart | 9 +- lib/src/components/animate_icon.dart | 4 +- lib/src/components/best_friends_selector.dart | 7 +- lib/src/components/flame.dart | 2 +- .../components/message_send_state_icon.dart | 6 +- lib/src/components/permissions_view.dart | 25 - lib/src/components/user_context_menu.dart | 2 +- lib/src/components/verified_shield.dart | 2 +- .../{database.dart => daos/contacts_dao.dart} | 148 +- lib/src/database/daos/contacts_dao.g.dart | 8 + lib/src/database/daos/messages_dao.dart | 127 ++ lib/src/database/daos/messages_dao.g.dart | 9 + .../contacts_table.dart} | 2 +- .../messages_table.dart} | 5 +- .../signal_identity_key_store_table.dart | 12 + .../tables/signal_pre_key_store_table.dart | 11 + .../tables/signal_sender_key_store_table.dart | 10 + .../tables/signal_session_store_table.dart | 12 + lib/src/database/twonly_database.dart | 42 + ...database.g.dart => twonly_database.g.dart} | 1617 ++++++++++++++++- .../{model/json => json_models}/message.dart | 0 .../json => json_models}/signal_identity.dart | 0 .../signal_identity.g.dart | 0 .../json => json_models}/user_data.g.dart | 2 +- .../userdata.dart} | 0 lib/src/model/identity_key_store_model.dart | 36 - lib/src/model/pre_key_model.dart | 31 - lib/src/model/sender_key_store_model.dart | 31 - lib/src/model/session_store_model.dart | 35 - lib/src/providers/api/api.dart | 10 +- lib/src/providers/api/media.dart | 16 +- lib/src/providers/api/server_messages.dart | 32 +- lib/src/providers/db_provider.dart | 72 - lib/src/services/fcm_service.dart | 2 +- lib/src/services/notification_service.dart | 11 +- .../signal/connect_identitiy_key_store.dart | 56 +- lib/src/signal/connect_pre_key_store.dart | 53 +- lib/src/signal/connect_sender_key_store.dart | 29 +- lib/src/signal/connect_session_store.dart | 80 +- lib/src/utils/misc.dart | 15 +- lib/src/utils/signal.dart | 6 +- lib/src/utils/storage.dart | 12 +- .../share_image_editor_view.dart | 9 +- .../camera_to_share/share_image_view.dart | 6 +- .../views/chats/chat_item_details_view.dart | 17 +- lib/src/views/chats/chat_list_view.dart | 18 +- lib/src/views/chats/media_viewer_view.dart | 8 +- lib/src/views/chats/search_username_view.dart | 21 +- .../views/contact/contact_verify_view.dart | 12 +- lib/src/views/contact/contact_view.dart | 16 +- lib/src/views/onboarding/register_view.dart | 4 +- lib/src/views/settings/privacy_view.dart | 2 +- .../settings/privacy_view_block_users.dart | 8 +- .../views/settings/settings_main_view.dart | 2 +- pubspec.lock | 114 +- pubspec.yaml | 6 - 57 files changed, 2100 insertions(+), 736 deletions(-) rename lib/src/database/{database.dart => daos/contacts_dao.dart} (50%) create mode 100644 lib/src/database/daos/contacts_dao.g.dart create mode 100644 lib/src/database/daos/messages_dao.dart create mode 100644 lib/src/database/daos/messages_dao.g.dart rename lib/src/database/{contacts_db.dart => tables/contacts_table.dart} (96%) rename lib/src/database/{messages_db.dart => tables/messages_table.dart} (88%) create mode 100644 lib/src/database/tables/signal_identity_key_store_table.dart create mode 100644 lib/src/database/tables/signal_pre_key_store_table.dart create mode 100644 lib/src/database/tables/signal_sender_key_store_table.dart create mode 100644 lib/src/database/tables/signal_session_store_table.dart create mode 100644 lib/src/database/twonly_database.dart rename lib/src/database/{database.g.dart => twonly_database.g.dart} (60%) rename lib/src/{model/json => json_models}/message.dart (100%) rename lib/src/{model/json => json_models}/signal_identity.dart (100%) rename lib/src/{model/json => json_models}/signal_identity.g.dart (100%) rename lib/src/{model/json => json_models}/user_data.g.dart (96%) rename lib/src/{model/json/user_data.dart => json_models/userdata.dart} (100%) delete mode 100644 lib/src/model/identity_key_store_model.dart delete mode 100644 lib/src/model/pre_key_model.dart delete mode 100644 lib/src/model/sender_key_store_model.dart delete mode 100644 lib/src/model/session_store_model.dart delete mode 100644 lib/src/providers/db_provider.dart diff --git a/lib/globals.dart b/lib/globals.dart index 72ab099..b1479da 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -1,9 +1,7 @@ -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/providers/api_provider.dart'; -import 'package:twonly/src/providers/db_provider.dart'; late ApiProvider apiProvider; // uses for background notification -late DbProvider dbProvider; late TwonlyDatabase twonlyDatabase; diff --git a/lib/main.dart b/lib/main.dart index 52f31a8..763e1e8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,10 @@ import 'package:flutter/foundation.dart'; -import 'package:flutter_foreground_task/flutter_foreground_task.dart'; import 'package:provider/provider.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/providers/api_provider.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; -import 'package:twonly/src/providers/db_provider.dart'; import 'package:twonly/src/providers/hive.dart'; import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/providers/settings_change_provider.dart'; @@ -39,14 +37,9 @@ void main() async { await initMediaStorage(); await initFCMService(); - dbProvider = DbProvider(); - await dbProvider.ready; - apiProvider = ApiProvider(); twonlyDatabase = TwonlyDatabase(); - FlutterForegroundTask.initCommunicationPort(); - runApp( MultiProvider( providers: [ diff --git a/lib/src/components/animate_icon.dart b/lib/src/components/animate_icon.dart index 065efc6..a92a713 100644 --- a/lib/src/components/animate_icon.dart +++ b/lib/src/components/animate_icon.dart @@ -1,4 +1,3 @@ -import 'package:cv/cv.dart'; import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; @@ -30,8 +29,7 @@ class EmojiAnimation extends StatelessWidget { // Check if the emoji has a corresponding Lottie animation if (animatedIcons.containsKey(emoji)) { - return Lottie.asset( - "assets/animated_icons/${animatedIcons.getValue(emoji)}"); + return Lottie.asset("assets/animated_icons/${animatedIcons[emoji]}"); } else { return Text( emoji, diff --git a/lib/src/components/best_friends_selector.dart b/lib/src/components/best_friends_selector.dart index 30b3658..d233b9f 100644 --- a/lib/src/components/best_friends_selector.dart +++ b/lib/src/components/best_friends_selector.dart @@ -2,8 +2,8 @@ import 'dart:collection'; import 'package:flutter/material.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/components/verified_shield.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/components/flame.dart'; import 'package:twonly/src/components/headline.dart'; @@ -142,7 +142,8 @@ class UserCheckbox extends StatelessWidget { ], ), StreamBuilder( - stream: twonlyDatabase.watchFlameCounter(user.userId), + stream: twonlyDatabase.contactsDao + .watchFlameCounter(user.userId), builder: (context, snapshot) { if (!snapshot.hasData || snapshot.data! == 0) { return Container(); diff --git a/lib/src/components/flame.dart b/lib/src/components/flame.dart index d7cba3e..23cde6d 100644 --- a/lib/src/components/flame.dart +++ b/lib/src/components/flame.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:twonly/src/components/animate_icon.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; class FlameCounterWidget extends StatelessWidget { final Contact user; diff --git a/lib/src/components/message_send_state_icon.dart b/lib/src/components/message_send_state_icon.dart index ee6237d..3259594 100644 --- a/lib/src/components/message_send_state_icon.dart +++ b/lib/src/components/message_send_state_icon.dart @@ -2,9 +2,9 @@ import 'dart:collection'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/utils/misc.dart'; enum MessageSendState { diff --git a/lib/src/components/permissions_view.dart b/lib/src/components/permissions_view.dart index e325d59..3ad1359 100644 --- a/lib/src/components/permissions_view.dart +++ b/lib/src/components/permissions_view.dart @@ -1,7 +1,4 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:flutter_foreground_task/flutter_foreground_task.dart'; import 'package:permission_handler/permission_handler.dart'; class PermissionHandlerView extends StatefulWidget { @@ -48,28 +45,6 @@ class PermissionHandlerViewState extends State { // } } - if (Platform.isAndroid) { - // Android 12+, there are restrictions on starting a foreground service. - // - // To restart the service on device reboot or unexpected problem, you need to allow below permission. - if (!await FlutterForegroundTask.isIgnoringBatteryOptimizations) { - // This function requires `android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` permission. - await FlutterForegroundTask.requestIgnoreBatteryOptimization(); - } - - // Use this utility only if you provide services that require long-term survival, - // such as exact alarm service, healthcare service, or Bluetooth communication. - // - // This utility requires the "android.permission.SCHEDULE_EXACT_ALARM" permission. - // Using this permission may make app distribution difficult due to Google policy. - // if (!await FlutterForegroundTask.canScheduleExactAlarms) { - // When you call this function, will be gone to the settings page. - // So you need to explain to the user why set it. - // await FlutterForegroundTask.openAlarmsAndRemindersSettings(); - // } - } - - /*{Permission.camera: PermissionStatus.granted, Permission.storage: PermissionStatus.granted}*/ return statuses; } diff --git a/lib/src/components/user_context_menu.dart b/lib/src/components/user_context_menu.dart index 50e5c47..402e6a9 100644 --- a/lib/src/components/user_context_menu.dart +++ b/lib/src/components/user_context_menu.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:pie_menu/pie_menu.dart'; import 'package:provider/provider.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/views/chats/chat_item_details_view.dart'; diff --git a/lib/src/components/verified_shield.dart b/lib/src/components/verified_shield.dart index 0891651..6f6163f 100644 --- a/lib/src/components/verified_shield.dart +++ b/lib/src/components/verified_shield.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; class VerifiedShield extends StatelessWidget { final Contact contact; diff --git a/lib/src/database/database.dart b/lib/src/database/daos/contacts_dao.dart similarity index 50% rename from lib/src/database/database.dart rename to lib/src/database/daos/contacts_dao.dart index 22ef32c..690d200 100644 --- a/lib/src/database/database.dart +++ b/lib/src/database/daos/contacts_dao.dart @@ -1,145 +1,15 @@ import 'package:drift/drift.dart'; -import 'package:drift_flutter/drift_flutter.dart'; -import 'package:logging/logging.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; -part 'database.g.dart'; +part 'contacts_dao.g.dart'; -// You can then create a database class that includes this table -@DriftDatabase(tables: [Contacts, Messages]) -class TwonlyDatabase extends _$TwonlyDatabase { - TwonlyDatabase() : super(_openConnection()); - - @override - int get schemaVersion => 1; - - static QueryExecutor _openConnection() { - return driftDatabase( - name: 'twonly_main_db', - native: const DriftNativeOptions( - databaseDirectory: getApplicationSupportDirectory, - ), - ); - } - - // ------------ - - Stream> watchMessageNotOpened(int contactId) { - return (select(messages) - ..where((t) => t.openedAt.isNull() & t.contactId.equals(contactId)) - ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])) - .watch(); - } - - Stream> watchMediaMessageNotOpened(int contactId) { - return (select(messages) - ..where((t) => - t.openedAt.isNull() & - t.contactId.equals(contactId) & - t.kind.equals(MessageKind.media.name)) - ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])) - .watch(); - } - - Stream> watchLastMessage(int contactId) { - return (select(messages) - ..where((t) => t.contactId.equals(contactId)) - ..orderBy([(t) => OrderingTerm.desc(t.sendAt)]) - ..limit(1)) - .watch(); - } - - Stream> watchAllMessagesFrom(int contactId) { - return (select(messages) - ..where((t) => - t.contactId.equals(contactId) & - t.contentJson.isNotNull() & - (t.openedAt.isNull() | - t.openedAt.isBiggerThanValue( - DateTime.now().subtract(Duration(days: 1))))) - ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])) - .watch(); - } - - Future removeOldMessages() { - return (update(messages) - ..where((t) => - t.openedAt.isSmallerThanValue( - DateTime.now().subtract(Duration(days: 1))) & - t.kind.equals(MessageKind.textMessage.name))) - .write(MessagesCompanion(contentJson: Value(null))); - } - - Future> getAllMessagesPendingDownloading() { - return (select(messages) - ..where( - (t) => - t.downloadState.equals(DownloadState.downloaded.index).not() & - t.messageOtherId.isNotNull() & - t.kind.equals(MessageKind.media.name), - )) - .get(); - } - - Future> getAllMessagesForRetransmitting() { - return (select(messages)..where((t) => t.acknowledgeByServer.equals(false))) - .get(); - } - - Future openedAllTextMessages(int contactId) { - final updates = MessagesCompanion(openedAt: Value(DateTime.now())); - return (update(messages) - ..where((t) => - t.contactId.equals(contactId) & - t.openedAt.isNull() & - t.kind.equals(MessageKind.textMessage.name))) - .write(updates); - } - - Future updateMessageByOtherUser( - int userId, int messageId, MessagesCompanion updatedValues) { - return (update(messages) - ..where((c) => - c.contactId.equals(userId) & c.messageId.equals(messageId))) - .write(updatedValues); - } - - Future updateMessageByOtherMessageId( - int userId, int messageOtherId, MessagesCompanion updatedValues) { - return (update(messages) - ..where((c) => - c.contactId.equals(userId) & - c.messageOtherId.equals(messageOtherId))) - .write(updatedValues); - } - - Future updateMessageByMessageId( - int messageId, MessagesCompanion updatedValues) { - return (update(messages)..where((c) => c.messageId.equals(messageId))) - .write(updatedValues); - } - - Future insertMessage(MessagesCompanion message) async { - try { - return await into(messages).insert(message); - } catch (e) { - Logger("twonlyDatabase").shout("Error while inserting message: $e"); - return null; - } - } - - Future deleteMessageById(int messageId) { - return (delete(messages)..where((t) => t.messageId.equals(messageId))).go(); - } - - SingleOrNullSelectable getMessageByMessageId(int messageId) { - return select(messages)..where((t) => t.messageId.equals(messageId)); - } - - // ------------ +@DriftAccessor(tables: [Contacts]) +class ContactsDao extends DatabaseAccessor + with _$ContactsDaoMixin { + // this constructor is required so that the main database can create an instance + // of this object. + ContactsDao(TwonlyDatabase db) : super(db); Future insertContact(ContactsCompanion contact) async { try { diff --git a/lib/src/database/daos/contacts_dao.g.dart b/lib/src/database/daos/contacts_dao.g.dart new file mode 100644 index 0000000..7f5fb6b --- /dev/null +++ b/lib/src/database/daos/contacts_dao.g.dart @@ -0,0 +1,8 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'contacts_dao.dart'; + +// ignore_for_file: type=lint +mixin _$ContactsDaoMixin on DatabaseAccessor { + $ContactsTable get contacts => attachedDatabase.contacts; +} diff --git a/lib/src/database/daos/messages_dao.dart b/lib/src/database/daos/messages_dao.dart new file mode 100644 index 0000000..b759df1 --- /dev/null +++ b/lib/src/database/daos/messages_dao.dart @@ -0,0 +1,127 @@ +import 'package:drift/drift.dart'; +import 'package:logging/logging.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/json_models/message.dart'; + +part 'messages_dao.g.dart'; + +@DriftAccessor(tables: [Messages]) +class MessagesDao extends DatabaseAccessor + with _$MessagesDaoMixin { + // this constructor is required so that the main database can create an instance + // of this object. + MessagesDao(TwonlyDatabase db) : super(db); + + Stream> watchMessageNotOpened(int contactId) { + return (select(messages) + ..where((t) => t.openedAt.isNull() & t.contactId.equals(contactId)) + ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])) + .watch(); + } + + Stream> watchMediaMessageNotOpened(int contactId) { + return (select(messages) + ..where((t) => + t.openedAt.isNull() & + t.contactId.equals(contactId) & + t.kind.equals(MessageKind.media.name)) + ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])) + .watch(); + } + + Stream> watchLastMessage(int contactId) { + return (select(messages) + ..where((t) => t.contactId.equals(contactId)) + ..orderBy([(t) => OrderingTerm.desc(t.sendAt)]) + ..limit(1)) + .watch(); + } + + Stream> watchAllMessagesFrom(int contactId) { + return (select(messages) + ..where((t) => + t.contactId.equals(contactId) & + t.contentJson.isNotNull() & + (t.openedAt.isNull() | + t.openedAt.isBiggerThanValue( + DateTime.now().subtract(Duration(days: 1))))) + ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])) + .watch(); + } + + Future removeOldMessages() { + return (update(messages) + ..where((t) => + t.openedAt.isSmallerThanValue( + DateTime.now().subtract(Duration(days: 1))) & + t.kind.equals(MessageKind.textMessage.name))) + .write(MessagesCompanion(contentJson: Value(null))); + } + + Future> getAllMessagesPendingDownloading() { + return (select(messages) + ..where( + (t) => + t.downloadState.equals(DownloadState.downloaded.index).not() & + t.messageOtherId.isNotNull() & + t.kind.equals(MessageKind.media.name), + )) + .get(); + } + + Future> getAllMessagesForRetransmitting() { + return (select(messages)..where((t) => t.acknowledgeByServer.equals(false))) + .get(); + } + + Future openedAllTextMessages(int contactId) { + final updates = MessagesCompanion(openedAt: Value(DateTime.now())); + return (update(messages) + ..where((t) => + t.contactId.equals(contactId) & + t.openedAt.isNull() & + t.kind.equals(MessageKind.textMessage.name))) + .write(updates); + } + + Future updateMessageByOtherUser( + int userId, int messageId, MessagesCompanion updatedValues) { + return (update(messages) + ..where((c) => + c.contactId.equals(userId) & c.messageId.equals(messageId))) + .write(updatedValues); + } + + Future updateMessageByOtherMessageId( + int userId, int messageOtherId, MessagesCompanion updatedValues) { + return (update(messages) + ..where((c) => + c.contactId.equals(userId) & + c.messageOtherId.equals(messageOtherId))) + .write(updatedValues); + } + + Future updateMessageByMessageId( + int messageId, MessagesCompanion updatedValues) { + return (update(messages)..where((c) => c.messageId.equals(messageId))) + .write(updatedValues); + } + + Future insertMessage(MessagesCompanion message) async { + try { + return await into(messages).insert(message); + } catch (e) { + Logger("twonlyDatabase").shout("Error while inserting message: $e"); + return null; + } + } + + Future deleteMessageById(int messageId) { + return (delete(messages)..where((t) => t.messageId.equals(messageId))).go(); + } + + SingleOrNullSelectable getMessageByMessageId(int messageId) { + return select(messages)..where((t) => t.messageId.equals(messageId)); + } +} diff --git a/lib/src/database/daos/messages_dao.g.dart b/lib/src/database/daos/messages_dao.g.dart new file mode 100644 index 0000000..1967aec --- /dev/null +++ b/lib/src/database/daos/messages_dao.g.dart @@ -0,0 +1,9 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'messages_dao.dart'; + +// ignore_for_file: type=lint +mixin _$MessagesDaoMixin on DatabaseAccessor { + $ContactsTable get contacts => attachedDatabase.contacts; + $MessagesTable get messages => attachedDatabase.messages; +} diff --git a/lib/src/database/contacts_db.dart b/lib/src/database/tables/contacts_table.dart similarity index 96% rename from lib/src/database/contacts_db.dart rename to lib/src/database/tables/contacts_table.dart index 9418555..8dc66a0 100644 --- a/lib/src/database/contacts_db.dart +++ b/lib/src/database/tables/contacts_table.dart @@ -1,5 +1,5 @@ import 'package:drift/drift.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; class Contacts extends Table { IntColumn get userId => integer()(); diff --git a/lib/src/database/messages_db.dart b/lib/src/database/tables/messages_table.dart similarity index 88% rename from lib/src/database/messages_db.dart rename to lib/src/database/tables/messages_table.dart index e6be404..e15f4b0 100644 --- a/lib/src/database/messages_db.dart +++ b/lib/src/database/tables/messages_table.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/json_models/message.dart'; enum DownloadState { pending, @@ -8,6 +8,7 @@ enum DownloadState { downloaded, } +@DataClassName('Message') class Messages extends Table { IntColumn get contactId => integer().references(Contacts, #userId)(); diff --git a/lib/src/database/tables/signal_identity_key_store_table.dart b/lib/src/database/tables/signal_identity_key_store_table.dart new file mode 100644 index 0000000..1f7d380 --- /dev/null +++ b/lib/src/database/tables/signal_identity_key_store_table.dart @@ -0,0 +1,12 @@ +import 'package:drift/drift.dart'; + +@DataClassName('SignalIdentityKeyStore') +class SignalIdentityKeyStores extends Table { + IntColumn get deviceId => integer()(); + TextColumn get name => text()(); + BlobColumn get identityKey => blob()(); + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); + + @override + Set get primaryKey => {deviceId, name}; +} diff --git a/lib/src/database/tables/signal_pre_key_store_table.dart b/lib/src/database/tables/signal_pre_key_store_table.dart new file mode 100644 index 0000000..eb74263 --- /dev/null +++ b/lib/src/database/tables/signal_pre_key_store_table.dart @@ -0,0 +1,11 @@ +import 'package:drift/drift.dart'; + +@DataClassName('SignalPreKeyStore') +class SignalPreKeyStores extends Table { + IntColumn get preKeyId => integer()(); + BlobColumn get preKey => blob()(); + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); + + @override + Set get primaryKey => {preKeyId}; +} diff --git a/lib/src/database/tables/signal_sender_key_store_table.dart b/lib/src/database/tables/signal_sender_key_store_table.dart new file mode 100644 index 0000000..1c10183 --- /dev/null +++ b/lib/src/database/tables/signal_sender_key_store_table.dart @@ -0,0 +1,10 @@ +import 'package:drift/drift.dart'; + +@DataClassName('SignalSenderKeyStore') +class SignalSenderKeyStores extends Table { + TextColumn get senderKeyName => text()(); + BlobColumn get senderKey => blob()(); + + @override + Set get primaryKey => {senderKeyName}; +} diff --git a/lib/src/database/tables/signal_session_store_table.dart b/lib/src/database/tables/signal_session_store_table.dart new file mode 100644 index 0000000..e522700 --- /dev/null +++ b/lib/src/database/tables/signal_session_store_table.dart @@ -0,0 +1,12 @@ +import 'package:drift/drift.dart'; + +@DataClassName('SignalSessionStore') +class SignalSessionStores extends Table { + IntColumn get deviceId => integer()(); + TextColumn get name => text()(); + BlobColumn get sessionRecord => blob()(); + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); + + @override + Set get primaryKey => {deviceId, name}; +} diff --git a/lib/src/database/twonly_database.dart b/lib/src/database/twonly_database.dart new file mode 100644 index 0000000..51ed17b --- /dev/null +++ b/lib/src/database/twonly_database.dart @@ -0,0 +1,42 @@ +import 'package:drift/drift.dart'; +import 'package:drift_flutter/drift_flutter.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:twonly/src/database/daos/contacts_dao.dart'; +import 'package:twonly/src/database/daos/messages_dao.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/database/tables/signal_identity_key_store_table.dart'; +import 'package:twonly/src/database/tables/signal_pre_key_store_table.dart'; +import 'package:twonly/src/database/tables/signal_sender_key_store_table.dart'; +import 'package:twonly/src/database/tables/signal_session_store_table.dart'; +import 'package:twonly/src/json_models/message.dart'; + +part 'twonly_database.g.dart'; + +// You can then create a database class that includes this table +@DriftDatabase(tables: [ + Contacts, + Messages, + SignalIdentityKeyStores, + SignalPreKeyStores, + SignalSenderKeyStores, + SignalSessionStores +], daos: [ + MessagesDao, + ContactsDao +]) +class TwonlyDatabase extends _$TwonlyDatabase { + TwonlyDatabase() : super(_openConnection()); + + @override + int get schemaVersion => 1; + + static QueryExecutor _openConnection() { + return driftDatabase( + name: 'twonly_database', + native: const DriftNativeOptions( + databaseDirectory: getApplicationSupportDirectory, + ), + ); + } +} diff --git a/lib/src/database/database.g.dart b/lib/src/database/twonly_database.g.dart similarity index 60% rename from lib/src/database/database.g.dart rename to lib/src/database/twonly_database.g.dart index a52e337..bc6e389 100644 --- a/lib/src/database/database.g.dart +++ b/lib/src/database/twonly_database.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'database.dart'; +part of 'twonly_database.dart'; // ignore_for_file: type=lint class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> { @@ -1377,16 +1377,1014 @@ class MessagesCompanion extends UpdateCompanion { } } +class $SignalIdentityKeyStoresTable extends SignalIdentityKeyStores + with TableInfo<$SignalIdentityKeyStoresTable, SignalIdentityKeyStore> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SignalIdentityKeyStoresTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _deviceIdMeta = + const VerificationMeta('deviceId'); + @override + late final GeneratedColumn deviceId = GeneratedColumn( + 'device_id', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _identityKeyMeta = + const VerificationMeta('identityKey'); + @override + late final GeneratedColumn identityKey = + GeneratedColumn('identity_key', aliasedName, false, + type: DriftSqlType.blob, requiredDuringInsert: true); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => + [deviceId, name, identityKey, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'signal_identity_key_stores'; + @override + VerificationContext validateIntegrity( + Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('device_id')) { + context.handle(_deviceIdMeta, + deviceId.isAcceptableOrUnknown(data['device_id']!, _deviceIdMeta)); + } else if (isInserting) { + context.missing(_deviceIdMeta); + } + if (data.containsKey('name')) { + context.handle( + _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('identity_key')) { + context.handle( + _identityKeyMeta, + identityKey.isAcceptableOrUnknown( + data['identity_key']!, _identityKeyMeta)); + } else if (isInserting) { + context.missing(_identityKeyMeta); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {deviceId, name}; + @override + SignalIdentityKeyStore map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SignalIdentityKeyStore( + deviceId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}device_id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + identityKey: attachedDatabase.typeMapping + .read(DriftSqlType.blob, data['${effectivePrefix}identity_key'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + $SignalIdentityKeyStoresTable createAlias(String alias) { + return $SignalIdentityKeyStoresTable(attachedDatabase, alias); + } +} + +class SignalIdentityKeyStore extends DataClass + implements Insertable { + final int deviceId; + final String name; + final Uint8List identityKey; + final DateTime createdAt; + const SignalIdentityKeyStore( + {required this.deviceId, + required this.name, + required this.identityKey, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['device_id'] = Variable(deviceId); + map['name'] = Variable(name); + map['identity_key'] = Variable(identityKey); + map['created_at'] = Variable(createdAt); + return map; + } + + SignalIdentityKeyStoresCompanion toCompanion(bool nullToAbsent) { + return SignalIdentityKeyStoresCompanion( + deviceId: Value(deviceId), + name: Value(name), + identityKey: Value(identityKey), + createdAt: Value(createdAt), + ); + } + + factory SignalIdentityKeyStore.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SignalIdentityKeyStore( + deviceId: serializer.fromJson(json['deviceId']), + name: serializer.fromJson(json['name']), + identityKey: serializer.fromJson(json['identityKey']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'deviceId': serializer.toJson(deviceId), + 'name': serializer.toJson(name), + 'identityKey': serializer.toJson(identityKey), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SignalIdentityKeyStore copyWith( + {int? deviceId, + String? name, + Uint8List? identityKey, + DateTime? createdAt}) => + SignalIdentityKeyStore( + deviceId: deviceId ?? this.deviceId, + name: name ?? this.name, + identityKey: identityKey ?? this.identityKey, + createdAt: createdAt ?? this.createdAt, + ); + SignalIdentityKeyStore copyWithCompanion( + SignalIdentityKeyStoresCompanion data) { + return SignalIdentityKeyStore( + deviceId: data.deviceId.present ? data.deviceId.value : this.deviceId, + name: data.name.present ? data.name.value : this.name, + identityKey: + data.identityKey.present ? data.identityKey.value : this.identityKey, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('SignalIdentityKeyStore(') + ..write('deviceId: $deviceId, ') + ..write('name: $name, ') + ..write('identityKey: $identityKey, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + deviceId, name, $driftBlobEquality.hash(identityKey), createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SignalIdentityKeyStore && + other.deviceId == this.deviceId && + other.name == this.name && + $driftBlobEquality.equals(other.identityKey, this.identityKey) && + other.createdAt == this.createdAt); +} + +class SignalIdentityKeyStoresCompanion + extends UpdateCompanion { + final Value deviceId; + final Value name; + final Value identityKey; + final Value createdAt; + final Value rowid; + const SignalIdentityKeyStoresCompanion({ + this.deviceId = const Value.absent(), + this.name = const Value.absent(), + this.identityKey = const Value.absent(), + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + SignalIdentityKeyStoresCompanion.insert({ + required int deviceId, + required String name, + required Uint8List identityKey, + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : deviceId = Value(deviceId), + name = Value(name), + identityKey = Value(identityKey); + static Insertable custom({ + Expression? deviceId, + Expression? name, + Expression? identityKey, + Expression? createdAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (deviceId != null) 'device_id': deviceId, + if (name != null) 'name': name, + if (identityKey != null) 'identity_key': identityKey, + if (createdAt != null) 'created_at': createdAt, + if (rowid != null) 'rowid': rowid, + }); + } + + SignalIdentityKeyStoresCompanion copyWith( + {Value? deviceId, + Value? name, + Value? identityKey, + Value? createdAt, + Value? rowid}) { + return SignalIdentityKeyStoresCompanion( + deviceId: deviceId ?? this.deviceId, + name: name ?? this.name, + identityKey: identityKey ?? this.identityKey, + createdAt: createdAt ?? this.createdAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (deviceId.present) { + map['device_id'] = Variable(deviceId.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (identityKey.present) { + map['identity_key'] = Variable(identityKey.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SignalIdentityKeyStoresCompanion(') + ..write('deviceId: $deviceId, ') + ..write('name: $name, ') + ..write('identityKey: $identityKey, ') + ..write('createdAt: $createdAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $SignalPreKeyStoresTable extends SignalPreKeyStores + with TableInfo<$SignalPreKeyStoresTable, SignalPreKeyStore> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SignalPreKeyStoresTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _preKeyIdMeta = + const VerificationMeta('preKeyId'); + @override + late final GeneratedColumn preKeyId = GeneratedColumn( + 'pre_key_id', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: false); + static const VerificationMeta _preKeyMeta = const VerificationMeta('preKey'); + @override + late final GeneratedColumn preKey = GeneratedColumn( + 'pre_key', aliasedName, false, + type: DriftSqlType.blob, requiredDuringInsert: true); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => [preKeyId, preKey, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'signal_pre_key_stores'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('pre_key_id')) { + context.handle(_preKeyIdMeta, + preKeyId.isAcceptableOrUnknown(data['pre_key_id']!, _preKeyIdMeta)); + } + if (data.containsKey('pre_key')) { + context.handle(_preKeyMeta, + preKey.isAcceptableOrUnknown(data['pre_key']!, _preKeyMeta)); + } else if (isInserting) { + context.missing(_preKeyMeta); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {preKeyId}; + @override + SignalPreKeyStore map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SignalPreKeyStore( + preKeyId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}pre_key_id'])!, + preKey: attachedDatabase.typeMapping + .read(DriftSqlType.blob, data['${effectivePrefix}pre_key'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + $SignalPreKeyStoresTable createAlias(String alias) { + return $SignalPreKeyStoresTable(attachedDatabase, alias); + } +} + +class SignalPreKeyStore extends DataClass + implements Insertable { + final int preKeyId; + final Uint8List preKey; + final DateTime createdAt; + const SignalPreKeyStore( + {required this.preKeyId, required this.preKey, required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['pre_key_id'] = Variable(preKeyId); + map['pre_key'] = Variable(preKey); + map['created_at'] = Variable(createdAt); + return map; + } + + SignalPreKeyStoresCompanion toCompanion(bool nullToAbsent) { + return SignalPreKeyStoresCompanion( + preKeyId: Value(preKeyId), + preKey: Value(preKey), + createdAt: Value(createdAt), + ); + } + + factory SignalPreKeyStore.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SignalPreKeyStore( + preKeyId: serializer.fromJson(json['preKeyId']), + preKey: serializer.fromJson(json['preKey']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'preKeyId': serializer.toJson(preKeyId), + 'preKey': serializer.toJson(preKey), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SignalPreKeyStore copyWith( + {int? preKeyId, Uint8List? preKey, DateTime? createdAt}) => + SignalPreKeyStore( + preKeyId: preKeyId ?? this.preKeyId, + preKey: preKey ?? this.preKey, + createdAt: createdAt ?? this.createdAt, + ); + SignalPreKeyStore copyWithCompanion(SignalPreKeyStoresCompanion data) { + return SignalPreKeyStore( + preKeyId: data.preKeyId.present ? data.preKeyId.value : this.preKeyId, + preKey: data.preKey.present ? data.preKey.value : this.preKey, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('SignalPreKeyStore(') + ..write('preKeyId: $preKeyId, ') + ..write('preKey: $preKey, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(preKeyId, $driftBlobEquality.hash(preKey), createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SignalPreKeyStore && + other.preKeyId == this.preKeyId && + $driftBlobEquality.equals(other.preKey, this.preKey) && + other.createdAt == this.createdAt); +} + +class SignalPreKeyStoresCompanion extends UpdateCompanion { + final Value preKeyId; + final Value preKey; + final Value createdAt; + const SignalPreKeyStoresCompanion({ + this.preKeyId = const Value.absent(), + this.preKey = const Value.absent(), + this.createdAt = const Value.absent(), + }); + SignalPreKeyStoresCompanion.insert({ + this.preKeyId = const Value.absent(), + required Uint8List preKey, + this.createdAt = const Value.absent(), + }) : preKey = Value(preKey); + static Insertable custom({ + Expression? preKeyId, + Expression? preKey, + Expression? createdAt, + }) { + return RawValuesInsertable({ + if (preKeyId != null) 'pre_key_id': preKeyId, + if (preKey != null) 'pre_key': preKey, + if (createdAt != null) 'created_at': createdAt, + }); + } + + SignalPreKeyStoresCompanion copyWith( + {Value? preKeyId, + Value? preKey, + Value? createdAt}) { + return SignalPreKeyStoresCompanion( + preKeyId: preKeyId ?? this.preKeyId, + preKey: preKey ?? this.preKey, + createdAt: createdAt ?? this.createdAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (preKeyId.present) { + map['pre_key_id'] = Variable(preKeyId.value); + } + if (preKey.present) { + map['pre_key'] = Variable(preKey.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SignalPreKeyStoresCompanion(') + ..write('preKeyId: $preKeyId, ') + ..write('preKey: $preKey, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } +} + +class $SignalSenderKeyStoresTable extends SignalSenderKeyStores + with TableInfo<$SignalSenderKeyStoresTable, SignalSenderKeyStore> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SignalSenderKeyStoresTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _senderKeyNameMeta = + const VerificationMeta('senderKeyName'); + @override + late final GeneratedColumn senderKeyName = GeneratedColumn( + 'sender_key_name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _senderKeyMeta = + const VerificationMeta('senderKey'); + @override + late final GeneratedColumn senderKey = GeneratedColumn( + 'sender_key', aliasedName, false, + type: DriftSqlType.blob, requiredDuringInsert: true); + @override + List get $columns => [senderKeyName, senderKey]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'signal_sender_key_stores'; + @override + VerificationContext validateIntegrity( + Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('sender_key_name')) { + context.handle( + _senderKeyNameMeta, + senderKeyName.isAcceptableOrUnknown( + data['sender_key_name']!, _senderKeyNameMeta)); + } else if (isInserting) { + context.missing(_senderKeyNameMeta); + } + if (data.containsKey('sender_key')) { + context.handle(_senderKeyMeta, + senderKey.isAcceptableOrUnknown(data['sender_key']!, _senderKeyMeta)); + } else if (isInserting) { + context.missing(_senderKeyMeta); + } + return context; + } + + @override + Set get $primaryKey => {senderKeyName}; + @override + SignalSenderKeyStore map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SignalSenderKeyStore( + senderKeyName: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}sender_key_name'])!, + senderKey: attachedDatabase.typeMapping + .read(DriftSqlType.blob, data['${effectivePrefix}sender_key'])!, + ); + } + + @override + $SignalSenderKeyStoresTable createAlias(String alias) { + return $SignalSenderKeyStoresTable(attachedDatabase, alias); + } +} + +class SignalSenderKeyStore extends DataClass + implements Insertable { + final String senderKeyName; + final Uint8List senderKey; + const SignalSenderKeyStore( + {required this.senderKeyName, required this.senderKey}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['sender_key_name'] = Variable(senderKeyName); + map['sender_key'] = Variable(senderKey); + return map; + } + + SignalSenderKeyStoresCompanion toCompanion(bool nullToAbsent) { + return SignalSenderKeyStoresCompanion( + senderKeyName: Value(senderKeyName), + senderKey: Value(senderKey), + ); + } + + factory SignalSenderKeyStore.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SignalSenderKeyStore( + senderKeyName: serializer.fromJson(json['senderKeyName']), + senderKey: serializer.fromJson(json['senderKey']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'senderKeyName': serializer.toJson(senderKeyName), + 'senderKey': serializer.toJson(senderKey), + }; + } + + SignalSenderKeyStore copyWith( + {String? senderKeyName, Uint8List? senderKey}) => + SignalSenderKeyStore( + senderKeyName: senderKeyName ?? this.senderKeyName, + senderKey: senderKey ?? this.senderKey, + ); + SignalSenderKeyStore copyWithCompanion(SignalSenderKeyStoresCompanion data) { + return SignalSenderKeyStore( + senderKeyName: data.senderKeyName.present + ? data.senderKeyName.value + : this.senderKeyName, + senderKey: data.senderKey.present ? data.senderKey.value : this.senderKey, + ); + } + + @override + String toString() { + return (StringBuffer('SignalSenderKeyStore(') + ..write('senderKeyName: $senderKeyName, ') + ..write('senderKey: $senderKey') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(senderKeyName, $driftBlobEquality.hash(senderKey)); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SignalSenderKeyStore && + other.senderKeyName == this.senderKeyName && + $driftBlobEquality.equals(other.senderKey, this.senderKey)); +} + +class SignalSenderKeyStoresCompanion + extends UpdateCompanion { + final Value senderKeyName; + final Value senderKey; + final Value rowid; + const SignalSenderKeyStoresCompanion({ + this.senderKeyName = const Value.absent(), + this.senderKey = const Value.absent(), + this.rowid = const Value.absent(), + }); + SignalSenderKeyStoresCompanion.insert({ + required String senderKeyName, + required Uint8List senderKey, + this.rowid = const Value.absent(), + }) : senderKeyName = Value(senderKeyName), + senderKey = Value(senderKey); + static Insertable custom({ + Expression? senderKeyName, + Expression? senderKey, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (senderKeyName != null) 'sender_key_name': senderKeyName, + if (senderKey != null) 'sender_key': senderKey, + if (rowid != null) 'rowid': rowid, + }); + } + + SignalSenderKeyStoresCompanion copyWith( + {Value? senderKeyName, + Value? senderKey, + Value? rowid}) { + return SignalSenderKeyStoresCompanion( + senderKeyName: senderKeyName ?? this.senderKeyName, + senderKey: senderKey ?? this.senderKey, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (senderKeyName.present) { + map['sender_key_name'] = Variable(senderKeyName.value); + } + if (senderKey.present) { + map['sender_key'] = Variable(senderKey.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SignalSenderKeyStoresCompanion(') + ..write('senderKeyName: $senderKeyName, ') + ..write('senderKey: $senderKey, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $SignalSessionStoresTable extends SignalSessionStores + with TableInfo<$SignalSessionStoresTable, SignalSessionStore> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SignalSessionStoresTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _deviceIdMeta = + const VerificationMeta('deviceId'); + @override + late final GeneratedColumn deviceId = GeneratedColumn( + 'device_id', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _sessionRecordMeta = + const VerificationMeta('sessionRecord'); + @override + late final GeneratedColumn sessionRecord = + GeneratedColumn('session_record', aliasedName, false, + type: DriftSqlType.blob, requiredDuringInsert: true); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => + [deviceId, name, sessionRecord, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'signal_session_stores'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('device_id')) { + context.handle(_deviceIdMeta, + deviceId.isAcceptableOrUnknown(data['device_id']!, _deviceIdMeta)); + } else if (isInserting) { + context.missing(_deviceIdMeta); + } + if (data.containsKey('name')) { + context.handle( + _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('session_record')) { + context.handle( + _sessionRecordMeta, + sessionRecord.isAcceptableOrUnknown( + data['session_record']!, _sessionRecordMeta)); + } else if (isInserting) { + context.missing(_sessionRecordMeta); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {deviceId, name}; + @override + SignalSessionStore map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SignalSessionStore( + deviceId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}device_id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + sessionRecord: attachedDatabase.typeMapping + .read(DriftSqlType.blob, data['${effectivePrefix}session_record'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + $SignalSessionStoresTable createAlias(String alias) { + return $SignalSessionStoresTable(attachedDatabase, alias); + } +} + +class SignalSessionStore extends DataClass + implements Insertable { + final int deviceId; + final String name; + final Uint8List sessionRecord; + final DateTime createdAt; + const SignalSessionStore( + {required this.deviceId, + required this.name, + required this.sessionRecord, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['device_id'] = Variable(deviceId); + map['name'] = Variable(name); + map['session_record'] = Variable(sessionRecord); + map['created_at'] = Variable(createdAt); + return map; + } + + SignalSessionStoresCompanion toCompanion(bool nullToAbsent) { + return SignalSessionStoresCompanion( + deviceId: Value(deviceId), + name: Value(name), + sessionRecord: Value(sessionRecord), + createdAt: Value(createdAt), + ); + } + + factory SignalSessionStore.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SignalSessionStore( + deviceId: serializer.fromJson(json['deviceId']), + name: serializer.fromJson(json['name']), + sessionRecord: serializer.fromJson(json['sessionRecord']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'deviceId': serializer.toJson(deviceId), + 'name': serializer.toJson(name), + 'sessionRecord': serializer.toJson(sessionRecord), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SignalSessionStore copyWith( + {int? deviceId, + String? name, + Uint8List? sessionRecord, + DateTime? createdAt}) => + SignalSessionStore( + deviceId: deviceId ?? this.deviceId, + name: name ?? this.name, + sessionRecord: sessionRecord ?? this.sessionRecord, + createdAt: createdAt ?? this.createdAt, + ); + SignalSessionStore copyWithCompanion(SignalSessionStoresCompanion data) { + return SignalSessionStore( + deviceId: data.deviceId.present ? data.deviceId.value : this.deviceId, + name: data.name.present ? data.name.value : this.name, + sessionRecord: data.sessionRecord.present + ? data.sessionRecord.value + : this.sessionRecord, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('SignalSessionStore(') + ..write('deviceId: $deviceId, ') + ..write('name: $name, ') + ..write('sessionRecord: $sessionRecord, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + deviceId, name, $driftBlobEquality.hash(sessionRecord), createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SignalSessionStore && + other.deviceId == this.deviceId && + other.name == this.name && + $driftBlobEquality.equals(other.sessionRecord, this.sessionRecord) && + other.createdAt == this.createdAt); +} + +class SignalSessionStoresCompanion extends UpdateCompanion { + final Value deviceId; + final Value name; + final Value sessionRecord; + final Value createdAt; + final Value rowid; + const SignalSessionStoresCompanion({ + this.deviceId = const Value.absent(), + this.name = const Value.absent(), + this.sessionRecord = const Value.absent(), + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + SignalSessionStoresCompanion.insert({ + required int deviceId, + required String name, + required Uint8List sessionRecord, + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : deviceId = Value(deviceId), + name = Value(name), + sessionRecord = Value(sessionRecord); + static Insertable custom({ + Expression? deviceId, + Expression? name, + Expression? sessionRecord, + Expression? createdAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (deviceId != null) 'device_id': deviceId, + if (name != null) 'name': name, + if (sessionRecord != null) 'session_record': sessionRecord, + if (createdAt != null) 'created_at': createdAt, + if (rowid != null) 'rowid': rowid, + }); + } + + SignalSessionStoresCompanion copyWith( + {Value? deviceId, + Value? name, + Value? sessionRecord, + Value? createdAt, + Value? rowid}) { + return SignalSessionStoresCompanion( + deviceId: deviceId ?? this.deviceId, + name: name ?? this.name, + sessionRecord: sessionRecord ?? this.sessionRecord, + createdAt: createdAt ?? this.createdAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (deviceId.present) { + map['device_id'] = Variable(deviceId.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (sessionRecord.present) { + map['session_record'] = Variable(sessionRecord.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SignalSessionStoresCompanion(') + ..write('deviceId: $deviceId, ') + ..write('name: $name, ') + ..write('sessionRecord: $sessionRecord, ') + ..write('createdAt: $createdAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + abstract class _$TwonlyDatabase extends GeneratedDatabase { _$TwonlyDatabase(QueryExecutor e) : super(e); $TwonlyDatabaseManager get managers => $TwonlyDatabaseManager(this); late final $ContactsTable contacts = $ContactsTable(this); late final $MessagesTable messages = $MessagesTable(this); + late final $SignalIdentityKeyStoresTable signalIdentityKeyStores = + $SignalIdentityKeyStoresTable(this); + late final $SignalPreKeyStoresTable signalPreKeyStores = + $SignalPreKeyStoresTable(this); + late final $SignalSenderKeyStoresTable signalSenderKeyStores = + $SignalSenderKeyStoresTable(this); + late final $SignalSessionStoresTable signalSessionStores = + $SignalSessionStoresTable(this); + late final MessagesDao messagesDao = MessagesDao(this as TwonlyDatabase); + late final ContactsDao contactsDao = ContactsDao(this as TwonlyDatabase); @override Iterable> get allTables => allSchemaEntities.whereType>(); @override - List get allSchemaEntities => [contacts, messages]; + List get allSchemaEntities => [ + contacts, + messages, + signalIdentityKeyStores, + signalPreKeyStores, + signalSenderKeyStores, + signalSessionStores + ]; } typedef $$ContactsTableCreateCompanionBuilder = ContactsCompanion Function({ @@ -2176,6 +3174,612 @@ typedef $$MessagesTableProcessedTableManager = ProcessedTableManager< (Message, $$MessagesTableReferences), Message, PrefetchHooks Function({bool contactId})>; +typedef $$SignalIdentityKeyStoresTableCreateCompanionBuilder + = SignalIdentityKeyStoresCompanion Function({ + required int deviceId, + required String name, + required Uint8List identityKey, + Value createdAt, + Value rowid, +}); +typedef $$SignalIdentityKeyStoresTableUpdateCompanionBuilder + = SignalIdentityKeyStoresCompanion Function({ + Value deviceId, + Value name, + Value identityKey, + Value createdAt, + Value rowid, +}); + +class $$SignalIdentityKeyStoresTableFilterComposer + extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> { + $$SignalIdentityKeyStoresTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get deviceId => $composableBuilder( + column: $table.deviceId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get name => $composableBuilder( + column: $table.name, builder: (column) => ColumnFilters(column)); + + ColumnFilters get identityKey => $composableBuilder( + column: $table.identityKey, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); +} + +class $$SignalIdentityKeyStoresTableOrderingComposer + extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> { + $$SignalIdentityKeyStoresTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get deviceId => $composableBuilder( + column: $table.deviceId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get name => $composableBuilder( + column: $table.name, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get identityKey => $composableBuilder( + column: $table.identityKey, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); +} + +class $$SignalIdentityKeyStoresTableAnnotationComposer + extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> { + $$SignalIdentityKeyStoresTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get deviceId => + $composableBuilder(column: $table.deviceId, builder: (column) => column); + + GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + GeneratedColumn get identityKey => $composableBuilder( + column: $table.identityKey, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); +} + +class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager< + _$TwonlyDatabase, + $SignalIdentityKeyStoresTable, + SignalIdentityKeyStore, + $$SignalIdentityKeyStoresTableFilterComposer, + $$SignalIdentityKeyStoresTableOrderingComposer, + $$SignalIdentityKeyStoresTableAnnotationComposer, + $$SignalIdentityKeyStoresTableCreateCompanionBuilder, + $$SignalIdentityKeyStoresTableUpdateCompanionBuilder, + ( + SignalIdentityKeyStore, + BaseReferences<_$TwonlyDatabase, $SignalIdentityKeyStoresTable, + SignalIdentityKeyStore> + ), + SignalIdentityKeyStore, + PrefetchHooks Function()> { + $$SignalIdentityKeyStoresTableTableManager( + _$TwonlyDatabase db, $SignalIdentityKeyStoresTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$SignalIdentityKeyStoresTableFilterComposer( + $db: db, $table: table), + createOrderingComposer: () => + $$SignalIdentityKeyStoresTableOrderingComposer( + $db: db, $table: table), + createComputedFieldComposer: () => + $$SignalIdentityKeyStoresTableAnnotationComposer( + $db: db, $table: table), + updateCompanionCallback: ({ + Value deviceId = const Value.absent(), + Value name = const Value.absent(), + Value identityKey = const Value.absent(), + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SignalIdentityKeyStoresCompanion( + deviceId: deviceId, + name: name, + identityKey: identityKey, + createdAt: createdAt, + rowid: rowid, + ), + createCompanionCallback: ({ + required int deviceId, + required String name, + required Uint8List identityKey, + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SignalIdentityKeyStoresCompanion.insert( + deviceId: deviceId, + name: name, + identityKey: identityKey, + createdAt: createdAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$SignalIdentityKeyStoresTableProcessedTableManager + = ProcessedTableManager< + _$TwonlyDatabase, + $SignalIdentityKeyStoresTable, + SignalIdentityKeyStore, + $$SignalIdentityKeyStoresTableFilterComposer, + $$SignalIdentityKeyStoresTableOrderingComposer, + $$SignalIdentityKeyStoresTableAnnotationComposer, + $$SignalIdentityKeyStoresTableCreateCompanionBuilder, + $$SignalIdentityKeyStoresTableUpdateCompanionBuilder, + ( + SignalIdentityKeyStore, + BaseReferences<_$TwonlyDatabase, $SignalIdentityKeyStoresTable, + SignalIdentityKeyStore> + ), + SignalIdentityKeyStore, + PrefetchHooks Function()>; +typedef $$SignalPreKeyStoresTableCreateCompanionBuilder + = SignalPreKeyStoresCompanion Function({ + Value preKeyId, + required Uint8List preKey, + Value createdAt, +}); +typedef $$SignalPreKeyStoresTableUpdateCompanionBuilder + = SignalPreKeyStoresCompanion Function({ + Value preKeyId, + Value preKey, + Value createdAt, +}); + +class $$SignalPreKeyStoresTableFilterComposer + extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> { + $$SignalPreKeyStoresTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get preKeyId => $composableBuilder( + column: $table.preKeyId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get preKey => $composableBuilder( + column: $table.preKey, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); +} + +class $$SignalPreKeyStoresTableOrderingComposer + extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> { + $$SignalPreKeyStoresTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get preKeyId => $composableBuilder( + column: $table.preKeyId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get preKey => $composableBuilder( + column: $table.preKey, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); +} + +class $$SignalPreKeyStoresTableAnnotationComposer + extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> { + $$SignalPreKeyStoresTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get preKeyId => + $composableBuilder(column: $table.preKeyId, builder: (column) => column); + + GeneratedColumn get preKey => + $composableBuilder(column: $table.preKey, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); +} + +class $$SignalPreKeyStoresTableTableManager extends RootTableManager< + _$TwonlyDatabase, + $SignalPreKeyStoresTable, + SignalPreKeyStore, + $$SignalPreKeyStoresTableFilterComposer, + $$SignalPreKeyStoresTableOrderingComposer, + $$SignalPreKeyStoresTableAnnotationComposer, + $$SignalPreKeyStoresTableCreateCompanionBuilder, + $$SignalPreKeyStoresTableUpdateCompanionBuilder, + ( + SignalPreKeyStore, + BaseReferences<_$TwonlyDatabase, $SignalPreKeyStoresTable, + SignalPreKeyStore> + ), + SignalPreKeyStore, + PrefetchHooks Function()> { + $$SignalPreKeyStoresTableTableManager( + _$TwonlyDatabase db, $SignalPreKeyStoresTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$SignalPreKeyStoresTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$SignalPreKeyStoresTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$SignalPreKeyStoresTableAnnotationComposer( + $db: db, $table: table), + updateCompanionCallback: ({ + Value preKeyId = const Value.absent(), + Value preKey = const Value.absent(), + Value createdAt = const Value.absent(), + }) => + SignalPreKeyStoresCompanion( + preKeyId: preKeyId, + preKey: preKey, + createdAt: createdAt, + ), + createCompanionCallback: ({ + Value preKeyId = const Value.absent(), + required Uint8List preKey, + Value createdAt = const Value.absent(), + }) => + SignalPreKeyStoresCompanion.insert( + preKeyId: preKeyId, + preKey: preKey, + createdAt: createdAt, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$SignalPreKeyStoresTableProcessedTableManager = ProcessedTableManager< + _$TwonlyDatabase, + $SignalPreKeyStoresTable, + SignalPreKeyStore, + $$SignalPreKeyStoresTableFilterComposer, + $$SignalPreKeyStoresTableOrderingComposer, + $$SignalPreKeyStoresTableAnnotationComposer, + $$SignalPreKeyStoresTableCreateCompanionBuilder, + $$SignalPreKeyStoresTableUpdateCompanionBuilder, + ( + SignalPreKeyStore, + BaseReferences<_$TwonlyDatabase, $SignalPreKeyStoresTable, + SignalPreKeyStore> + ), + SignalPreKeyStore, + PrefetchHooks Function()>; +typedef $$SignalSenderKeyStoresTableCreateCompanionBuilder + = SignalSenderKeyStoresCompanion Function({ + required String senderKeyName, + required Uint8List senderKey, + Value rowid, +}); +typedef $$SignalSenderKeyStoresTableUpdateCompanionBuilder + = SignalSenderKeyStoresCompanion Function({ + Value senderKeyName, + Value senderKey, + Value rowid, +}); + +class $$SignalSenderKeyStoresTableFilterComposer + extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> { + $$SignalSenderKeyStoresTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get senderKeyName => $composableBuilder( + column: $table.senderKeyName, builder: (column) => ColumnFilters(column)); + + ColumnFilters get senderKey => $composableBuilder( + column: $table.senderKey, builder: (column) => ColumnFilters(column)); +} + +class $$SignalSenderKeyStoresTableOrderingComposer + extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> { + $$SignalSenderKeyStoresTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get senderKeyName => $composableBuilder( + column: $table.senderKeyName, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get senderKey => $composableBuilder( + column: $table.senderKey, builder: (column) => ColumnOrderings(column)); +} + +class $$SignalSenderKeyStoresTableAnnotationComposer + extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> { + $$SignalSenderKeyStoresTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get senderKeyName => $composableBuilder( + column: $table.senderKeyName, builder: (column) => column); + + GeneratedColumn get senderKey => + $composableBuilder(column: $table.senderKey, builder: (column) => column); +} + +class $$SignalSenderKeyStoresTableTableManager extends RootTableManager< + _$TwonlyDatabase, + $SignalSenderKeyStoresTable, + SignalSenderKeyStore, + $$SignalSenderKeyStoresTableFilterComposer, + $$SignalSenderKeyStoresTableOrderingComposer, + $$SignalSenderKeyStoresTableAnnotationComposer, + $$SignalSenderKeyStoresTableCreateCompanionBuilder, + $$SignalSenderKeyStoresTableUpdateCompanionBuilder, + ( + SignalSenderKeyStore, + BaseReferences<_$TwonlyDatabase, $SignalSenderKeyStoresTable, + SignalSenderKeyStore> + ), + SignalSenderKeyStore, + PrefetchHooks Function()> { + $$SignalSenderKeyStoresTableTableManager( + _$TwonlyDatabase db, $SignalSenderKeyStoresTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$SignalSenderKeyStoresTableFilterComposer( + $db: db, $table: table), + createOrderingComposer: () => + $$SignalSenderKeyStoresTableOrderingComposer( + $db: db, $table: table), + createComputedFieldComposer: () => + $$SignalSenderKeyStoresTableAnnotationComposer( + $db: db, $table: table), + updateCompanionCallback: ({ + Value senderKeyName = const Value.absent(), + Value senderKey = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SignalSenderKeyStoresCompanion( + senderKeyName: senderKeyName, + senderKey: senderKey, + rowid: rowid, + ), + createCompanionCallback: ({ + required String senderKeyName, + required Uint8List senderKey, + Value rowid = const Value.absent(), + }) => + SignalSenderKeyStoresCompanion.insert( + senderKeyName: senderKeyName, + senderKey: senderKey, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$SignalSenderKeyStoresTableProcessedTableManager + = ProcessedTableManager< + _$TwonlyDatabase, + $SignalSenderKeyStoresTable, + SignalSenderKeyStore, + $$SignalSenderKeyStoresTableFilterComposer, + $$SignalSenderKeyStoresTableOrderingComposer, + $$SignalSenderKeyStoresTableAnnotationComposer, + $$SignalSenderKeyStoresTableCreateCompanionBuilder, + $$SignalSenderKeyStoresTableUpdateCompanionBuilder, + ( + SignalSenderKeyStore, + BaseReferences<_$TwonlyDatabase, $SignalSenderKeyStoresTable, + SignalSenderKeyStore> + ), + SignalSenderKeyStore, + PrefetchHooks Function()>; +typedef $$SignalSessionStoresTableCreateCompanionBuilder + = SignalSessionStoresCompanion Function({ + required int deviceId, + required String name, + required Uint8List sessionRecord, + Value createdAt, + Value rowid, +}); +typedef $$SignalSessionStoresTableUpdateCompanionBuilder + = SignalSessionStoresCompanion Function({ + Value deviceId, + Value name, + Value sessionRecord, + Value createdAt, + Value rowid, +}); + +class $$SignalSessionStoresTableFilterComposer + extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> { + $$SignalSessionStoresTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get deviceId => $composableBuilder( + column: $table.deviceId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get name => $composableBuilder( + column: $table.name, builder: (column) => ColumnFilters(column)); + + ColumnFilters get sessionRecord => $composableBuilder( + column: $table.sessionRecord, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); +} + +class $$SignalSessionStoresTableOrderingComposer + extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> { + $$SignalSessionStoresTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get deviceId => $composableBuilder( + column: $table.deviceId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get name => $composableBuilder( + column: $table.name, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get sessionRecord => $composableBuilder( + column: $table.sessionRecord, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); +} + +class $$SignalSessionStoresTableAnnotationComposer + extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> { + $$SignalSessionStoresTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get deviceId => + $composableBuilder(column: $table.deviceId, builder: (column) => column); + + GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + GeneratedColumn get sessionRecord => $composableBuilder( + column: $table.sessionRecord, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); +} + +class $$SignalSessionStoresTableTableManager extends RootTableManager< + _$TwonlyDatabase, + $SignalSessionStoresTable, + SignalSessionStore, + $$SignalSessionStoresTableFilterComposer, + $$SignalSessionStoresTableOrderingComposer, + $$SignalSessionStoresTableAnnotationComposer, + $$SignalSessionStoresTableCreateCompanionBuilder, + $$SignalSessionStoresTableUpdateCompanionBuilder, + ( + SignalSessionStore, + BaseReferences<_$TwonlyDatabase, $SignalSessionStoresTable, + SignalSessionStore> + ), + SignalSessionStore, + PrefetchHooks Function()> { + $$SignalSessionStoresTableTableManager( + _$TwonlyDatabase db, $SignalSessionStoresTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$SignalSessionStoresTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$SignalSessionStoresTableOrderingComposer( + $db: db, $table: table), + createComputedFieldComposer: () => + $$SignalSessionStoresTableAnnotationComposer( + $db: db, $table: table), + updateCompanionCallback: ({ + Value deviceId = const Value.absent(), + Value name = const Value.absent(), + Value sessionRecord = const Value.absent(), + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SignalSessionStoresCompanion( + deviceId: deviceId, + name: name, + sessionRecord: sessionRecord, + createdAt: createdAt, + rowid: rowid, + ), + createCompanionCallback: ({ + required int deviceId, + required String name, + required Uint8List sessionRecord, + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SignalSessionStoresCompanion.insert( + deviceId: deviceId, + name: name, + sessionRecord: sessionRecord, + createdAt: createdAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$SignalSessionStoresTableProcessedTableManager = ProcessedTableManager< + _$TwonlyDatabase, + $SignalSessionStoresTable, + SignalSessionStore, + $$SignalSessionStoresTableFilterComposer, + $$SignalSessionStoresTableOrderingComposer, + $$SignalSessionStoresTableAnnotationComposer, + $$SignalSessionStoresTableCreateCompanionBuilder, + $$SignalSessionStoresTableUpdateCompanionBuilder, + ( + SignalSessionStore, + BaseReferences<_$TwonlyDatabase, $SignalSessionStoresTable, + SignalSessionStore> + ), + SignalSessionStore, + PrefetchHooks Function()>; class $TwonlyDatabaseManager { final _$TwonlyDatabase _db; @@ -2184,4 +3788,13 @@ class $TwonlyDatabaseManager { $$ContactsTableTableManager(_db, _db.contacts); $$MessagesTableTableManager get messages => $$MessagesTableTableManager(_db, _db.messages); + $$SignalIdentityKeyStoresTableTableManager get signalIdentityKeyStores => + $$SignalIdentityKeyStoresTableTableManager( + _db, _db.signalIdentityKeyStores); + $$SignalPreKeyStoresTableTableManager get signalPreKeyStores => + $$SignalPreKeyStoresTableTableManager(_db, _db.signalPreKeyStores); + $$SignalSenderKeyStoresTableTableManager get signalSenderKeyStores => + $$SignalSenderKeyStoresTableTableManager(_db, _db.signalSenderKeyStores); + $$SignalSessionStoresTableTableManager get signalSessionStores => + $$SignalSessionStoresTableTableManager(_db, _db.signalSessionStores); } diff --git a/lib/src/model/json/message.dart b/lib/src/json_models/message.dart similarity index 100% rename from lib/src/model/json/message.dart rename to lib/src/json_models/message.dart diff --git a/lib/src/model/json/signal_identity.dart b/lib/src/json_models/signal_identity.dart similarity index 100% rename from lib/src/model/json/signal_identity.dart rename to lib/src/json_models/signal_identity.dart diff --git a/lib/src/model/json/signal_identity.g.dart b/lib/src/json_models/signal_identity.g.dart similarity index 100% rename from lib/src/model/json/signal_identity.g.dart rename to lib/src/json_models/signal_identity.g.dart diff --git a/lib/src/model/json/user_data.g.dart b/lib/src/json_models/user_data.g.dart similarity index 96% rename from lib/src/model/json/user_data.g.dart rename to lib/src/json_models/user_data.g.dart index bc123e2..2ddef7d 100644 --- a/lib/src/model/json/user_data.g.dart +++ b/lib/src/json_models/user_data.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'user_data.dart'; +part of 'userdata.dart'; // ************************************************************************** // JsonSerializableGenerator diff --git a/lib/src/model/json/user_data.dart b/lib/src/json_models/userdata.dart similarity index 100% rename from lib/src/model/json/user_data.dart rename to lib/src/json_models/userdata.dart diff --git a/lib/src/model/identity_key_store_model.dart b/lib/src/model/identity_key_store_model.dart deleted file mode 100644 index a8f6d5f..0000000 --- a/lib/src/model/identity_key_store_model.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'dart:typed_data'; - -import 'package:cv/cv.dart'; -import 'package:sqflite_sqlcipher/sqflite.dart'; - -class DbSignalIdentityKeyStore extends CvModelBase { - static const tableName = "signal_identity_key_store"; - - static const columnDeviceId = "device_id"; - final deviceId = CvField(columnDeviceId); - - static const columnName = "name"; - final name = CvField(columnName); - - static const columnIdentityKey = "identity_key"; - final identityKey = CvField(columnIdentityKey); - - static const columnCreatedAt = "created_at"; - final createdAt = CvField(columnCreatedAt); - - static Future setupDatabaseTable(Database db) async { - String createTableString = """ - CREATE TABLE IF NOT EXISTS $tableName ( - $columnDeviceId INTEGER NOT NULL, - $columnName TEXT NOT NULL, - $columnIdentityKey BLOB NOT NULL, - $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY ($columnDeviceId, $columnName) - ) - """; - await db.execute(createTableString); - } - - @override - List get fields => [deviceId, name, identityKey, createdAt]; -} diff --git a/lib/src/model/pre_key_model.dart b/lib/src/model/pre_key_model.dart deleted file mode 100644 index 4280170..0000000 --- a/lib/src/model/pre_key_model.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'dart:typed_data'; -import 'package:cv/cv.dart'; -import 'package:sqflite_sqlcipher/sqflite.dart'; - -class DbSignalPreKeyStore extends CvModelBase { - static const tableName = "signal_pre_key_store"; - - static const columnPreKeyId = "pre_key_id"; - final preKeyId = CvField(columnPreKeyId); - - static const columnPreKey = "pre_key"; - final preKey = CvField(columnPreKey); - - static const columnCreatedAt = "created_at"; - final createdAt = CvField(columnCreatedAt); - - static Future setupDatabaseTable(Database db) async { - String createTableString = """ - CREATE TABLE IF NOT EXISTS $tableName ( - $columnPreKeyId INTEGER NOT NULL, - $columnPreKey BLOB NOT NULL, - $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY ($columnPreKeyId) - ) - """; - await db.execute(createTableString); - } - - @override - List get fields => [preKeyId, preKey, createdAt]; -} diff --git a/lib/src/model/sender_key_store_model.dart b/lib/src/model/sender_key_store_model.dart deleted file mode 100644 index ada0d87..0000000 --- a/lib/src/model/sender_key_store_model.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'dart:typed_data'; -import 'package:cv/cv.dart'; -import 'package:sqflite_sqlcipher/sqflite.dart'; - -class DbSignalSenderKeyStore extends CvModelBase { - static const tableName = "signal_sender_key_store"; - - static const columnSenderKeyName = "sender_key_name"; - final senderKeyName = CvField(columnSenderKeyName); - - static const columnSenderKey = "sender_key"; - final senderKey = CvField(columnSenderKey); - - static const columnCreatedAt = "created_at"; - final createdAt = CvField(columnCreatedAt); - - static Future setupDatabaseTable(Database db) async { - String createTableString = """ - CREATE TABLE IF NOT EXISTS $tableName ( - $columnSenderKeyName TEXT NOT NULL, - $columnSenderKey BLOB NOT NULL, - $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY ($columnSenderKeyName) - ) - """; - await db.execute(createTableString); - } - - @override - List get fields => [senderKeyName, senderKey, createdAt]; -} diff --git a/lib/src/model/session_store_model.dart b/lib/src/model/session_store_model.dart deleted file mode 100644 index b21e70c..0000000 --- a/lib/src/model/session_store_model.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'dart:typed_data'; -import 'package:cv/cv.dart'; -import 'package:sqflite_sqlcipher/sqflite.dart'; - -class DbSignalSessionStore extends CvModelBase { - static const tableName = "signal_session_store"; - - static const columnDeviceId = "device_id"; - final deviceId = CvField(columnDeviceId); - - static const columnName = "name"; - final name = CvField(columnName); - - static const columnSessionRecord = "session_record"; - final sessionRecord = CvField(columnSessionRecord); - - static const columnCreatedAt = "created_at"; - final createdAt = CvField(columnCreatedAt); - - static Future setupDatabaseTable(Database db) async { - String createTableString = """ - CREATE TABLE IF NOT EXISTS $tableName ( - $columnDeviceId INTEGER NOT NULL, - $columnName TEXT NOT NULL, - $columnSessionRecord BLOB NOT NULL, - $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY ($columnDeviceId, $columnName) - ) - """; - await db.execute(createTableString); - } - - @override - List get fields => [deviceId, name, sessionRecord, createdAt]; -} diff --git a/lib/src/providers/api/api.dart b/lib/src/providers/api/api.dart index 9fb0992..80dd0b8 100644 --- a/lib/src/providers/api/api.dart +++ b/lib/src/providers/api/api.dart @@ -3,9 +3,9 @@ import 'package:drift/drift.dart'; import 'package:hive/hive.dart'; import 'package:logging/logging.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/proto/api/error.pb.dart'; import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/providers/hive.dart'; @@ -70,7 +70,7 @@ Future encryptAndSendMessage( if (resp.isSuccess) { if (messageId != null) { - await twonlyDatabase.updateMessageByMessageId( + await twonlyDatabase.messagesDao.updateMessageByMessageId( messageId, MessagesCompanion(acknowledgeByServer: Value(true)), ); @@ -86,7 +86,7 @@ Future sendTextMessage(int target, String message) async { DateTime messageSendAt = DateTime.now(); - int? messageId = await twonlyDatabase.insertMessage( + int? messageId = await twonlyDatabase.messagesDao.insertMessage( MessagesCompanion( contactId: Value(target), kind: Value(MessageKind.textMessage), diff --git a/lib/src/providers/api/media.dart b/lib/src/providers/api/media.dart index eaded7a..a909246 100644 --- a/lib/src/providers/api/media.dart +++ b/lib/src/providers/api/media.dart @@ -5,9 +5,9 @@ import 'package:drift/drift.dart'; import 'package:logging/logging.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/app.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/proto/api/server_to_client.pb.dart'; import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/api_utils.dart'; @@ -19,7 +19,7 @@ Future tryDownloadAllMediaFiles() async { return; } List messages = - await twonlyDatabase.getAllMessagesPendingDownloading(); + await twonlyDatabase.messagesDao.getAllMessagesPendingDownloading(); for (Message message in messages) { MessageContent? content = @@ -163,7 +163,7 @@ class ImageUploader { final downloadToken = uploadState.downloadTokens.removeLast(); - twonlyDatabase.incFlameCounter( + twonlyDatabase.contactsDao.incFlameCounter( targetUserId, false, metadata.messageSendAt, @@ -215,7 +215,7 @@ Future sendImage( // at this point it is safe inform the user about the process of sending the image.. for (final userId in metadata.userIds) { - int? messageId = await twonlyDatabase.insertMessage( + int? messageId = await twonlyDatabase.messagesDao.insertMessage( MessagesCompanion( contactId: Value(userId), kind: Value(MessageKind.media), @@ -284,7 +284,7 @@ Future tryDownloadMedia( box.put("${content.downloadToken!}_messageId", messageId); - await twonlyDatabase.updateMessageByOtherUser( + await twonlyDatabase.messagesDao.updateMessageByOtherUser( fromUserId, messageId, MessagesCompanion( @@ -307,7 +307,7 @@ Future getDownloadedMedia( // await userOpenedOtherMessage(otherUserId, messageOtherId); notifyContactAboutOpeningMessage(message.contactId, message.messageOtherId!); - twonlyDatabase.updateMessageByMessageId( + twonlyDatabase.messagesDao.updateMessageByMessageId( message.messageId, MessagesCompanion(openedAt: Value(DateTime.now()))); box.delete(downloadToken.toString()); diff --git a/lib/src/providers/api/server_messages.dart b/lib/src/providers/api/server_messages.dart index 6fefbf2..32a2e90 100644 --- a/lib/src/providers/api/server_messages.dart +++ b/lib/src/providers/api/server_messages.dart @@ -7,9 +7,9 @@ import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; import 'package:logging/logging.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/app.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/proto/api/client_to_server.pb.dart' as client; import 'package:twonly/src/proto/api/client_to_server.pbserver.dart'; import 'package:twonly/src/proto/api/error.pb.dart'; @@ -76,7 +76,7 @@ Future handleDownloadData(DownloadData data) async { if (data.fin && data.data.isEmpty) { // media file was deleted by the server. remove the media from device - await twonlyDatabase.deleteMessageById(messageId); + await twonlyDatabase.messagesDao.deleteMessageById(messageId); box.delete(boxId); box.delete("${data.downloadToken}_downloaded"); var ok = client.Response_Ok()..none = true; @@ -111,8 +111,9 @@ Future handleDownloadData(DownloadData data) async { // Uint8List? rawBytes = // await SignalHelper.decryptBytes(downloadedBytes, fromUserId); - Message? msg = - await twonlyDatabase.getMessageByMessageId(messageId).getSingleOrNull(); + Message? msg = await twonlyDatabase.messagesDao + .getMessageByMessageId(messageId) + .getSingleOrNull(); if (msg == null) { Logger("server_messages") .info("messageId not found in database. Ignoring download"); @@ -141,13 +142,13 @@ Future handleDownloadData(DownloadData data) async { } catch (e) { Logger("server_messages").info("Decryption error: $e"); // deleting message as this is an invalid image - await twonlyDatabase.deleteMessageById(messageId); + await twonlyDatabase.messagesDao.deleteMessageById(messageId); // answers with ok, so the server will delete the message var ok = client.Response_Ok()..none = true; return client.Response()..ok = ok; } - await twonlyDatabase.updateMessageByOtherUser( + await twonlyDatabase.messagesDao.updateMessageByOtherUser( msg.contactId, messageId, MessagesCompanion(downloadState: Value(DownloadState.downloaded)), @@ -168,7 +169,8 @@ Future handleNewMessage(int fromUserId, Uint8List body) async { if (username.isSuccess) { Uint8List name = username.value.userdata.username; - int added = await twonlyDatabase.insertContact(ContactsCompanion( + int added = + await twonlyDatabase.contactsDao.insertContact(ContactsCompanion( username: Value(utf8.decode(name)), userId: Value(fromUserId), requested: Value(true), @@ -184,23 +186,23 @@ Future handleNewMessage(int fromUserId, Uint8List body) async { break; case MessageKind.opened: final update = MessagesCompanion(openedAt: Value(message.timestamp)); - await twonlyDatabase.updateMessageByOtherUser( + await twonlyDatabase.messagesDao.updateMessageByOtherUser( fromUserId, message.messageId!, update, ); break; case MessageKind.rejectRequest: - await twonlyDatabase.deleteContactByUserId(fromUserId); + await twonlyDatabase.contactsDao.deleteContactByUserId(fromUserId); break; case MessageKind.acceptRequest: final update = ContactsCompanion(accepted: Value(true)); - twonlyDatabase.updateContact(fromUserId, update); + twonlyDatabase.contactsDao.updateContact(fromUserId, update); localPushNotificationNewMessage(fromUserId.toInt(), message, 8888888); break; case MessageKind.ack: final update = MessagesCompanion(acknowledgeByUser: Value(true)); - await twonlyDatabase.updateMessageByOtherUser( + await twonlyDatabase.messagesDao.updateMessageByOtherUser( fromUserId, message.messageId!, update, @@ -226,7 +228,7 @@ Future handleNewMessage(int fromUserId, Uint8List body) async { sendAt: Value(message.timestamp), ); - final messageId = await twonlyDatabase.insertMessage( + final messageId = await twonlyDatabase.messagesDao.insertMessage( update, ); @@ -246,7 +248,7 @@ Future handleNewMessage(int fromUserId, Uint8List body) async { ); if (message.kind == MessageKind.media) { - twonlyDatabase.incFlameCounter( + twonlyDatabase.contactsDao.incFlameCounter( fromUserId, true, message.timestamp, diff --git a/lib/src/providers/db_provider.dart b/lib/src/providers/db_provider.dart deleted file mode 100644 index 2160718..0000000 --- a/lib/src/providers/db_provider.dart +++ /dev/null @@ -1,72 +0,0 @@ -import 'dart:async'; -import 'dart:math'; -import 'package:twonly/src/model/identity_key_store_model.dart'; -import 'package:twonly/src/model/pre_key_model.dart'; -import 'package:twonly/src/model/sender_key_store_model.dart'; -import 'package:twonly/src/model/session_store_model.dart'; -import 'package:sqflite_sqlcipher/sqflite.dart'; -import 'package:twonly/src/utils/misc.dart'; - -class DbProvider { - Database? db; - - static const String dbName = 'twonly.db'; - - Future openPath(String path) async { - // Read the password for the database from the secure storage. If there is no, then create a - // new cryptographically secure random password with 32 bytes and store them in the secure storage. - // So if someone dumps the app for example using a tool like Cellebrite including the apps - // content he is not able to access the databases content. - // (https://signal.org/blog/cellebrite-and-clickbait/) - // - // CHECK: Does this actually improve the security or is this just security through obscurity and - // can be removed as it does increase complexity? - // Current thoughts: As the database password is at some point in the memory the attacker could - // just dump it. Questions here: What capabilities must the attacker have to do that? - - final storage = getSecureStorage(); - var password = await storage.read(key: "sqflite_database_password"); - if (password == null) { - var secureRandom = Random.secure(); - password = ""; - for (var i = 0; i < 32; i++) { - password = "$password${String.fromCharCode(secureRandom.nextInt(256))}"; - } - await storage.write(key: "sqflite_database_password", value: password); - } - - db = await openDatabase(path, password: password); - if (db != null) { - await setupDatabaseTable(db!); - } - } - - Future get ready async { - if (db == null) { - await open(); - } - return db; - } - - Future setupDatabaseTable(Database db) async { - await DbSignalSessionStore.setupDatabaseTable(db); - await DbSignalPreKeyStore.setupDatabaseTable(db); - await DbSignalSenderKeyStore.setupDatabaseTable(db); - await DbSignalIdentityKeyStore.setupDatabaseTable(db); - } - - Future open() async { - await openPath(await fixPath(dbName)); - } - - Future remove() async { - await deleteDatabase(await fixPath(dbName)); - // await _createDb(db!); - } - - Future fixPath(String path) async => path; - - Future close() async { - await db!.close(); - } -} diff --git a/lib/src/services/fcm_service.dart b/lib/src/services/fcm_service.dart index 0f87461..4242982 100644 --- a/lib/src/services/fcm_service.dart +++ b/lib/src/services/fcm_service.dart @@ -3,7 +3,7 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:logging/logging.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/app.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/providers/api_provider.dart'; import 'package:twonly/src/utils/misc.dart'; diff --git a/lib/src/services/notification_service.dart b/lib/src/services/notification_service.dart index b876891..050ff35 100644 --- a/lib/src/services/notification_service.dart +++ b/lib/src/services/notification_service.dart @@ -4,9 +4,9 @@ import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:logging/logging.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/model/json/message.dart' as my; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/json_models/message.dart' as my; /// Streams are created so that app can respond to notification-related events /// since the plugin is initialized in the `main` function @@ -167,8 +167,9 @@ String getPushNotificationText(String key, String userName) { Future localPushNotificationNewMessage( int fromUserId, my.MessageJson message, int messageId) async { - Contact? user = - await twonlyDatabase.getContactByUserId(fromUserId).getSingleOrNull(); + Contact? user = await twonlyDatabase.contactsDao + .getContactByUserId(fromUserId) + .getSingleOrNull(); if (user == null) return; diff --git a/lib/src/signal/connect_identitiy_key_store.dart b/lib/src/signal/connect_identitiy_key_store.dart index 5f371fe..55ae180 100644 --- a/lib/src/signal/connect_identitiy_key_store.dart +++ b/lib/src/signal/connect_identitiy_key_store.dart @@ -1,14 +1,8 @@ -import 'dart:typed_data'; import 'package:collection/collection.dart'; +import 'package:drift/drift.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/model/identity_key_store_model.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; - -bool eq(List? list1, List? list2) => - ListEquality().equals(list1, list2); - -// make it easier to read -typedef DB = DbSignalIdentityKeyStore; +import 'package:twonly/src/database/twonly_database.dart'; class ConnectIdentityKeyStore extends IdentityKeyStore { ConnectIdentityKeyStore(this.identityKeyPair, this.localRegistrationId); @@ -18,15 +12,15 @@ class ConnectIdentityKeyStore extends IdentityKeyStore { @override Future getIdentity(SignalProtocolAddress address) async { - var dbIdentityKey = (await dbProvider.db!.query(DB.tableName, - columns: [DB.columnIdentityKey], - where: '${DB.columnDeviceId} = ? AND ${DB.columnName} = ?', - whereArgs: [address.getDeviceId(), address.getName()])); - if (dbIdentityKey.isEmpty) { - return null; - } - Uint8List identityKey = dbIdentityKey.first.cast()[DB.columnIdentityKey]; - return IdentityKey.fromBytes(identityKey, 0); + SignalIdentityKeyStore? identity = + await (twonlyDatabase.select(twonlyDatabase.signalIdentityKeyStores) + ..where((t) => + t.deviceId.equals(address.getDeviceId()) & + t.name.equals(address.getName()))) + .getSingleOrNull(); + + if (identity == null) return null; + return IdentityKey.fromBytes(identity.identityKey, 0); } @override @@ -42,7 +36,8 @@ class ConnectIdentityKeyStore extends IdentityKeyStore { if (identityKey == null) { return false; } - return trusted == null || eq(trusted.serialize(), identityKey.serialize()); + return trusted == null || + ListEquality().equals(trusted.serialize(), identityKey.serialize()); } @override @@ -52,16 +47,23 @@ class ConnectIdentityKeyStore extends IdentityKeyStore { return false; } if (await getIdentity(address) == null) { - await dbProvider.db!.insert(DB.tableName, { - DB.columnDeviceId: address.getDeviceId(), - DB.columnName: address.getName(), - DB.columnIdentityKey: identityKey.serialize() - }); + await twonlyDatabase.into(twonlyDatabase.signalIdentityKeyStores).insert( + SignalIdentityKeyStoresCompanion( + deviceId: Value(address.getDeviceId()), + name: Value(address.getName()), + identityKey: Value(identityKey.serialize()), + ), + ); } else { - await dbProvider.db!.update( - DB.tableName, {DB.columnIdentityKey: identityKey.serialize()}, - where: '${DB.columnDeviceId} = ? AND ${DB.columnName} = ?', - whereArgs: [address.getDeviceId(), address.getName()]); + await (twonlyDatabase.update(twonlyDatabase.signalIdentityKeyStores) + ..where((t) => + t.deviceId.equals(address.getDeviceId()) & + t.name.equals(address.getName()))) + .write( + SignalIdentityKeyStoresCompanion( + identityKey: Value(identityKey.serialize()), + ), + ); } return true; } diff --git a/lib/src/signal/connect_pre_key_store.dart b/lib/src/signal/connect_pre_key_store.dart index a117af0..04eb501 100644 --- a/lib/src/signal/connect_pre_key_store.dart +++ b/lib/src/signal/connect_pre_key_store.dart @@ -1,49 +1,52 @@ -import 'dart:typed_data'; +import 'package:drift/drift.dart'; +import 'package:logging/logging.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/model/pre_key_model.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; - -typedef DB = DbSignalPreKeyStore; +import 'package:twonly/src/database/twonly_database.dart'; class ConnectPreKeyStore extends PreKeyStore { @override Future containsPreKey(int preKeyId) async { - final dbPreKey = await dbProvider.db!.query(DB.tableName, - columns: [DB.columnPreKey], - where: '${DB.columnPreKeyId} = ?', - whereArgs: [preKeyId]); - return dbPreKey.isNotEmpty; + final preKeyRecord = + await (twonlyDatabase.select(twonlyDatabase.signalPreKeyStores) + ..where((tbl) => tbl.preKeyId.equals(preKeyId))) + .get(); + return preKeyRecord.isNotEmpty; } @override Future loadPreKey(int preKeyId) async { - final dbPreKey = await dbProvider.db!.query(DB.tableName, - columns: [DB.columnPreKey], - where: '${DB.columnPreKeyId} = ?', - whereArgs: [preKeyId]); - if (dbPreKey.isEmpty) { + final preKeyRecord = + await (twonlyDatabase.select(twonlyDatabase.signalPreKeyStores) + ..where((tbl) => tbl.preKeyId.equals(preKeyId))) + .get(); + if (preKeyRecord.isEmpty) { throw InvalidKeyIdException('No such preKey record! - $preKeyId'); } - Uint8List preKey = dbPreKey.first.cast()[DB.columnPreKey]; + Uint8List preKey = preKeyRecord.first.preKey; return PreKeyRecord.fromBuffer(preKey); } @override Future removePreKey(int preKeyId) async { - await dbProvider.db!.delete(DB.tableName, - where: '${DB.columnPreKeyId} = ?', - whereArgs: [DB.columnPreKeyId]); + await (twonlyDatabase.delete(twonlyDatabase.signalPreKeyStores) + ..where((tbl) => tbl.preKeyId.equals(preKeyId))) + .go(); } @override Future storePreKey(int preKeyId, PreKeyRecord record) async { - if (!await containsPreKey(preKeyId)) { - await dbProvider.db!.insert(DB.tableName, - {DB.columnPreKeyId: preKeyId, DB.columnPreKey: record.serialize()}); - } else { - await dbProvider.db!.update( - DB.tableName, {DB.columnPreKey: record.serialize()}, - where: '${DB.columnPreKeyId} = ?', whereArgs: [preKeyId]); + final preKeyCompanion = SignalPreKeyStoresCompanion( + preKeyId: Value(preKeyId), + preKey: Value(record.serialize()), + ); + + try { + await twonlyDatabase + .into(twonlyDatabase.signalPreKeyStores) + .insert(preKeyCompanion); + } catch (e) { + Logger("pre_key_store").shout("$e"); } } } diff --git a/lib/src/signal/connect_sender_key_store.dart b/lib/src/signal/connect_sender_key_store.dart index 90c9b12..47f8aee 100644 --- a/lib/src/signal/connect_sender_key_store.dart +++ b/lib/src/signal/connect_sender_key_store.dart @@ -1,31 +1,30 @@ -import 'dart:typed_data'; +import 'package:drift/drift.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/model/sender_key_store_model.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; -typedef DB = DbSignalSenderKeyStore; - class ConnectSenderKeyStore extends SenderKeyStore { @override Future loadSenderKey(SenderKeyName senderKeyName) async { - final dbSenderKey = await dbProvider.db!.query(DB.tableName, - columns: [DB.columnSenderKey], - where: '${DB.columnSenderKeyName} = ?', - whereArgs: [senderKeyName.serialize()]); - if (dbSenderKey.isEmpty) { + SignalSenderKeyStore? identity = + await (twonlyDatabase.select(twonlyDatabase.signalSenderKeyStores) + ..where((t) => t.senderKeyName.equals(senderKeyName.serialize()))) + .getSingleOrNull(); + if (identity == null) { throw InvalidKeyIdException( 'No such sender key record! - $senderKeyName'); } - Uint8List preKey = dbSenderKey.first.cast()[DB.columnSenderKey]; - return SenderKeyRecord.fromSerialized(preKey); + return SenderKeyRecord.fromSerialized(identity.senderKey); } @override Future storeSenderKey( SenderKeyName senderKeyName, SenderKeyRecord record) async { - await dbProvider.db!.insert(DB.tableName, { - DB.columnSenderKeyName: senderKeyName.serialize(), - DB.columnSenderKey: record.serialize() - }); + await twonlyDatabase.into(twonlyDatabase.signalSenderKeyStores).insert( + SignalSenderKeyStoresCompanion( + senderKey: Value(record.serialize()), + senderKeyName: Value(senderKeyName.serialize()), + ), + ); } } diff --git a/lib/src/signal/connect_session_store.dart b/lib/src/signal/connect_session_store.dart index 74d1cf2..f811fe4 100644 --- a/lib/src/signal/connect_session_store.dart +++ b/lib/src/signal/connect_session_store.dart @@ -1,73 +1,81 @@ -import 'dart:typed_data'; +import 'package:drift/drift.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/model/session_store_model.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; - -// make it easier to read -typedef DB = DbSignalSessionStore; +import 'package:twonly/src/database/twonly_database.dart'; class ConnectSessionStore extends SessionStore { - ConnectSessionStore(); - @override Future containsSession(SignalProtocolAddress address) async { - var list = (await dbProvider.db!.query(DB.tableName, - columns: [], - where: '${DB.columnDeviceId} = ? AND ${DB.columnName} = ?', - whereArgs: [address.getDeviceId(), address.getName()])); - return list.isNotEmpty; + final sessions = + await (twonlyDatabase.select(twonlyDatabase.signalSessionStores) + ..where((tbl) => + tbl.deviceId.equals(address.getDeviceId()) & + tbl.name.equals(address.getName()))) + .get(); + return sessions.isNotEmpty; } @override Future deleteAllSessions(String name) async { - await dbProvider.db!.delete(DB.tableName, - where: '${DB.columnName} = ?', whereArgs: [name]); + await (twonlyDatabase.delete(twonlyDatabase.signalSessionStores) + ..where((tbl) => tbl.name.equals(name))) + .go(); } @override Future deleteSession(SignalProtocolAddress address) async { - await dbProvider.db!.delete(DB.tableName, - where: '${DB.columnDeviceId} = ? AND ${DB.columnName} = ?', - whereArgs: [address.getDeviceId(), address.getName()]); + await (twonlyDatabase.delete(twonlyDatabase.signalSessionStores) + ..where((tbl) => + tbl.deviceId.equals(address.getDeviceId()) & + tbl.name.equals(address.getName()))) + .go(); } @override Future> getSubDeviceSessions(String name) async { - var deviceIds = (await dbProvider.db!.query(DB.tableName, - columns: [DB.columnDeviceId], - where: '${DB.columnDeviceId} != 1 AND ${DB.columnName} = ?', - whereArgs: [name])); - return deviceIds.cast(); + final deviceIds = await (twonlyDatabase + .select(twonlyDatabase.signalSessionStores) + ..where( + (tbl) => tbl.deviceId.equals(1).not() & tbl.name.equals(name))) + .get(); + return deviceIds.map((row) => row.deviceId).toList(); } @override Future loadSession(SignalProtocolAddress address) async { - var dbSession = (await dbProvider.db!.query(DB.tableName, - columns: [DB.columnSessionRecord], - where: '${DB.columnDeviceId} = ? AND ${DB.columnName} = ?', - whereArgs: [address.getDeviceId(), address.getName()])); + final dbSession = + await (twonlyDatabase.select(twonlyDatabase.signalSessionStores) + ..where((tbl) => + tbl.deviceId.equals(address.getDeviceId()) & + tbl.name.equals(address.getName()))) + .get(); if (dbSession.isEmpty) { return SessionRecord(); } - Uint8List session = dbSession.first.cast()[DB.columnSessionRecord]; + Uint8List session = dbSession.first.sessionRecord; return SessionRecord.fromSerialized(session); } @override Future storeSession( SignalProtocolAddress address, SessionRecord record) async { + final sessionCompanion = SignalSessionStoresCompanion( + deviceId: Value(address.getDeviceId()), + name: Value(address.getName()), + sessionRecord: Value(record.serialize()), + ); + if (!await containsSession(address)) { - await dbProvider.db!.insert(DB.tableName, { - DB.columnDeviceId: address.getDeviceId(), - DB.columnName: address.getName(), - DB.columnSessionRecord: record.serialize() - }); + await twonlyDatabase + .into(twonlyDatabase.signalSessionStores) + .insert(sessionCompanion); } else { - await dbProvider.db!.update( - DB.tableName, {DB.columnSessionRecord: record.serialize()}, - where: '${DB.columnDeviceId} = ? AND ${DB.columnName} = ?', - whereArgs: [address.getDeviceId(), address.getName()]); + await (twonlyDatabase.update(twonlyDatabase.signalSessionStores) + ..where((tbl) => + tbl.deviceId.equals(address.getDeviceId()) & + tbl.name.equals(address.getName()))) + .write(sessionCompanion); } } } diff --git a/lib/src/utils/misc.dart b/lib/src/utils/misc.dart index 2528d66..e193344 100644 --- a/lib/src/utils/misc.dart +++ b/lib/src/utils/misc.dart @@ -10,8 +10,7 @@ import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:provider/provider.dart'; -import 'package:sqflite_sqlcipher/sqflite.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/proto/api/error.pb.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -20,18 +19,6 @@ extension ShortCutsExtension on BuildContext { TwonlyDatabase get db => Provider.of(this); } -// Function to check if a column exists -Future columnExists( - Database db, String tableName, String columnName) async { - final result = await db.rawQuery('PRAGMA table_info($tableName)'); - for (var row in result) { - if (row['name'] == columnName) { - return true; // Column exists - } - } - return false; // Column does not exist -} - Future writeLogToFile(LogRecord record) async { final directory = await getApplicationDocumentsDirectory(); final logFile = File('${directory.path}/app.log'); diff --git a/lib/src/utils/signal.dart b/lib/src/utils/signal.dart index ba1d855..4adc12f 100644 --- a/lib/src/utils/signal.dart +++ b/lib/src/utils/signal.dart @@ -3,9 +3,9 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; import 'package:logging/logging.dart'; -import 'package:twonly/src/model/json/message.dart'; -import 'package:twonly/src/model/json/signal_identity.dart'; -import 'package:twonly/src/model/json/user_data.dart'; +import 'package:twonly/src/json_models/message.dart'; +import 'package:twonly/src/json_models/signal_identity.dart'; +import 'package:twonly/src/json_models/userdata.dart'; import 'package:twonly/src/proto/api/server_to_client.pb.dart'; import 'package:twonly/src/signal/connect_signal_protocol_store.dart'; import 'package:twonly/src/utils/misc.dart'; diff --git a/lib/src/utils/storage.dart b/lib/src/utils/storage.dart index 42c9c92..2aa643d 100644 --- a/lib/src/utils/storage.dart +++ b/lib/src/utils/storage.dart @@ -1,8 +1,7 @@ import 'dart:convert'; import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:twonly/globals.dart'; -import 'package:twonly/src/model/json/user_data.dart'; +import 'package:twonly/src/json_models/userdata.dart'; import 'package:twonly/src/utils/misc.dart'; Future isUserCreated() async { @@ -15,7 +14,7 @@ Future isUserCreated() async { Future getUser() async { final storage = getSecureStorage(); - String? userJson = await storage.read(key: "user_data"); + String? userJson = await storage.read(key: "userData"); if (userJson == null) { return null; } @@ -30,16 +29,11 @@ Future getUser() async { } Future deleteLocalUserData() async { - final storage = getSecureStorage(); - var password = await storage.read(key: "sqflite_database_password"); - await dbProvider.remove(); - final appDir = await getApplicationSupportDirectory(); if (appDir.existsSync()) { appDir.deleteSync(recursive: true); } - - await storage.write(key: "sqflite_database_password", value: password); + final storage = getSecureStorage(); await storage.deleteAll(); return true; } diff --git a/lib/src/views/camera_to_share/share_image_editor_view.dart b/lib/src/views/camera_to_share/share_image_editor_view.dart index 53c6fd6..c78f3de 100644 --- a/lib/src/views/camera_to_share/share_image_editor_view.dart +++ b/lib/src/views/camera_to_share/share_image_editor_view.dart @@ -5,8 +5,8 @@ import 'package:twonly/globals.dart'; import 'package:twonly/src/components/image_editor/action_button.dart'; import 'package:twonly/src/components/media_view_sizing.dart'; import 'package:twonly/src/components/notification_badge.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/providers/api/media.dart'; import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/utils/misc.dart'; @@ -55,8 +55,9 @@ class _ShareImageEditorView extends State { Future updateAsync(int userId) async { if (sendNextMediaToUserName != null) return; - Contact? contact = - await twonlyDatabase.getContactByUserId(userId).getSingleOrNull(); + Contact? contact = await twonlyDatabase.contactsDao + .getContactByUserId(userId) + .getSingleOrNull(); if (contact != null) { sendNextMediaToUserName = getContactDisplayName(contact); } diff --git a/lib/src/views/camera_to_share/share_image_view.dart b/lib/src/views/camera_to_share/share_image_view.dart index cc84ed2..927c634 100644 --- a/lib/src/views/camera_to_share/share_image_view.dart +++ b/lib/src/views/camera_to_share/share_image_view.dart @@ -10,8 +10,8 @@ import 'package:twonly/src/components/flame.dart'; import 'package:twonly/src/components/headline.dart'; import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/components/verified_shield.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/providers/api/media.dart'; import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/utils/misc.dart'; @@ -54,7 +54,7 @@ class _ShareImageView extends State { } Stream> allContacts = - twonlyDatabase.watchContactsForChatList(); + twonlyDatabase.contactsDao.watchContactsForChatList(); contactSub = allContacts.listen((allContacts) { setState(() { diff --git a/lib/src/views/chats/chat_item_details_view.dart b/lib/src/views/chats/chat_item_details_view.dart index 2accfe3..24e3879 100644 --- a/lib/src/views/chats/chat_item_details_view.dart +++ b/lib/src/views/chats/chat_item_details_view.dart @@ -9,10 +9,10 @@ import 'package:twonly/src/components/animate_icon.dart'; import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/components/message_send_state_icon.dart'; import 'package:twonly/src/components/verified_shield.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/media.dart'; import 'package:twonly/src/providers/send_next_media_to.dart'; @@ -158,8 +158,9 @@ class _ChatItemDetailsViewState extends State { } Future initStreams() async { - await twonlyDatabase.removeOldMessages(); - Stream contact = twonlyDatabase.watchContact(widget.userid); + await twonlyDatabase.messagesDao.removeOldMessages(); + Stream contact = + twonlyDatabase.contactsDao.watchContact(widget.userid); userSub = contact.listen((contact) { setState(() { user = contact; @@ -167,7 +168,7 @@ class _ChatItemDetailsViewState extends State { }); Stream> msgStream = - twonlyDatabase.watchAllMessagesFrom(widget.userid); + twonlyDatabase.messagesDao.watchAllMessagesFrom(widget.userid); messageSub = msgStream.listen((msgs) { if (!context.mounted) return; var updated = false; @@ -181,7 +182,7 @@ class _ChatItemDetailsViewState extends State { } } if (updated) { - twonlyDatabase.openedAllTextMessages(widget.userid); + twonlyDatabase.messagesDao.openedAllTextMessages(widget.userid); } else { // The stream should be get an update, so only update the UI when all are opened setState(() { diff --git a/lib/src/views/chats/chat_list_view.dart b/lib/src/views/chats/chat_list_view.dart index 827aceb..475f4be 100644 --- a/lib/src/views/chats/chat_list_view.dart +++ b/lib/src/views/chats/chat_list_view.dart @@ -9,10 +9,10 @@ import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/components/message_send_state_icon.dart'; import 'package:twonly/src/components/notification_badge.dart'; import 'package:twonly/src/components/user_context_menu.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/providers/api/media.dart'; import 'package:twonly/src/providers/send_next_media_to.dart'; import 'package:twonly/src/utils/misc.dart'; @@ -50,7 +50,7 @@ class _ChatListViewState extends State { // title: actions: [ StreamBuilder( - stream: twonlyDatabase.watchContactsRequested(), + stream: twonlyDatabase.contactsDao.watchContactsRequested(), builder: (context, snapshot) { var count = 0; if (snapshot.hasData && snapshot.data != null) { @@ -86,7 +86,7 @@ class _ChatListViewState extends State { ], ), body: StreamBuilder( - stream: twonlyDatabase.watchContactsForChatList(), + stream: twonlyDatabase.contactsDao.watchContactsForChatList(), builder: (context, snapshot) { if (!snapshot.hasData || snapshot.data == null) { return Container(); @@ -190,7 +190,8 @@ class _UserListItem extends State { child: ListTile( title: Text(getContactDisplayName(widget.user)), subtitle: StreamBuilder( - stream: twonlyDatabase.watchLastMessage(widget.user.userId), + stream: + twonlyDatabase.messagesDao.watchLastMessage(widget.user.userId), builder: (context, lastMessageSnapshot) { if (!lastMessageSnapshot.hasData) { return Container(); @@ -200,7 +201,8 @@ class _UserListItem extends State { } final lastMessage = lastMessageSnapshot.data!.first; return StreamBuilder( - stream: twonlyDatabase.watchMessageNotOpened(widget.user.userId), + stream: twonlyDatabase.messagesDao + .watchMessageNotOpened(widget.user.userId), builder: (context, notOpenedMessagesSnapshot) { if (!lastMessageSnapshot.hasData) { return Container(); diff --git a/lib/src/views/chats/media_viewer_view.dart b/lib/src/views/chats/media_viewer_view.dart index 0002839..5d123b2 100644 --- a/lib/src/views/chats/media_viewer_view.dart +++ b/lib/src/views/chats/media_viewer_view.dart @@ -9,9 +9,9 @@ import 'package:provider/provider.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/components/animate_icon.dart'; import 'package:twonly/src/components/media_view_sizing.dart'; -import 'package:twonly/src/database/database.dart'; -import 'package:twonly/src/database/messages_db.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/media.dart'; import 'package:twonly/src/providers/send_next_media_to.dart'; @@ -57,7 +57,7 @@ class _MediaViewerViewState extends State { Future asyncLoadNextMedia(bool firstRun) async { Stream> messages = - twonlyDatabase.watchMediaMessageNotOpened(widget.userId); + twonlyDatabase.messagesDao.watchMediaMessageNotOpened(widget.userId); _subscription = messages.listen((messages) { for (Message msg in messages) { diff --git a/lib/src/views/chats/search_username_view.dart b/lib/src/views/chats/search_username_view.dart index 178a104..dbdb997 100644 --- a/lib/src/views/chats/search_username_view.dart +++ b/lib/src/views/chats/search_username_view.dart @@ -2,13 +2,13 @@ import 'dart:async'; import 'package:drift/drift.dart' hide Column; import 'package:flutter/material.dart'; import 'package:twonly/src/components/alert_dialog.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/components/headline.dart'; import 'package:twonly/src/components/initialsavatar.dart'; -import 'package:twonly/src/model/json/message.dart'; +import 'package:twonly/src/json_models/message.dart'; import 'package:twonly/src/providers/api/api.dart'; // ignore: library_prefixes import 'package:twonly/src/utils/signal.dart' as SignalHelper; @@ -49,7 +49,8 @@ class _SearchUsernameView extends State { return; } - int added = await twonlyDatabase.insertContact(ContactsCompanion( + int added = + await twonlyDatabase.contactsDao.insertContact(ContactsCompanion( username: Value(searchUserName.text), userId: Value(res.value.userdata.userId.toInt()), requested: Value(false), @@ -97,7 +98,8 @@ class _SearchUsernameView extends State { ); } - Stream> contacts = twonlyDatabase.watchNotAcceptedContacts(); + Stream> contacts = + twonlyDatabase.contactsDao.watchNotAcceptedContacts(); return Scaffold( appBar: AppBar( @@ -195,8 +197,8 @@ class _ContactsListViewState extends State { color: const Color.fromARGB(164, 244, 67, 54)), onPressed: () async { final update = ContactsCompanion(blocked: Value(true)); - await twonlyDatabase.updateContact( - contact.userId, update); + await twonlyDatabase.contactsDao + .updateContact(contact.userId, update); }, ), ), @@ -205,7 +207,7 @@ class _ContactsListViewState extends State { child: IconButton( icon: Icon(Icons.close, color: Colors.red), onPressed: () async { - await twonlyDatabase + await twonlyDatabase.contactsDao .deleteContactByUserId(contact.userId); encryptAndSendMessage( null, @@ -223,7 +225,8 @@ class _ContactsListViewState extends State { icon: Icon(Icons.check, color: Colors.green), onPressed: () async { final update = ContactsCompanion(accepted: Value(true)); - await twonlyDatabase.updateContact(contact.userId, update); + await twonlyDatabase.contactsDao + .updateContact(contact.userId, update); encryptAndSendMessage( null, contact.userId, diff --git a/lib/src/views/contact/contact_verify_view.dart b/lib/src/views/contact/contact_verify_view.dart index 75808ab..e11f75d 100644 --- a/lib/src/views/contact/contact_verify_view.dart +++ b/lib/src/views/contact/contact_verify_view.dart @@ -6,8 +6,8 @@ import 'package:qr_flutter/qr_flutter.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/components/format_long_string.dart'; import 'package:flutter/material.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/signal.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -37,7 +37,7 @@ class _ContactVerifyViewState extends State { @override Widget build(BuildContext context) { - Stream contact = twonlyDatabase + Stream contact = twonlyDatabase.contactsDao .getContactByUserId(widget.contact.userId) .watchSingleOrNull(); @@ -145,7 +145,8 @@ class _ContactVerifyViewState extends State { onPressed: () { final update = ContactsCompanion(verified: Value(false)); - twonlyDatabase.updateContact(contact.userId, update); + twonlyDatabase.contactsDao + .updateContact(contact.userId, update); }, label: Text( context.lang.contactVerifyNumberClearVerification), @@ -155,7 +156,8 @@ class _ContactVerifyViewState extends State { icon: FaIcon(FontAwesomeIcons.shieldHeart), onPressed: () { final update = ContactsCompanion(verified: Value(true)); - twonlyDatabase.updateContact(contact.userId, update); + twonlyDatabase.contactsDao + .updateContact(contact.userId, update); }, label: Text(context.lang.contactVerifyNumberMarkAsVerified), ); diff --git a/lib/src/views/contact/contact_view.dart b/lib/src/views/contact/contact_view.dart index aff6705..84e05a5 100644 --- a/lib/src/views/contact/contact_view.dart +++ b/lib/src/views/contact/contact_view.dart @@ -7,8 +7,8 @@ import 'package:twonly/src/components/flame.dart'; import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/components/verified_shield.dart'; import 'package:flutter/material.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/views/contact/contact_verify_view.dart'; @@ -24,8 +24,9 @@ class ContactView extends StatefulWidget { class _ContactViewState extends State { @override Widget build(BuildContext context) { - Stream contact = - twonlyDatabase.getContactByUserId(widget.userId).watchSingleOrNull(); + Stream contact = twonlyDatabase.contactsDao + .getContactByUserId(widget.userId) + .watchSingleOrNull(); return Scaffold( appBar: AppBar( @@ -79,7 +80,8 @@ class _ContactViewState extends State { if (context.mounted && nickName != null && nickName != "") { final update = ContactsCompanion(nickName: Value(nickName)); - twonlyDatabase.updateContact(contact.userId, update); + twonlyDatabase.contactsDao + .updateContact(contact.userId, update); } }, ), @@ -109,8 +111,8 @@ class _ContactViewState extends State { if (block) { final update = ContactsCompanion(blocked: Value(true)); if (context.mounted) { - await twonlyDatabase.updateContact( - contact.userId, update); + await twonlyDatabase.contactsDao + .updateContact(contact.userId, update); } if (context.mounted) { Navigator.popUntil(context, (route) => route.isFirst); diff --git a/lib/src/views/onboarding/register_view.dart b/lib/src/views/onboarding/register_view.dart index f07e6b7..7130cab 100644 --- a/lib/src/views/onboarding/register_view.dart +++ b/lib/src/views/onboarding/register_view.dart @@ -5,7 +5,7 @@ import 'package:twonly/globals.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:twonly/src/components/alert_dialog.dart'; -import 'package:twonly/src/model/json/user_data.dart'; +import 'package:twonly/src/json_models/userdata.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/signal.dart'; @@ -43,7 +43,7 @@ class _RegisterViewState extends State { username: username, displayName: username, ); - storage.write(key: "user_data", value: jsonEncode(userData)); + storage.write(key: "userData", value: jsonEncode(userData)); } setState(() { diff --git a/lib/src/views/settings/privacy_view.dart b/lib/src/views/settings/privacy_view.dart index 84287b6..237649d 100644 --- a/lib/src/views/settings/privacy_view.dart +++ b/lib/src/views/settings/privacy_view.dart @@ -27,7 +27,7 @@ class _PrivacyViewState extends State { ListTile( title: Text(context.lang.settingsPrivacyBlockUsers), subtitle: StreamBuilder( - stream: twonlyDatabase.watchContactsBlocked(), + stream: twonlyDatabase.contactsDao.watchContactsBlocked(), builder: (context, snapshot) { if (snapshot.hasData && snapshot.data != null) { return Text( diff --git a/lib/src/views/settings/privacy_view_block_users.dart b/lib/src/views/settings/privacy_view_block_users.dart index b1bfcbf..09d88ca 100644 --- a/lib/src/views/settings/privacy_view_block_users.dart +++ b/lib/src/views/settings/privacy_view_block_users.dart @@ -2,8 +2,8 @@ import 'package:drift/drift.dart' hide Column; import 'package:flutter/material.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/components/initialsavatar.dart'; -import 'package:twonly/src/database/contacts_db.dart'; -import 'package:twonly/src/database/database.dart'; +import 'package:twonly/src/database/tables/contacts_table.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/utils/misc.dart'; class PrivacyViewBlockUsers extends StatefulWidget { @@ -21,7 +21,7 @@ class _PrivacyViewBlockUsers extends State { @override void initState() { super.initState(); - allUsers = twonlyDatabase.watchAllContacts(); + allUsers = twonlyDatabase.contactsDao.watchAllContacts(); loadAsync(); } @@ -105,7 +105,7 @@ class UserList extends StatelessWidget { Future block(BuildContext context, int userId, bool? value) async { if (value != null) { final update = ContactsCompanion(blocked: Value(!value)); - await twonlyDatabase.updateContact(userId, update); + await twonlyDatabase.contactsDao.updateContact(userId, update); } } diff --git a/lib/src/views/settings/settings_main_view.dart b/lib/src/views/settings/settings_main_view.dart index 1a1d492..d388245 100644 --- a/lib/src/views/settings/settings_main_view.dart +++ b/lib/src/views/settings/settings_main_view.dart @@ -1,7 +1,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:twonly/src/components/better_list_title.dart'; import 'package:twonly/src/components/initialsavatar.dart'; -import 'package:twonly/src/model/json/user_data.dart'; +import 'package:twonly/src/json_models/userdata.dart'; import 'package:flutter/material.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/storage.dart'; diff --git a/pubspec.lock b/pubspec.lock index ab8e409..5e03d43 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -265,14 +265,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.7.1" - cv: - dependency: "direct main" - description: - name: cv - sha256: b7ad2d39ebd8d0a610c69becbd9b0131c1b1544d42186fa025710f8ebff038a0 - url: "https://pub.dev" - source: hosted - version: "1.1.3" dart_style: dependency: transitive description: @@ -410,7 +402,7 @@ packages: source: hosted version: "3.10.2" fixnum: - dependency: "direct main" + dependency: transitive description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be @@ -422,14 +414,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_foreground_task: - dependency: "direct main" - description: - name: flutter_foreground_task - sha256: "206017ee1bf864f34b8d7bce664a172717caa21af8da23f55866470dfe316644" - url: "https://pub.dev" - source: hosted - version: "8.17.0" flutter_image_compress: dependency: "direct main" description: @@ -669,14 +653,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 - url: "https://pub.dev" - source: hosted - version: "6.2.1" graphs: dependency: transitive description: @@ -1189,14 +1165,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" - reorderables: - dependency: "direct main" - description: - name: reorderables - sha256: "004a886e4878df1ee27321831c838bc1c976311f4ca6a74ce7d561e506540a77" - url: "https://pub.dev" - source: hosted - version: "0.6.0" restart_app: dependency: "direct main" description: @@ -1221,62 +1189,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" - shared_preferences: - dependency: transitive - description: - name: shared_preferences - sha256: "688ee90fbfb6989c980254a56cb26ebe9bb30a3a2dff439a78894211f73de67a" - url: "https://pub.dev" - source: hosted - version: "2.5.1" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: "650584dcc0a39856f369782874e562efd002a9c94aec032412c9eb81419cce1f" - url: "https://pub.dev" - source: hosted - version: "2.4.4" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" - url: "https://pub.dev" - source: hosted - version: "2.5.4" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e - url: "https://pub.dev" - source: hosted - version: "2.4.2" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" - source: hosted - version: "2.4.1" shelf: dependency: transitive description: @@ -1330,22 +1242,6 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" - sqflite_common: - dependency: transitive - description: - name: sqflite_common - sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709" - url: "https://pub.dev" - source: hosted - version: "2.5.4+6" - sqflite_sqlcipher: - dependency: "direct main" - description: - name: sqflite_sqlcipher - sha256: "16033fde6c7d7bd657b71a2bc42332ab02bc8001c3212f502d2e02714e735ec9" - url: "https://pub.dev" - source: hosted - version: "3.1.0+1" sqlite3: dependency: transitive description: @@ -1402,14 +1298,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - synchronized: - dependency: transitive - description: - name: synchronized - sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" - url: "https://pub.dev" - source: hosted - version: "3.3.0+3" term_glyph: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index bb3455b..9fddacd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,16 +15,13 @@ dependencies: # path: ../CamerAwesome collection: ^1.18.0 connectivity_plus: ^6.1.2 - cv: ^1.1.3 drift: ^2.25.1 drift_flutter: ^0.2.4 exif: ^3.3.0 firebase_core: ^3.11.0 firebase_messaging: ^15.2.2 - fixnum: ^1.1.1 flutter: sdk: flutter - flutter_foreground_task: ^8.17.0 flutter_image_compress: ^2.4.0 flutter_local_notifications: ^18.0.1 flutter_localizations: @@ -32,7 +29,6 @@ dependencies: flutter_secure_storage: ^10.0.0-beta.4 font_awesome_flutter: ^10.8.0 gal: ^2.3.1 - google_fonts: ^6.2.1 hand_signature: ^3.0.3 hive: ^2.2.3 image: ^4.3.0 @@ -54,10 +50,8 @@ dependencies: cryptography_flutter_plus: ^2.3.2 provider: ^6.1.2 qr_flutter: ^4.1.0 - reorderables: ^0.6.0 restart_app: ^1.3.2 screenshot: ^3.0.0 - sqflite_sqlcipher: ^3.1.0+1 url_launcher: ^6.3.1 web_socket_channel: ^3.0.1