mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 11:18:41 +00:00
starting with #227
This commit is contained in:
parent
90e6aa6598
commit
a4ccefec75
131 changed files with 14355 additions and 1435 deletions
6
.gitmodules
vendored
6
.gitmodules
vendored
|
|
@ -1,9 +1,3 @@
|
||||||
[submodule "dependencies/flutter_secure_storage"]
|
|
||||||
path = dependencies/flutter_secure_storage
|
|
||||||
url = https://github.com/juliansteenbakker/flutter_secure_storage
|
|
||||||
[submodule "dependencies/flutter_zxing"]
|
[submodule "dependencies/flutter_zxing"]
|
||||||
path = dependencies/flutter_zxing
|
path = dependencies/flutter_zxing
|
||||||
url = https://github.com/khoren93/flutter_zxing.git
|
url = https://github.com/khoren93/flutter_zxing.git
|
||||||
[submodule "dependencies/flutter-pie-menu"]
|
|
||||||
path = dependencies/flutter-pie-menu
|
|
||||||
url = https://github.com/otsmr/flutter-pie-menu.git
|
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,5 @@ targets:
|
||||||
drift_dev:
|
drift_dev:
|
||||||
options:
|
options:
|
||||||
databases:
|
databases:
|
||||||
twonly_database: lib/src/database/twonly_database.dart
|
twonly_db: lib/src/database/twonly.db.dart
|
||||||
|
twonly_database: lib/src/database/twonly_database_old.dart
|
||||||
1
dependencies/flutter-pie-menu
vendored
1
dependencies/flutter-pie-menu
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 22df3f2ab9ad71db60526668578a5309b3cc84ef
|
|
||||||
1
dependencies/flutter_secure_storage
vendored
1
dependencies/flutter_secure_storage
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 71b75a36f35f2ce945998e20c6c6aa1820babfc6
|
|
||||||
|
|
@ -103,7 +103,7 @@ enum PushKind: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EncryptedPushNotification: @unchecked Sendable {
|
struct EncryptedPushNotification: Sendable {
|
||||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
// methods supported on all messages.
|
// methods supported on all messages.
|
||||||
|
|
@ -195,7 +195,7 @@ struct PushUser: Sendable {
|
||||||
fileprivate var _lastMessageID: Int64? = nil
|
fileprivate var _lastMessageID: Int64? = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PushKey: @unchecked Sendable {
|
struct PushKey: Sendable {
|
||||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
// methods supported on all messages.
|
// methods supported on all messages.
|
||||||
|
|
@ -214,32 +214,12 @@ struct PushKey: @unchecked Sendable {
|
||||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||||
|
|
||||||
extension PushKind: SwiftProtobuf._ProtoNameProviding {
|
extension PushKind: SwiftProtobuf._ProtoNameProviding {
|
||||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0reaction\0\u{1}response\0\u{1}text\0\u{1}video\0\u{1}twonly\0\u{1}image\0\u{1}contactRequest\0\u{1}acceptRequest\0\u{1}storedMediaFile\0\u{1}testNotification\0\u{1}reopenedMedia\0\u{1}reactionToVideo\0\u{1}reactionToText\0\u{1}reactionToImage\0")
|
||||||
0: .same(proto: "reaction"),
|
|
||||||
1: .same(proto: "response"),
|
|
||||||
2: .same(proto: "text"),
|
|
||||||
3: .same(proto: "video"),
|
|
||||||
4: .same(proto: "twonly"),
|
|
||||||
5: .same(proto: "image"),
|
|
||||||
6: .same(proto: "contactRequest"),
|
|
||||||
7: .same(proto: "acceptRequest"),
|
|
||||||
8: .same(proto: "storedMediaFile"),
|
|
||||||
9: .same(proto: "testNotification"),
|
|
||||||
10: .same(proto: "reopenedMedia"),
|
|
||||||
11: .same(proto: "reactionToVideo"),
|
|
||||||
12: .same(proto: "reactionToText"),
|
|
||||||
13: .same(proto: "reactionToImage"),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension EncryptedPushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
extension EncryptedPushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
static let protoMessageName: String = "EncryptedPushNotification"
|
static let protoMessageName: String = "EncryptedPushNotification"
|
||||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}keyId\0\u{1}nonce\0\u{1}ciphertext\0\u{1}mac\0")
|
||||||
1: .same(proto: "keyId"),
|
|
||||||
2: .same(proto: "nonce"),
|
|
||||||
3: .same(proto: "ciphertext"),
|
|
||||||
4: .same(proto: "mac"),
|
|
||||||
]
|
|
||||||
|
|
||||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
|
@ -284,11 +264,7 @@ extension EncryptedPushNotification: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
||||||
|
|
||||||
extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
static let protoMessageName: String = "PushNotification"
|
static let protoMessageName: String = "PushNotification"
|
||||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}kind\0\u{1}messageId\0\u{1}reactionContent\0")
|
||||||
1: .same(proto: "kind"),
|
|
||||||
2: .same(proto: "messageId"),
|
|
||||||
3: .same(proto: "reactionContent"),
|
|
||||||
]
|
|
||||||
|
|
||||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
|
@ -332,9 +308,7 @@ extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme
|
||||||
|
|
||||||
extension PushUsers: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
extension PushUsers: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
static let protoMessageName: String = "PushUsers"
|
static let protoMessageName: String = "PushUsers"
|
||||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}users\0")
|
||||||
1: .same(proto: "users"),
|
|
||||||
]
|
|
||||||
|
|
||||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
|
@ -364,13 +338,7 @@ extension PushUsers: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
|
||||||
|
|
||||||
extension PushUser: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
extension PushUser: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
static let protoMessageName: String = "PushUser"
|
static let protoMessageName: String = "PushUser"
|
||||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}userId\0\u{1}displayName\0\u{1}blocked\0\u{1}lastMessageId\0\u{1}pushKeys\0")
|
||||||
1: .same(proto: "userId"),
|
|
||||||
2: .same(proto: "displayName"),
|
|
||||||
3: .same(proto: "blocked"),
|
|
||||||
4: .same(proto: "lastMessageId"),
|
|
||||||
5: .same(proto: "pushKeys"),
|
|
||||||
]
|
|
||||||
|
|
||||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
|
@ -424,11 +392,7 @@ extension PushUser: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
||||||
|
|
||||||
extension PushKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
extension PushKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
static let protoMessageName: String = "PushKey"
|
static let protoMessageName: String = "PushKey"
|
||||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0\u{1}key\0\u{1}createdAtUnixTimestamp\0")
|
||||||
1: .same(proto: "id"),
|
|
||||||
2: .same(proto: "key"),
|
|
||||||
3: .same(proto: "createdAtUnixTimestamp"),
|
|
||||||
]
|
|
||||||
|
|
||||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/api.service.dart';
|
import 'package:twonly/src/services/api.service.dart';
|
||||||
|
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
|
|
||||||
// uses for background notification
|
// uses for background notification
|
||||||
late TwonlyDatabase twonlyDB;
|
late TwonlyDB twonlyDB;
|
||||||
|
|
||||||
List<CameraDescription> gCameras = <CameraDescription>[];
|
List<CameraDescription> gCameras = <CameraDescription>[];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/providers/connection.provider.dart';
|
import 'package:twonly/src/providers/connection.provider.dart';
|
||||||
import 'package:twonly/src/providers/image_editor.provider.dart';
|
import 'package:twonly/src/providers/image_editor.provider.dart';
|
||||||
import 'package:twonly/src/providers/settings.provider.dart';
|
import 'package:twonly/src/providers/settings.provider.dart';
|
||||||
|
|
@ -43,18 +43,18 @@ void main() async {
|
||||||
gCameras = await availableCameras();
|
gCameras = await availableCameras();
|
||||||
|
|
||||||
apiService = ApiService();
|
apiService = ApiService();
|
||||||
twonlyDB = TwonlyDatabase();
|
twonlyDB = TwonlyDB();
|
||||||
|
|
||||||
await twonlyDB.messagesDao.resetPendingDownloadState();
|
// await twonlyDB.messagesDao.resetPendingDownloadState();
|
||||||
await twonlyDB.messagesDao.handleMediaFilesOlderThan30Days();
|
// await twonlyDB.messagesDao.handleMediaFilesOlderThan30Days();
|
||||||
await twonlyDB.messageRetransmissionDao.purgeOldRetransmissions();
|
// await twonlyDB.messageRetransmissionDao.purgeOldRetransmissions();
|
||||||
await twonlyDB.signalDao.purgeOutDatedPreKeys();
|
// await twonlyDB.signalDao.purgeOutDatedPreKeys();
|
||||||
|
|
||||||
// Purge media files in the background
|
// Purge media files in the background
|
||||||
unawaited(purgeReceivedMediaFiles());
|
// unawaited(purgeReceivedMediaFiles());
|
||||||
unawaited(purgeSendMediaFiles());
|
// unawaited(purgeSendMediaFiles());
|
||||||
|
|
||||||
unawaited(performTwonlySafeBackup());
|
// unawaited(performTwonlySafeBackup());
|
||||||
|
|
||||||
await initFileDownloader();
|
await initFileDownloader();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/src/database/tables/contacts_table.dart';
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||||
|
|
||||||
part 'contacts_dao.g.dart';
|
part 'contacts.dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(tables: [Contacts])
|
@DriftAccessor(tables: [Contacts])
|
||||||
class ContactsDao extends DatabaseAccessor<TwonlyDatabase>
|
class ContactsDao extends DatabaseAccessor<TwonlyDB> with _$ContactsDaoMixin {
|
||||||
with _$ContactsDaoMixin {
|
|
||||||
// this constructor is required so that the main database can create an instance
|
// this constructor is required so that the main database can create an instance
|
||||||
// of this object.
|
// of this object.
|
||||||
// ignore: matching_super_parameters
|
// ignore: matching_super_parameters
|
||||||
|
|
@ -135,42 +134,39 @@ class ContactsDao extends DatabaseAccessor<TwonlyDatabase>
|
||||||
.watchSingleOrNull();
|
.watchSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<List<Contact>> watchContactsForShareView() {
|
// Stream<List<Contact>> watchContactsForShareView() {
|
||||||
return (select(contacts)
|
// return (select(contacts)
|
||||||
..where(
|
// ..where(
|
||||||
(t) =>
|
// (t) =>
|
||||||
t.accepted.equals(true) &
|
// t.accepted.equals(true) &
|
||||||
t.blocked.equals(false) &
|
// t.blocked.equals(false) &
|
||||||
t.deleted.equals(false),
|
// t.deleted.equals(false),
|
||||||
)
|
// )
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
// ..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
||||||
.watch();
|
// .watch();
|
||||||
}
|
// }
|
||||||
|
|
||||||
Stream<List<Contact>> watchContactsForStartNewChat() {
|
// Stream<List<Contact>> watchContactsForStartNewChat() {
|
||||||
return (select(contacts)
|
// return (select(contacts)
|
||||||
..where((t) => t.accepted.equals(true) & t.blocked.equals(false))
|
// ..where((t) => t.accepted.equals(true) & t.blocked.equals(false))
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
// ..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
||||||
.watch();
|
// .watch();
|
||||||
}
|
// }
|
||||||
|
|
||||||
Stream<List<Contact>> watchContactsForChatList() {
|
// Stream<List<Contact>> watchContactsForChatList() {
|
||||||
return (select(contacts)
|
// return (select(contacts)
|
||||||
..where(
|
// ..where(
|
||||||
(t) =>
|
// (t) =>
|
||||||
t.accepted.equals(true) &
|
// t.accepted.equals(true) &
|
||||||
t.blocked.equals(false) &
|
// t.blocked.equals(false) &
|
||||||
t.archived.equals(false),
|
// t.archived.equals(false),
|
||||||
)
|
// )
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
// ..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
||||||
.watch();
|
// .watch();
|
||||||
}
|
// }
|
||||||
|
|
||||||
Future<List<Contact>> getAllNotBlockedContacts() {
|
Future<List<Contact>> getAllNotBlockedContacts() {
|
||||||
return (select(contacts)
|
return (select(contacts)..where((t) => t.blocked.equals(false))).get();
|
||||||
..where((t) => t.blocked.equals(false))
|
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
|
|
||||||
.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<int?> watchContactsBlocked() {
|
Stream<int?> watchContactsBlocked() {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'contacts_dao.dart';
|
part of 'contacts.dao.dart';
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
mixin _$ContactsDaoMixin on DatabaseAccessor<TwonlyDatabase> {
|
mixin _$ContactsDaoMixin on DatabaseAccessor<TwonlyDB> {
|
||||||
$ContactsTable get contacts => attachedDatabase.contacts;
|
$ContactsTable get contacts => attachedDatabase.contacts;
|
||||||
}
|
}
|
||||||
21
lib/src/database/daos/groups.dao.dart
Normal file
21
lib/src/database/daos/groups.dao.dart
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/src/database/tables/groups.table.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
|
||||||
|
part 'groups.dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Groups, GroupMembers])
|
||||||
|
class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
||||||
|
// this constructor is required so that the main database can create an instance
|
||||||
|
// of this object.
|
||||||
|
// ignore: matching_super_parameters
|
||||||
|
GroupsDao(super.db);
|
||||||
|
|
||||||
|
Future<bool> isContactInGroup(int contactId, String groupId) async {
|
||||||
|
final entry = await (select(groupMembers)
|
||||||
|
..where(
|
||||||
|
(t) => t.contactId.equals(contactId) & t.groupId.equals(groupId)))
|
||||||
|
.getSingleOrNull();
|
||||||
|
return entry != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lib/src/database/daos/groups.dao.g.dart
Normal file
10
lib/src/database/daos/groups.dao.g.dart
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'groups.dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$GroupsDaoMixin on DatabaseAccessor<TwonlyDB> {
|
||||||
|
$GroupsTable get groups => attachedDatabase.groups;
|
||||||
|
$ContactsTable get contacts => attachedDatabase.contacts;
|
||||||
|
$GroupMembersTable get groupMembers => attachedDatabase.groupMembers;
|
||||||
|
}
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:twonly/src/database/tables/media_uploads_table.dart';
|
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
|
||||||
import 'package:twonly/src/utils/log.dart';
|
|
||||||
|
|
||||||
part 'media_uploads_dao.g.dart';
|
|
||||||
|
|
||||||
@DriftAccessor(tables: [MediaUploads])
|
|
||||||
class MediaUploadsDao extends DatabaseAccessor<TwonlyDatabase>
|
|
||||||
with _$MediaUploadsDaoMixin {
|
|
||||||
// ignore: matching_super_parameters
|
|
||||||
MediaUploadsDao(super.db);
|
|
||||||
|
|
||||||
Future<List<MediaUpload>> getMediaUploadsForRetry() {
|
|
||||||
return (select(mediaUploads)
|
|
||||||
..where(
|
|
||||||
(t) => t.state.equals(UploadState.receiverNotified.name).not(),
|
|
||||||
))
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int> updateMediaUpload(
|
|
||||||
int mediaUploadId,
|
|
||||||
MediaUploadsCompanion updatedValues,
|
|
||||||
) {
|
|
||||||
return (update(mediaUploads)
|
|
||||||
..where((c) => c.mediaUploadId.equals(mediaUploadId)))
|
|
||||||
.write(updatedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int?> insertMediaUpload(MediaUploadsCompanion values) async {
|
|
||||||
try {
|
|
||||||
return await into(mediaUploads).insert(values);
|
|
||||||
} catch (e) {
|
|
||||||
Log.error('Error while inserting media upload: $e');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteMediaUpload(int mediaUploadId) {
|
|
||||||
return (delete(mediaUploads)
|
|
||||||
..where((t) => t.mediaUploadId.equals(mediaUploadId)))
|
|
||||||
.go();
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleOrNullSelectable<MediaUpload> getMediaUploadById(int mediaUploadId) {
|
|
||||||
return select(mediaUploads)
|
|
||||||
..where((t) => t.mediaUploadId.equals(mediaUploadId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'media_uploads_dao.dart';
|
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
mixin _$MediaUploadsDaoMixin on DatabaseAccessor<TwonlyDatabase> {
|
|
||||||
$MediaUploadsTable get mediaUploads => attachedDatabase.mediaUploads;
|
|
||||||
}
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:twonly/src/database/tables/message_retransmissions.dart';
|
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
|
||||||
import 'package:twonly/src/utils/log.dart';
|
|
||||||
|
|
||||||
part 'message_retransmissions.dao.g.dart';
|
|
||||||
|
|
||||||
@DriftAccessor(tables: [MessageRetransmissions])
|
|
||||||
class MessageRetransmissionDao extends DatabaseAccessor<TwonlyDatabase>
|
|
||||||
with _$MessageRetransmissionDaoMixin {
|
|
||||||
// this constructor is required so that the main database can create an instance
|
|
||||||
// of this object.
|
|
||||||
// ignore: matching_super_parameters
|
|
||||||
MessageRetransmissionDao(super.db);
|
|
||||||
|
|
||||||
Future<int?> insertRetransmission(
|
|
||||||
MessageRetransmissionsCompanion message,
|
|
||||||
) async {
|
|
||||||
try {
|
|
||||||
return await into(messageRetransmissions).insert(message);
|
|
||||||
} catch (e) {
|
|
||||||
Log.error('Error while inserting message for retransmission: $e');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> purgeOldRetransmissions() async {
|
|
||||||
// delete entries older than two weeks
|
|
||||||
await (delete(messageRetransmissions)
|
|
||||||
..where(
|
|
||||||
(t) => (t.acknowledgeByServerAt.isSmallerThanValue(
|
|
||||||
DateTime.now().subtract(
|
|
||||||
const Duration(days: 25),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
))
|
|
||||||
.go();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<int>> getRetransmitAbleMessages() async {
|
|
||||||
final countDeleted = await (delete(messageRetransmissions)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.encryptedHash.isNull() & t.acknowledgeByServerAt.isNotNull(),
|
|
||||||
))
|
|
||||||
.go();
|
|
||||||
|
|
||||||
if (countDeleted > 0) {
|
|
||||||
Log.info('Deleted $countDeleted faulty retransmissions');
|
|
||||||
}
|
|
||||||
|
|
||||||
return (await (select(messageRetransmissions)
|
|
||||||
..where((t) => t.acknowledgeByServerAt.isNull()))
|
|
||||||
.get())
|
|
||||||
.map((msg) => msg.retransmissionId)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleOrNullSelectable<MessageRetransmission> getRetransmissionById(
|
|
||||||
int retransmissionId,
|
|
||||||
) {
|
|
||||||
return select(messageRetransmissions)
|
|
||||||
..where((t) => t.retransmissionId.equals(retransmissionId));
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<MessageRetransmission>> watchAllMessages() {
|
|
||||||
return (select(messageRetransmissions)
|
|
||||||
..orderBy([(t) => OrderingTerm.asc(t.retransmissionId)]))
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> updateRetransmission(
|
|
||||||
int retransmissionId,
|
|
||||||
MessageRetransmissionsCompanion updatedValues,
|
|
||||||
) {
|
|
||||||
return (update(messageRetransmissions)
|
|
||||||
..where((c) => c.retransmissionId.equals(retransmissionId)))
|
|
||||||
.write(updatedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int> resetAckStatusFor(int fromUserId, Uint8List encryptedHash) async {
|
|
||||||
return ((update(messageRetransmissions))
|
|
||||||
..where(
|
|
||||||
(m) =>
|
|
||||||
m.contactId.equals(fromUserId) &
|
|
||||||
m.encryptedHash.equals(encryptedHash),
|
|
||||||
))
|
|
||||||
.write(
|
|
||||||
const MessageRetransmissionsCompanion(
|
|
||||||
acknowledgeByServerAt: Value(null),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<MessageRetransmission?> getRetransmissionFromHash(
|
|
||||||
int fromUserId,
|
|
||||||
Uint8List encryptedHash,
|
|
||||||
) async {
|
|
||||||
return ((select(messageRetransmissions))
|
|
||||||
..where(
|
|
||||||
(m) =>
|
|
||||||
m.contactId.equals(fromUserId) &
|
|
||||||
m.encryptedHash.equals(encryptedHash),
|
|
||||||
))
|
|
||||||
.getSingleOrNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteRetransmissionById(int retransmissionId) {
|
|
||||||
return (delete(messageRetransmissions)
|
|
||||||
..where((t) => t.retransmissionId.equals(retransmissionId)))
|
|
||||||
.go();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> clearRetransmissionTable() {
|
|
||||||
return delete(messageRetransmissions).go();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteRetransmissionByMessageId(int messageId) {
|
|
||||||
return (delete(messageRetransmissions)
|
|
||||||
..where((t) => t.messageId.equals(messageId)))
|
|
||||||
.go();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'message_retransmissions.dao.dart';
|
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
mixin _$MessageRetransmissionDaoMixin on DatabaseAccessor<TwonlyDatabase> {
|
|
||||||
$ContactsTable get contacts => attachedDatabase.contacts;
|
|
||||||
$MessagesTable get messages => attachedDatabase.messages;
|
|
||||||
$MessageRetransmissionsTable get messageRetransmissions =>
|
|
||||||
attachedDatabase.messageRetransmissions;
|
|
||||||
}
|
|
||||||
377
lib/src/database/daos/messages.dao.dart
Normal file
377
lib/src/database/daos/messages.dao.dart
Normal file
|
|
@ -0,0 +1,377 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/mediafile.service.dart';
|
||||||
|
|
||||||
|
part 'messages.dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Messages, Contacts, MediaFiles, MessageHistories])
|
||||||
|
class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
|
// this constructor is required so that the main database can create an instance
|
||||||
|
// of this object.
|
||||||
|
// ignore: matching_super_parameters
|
||||||
|
MessagesDao(super.db);
|
||||||
|
|
||||||
|
// Stream<List<Message>> watchMessageNotOpened(int contactId) {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.openedAt.isNull() &
|
||||||
|
// t.contactId.equals(contactId) &
|
||||||
|
// t.errorWhileSending.equals(false),
|
||||||
|
// )
|
||||||
|
// ..orderBy([(t) => OrderingTerm.desc(t.sendAt)]))
|
||||||
|
// .watch();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Stream<List<Message>> watchMediaMessageNotOpened(int contactId) {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.openedAt.isNull() &
|
||||||
|
// t.contactId.equals(contactId) &
|
||||||
|
// t.errorWhileSending.equals(false) &
|
||||||
|
// t.messageOtherId.isNotNull() &
|
||||||
|
// t.kind.equals(MessageKind.media.name),
|
||||||
|
// )
|
||||||
|
// ..orderBy([(t) => OrderingTerm.asc(t.sendAt)]))
|
||||||
|
// .watch();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Stream<List<Message>> watchLastMessage(int contactId) {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where((t) => t.contactId.equals(contactId))
|
||||||
|
// ..orderBy([(t) => OrderingTerm.desc(t.sendAt)])
|
||||||
|
// ..limit(1))
|
||||||
|
// .watch();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Stream<List<Message>> watchAllMessagesFrom(int contactId) {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.contactId.equals(contactId) &
|
||||||
|
// t.contentJson.isNotNull() &
|
||||||
|
// (t.openedAt.isNull() |
|
||||||
|
// t.mediaStored.equals(true) |
|
||||||
|
// t.openedAt.isBiggerThanValue(
|
||||||
|
// DateTime.now().subtract(const Duration(days: 1)),
|
||||||
|
// )),
|
||||||
|
// )
|
||||||
|
// ..orderBy([(t) => OrderingTerm.asc(t.sendAt)]))
|
||||||
|
// .watch();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> removeOldMessages() {
|
||||||
|
// return (update(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// (t.openedAt.isSmallerThanValue(
|
||||||
|
// DateTime.now().subtract(const Duration(days: 1)),
|
||||||
|
// ) |
|
||||||
|
// (t.sendAt.isSmallerThanValue(
|
||||||
|
// DateTime.now().subtract(const Duration(days: 3)),
|
||||||
|
// ) &
|
||||||
|
// t.errorWhileSending.equals(true))) &
|
||||||
|
// t.kind.equals(MessageKind.textMessage.name),
|
||||||
|
// ))
|
||||||
|
// .write(const MessagesCompanion(contentJson: Value(null)));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> handleMediaFilesOlderThan30Days() {
|
||||||
|
// /// media files will be deleted by the server after 30 days, so delete them here also
|
||||||
|
// return (update(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) => (t.kind.equals(MessageKind.media.name) &
|
||||||
|
// t.openedAt.isNull() &
|
||||||
|
// t.messageOtherId.isNull() &
|
||||||
|
// (t.sendAt.isSmallerThanValue(
|
||||||
|
// DateTime.now().subtract(
|
||||||
|
// const Duration(days: 30),
|
||||||
|
// ),
|
||||||
|
// ))),
|
||||||
|
// ))
|
||||||
|
// .write(const MessagesCompanion(errorWhileSending: Value(true)));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<List<Message>> getAllMessagesPendingDownloading() {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.downloadState.equals(DownloadState.downloaded.index).not() &
|
||||||
|
// t.messageOtherId.isNotNull() &
|
||||||
|
// t.errorWhileSending.equals(false) &
|
||||||
|
// t.kind.equals(MessageKind.media.name),
|
||||||
|
// ))
|
||||||
|
// .get();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<List<Message>> getAllNonACKMessagesFromUser() {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.acknowledgeByUser.equals(false) &
|
||||||
|
// t.messageOtherId.isNull() &
|
||||||
|
// t.errorWhileSending.equals(false) &
|
||||||
|
// t.sendAt.isBiggerThanValue(
|
||||||
|
// DateTime.now().subtract(const Duration(minutes: 10)),
|
||||||
|
// ),
|
||||||
|
// ))
|
||||||
|
// .get();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Stream<List<Message>> getAllStoredMediaFiles() {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where((t) => t.mediaStored.equals(true))
|
||||||
|
// ..orderBy([(t) => OrderingTerm.desc(t.sendAt)]))
|
||||||
|
// .watch();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<List<Message>> getAllMessagesPendingUpload() {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.acknowledgeByServer.equals(false) &
|
||||||
|
// t.messageOtherId.isNull() &
|
||||||
|
// t.mediaUploadId.isNotNull() &
|
||||||
|
// t.downloadState.equals(DownloadState.pending.index) &
|
||||||
|
// t.errorWhileSending.equals(false) &
|
||||||
|
// t.kind.equals(MessageKind.media.name),
|
||||||
|
// ))
|
||||||
|
// .get();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> openedAllNonMediaMessages(int contactId) {
|
||||||
|
// final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
|
||||||
|
// return (update(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.contactId.equals(contactId) &
|
||||||
|
// t.messageOtherId.isNotNull() &
|
||||||
|
// t.openedAt.isNull() &
|
||||||
|
// t.kind.equals(MessageKind.media.name).not(),
|
||||||
|
// ))
|
||||||
|
// .write(updates);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> resetPendingDownloadState() {
|
||||||
|
// // All media files in the downloading state are reset to the pending state
|
||||||
|
// // When the app is used in mobile network, they will not be downloaded at the start
|
||||||
|
// // if they are not yet downloaded...
|
||||||
|
// const updates =
|
||||||
|
// MessagesCompanion(downloadState: Value(DownloadState.pending));
|
||||||
|
// return (update(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.messageOtherId.isNotNull() &
|
||||||
|
// t.downloadState.equals(DownloadState.downloading.index) &
|
||||||
|
// t.kind.equals(MessageKind.media.name),
|
||||||
|
// ))
|
||||||
|
// .write(updates);
|
||||||
|
// }
|
||||||
|
|
||||||
|
Future<void> handleMessageDeletion(
|
||||||
|
int contactId,
|
||||||
|
String messageId,
|
||||||
|
DateTime timestamp,
|
||||||
|
) async {
|
||||||
|
final msg = await getMessageById(messageId).getSingleOrNull();
|
||||||
|
if (msg == null || msg.senderId != contactId) return;
|
||||||
|
if (msg.mediaId != null) {
|
||||||
|
await (delete(mediaFiles)..where((t) => t.mediaId.equals(msg.mediaId!)))
|
||||||
|
.go();
|
||||||
|
await removeMediaFile(msg.mediaId!);
|
||||||
|
}
|
||||||
|
await (delete(messageHistories)
|
||||||
|
..where((t) => t.messageId.equals(messageId)))
|
||||||
|
.go();
|
||||||
|
|
||||||
|
await (update(messages)
|
||||||
|
..where(
|
||||||
|
(t) => t.messageId.equals(messageId) & t.senderId.equals(contactId),
|
||||||
|
))
|
||||||
|
.write(
|
||||||
|
MessagesCompanion(
|
||||||
|
isDeletedFromSender: const Value(true),
|
||||||
|
content: const Value(null),
|
||||||
|
modifiedAt: Value(timestamp),
|
||||||
|
mediaId: const Value(null),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleTextEdit(
|
||||||
|
int contactId,
|
||||||
|
String messageId,
|
||||||
|
String text,
|
||||||
|
DateTime timestamp,
|
||||||
|
) async {
|
||||||
|
final msg = await getMessageById(messageId).getSingleOrNull();
|
||||||
|
if (msg == null || msg.content == null || msg.senderId == contactId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await into(messageHistories).insert(
|
||||||
|
MessageHistoriesCompanion(
|
||||||
|
messageId: Value(messageId),
|
||||||
|
content: Value(msg.content),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await (update(messages)
|
||||||
|
..where(
|
||||||
|
(t) => t.messageId.equals(messageId) & t.senderId.equals(contactId),
|
||||||
|
))
|
||||||
|
.write(
|
||||||
|
MessagesCompanion(
|
||||||
|
content: Value(text),
|
||||||
|
modifiedAt: Value(timestamp),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleMessageOpened(
|
||||||
|
String groupId,
|
||||||
|
String messageId,
|
||||||
|
DateTime timestamp,
|
||||||
|
) async {
|
||||||
|
final msg = await getMessageById(messageId).getSingleOrNull();
|
||||||
|
if (msg == null) return;
|
||||||
|
await (update(messages)
|
||||||
|
..where(
|
||||||
|
(t) =>
|
||||||
|
t.groupId.equals(groupId) &
|
||||||
|
t.messageId.equals(messageId) &
|
||||||
|
t.senderId.isNull(),
|
||||||
|
))
|
||||||
|
.write(
|
||||||
|
MessagesCompanion(
|
||||||
|
openedAt: Value(timestamp),
|
||||||
|
openedByCounter: Value(msg.openedByCounter + 1),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future<void> updateMessageByOtherUser(
|
||||||
|
// int userId,
|
||||||
|
// int messageId,
|
||||||
|
// MessagesCompanion updatedValues,
|
||||||
|
// ) {
|
||||||
|
// return (update(messages)
|
||||||
|
// ..where(
|
||||||
|
// (c) => c.contactId.equals(userId) & c.messageId.equals(messageId),
|
||||||
|
// ))
|
||||||
|
// .write(updatedValues);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> updateMessageByOtherMessageId(
|
||||||
|
// int userId,
|
||||||
|
// int messageOtherId,
|
||||||
|
// MessagesCompanion updatedValues,
|
||||||
|
// ) {
|
||||||
|
// return (update(messages)
|
||||||
|
// ..where(
|
||||||
|
// (c) =>
|
||||||
|
// c.contactId.equals(userId) &
|
||||||
|
// c.messageOtherId.equals(messageOtherId),
|
||||||
|
// ))
|
||||||
|
// .write(updatedValues);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> updateMessageByMessageId(
|
||||||
|
// int messageId,
|
||||||
|
// MessagesCompanion updatedValues,
|
||||||
|
// ) {
|
||||||
|
// return (update(messages)..where((c) => c.messageId.equals(messageId)))
|
||||||
|
// .write(updatedValues);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<int?> insertMessage(MessagesCompanion message) async {
|
||||||
|
// try {
|
||||||
|
// await (update(contacts)
|
||||||
|
// ..where(
|
||||||
|
// (c) => c.userId.equals(message.contactId.value),
|
||||||
|
// ))
|
||||||
|
// .write(ContactsCompanion(lastMessageExchange: Value(DateTime.now())));
|
||||||
|
|
||||||
|
// return await into(messages).insert(message);
|
||||||
|
// } catch (e) {
|
||||||
|
// Log.error('Error while inserting message: $e');
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> deleteMessagesByContactId(int contactId) {
|
||||||
|
// return (delete(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) => t.contactId.equals(contactId) & t.mediaStored.equals(false),
|
||||||
|
// ))
|
||||||
|
// .go();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> deleteMessagesByContactIdAndOtherMessageId(
|
||||||
|
// int contactId,
|
||||||
|
// int messageOtherId,
|
||||||
|
// ) {
|
||||||
|
// return (delete(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.contactId.equals(contactId) &
|
||||||
|
// t.messageOtherId.equals(messageOtherId),
|
||||||
|
// ))
|
||||||
|
// .go();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> deleteMessagesByMessageId(int messageId) {
|
||||||
|
// return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<void> deleteAllMessagesByContactId(int contactId) {
|
||||||
|
// return (delete(messages)..where((t) => t.contactId.equals(contactId))).go();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<bool> containsOtherMessageId(
|
||||||
|
// int fromUserId,
|
||||||
|
// int messageOtherId,
|
||||||
|
// ) async {
|
||||||
|
// final query = select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.messageOtherId.equals(messageOtherId) &
|
||||||
|
// t.contactId.equals(fromUserId),
|
||||||
|
// );
|
||||||
|
// final entry = await query.get();
|
||||||
|
// return entry.isNotEmpty;
|
||||||
|
// }
|
||||||
|
|
||||||
|
SingleOrNullSelectable<Message> getMessageById(String messageId) {
|
||||||
|
return select(messages)..where((t) => t.messageId.equals(messageId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future<List<Message>> getMessagesByMediaUploadId(int mediaUploadId) async {
|
||||||
|
// return (select(messages)
|
||||||
|
// ..where((t) => t.mediaUploadId.equals(mediaUploadId)))
|
||||||
|
// .get();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// SingleOrNullSelectable<Message> getMessageByOtherMessageId(
|
||||||
|
// int fromUserId,
|
||||||
|
// int messageId,
|
||||||
|
// ) {
|
||||||
|
// return select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) =>
|
||||||
|
// t.messageOtherId.equals(messageId) & t.contactId.equals(fromUserId),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// SingleOrNullSelectable<Message> getMessageByIdAndContactId(
|
||||||
|
// int fromUserId,
|
||||||
|
// int messageId,
|
||||||
|
// ) {
|
||||||
|
// return select(messages)
|
||||||
|
// ..where(
|
||||||
|
// (t) => t.messageId.equals(messageId) & t.contactId.equals(fromUserId),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
}
|
||||||
12
lib/src/database/daos/messages.dao.g.dart
Normal file
12
lib/src/database/daos/messages.dao.g.dart
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'messages.dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$MessagesDaoMixin on DatabaseAccessor<TwonlyDB> {
|
||||||
|
$ContactsTable get contacts => attachedDatabase.contacts;
|
||||||
|
$MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles;
|
||||||
|
$MessagesTable get messages => attachedDatabase.messages;
|
||||||
|
$MessageHistoriesTable get messageHistories =>
|
||||||
|
attachedDatabase.messageHistories;
|
||||||
|
}
|
||||||
|
|
@ -1,311 +0,0 @@
|
||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:twonly/src/database/tables/contacts_table.dart';
|
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
|
||||||
import 'package:twonly/src/utils/log.dart';
|
|
||||||
|
|
||||||
part 'messages_dao.g.dart';
|
|
||||||
|
|
||||||
@DriftAccessor(tables: [Messages, Contacts])
|
|
||||||
class MessagesDao extends DatabaseAccessor<TwonlyDatabase>
|
|
||||||
with _$MessagesDaoMixin {
|
|
||||||
// this constructor is required so that the main database can create an instance
|
|
||||||
// of this object.
|
|
||||||
// ignore: matching_super_parameters
|
|
||||||
MessagesDao(super.db);
|
|
||||||
|
|
||||||
Stream<List<Message>> watchMessageNotOpened(int contactId) {
|
|
||||||
return (select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.openedAt.isNull() &
|
|
||||||
t.contactId.equals(contactId) &
|
|
||||||
t.errorWhileSending.equals(false),
|
|
||||||
)
|
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.sendAt)]))
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<Message>> watchMediaMessageNotOpened(int contactId) {
|
|
||||||
return (select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.openedAt.isNull() &
|
|
||||||
t.contactId.equals(contactId) &
|
|
||||||
t.errorWhileSending.equals(false) &
|
|
||||||
t.messageOtherId.isNotNull() &
|
|
||||||
t.kind.equals(MessageKind.media.name),
|
|
||||||
)
|
|
||||||
..orderBy([(t) => OrderingTerm.asc(t.sendAt)]))
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<Message>> watchLastMessage(int contactId) {
|
|
||||||
return (select(messages)
|
|
||||||
..where((t) => t.contactId.equals(contactId))
|
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.sendAt)])
|
|
||||||
..limit(1))
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<Message>> watchAllMessagesFrom(int contactId) {
|
|
||||||
return (select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.contactId.equals(contactId) &
|
|
||||||
t.contentJson.isNotNull() &
|
|
||||||
(t.openedAt.isNull() |
|
|
||||||
t.mediaStored.equals(true) |
|
|
||||||
t.openedAt.isBiggerThanValue(
|
|
||||||
DateTime.now().subtract(const Duration(days: 1)),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
..orderBy([(t) => OrderingTerm.asc(t.sendAt)]))
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> removeOldMessages() {
|
|
||||||
return (update(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
(t.openedAt.isSmallerThanValue(
|
|
||||||
DateTime.now().subtract(const Duration(days: 1)),
|
|
||||||
) |
|
|
||||||
(t.sendAt.isSmallerThanValue(
|
|
||||||
DateTime.now().subtract(const Duration(days: 3)),
|
|
||||||
) &
|
|
||||||
t.errorWhileSending.equals(true))) &
|
|
||||||
t.kind.equals(MessageKind.textMessage.name),
|
|
||||||
))
|
|
||||||
.write(const MessagesCompanion(contentJson: Value(null)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> handleMediaFilesOlderThan30Days() {
|
|
||||||
/// media files will be deleted by the server after 30 days, so delete them here also
|
|
||||||
return (update(messages)
|
|
||||||
..where(
|
|
||||||
(t) => (t.kind.equals(MessageKind.media.name) &
|
|
||||||
t.openedAt.isNull() &
|
|
||||||
t.messageOtherId.isNull() &
|
|
||||||
(t.sendAt.isSmallerThanValue(
|
|
||||||
DateTime.now().subtract(
|
|
||||||
const Duration(days: 30),
|
|
||||||
),
|
|
||||||
))),
|
|
||||||
))
|
|
||||||
.write(const MessagesCompanion(errorWhileSending: Value(true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Message>> getAllMessagesPendingDownloading() {
|
|
||||||
return (select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.downloadState.equals(DownloadState.downloaded.index).not() &
|
|
||||||
t.messageOtherId.isNotNull() &
|
|
||||||
t.errorWhileSending.equals(false) &
|
|
||||||
t.kind.equals(MessageKind.media.name),
|
|
||||||
))
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Message>> getAllNonACKMessagesFromUser() {
|
|
||||||
return (select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.acknowledgeByUser.equals(false) &
|
|
||||||
t.messageOtherId.isNull() &
|
|
||||||
t.errorWhileSending.equals(false) &
|
|
||||||
t.sendAt.isBiggerThanValue(
|
|
||||||
DateTime.now().subtract(const Duration(minutes: 10)),
|
|
||||||
),
|
|
||||||
))
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<Message>> getAllStoredMediaFiles() {
|
|
||||||
return (select(messages)
|
|
||||||
..where((t) => t.mediaStored.equals(true))
|
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.sendAt)]))
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Message>> getAllMessagesPendingUpload() {
|
|
||||||
return (select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.acknowledgeByServer.equals(false) &
|
|
||||||
t.messageOtherId.isNull() &
|
|
||||||
t.mediaUploadId.isNotNull() &
|
|
||||||
t.downloadState.equals(DownloadState.pending.index) &
|
|
||||||
t.errorWhileSending.equals(false) &
|
|
||||||
t.kind.equals(MessageKind.media.name),
|
|
||||||
))
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> openedAllNonMediaMessages(int contactId) {
|
|
||||||
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
|
|
||||||
return (update(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.contactId.equals(contactId) &
|
|
||||||
t.messageOtherId.isNotNull() &
|
|
||||||
t.openedAt.isNull() &
|
|
||||||
t.kind.equals(MessageKind.media.name).not(),
|
|
||||||
))
|
|
||||||
.write(updates);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> resetPendingDownloadState() {
|
|
||||||
// All media files in the downloading state are reset to the pending state
|
|
||||||
// When the app is used in mobile network, they will not be downloaded at the start
|
|
||||||
// if they are not yet downloaded...
|
|
||||||
const updates =
|
|
||||||
MessagesCompanion(downloadState: Value(DownloadState.pending));
|
|
||||||
return (update(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.messageOtherId.isNotNull() &
|
|
||||||
t.downloadState.equals(DownloadState.downloading.index) &
|
|
||||||
t.kind.equals(MessageKind.media.name),
|
|
||||||
))
|
|
||||||
.write(updates);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> openedAllNonMediaMessagesFromOtherUser(int contactId) {
|
|
||||||
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
|
|
||||||
return (update(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.contactId.equals(contactId) &
|
|
||||||
t.messageOtherId
|
|
||||||
.isNull() & // only mark messages open that where send
|
|
||||||
t.openedAt.isNull() &
|
|
||||||
t.kind.equals(MessageKind.media.name).not(),
|
|
||||||
))
|
|
||||||
.write(updates);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> updateMessageByOtherUser(
|
|
||||||
int userId,
|
|
||||||
int messageId,
|
|
||||||
MessagesCompanion updatedValues,
|
|
||||||
) {
|
|
||||||
return (update(messages)
|
|
||||||
..where(
|
|
||||||
(c) => c.contactId.equals(userId) & c.messageId.equals(messageId),
|
|
||||||
))
|
|
||||||
.write(updatedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> updateMessageByOtherMessageId(
|
|
||||||
int userId,
|
|
||||||
int messageOtherId,
|
|
||||||
MessagesCompanion updatedValues,
|
|
||||||
) {
|
|
||||||
return (update(messages)
|
|
||||||
..where(
|
|
||||||
(c) =>
|
|
||||||
c.contactId.equals(userId) &
|
|
||||||
c.messageOtherId.equals(messageOtherId),
|
|
||||||
))
|
|
||||||
.write(updatedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> updateMessageByMessageId(
|
|
||||||
int messageId,
|
|
||||||
MessagesCompanion updatedValues,
|
|
||||||
) {
|
|
||||||
return (update(messages)..where((c) => c.messageId.equals(messageId)))
|
|
||||||
.write(updatedValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int?> insertMessage(MessagesCompanion message) async {
|
|
||||||
try {
|
|
||||||
await (update(contacts)
|
|
||||||
..where(
|
|
||||||
(c) => c.userId.equals(message.contactId.value),
|
|
||||||
))
|
|
||||||
.write(ContactsCompanion(lastMessageExchange: Value(DateTime.now())));
|
|
||||||
|
|
||||||
return await into(messages).insert(message);
|
|
||||||
} catch (e) {
|
|
||||||
Log.error('Error while inserting message: $e');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteMessagesByContactId(int contactId) {
|
|
||||||
return (delete(messages)
|
|
||||||
..where(
|
|
||||||
(t) => t.contactId.equals(contactId) & t.mediaStored.equals(false),
|
|
||||||
))
|
|
||||||
.go();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteMessagesByContactIdAndOtherMessageId(
|
|
||||||
int contactId,
|
|
||||||
int messageOtherId,
|
|
||||||
) {
|
|
||||||
return (delete(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.contactId.equals(contactId) &
|
|
||||||
t.messageOtherId.equals(messageOtherId),
|
|
||||||
))
|
|
||||||
.go();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteMessagesByMessageId(int messageId) {
|
|
||||||
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteAllMessagesByContactId(int contactId) {
|
|
||||||
return (delete(messages)..where((t) => t.contactId.equals(contactId))).go();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> containsOtherMessageId(
|
|
||||||
int fromUserId,
|
|
||||||
int messageOtherId,
|
|
||||||
) async {
|
|
||||||
final query = select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.messageOtherId.equals(messageOtherId) &
|
|
||||||
t.contactId.equals(fromUserId),
|
|
||||||
);
|
|
||||||
final entry = await query.get();
|
|
||||||
return entry.isNotEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleOrNullSelectable<Message> getMessageByMessageId(int messageId) {
|
|
||||||
return select(messages)..where((t) => t.messageId.equals(messageId));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Message>> getMessagesByMediaUploadId(int mediaUploadId) async {
|
|
||||||
return (select(messages)
|
|
||||||
..where((t) => t.mediaUploadId.equals(mediaUploadId)))
|
|
||||||
.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleOrNullSelectable<Message> getMessageByOtherMessageId(
|
|
||||||
int fromUserId,
|
|
||||||
int messageId,
|
|
||||||
) {
|
|
||||||
return select(messages)
|
|
||||||
..where(
|
|
||||||
(t) =>
|
|
||||||
t.messageOtherId.equals(messageId) & t.contactId.equals(fromUserId),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleOrNullSelectable<Message> getMessageByIdAndContactId(
|
|
||||||
int fromUserId,
|
|
||||||
int messageId,
|
|
||||||
) {
|
|
||||||
return select(messages)
|
|
||||||
..where(
|
|
||||||
(t) => t.messageId.equals(messageId) & t.contactId.equals(fromUserId),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'messages_dao.dart';
|
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
mixin _$MessagesDaoMixin on DatabaseAccessor<TwonlyDatabase> {
|
|
||||||
$ContactsTable get contacts => attachedDatabase.contacts;
|
|
||||||
$MessagesTable get messages => attachedDatabase.messages;
|
|
||||||
}
|
|
||||||
44
lib/src/database/daos/reactions.dao.dart
Normal file
44
lib/src/database/daos/reactions.dao.dart
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/database/tables/reactions.table.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
|
part 'reactions.dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Reactions])
|
||||||
|
class ReactionsDao extends DatabaseAccessor<TwonlyDB> with _$ReactionsDaoMixin {
|
||||||
|
// this constructor is required so that the main database can create an instance
|
||||||
|
// of this object.
|
||||||
|
// ignore: matching_super_parameters
|
||||||
|
ReactionsDao(super.db);
|
||||||
|
|
||||||
|
Future<void> updateReaction(
|
||||||
|
int contactId,
|
||||||
|
String messageId,
|
||||||
|
String groupId,
|
||||||
|
String? emoji,
|
||||||
|
) async {
|
||||||
|
final msg =
|
||||||
|
await twonlyDB.messagesDao.getMessageById(messageId).getSingleOrNull();
|
||||||
|
if (msg == null || msg.groupId != groupId) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await (delete(reactions)
|
||||||
|
..where(
|
||||||
|
(t) =>
|
||||||
|
t.senderId.equals(contactId) & t.messageId.equals(messageId),
|
||||||
|
))
|
||||||
|
.go();
|
||||||
|
if (emoji != null) {
|
||||||
|
await into(reactions).insert(ReactionsCompanion(
|
||||||
|
messageId: Value(messageId),
|
||||||
|
emoji: Value(emoji),
|
||||||
|
senderId: Value(contactId),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
lib/src/database/daos/reactions.dao.g.dart
Normal file
11
lib/src/database/daos/reactions.dao.g.dart
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'reactions.dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$ReactionsDaoMixin on DatabaseAccessor<TwonlyDB> {
|
||||||
|
$ContactsTable get contacts => attachedDatabase.contacts;
|
||||||
|
$MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles;
|
||||||
|
$MessagesTable get messages => attachedDatabase.messages;
|
||||||
|
$ReactionsTable get reactions => attachedDatabase.reactions;
|
||||||
|
}
|
||||||
52
lib/src/database/daos/receipts.dao.dart
Normal file
52
lib/src/database/daos/receipts.dao.dart
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/receipts.table.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
|
part 'receipts.dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Receipts, Messages])
|
||||||
|
class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
||||||
|
// this constructor is required so that the main database can create an instance
|
||||||
|
// of this object.
|
||||||
|
// ignore: matching_super_parameters
|
||||||
|
ReceiptsDao(super.db);
|
||||||
|
|
||||||
|
Future<void> confirmReceipt(String receiptId, int fromUserId) async {
|
||||||
|
final receipt = await (select(receipts)
|
||||||
|
..where((t) =>
|
||||||
|
t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId)))
|
||||||
|
.getSingleOrNull();
|
||||||
|
|
||||||
|
if (receipt == null) return;
|
||||||
|
|
||||||
|
if (receipt.messageId != null) {
|
||||||
|
await (update(messages)
|
||||||
|
..where((t) => t.messageId.equals(receipt.messageId!)))
|
||||||
|
.write(
|
||||||
|
const MessagesCompanion(
|
||||||
|
acknowledgeByUser: Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await (delete(receipts)
|
||||||
|
..where(
|
||||||
|
(t) =>
|
||||||
|
t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId),
|
||||||
|
))
|
||||||
|
.go();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Receipt?> insertReceipt(ReceiptsCompanion entry) async {
|
||||||
|
try {
|
||||||
|
final id = await into(receipts).insert(entry);
|
||||||
|
return await (select(receipts)..where((t) => t.rowId.equals(id)))
|
||||||
|
.getSingle();
|
||||||
|
} catch (e) {
|
||||||
|
Log.error(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
lib/src/database/daos/receipts.dao.g.dart
Normal file
11
lib/src/database/daos/receipts.dao.g.dart
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'receipts.dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$ReceiptsDaoMixin on DatabaseAccessor<TwonlyDB> {
|
||||||
|
$ContactsTable get contacts => attachedDatabase.contacts;
|
||||||
|
$MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles;
|
||||||
|
$MessagesTable get messages => attachedDatabase.messages;
|
||||||
|
$ReceiptsTable get receipts => attachedDatabase.receipts;
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/tables/signal_contact_prekey_table.dart';
|
import 'package:twonly/src/database/tables/signal_contact_prekey.table.dart';
|
||||||
import 'package:twonly/src/database/tables/signal_contact_signed_prekey_table.dart';
|
import 'package:twonly/src/database/tables/signal_contact_signed_prekey.table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
part 'signal_dao.g.dart';
|
part 'signal.dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(
|
@DriftAccessor(
|
||||||
tables: [
|
tables: [
|
||||||
|
|
@ -13,7 +13,7 @@ part 'signal_dao.g.dart';
|
||||||
SignalContactSignedPreKeys,
|
SignalContactSignedPreKeys,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class SignalDao extends DatabaseAccessor<TwonlyDatabase> with _$SignalDaoMixin {
|
class SignalDao extends DatabaseAccessor<TwonlyDB> with _$SignalDaoMixin {
|
||||||
// this constructor is required so that the main database can create an instance
|
// this constructor is required so that the main database can create an instance
|
||||||
// of this object.
|
// of this object.
|
||||||
// ignore: matching_super_parameters
|
// ignore: matching_super_parameters
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'signal_dao.dart';
|
part of 'signal.dao.dart';
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
mixin _$SignalDaoMixin on DatabaseAccessor<TwonlyDatabase> {
|
mixin _$SignalDaoMixin on DatabaseAccessor<TwonlyDB> {
|
||||||
|
$ContactsTable get contacts => attachedDatabase.contacts;
|
||||||
$SignalContactPreKeysTable get signalContactPreKeys =>
|
$SignalContactPreKeysTable get signalContactPreKeys =>
|
||||||
attachedDatabase.signalContactPreKeys;
|
attachedDatabase.signalContactPreKeys;
|
||||||
$SignalContactSignedPreKeysTable get signalContactSignedPreKeys =>
|
$SignalContactSignedPreKeysTable get signalContactSignedPreKeys =>
|
||||||
|
|
@ -2,7 +2,7 @@ import 'package:collection/collection.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
|
||||||
class ConnectIdentityKeyStore extends IdentityKeyStore {
|
class ConnectIdentityKeyStore extends IdentityKeyStore {
|
||||||
ConnectIdentityKeyStore(this.identityKeyPair, this.localRegistrationId);
|
ConnectIdentityKeyStore(this.identityKeyPair, this.localRegistrationId);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
class ConnectPreKeyStore extends PreKeyStore {
|
class ConnectPreKeyStore extends PreKeyStore {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
|
||||||
class ConnectSenderKeyStore extends SenderKeyStore {
|
class ConnectSenderKeyStore extends SenderKeyStore {
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
|
||||||
class ConnectSessionStore extends SessionStore {
|
class ConnectSessionStore extends SessionStore {
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
41
lib/src/database/tables/contacts.table.dart
Normal file
41
lib/src/database/tables/contacts.table.dart
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
|
||||||
|
class Contacts extends Table {
|
||||||
|
IntColumn get userId => integer()();
|
||||||
|
|
||||||
|
TextColumn get username => text()();
|
||||||
|
TextColumn get displayName => text().nullable()();
|
||||||
|
TextColumn get nickName => text().nullable()();
|
||||||
|
TextColumn get avatarSvg => text().nullable()();
|
||||||
|
|
||||||
|
IntColumn get senderProfileCounter =>
|
||||||
|
integer().withDefault(const Constant(0))();
|
||||||
|
|
||||||
|
BoolColumn get accepted => boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get requested => boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get hidden => boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get blocked => boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get verified => boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get archived => boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
BoolColumn get alsoBestFriend =>
|
||||||
|
boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
IntColumn get deleteMessagesAfterXMinutes =>
|
||||||
|
integer().withDefault(const Constant(60 * 24))();
|
||||||
|
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
IntColumn get totalMediaCounter => integer().withDefault(const Constant(0))();
|
||||||
|
|
||||||
|
DateTimeColumn get lastMessageSend => dateTime().nullable()();
|
||||||
|
DateTimeColumn get lastMessageReceived => dateTime().nullable()();
|
||||||
|
DateTimeColumn get lastFlameCounterChange => dateTime().nullable()();
|
||||||
|
DateTimeColumn get lastFlameSync => dateTime().nullable()();
|
||||||
|
|
||||||
|
IntColumn get flameCounter => integer().withDefault(const Constant(0))();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {userId};
|
||||||
|
}
|
||||||
34
lib/src/database/tables/groups.table.dart
Normal file
34
lib/src/database/tables/groups.table.dart
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:hashlib/random.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
|
||||||
|
@DataClassName('Group')
|
||||||
|
class Groups extends Table {
|
||||||
|
TextColumn get groupId => text().clientDefault(() => uuid.v4())();
|
||||||
|
|
||||||
|
BoolColumn get isGroupAdmin => boolean()();
|
||||||
|
BoolColumn get isGroupOfTwo => boolean()();
|
||||||
|
BoolColumn get pinned => boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
DateTimeColumn get lastMessageExchange =>
|
||||||
|
dateTime().withDefault(currentDateAndTime)();
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {groupId};
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MemberState { invited, accepted, admin }
|
||||||
|
|
||||||
|
@DataClassName('GroupMember')
|
||||||
|
class GroupMembers extends Table {
|
||||||
|
TextColumn get groupId => text()();
|
||||||
|
|
||||||
|
IntColumn get contactId => integer().references(Contacts, #userId)();
|
||||||
|
TextColumn get memberState => textEnum<MemberState>().nullable()();
|
||||||
|
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {groupId, contactId};
|
||||||
|
}
|
||||||
48
lib/src/database/tables/mediafiles.table.dart
Normal file
48
lib/src/database/tables/mediafiles.table.dart
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:hashlib/random.dart';
|
||||||
|
|
||||||
|
enum MediaType {
|
||||||
|
image,
|
||||||
|
video,
|
||||||
|
gif,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UploadState {
|
||||||
|
pending,
|
||||||
|
readyToUpload,
|
||||||
|
uploadTaskStarted,
|
||||||
|
receiverNotified,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DownloadState {
|
||||||
|
pending,
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataClassName('MediaFile')
|
||||||
|
class MediaFiles extends Table {
|
||||||
|
TextColumn get mediaId => text().clientDefault(() => uuid.v4())();
|
||||||
|
|
||||||
|
TextColumn get type => textEnum<MediaType>()();
|
||||||
|
|
||||||
|
TextColumn get uploadState => textEnum<UploadState>().nullable()();
|
||||||
|
TextColumn get downloadState => textEnum<DownloadState>().nullable()();
|
||||||
|
|
||||||
|
BoolColumn get requiresAuthentication => boolean()();
|
||||||
|
BoolColumn get reopenByContact =>
|
||||||
|
boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
BoolColumn get storedByContact =>
|
||||||
|
boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
IntColumn get displayLimitInMilliseconds => integer().nullable()();
|
||||||
|
|
||||||
|
BlobColumn get downloadToken => blob().nullable()();
|
||||||
|
BlobColumn get encryptionKey => blob().nullable()();
|
||||||
|
BlobColumn get encryptionMac => blob().nullable()();
|
||||||
|
BlobColumn get encryptionNonce => blob().nullable()();
|
||||||
|
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {mediaId};
|
||||||
|
}
|
||||||
52
lib/src/database/tables/messages.table.dart
Normal file
52
lib/src/database/tables/messages.table.dart
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
|
|
||||||
|
@DataClassName('Message')
|
||||||
|
class Messages extends Table {
|
||||||
|
TextColumn get groupId => text()();
|
||||||
|
TextColumn get messageId => text()();
|
||||||
|
|
||||||
|
// in case senderId is null, it was send by user itself
|
||||||
|
IntColumn get senderId =>
|
||||||
|
integer().nullable().references(Contacts, #userId)();
|
||||||
|
|
||||||
|
TextColumn get content => text().nullable()();
|
||||||
|
TextColumn get mediaId =>
|
||||||
|
text().nullable().references(MediaFiles, #mediaId)();
|
||||||
|
|
||||||
|
TextColumn get quotesMessageId =>
|
||||||
|
text().nullable().references(Messages, #messageId)();
|
||||||
|
|
||||||
|
BoolColumn get isDeletedFromSender =>
|
||||||
|
boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
BoolColumn get isEdited => boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
BoolColumn get acknowledgeByUser =>
|
||||||
|
boolean().withDefault(const Constant(false))();
|
||||||
|
BoolColumn get acknowledgeByServer =>
|
||||||
|
boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
IntColumn get openedByCounter => integer().withDefault(const Constant(0))();
|
||||||
|
DateTimeColumn get openedAt => dateTime().nullable()();
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
DateTimeColumn get modifiedAt =>
|
||||||
|
dateTime().nullable().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {messageId};
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataClassName('MessageHistory')
|
||||||
|
class MessageHistories extends Table {
|
||||||
|
TextColumn get messageId =>
|
||||||
|
text().references(Messages, #messageId, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
TextColumn get content => text().nullable()();
|
||||||
|
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {messageId, createdAt};
|
||||||
|
}
|
||||||
21
lib/src/database/tables/reactions.table.dart
Normal file
21
lib/src/database/tables/reactions.table.dart
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
|
|
||||||
|
@DataClassName('Reaction')
|
||||||
|
class Reactions extends Table {
|
||||||
|
TextColumn get messageId =>
|
||||||
|
text().references(Messages, #messageId, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
TextColumn get emoji => text()();
|
||||||
|
|
||||||
|
// in case senderId is null, it was send by user itself
|
||||||
|
IntColumn get senderId => integer()
|
||||||
|
.nullable()
|
||||||
|
.references(Contacts, #userId, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {messageId, senderId, createdAt};
|
||||||
|
}
|
||||||
30
lib/src/database/tables/receipts.table.dart
Normal file
30
lib/src/database/tables/receipts.table.dart
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:hashlib/random.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
|
|
||||||
|
@DataClassName('Receipt')
|
||||||
|
class Receipts extends Table {
|
||||||
|
TextColumn get receiptId => text().clientDefault(() => uuid.v4())();
|
||||||
|
|
||||||
|
IntColumn get contactId =>
|
||||||
|
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
// in case a message is deleted, it should be also deleted from the receipts table
|
||||||
|
TextColumn get messageId => text()
|
||||||
|
.nullable()
|
||||||
|
.references(Messages, #messageId, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
BlobColumn get message => blob()();
|
||||||
|
|
||||||
|
BoolColumn get contactWillSendsReceipt =>
|
||||||
|
boolean().withDefault(const Constant(true))();
|
||||||
|
|
||||||
|
IntColumn get retryCount => integer().withDefault(const Constant(0))();
|
||||||
|
DateTimeColumn get lastRetry => dateTime().nullable()();
|
||||||
|
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {receiptId};
|
||||||
|
}
|
||||||
13
lib/src/database/tables/signal_contact_prekey.table.dart
Normal file
13
lib/src/database/tables/signal_contact_prekey.table.dart
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
|
||||||
|
@DataClassName('SignalContactPreKey')
|
||||||
|
class SignalContactPreKeys extends Table {
|
||||||
|
IntColumn get contactId =>
|
||||||
|
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
|
||||||
|
IntColumn get preKeyId => integer()();
|
||||||
|
BlobColumn get preKey => blob()();
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {contactId, preKeyId};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
|
||||||
|
@DataClassName('SignalContactSignedPreKey')
|
||||||
|
class SignalContactSignedPreKeys extends Table {
|
||||||
|
IntColumn get contactId =>
|
||||||
|
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
|
||||||
|
IntColumn get signedPreKeyId => integer()();
|
||||||
|
BlobColumn get signedPreKey => blob()();
|
||||||
|
BlobColumn get signedPreKeySignature => blob()();
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {contactId};
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/src/database/tables/contacts_table.dart';
|
import 'package:twonly/src/database/tables_old/contacts_table.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables_old/messages_table.dart';
|
||||||
|
|
||||||
@DataClassName('MessageRetransmission')
|
@DataClassName('MessageRetransmission')
|
||||||
class MessageRetransmissions extends Table {
|
class MessageRetransmissions extends Table {
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/src/database/tables/contacts_table.dart';
|
import 'package:twonly/src/database/tables_old/contacts_table.dart';
|
||||||
|
|
||||||
enum MessageKind {
|
enum MessageKind {
|
||||||
textMessage,
|
textMessage,
|
||||||
|
|
@ -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<Column> get primaryKey => {deviceId, name};
|
||||||
|
}
|
||||||
11
lib/src/database/tables_old/signal_pre_key_store_table.dart
Normal file
11
lib/src/database/tables_old/signal_pre_key_store_table.dart
Normal file
|
|
@ -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<Column> get primaryKey => {preKeyId};
|
||||||
|
}
|
||||||
|
|
@ -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<Column> get primaryKey => {senderKeyName};
|
||||||
|
}
|
||||||
12
lib/src/database/tables_old/signal_session_store_table.dart
Normal file
12
lib/src/database/tables_old/signal_session_store_table.dart
Normal file
|
|
@ -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<Column> get primaryKey => {deviceId, name};
|
||||||
|
}
|
||||||
124
lib/src/database/twonly.db.dart
Normal file
124
lib/src/database/twonly.db.dart
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift_flutter/drift_flutter.dart'
|
||||||
|
show DriftNativeOptions, driftDatabase;
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
|
import 'package:twonly/src/database/daos/groups.dao.dart';
|
||||||
|
import 'package:twonly/src/database/daos/messages.dao.dart';
|
||||||
|
import 'package:twonly/src/database/daos/reactions.dao.dart';
|
||||||
|
import 'package:twonly/src/database/daos/receipts.dao.dart';
|
||||||
|
import 'package:twonly/src/database/daos/signal.dao.dart';
|
||||||
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/groups.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/reactions.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/receipts.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/signal_contact_prekey.table.dart';
|
||||||
|
import 'package:twonly/src/database/tables/signal_contact_signed_prekey.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/utils/log.dart';
|
||||||
|
|
||||||
|
part 'twonly.db.g.dart';
|
||||||
|
|
||||||
|
// You can then create a database class that includes this table
|
||||||
|
@DriftDatabase(
|
||||||
|
tables: [
|
||||||
|
Contacts,
|
||||||
|
Messages,
|
||||||
|
MessageHistories,
|
||||||
|
MediaFiles,
|
||||||
|
Reactions,
|
||||||
|
Groups,
|
||||||
|
GroupMembers,
|
||||||
|
Receipts,
|
||||||
|
SignalIdentityKeyStores,
|
||||||
|
SignalPreKeyStores,
|
||||||
|
SignalSenderKeyStores,
|
||||||
|
SignalSessionStores,
|
||||||
|
SignalContactPreKeys,
|
||||||
|
SignalContactSignedPreKeys,
|
||||||
|
],
|
||||||
|
daos: [
|
||||||
|
MessagesDao,
|
||||||
|
ContactsDao,
|
||||||
|
SignalDao,
|
||||||
|
ReceiptsDao,
|
||||||
|
GroupsDao,
|
||||||
|
ReactionsDao
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class TwonlyDB extends _$TwonlyDB {
|
||||||
|
TwonlyDB([QueryExecutor? e])
|
||||||
|
: super(
|
||||||
|
e ?? _openConnection(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// ignore: matching_super_parameters
|
||||||
|
TwonlyDB.forTesting(DatabaseConnection super.connection);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get schemaVersion => 1;
|
||||||
|
|
||||||
|
static QueryExecutor _openConnection() {
|
||||||
|
return driftDatabase(
|
||||||
|
name: 'twonly',
|
||||||
|
native: const DriftNativeOptions(
|
||||||
|
databaseDirectory: getApplicationSupportDirectory,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
MigrationStrategy get migration {
|
||||||
|
return MigrationStrategy(
|
||||||
|
beforeOpen: (details) async {
|
||||||
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
|
},
|
||||||
|
// onUpgrade: stepByStep(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void markUpdated() {
|
||||||
|
notifyUpdates({TableUpdate.onTable(messages, kind: UpdateKind.update)});
|
||||||
|
notifyUpdates({TableUpdate.onTable(contacts, kind: UpdateKind.update)});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> printTableSizes() async {
|
||||||
|
final result = await customSelect(
|
||||||
|
'SELECT name, SUM(pgsize) as size FROM dbstat GROUP BY name',
|
||||||
|
).get();
|
||||||
|
|
||||||
|
for (final row in result) {
|
||||||
|
final tableName = row.read<String>('name');
|
||||||
|
final tableSize = row.read<String>('size');
|
||||||
|
Log.info('Table: $tableName, Size: $tableSize bytes');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteDataForTwonlySafe() async {
|
||||||
|
// await delete(messages).go();
|
||||||
|
// await delete(messageRetransmissions).go();
|
||||||
|
// await delete(mediaUploads).go();
|
||||||
|
// await update(contacts).write(
|
||||||
|
// const ContactsCompanion(
|
||||||
|
// avatarSvg: Value(null),
|
||||||
|
// myAvatarCounter: Value(0),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// await delete(signalContactPreKeys).go();
|
||||||
|
// await delete(signalContactSignedPreKeys).go();
|
||||||
|
// await (delete(signalPreKeyStores)
|
||||||
|
// ..where(
|
||||||
|
// (t) => (t.createdAt.isSmallerThanValue(
|
||||||
|
// DateTime.now().subtract(
|
||||||
|
// const Duration(days: 25),
|
||||||
|
// ),
|
||||||
|
// )),
|
||||||
|
// ))
|
||||||
|
// .go();
|
||||||
|
}
|
||||||
|
}
|
||||||
10544
lib/src/database/twonly.db.g.dart
Normal file
10544
lib/src/database/twonly.db.g.dart
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -2,25 +2,20 @@ import 'package:drift/drift.dart';
|
||||||
import 'package:drift_flutter/drift_flutter.dart'
|
import 'package:drift_flutter/drift_flutter.dart'
|
||||||
show DriftNativeOptions, driftDatabase;
|
show DriftNativeOptions, driftDatabase;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/tables_old/contacts_table.dart';
|
||||||
import 'package:twonly/src/database/daos/media_uploads_dao.dart';
|
import 'package:twonly/src/database/tables_old/media_uploads_table.dart';
|
||||||
import 'package:twonly/src/database/daos/message_retransmissions.dao.dart';
|
import 'package:twonly/src/database/tables_old/message_retransmissions.dart';
|
||||||
import 'package:twonly/src/database/daos/messages_dao.dart';
|
import 'package:twonly/src/database/tables_old/messages_table.dart';
|
||||||
import 'package:twonly/src/database/daos/signal_dao.dart';
|
import 'package:twonly/src/database/tables_old/signal_contact_prekey_table.dart';
|
||||||
import 'package:twonly/src/database/tables/contacts_table.dart';
|
import 'package:twonly/src/database/tables_old/signal_contact_signed_prekey_table.dart';
|
||||||
import 'package:twonly/src/database/tables/media_uploads_table.dart';
|
import 'package:twonly/src/database/tables_old/signal_identity_key_store_table.dart';
|
||||||
import 'package:twonly/src/database/tables/message_retransmissions.dart';
|
import 'package:twonly/src/database/tables_old/signal_pre_key_store_table.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables_old/signal_sender_key_store_table.dart';
|
||||||
import 'package:twonly/src/database/tables/signal_contact_prekey_table.dart';
|
import 'package:twonly/src/database/tables_old/signal_session_store_table.dart';
|
||||||
import 'package:twonly/src/database/tables/signal_contact_signed_prekey_table.dart';
|
import 'package:twonly/src/database/twonly_database_old.steps.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/database/twonly_database.steps.dart';
|
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
part 'twonly_database.g.dart';
|
part 'twonly_database_old.g.dart';
|
||||||
|
|
||||||
// You can then create a database class that includes this table
|
// You can then create a database class that includes this table
|
||||||
@DriftDatabase(
|
@DriftDatabase(
|
||||||
|
|
@ -36,22 +31,16 @@ part 'twonly_database.g.dart';
|
||||||
SignalContactSignedPreKeys,
|
SignalContactSignedPreKeys,
|
||||||
MessageRetransmissions,
|
MessageRetransmissions,
|
||||||
],
|
],
|
||||||
daos: [
|
daos: [],
|
||||||
MessagesDao,
|
|
||||||
ContactsDao,
|
|
||||||
MediaUploadsDao,
|
|
||||||
SignalDao,
|
|
||||||
MessageRetransmissionDao,
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
class TwonlyDatabase extends _$TwonlyDatabase {
|
class TwonlyDatabaseOld extends _$TwonlyDatabaseOld {
|
||||||
TwonlyDatabase([QueryExecutor? e])
|
TwonlyDatabaseOld([QueryExecutor? e])
|
||||||
: super(
|
: super(
|
||||||
e ?? _openConnection(),
|
e ?? _openConnection(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// ignore: matching_super_parameters
|
// ignore: matching_super_parameters
|
||||||
TwonlyDatabase.forTesting(DatabaseConnection super.connection);
|
TwonlyDatabaseOld.forTesting(DatabaseConnection super.connection);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 17;
|
int get schemaVersion => 17;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'twonly_database.dart';
|
part of 'twonly_database_old.dart';
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> {
|
class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> {
|
||||||
|
|
@ -4443,9 +4443,9 @@ class MessageRetransmissionsCompanion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _$TwonlyDatabase extends GeneratedDatabase {
|
abstract class _$TwonlyDatabaseOld extends GeneratedDatabase {
|
||||||
_$TwonlyDatabase(QueryExecutor e) : super(e);
|
_$TwonlyDatabaseOld(QueryExecutor e) : super(e);
|
||||||
$TwonlyDatabaseManager get managers => $TwonlyDatabaseManager(this);
|
$TwonlyDatabaseOldManager get managers => $TwonlyDatabaseOldManager(this);
|
||||||
late final $ContactsTable contacts = $ContactsTable(this);
|
late final $ContactsTable contacts = $ContactsTable(this);
|
||||||
late final $MessagesTable messages = $MessagesTable(this);
|
late final $MessagesTable messages = $MessagesTable(this);
|
||||||
late final $MediaUploadsTable mediaUploads = $MediaUploadsTable(this);
|
late final $MediaUploadsTable mediaUploads = $MediaUploadsTable(this);
|
||||||
|
|
@ -4463,13 +4463,6 @@ abstract class _$TwonlyDatabase extends GeneratedDatabase {
|
||||||
$SignalContactSignedPreKeysTable(this);
|
$SignalContactSignedPreKeysTable(this);
|
||||||
late final $MessageRetransmissionsTable messageRetransmissions =
|
late final $MessageRetransmissionsTable messageRetransmissions =
|
||||||
$MessageRetransmissionsTable(this);
|
$MessageRetransmissionsTable(this);
|
||||||
late final MessagesDao messagesDao = MessagesDao(this as TwonlyDatabase);
|
|
||||||
late final ContactsDao contactsDao = ContactsDao(this as TwonlyDatabase);
|
|
||||||
late final MediaUploadsDao mediaUploadsDao =
|
|
||||||
MediaUploadsDao(this as TwonlyDatabase);
|
|
||||||
late final SignalDao signalDao = SignalDao(this as TwonlyDatabase);
|
|
||||||
late final MessageRetransmissionDao messageRetransmissionDao =
|
|
||||||
MessageRetransmissionDao(this as TwonlyDatabase);
|
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||||
|
|
@ -4559,11 +4552,11 @@ typedef $$ContactsTableUpdateCompanionBuilder = ContactsCompanion Function({
|
||||||
});
|
});
|
||||||
|
|
||||||
final class $$ContactsTableReferences
|
final class $$ContactsTableReferences
|
||||||
extends BaseReferences<_$TwonlyDatabase, $ContactsTable, Contact> {
|
extends BaseReferences<_$TwonlyDatabaseOld, $ContactsTable, Contact> {
|
||||||
$$ContactsTableReferences(super.$_db, super.$_table, super.$_typedResult);
|
$$ContactsTableReferences(super.$_db, super.$_table, super.$_typedResult);
|
||||||
|
|
||||||
static MultiTypedResultKey<$MessagesTable, List<Message>> _messagesRefsTable(
|
static MultiTypedResultKey<$MessagesTable, List<Message>> _messagesRefsTable(
|
||||||
_$TwonlyDatabase db) =>
|
_$TwonlyDatabaseOld db) =>
|
||||||
MultiTypedResultKey.fromTable(db.messages,
|
MultiTypedResultKey.fromTable(db.messages,
|
||||||
aliasName:
|
aliasName:
|
||||||
$_aliasNameGenerator(db.contacts.userId, db.messages.contactId));
|
$_aliasNameGenerator(db.contacts.userId, db.messages.contactId));
|
||||||
|
|
@ -4579,7 +4572,7 @@ final class $$ContactsTableReferences
|
||||||
|
|
||||||
static MultiTypedResultKey<$MessageRetransmissionsTable,
|
static MultiTypedResultKey<$MessageRetransmissionsTable,
|
||||||
List<MessageRetransmission>> _messageRetransmissionsRefsTable(
|
List<MessageRetransmission>> _messageRetransmissionsRefsTable(
|
||||||
_$TwonlyDatabase db) =>
|
_$TwonlyDatabaseOld db) =>
|
||||||
MultiTypedResultKey.fromTable(db.messageRetransmissions,
|
MultiTypedResultKey.fromTable(db.messageRetransmissions,
|
||||||
aliasName: $_aliasNameGenerator(
|
aliasName: $_aliasNameGenerator(
|
||||||
db.contacts.userId, db.messageRetransmissions.contactId));
|
db.contacts.userId, db.messageRetransmissions.contactId));
|
||||||
|
|
@ -4599,7 +4592,7 @@ final class $$ContactsTableReferences
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$ContactsTableFilterComposer
|
class $$ContactsTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $ContactsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $ContactsTable> {
|
||||||
$$ContactsTableFilterComposer({
|
$$ContactsTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -4730,7 +4723,7 @@ class $$ContactsTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$ContactsTableOrderingComposer
|
class $$ContactsTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $ContactsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $ContactsTable> {
|
||||||
$$ContactsTableOrderingComposer({
|
$$ContactsTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -4819,7 +4812,7 @@ class $$ContactsTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$ContactsTableAnnotationComposer
|
class $$ContactsTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $ContactsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $ContactsTable> {
|
||||||
$$ContactsTableAnnotationComposer({
|
$$ContactsTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -4942,7 +4935,7 @@ class $$ContactsTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$ContactsTableTableManager extends RootTableManager<
|
class $$ContactsTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$ContactsTable,
|
$ContactsTable,
|
||||||
Contact,
|
Contact,
|
||||||
$$ContactsTableFilterComposer,
|
$$ContactsTableFilterComposer,
|
||||||
|
|
@ -4954,7 +4947,7 @@ class $$ContactsTableTableManager extends RootTableManager<
|
||||||
Contact,
|
Contact,
|
||||||
PrefetchHooks Function(
|
PrefetchHooks Function(
|
||||||
{bool messagesRefs, bool messageRetransmissionsRefs})> {
|
{bool messagesRefs, bool messageRetransmissionsRefs})> {
|
||||||
$$ContactsTableTableManager(_$TwonlyDatabase db, $ContactsTable table)
|
$$ContactsTableTableManager(_$TwonlyDatabaseOld db, $ContactsTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -5112,7 +5105,7 @@ class $$ContactsTableTableManager extends RootTableManager<
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef $$ContactsTableProcessedTableManager = ProcessedTableManager<
|
typedef $$ContactsTableProcessedTableManager = ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$ContactsTable,
|
$ContactsTable,
|
||||||
Contact,
|
Contact,
|
||||||
$$ContactsTableFilterComposer,
|
$$ContactsTableFilterComposer,
|
||||||
|
|
@ -5166,10 +5159,10 @@ typedef $$MessagesTableUpdateCompanionBuilder = MessagesCompanion Function({
|
||||||
});
|
});
|
||||||
|
|
||||||
final class $$MessagesTableReferences
|
final class $$MessagesTableReferences
|
||||||
extends BaseReferences<_$TwonlyDatabase, $MessagesTable, Message> {
|
extends BaseReferences<_$TwonlyDatabaseOld, $MessagesTable, Message> {
|
||||||
$$MessagesTableReferences(super.$_db, super.$_table, super.$_typedResult);
|
$$MessagesTableReferences(super.$_db, super.$_table, super.$_typedResult);
|
||||||
|
|
||||||
static $ContactsTable _contactIdTable(_$TwonlyDatabase db) =>
|
static $ContactsTable _contactIdTable(_$TwonlyDatabaseOld db) =>
|
||||||
db.contacts.createAlias(
|
db.contacts.createAlias(
|
||||||
$_aliasNameGenerator(db.messages.contactId, db.contacts.userId));
|
$_aliasNameGenerator(db.messages.contactId, db.contacts.userId));
|
||||||
|
|
||||||
|
|
@ -5186,7 +5179,7 @@ final class $$MessagesTableReferences
|
||||||
|
|
||||||
static MultiTypedResultKey<$MessageRetransmissionsTable,
|
static MultiTypedResultKey<$MessageRetransmissionsTable,
|
||||||
List<MessageRetransmission>> _messageRetransmissionsRefsTable(
|
List<MessageRetransmission>> _messageRetransmissionsRefsTable(
|
||||||
_$TwonlyDatabase db) =>
|
_$TwonlyDatabaseOld db) =>
|
||||||
MultiTypedResultKey.fromTable(db.messageRetransmissions,
|
MultiTypedResultKey.fromTable(db.messageRetransmissions,
|
||||||
aliasName: $_aliasNameGenerator(
|
aliasName: $_aliasNameGenerator(
|
||||||
db.messages.messageId, db.messageRetransmissions.messageId));
|
db.messages.messageId, db.messageRetransmissions.messageId));
|
||||||
|
|
@ -5206,7 +5199,7 @@ final class $$MessagesTableReferences
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessagesTableFilterComposer
|
class $$MessagesTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MessagesTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MessagesTable> {
|
||||||
$$MessagesTableFilterComposer({
|
$$MessagesTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5324,7 +5317,7 @@ class $$MessagesTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessagesTableOrderingComposer
|
class $$MessagesTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MessagesTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MessagesTable> {
|
||||||
$$MessagesTableOrderingComposer({
|
$$MessagesTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5415,7 +5408,7 @@ class $$MessagesTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessagesTableAnnotationComposer
|
class $$MessagesTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MessagesTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MessagesTable> {
|
||||||
$$MessagesTableAnnotationComposer({
|
$$MessagesTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5521,7 +5514,7 @@ class $$MessagesTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessagesTableTableManager extends RootTableManager<
|
class $$MessagesTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$MessagesTable,
|
$MessagesTable,
|
||||||
Message,
|
Message,
|
||||||
$$MessagesTableFilterComposer,
|
$$MessagesTableFilterComposer,
|
||||||
|
|
@ -5532,7 +5525,7 @@ class $$MessagesTableTableManager extends RootTableManager<
|
||||||
(Message, $$MessagesTableReferences),
|
(Message, $$MessagesTableReferences),
|
||||||
Message,
|
Message,
|
||||||
PrefetchHooks Function({bool contactId, bool messageRetransmissionsRefs})> {
|
PrefetchHooks Function({bool contactId, bool messageRetransmissionsRefs})> {
|
||||||
$$MessagesTableTableManager(_$TwonlyDatabase db, $MessagesTable table)
|
$$MessagesTableTableManager(_$TwonlyDatabaseOld db, $MessagesTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -5684,7 +5677,7 @@ class $$MessagesTableTableManager extends RootTableManager<
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef $$MessagesTableProcessedTableManager = ProcessedTableManager<
|
typedef $$MessagesTableProcessedTableManager = ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$MessagesTable,
|
$MessagesTable,
|
||||||
Message,
|
Message,
|
||||||
$$MessagesTableFilterComposer,
|
$$MessagesTableFilterComposer,
|
||||||
|
|
@ -5713,7 +5706,7 @@ typedef $$MediaUploadsTableUpdateCompanionBuilder = MediaUploadsCompanion
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$MediaUploadsTableFilterComposer
|
class $$MediaUploadsTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MediaUploadsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MediaUploadsTable> {
|
||||||
$$MediaUploadsTableFilterComposer({
|
$$MediaUploadsTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5748,7 +5741,7 @@ class $$MediaUploadsTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MediaUploadsTableOrderingComposer
|
class $$MediaUploadsTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MediaUploadsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MediaUploadsTable> {
|
||||||
$$MediaUploadsTableOrderingComposer({
|
$$MediaUploadsTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5775,7 +5768,7 @@ class $$MediaUploadsTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MediaUploadsTableAnnotationComposer
|
class $$MediaUploadsTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MediaUploadsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MediaUploadsTable> {
|
||||||
$$MediaUploadsTableAnnotationComposer({
|
$$MediaUploadsTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5802,7 +5795,7 @@ class $$MediaUploadsTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MediaUploadsTableTableManager extends RootTableManager<
|
class $$MediaUploadsTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$MediaUploadsTable,
|
$MediaUploadsTable,
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
$$MediaUploadsTableFilterComposer,
|
$$MediaUploadsTableFilterComposer,
|
||||||
|
|
@ -5812,11 +5805,12 @@ class $$MediaUploadsTableTableManager extends RootTableManager<
|
||||||
$$MediaUploadsTableUpdateCompanionBuilder,
|
$$MediaUploadsTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
BaseReferences<_$TwonlyDatabase, $MediaUploadsTable, MediaUpload>
|
BaseReferences<_$TwonlyDatabaseOld, $MediaUploadsTable, MediaUpload>
|
||||||
),
|
),
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
PrefetchHooks Function()> {
|
PrefetchHooks Function()> {
|
||||||
$$MediaUploadsTableTableManager(_$TwonlyDatabase db, $MediaUploadsTable table)
|
$$MediaUploadsTableTableManager(
|
||||||
|
_$TwonlyDatabaseOld db, $MediaUploadsTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -5862,7 +5856,7 @@ class $$MediaUploadsTableTableManager extends RootTableManager<
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef $$MediaUploadsTableProcessedTableManager = ProcessedTableManager<
|
typedef $$MediaUploadsTableProcessedTableManager = ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$MediaUploadsTable,
|
$MediaUploadsTable,
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
$$MediaUploadsTableFilterComposer,
|
$$MediaUploadsTableFilterComposer,
|
||||||
|
|
@ -5872,7 +5866,7 @@ typedef $$MediaUploadsTableProcessedTableManager = ProcessedTableManager<
|
||||||
$$MediaUploadsTableUpdateCompanionBuilder,
|
$$MediaUploadsTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
BaseReferences<_$TwonlyDatabase, $MediaUploadsTable, MediaUpload>
|
BaseReferences<_$TwonlyDatabaseOld, $MediaUploadsTable, MediaUpload>
|
||||||
),
|
),
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
PrefetchHooks Function()>;
|
PrefetchHooks Function()>;
|
||||||
|
|
@ -5894,7 +5888,7 @@ typedef $$SignalIdentityKeyStoresTableUpdateCompanionBuilder
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$SignalIdentityKeyStoresTableFilterComposer
|
class $$SignalIdentityKeyStoresTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable> {
|
||||||
$$SignalIdentityKeyStoresTableFilterComposer({
|
$$SignalIdentityKeyStoresTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5916,7 +5910,7 @@ class $$SignalIdentityKeyStoresTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalIdentityKeyStoresTableOrderingComposer
|
class $$SignalIdentityKeyStoresTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable> {
|
||||||
$$SignalIdentityKeyStoresTableOrderingComposer({
|
$$SignalIdentityKeyStoresTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5938,7 +5932,7 @@ class $$SignalIdentityKeyStoresTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalIdentityKeyStoresTableAnnotationComposer
|
class $$SignalIdentityKeyStoresTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable> {
|
||||||
$$SignalIdentityKeyStoresTableAnnotationComposer({
|
$$SignalIdentityKeyStoresTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -5960,7 +5954,7 @@ class $$SignalIdentityKeyStoresTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager<
|
class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalIdentityKeyStoresTable,
|
$SignalIdentityKeyStoresTable,
|
||||||
SignalIdentityKeyStore,
|
SignalIdentityKeyStore,
|
||||||
$$SignalIdentityKeyStoresTableFilterComposer,
|
$$SignalIdentityKeyStoresTableFilterComposer,
|
||||||
|
|
@ -5970,13 +5964,13 @@ class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager<
|
||||||
$$SignalIdentityKeyStoresTableUpdateCompanionBuilder,
|
$$SignalIdentityKeyStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalIdentityKeyStore,
|
SignalIdentityKeyStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalIdentityKeyStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable,
|
||||||
SignalIdentityKeyStore>
|
SignalIdentityKeyStore>
|
||||||
),
|
),
|
||||||
SignalIdentityKeyStore,
|
SignalIdentityKeyStore,
|
||||||
PrefetchHooks Function()> {
|
PrefetchHooks Function()> {
|
||||||
$$SignalIdentityKeyStoresTableTableManager(
|
$$SignalIdentityKeyStoresTableTableManager(
|
||||||
_$TwonlyDatabase db, $SignalIdentityKeyStoresTable table)
|
_$TwonlyDatabaseOld db, $SignalIdentityKeyStoresTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -6026,7 +6020,7 @@ class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager<
|
||||||
|
|
||||||
typedef $$SignalIdentityKeyStoresTableProcessedTableManager
|
typedef $$SignalIdentityKeyStoresTableProcessedTableManager
|
||||||
= ProcessedTableManager<
|
= ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalIdentityKeyStoresTable,
|
$SignalIdentityKeyStoresTable,
|
||||||
SignalIdentityKeyStore,
|
SignalIdentityKeyStore,
|
||||||
$$SignalIdentityKeyStoresTableFilterComposer,
|
$$SignalIdentityKeyStoresTableFilterComposer,
|
||||||
|
|
@ -6036,7 +6030,7 @@ typedef $$SignalIdentityKeyStoresTableProcessedTableManager
|
||||||
$$SignalIdentityKeyStoresTableUpdateCompanionBuilder,
|
$$SignalIdentityKeyStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalIdentityKeyStore,
|
SignalIdentityKeyStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalIdentityKeyStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable,
|
||||||
SignalIdentityKeyStore>
|
SignalIdentityKeyStore>
|
||||||
),
|
),
|
||||||
SignalIdentityKeyStore,
|
SignalIdentityKeyStore,
|
||||||
|
|
@ -6055,7 +6049,7 @@ typedef $$SignalPreKeyStoresTableUpdateCompanionBuilder
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$SignalPreKeyStoresTableFilterComposer
|
class $$SignalPreKeyStoresTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable> {
|
||||||
$$SignalPreKeyStoresTableFilterComposer({
|
$$SignalPreKeyStoresTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6074,7 +6068,7 @@ class $$SignalPreKeyStoresTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalPreKeyStoresTableOrderingComposer
|
class $$SignalPreKeyStoresTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable> {
|
||||||
$$SignalPreKeyStoresTableOrderingComposer({
|
$$SignalPreKeyStoresTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6093,7 +6087,7 @@ class $$SignalPreKeyStoresTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalPreKeyStoresTableAnnotationComposer
|
class $$SignalPreKeyStoresTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable> {
|
||||||
$$SignalPreKeyStoresTableAnnotationComposer({
|
$$SignalPreKeyStoresTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6112,7 +6106,7 @@ class $$SignalPreKeyStoresTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalPreKeyStoresTableTableManager extends RootTableManager<
|
class $$SignalPreKeyStoresTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalPreKeyStoresTable,
|
$SignalPreKeyStoresTable,
|
||||||
SignalPreKeyStore,
|
SignalPreKeyStore,
|
||||||
$$SignalPreKeyStoresTableFilterComposer,
|
$$SignalPreKeyStoresTableFilterComposer,
|
||||||
|
|
@ -6122,13 +6116,13 @@ class $$SignalPreKeyStoresTableTableManager extends RootTableManager<
|
||||||
$$SignalPreKeyStoresTableUpdateCompanionBuilder,
|
$$SignalPreKeyStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalPreKeyStore,
|
SignalPreKeyStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalPreKeyStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable,
|
||||||
SignalPreKeyStore>
|
SignalPreKeyStore>
|
||||||
),
|
),
|
||||||
SignalPreKeyStore,
|
SignalPreKeyStore,
|
||||||
PrefetchHooks Function()> {
|
PrefetchHooks Function()> {
|
||||||
$$SignalPreKeyStoresTableTableManager(
|
$$SignalPreKeyStoresTableTableManager(
|
||||||
_$TwonlyDatabase db, $SignalPreKeyStoresTable table)
|
_$TwonlyDatabaseOld db, $SignalPreKeyStoresTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -6167,7 +6161,7 @@ class $$SignalPreKeyStoresTableTableManager extends RootTableManager<
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef $$SignalPreKeyStoresTableProcessedTableManager = ProcessedTableManager<
|
typedef $$SignalPreKeyStoresTableProcessedTableManager = ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalPreKeyStoresTable,
|
$SignalPreKeyStoresTable,
|
||||||
SignalPreKeyStore,
|
SignalPreKeyStore,
|
||||||
$$SignalPreKeyStoresTableFilterComposer,
|
$$SignalPreKeyStoresTableFilterComposer,
|
||||||
|
|
@ -6177,7 +6171,7 @@ typedef $$SignalPreKeyStoresTableProcessedTableManager = ProcessedTableManager<
|
||||||
$$SignalPreKeyStoresTableUpdateCompanionBuilder,
|
$$SignalPreKeyStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalPreKeyStore,
|
SignalPreKeyStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalPreKeyStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable,
|
||||||
SignalPreKeyStore>
|
SignalPreKeyStore>
|
||||||
),
|
),
|
||||||
SignalPreKeyStore,
|
SignalPreKeyStore,
|
||||||
|
|
@ -6196,7 +6190,7 @@ typedef $$SignalSenderKeyStoresTableUpdateCompanionBuilder
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$SignalSenderKeyStoresTableFilterComposer
|
class $$SignalSenderKeyStoresTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable> {
|
||||||
$$SignalSenderKeyStoresTableFilterComposer({
|
$$SignalSenderKeyStoresTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6212,7 +6206,7 @@ class $$SignalSenderKeyStoresTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalSenderKeyStoresTableOrderingComposer
|
class $$SignalSenderKeyStoresTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable> {
|
||||||
$$SignalSenderKeyStoresTableOrderingComposer({
|
$$SignalSenderKeyStoresTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6229,7 +6223,7 @@ class $$SignalSenderKeyStoresTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalSenderKeyStoresTableAnnotationComposer
|
class $$SignalSenderKeyStoresTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable> {
|
||||||
$$SignalSenderKeyStoresTableAnnotationComposer({
|
$$SignalSenderKeyStoresTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6245,7 +6239,7 @@ class $$SignalSenderKeyStoresTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalSenderKeyStoresTableTableManager extends RootTableManager<
|
class $$SignalSenderKeyStoresTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalSenderKeyStoresTable,
|
$SignalSenderKeyStoresTable,
|
||||||
SignalSenderKeyStore,
|
SignalSenderKeyStore,
|
||||||
$$SignalSenderKeyStoresTableFilterComposer,
|
$$SignalSenderKeyStoresTableFilterComposer,
|
||||||
|
|
@ -6255,13 +6249,13 @@ class $$SignalSenderKeyStoresTableTableManager extends RootTableManager<
|
||||||
$$SignalSenderKeyStoresTableUpdateCompanionBuilder,
|
$$SignalSenderKeyStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalSenderKeyStore,
|
SignalSenderKeyStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalSenderKeyStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable,
|
||||||
SignalSenderKeyStore>
|
SignalSenderKeyStore>
|
||||||
),
|
),
|
||||||
SignalSenderKeyStore,
|
SignalSenderKeyStore,
|
||||||
PrefetchHooks Function()> {
|
PrefetchHooks Function()> {
|
||||||
$$SignalSenderKeyStoresTableTableManager(
|
$$SignalSenderKeyStoresTableTableManager(
|
||||||
_$TwonlyDatabase db, $SignalSenderKeyStoresTable table)
|
_$TwonlyDatabaseOld db, $SignalSenderKeyStoresTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -6303,7 +6297,7 @@ class $$SignalSenderKeyStoresTableTableManager extends RootTableManager<
|
||||||
|
|
||||||
typedef $$SignalSenderKeyStoresTableProcessedTableManager
|
typedef $$SignalSenderKeyStoresTableProcessedTableManager
|
||||||
= ProcessedTableManager<
|
= ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalSenderKeyStoresTable,
|
$SignalSenderKeyStoresTable,
|
||||||
SignalSenderKeyStore,
|
SignalSenderKeyStore,
|
||||||
$$SignalSenderKeyStoresTableFilterComposer,
|
$$SignalSenderKeyStoresTableFilterComposer,
|
||||||
|
|
@ -6313,7 +6307,7 @@ typedef $$SignalSenderKeyStoresTableProcessedTableManager
|
||||||
$$SignalSenderKeyStoresTableUpdateCompanionBuilder,
|
$$SignalSenderKeyStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalSenderKeyStore,
|
SignalSenderKeyStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalSenderKeyStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable,
|
||||||
SignalSenderKeyStore>
|
SignalSenderKeyStore>
|
||||||
),
|
),
|
||||||
SignalSenderKeyStore,
|
SignalSenderKeyStore,
|
||||||
|
|
@ -6336,7 +6330,7 @@ typedef $$SignalSessionStoresTableUpdateCompanionBuilder
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$SignalSessionStoresTableFilterComposer
|
class $$SignalSessionStoresTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalSessionStoresTable> {
|
||||||
$$SignalSessionStoresTableFilterComposer({
|
$$SignalSessionStoresTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6358,7 +6352,7 @@ class $$SignalSessionStoresTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalSessionStoresTableOrderingComposer
|
class $$SignalSessionStoresTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalSessionStoresTable> {
|
||||||
$$SignalSessionStoresTableOrderingComposer({
|
$$SignalSessionStoresTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6381,7 +6375,7 @@ class $$SignalSessionStoresTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalSessionStoresTableAnnotationComposer
|
class $$SignalSessionStoresTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalSessionStoresTable> {
|
||||||
$$SignalSessionStoresTableAnnotationComposer({
|
$$SignalSessionStoresTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6403,7 +6397,7 @@ class $$SignalSessionStoresTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalSessionStoresTableTableManager extends RootTableManager<
|
class $$SignalSessionStoresTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalSessionStoresTable,
|
$SignalSessionStoresTable,
|
||||||
SignalSessionStore,
|
SignalSessionStore,
|
||||||
$$SignalSessionStoresTableFilterComposer,
|
$$SignalSessionStoresTableFilterComposer,
|
||||||
|
|
@ -6413,13 +6407,13 @@ class $$SignalSessionStoresTableTableManager extends RootTableManager<
|
||||||
$$SignalSessionStoresTableUpdateCompanionBuilder,
|
$$SignalSessionStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalSessionStore,
|
SignalSessionStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalSessionStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalSessionStoresTable,
|
||||||
SignalSessionStore>
|
SignalSessionStore>
|
||||||
),
|
),
|
||||||
SignalSessionStore,
|
SignalSessionStore,
|
||||||
PrefetchHooks Function()> {
|
PrefetchHooks Function()> {
|
||||||
$$SignalSessionStoresTableTableManager(
|
$$SignalSessionStoresTableTableManager(
|
||||||
_$TwonlyDatabase db, $SignalSessionStoresTable table)
|
_$TwonlyDatabaseOld db, $SignalSessionStoresTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -6467,7 +6461,7 @@ class $$SignalSessionStoresTableTableManager extends RootTableManager<
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef $$SignalSessionStoresTableProcessedTableManager = ProcessedTableManager<
|
typedef $$SignalSessionStoresTableProcessedTableManager = ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalSessionStoresTable,
|
$SignalSessionStoresTable,
|
||||||
SignalSessionStore,
|
SignalSessionStore,
|
||||||
$$SignalSessionStoresTableFilterComposer,
|
$$SignalSessionStoresTableFilterComposer,
|
||||||
|
|
@ -6477,7 +6471,7 @@ typedef $$SignalSessionStoresTableProcessedTableManager = ProcessedTableManager<
|
||||||
$$SignalSessionStoresTableUpdateCompanionBuilder,
|
$$SignalSessionStoresTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalSessionStore,
|
SignalSessionStore,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalSessionStoresTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalSessionStoresTable,
|
||||||
SignalSessionStore>
|
SignalSessionStore>
|
||||||
),
|
),
|
||||||
SignalSessionStore,
|
SignalSessionStore,
|
||||||
|
|
@ -6500,7 +6494,7 @@ typedef $$SignalContactPreKeysTableUpdateCompanionBuilder
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$SignalContactPreKeysTableFilterComposer
|
class $$SignalContactPreKeysTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalContactPreKeysTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalContactPreKeysTable> {
|
||||||
$$SignalContactPreKeysTableFilterComposer({
|
$$SignalContactPreKeysTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6522,7 +6516,7 @@ class $$SignalContactPreKeysTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalContactPreKeysTableOrderingComposer
|
class $$SignalContactPreKeysTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalContactPreKeysTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalContactPreKeysTable> {
|
||||||
$$SignalContactPreKeysTableOrderingComposer({
|
$$SignalContactPreKeysTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6544,7 +6538,7 @@ class $$SignalContactPreKeysTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalContactPreKeysTableAnnotationComposer
|
class $$SignalContactPreKeysTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalContactPreKeysTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalContactPreKeysTable> {
|
||||||
$$SignalContactPreKeysTableAnnotationComposer({
|
$$SignalContactPreKeysTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6566,7 +6560,7 @@ class $$SignalContactPreKeysTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalContactPreKeysTableTableManager extends RootTableManager<
|
class $$SignalContactPreKeysTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalContactPreKeysTable,
|
$SignalContactPreKeysTable,
|
||||||
SignalContactPreKey,
|
SignalContactPreKey,
|
||||||
$$SignalContactPreKeysTableFilterComposer,
|
$$SignalContactPreKeysTableFilterComposer,
|
||||||
|
|
@ -6576,13 +6570,13 @@ class $$SignalContactPreKeysTableTableManager extends RootTableManager<
|
||||||
$$SignalContactPreKeysTableUpdateCompanionBuilder,
|
$$SignalContactPreKeysTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalContactPreKey,
|
SignalContactPreKey,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalContactPreKeysTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalContactPreKeysTable,
|
||||||
SignalContactPreKey>
|
SignalContactPreKey>
|
||||||
),
|
),
|
||||||
SignalContactPreKey,
|
SignalContactPreKey,
|
||||||
PrefetchHooks Function()> {
|
PrefetchHooks Function()> {
|
||||||
$$SignalContactPreKeysTableTableManager(
|
$$SignalContactPreKeysTableTableManager(
|
||||||
_$TwonlyDatabase db, $SignalContactPreKeysTable table)
|
_$TwonlyDatabaseOld db, $SignalContactPreKeysTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -6631,7 +6625,7 @@ class $$SignalContactPreKeysTableTableManager extends RootTableManager<
|
||||||
|
|
||||||
typedef $$SignalContactPreKeysTableProcessedTableManager
|
typedef $$SignalContactPreKeysTableProcessedTableManager
|
||||||
= ProcessedTableManager<
|
= ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalContactPreKeysTable,
|
$SignalContactPreKeysTable,
|
||||||
SignalContactPreKey,
|
SignalContactPreKey,
|
||||||
$$SignalContactPreKeysTableFilterComposer,
|
$$SignalContactPreKeysTableFilterComposer,
|
||||||
|
|
@ -6641,7 +6635,7 @@ typedef $$SignalContactPreKeysTableProcessedTableManager
|
||||||
$$SignalContactPreKeysTableUpdateCompanionBuilder,
|
$$SignalContactPreKeysTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalContactPreKey,
|
SignalContactPreKey,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalContactPreKeysTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalContactPreKeysTable,
|
||||||
SignalContactPreKey>
|
SignalContactPreKey>
|
||||||
),
|
),
|
||||||
SignalContactPreKey,
|
SignalContactPreKey,
|
||||||
|
|
@ -6664,7 +6658,7 @@ typedef $$SignalContactSignedPreKeysTableUpdateCompanionBuilder
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$SignalContactSignedPreKeysTableFilterComposer
|
class $$SignalContactSignedPreKeysTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalContactSignedPreKeysTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable> {
|
||||||
$$SignalContactSignedPreKeysTableFilterComposer({
|
$$SignalContactSignedPreKeysTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6691,7 +6685,7 @@ class $$SignalContactSignedPreKeysTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalContactSignedPreKeysTableOrderingComposer
|
class $$SignalContactSignedPreKeysTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalContactSignedPreKeysTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable> {
|
||||||
$$SignalContactSignedPreKeysTableOrderingComposer({
|
$$SignalContactSignedPreKeysTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6719,7 +6713,7 @@ class $$SignalContactSignedPreKeysTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalContactSignedPreKeysTableAnnotationComposer
|
class $$SignalContactSignedPreKeysTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $SignalContactSignedPreKeysTable> {
|
extends Composer<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable> {
|
||||||
$$SignalContactSignedPreKeysTableAnnotationComposer({
|
$$SignalContactSignedPreKeysTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6744,7 +6738,7 @@ class $$SignalContactSignedPreKeysTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SignalContactSignedPreKeysTableTableManager extends RootTableManager<
|
class $$SignalContactSignedPreKeysTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalContactSignedPreKeysTable,
|
$SignalContactSignedPreKeysTable,
|
||||||
SignalContactSignedPreKey,
|
SignalContactSignedPreKey,
|
||||||
$$SignalContactSignedPreKeysTableFilterComposer,
|
$$SignalContactSignedPreKeysTableFilterComposer,
|
||||||
|
|
@ -6754,13 +6748,13 @@ class $$SignalContactSignedPreKeysTableTableManager extends RootTableManager<
|
||||||
$$SignalContactSignedPreKeysTableUpdateCompanionBuilder,
|
$$SignalContactSignedPreKeysTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalContactSignedPreKey,
|
SignalContactSignedPreKey,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalContactSignedPreKeysTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable,
|
||||||
SignalContactSignedPreKey>
|
SignalContactSignedPreKey>
|
||||||
),
|
),
|
||||||
SignalContactSignedPreKey,
|
SignalContactSignedPreKey,
|
||||||
PrefetchHooks Function()> {
|
PrefetchHooks Function()> {
|
||||||
$$SignalContactSignedPreKeysTableTableManager(
|
$$SignalContactSignedPreKeysTableTableManager(
|
||||||
_$TwonlyDatabase db, $SignalContactSignedPreKeysTable table)
|
_$TwonlyDatabaseOld db, $SignalContactSignedPreKeysTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -6810,7 +6804,7 @@ class $$SignalContactSignedPreKeysTableTableManager extends RootTableManager<
|
||||||
|
|
||||||
typedef $$SignalContactSignedPreKeysTableProcessedTableManager
|
typedef $$SignalContactSignedPreKeysTableProcessedTableManager
|
||||||
= ProcessedTableManager<
|
= ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$SignalContactSignedPreKeysTable,
|
$SignalContactSignedPreKeysTable,
|
||||||
SignalContactSignedPreKey,
|
SignalContactSignedPreKey,
|
||||||
$$SignalContactSignedPreKeysTableFilterComposer,
|
$$SignalContactSignedPreKeysTableFilterComposer,
|
||||||
|
|
@ -6820,7 +6814,7 @@ typedef $$SignalContactSignedPreKeysTableProcessedTableManager
|
||||||
$$SignalContactSignedPreKeysTableUpdateCompanionBuilder,
|
$$SignalContactSignedPreKeysTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
SignalContactSignedPreKey,
|
SignalContactSignedPreKey,
|
||||||
BaseReferences<_$TwonlyDatabase, $SignalContactSignedPreKeysTable,
|
BaseReferences<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable,
|
||||||
SignalContactSignedPreKey>
|
SignalContactSignedPreKey>
|
||||||
),
|
),
|
||||||
SignalContactSignedPreKey,
|
SignalContactSignedPreKey,
|
||||||
|
|
@ -6851,11 +6845,11 @@ typedef $$MessageRetransmissionsTableUpdateCompanionBuilder
|
||||||
});
|
});
|
||||||
|
|
||||||
final class $$MessageRetransmissionsTableReferences extends BaseReferences<
|
final class $$MessageRetransmissionsTableReferences extends BaseReferences<
|
||||||
_$TwonlyDatabase, $MessageRetransmissionsTable, MessageRetransmission> {
|
_$TwonlyDatabaseOld, $MessageRetransmissionsTable, MessageRetransmission> {
|
||||||
$$MessageRetransmissionsTableReferences(
|
$$MessageRetransmissionsTableReferences(
|
||||||
super.$_db, super.$_table, super.$_typedResult);
|
super.$_db, super.$_table, super.$_typedResult);
|
||||||
|
|
||||||
static $ContactsTable _contactIdTable(_$TwonlyDatabase db) =>
|
static $ContactsTable _contactIdTable(_$TwonlyDatabaseOld db) =>
|
||||||
db.contacts.createAlias($_aliasNameGenerator(
|
db.contacts.createAlias($_aliasNameGenerator(
|
||||||
db.messageRetransmissions.contactId, db.contacts.userId));
|
db.messageRetransmissions.contactId, db.contacts.userId));
|
||||||
|
|
||||||
|
|
@ -6870,7 +6864,7 @@ final class $$MessageRetransmissionsTableReferences extends BaseReferences<
|
||||||
manager.$state.copyWith(prefetchedData: [item]));
|
manager.$state.copyWith(prefetchedData: [item]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static $MessagesTable _messageIdTable(_$TwonlyDatabase db) =>
|
static $MessagesTable _messageIdTable(_$TwonlyDatabaseOld db) =>
|
||||||
db.messages.createAlias($_aliasNameGenerator(
|
db.messages.createAlias($_aliasNameGenerator(
|
||||||
db.messageRetransmissions.messageId, db.messages.messageId));
|
db.messageRetransmissions.messageId, db.messages.messageId));
|
||||||
|
|
||||||
|
|
@ -6887,7 +6881,7 @@ final class $$MessageRetransmissionsTableReferences extends BaseReferences<
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessageRetransmissionsTableFilterComposer
|
class $$MessageRetransmissionsTableFilterComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MessageRetransmissionsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MessageRetransmissionsTable> {
|
||||||
$$MessageRetransmissionsTableFilterComposer({
|
$$MessageRetransmissionsTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -6961,7 +6955,7 @@ class $$MessageRetransmissionsTableFilterComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessageRetransmissionsTableOrderingComposer
|
class $$MessageRetransmissionsTableOrderingComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MessageRetransmissionsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MessageRetransmissionsTable> {
|
||||||
$$MessageRetransmissionsTableOrderingComposer({
|
$$MessageRetransmissionsTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -7036,7 +7030,7 @@ class $$MessageRetransmissionsTableOrderingComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessageRetransmissionsTableAnnotationComposer
|
class $$MessageRetransmissionsTableAnnotationComposer
|
||||||
extends Composer<_$TwonlyDatabase, $MessageRetransmissionsTable> {
|
extends Composer<_$TwonlyDatabaseOld, $MessageRetransmissionsTable> {
|
||||||
$$MessageRetransmissionsTableAnnotationComposer({
|
$$MessageRetransmissionsTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
|
|
@ -7107,7 +7101,7 @@ class $$MessageRetransmissionsTableAnnotationComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$MessageRetransmissionsTable,
|
$MessageRetransmissionsTable,
|
||||||
MessageRetransmission,
|
MessageRetransmission,
|
||||||
$$MessageRetransmissionsTableFilterComposer,
|
$$MessageRetransmissionsTableFilterComposer,
|
||||||
|
|
@ -7119,7 +7113,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
||||||
MessageRetransmission,
|
MessageRetransmission,
|
||||||
PrefetchHooks Function({bool contactId, bool messageId})> {
|
PrefetchHooks Function({bool contactId, bool messageId})> {
|
||||||
$$MessageRetransmissionsTableTableManager(
|
$$MessageRetransmissionsTableTableManager(
|
||||||
_$TwonlyDatabase db, $MessageRetransmissionsTable table)
|
_$TwonlyDatabaseOld db, $MessageRetransmissionsTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
|
|
@ -7234,7 +7228,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
||||||
|
|
||||||
typedef $$MessageRetransmissionsTableProcessedTableManager
|
typedef $$MessageRetransmissionsTableProcessedTableManager
|
||||||
= ProcessedTableManager<
|
= ProcessedTableManager<
|
||||||
_$TwonlyDatabase,
|
_$TwonlyDatabaseOld,
|
||||||
$MessageRetransmissionsTable,
|
$MessageRetransmissionsTable,
|
||||||
MessageRetransmission,
|
MessageRetransmission,
|
||||||
$$MessageRetransmissionsTableFilterComposer,
|
$$MessageRetransmissionsTableFilterComposer,
|
||||||
|
|
@ -7246,9 +7240,9 @@ typedef $$MessageRetransmissionsTableProcessedTableManager
|
||||||
MessageRetransmission,
|
MessageRetransmission,
|
||||||
PrefetchHooks Function({bool contactId, bool messageId})>;
|
PrefetchHooks Function({bool contactId, bool messageId})>;
|
||||||
|
|
||||||
class $TwonlyDatabaseManager {
|
class $TwonlyDatabaseOldManager {
|
||||||
final _$TwonlyDatabase _db;
|
final _$TwonlyDatabaseOld _db;
|
||||||
$TwonlyDatabaseManager(this._db);
|
$TwonlyDatabaseOldManager(this._db);
|
||||||
$$ContactsTableTableManager get contacts =>
|
$$ContactsTableTableManager get contacts =>
|
||||||
$$ContactsTableTableManager(_db, _db.contacts);
|
$$ContactsTableTableManager(_db, _db.contacts);
|
||||||
$$MessagesTableTableManager get messages =>
|
$$MessagesTableTableManager get messages =>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// ignore_for_file: strict_raw_type, prefer_constructors_over_static_methods
|
// ignore_for_file: strict_raw_type, prefer_constructors_over_static_methods
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables_old/messages_table.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
Color getMessageColorFromType(MessageContent content, BuildContext context) {
|
Color getMessageColorFromType(MessageContent content, BuildContext context) {
|
||||||
|
|
@ -3,8 +3,8 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message_old.dart';
|
||||||
import 'package:twonly/src/services/api/media_upload.dart' as send;
|
import 'package:twonly/src/services/api/media_upload.dart' as send;
|
||||||
import 'package:twonly/src/services/thumbnail.service.dart';
|
import 'package:twonly/src/services/thumbnail.service.dart';
|
||||||
|
|
||||||
|
|
|
||||||
1172
lib/src/model/protobuf/client/generated/messages.pb.dart
Normal file
1172
lib/src/model/protobuf/client/generated/messages.pb.dart
Normal file
File diff suppressed because it is too large
Load diff
149
lib/src/model/protobuf/client/generated/messages.pbenum.dart
Normal file
149
lib/src/model/protobuf/client/generated/messages.pbenum.dart
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: messages.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
|
||||||
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
|
class Message_Type extends $pb.ProtobufEnum {
|
||||||
|
static const Message_Type SENDER_DELIVERY_RECEIPT = Message_Type._(0, _omitEnumNames ? '' : 'SENDER_DELIVERY_RECEIPT');
|
||||||
|
static const Message_Type PLAINTEXT_CONTENT = Message_Type._(1, _omitEnumNames ? '' : 'PLAINTEXT_CONTENT');
|
||||||
|
static const Message_Type CIPHERTEXT = Message_Type._(2, _omitEnumNames ? '' : 'CIPHERTEXT');
|
||||||
|
static const Message_Type PREKEY_BUNDLE = Message_Type._(3, _omitEnumNames ? '' : 'PREKEY_BUNDLE');
|
||||||
|
|
||||||
|
static const $core.List<Message_Type> values = <Message_Type> [
|
||||||
|
SENDER_DELIVERY_RECEIPT,
|
||||||
|
PLAINTEXT_CONTENT,
|
||||||
|
CIPHERTEXT,
|
||||||
|
PREKEY_BUNDLE,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, Message_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static Message_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const Message_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlaintextContent_DecryptionErrorMessage_Type extends $pb.ProtobufEnum {
|
||||||
|
static const PlaintextContent_DecryptionErrorMessage_Type UNKNOWN = PlaintextContent_DecryptionErrorMessage_Type._(0, _omitEnumNames ? '' : 'UNKNOWN');
|
||||||
|
static const PlaintextContent_DecryptionErrorMessage_Type PREKEY_UNKNOWN = PlaintextContent_DecryptionErrorMessage_Type._(1, _omitEnumNames ? '' : 'PREKEY_UNKNOWN');
|
||||||
|
|
||||||
|
static const $core.List<PlaintextContent_DecryptionErrorMessage_Type> values = <PlaintextContent_DecryptionErrorMessage_Type> [
|
||||||
|
UNKNOWN,
|
||||||
|
PREKEY_UNKNOWN,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, PlaintextContent_DecryptionErrorMessage_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static PlaintextContent_DecryptionErrorMessage_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const PlaintextContent_DecryptionErrorMessage_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EncryptedContent_MessageUpdate_Type extends $pb.ProtobufEnum {
|
||||||
|
static const EncryptedContent_MessageUpdate_Type DELETE = EncryptedContent_MessageUpdate_Type._(0, _omitEnumNames ? '' : 'DELETE');
|
||||||
|
static const EncryptedContent_MessageUpdate_Type EDIT_TEXT = EncryptedContent_MessageUpdate_Type._(1, _omitEnumNames ? '' : 'EDIT_TEXT');
|
||||||
|
static const EncryptedContent_MessageUpdate_Type OPENED = EncryptedContent_MessageUpdate_Type._(2, _omitEnumNames ? '' : 'OPENED');
|
||||||
|
|
||||||
|
static const $core.List<EncryptedContent_MessageUpdate_Type> values = <EncryptedContent_MessageUpdate_Type> [
|
||||||
|
DELETE,
|
||||||
|
EDIT_TEXT,
|
||||||
|
OPENED,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, EncryptedContent_MessageUpdate_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static EncryptedContent_MessageUpdate_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const EncryptedContent_MessageUpdate_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EncryptedContent_Media_Type extends $pb.ProtobufEnum {
|
||||||
|
static const EncryptedContent_Media_Type IMAGE = EncryptedContent_Media_Type._(0, _omitEnumNames ? '' : 'IMAGE');
|
||||||
|
static const EncryptedContent_Media_Type VIDEO = EncryptedContent_Media_Type._(1, _omitEnumNames ? '' : 'VIDEO');
|
||||||
|
static const EncryptedContent_Media_Type GIF = EncryptedContent_Media_Type._(2, _omitEnumNames ? '' : 'GIF');
|
||||||
|
|
||||||
|
static const $core.List<EncryptedContent_Media_Type> values = <EncryptedContent_Media_Type> [
|
||||||
|
IMAGE,
|
||||||
|
VIDEO,
|
||||||
|
GIF,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, EncryptedContent_Media_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static EncryptedContent_Media_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const EncryptedContent_Media_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EncryptedContent_MediaUpdate_Type extends $pb.ProtobufEnum {
|
||||||
|
static const EncryptedContent_MediaUpdate_Type REOPENED = EncryptedContent_MediaUpdate_Type._(0, _omitEnumNames ? '' : 'REOPENED');
|
||||||
|
static const EncryptedContent_MediaUpdate_Type STORED = EncryptedContent_MediaUpdate_Type._(1, _omitEnumNames ? '' : 'STORED');
|
||||||
|
static const EncryptedContent_MediaUpdate_Type DECRYPTION_ERROR = EncryptedContent_MediaUpdate_Type._(2, _omitEnumNames ? '' : 'DECRYPTION_ERROR');
|
||||||
|
|
||||||
|
static const $core.List<EncryptedContent_MediaUpdate_Type> values = <EncryptedContent_MediaUpdate_Type> [
|
||||||
|
REOPENED,
|
||||||
|
STORED,
|
||||||
|
DECRYPTION_ERROR,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, EncryptedContent_MediaUpdate_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static EncryptedContent_MediaUpdate_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const EncryptedContent_MediaUpdate_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EncryptedContent_ContactRequest_Type extends $pb.ProtobufEnum {
|
||||||
|
static const EncryptedContent_ContactRequest_Type REQUEST = EncryptedContent_ContactRequest_Type._(0, _omitEnumNames ? '' : 'REQUEST');
|
||||||
|
static const EncryptedContent_ContactRequest_Type REJECT = EncryptedContent_ContactRequest_Type._(1, _omitEnumNames ? '' : 'REJECT');
|
||||||
|
static const EncryptedContent_ContactRequest_Type ACCEPT = EncryptedContent_ContactRequest_Type._(2, _omitEnumNames ? '' : 'ACCEPT');
|
||||||
|
|
||||||
|
static const $core.List<EncryptedContent_ContactRequest_Type> values = <EncryptedContent_ContactRequest_Type> [
|
||||||
|
REQUEST,
|
||||||
|
REJECT,
|
||||||
|
ACCEPT,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, EncryptedContent_ContactRequest_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static EncryptedContent_ContactRequest_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const EncryptedContent_ContactRequest_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EncryptedContent_ContactUpdate_Type extends $pb.ProtobufEnum {
|
||||||
|
static const EncryptedContent_ContactUpdate_Type REQUEST = EncryptedContent_ContactUpdate_Type._(0, _omitEnumNames ? '' : 'REQUEST');
|
||||||
|
static const EncryptedContent_ContactUpdate_Type UPDATE = EncryptedContent_ContactUpdate_Type._(1, _omitEnumNames ? '' : 'UPDATE');
|
||||||
|
|
||||||
|
static const $core.List<EncryptedContent_ContactUpdate_Type> values = <EncryptedContent_ContactUpdate_Type> [
|
||||||
|
REQUEST,
|
||||||
|
UPDATE,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, EncryptedContent_ContactUpdate_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static EncryptedContent_ContactUpdate_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const EncryptedContent_ContactUpdate_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EncryptedContent_PushKeys_Type extends $pb.ProtobufEnum {
|
||||||
|
static const EncryptedContent_PushKeys_Type REQUEST = EncryptedContent_PushKeys_Type._(0, _omitEnumNames ? '' : 'REQUEST');
|
||||||
|
static const EncryptedContent_PushKeys_Type UPDATE = EncryptedContent_PushKeys_Type._(1, _omitEnumNames ? '' : 'UPDATE');
|
||||||
|
|
||||||
|
static const $core.List<EncryptedContent_PushKeys_Type> values = <EncryptedContent_PushKeys_Type> [
|
||||||
|
REQUEST,
|
||||||
|
UPDATE,
|
||||||
|
];
|
||||||
|
|
||||||
|
static final $core.Map<$core.int, EncryptedContent_PushKeys_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
static EncryptedContent_PushKeys_Type? valueOf($core.int value) => _byValue[value];
|
||||||
|
|
||||||
|
const EncryptedContent_PushKeys_Type._($core.int v, $core.String n) : super(v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
|
||||||
358
lib/src/model/protobuf/client/generated/messages.pbjson.dart
Normal file
358
lib/src/model/protobuf/client/generated/messages.pbjson.dart
Normal file
|
|
@ -0,0 +1,358 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: messages.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
import 'dart:convert' as $convert;
|
||||||
|
import 'dart:core' as $core;
|
||||||
|
import 'dart:typed_data' as $typed_data;
|
||||||
|
|
||||||
|
@$core.Deprecated('Use messageDescriptor instead')
|
||||||
|
const Message$json = {
|
||||||
|
'1': 'Message',
|
||||||
|
'2': [
|
||||||
|
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.Message.Type', '10': 'type'},
|
||||||
|
{'1': 'receiptId', '3': 2, '4': 1, '5': 9, '10': 'receiptId'},
|
||||||
|
{'1': 'encryptedContent', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'encryptedContent', '17': true},
|
||||||
|
{'1': 'plaintextContent', '3': 4, '4': 1, '5': 11, '6': '.PlaintextContent', '9': 1, '10': 'plaintextContent', '17': true},
|
||||||
|
],
|
||||||
|
'4': [Message_Type$json],
|
||||||
|
'8': [
|
||||||
|
{'1': '_encryptedContent'},
|
||||||
|
{'1': '_plaintextContent'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use messageDescriptor instead')
|
||||||
|
const Message_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'SENDER_DELIVERY_RECEIPT', '2': 0},
|
||||||
|
{'1': 'PLAINTEXT_CONTENT', '2': 1},
|
||||||
|
{'1': 'CIPHERTEXT', '2': 2},
|
||||||
|
{'1': 'PREKEY_BUNDLE', '2': 3},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `Message`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List messageDescriptor = $convert.base64Decode(
|
||||||
|
'CgdNZXNzYWdlEiEKBHR5cGUYASABKA4yDS5NZXNzYWdlLlR5cGVSBHR5cGUSHAoJcmVjZWlwdE'
|
||||||
|
'lkGAIgASgJUglyZWNlaXB0SWQSLwoQZW5jcnlwdGVkQ29udGVudBgDIAEoDEgAUhBlbmNyeXB0'
|
||||||
|
'ZWRDb250ZW50iAEBEkIKEHBsYWludGV4dENvbnRlbnQYBCABKAsyES5QbGFpbnRleHRDb250ZW'
|
||||||
|
'50SAFSEHBsYWludGV4dENvbnRlbnSIAQEiXQoEVHlwZRIbChdTRU5ERVJfREVMSVZFUllfUkVD'
|
||||||
|
'RUlQVBAAEhUKEVBMQUlOVEVYVF9DT05URU5UEAESDgoKQ0lQSEVSVEVYVBACEhEKDVBSRUtFWV'
|
||||||
|
'9CVU5ETEUQA0ITChFfZW5jcnlwdGVkQ29udGVudEITChFfcGxhaW50ZXh0Q29udGVudA==');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use plaintextContentDescriptor instead')
|
||||||
|
const PlaintextContent$json = {
|
||||||
|
'1': 'PlaintextContent',
|
||||||
|
'2': [
|
||||||
|
{'1': 'decryptionErrorMessage', '3': 1, '4': 1, '5': 11, '6': '.PlaintextContent.DecryptionErrorMessage', '9': 0, '10': 'decryptionErrorMessage', '17': true},
|
||||||
|
],
|
||||||
|
'3': [PlaintextContent_DecryptionErrorMessage$json],
|
||||||
|
'8': [
|
||||||
|
{'1': '_decryptionErrorMessage'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use plaintextContentDescriptor instead')
|
||||||
|
const PlaintextContent_DecryptionErrorMessage$json = {
|
||||||
|
'1': 'DecryptionErrorMessage',
|
||||||
|
'2': [
|
||||||
|
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.PlaintextContent.DecryptionErrorMessage.Type', '10': 'type'},
|
||||||
|
],
|
||||||
|
'4': [PlaintextContent_DecryptionErrorMessage_Type$json],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use plaintextContentDescriptor instead')
|
||||||
|
const PlaintextContent_DecryptionErrorMessage_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'UNKNOWN', '2': 0},
|
||||||
|
{'1': 'PREKEY_UNKNOWN', '2': 1},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `PlaintextContent`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List plaintextContentDescriptor = $convert.base64Decode(
|
||||||
|
'ChBQbGFpbnRleHRDb250ZW50EmUKFmRlY3J5cHRpb25FcnJvck1lc3NhZ2UYASABKAsyKC5QbG'
|
||||||
|
'FpbnRleHRDb250ZW50LkRlY3J5cHRpb25FcnJvck1lc3NhZ2VIAFIWZGVjcnlwdGlvbkVycm9y'
|
||||||
|
'TWVzc2FnZYgBARqEAQoWRGVjcnlwdGlvbkVycm9yTWVzc2FnZRJBCgR0eXBlGAEgASgOMi0uUG'
|
||||||
|
'xhaW50ZXh0Q29udGVudC5EZWNyeXB0aW9uRXJyb3JNZXNzYWdlLlR5cGVSBHR5cGUiJwoEVHlw'
|
||||||
|
'ZRILCgdVTktOT1dOEAASEgoOUFJFS0VZX1VOS05PV04QAUIZChdfZGVjcnlwdGlvbkVycm9yTW'
|
||||||
|
'Vzc2FnZQ==');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent$json = {
|
||||||
|
'1': 'EncryptedContent',
|
||||||
|
'2': [
|
||||||
|
{'1': 'groupId', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'groupId', '17': true},
|
||||||
|
{'1': 'senderProfileCounter', '3': 3, '4': 1, '5': 3, '9': 1, '10': 'senderProfileCounter', '17': true},
|
||||||
|
{'1': 'textMessage', '3': 4, '4': 1, '5': 11, '6': '.EncryptedContent.TextMessage', '9': 2, '10': 'textMessage', '17': true},
|
||||||
|
{'1': 'messageUpdate', '3': 5, '4': 1, '5': 11, '6': '.EncryptedContent.MessageUpdate', '9': 3, '10': 'messageUpdate', '17': true},
|
||||||
|
{'1': 'media', '3': 6, '4': 1, '5': 11, '6': '.EncryptedContent.Media', '9': 4, '10': 'media', '17': true},
|
||||||
|
{'1': 'mediaUpdate', '3': 7, '4': 1, '5': 11, '6': '.EncryptedContent.MediaUpdate', '9': 5, '10': 'mediaUpdate', '17': true},
|
||||||
|
{'1': 'contactUpdate', '3': 8, '4': 1, '5': 11, '6': '.EncryptedContent.ContactUpdate', '9': 6, '10': 'contactUpdate', '17': true},
|
||||||
|
{'1': 'contactRequest', '3': 9, '4': 1, '5': 11, '6': '.EncryptedContent.ContactRequest', '9': 7, '10': 'contactRequest', '17': true},
|
||||||
|
{'1': 'flameSync', '3': 10, '4': 1, '5': 11, '6': '.EncryptedContent.FlameSync', '9': 8, '10': 'flameSync', '17': true},
|
||||||
|
{'1': 'pushKeys', '3': 11, '4': 1, '5': 11, '6': '.EncryptedContent.PushKeys', '9': 9, '10': 'pushKeys', '17': true},
|
||||||
|
{'1': 'reaction', '3': 12, '4': 1, '5': 11, '6': '.EncryptedContent.Reaction', '9': 10, '10': 'reaction', '17': true},
|
||||||
|
],
|
||||||
|
'3': [EncryptedContent_TextMessage$json, EncryptedContent_Reaction$json, EncryptedContent_MessageUpdate$json, EncryptedContent_Media$json, EncryptedContent_MediaUpdate$json, EncryptedContent_ContactRequest$json, EncryptedContent_ContactUpdate$json, EncryptedContent_PushKeys$json, EncryptedContent_FlameSync$json],
|
||||||
|
'8': [
|
||||||
|
{'1': '_groupId'},
|
||||||
|
{'1': '_senderProfileCounter'},
|
||||||
|
{'1': '_textMessage'},
|
||||||
|
{'1': '_messageUpdate'},
|
||||||
|
{'1': '_media'},
|
||||||
|
{'1': '_mediaUpdate'},
|
||||||
|
{'1': '_contactUpdate'},
|
||||||
|
{'1': '_contactRequest'},
|
||||||
|
{'1': '_flameSync'},
|
||||||
|
{'1': '_pushKeys'},
|
||||||
|
{'1': '_reaction'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_TextMessage$json = {
|
||||||
|
'1': 'TextMessage',
|
||||||
|
'2': [
|
||||||
|
{'1': 'senderMessageId', '3': 1, '4': 1, '5': 9, '10': 'senderMessageId'},
|
||||||
|
{'1': 'text', '3': 2, '4': 1, '5': 9, '10': 'text'},
|
||||||
|
{'1': 'quoteMessageId', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'quoteMessageId', '17': true},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_quoteMessageId'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_Reaction$json = {
|
||||||
|
'1': 'Reaction',
|
||||||
|
'2': [
|
||||||
|
{'1': 'targetMessageId', '3': 1, '4': 1, '5': 9, '10': 'targetMessageId'},
|
||||||
|
{'1': 'emoji', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'emoji', '17': true},
|
||||||
|
{'1': 'remove', '3': 3, '4': 1, '5': 8, '9': 1, '10': 'remove', '17': true},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_emoji'},
|
||||||
|
{'1': '_remove'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_MessageUpdate$json = {
|
||||||
|
'1': 'MessageUpdate',
|
||||||
|
'2': [
|
||||||
|
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.MessageUpdate.Type', '10': 'type'},
|
||||||
|
{'1': 'senderMessageId', '3': 2, '4': 1, '5': 9, '10': 'senderMessageId'},
|
||||||
|
{'1': 'text', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'text', '17': true},
|
||||||
|
{'1': 'timestamp', '3': 4, '4': 1, '5': 3, '9': 1, '10': 'timestamp', '17': true},
|
||||||
|
],
|
||||||
|
'4': [EncryptedContent_MessageUpdate_Type$json],
|
||||||
|
'8': [
|
||||||
|
{'1': '_text'},
|
||||||
|
{'1': '_timestamp'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_MessageUpdate_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'DELETE', '2': 0},
|
||||||
|
{'1': 'EDIT_TEXT', '2': 1},
|
||||||
|
{'1': 'OPENED', '2': 2},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_Media$json = {
|
||||||
|
'1': 'Media',
|
||||||
|
'2': [
|
||||||
|
{'1': 'senderMessageId', '3': 1, '4': 1, '5': 9, '10': 'senderMessageId'},
|
||||||
|
{'1': 'type', '3': 2, '4': 1, '5': 14, '6': '.EncryptedContent.Media.Type', '10': 'type'},
|
||||||
|
{'1': 'displayLimitInMilliseconds', '3': 3, '4': 1, '5': 3, '9': 0, '10': 'displayLimitInMilliseconds', '17': true},
|
||||||
|
{'1': 'requiresAuthentication', '3': 4, '4': 1, '5': 8, '10': 'requiresAuthentication'},
|
||||||
|
{'1': 'downloadToken', '3': 5, '4': 1, '5': 12, '9': 1, '10': 'downloadToken', '17': true},
|
||||||
|
{'1': 'encryptionKey', '3': 6, '4': 1, '5': 12, '9': 2, '10': 'encryptionKey', '17': true},
|
||||||
|
{'1': 'encryptionMac', '3': 7, '4': 1, '5': 12, '9': 3, '10': 'encryptionMac', '17': true},
|
||||||
|
{'1': 'encryptionNonce', '3': 8, '4': 1, '5': 12, '9': 4, '10': 'encryptionNonce', '17': true},
|
||||||
|
],
|
||||||
|
'4': [EncryptedContent_Media_Type$json],
|
||||||
|
'8': [
|
||||||
|
{'1': '_displayLimitInMilliseconds'},
|
||||||
|
{'1': '_downloadToken'},
|
||||||
|
{'1': '_encryptionKey'},
|
||||||
|
{'1': '_encryptionMac'},
|
||||||
|
{'1': '_encryptionNonce'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_Media_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'IMAGE', '2': 0},
|
||||||
|
{'1': 'VIDEO', '2': 1},
|
||||||
|
{'1': 'GIF', '2': 2},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_MediaUpdate$json = {
|
||||||
|
'1': 'MediaUpdate',
|
||||||
|
'2': [
|
||||||
|
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.MediaUpdate.Type', '10': 'type'},
|
||||||
|
{'1': 'targetMessageId', '3': 2, '4': 1, '5': 9, '10': 'targetMessageId'},
|
||||||
|
],
|
||||||
|
'4': [EncryptedContent_MediaUpdate_Type$json],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_MediaUpdate_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'REOPENED', '2': 0},
|
||||||
|
{'1': 'STORED', '2': 1},
|
||||||
|
{'1': 'DECRYPTION_ERROR', '2': 2},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_ContactRequest$json = {
|
||||||
|
'1': 'ContactRequest',
|
||||||
|
'2': [
|
||||||
|
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.ContactRequest.Type', '10': 'type'},
|
||||||
|
],
|
||||||
|
'4': [EncryptedContent_ContactRequest_Type$json],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_ContactRequest_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'REQUEST', '2': 0},
|
||||||
|
{'1': 'REJECT', '2': 1},
|
||||||
|
{'1': 'ACCEPT', '2': 2},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_ContactUpdate$json = {
|
||||||
|
'1': 'ContactUpdate',
|
||||||
|
'2': [
|
||||||
|
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.ContactUpdate.Type', '10': 'type'},
|
||||||
|
{'1': 'avatarSvg', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'avatarSvg', '17': true},
|
||||||
|
{'1': 'displayName', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'displayName', '17': true},
|
||||||
|
],
|
||||||
|
'4': [EncryptedContent_ContactUpdate_Type$json],
|
||||||
|
'8': [
|
||||||
|
{'1': '_avatarSvg'},
|
||||||
|
{'1': '_displayName'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_ContactUpdate_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'REQUEST', '2': 0},
|
||||||
|
{'1': 'UPDATE', '2': 1},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_PushKeys$json = {
|
||||||
|
'1': 'PushKeys',
|
||||||
|
'2': [
|
||||||
|
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.PushKeys.Type', '10': 'type'},
|
||||||
|
{'1': 'keyId', '3': 2, '4': 1, '5': 3, '9': 0, '10': 'keyId', '17': true},
|
||||||
|
{'1': 'key', '3': 3, '4': 1, '5': 12, '9': 1, '10': 'key', '17': true},
|
||||||
|
],
|
||||||
|
'4': [EncryptedContent_PushKeys_Type$json],
|
||||||
|
'8': [
|
||||||
|
{'1': '_keyId'},
|
||||||
|
{'1': '_key'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_PushKeys_Type$json = {
|
||||||
|
'1': 'Type',
|
||||||
|
'2': [
|
||||||
|
{'1': 'REQUEST', '2': 0},
|
||||||
|
{'1': 'UPDATE', '2': 1},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use encryptedContentDescriptor instead')
|
||||||
|
const EncryptedContent_FlameSync$json = {
|
||||||
|
'1': 'FlameSync',
|
||||||
|
'2': [
|
||||||
|
{'1': 'flameCounter', '3': 1, '4': 1, '5': 3, '10': 'flameCounter'},
|
||||||
|
{'1': 'lastFlameCounterChange', '3': 2, '4': 1, '5': 3, '10': 'lastFlameCounterChange'},
|
||||||
|
{'1': 'bestFriend', '3': 3, '4': 1, '5': 8, '10': 'bestFriend'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `EncryptedContent`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List encryptedContentDescriptor = $convert.base64Decode(
|
||||||
|
'ChBFbmNyeXB0ZWRDb250ZW50Eh0KB2dyb3VwSWQYAiABKAlIAFIHZ3JvdXBJZIgBARI3ChRzZW'
|
||||||
|
'5kZXJQcm9maWxlQ291bnRlchgDIAEoA0gBUhRzZW5kZXJQcm9maWxlQ291bnRlcogBARJECgt0'
|
||||||
|
'ZXh0TWVzc2FnZRgEIAEoCzIdLkVuY3J5cHRlZENvbnRlbnQuVGV4dE1lc3NhZ2VIAlILdGV4dE'
|
||||||
|
'1lc3NhZ2WIAQESSgoNbWVzc2FnZVVwZGF0ZRgFIAEoCzIfLkVuY3J5cHRlZENvbnRlbnQuTWVz'
|
||||||
|
'c2FnZVVwZGF0ZUgDUg1tZXNzYWdlVXBkYXRliAEBEjIKBW1lZGlhGAYgASgLMhcuRW5jcnlwdG'
|
||||||
|
'VkQ29udGVudC5NZWRpYUgEUgVtZWRpYYgBARJECgttZWRpYVVwZGF0ZRgHIAEoCzIdLkVuY3J5'
|
||||||
|
'cHRlZENvbnRlbnQuTWVkaWFVcGRhdGVIBVILbWVkaWFVcGRhdGWIAQESSgoNY29udGFjdFVwZG'
|
||||||
|
'F0ZRgIIAEoCzIfLkVuY3J5cHRlZENvbnRlbnQuQ29udGFjdFVwZGF0ZUgGUg1jb250YWN0VXBk'
|
||||||
|
'YXRliAEBEk0KDmNvbnRhY3RSZXF1ZXN0GAkgASgLMiAuRW5jcnlwdGVkQ29udGVudC5Db250YW'
|
||||||
|
'N0UmVxdWVzdEgHUg5jb250YWN0UmVxdWVzdIgBARI+CglmbGFtZVN5bmMYCiABKAsyGy5FbmNy'
|
||||||
|
'eXB0ZWRDb250ZW50LkZsYW1lU3luY0gIUglmbGFtZVN5bmOIAQESOwoIcHVzaEtleXMYCyABKA'
|
||||||
|
'syGi5FbmNyeXB0ZWRDb250ZW50LlB1c2hLZXlzSAlSCHB1c2hLZXlziAEBEjsKCHJlYWN0aW9u'
|
||||||
|
'GAwgASgLMhouRW5jcnlwdGVkQ29udGVudC5SZWFjdGlvbkgKUghyZWFjdGlvbogBARqLAQoLVG'
|
||||||
|
'V4dE1lc3NhZ2USKAoPc2VuZGVyTWVzc2FnZUlkGAEgASgJUg9zZW5kZXJNZXNzYWdlSWQSEgoE'
|
||||||
|
'dGV4dBgCIAEoCVIEdGV4dBIrCg5xdW90ZU1lc3NhZ2VJZBgDIAEoCUgAUg5xdW90ZU1lc3NhZ2'
|
||||||
|
'VJZIgBAUIRCg9fcXVvdGVNZXNzYWdlSWQagQEKCFJlYWN0aW9uEigKD3RhcmdldE1lc3NhZ2VJ'
|
||||||
|
'ZBgBIAEoCVIPdGFyZ2V0TWVzc2FnZUlkEhkKBWVtb2ppGAIgASgJSABSBWVtb2ppiAEBEhsKBn'
|
||||||
|
'JlbW92ZRgDIAEoCEgBUgZyZW1vdmWIAQFCCAoGX2Vtb2ppQgkKB19yZW1vdmUa9QEKDU1lc3Nh'
|
||||||
|
'Z2VVcGRhdGUSOAoEdHlwZRgBIAEoDjIkLkVuY3J5cHRlZENvbnRlbnQuTWVzc2FnZVVwZGF0ZS'
|
||||||
|
'5UeXBlUgR0eXBlEigKD3NlbmRlck1lc3NhZ2VJZBgCIAEoCVIPc2VuZGVyTWVzc2FnZUlkEhcK'
|
||||||
|
'BHRleHQYAyABKAlIAFIEdGV4dIgBARIhCgl0aW1lc3RhbXAYBCABKANIAVIJdGltZXN0YW1wiA'
|
||||||
|
'EBIi0KBFR5cGUSCgoGREVMRVRFEAASDQoJRURJVF9URVhUEAESCgoGT1BFTkVEEAJCBwoFX3Rl'
|
||||||
|
'eHRCDAoKX3RpbWVzdGFtcBqgBAoFTWVkaWESKAoPc2VuZGVyTWVzc2FnZUlkGAEgASgJUg9zZW'
|
||||||
|
'5kZXJNZXNzYWdlSWQSMAoEdHlwZRgCIAEoDjIcLkVuY3J5cHRlZENvbnRlbnQuTWVkaWEuVHlw'
|
||||||
|
'ZVIEdHlwZRJDChpkaXNwbGF5TGltaXRJbk1pbGxpc2Vjb25kcxgDIAEoA0gAUhpkaXNwbGF5TG'
|
||||||
|
'ltaXRJbk1pbGxpc2Vjb25kc4gBARI2ChZyZXF1aXJlc0F1dGhlbnRpY2F0aW9uGAQgASgIUhZy'
|
||||||
|
'ZXF1aXJlc0F1dGhlbnRpY2F0aW9uEikKDWRvd25sb2FkVG9rZW4YBSABKAxIAVINZG93bmxvYW'
|
||||||
|
'RUb2tlbogBARIpCg1lbmNyeXB0aW9uS2V5GAYgASgMSAJSDWVuY3J5cHRpb25LZXmIAQESKQoN'
|
||||||
|
'ZW5jcnlwdGlvbk1hYxgHIAEoDEgDUg1lbmNyeXB0aW9uTWFjiAEBEi0KD2VuY3J5cHRpb25Ob2'
|
||||||
|
'5jZRgIIAEoDEgEUg9lbmNyeXB0aW9uTm9uY2WIAQEiJQoEVHlwZRIJCgVJTUFHRRAAEgkKBVZJ'
|
||||||
|
'REVPEAESBwoDR0lGEAJCHQobX2Rpc3BsYXlMaW1pdEluTWlsbGlzZWNvbmRzQhAKDl9kb3dubG'
|
||||||
|
'9hZFRva2VuQhAKDl9lbmNyeXB0aW9uS2V5QhAKDl9lbmNyeXB0aW9uTWFjQhIKEF9lbmNyeXB0'
|
||||||
|
'aW9uTm9uY2UapwEKC01lZGlhVXBkYXRlEjYKBHR5cGUYASABKA4yIi5FbmNyeXB0ZWRDb250ZW'
|
||||||
|
'50Lk1lZGlhVXBkYXRlLlR5cGVSBHR5cGUSKAoPdGFyZ2V0TWVzc2FnZUlkGAIgASgJUg90YXJn'
|
||||||
|
'ZXRNZXNzYWdlSWQiNgoEVHlwZRIMCghSRU9QRU5FRBAAEgoKBlNUT1JFRBABEhQKEERFQ1JZUF'
|
||||||
|
'RJT05fRVJST1IQAhp4Cg5Db250YWN0UmVxdWVzdBI5CgR0eXBlGAEgASgOMiUuRW5jcnlwdGVk'
|
||||||
|
'Q29udGVudC5Db250YWN0UmVxdWVzdC5UeXBlUgR0eXBlIisKBFR5cGUSCwoHUkVRVUVTVBAAEg'
|
||||||
|
'oKBlJFSkVDVBABEgoKBkFDQ0VQVBACGtIBCg1Db250YWN0VXBkYXRlEjgKBHR5cGUYASABKA4y'
|
||||||
|
'JC5FbmNyeXB0ZWRDb250ZW50LkNvbnRhY3RVcGRhdGUuVHlwZVIEdHlwZRIhCglhdmF0YXJTdm'
|
||||||
|
'cYAiABKAlIAFIJYXZhdGFyU3ZniAEBEiUKC2Rpc3BsYXlOYW1lGAMgASgJSAFSC2Rpc3BsYXlO'
|
||||||
|
'YW1liAEBIh8KBFR5cGUSCwoHUkVRVUVTVBAAEgoKBlVQREFURRABQgwKCl9hdmF0YXJTdmdCDg'
|
||||||
|
'oMX2Rpc3BsYXlOYW1lGqQBCghQdXNoS2V5cxIzCgR0eXBlGAEgASgOMh8uRW5jcnlwdGVkQ29u'
|
||||||
|
'dGVudC5QdXNoS2V5cy5UeXBlUgR0eXBlEhkKBWtleUlkGAIgASgDSABSBWtleUlkiAEBEhUKA2'
|
||||||
|
'tleRgDIAEoDEgBUgNrZXmIAQEiHwoEVHlwZRILCgdSRVFVRVNUEAASCgoGVVBEQVRFEAFCCAoG'
|
||||||
|
'X2tleUlkQgYKBF9rZXkahwEKCUZsYW1lU3luYxIiCgxmbGFtZUNvdW50ZXIYASABKANSDGZsYW'
|
||||||
|
'1lQ291bnRlchI2ChZsYXN0RmxhbWVDb3VudGVyQ2hhbmdlGAIgASgDUhZsYXN0RmxhbWVDb3Vu'
|
||||||
|
'dGVyQ2hhbmdlEh4KCmJlc3RGcmllbmQYAyABKAhSCmJlc3RGcmllbmRCCgoIX2dyb3VwSWRCFw'
|
||||||
|
'oVX3NlbmRlclByb2ZpbGVDb3VudGVyQg4KDF90ZXh0TWVzc2FnZUIQCg5fbWVzc2FnZVVwZGF0'
|
||||||
|
'ZUIICgZfbWVkaWFCDgoMX21lZGlhVXBkYXRlQhAKDl9jb250YWN0VXBkYXRlQhEKD19jb250YW'
|
||||||
|
'N0UmVxdWVzdEIMCgpfZmxhbWVTeW5jQgsKCV9wdXNoS2V5c0ILCglfcmVhY3Rpb24=');
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// Generated code. Do not modify.
|
||||||
|
// source: messages.proto
|
||||||
|
//
|
||||||
|
// @dart = 2.12
|
||||||
|
|
||||||
|
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
||||||
|
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||||
|
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||||
|
|
||||||
|
export 'messages.pb.dart';
|
||||||
|
|
||||||
135
lib/src/model/protobuf/client/messages.proto
Normal file
135
lib/src/model/protobuf/client/messages.proto
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message Message {
|
||||||
|
enum Type {
|
||||||
|
SENDER_DELIVERY_RECEIPT = 0;
|
||||||
|
PLAINTEXT_CONTENT = 1;
|
||||||
|
CIPHERTEXT = 2;
|
||||||
|
PREKEY_BUNDLE = 3;
|
||||||
|
}
|
||||||
|
Type type = 1;
|
||||||
|
string receiptId = 2;
|
||||||
|
optional bytes encryptedContent = 3;
|
||||||
|
optional PlaintextContent plaintextContent = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlaintextContent {
|
||||||
|
optional DecryptionErrorMessage decryptionErrorMessage = 1;
|
||||||
|
|
||||||
|
message DecryptionErrorMessage {
|
||||||
|
enum Type {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
PREKEY_UNKNOWN = 1;
|
||||||
|
}
|
||||||
|
Type type = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message EncryptedContent {
|
||||||
|
|
||||||
|
optional string groupId = 2;
|
||||||
|
|
||||||
|
/// This can be added, so the receiver can check weather he is up to date with the current profile
|
||||||
|
optional int64 senderProfileCounter = 3;
|
||||||
|
|
||||||
|
optional TextMessage textMessage = 4;
|
||||||
|
optional MessageUpdate messageUpdate = 5;
|
||||||
|
optional Media media = 6;
|
||||||
|
optional MediaUpdate mediaUpdate = 7;
|
||||||
|
optional ContactUpdate contactUpdate = 8;
|
||||||
|
optional ContactRequest contactRequest = 9;
|
||||||
|
optional FlameSync flameSync = 10;
|
||||||
|
optional PushKeys pushKeys = 11;
|
||||||
|
optional Reaction reaction = 12;
|
||||||
|
|
||||||
|
message TextMessage {
|
||||||
|
string senderMessageId = 1;
|
||||||
|
string text = 2;
|
||||||
|
optional string quoteMessageId = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Reaction {
|
||||||
|
string targetMessageId = 1;
|
||||||
|
optional string emoji = 2;
|
||||||
|
optional bool remove = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageUpdate {
|
||||||
|
enum Type {
|
||||||
|
DELETE = 0;
|
||||||
|
EDIT_TEXT = 1;
|
||||||
|
OPENED = 2;
|
||||||
|
}
|
||||||
|
Type type = 1;
|
||||||
|
string senderMessageId = 2;
|
||||||
|
optional string text = 3;
|
||||||
|
optional int64 timestamp = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Media {
|
||||||
|
enum Type {
|
||||||
|
IMAGE = 0;
|
||||||
|
VIDEO = 1;
|
||||||
|
GIF = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
string senderMessageId = 1;
|
||||||
|
Type type = 2;
|
||||||
|
optional int64 displayLimitInMilliseconds = 3;
|
||||||
|
bool requiresAuthentication = 4;
|
||||||
|
|
||||||
|
optional bytes downloadToken = 5;
|
||||||
|
optional bytes encryptionKey = 6;
|
||||||
|
optional bytes encryptionMac = 7;
|
||||||
|
optional bytes encryptionNonce = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MediaUpdate {
|
||||||
|
enum Type {
|
||||||
|
REOPENED = 0;
|
||||||
|
STORED = 1;
|
||||||
|
DECRYPTION_ERROR = 2;
|
||||||
|
}
|
||||||
|
Type type = 1;
|
||||||
|
string targetMessageId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ContactRequest {
|
||||||
|
enum Type {
|
||||||
|
REQUEST = 0;
|
||||||
|
REJECT = 1;
|
||||||
|
ACCEPT = 2;
|
||||||
|
}
|
||||||
|
Type type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ContactUpdate {
|
||||||
|
enum Type {
|
||||||
|
REQUEST = 0;
|
||||||
|
UPDATE = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type = 1;
|
||||||
|
optional string avatarSvg = 2;
|
||||||
|
optional string displayName = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PushKeys {
|
||||||
|
enum Type {
|
||||||
|
REQUEST = 0;
|
||||||
|
UPDATE = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type = 1;
|
||||||
|
optional int64 keyId = 2;
|
||||||
|
optional bytes key = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FlameSync {
|
||||||
|
int64 flameCounter = 1;
|
||||||
|
int64 lastFlameCounterChange = 2;
|
||||||
|
bool bestFriend = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ import 'package:mutex/mutex.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pbserver.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pbserver.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart'
|
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart'
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message_old.dart';
|
||||||
import 'package:twonly/src/services/api/media_upload.dart';
|
import 'package:twonly/src/services/api/media_upload.dart';
|
||||||
import 'package:twonly/src/services/api/utils.dart';
|
import 'package:twonly/src/services/api/utils.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
||||||
import 'package:twonly/src/database/tables/media_uploads_table.dart';
|
import 'package:twonly/src/database/tables/media_uploads_table.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message_old.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/http/http_requests.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/http/http_requests.pb.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
||||||
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pbserver.dart';
|
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pbserver.dart';
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message_old.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
||||||
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart'
|
||||||
|
as pb;
|
||||||
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pb.dart';
|
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pb.dart';
|
||||||
import 'package:twonly/src/services/api/server_messages.dart'
|
import 'package:twonly/src/services/api/server_messages.dart'
|
||||||
show messageGetsAck;
|
show messageGetsAck;
|
||||||
|
|
@ -36,12 +38,15 @@ Future<void> tryTransmitMessages() async {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sendRetransmitMessage(int retransId) async {
|
Future<void> tryToSendCompleteMessage(String receiptId) async {
|
||||||
try {
|
try {
|
||||||
final retrans = await twonlyDB.messageRetransmissionDao
|
final retrans = await twonlyDB.messageRetransmissionDao
|
||||||
.getRetransmissionById(retransId)
|
.getRetransmissionById(retransId)
|
||||||
.getSingleOrNull();
|
.getSingleOrNull();
|
||||||
|
|
||||||
|
/// SET THE Message().receiptID !!!!!!!
|
||||||
|
/// ALSO THE encryptedContent is NOT YET ENCRYPTED!
|
||||||
|
|
||||||
if (retrans == null) {
|
if (retrans == null) {
|
||||||
Log.error('$retransId not found in database');
|
Log.error('$retransId not found in database');
|
||||||
return;
|
return;
|
||||||
|
|
@ -156,97 +161,74 @@ Future<void> sendRetransmitMessage(int retransId) async {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypts and stores the message and then sends it in the background
|
Future<void> sendCipherText(
|
||||||
Future<void> encryptAndSendMessageAsync(
|
int contactId,
|
||||||
int? messageId,
|
pb.EncryptedContent encryptedContent,
|
||||||
int userId,
|
|
||||||
MessageJson msg, {
|
|
||||||
PushNotification? pushNotification,
|
|
||||||
}) async {
|
|
||||||
Uint8List? pushData;
|
|
||||||
if (pushNotification != null) {
|
|
||||||
pushData = await getPushData(userId, pushNotification);
|
|
||||||
}
|
|
||||||
|
|
||||||
final retransId =
|
|
||||||
await twonlyDB.messageRetransmissionDao.insertRetransmission(
|
|
||||||
MessageRetransmissionsCompanion(
|
|
||||||
contactId: Value(userId),
|
|
||||||
messageId: Value(messageId),
|
|
||||||
plaintextContent: Value(Uint8List(0)),
|
|
||||||
pushData: Value(pushData),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (retransId == null) {
|
|
||||||
Log.error('Could not insert the message into the retransmission database');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.retransId = retransId;
|
|
||||||
|
|
||||||
final plaintextContent =
|
|
||||||
Uint8List.fromList(gzip.encode(utf8.encode(jsonEncode(msg.toJson()))));
|
|
||||||
|
|
||||||
await twonlyDB.messageRetransmissionDao.updateRetransmission(
|
|
||||||
retransId,
|
|
||||||
MessageRetransmissionsCompanion(
|
|
||||||
plaintextContent: Value(plaintextContent),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// this can now be done in the background...
|
|
||||||
unawaited(sendRetransmitMessage(retransId));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> sendTextMessage(
|
|
||||||
int target,
|
|
||||||
TextMessageContent content,
|
|
||||||
PushNotification? pushNotification,
|
|
||||||
) async {
|
) async {
|
||||||
final messageSendAt = DateTime.now();
|
final response = pb.Message()
|
||||||
DateTime? openedAt;
|
..type = pb.Message_Type.CIPHERTEXT
|
||||||
|
..encryptedContent = encryptedContent.writeToBuffer();
|
||||||
|
|
||||||
if (pushNotification != null && pushNotification.hasReactionContent()) {
|
final receipt = await twonlyDB.receiptsDao.insertReceipt(
|
||||||
openedAt = DateTime.now();
|
ReceiptsCompanion(
|
||||||
}
|
contactId: Value(contactId),
|
||||||
|
message: Value(response.writeToBuffer()),
|
||||||
final messageId = await twonlyDB.messagesDao.insertMessage(
|
|
||||||
MessagesCompanion(
|
|
||||||
contactId: Value(target),
|
|
||||||
kind: const Value(MessageKind.textMessage),
|
|
||||||
sendAt: Value(messageSendAt),
|
|
||||||
responseToOtherMessageId: Value(content.responseToMessageId),
|
|
||||||
responseToMessageId: Value(content.responseToOtherMessageId),
|
|
||||||
downloadState: const Value(DownloadState.downloaded),
|
|
||||||
openedAt: Value(openedAt),
|
|
||||||
contentJson: Value(
|
|
||||||
jsonEncode(content.toJson()),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (messageId == null) return;
|
if (receipt != null) {
|
||||||
|
await tryToSendCompleteMessage(receipt.receiptId);
|
||||||
if (pushNotification != null && !pushNotification.hasReactionContent()) {
|
|
||||||
pushNotification.messageId = Int64(messageId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final msg = MessageJson(
|
|
||||||
kind: MessageKind.textMessage,
|
|
||||||
messageSenderId: messageId,
|
|
||||||
content: content,
|
|
||||||
timestamp: messageSendAt,
|
|
||||||
);
|
|
||||||
|
|
||||||
await encryptAndSendMessageAsync(
|
|
||||||
messageId,
|
|
||||||
target,
|
|
||||||
msg,
|
|
||||||
pushNotification: pushNotification,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> sendTextMessage(
|
||||||
|
// int target,
|
||||||
|
// TextMessageContent content,
|
||||||
|
// PushNotification? pushNotification,
|
||||||
|
// ) async {
|
||||||
|
// final messageSendAt = DateTime.now();
|
||||||
|
// DateTime? openedAt;
|
||||||
|
|
||||||
|
// if (pushNotification != null && pushNotification.hasReactionContent()) {
|
||||||
|
// openedAt = DateTime.now();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// final messageId = await twonlyDB.messagesDao.insertMessage(
|
||||||
|
// MessagesCompanion(
|
||||||
|
// contactId: Value(target),
|
||||||
|
// kind: const Value(MessageKind.textMessage),
|
||||||
|
// sendAt: Value(messageSendAt),
|
||||||
|
// responseToOtherMessageId: Value(content.responseToMessageId),
|
||||||
|
// responseToMessageId: Value(content.responseToOtherMessageId),
|
||||||
|
// downloadState: const Value(DownloadState.downloaded),
|
||||||
|
// openedAt: Value(openedAt),
|
||||||
|
// contentJson: Value(
|
||||||
|
// jsonEncode(content.toJson()),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (messageId == null) return;
|
||||||
|
|
||||||
|
// if (pushNotification != null && !pushNotification.hasReactionContent()) {
|
||||||
|
// pushNotification.messageId = Int64(messageId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// final msg = MessageJson(
|
||||||
|
// kind: MessageKind.textMessage,
|
||||||
|
// messageSenderId: messageId,
|
||||||
|
// content: content,
|
||||||
|
// timestamp: messageSendAt,
|
||||||
|
// );
|
||||||
|
|
||||||
|
// await encryptAndSendMessageAsync(
|
||||||
|
// messageId,
|
||||||
|
// target,
|
||||||
|
// msg,
|
||||||
|
// pushNotification: pushNotification,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
Future<void> notifyContactAboutOpeningMessage(
|
Future<void> notifyContactAboutOpeningMessage(
|
||||||
int fromUserId,
|
int fromUserId,
|
||||||
List<int> messageOtherIds,
|
List<int> messageOtherIds,
|
||||||
|
|
@ -269,33 +251,25 @@ Future<void> notifyContactAboutOpeningMessage(
|
||||||
await updateLastMessageId(fromUserId, biggestMessageId);
|
await updateLastMessageId(fromUserId, biggestMessageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> notifyContactsAboutProfileChange() async {
|
Future<void> notifyContactsAboutProfileChange({int? onlyToContact}) async {
|
||||||
final contacts = await twonlyDB.contactsDao.getAllNotBlockedContacts();
|
|
||||||
|
|
||||||
final user = await getUser();
|
final user = await getUser();
|
||||||
if (user == null) return;
|
if (user == null) return;
|
||||||
if (user.avatarSvg == null) return;
|
if (user.avatarSvg == null) return;
|
||||||
|
|
||||||
|
final encryptedContent = pb.EncryptedContent()
|
||||||
|
..contactUpdate = (pb.EncryptedContent_ContactUpdate()
|
||||||
|
..type = pb.EncryptedContent_ContactUpdate_Type.UPDATE
|
||||||
|
..avatarSvg = user.avatarSvg!
|
||||||
|
..displayName = user.displayName);
|
||||||
|
|
||||||
|
if (onlyToContact != null) {
|
||||||
|
await sendCipherText(onlyToContact, encryptedContent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final contacts = await twonlyDB.contactsDao.getAllNotBlockedContacts();
|
||||||
|
|
||||||
for (final contact in contacts) {
|
for (final contact in contacts) {
|
||||||
if (contact.myAvatarCounter < user.avatarCounter) {
|
await sendCipherText(contact.userId, encryptedContent);
|
||||||
await twonlyDB.contactsDao.updateContact(
|
|
||||||
contact.userId,
|
|
||||||
ContactsCompanion(
|
|
||||||
myAvatarCounter: Value(user.avatarCounter),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await encryptAndSendMessageAsync(
|
|
||||||
null,
|
|
||||||
contact.userId,
|
|
||||||
MessageJson(
|
|
||||||
kind: MessageKind.profileChange,
|
|
||||||
content: ProfileContent(
|
|
||||||
avatarSvg: user.avatarSvg!,
|
|
||||||
displayName: user.displayName,
|
|
||||||
),
|
|
||||||
timestamp: DateTime.now(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,31 @@
|
||||||
// ignore_for_file: avoid_dynamic_calls
|
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:cryptography_plus/cryptography_plus.dart';
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/tables/media_uploads_table.dart';
|
import 'package:twonly/src/database/twonly.db.dart' hide Message;
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart'
|
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart'
|
||||||
as client;
|
as client;
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart'
|
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart'
|
||||||
as server;
|
as server;
|
||||||
import 'package:twonly/src/services/api/media_download.dart';
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/services/api/media_upload.dart';
|
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
import 'package:twonly/src/services/api/utils.dart';
|
import 'package:twonly/src/services/api/server_messages/contact.server_messages.dart';
|
||||||
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
import 'package:twonly/src/services/api/server_messages/media.server_messages.dart';
|
||||||
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
import 'package:twonly/src/services/api/server_messages/messages.server_messages.dart';
|
||||||
|
import 'package:twonly/src/services/api/server_messages/prekeys.server_messages.dart';
|
||||||
|
import 'package:twonly/src/services/api/server_messages/pushkeys.server_messages.dart';
|
||||||
|
import 'package:twonly/src/services/api/server_messages/reaction.server_message.dart';
|
||||||
|
import 'package:twonly/src/services/api/server_messages/text_message.server_messages.dart';
|
||||||
import 'package:twonly/src/services/signal/encryption.signal.dart';
|
import 'package:twonly/src/services/signal/encryption.signal.dart';
|
||||||
import 'package:twonly/src/services/signal/identity.signal.dart';
|
|
||||||
import 'package:twonly/src/services/thumbnail.service.dart';
|
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
|
||||||
import 'package:twonly/src/views/components/animate_icon.dart';
|
|
||||||
|
|
||||||
final lockHandleServerMessage = Mutex();
|
final lockHandleServerMessage = Mutex();
|
||||||
|
|
||||||
Future<void> handleServerMessage(server.ServerToClient msg) async {
|
Future<void> handleServerMessage(server.ServerToClient msg) async {
|
||||||
// return lockHandleServerMessage.protect(() async {
|
/// Returns means, that the server can delete the message from the server.
|
||||||
client.Response? response;
|
final ok = client.Response_Ok()..none = true;
|
||||||
|
var response = client.Response()..ok = ok;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (msg.v0.hasRequestNewPreKeys()) {
|
if (msg.v0.hasRequestNewPreKeys()) {
|
||||||
|
|
@ -44,13 +33,12 @@ Future<void> handleServerMessage(server.ServerToClient msg) async {
|
||||||
} else if (msg.v0.hasNewMessage()) {
|
} else if (msg.v0.hasNewMessage()) {
|
||||||
final body = Uint8List.fromList(msg.v0.newMessage.body);
|
final body = Uint8List.fromList(msg.v0.newMessage.body);
|
||||||
final fromUserId = msg.v0.newMessage.fromUserId.toInt();
|
final fromUserId = msg.v0.newMessage.fromUserId.toInt();
|
||||||
response = await handleNewMessage(fromUserId, body);
|
await handleNewMessage(fromUserId, body);
|
||||||
} else {
|
} else {
|
||||||
Log.error('Got a unknown message from the server: $msg');
|
Log.error('Unknown server message: $msg');
|
||||||
response = client.Response()..error = ErrorCode.InternalError;
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
response = client.Response()..error = ErrorCode.InternalError;
|
Log.error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
final v0 = client.V0()
|
final v0 = client.V0()
|
||||||
|
|
@ -58,435 +46,159 @@ Future<void> handleServerMessage(server.ServerToClient msg) async {
|
||||||
..response = response;
|
..response = response;
|
||||||
|
|
||||||
await apiService.sendResponse(ClientToServer()..v0 = v0);
|
await apiService.sendResponse(ClientToServer()..v0 = v0);
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime lastSignalDecryptMessage =
|
|
||||||
DateTime.now().subtract(const Duration(hours: 1));
|
|
||||||
DateTime lastPushKeyRequest = DateTime.now().subtract(const Duration(hours: 1));
|
DateTime lastPushKeyRequest = DateTime.now().subtract(const Duration(hours: 1));
|
||||||
|
|
||||||
bool messageGetsAck(MessageKind kind) {
|
Future<void> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||||
return kind != MessageKind.pushKey && kind != MessageKind.ack;
|
final message = Message.fromBuffer(body);
|
||||||
}
|
final receiptId = message.receiptId;
|
||||||
|
|
||||||
Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
switch (message.type) {
|
||||||
final message = await signalDecryptMessage(fromUserId, body);
|
case Message_Type.SENDER_DELIVERY_RECEIPT:
|
||||||
if (message == null) {
|
Log.info('Got delivery receipt for $receiptId!');
|
||||||
final encryptedHash = (await Sha256().hash(body)).bytes;
|
await twonlyDB.receiptsDao.confirmReceipt(receiptId, fromUserId);
|
||||||
await encryptAndSendMessageAsync(
|
|
||||||
null,
|
|
||||||
fromUserId,
|
|
||||||
MessageJson(
|
|
||||||
kind: MessageKind.signalDecryptError,
|
|
||||||
content: SignalDecryptErrorContent(encryptedHash: encryptedHash),
|
|
||||||
timestamp: DateTime.now(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
Log.error('Could not decrypt others message!');
|
case Message_Type.PLAINTEXT_CONTENT:
|
||||||
|
if (message.hasPlaintextContent() &&
|
||||||
// Message is not valid, so server can delete it
|
message.plaintextContent.hasDecryptionErrorMessage()) {
|
||||||
final ok = client.Response_Ok()..none = true;
|
Log.info(
|
||||||
return client.Response()..ok = ok;
|
'Got decryption error: ${message.plaintextContent.decryptionErrorMessage.type} for $receiptId',
|
||||||
}
|
|
||||||
|
|
||||||
client.Response? result;
|
|
||||||
|
|
||||||
Log.info('Got: ${message.kind} from $fromUserId');
|
|
||||||
|
|
||||||
switch (message.kind) {
|
|
||||||
case MessageKind.ack:
|
|
||||||
final content = message.content;
|
|
||||||
if (content is AckContent) {
|
|
||||||
if (content.messageIdToAck != null) {
|
|
||||||
const update = MessagesCompanion(
|
|
||||||
acknowledgeByUser: Value(true),
|
|
||||||
errorWhileSending: Value(false),
|
|
||||||
);
|
|
||||||
await twonlyDB.messagesDao.updateMessageByOtherUser(
|
|
||||||
fromUserId,
|
|
||||||
content.messageIdToAck!,
|
|
||||||
update,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await twonlyDB.messageRetransmissionDao
|
|
||||||
.deleteRetransmissionById(content.retransIdToAck);
|
|
||||||
}
|
|
||||||
case MessageKind.signalDecryptError:
|
|
||||||
Log.error(
|
|
||||||
'Got signal decrypt error from other user! Sending it again.',
|
|
||||||
);
|
|
||||||
|
|
||||||
final content = message.content;
|
|
||||||
if (content is SignalDecryptErrorContent) {
|
|
||||||
final hash = Uint8List.fromList(content.encryptedHash);
|
|
||||||
await twonlyDB.messageRetransmissionDao.resetAckStatusFor(
|
|
||||||
fromUserId,
|
|
||||||
hash,
|
|
||||||
);
|
);
|
||||||
final message = await twonlyDB.messageRetransmissionDao
|
await tryToSendCompleteMessage(receiptId);
|
||||||
.getRetransmissionFromHash(fromUserId, hash);
|
}
|
||||||
if (message != null) {
|
|
||||||
unawaited(sendRetransmitMessage(message.retransmissionId));
|
case Message_Type.CIPHERTEXT:
|
||||||
|
case Message_Type.PREKEY_BUNDLE:
|
||||||
|
if (message.hasEncryptedContent()) {
|
||||||
|
final encryptedContentRaw =
|
||||||
|
Uint8List.fromList(message.encryptedContent);
|
||||||
|
|
||||||
|
final responsePlaintextContent = await handleEncryptedMessage(
|
||||||
|
fromUserId,
|
||||||
|
encryptedContentRaw,
|
||||||
|
message.type,
|
||||||
|
);
|
||||||
|
Message response;
|
||||||
|
if (responsePlaintextContent != null) {
|
||||||
|
response = Message()
|
||||||
|
..receiptId = receiptId
|
||||||
|
..type = Message_Type.PLAINTEXT_CONTENT
|
||||||
|
..plaintextContent = responsePlaintextContent;
|
||||||
|
Log.error('Sending decryption error ($receiptId)');
|
||||||
} else {
|
} else {
|
||||||
Log.error('Could not find message to retransmit!');
|
response = Message()..type = Message_Type.SENDER_DELIVERY_RECEIPT;
|
||||||
}
|
}
|
||||||
}
|
await twonlyDB.receiptsDao.insertReceipt(
|
||||||
|
ReceiptsCompanion(
|
||||||
case MessageKind.contactRequest:
|
receiptId: Value(receiptId),
|
||||||
await handleContactRequest(fromUserId, message);
|
contactId: Value(fromUserId),
|
||||||
|
message: Value(response.writeToBuffer()),
|
||||||
case MessageKind.flameSync:
|
contactWillSendsReceipt: const Value(false),
|
||||||
final contact = await twonlyDB.contactsDao
|
),
|
||||||
.getContactByUserId(fromUserId)
|
|
||||||
.getSingleOrNull();
|
|
||||||
if (contact != null && contact.lastFlameCounterChange != null) {
|
|
||||||
final content = message.content;
|
|
||||||
if (content is FlameSyncContent) {
|
|
||||||
var updates = ContactsCompanion(
|
|
||||||
alsoBestFriend: Value(content.bestFriend),
|
|
||||||
);
|
|
||||||
if (isToday(contact.lastFlameCounterChange!) &&
|
|
||||||
isToday(content.lastFlameCounterChange)) {
|
|
||||||
if (content.flameCounter > contact.flameCounter) {
|
|
||||||
updates = ContactsCompanion(
|
|
||||||
flameCounter: Value(content.flameCounter),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await twonlyDB.contactsDao.updateContact(fromUserId, updates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case MessageKind.receiveMediaError:
|
|
||||||
if (message.messageReceiverId != null) {
|
|
||||||
final openedMessage = await twonlyDB.messagesDao
|
|
||||||
.getMessageByIdAndContactId(fromUserId, message.messageReceiverId!)
|
|
||||||
.getSingleOrNull();
|
|
||||||
|
|
||||||
if (openedMessage != null) {
|
|
||||||
/// message found
|
|
||||||
|
|
||||||
/// checks if
|
|
||||||
/// 1. this was a media upload
|
|
||||||
/// 2. the media was not already retransmitted
|
|
||||||
/// 3. the media was send in the last two days
|
|
||||||
if (openedMessage.mediaUploadId != null &&
|
|
||||||
openedMessage.mediaRetransmissionState ==
|
|
||||||
MediaRetransmitting.none &&
|
|
||||||
openedMessage.sendAt
|
|
||||||
.isAfter(DateTime.now().subtract(const Duration(days: 2)))) {
|
|
||||||
// reset the media upload state to pending,
|
|
||||||
// this will cause the media to be re-encrypted again
|
|
||||||
await twonlyDB.mediaUploadsDao.updateMediaUpload(
|
|
||||||
openedMessage.mediaUploadId!,
|
|
||||||
const MediaUploadsCompanion(
|
|
||||||
state: Value(
|
|
||||||
UploadState.pending,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
// reset the message upload so the upload will be done again
|
|
||||||
await twonlyDB.messagesDao.updateMessageByOtherUser(
|
|
||||||
fromUserId,
|
|
||||||
message.messageReceiverId!,
|
|
||||||
const MessagesCompanion(
|
|
||||||
downloadState: Value(DownloadState.pending),
|
|
||||||
mediaRetransmissionState:
|
|
||||||
Value(MediaRetransmitting.retransmitted),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
unawaited(retryMediaUpload(false));
|
|
||||||
} else {
|
|
||||||
await twonlyDB.messagesDao.updateMessageByOtherUser(
|
|
||||||
fromUserId,
|
|
||||||
message.messageReceiverId!,
|
|
||||||
const MessagesCompanion(
|
|
||||||
errorWhileSending: Value(true),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case MessageKind.opened:
|
|
||||||
if (message.messageReceiverId != null) {
|
|
||||||
final update = MessagesCompanion(
|
|
||||||
openedAt: Value(message.timestamp),
|
|
||||||
errorWhileSending: const Value(false),
|
|
||||||
);
|
);
|
||||||
await twonlyDB.messagesDao.updateMessageByOtherUser(
|
await tryToSendCompleteMessage(receiptId);
|
||||||
fromUserId,
|
|
||||||
message.messageReceiverId!,
|
|
||||||
update,
|
|
||||||
);
|
|
||||||
final openedMessage = await twonlyDB.messagesDao
|
|
||||||
.getMessageByMessageId(message.messageReceiverId!)
|
|
||||||
.getSingleOrNull();
|
|
||||||
if (openedMessage != null &&
|
|
||||||
openedMessage.kind == MessageKind.textMessage) {
|
|
||||||
await twonlyDB.messagesDao.openedAllNonMediaMessagesFromOtherUser(
|
|
||||||
fromUserId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case MessageKind.rejectRequest:
|
|
||||||
await deleteContact(fromUserId);
|
|
||||||
|
|
||||||
case MessageKind.acceptRequest:
|
|
||||||
const update = ContactsCompanion(accepted: Value(true));
|
|
||||||
await twonlyDB.contactsDao.updateContact(fromUserId, update);
|
|
||||||
unawaited(notifyContactsAboutProfileChange());
|
|
||||||
|
|
||||||
case MessageKind.profileChange:
|
|
||||||
final content = message.content;
|
|
||||||
if (content is ProfileContent) {
|
|
||||||
final update = ContactsCompanion(
|
|
||||||
avatarSvg: Value(content.avatarSvg),
|
|
||||||
displayName: Value(content.displayName),
|
|
||||||
);
|
|
||||||
await twonlyDB.contactsDao.updateContact(fromUserId, update);
|
|
||||||
}
|
|
||||||
unawaited(createPushAvatars());
|
|
||||||
|
|
||||||
case MessageKind.requestPushKey:
|
|
||||||
if (lastPushKeyRequest
|
|
||||||
.isBefore(DateTime.now().subtract(const Duration(seconds: 60)))) {
|
|
||||||
lastPushKeyRequest = DateTime.now();
|
|
||||||
unawaited(setupNotificationWithUsers(forceContact: fromUserId));
|
|
||||||
}
|
|
||||||
|
|
||||||
case MessageKind.pushKey:
|
|
||||||
if (message.content != null) {
|
|
||||||
final pushKey = message.content!;
|
|
||||||
if (pushKey is PushKeyContent) {
|
|
||||||
await handleNewPushKey(fromUserId, pushKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore: no_default_cases
|
|
||||||
default:
|
|
||||||
if (message.messageSenderId == null) {
|
|
||||||
Log.error('Messageid not defined $message');
|
|
||||||
} else if ([
|
|
||||||
MessageKind.textMessage,
|
|
||||||
MessageKind.media,
|
|
||||||
MessageKind.storedMediaFile,
|
|
||||||
MessageKind.reopenedMedia,
|
|
||||||
].contains(message.kind)) {
|
|
||||||
result = await handleMediaOrTextMessage(fromUserId, message);
|
|
||||||
} else {
|
|
||||||
Log.error('Got unknown MessageKind $message');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageGetsAck(message.kind) && message.retransId != null) {
|
|
||||||
Log.info('Sending ACK for ${message.kind}');
|
|
||||||
|
|
||||||
/// ACK every message
|
|
||||||
await encryptAndSendMessageAsync(
|
|
||||||
null,
|
|
||||||
fromUserId,
|
|
||||||
MessageJson(
|
|
||||||
kind: MessageKind.ack,
|
|
||||||
content: AckContent(
|
|
||||||
messageIdToAck: message.messageSenderId,
|
|
||||||
retransIdToAck: message.retransId!,
|
|
||||||
),
|
|
||||||
timestamp: DateTime.now(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
final ok = client.Response_Ok()..none = true;
|
|
||||||
return client.Response()..ok = ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<client.Response?> handleMediaOrTextMessage(
|
Future<PlaintextContent?> handleEncryptedMessage(
|
||||||
int fromUserId,
|
int fromUserId,
|
||||||
MessageJson message,
|
Uint8List encryptedContentRaw,
|
||||||
|
Message_Type messageType,
|
||||||
) async {
|
) async {
|
||||||
if (message.kind == MessageKind.storedMediaFile) {
|
final (content, decryptionErrorType) = await signalDecryptMessage(
|
||||||
if (message.messageReceiverId != null) {
|
fromUserId,
|
||||||
/// stored media file just updates the message
|
encryptedContentRaw,
|
||||||
await twonlyDB.messagesDao.updateMessageByOtherUser(
|
messageType as int,
|
||||||
fromUserId,
|
);
|
||||||
message.messageReceiverId!,
|
|
||||||
const MessagesCompanion(
|
|
||||||
mediaStored: Value(true),
|
|
||||||
errorWhileSending: Value(false),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final msg = await twonlyDB.messagesDao
|
|
||||||
.getMessageByIdAndContactId(
|
|
||||||
fromUserId,
|
|
||||||
message.messageReceiverId!,
|
|
||||||
)
|
|
||||||
.getSingleOrNull();
|
|
||||||
if (msg != null && msg.mediaUploadId != null) {
|
|
||||||
final filePath = await getMediaFilePath(msg.mediaUploadId, 'send');
|
|
||||||
if (filePath.contains('mp4')) {
|
|
||||||
unawaited(createThumbnailsForVideo(File(filePath)));
|
|
||||||
} else {
|
|
||||||
unawaited(createThumbnailsForImage(File(filePath)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (message.content != null) {
|
|
||||||
final content = message.content!;
|
|
||||||
// when a message is received doubled ignore it...
|
|
||||||
|
|
||||||
final openedMessage = await twonlyDB.messagesDao
|
if (content == null) {
|
||||||
.getMessageByOtherMessageId(fromUserId, message.messageSenderId!)
|
return PlaintextContent()
|
||||||
.getSingleOrNull();
|
..decryptionErrorMessage = (PlaintextContent_DecryptionErrorMessage()
|
||||||
|
..type = decryptionErrorType!);
|
||||||
if (openedMessage != null) {
|
}
|
||||||
if (openedMessage.errorWhileSending) {
|
|
||||||
await twonlyDB.messagesDao
|
final senderProfileCounter = await checkForProfileUpdate(fromUserId, content);
|
||||||
.deleteMessagesByMessageId(openedMessage.messageId);
|
|
||||||
} else {
|
if (content.hasContactRequest()) {
|
||||||
Log.error(
|
await handleContactRequest(fromUserId, content.contactRequest);
|
||||||
'Got a duplicated message from other user: ${message.messageSenderId!}',
|
return null;
|
||||||
);
|
}
|
||||||
final ok = client.Response_Ok()..none = true;
|
|
||||||
return client.Response()..ok = ok;
|
if (content.hasContactUpdate()) {
|
||||||
}
|
await handleContactUpdate(
|
||||||
}
|
fromUserId,
|
||||||
|
content.contactUpdate,
|
||||||
int? responseToMessageId;
|
senderProfileCounter,
|
||||||
int? responseToOtherMessageId;
|
);
|
||||||
int? messageId;
|
return null;
|
||||||
|
}
|
||||||
var acknowledgeByUser = false;
|
|
||||||
DateTime? openedAt;
|
if (content.hasFlameSync()) {
|
||||||
|
await handleFlameSync(fromUserId, content.flameSync);
|
||||||
if (message.kind == MessageKind.reopenedMedia) {
|
return null;
|
||||||
acknowledgeByUser = true;
|
}
|
||||||
openedAt = DateTime.now();
|
|
||||||
}
|
if (content.hasPushKeys()) {
|
||||||
|
await handlePushKey(fromUserId, content.pushKeys);
|
||||||
if (content is TextMessageContent) {
|
return null;
|
||||||
responseToMessageId = content.responseToMessageId;
|
}
|
||||||
responseToOtherMessageId = content.responseToOtherMessageId;
|
|
||||||
|
if (!content.hasGroupId()) {
|
||||||
if (responseToMessageId != null || responseToOtherMessageId != null) {
|
return null;
|
||||||
// reactions are shown in the notification directly...
|
}
|
||||||
if (isEmoji(content.text)) {
|
|
||||||
openedAt = DateTime.now();
|
/// Verify that the user is (still) in that group...
|
||||||
}
|
if (!await twonlyDB.groupsDao.isContactInGroup(fromUserId, content.groupId)) {
|
||||||
}
|
Log.error('User $fromUserId tried to access group ${content.groupId}.');
|
||||||
}
|
return null;
|
||||||
if (content is ReopenedMediaFileContent) {
|
}
|
||||||
responseToMessageId = content.messageId;
|
|
||||||
}
|
if (content.hasMessageUpdate()) {
|
||||||
|
await handleMessageUpdate(
|
||||||
if (responseToMessageId != null) {
|
fromUserId,
|
||||||
await twonlyDB.messagesDao.updateMessageByOtherUser(
|
content.groupId,
|
||||||
fromUserId,
|
content.messageUpdate,
|
||||||
responseToMessageId,
|
);
|
||||||
MessagesCompanion(
|
return null;
|
||||||
errorWhileSending: const Value(false),
|
}
|
||||||
openedAt: Value(
|
|
||||||
DateTime.now(),
|
if (content.hasTextMessage()) {
|
||||||
), // when a user reacted to the media file, it should be marked as opened
|
await handleTextMessage(
|
||||||
),
|
fromUserId,
|
||||||
);
|
content.groupId,
|
||||||
}
|
content.textMessage,
|
||||||
|
);
|
||||||
final contentJson = jsonEncode(content.toJson());
|
return null;
|
||||||
final update = MessagesCompanion(
|
}
|
||||||
contactId: Value(fromUserId),
|
|
||||||
kind: Value(message.kind),
|
if (content.hasReaction()) {
|
||||||
messageOtherId: Value(message.messageSenderId),
|
await handleReaction(
|
||||||
contentJson: Value(contentJson),
|
fromUserId,
|
||||||
acknowledgeByServer: const Value(true),
|
content.groupId,
|
||||||
acknowledgeByUser: Value(acknowledgeByUser),
|
content.reaction,
|
||||||
responseToMessageId: Value(responseToMessageId),
|
);
|
||||||
responseToOtherMessageId: Value(responseToOtherMessageId),
|
return null;
|
||||||
openedAt: Value(openedAt),
|
}
|
||||||
downloadState: Value(
|
|
||||||
message.kind == MessageKind.media
|
if (content.hasMedia()) {
|
||||||
? DownloadState.pending
|
await handleMedia(
|
||||||
: DownloadState.downloaded,
|
fromUserId,
|
||||||
),
|
content.groupId,
|
||||||
sendAt: Value(message.timestamp),
|
content.media,
|
||||||
);
|
);
|
||||||
|
return null;
|
||||||
messageId = await twonlyDB.messagesDao.insertMessage(
|
}
|
||||||
update,
|
|
||||||
);
|
if (content.hasMediaUpdate()) {
|
||||||
|
await handleMediaUpdate(
|
||||||
if (messageId == null) {
|
fromUserId,
|
||||||
Log.error('could not insert message into db');
|
content.groupId,
|
||||||
return client.Response()..error = ErrorCode.InternalError;
|
content.mediaUpdate,
|
||||||
}
|
);
|
||||||
|
return null;
|
||||||
Log.info('Inserted a new message with id: $messageId');
|
|
||||||
|
|
||||||
if (message.kind == MessageKind.media) {
|
|
||||||
await twonlyDB.contactsDao.incFlameCounter(
|
|
||||||
fromUserId,
|
|
||||||
true,
|
|
||||||
message.timestamp,
|
|
||||||
);
|
|
||||||
|
|
||||||
final msg = await twonlyDB.messagesDao
|
|
||||||
.getMessageByMessageId(messageId)
|
|
||||||
.getSingleOrNull();
|
|
||||||
if (msg != null) {
|
|
||||||
unawaited(startDownloadMedia(msg, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.error('Content is not defined $message');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unarchive contact when receiving a new message
|
|
||||||
await twonlyDB.contactsDao.updateContact(
|
|
||||||
fromUserId,
|
|
||||||
const ContactsCompanion(
|
|
||||||
archived: Value(false),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<client.Response> handleRequestNewPreKey() async {
|
|
||||||
final localPreKeys = await signalGetPreKeys();
|
|
||||||
|
|
||||||
final prekeysList = <client.Response_PreKey>[];
|
|
||||||
for (var i = 0; i < localPreKeys.length; i++) {
|
|
||||||
prekeysList.add(
|
|
||||||
client.Response_PreKey()
|
|
||||||
..id = Int64(localPreKeys[i].id)
|
|
||||||
..prekey = localPreKeys[i].getKeyPair().publicKey.serialize(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final prekeys = client.Response_Prekeys(prekeys: prekeysList);
|
|
||||||
final ok = client.Response_Ok()..prekeys = prekeys;
|
|
||||||
return client.Response()..ok = ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> handleContactRequest(
|
|
||||||
int fromUserId,
|
|
||||||
MessageJson message,
|
|
||||||
) async {
|
|
||||||
// request the username by the server so an attacker can not
|
|
||||||
// forge the displayed username in the contact request
|
|
||||||
final username = await apiService.getUsername(fromUserId);
|
|
||||||
if (username.isSuccess) {
|
|
||||||
final name = username.value.userdata.username as Uint8List;
|
|
||||||
await twonlyDB.contactsDao.insertContact(
|
|
||||||
ContactsCompanion(
|
|
||||||
username: Value(utf8.decode(name)),
|
|
||||||
userId: Value(fromUserId),
|
|
||||||
requested: const Value(true),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await setupNotificationWithUsers();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart' hide Message;
|
||||||
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
|
import 'package:twonly/src/services/api/utils.dart';
|
||||||
|
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||||
|
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
|
Future<void> handleContactRequest(
|
||||||
|
int fromUserId,
|
||||||
|
EncryptedContent_ContactRequest contactRequest,
|
||||||
|
) async {
|
||||||
|
switch (contactRequest.type) {
|
||||||
|
case EncryptedContent_ContactRequest_Type.REQUEST:
|
||||||
|
// Request the username by the server so an attacker can not
|
||||||
|
// forge the displayed username in the contact request
|
||||||
|
final username = await apiService.getUsername(fromUserId);
|
||||||
|
if (username.isSuccess) {
|
||||||
|
// ignore: avoid_dynamic_calls
|
||||||
|
final name = username.value.userdata.username as Uint8List;
|
||||||
|
await twonlyDB.contactsDao.insertContact(
|
||||||
|
ContactsCompanion(
|
||||||
|
username: Value(utf8.decode(name)),
|
||||||
|
userId: Value(fromUserId),
|
||||||
|
requested: const Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await setupNotificationWithUsers();
|
||||||
|
case EncryptedContent_ContactRequest_Type.ACCEPT:
|
||||||
|
await twonlyDB.contactsDao.updateContact(
|
||||||
|
fromUserId,
|
||||||
|
const ContactsCompanion(
|
||||||
|
requested: Value(false),
|
||||||
|
accepted: Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case EncryptedContent_ContactRequest_Type.REJECT:
|
||||||
|
await twonlyDB.contactsDao.deleteContactByUserId(fromUserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleContactUpdate(
|
||||||
|
int fromUserId,
|
||||||
|
EncryptedContent_ContactUpdate contactUpdate,
|
||||||
|
int? senderProfileCounter) async {
|
||||||
|
switch (contactUpdate.type) {
|
||||||
|
case EncryptedContent_ContactUpdate_Type.REQUEST:
|
||||||
|
await notifyContactsAboutProfileChange(onlyToContact: fromUserId);
|
||||||
|
|
||||||
|
case EncryptedContent_ContactUpdate_Type.UPDATE:
|
||||||
|
if (contactUpdate.hasAvatarSvg() &&
|
||||||
|
contactUpdate.hasDisplayName() &&
|
||||||
|
senderProfileCounter != null) {
|
||||||
|
await twonlyDB.contactsDao.updateContact(
|
||||||
|
fromUserId,
|
||||||
|
ContactsCompanion(
|
||||||
|
avatarSvg: Value(contactUpdate.avatarSvg),
|
||||||
|
displayName: Value(contactUpdate.displayName),
|
||||||
|
senderProfileCounter: Value(senderProfileCounter),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
unawaited(createPushAvatars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleFlameSync(
|
||||||
|
int contactId,
|
||||||
|
EncryptedContent_FlameSync flameSync,
|
||||||
|
) async {
|
||||||
|
final contact = await twonlyDB.contactsDao
|
||||||
|
.getContactByUserId(contactId)
|
||||||
|
.getSingleOrNull();
|
||||||
|
|
||||||
|
if (contact == null || contact.lastFlameCounterChange != null) return;
|
||||||
|
|
||||||
|
var updates = ContactsCompanion(
|
||||||
|
alsoBestFriend: Value(flameSync.bestFriend),
|
||||||
|
);
|
||||||
|
if (isToday(contact.lastFlameCounterChange!) &&
|
||||||
|
isToday(fromTimestamp(flameSync.lastFlameCounterChange))) {
|
||||||
|
if (flameSync.flameCounter > contact.flameCounter) {
|
||||||
|
updates = ContactsCompanion(
|
||||||
|
flameCounter: Value(flameSync.flameCounter.toInt()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await twonlyDB.contactsDao.updateContact(contactId, updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int?> checkForProfileUpdate(
|
||||||
|
int fromUserId,
|
||||||
|
EncryptedContent content,
|
||||||
|
) async {
|
||||||
|
int? senderProfileCounter;
|
||||||
|
|
||||||
|
if (content.hasSenderProfileCounter() && !content.hasContactUpdate()) {
|
||||||
|
senderProfileCounter = content.senderProfileCounter.toInt();
|
||||||
|
final contact = await twonlyDB.contactsDao
|
||||||
|
.getContactByUserId(fromUserId)
|
||||||
|
.getSingleOrNull();
|
||||||
|
if (contact != null) {
|
||||||
|
if (contact.senderProfileCounter < senderProfileCounter) {
|
||||||
|
await sendCipherText(
|
||||||
|
fromUserId,
|
||||||
|
EncryptedContent()
|
||||||
|
..contactUpdate = (EncryptedContent_ContactUpdate()
|
||||||
|
..type = EncryptedContent_ContactUpdate_Type.REQUEST),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return senderProfileCounter;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
|
||||||
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
|
|
||||||
|
Future<void> handleMedia(int fromUserId, String groupId, EncryptedContent_Media media) async {
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleMediaUpdate(int fromUserId, String groupId, EncryptedContent_MediaUpdate mediaUpdate) async {
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
// switch (message.kind) {
|
||||||
|
// case MessageKind.receiveMediaError:
|
||||||
|
// if (message.messageReceiverId != null) {
|
||||||
|
// final openedMessage = await twonlyDB.messagesDao
|
||||||
|
// .getMessageByIdAndContactId(fromUserId, message.messageReceiverId!)
|
||||||
|
// .getSingleOrNull();
|
||||||
|
|
||||||
|
// if (openedMessage != null) {
|
||||||
|
// /// message found
|
||||||
|
|
||||||
|
// /// checks if
|
||||||
|
// /// 1. this was a media upload
|
||||||
|
// /// 2. the media was not already retransmitted
|
||||||
|
// /// 3. the media was send in the last two days
|
||||||
|
// if (openedMessage.mediaUploadId != null &&
|
||||||
|
// openedMessage.mediaRetransmissionState ==
|
||||||
|
// MediaRetransmitting.none &&
|
||||||
|
// openedMessage.sendAt
|
||||||
|
// .isAfter(DateTime.now().subtract(const Duration(days: 2)))) {
|
||||||
|
// // reset the media upload state to pending,
|
||||||
|
// // this will cause the media to be re-encrypted again
|
||||||
|
// await twonlyDB.mediaUploadsDao.updateMediaUpload(
|
||||||
|
// openedMessage.mediaUploadId!,
|
||||||
|
// const MediaUploadsCompanion(
|
||||||
|
// state: Value(
|
||||||
|
// UploadState.pending,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// // reset the message upload so the upload will be done again
|
||||||
|
// await twonlyDB.messagesDao.updateMessageByOtherUser(
|
||||||
|
// fromUserId,
|
||||||
|
// message.messageReceiverId!,
|
||||||
|
// const MessagesCompanion(
|
||||||
|
// downloadState: Value(DownloadState.pending),
|
||||||
|
// mediaRetransmissionState:
|
||||||
|
// Value(MediaRetransmitting.retransmitted),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// unawaited(retryMediaUpload(false));
|
||||||
|
// } else {
|
||||||
|
// await twonlyDB.messagesDao.updateMessageByOtherUser(
|
||||||
|
// fromUserId,
|
||||||
|
// message.messageReceiverId!,
|
||||||
|
// const MessagesCompanion(
|
||||||
|
// errorWhileSending: Value(true),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
if (message.kind == MessageKind.storedMediaFile) {
|
||||||
|
if (message.messageReceiverId != null) {
|
||||||
|
/// stored media file just updates the message
|
||||||
|
await twonlyDB.messagesDao.updateMessageByOtherUser(
|
||||||
|
fromUserId,
|
||||||
|
message.messageReceiverId!,
|
||||||
|
const MessagesCompanion(
|
||||||
|
mediaStored: Value(true),
|
||||||
|
errorWhileSending: Value(false),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final msg = await twonlyDB.messagesDao
|
||||||
|
.getMessageByIdAndContactId(
|
||||||
|
fromUserId,
|
||||||
|
message.messageReceiverId!,
|
||||||
|
)
|
||||||
|
.getSingleOrNull();
|
||||||
|
if (msg != null && msg.mediaUploadId != null) {
|
||||||
|
final filePath = await getMediaFilePath(msg.mediaUploadId, 'send');
|
||||||
|
if (filePath.contains('mp4')) {
|
||||||
|
unawaited(createThumbnailsForVideo(File(filePath)));
|
||||||
|
} else {
|
||||||
|
unawaited(createThumbnailsForImage(File(filePath)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (message.content != null) {}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
|
import 'package:twonly/src/services/api/utils.dart';
|
||||||
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
|
Future<void> handleMessageUpdate(
|
||||||
|
int contactId,
|
||||||
|
String groupId,
|
||||||
|
EncryptedContent_MessageUpdate messageUpdate,
|
||||||
|
) async {
|
||||||
|
switch (messageUpdate.type) {
|
||||||
|
case EncryptedContent_MessageUpdate_Type.OPENED:
|
||||||
|
Log.info('Opened message ${messageUpdate.senderMessageId}');
|
||||||
|
await twonlyDB.messagesDao.handleMessageOpened(
|
||||||
|
groupId,
|
||||||
|
messageUpdate.senderMessageId,
|
||||||
|
fromTimestamp(messageUpdate.timestamp),
|
||||||
|
);
|
||||||
|
case EncryptedContent_MessageUpdate_Type.DELETE:
|
||||||
|
Log.info('Delete message ${messageUpdate.senderMessageId}');
|
||||||
|
await twonlyDB.messagesDao.handleMessageDeletion(
|
||||||
|
contactId,
|
||||||
|
messageUpdate.senderMessageId,
|
||||||
|
fromTimestamp(messageUpdate.timestamp),
|
||||||
|
);
|
||||||
|
case EncryptedContent_MessageUpdate_Type.EDIT_TEXT:
|
||||||
|
Log.info('Edit message ${messageUpdate.senderMessageId}');
|
||||||
|
await twonlyDB.messagesDao.handleTextEdit(
|
||||||
|
contactId,
|
||||||
|
messageUpdate.senderMessageId,
|
||||||
|
messageUpdate.text,
|
||||||
|
fromTimestamp(messageUpdate.timestamp),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart'
|
||||||
|
as client;
|
||||||
|
import 'package:twonly/src/services/signal/identity.signal.dart';
|
||||||
|
|
||||||
|
Future<client.Response> handleRequestNewPreKey() async {
|
||||||
|
final localPreKeys = await signalGetPreKeys();
|
||||||
|
|
||||||
|
final prekeysList = <client.Response_PreKey>[];
|
||||||
|
for (var i = 0; i < localPreKeys.length; i++) {
|
||||||
|
prekeysList.add(
|
||||||
|
client.Response_PreKey()
|
||||||
|
..id = Int64(localPreKeys[i].id)
|
||||||
|
..prekey = localPreKeys[i].getKeyPair().publicKey.serialize(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final prekeys = client.Response_Prekeys(prekeys: prekeysList);
|
||||||
|
final ok = client.Response_Ok()..prekeys = prekeys;
|
||||||
|
return client.Response()..ok = ok;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
|
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||||
|
|
||||||
|
DateTime lastPushKeyRequest = DateTime.now().subtract(const Duration(hours: 1));
|
||||||
|
|
||||||
|
Future<void> handlePushKey(
|
||||||
|
int contactId,
|
||||||
|
EncryptedContent_PushKeys pushKeys,
|
||||||
|
) async {
|
||||||
|
switch (pushKeys.type) {
|
||||||
|
case EncryptedContent_PushKeys_Type.REQUEST:
|
||||||
|
if (lastPushKeyRequest
|
||||||
|
.isBefore(DateTime.now().subtract(const Duration(seconds: 60)))) {
|
||||||
|
lastPushKeyRequest = DateTime.now();
|
||||||
|
unawaited(setupNotificationWithUsers(forceContact: contactId));
|
||||||
|
}
|
||||||
|
|
||||||
|
case EncryptedContent_PushKeys_Type.UPDATE:
|
||||||
|
await handleNewPushKey(contactId, pushKeys.keyId.toInt(), pushKeys.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
|
|
||||||
|
Future<void> handleReaction(
|
||||||
|
int fromUserId,
|
||||||
|
String groupId,
|
||||||
|
EncryptedContent_Reaction reaction,
|
||||||
|
) async {
|
||||||
|
if (reaction.hasRemove()) {
|
||||||
|
if (reaction.remove) {
|
||||||
|
await twonlyDB.reactionsDao
|
||||||
|
.updateReaction(fromUserId, reaction.targetMessageId, groupId, null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (reaction.hasEmoji()) {
|
||||||
|
await twonlyDB.reactionsDao.updateReaction(
|
||||||
|
fromUserId,
|
||||||
|
reaction.targetMessageId,
|
||||||
|
groupId,
|
||||||
|
reaction.emoji,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
|
|
||||||
|
Future<void> handleTextMessage(
|
||||||
|
int fromUserId,
|
||||||
|
String groupId,
|
||||||
|
EncryptedContent_TextMessage textMessage,
|
||||||
|
) async {
|
||||||
|
TODO
|
||||||
|
// final content = message.content!;
|
||||||
|
// // when a message is received doubled ignore it...
|
||||||
|
|
||||||
|
// final openedMessage = await twonlyDB.messagesDao
|
||||||
|
// .getMessageByOtherMessageId(fromUserId, message.messageSenderId!)
|
||||||
|
// .getSingleOrNull();
|
||||||
|
|
||||||
|
// if (openedMessage != null) {
|
||||||
|
// if (openedMessage.errorWhileSending) {
|
||||||
|
// await twonlyDB.messagesDao
|
||||||
|
// .deleteMessagesByMessageId(openedMessage.messageId);
|
||||||
|
// } else {
|
||||||
|
// Log.error(
|
||||||
|
// 'Got a duplicated message from other user: ${message.messageSenderId!}',
|
||||||
|
// );
|
||||||
|
// final ok = client.Response_Ok()..none = true;
|
||||||
|
// return client.Response()..ok = ok;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int? responseToMessageId;
|
||||||
|
// int? responseToOtherMessageId;
|
||||||
|
// int? messageId;
|
||||||
|
|
||||||
|
// var acknowledgeByUser = false;
|
||||||
|
// DateTime? openedAt;
|
||||||
|
|
||||||
|
// if (message.kind == MessageKind.reopenedMedia) {
|
||||||
|
// acknowledgeByUser = true;
|
||||||
|
// openedAt = DateTime.now();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (content is TextMessageContent) {
|
||||||
|
// responseToMessageId = content.responseToMessageId;
|
||||||
|
// responseToOtherMessageId = content.responseToOtherMessageId;
|
||||||
|
|
||||||
|
// if (responseToMessageId != null || responseToOtherMessageId != null) {
|
||||||
|
// // reactions are shown in the notification directly...
|
||||||
|
// if (isEmoji(content.text)) {
|
||||||
|
// openedAt = DateTime.now();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (content is ReopenedMediaFileContent) {
|
||||||
|
// responseToMessageId = content.messageId;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (responseToMessageId != null) {
|
||||||
|
// await twonlyDB.messagesDao.updateMessageByOtherUser(
|
||||||
|
// fromUserId,
|
||||||
|
// responseToMessageId,
|
||||||
|
// MessagesCompanion(
|
||||||
|
// errorWhileSending: const Value(false),
|
||||||
|
// openedAt: Value(
|
||||||
|
// DateTime.now(),
|
||||||
|
// ), // when a user reacted to the media file, it should be marked as opened
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// final contentJson = jsonEncode(content.toJson());
|
||||||
|
// final update = MessagesCompanion(
|
||||||
|
// contactId: Value(fromUserId),
|
||||||
|
// kind: Value(message.kind),
|
||||||
|
// messageOtherId: Value(message.messageSenderId),
|
||||||
|
// contentJson: Value(contentJson),
|
||||||
|
// acknowledgeByServer: const Value(true),
|
||||||
|
// acknowledgeByUser: Value(acknowledgeByUser),
|
||||||
|
// responseToMessageId: Value(responseToMessageId),
|
||||||
|
// responseToOtherMessageId: Value(responseToOtherMessageId),
|
||||||
|
// openedAt: Value(openedAt),
|
||||||
|
// downloadState: Value(
|
||||||
|
// message.kind == MessageKind.media
|
||||||
|
// ? DownloadState.pending
|
||||||
|
// : DownloadState.downloaded,
|
||||||
|
// ),
|
||||||
|
// sendAt: Value(message.timestamp),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// messageId = await twonlyDB.messagesDao.insertMessage(
|
||||||
|
// update,
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (messageId == null) {
|
||||||
|
// Log.error('could not insert message into db');
|
||||||
|
// return client.Response()..error = ErrorCode.InternalError;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Log.info('Inserted a new message with id: $messageId');
|
||||||
|
|
||||||
|
// if (message.kind == MessageKind.media) {
|
||||||
|
// await twonlyDB.contactsDao.incFlameCounter(
|
||||||
|
// fromUserId,
|
||||||
|
// true,
|
||||||
|
// message.timestamp,
|
||||||
|
// );
|
||||||
|
|
||||||
|
// final msg = await twonlyDB.messagesDao
|
||||||
|
// .getMessageByMessageId(messageId)
|
||||||
|
// .getSingleOrNull();
|
||||||
|
// if (msg != null) {
|
||||||
|
// unawaited(startDownloadMedia(msg, false));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// Log.error('Content is not defined $message');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // unarchive contact when receiving a new message
|
||||||
|
// await twonlyDB.contactsDao.updateContact(
|
||||||
|
// fromUserId,
|
||||||
|
// const ContactsCompanion(
|
||||||
|
// archived: Value(false),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// return null;
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,8 @@ import 'package:drift/drift.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message_old.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart'
|
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart'
|
||||||
as client;
|
as client;
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pbserver.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pbserver.dart';
|
||||||
|
|
@ -24,6 +24,10 @@ class Result<T, E> {
|
||||||
bool get isError => error != null;
|
bool get isError => error != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DateTime fromTimestamp(Int64 timeStamp) {
|
||||||
|
return DateTime.fromMillisecondsSinceEpoch(timeStamp.toInt() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
// ignore: strict_raw_type
|
// ignore: strict_raw_type
|
||||||
Result asResult(server.ServerToClient? msg) {
|
Result asResult(server.ServerToClient? msg) {
|
||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart' as my;
|
import 'package:twonly/src/model/json/message_old.dart' as my;
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
|
||||||
5
lib/src/services/mediafile.service.dart
Normal file
5
lib/src/services/mediafile.service.dart
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
|
Future<void> removeMediaFile(String mediaId) async {
|
||||||
|
Log.error('TODO removeMediaFile: $mediaId');
|
||||||
|
}
|
||||||
|
|
@ -9,10 +9,10 @@ import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart' as my;
|
import 'package:twonly/src/model/json/message_old.dart' as my;
|
||||||
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pb.dart';
|
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pb.dart';
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
@ -144,7 +144,7 @@ Future<void> updatePushUser(Contact contact) async {
|
||||||
await setPushKeys(SecureStorageKeys.receivingPushKeys, pushKeys);
|
await setPushKeys(SecureStorageKeys.receivingPushKeys, pushKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleNewPushKey(int fromUserId, my.PushKeyContent pushKey) async {
|
Future<void> handleNewPushKey(int fromUserId, int keyId, List<int> key) async {
|
||||||
final pushKeys = await getPushKeys(SecureStorageKeys.sendingPushKeys);
|
final pushKeys = await getPushKeys(SecureStorageKeys.sendingPushKeys);
|
||||||
|
|
||||||
var pushUser = pushKeys.firstWhereOrNull((x) => x.userId == fromUserId);
|
var pushUser = pushKeys.firstWhereOrNull((x) => x.userId == fromUserId);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/services/signal/consts.signal.dart';
|
import 'package:twonly/src/services/signal/consts.signal.dart';
|
||||||
import 'package:twonly/src/services/signal/prekeys.signal.dart';
|
import 'package:twonly/src/services/signal/prekeys.signal.dart';
|
||||||
import 'package:twonly/src/services/signal/utils.signal.dart';
|
import 'package:twonly/src/services/signal/utils.signal.dart';
|
||||||
|
|
@ -92,42 +90,40 @@ Future<Uint8List?> signalEncryptMessage(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MessageJson?> signalDecryptMessage(int source, Uint8List msg) async {
|
Future<(EncryptedContent?, PlaintextContent_DecryptionErrorMessage_Type?)>
|
||||||
|
signalDecryptMessage(
|
||||||
|
int source,
|
||||||
|
Uint8List encryptedContentRaw,
|
||||||
|
int type,
|
||||||
|
) async {
|
||||||
try {
|
try {
|
||||||
final signalStore = (await getSignalStore())!;
|
|
||||||
|
|
||||||
final session = SessionCipher.fromStore(
|
final session = SessionCipher.fromStore(
|
||||||
signalStore,
|
(await getSignalStore())!,
|
||||||
SignalProtocolAddress(source.toString(), defaultDeviceId),
|
SignalProtocolAddress(source.toString(), defaultDeviceId),
|
||||||
);
|
);
|
||||||
|
|
||||||
final msgs = removeLastXBytes(msg, 4);
|
|
||||||
if (msgs == null) {
|
|
||||||
Log.error('Message requires at least 4 bytes.');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final body = msgs[0];
|
|
||||||
final type = bytesToInt(msgs[1]);
|
|
||||||
Uint8List plaintext;
|
Uint8List plaintext;
|
||||||
if (type == CiphertextMessage.prekeyType) {
|
|
||||||
final pre = PreKeySignalMessage(body);
|
switch (type) {
|
||||||
plaintext = await session.decrypt(pre);
|
case CiphertextMessage.prekeyType:
|
||||||
} else if (type == CiphertextMessage.whisperType) {
|
plaintext = await session.decrypt(
|
||||||
final signalMsg = SignalMessage.fromSerialized(body);
|
PreKeySignalMessage(encryptedContentRaw),
|
||||||
plaintext = await session.decryptFromSignal(signalMsg);
|
);
|
||||||
} else {
|
case CiphertextMessage.whisperType:
|
||||||
Log.error('Type not known: $type');
|
plaintext = await session.decryptFromSignal(
|
||||||
return null;
|
SignalMessage.fromSerialized(encryptedContentRaw),
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
Log.error('Unknown Message Decryption Type: $type');
|
||||||
|
return (null, PlaintextContent_DecryptionErrorMessage_Type.UNKNOWN);
|
||||||
}
|
}
|
||||||
return MessageJson.fromJson(
|
|
||||||
jsonDecode(
|
return (EncryptedContent.fromBuffer(plaintext), null);
|
||||||
utf8.decode(
|
} on InvalidKeyIdException catch (e) {
|
||||||
gzip.decode(plaintext),
|
Log.error(e);
|
||||||
),
|
return (null, PlaintextContent_DecryptionErrorMessage_Type.PREKEY_UNKNOWN);
|
||||||
) as Map<String, dynamic>,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error(e.toString());
|
Log.error(e);
|
||||||
return null;
|
return (null, PlaintextContent_DecryptionErrorMessage_Type.UNKNOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import 'dart:async';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart'
|
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart'
|
||||||
as server;
|
as server;
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.dart';
|
||||||
import 'package:twonly/src/model/protobuf/backup/backup.pb.dart';
|
import 'package:twonly/src/model/protobuf/backup/backup.pb.dart';
|
||||||
import 'package:twonly/src/services/api/media_upload.dart';
|
import 'package:twonly/src/services/api/media_upload.dart';
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
import 'package:twonly/src/constants/secure_storage_keys.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.dart';
|
||||||
import 'package:twonly/src/model/protobuf/backup/backup.pb.dart';
|
import 'package:twonly/src/model/protobuf/backup/backup.pb.dart';
|
||||||
import 'package:twonly/src/services/twonly_safe/common.twonly_safe.dart';
|
import 'package:twonly/src/services/twonly_safe/common.twonly_safe.dart';
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import 'package:gal/gal.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:local_auth/local_auth.dart';
|
import 'package:local_auth/local_auth.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/localization/generated/app_localizations.dart';
|
import 'package:twonly/src/localization/generated/app_localizations.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message_old.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
||||||
import 'package:twonly/src/providers/settings.provider.dart';
|
import 'package:twonly/src/providers/settings.provider.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:screenshot/screenshot.dart';
|
import 'package:screenshot/screenshot.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/storage.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
@ -308,7 +308,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
||||||
imageBytes: imageBytes,
|
imageBytes: imageBytes,
|
||||||
sharedFromGallery: sharedFromGallery,
|
sharedFromGallery: sharedFromGallery,
|
||||||
sendTo: widget.sendTo,
|
sendTo: widget.sendTo,
|
||||||
mirrorVideo: isFront && Platform.isAndroid,
|
mirrorVideo: isFront && Platform.isAndroid && false,
|
||||||
useHighQuality: true,
|
useHighQuality: true,
|
||||||
),
|
),
|
||||||
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import 'dart:async';
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:screenshot/screenshot.dart';
|
import 'package:screenshot/screenshot.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_preview_controller_view.dart';
|
import 'package:twonly/src/views/camera/camera_preview_controller_view.dart';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import 'dart:collection';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/components/flame.dart';
|
import 'package:twonly/src/views/components/flame.dart';
|
||||||
import 'package:twonly/src/views/components/headline.dart';
|
import 'package:twonly/src/views/components/headline.dart';
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:screenshot/screenshot.dart';
|
import 'package:screenshot/screenshot.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/api/media_upload.dart';
|
import 'package:twonly/src/services/api/media_upload.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import 'dart:typed_data';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/services/api/media_upload.dart';
|
import 'package:twonly/src/services/api/media_upload.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/camera/share_image_components/best_friends_selector.dart';
|
import 'package:twonly/src/views/camera/share_image_components/best_friends_selector.dart';
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message_old.dart';
|
||||||
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pbserver.dart';
|
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pbserver.dart';
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
import 'package:twonly/src/services/api/utils.dart';
|
import 'package:twonly/src/services/api/utils.dart';
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue