mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 13:08:42 +00:00
hopefully final fix for the retransmission problem
This commit is contained in:
parent
79caf95afe
commit
674e42722d
16 changed files with 8456 additions and 203 deletions
1
drift_schemas/twonly_database/drift_schema_v13.json
Normal file
1
drift_schemas/twonly_database/drift_schema_v13.json
Normal file
File diff suppressed because one or more lines are too long
1
drift_schemas/twonly_database/drift_schema_v14.json
Normal file
1
drift_schemas/twonly_database/drift_schema_v14.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -23,6 +23,15 @@ class MessageRetransmissionDao extends DatabaseAccessor<TwonlyDatabase>
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<int>> getRetransmitAbleMessages() async {
|
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)
|
return (await (select(messageRetransmissions)
|
||||||
..where((t) => t.acknowledgeByServerAt.isNull()))
|
..where((t) => t.acknowledgeByServerAt.isNull()))
|
||||||
.get())
|
.get())
|
||||||
|
|
@ -45,19 +54,11 @@ class MessageRetransmissionDao extends DatabaseAccessor<TwonlyDatabase>
|
||||||
.write(updatedValues);
|
.write(updatedValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future resetAckStatusForAllMessages(int fromUserId) async {
|
Future resetAckStatusFor(int fromUserId, Uint8List encryptedHash) async {
|
||||||
final deletedCount = await (delete(messageRetransmissions)
|
|
||||||
..where((m) =>
|
|
||||||
m.willNotGetACKByUser.equals(true) &
|
|
||||||
m.acknowledgeByServerAt.isNotNull()))
|
|
||||||
.go();
|
|
||||||
if (deletedCount > 0) {
|
|
||||||
Log.info('$deletedCount faulty retransmission messages where deleted.');
|
|
||||||
}
|
|
||||||
return ((update(messageRetransmissions))
|
return ((update(messageRetransmissions))
|
||||||
..where((m) =>
|
..where((m) =>
|
||||||
m.willNotGetACKByUser.equals(false) &
|
m.contactId.equals(fromUserId) &
|
||||||
m.contactId.equals(fromUserId)))
|
m.encryptedHash.equals(encryptedHash)))
|
||||||
.write(
|
.write(
|
||||||
MessageRetransmissionsCompanion(
|
MessageRetransmissionsCompanion(
|
||||||
acknowledgeByServerAt: Value(null),
|
acknowledgeByServerAt: Value(null),
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ class MessageRetransmissions extends Table {
|
||||||
|
|
||||||
BlobColumn get plaintextContent => blob()();
|
BlobColumn get plaintextContent => blob()();
|
||||||
BlobColumn get pushData => blob().nullable()();
|
BlobColumn get pushData => blob().nullable()();
|
||||||
|
BlobColumn get encryptedHash => blob().nullable()();
|
||||||
BoolColumn get willNotGetACKByUser =>
|
|
||||||
boolean().withDefault(Constant(false))();
|
|
||||||
|
|
||||||
DateTimeColumn get acknowledgeByServerAt => dateTime().nullable()();
|
DateTimeColumn get acknowledgeByServerAt => dateTime().nullable()();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class TwonlyDatabase extends _$TwonlyDatabase {
|
||||||
TwonlyDatabase.forTesting(DatabaseConnection super.connection);
|
TwonlyDatabase.forTesting(DatabaseConnection super.connection);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 12;
|
int get schemaVersion => 14;
|
||||||
|
|
||||||
static QueryExecutor _openConnection() {
|
static QueryExecutor _openConnection() {
|
||||||
return driftDatabase(
|
return driftDatabase(
|
||||||
|
|
@ -125,6 +125,14 @@ class TwonlyDatabase extends _$TwonlyDatabase {
|
||||||
m.addColumn(schema.messageRetransmissions,
|
m.addColumn(schema.messageRetransmissions,
|
||||||
schema.messageRetransmissions.willNotGetACKByUser);
|
schema.messageRetransmissions.willNotGetACKByUser);
|
||||||
},
|
},
|
||||||
|
from12To13: (m, schema) async {
|
||||||
|
m.dropColumn(
|
||||||
|
schema.messageRetransmissions, "will_not_get_a_c_k_by_user");
|
||||||
|
},
|
||||||
|
from13To14: (m, schema) async {
|
||||||
|
m.addColumn(schema.messageRetransmissions,
|
||||||
|
schema.messageRetransmissions.encryptedHash);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4225,16 +4225,12 @@ class $MessageRetransmissionsTable extends MessageRetransmissions
|
||||||
late final GeneratedColumn<Uint8List> pushData = GeneratedColumn<Uint8List>(
|
late final GeneratedColumn<Uint8List> pushData = GeneratedColumn<Uint8List>(
|
||||||
'push_data', aliasedName, true,
|
'push_data', aliasedName, true,
|
||||||
type: DriftSqlType.blob, requiredDuringInsert: false);
|
type: DriftSqlType.blob, requiredDuringInsert: false);
|
||||||
static const VerificationMeta _willNotGetACKByUserMeta =
|
static const VerificationMeta _encryptedHashMeta =
|
||||||
const VerificationMeta('willNotGetACKByUser');
|
const VerificationMeta('encryptedHash');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<bool> willNotGetACKByUser = GeneratedColumn<bool>(
|
late final GeneratedColumn<Uint8List> encryptedHash =
|
||||||
'will_not_get_a_c_k_by_user', aliasedName, false,
|
GeneratedColumn<Uint8List>('encrypted_hash', aliasedName, true,
|
||||||
type: DriftSqlType.bool,
|
type: DriftSqlType.blob, requiredDuringInsert: false);
|
||||||
requiredDuringInsert: false,
|
|
||||||
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
|
||||||
'CHECK ("will_not_get_a_c_k_by_user" IN (0, 1))'),
|
|
||||||
defaultValue: Constant(false));
|
|
||||||
static const VerificationMeta _acknowledgeByServerAtMeta =
|
static const VerificationMeta _acknowledgeByServerAtMeta =
|
||||||
const VerificationMeta('acknowledgeByServerAt');
|
const VerificationMeta('acknowledgeByServerAt');
|
||||||
@override
|
@override
|
||||||
|
|
@ -4248,7 +4244,7 @@ class $MessageRetransmissionsTable extends MessageRetransmissions
|
||||||
messageId,
|
messageId,
|
||||||
plaintextContent,
|
plaintextContent,
|
||||||
pushData,
|
pushData,
|
||||||
willNotGetACKByUser,
|
encryptedHash,
|
||||||
acknowledgeByServerAt
|
acknowledgeByServerAt
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
|
|
@ -4290,11 +4286,11 @@ class $MessageRetransmissionsTable extends MessageRetransmissions
|
||||||
context.handle(_pushDataMeta,
|
context.handle(_pushDataMeta,
|
||||||
pushData.isAcceptableOrUnknown(data['push_data']!, _pushDataMeta));
|
pushData.isAcceptableOrUnknown(data['push_data']!, _pushDataMeta));
|
||||||
}
|
}
|
||||||
if (data.containsKey('will_not_get_a_c_k_by_user')) {
|
if (data.containsKey('encrypted_hash')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_willNotGetACKByUserMeta,
|
_encryptedHashMeta,
|
||||||
willNotGetACKByUser.isAcceptableOrUnknown(
|
encryptedHash.isAcceptableOrUnknown(
|
||||||
data['will_not_get_a_c_k_by_user']!, _willNotGetACKByUserMeta));
|
data['encrypted_hash']!, _encryptedHashMeta));
|
||||||
}
|
}
|
||||||
if (data.containsKey('acknowledge_by_server_at')) {
|
if (data.containsKey('acknowledge_by_server_at')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
|
|
@ -4321,8 +4317,8 @@ class $MessageRetransmissionsTable extends MessageRetransmissions
|
||||||
DriftSqlType.blob, data['${effectivePrefix}plaintext_content'])!,
|
DriftSqlType.blob, data['${effectivePrefix}plaintext_content'])!,
|
||||||
pushData: attachedDatabase.typeMapping
|
pushData: attachedDatabase.typeMapping
|
||||||
.read(DriftSqlType.blob, data['${effectivePrefix}push_data']),
|
.read(DriftSqlType.blob, data['${effectivePrefix}push_data']),
|
||||||
willNotGetACKByUser: attachedDatabase.typeMapping.read(DriftSqlType.bool,
|
encryptedHash: attachedDatabase.typeMapping
|
||||||
data['${effectivePrefix}will_not_get_a_c_k_by_user'])!,
|
.read(DriftSqlType.blob, data['${effectivePrefix}encrypted_hash']),
|
||||||
acknowledgeByServerAt: attachedDatabase.typeMapping.read(
|
acknowledgeByServerAt: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.dateTime,
|
DriftSqlType.dateTime,
|
||||||
data['${effectivePrefix}acknowledge_by_server_at']),
|
data['${effectivePrefix}acknowledge_by_server_at']),
|
||||||
|
|
@ -4342,7 +4338,7 @@ class MessageRetransmission extends DataClass
|
||||||
final int? messageId;
|
final int? messageId;
|
||||||
final Uint8List plaintextContent;
|
final Uint8List plaintextContent;
|
||||||
final Uint8List? pushData;
|
final Uint8List? pushData;
|
||||||
final bool willNotGetACKByUser;
|
final Uint8List? encryptedHash;
|
||||||
final DateTime? acknowledgeByServerAt;
|
final DateTime? acknowledgeByServerAt;
|
||||||
const MessageRetransmission(
|
const MessageRetransmission(
|
||||||
{required this.retransmissionId,
|
{required this.retransmissionId,
|
||||||
|
|
@ -4350,7 +4346,7 @@ class MessageRetransmission extends DataClass
|
||||||
this.messageId,
|
this.messageId,
|
||||||
required this.plaintextContent,
|
required this.plaintextContent,
|
||||||
this.pushData,
|
this.pushData,
|
||||||
required this.willNotGetACKByUser,
|
this.encryptedHash,
|
||||||
this.acknowledgeByServerAt});
|
this.acknowledgeByServerAt});
|
||||||
@override
|
@override
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
|
|
@ -4364,7 +4360,9 @@ class MessageRetransmission extends DataClass
|
||||||
if (!nullToAbsent || pushData != null) {
|
if (!nullToAbsent || pushData != null) {
|
||||||
map['push_data'] = Variable<Uint8List>(pushData);
|
map['push_data'] = Variable<Uint8List>(pushData);
|
||||||
}
|
}
|
||||||
map['will_not_get_a_c_k_by_user'] = Variable<bool>(willNotGetACKByUser);
|
if (!nullToAbsent || encryptedHash != null) {
|
||||||
|
map['encrypted_hash'] = Variable<Uint8List>(encryptedHash);
|
||||||
|
}
|
||||||
if (!nullToAbsent || acknowledgeByServerAt != null) {
|
if (!nullToAbsent || acknowledgeByServerAt != null) {
|
||||||
map['acknowledge_by_server_at'] =
|
map['acknowledge_by_server_at'] =
|
||||||
Variable<DateTime>(acknowledgeByServerAt);
|
Variable<DateTime>(acknowledgeByServerAt);
|
||||||
|
|
@ -4383,7 +4381,9 @@ class MessageRetransmission extends DataClass
|
||||||
pushData: pushData == null && nullToAbsent
|
pushData: pushData == null && nullToAbsent
|
||||||
? const Value.absent()
|
? const Value.absent()
|
||||||
: Value(pushData),
|
: Value(pushData),
|
||||||
willNotGetACKByUser: Value(willNotGetACKByUser),
|
encryptedHash: encryptedHash == null && nullToAbsent
|
||||||
|
? const Value.absent()
|
||||||
|
: Value(encryptedHash),
|
||||||
acknowledgeByServerAt: acknowledgeByServerAt == null && nullToAbsent
|
acknowledgeByServerAt: acknowledgeByServerAt == null && nullToAbsent
|
||||||
? const Value.absent()
|
? const Value.absent()
|
||||||
: Value(acknowledgeByServerAt),
|
: Value(acknowledgeByServerAt),
|
||||||
|
|
@ -4400,8 +4400,7 @@ class MessageRetransmission extends DataClass
|
||||||
plaintextContent:
|
plaintextContent:
|
||||||
serializer.fromJson<Uint8List>(json['plaintextContent']),
|
serializer.fromJson<Uint8List>(json['plaintextContent']),
|
||||||
pushData: serializer.fromJson<Uint8List?>(json['pushData']),
|
pushData: serializer.fromJson<Uint8List?>(json['pushData']),
|
||||||
willNotGetACKByUser:
|
encryptedHash: serializer.fromJson<Uint8List?>(json['encryptedHash']),
|
||||||
serializer.fromJson<bool>(json['willNotGetACKByUser']),
|
|
||||||
acknowledgeByServerAt:
|
acknowledgeByServerAt:
|
||||||
serializer.fromJson<DateTime?>(json['acknowledgeByServerAt']),
|
serializer.fromJson<DateTime?>(json['acknowledgeByServerAt']),
|
||||||
);
|
);
|
||||||
|
|
@ -4415,7 +4414,7 @@ class MessageRetransmission extends DataClass
|
||||||
'messageId': serializer.toJson<int?>(messageId),
|
'messageId': serializer.toJson<int?>(messageId),
|
||||||
'plaintextContent': serializer.toJson<Uint8List>(plaintextContent),
|
'plaintextContent': serializer.toJson<Uint8List>(plaintextContent),
|
||||||
'pushData': serializer.toJson<Uint8List?>(pushData),
|
'pushData': serializer.toJson<Uint8List?>(pushData),
|
||||||
'willNotGetACKByUser': serializer.toJson<bool>(willNotGetACKByUser),
|
'encryptedHash': serializer.toJson<Uint8List?>(encryptedHash),
|
||||||
'acknowledgeByServerAt':
|
'acknowledgeByServerAt':
|
||||||
serializer.toJson<DateTime?>(acknowledgeByServerAt),
|
serializer.toJson<DateTime?>(acknowledgeByServerAt),
|
||||||
};
|
};
|
||||||
|
|
@ -4427,7 +4426,7 @@ class MessageRetransmission extends DataClass
|
||||||
Value<int?> messageId = const Value.absent(),
|
Value<int?> messageId = const Value.absent(),
|
||||||
Uint8List? plaintextContent,
|
Uint8List? plaintextContent,
|
||||||
Value<Uint8List?> pushData = const Value.absent(),
|
Value<Uint8List?> pushData = const Value.absent(),
|
||||||
bool? willNotGetACKByUser,
|
Value<Uint8List?> encryptedHash = const Value.absent(),
|
||||||
Value<DateTime?> acknowledgeByServerAt = const Value.absent()}) =>
|
Value<DateTime?> acknowledgeByServerAt = const Value.absent()}) =>
|
||||||
MessageRetransmission(
|
MessageRetransmission(
|
||||||
retransmissionId: retransmissionId ?? this.retransmissionId,
|
retransmissionId: retransmissionId ?? this.retransmissionId,
|
||||||
|
|
@ -4435,7 +4434,8 @@ class MessageRetransmission extends DataClass
|
||||||
messageId: messageId.present ? messageId.value : this.messageId,
|
messageId: messageId.present ? messageId.value : this.messageId,
|
||||||
plaintextContent: plaintextContent ?? this.plaintextContent,
|
plaintextContent: plaintextContent ?? this.plaintextContent,
|
||||||
pushData: pushData.present ? pushData.value : this.pushData,
|
pushData: pushData.present ? pushData.value : this.pushData,
|
||||||
willNotGetACKByUser: willNotGetACKByUser ?? this.willNotGetACKByUser,
|
encryptedHash:
|
||||||
|
encryptedHash.present ? encryptedHash.value : this.encryptedHash,
|
||||||
acknowledgeByServerAt: acknowledgeByServerAt.present
|
acknowledgeByServerAt: acknowledgeByServerAt.present
|
||||||
? acknowledgeByServerAt.value
|
? acknowledgeByServerAt.value
|
||||||
: this.acknowledgeByServerAt,
|
: this.acknowledgeByServerAt,
|
||||||
|
|
@ -4452,9 +4452,9 @@ class MessageRetransmission extends DataClass
|
||||||
? data.plaintextContent.value
|
? data.plaintextContent.value
|
||||||
: this.plaintextContent,
|
: this.plaintextContent,
|
||||||
pushData: data.pushData.present ? data.pushData.value : this.pushData,
|
pushData: data.pushData.present ? data.pushData.value : this.pushData,
|
||||||
willNotGetACKByUser: data.willNotGetACKByUser.present
|
encryptedHash: data.encryptedHash.present
|
||||||
? data.willNotGetACKByUser.value
|
? data.encryptedHash.value
|
||||||
: this.willNotGetACKByUser,
|
: this.encryptedHash,
|
||||||
acknowledgeByServerAt: data.acknowledgeByServerAt.present
|
acknowledgeByServerAt: data.acknowledgeByServerAt.present
|
||||||
? data.acknowledgeByServerAt.value
|
? data.acknowledgeByServerAt.value
|
||||||
: this.acknowledgeByServerAt,
|
: this.acknowledgeByServerAt,
|
||||||
|
|
@ -4469,7 +4469,7 @@ class MessageRetransmission extends DataClass
|
||||||
..write('messageId: $messageId, ')
|
..write('messageId: $messageId, ')
|
||||||
..write('plaintextContent: $plaintextContent, ')
|
..write('plaintextContent: $plaintextContent, ')
|
||||||
..write('pushData: $pushData, ')
|
..write('pushData: $pushData, ')
|
||||||
..write('willNotGetACKByUser: $willNotGetACKByUser, ')
|
..write('encryptedHash: $encryptedHash, ')
|
||||||
..write('acknowledgeByServerAt: $acknowledgeByServerAt')
|
..write('acknowledgeByServerAt: $acknowledgeByServerAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
|
|
@ -4482,7 +4482,7 @@ class MessageRetransmission extends DataClass
|
||||||
messageId,
|
messageId,
|
||||||
$driftBlobEquality.hash(plaintextContent),
|
$driftBlobEquality.hash(plaintextContent),
|
||||||
$driftBlobEquality.hash(pushData),
|
$driftBlobEquality.hash(pushData),
|
||||||
willNotGetACKByUser,
|
$driftBlobEquality.hash(encryptedHash),
|
||||||
acknowledgeByServerAt);
|
acknowledgeByServerAt);
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
|
|
@ -4494,7 +4494,7 @@ class MessageRetransmission extends DataClass
|
||||||
$driftBlobEquality.equals(
|
$driftBlobEquality.equals(
|
||||||
other.plaintextContent, this.plaintextContent) &&
|
other.plaintextContent, this.plaintextContent) &&
|
||||||
$driftBlobEquality.equals(other.pushData, this.pushData) &&
|
$driftBlobEquality.equals(other.pushData, this.pushData) &&
|
||||||
other.willNotGetACKByUser == this.willNotGetACKByUser &&
|
$driftBlobEquality.equals(other.encryptedHash, this.encryptedHash) &&
|
||||||
other.acknowledgeByServerAt == this.acknowledgeByServerAt);
|
other.acknowledgeByServerAt == this.acknowledgeByServerAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4505,7 +4505,7 @@ class MessageRetransmissionsCompanion
|
||||||
final Value<int?> messageId;
|
final Value<int?> messageId;
|
||||||
final Value<Uint8List> plaintextContent;
|
final Value<Uint8List> plaintextContent;
|
||||||
final Value<Uint8List?> pushData;
|
final Value<Uint8List?> pushData;
|
||||||
final Value<bool> willNotGetACKByUser;
|
final Value<Uint8List?> encryptedHash;
|
||||||
final Value<DateTime?> acknowledgeByServerAt;
|
final Value<DateTime?> acknowledgeByServerAt;
|
||||||
const MessageRetransmissionsCompanion({
|
const MessageRetransmissionsCompanion({
|
||||||
this.retransmissionId = const Value.absent(),
|
this.retransmissionId = const Value.absent(),
|
||||||
|
|
@ -4513,7 +4513,7 @@ class MessageRetransmissionsCompanion
|
||||||
this.messageId = const Value.absent(),
|
this.messageId = const Value.absent(),
|
||||||
this.plaintextContent = const Value.absent(),
|
this.plaintextContent = const Value.absent(),
|
||||||
this.pushData = const Value.absent(),
|
this.pushData = const Value.absent(),
|
||||||
this.willNotGetACKByUser = const Value.absent(),
|
this.encryptedHash = const Value.absent(),
|
||||||
this.acknowledgeByServerAt = const Value.absent(),
|
this.acknowledgeByServerAt = const Value.absent(),
|
||||||
});
|
});
|
||||||
MessageRetransmissionsCompanion.insert({
|
MessageRetransmissionsCompanion.insert({
|
||||||
|
|
@ -4522,7 +4522,7 @@ class MessageRetransmissionsCompanion
|
||||||
this.messageId = const Value.absent(),
|
this.messageId = const Value.absent(),
|
||||||
required Uint8List plaintextContent,
|
required Uint8List plaintextContent,
|
||||||
this.pushData = const Value.absent(),
|
this.pushData = const Value.absent(),
|
||||||
this.willNotGetACKByUser = const Value.absent(),
|
this.encryptedHash = const Value.absent(),
|
||||||
this.acknowledgeByServerAt = const Value.absent(),
|
this.acknowledgeByServerAt = const Value.absent(),
|
||||||
}) : contactId = Value(contactId),
|
}) : contactId = Value(contactId),
|
||||||
plaintextContent = Value(plaintextContent);
|
plaintextContent = Value(plaintextContent);
|
||||||
|
|
@ -4532,7 +4532,7 @@ class MessageRetransmissionsCompanion
|
||||||
Expression<int>? messageId,
|
Expression<int>? messageId,
|
||||||
Expression<Uint8List>? plaintextContent,
|
Expression<Uint8List>? plaintextContent,
|
||||||
Expression<Uint8List>? pushData,
|
Expression<Uint8List>? pushData,
|
||||||
Expression<bool>? willNotGetACKByUser,
|
Expression<Uint8List>? encryptedHash,
|
||||||
Expression<DateTime>? acknowledgeByServerAt,
|
Expression<DateTime>? acknowledgeByServerAt,
|
||||||
}) {
|
}) {
|
||||||
return RawValuesInsertable({
|
return RawValuesInsertable({
|
||||||
|
|
@ -4541,8 +4541,7 @@ class MessageRetransmissionsCompanion
|
||||||
if (messageId != null) 'message_id': messageId,
|
if (messageId != null) 'message_id': messageId,
|
||||||
if (plaintextContent != null) 'plaintext_content': plaintextContent,
|
if (plaintextContent != null) 'plaintext_content': plaintextContent,
|
||||||
if (pushData != null) 'push_data': pushData,
|
if (pushData != null) 'push_data': pushData,
|
||||||
if (willNotGetACKByUser != null)
|
if (encryptedHash != null) 'encrypted_hash': encryptedHash,
|
||||||
'will_not_get_a_c_k_by_user': willNotGetACKByUser,
|
|
||||||
if (acknowledgeByServerAt != null)
|
if (acknowledgeByServerAt != null)
|
||||||
'acknowledge_by_server_at': acknowledgeByServerAt,
|
'acknowledge_by_server_at': acknowledgeByServerAt,
|
||||||
});
|
});
|
||||||
|
|
@ -4554,7 +4553,7 @@ class MessageRetransmissionsCompanion
|
||||||
Value<int?>? messageId,
|
Value<int?>? messageId,
|
||||||
Value<Uint8List>? plaintextContent,
|
Value<Uint8List>? plaintextContent,
|
||||||
Value<Uint8List?>? pushData,
|
Value<Uint8List?>? pushData,
|
||||||
Value<bool>? willNotGetACKByUser,
|
Value<Uint8List?>? encryptedHash,
|
||||||
Value<DateTime?>? acknowledgeByServerAt}) {
|
Value<DateTime?>? acknowledgeByServerAt}) {
|
||||||
return MessageRetransmissionsCompanion(
|
return MessageRetransmissionsCompanion(
|
||||||
retransmissionId: retransmissionId ?? this.retransmissionId,
|
retransmissionId: retransmissionId ?? this.retransmissionId,
|
||||||
|
|
@ -4562,7 +4561,7 @@ class MessageRetransmissionsCompanion
|
||||||
messageId: messageId ?? this.messageId,
|
messageId: messageId ?? this.messageId,
|
||||||
plaintextContent: plaintextContent ?? this.plaintextContent,
|
plaintextContent: plaintextContent ?? this.plaintextContent,
|
||||||
pushData: pushData ?? this.pushData,
|
pushData: pushData ?? this.pushData,
|
||||||
willNotGetACKByUser: willNotGetACKByUser ?? this.willNotGetACKByUser,
|
encryptedHash: encryptedHash ?? this.encryptedHash,
|
||||||
acknowledgeByServerAt:
|
acknowledgeByServerAt:
|
||||||
acknowledgeByServerAt ?? this.acknowledgeByServerAt,
|
acknowledgeByServerAt ?? this.acknowledgeByServerAt,
|
||||||
);
|
);
|
||||||
|
|
@ -4586,9 +4585,8 @@ class MessageRetransmissionsCompanion
|
||||||
if (pushData.present) {
|
if (pushData.present) {
|
||||||
map['push_data'] = Variable<Uint8List>(pushData.value);
|
map['push_data'] = Variable<Uint8List>(pushData.value);
|
||||||
}
|
}
|
||||||
if (willNotGetACKByUser.present) {
|
if (encryptedHash.present) {
|
||||||
map['will_not_get_a_c_k_by_user'] =
|
map['encrypted_hash'] = Variable<Uint8List>(encryptedHash.value);
|
||||||
Variable<bool>(willNotGetACKByUser.value);
|
|
||||||
}
|
}
|
||||||
if (acknowledgeByServerAt.present) {
|
if (acknowledgeByServerAt.present) {
|
||||||
map['acknowledge_by_server_at'] =
|
map['acknowledge_by_server_at'] =
|
||||||
|
|
@ -4605,7 +4603,7 @@ class MessageRetransmissionsCompanion
|
||||||
..write('messageId: $messageId, ')
|
..write('messageId: $messageId, ')
|
||||||
..write('plaintextContent: $plaintextContent, ')
|
..write('plaintextContent: $plaintextContent, ')
|
||||||
..write('pushData: $pushData, ')
|
..write('pushData: $pushData, ')
|
||||||
..write('willNotGetACKByUser: $willNotGetACKByUser, ')
|
..write('encryptedHash: $encryptedHash, ')
|
||||||
..write('acknowledgeByServerAt: $acknowledgeByServerAt')
|
..write('acknowledgeByServerAt: $acknowledgeByServerAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
|
|
@ -7154,7 +7152,7 @@ typedef $$MessageRetransmissionsTableCreateCompanionBuilder
|
||||||
Value<int?> messageId,
|
Value<int?> messageId,
|
||||||
required Uint8List plaintextContent,
|
required Uint8List plaintextContent,
|
||||||
Value<Uint8List?> pushData,
|
Value<Uint8List?> pushData,
|
||||||
Value<bool> willNotGetACKByUser,
|
Value<Uint8List?> encryptedHash,
|
||||||
Value<DateTime?> acknowledgeByServerAt,
|
Value<DateTime?> acknowledgeByServerAt,
|
||||||
});
|
});
|
||||||
typedef $$MessageRetransmissionsTableUpdateCompanionBuilder
|
typedef $$MessageRetransmissionsTableUpdateCompanionBuilder
|
||||||
|
|
@ -7164,7 +7162,7 @@ typedef $$MessageRetransmissionsTableUpdateCompanionBuilder
|
||||||
Value<int?> messageId,
|
Value<int?> messageId,
|
||||||
Value<Uint8List> plaintextContent,
|
Value<Uint8List> plaintextContent,
|
||||||
Value<Uint8List?> pushData,
|
Value<Uint8List?> pushData,
|
||||||
Value<bool> willNotGetACKByUser,
|
Value<Uint8List?> encryptedHash,
|
||||||
Value<DateTime?> acknowledgeByServerAt,
|
Value<DateTime?> acknowledgeByServerAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -7224,9 +7222,8 @@ class $$MessageRetransmissionsTableFilterComposer
|
||||||
ColumnFilters<Uint8List> get pushData => $composableBuilder(
|
ColumnFilters<Uint8List> get pushData => $composableBuilder(
|
||||||
column: $table.pushData, builder: (column) => ColumnFilters(column));
|
column: $table.pushData, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
ColumnFilters<bool> get willNotGetACKByUser => $composableBuilder(
|
ColumnFilters<Uint8List> get encryptedHash => $composableBuilder(
|
||||||
column: $table.willNotGetACKByUser,
|
column: $table.encryptedHash, builder: (column) => ColumnFilters(column));
|
||||||
builder: (column) => ColumnFilters(column));
|
|
||||||
|
|
||||||
ColumnFilters<DateTime> get acknowledgeByServerAt => $composableBuilder(
|
ColumnFilters<DateTime> get acknowledgeByServerAt => $composableBuilder(
|
||||||
column: $table.acknowledgeByServerAt,
|
column: $table.acknowledgeByServerAt,
|
||||||
|
|
@ -7293,8 +7290,8 @@ class $$MessageRetransmissionsTableOrderingComposer
|
||||||
ColumnOrderings<Uint8List> get pushData => $composableBuilder(
|
ColumnOrderings<Uint8List> get pushData => $composableBuilder(
|
||||||
column: $table.pushData, builder: (column) => ColumnOrderings(column));
|
column: $table.pushData, builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<bool> get willNotGetACKByUser => $composableBuilder(
|
ColumnOrderings<Uint8List> get encryptedHash => $composableBuilder(
|
||||||
column: $table.willNotGetACKByUser,
|
column: $table.encryptedHash,
|
||||||
builder: (column) => ColumnOrderings(column));
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<DateTime> get acknowledgeByServerAt => $composableBuilder(
|
ColumnOrderings<DateTime> get acknowledgeByServerAt => $composableBuilder(
|
||||||
|
|
@ -7360,8 +7357,8 @@ class $$MessageRetransmissionsTableAnnotationComposer
|
||||||
GeneratedColumn<Uint8List> get pushData =>
|
GeneratedColumn<Uint8List> get pushData =>
|
||||||
$composableBuilder(column: $table.pushData, builder: (column) => column);
|
$composableBuilder(column: $table.pushData, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<bool> get willNotGetACKByUser => $composableBuilder(
|
GeneratedColumn<Uint8List> get encryptedHash => $composableBuilder(
|
||||||
column: $table.willNotGetACKByUser, builder: (column) => column);
|
column: $table.encryptedHash, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<DateTime> get acknowledgeByServerAt => $composableBuilder(
|
GeneratedColumn<DateTime> get acknowledgeByServerAt => $composableBuilder(
|
||||||
column: $table.acknowledgeByServerAt, builder: (column) => column);
|
column: $table.acknowledgeByServerAt, builder: (column) => column);
|
||||||
|
|
@ -7439,7 +7436,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
||||||
Value<int?> messageId = const Value.absent(),
|
Value<int?> messageId = const Value.absent(),
|
||||||
Value<Uint8List> plaintextContent = const Value.absent(),
|
Value<Uint8List> plaintextContent = const Value.absent(),
|
||||||
Value<Uint8List?> pushData = const Value.absent(),
|
Value<Uint8List?> pushData = const Value.absent(),
|
||||||
Value<bool> willNotGetACKByUser = const Value.absent(),
|
Value<Uint8List?> encryptedHash = const Value.absent(),
|
||||||
Value<DateTime?> acknowledgeByServerAt = const Value.absent(),
|
Value<DateTime?> acknowledgeByServerAt = const Value.absent(),
|
||||||
}) =>
|
}) =>
|
||||||
MessageRetransmissionsCompanion(
|
MessageRetransmissionsCompanion(
|
||||||
|
|
@ -7448,7 +7445,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
||||||
messageId: messageId,
|
messageId: messageId,
|
||||||
plaintextContent: plaintextContent,
|
plaintextContent: plaintextContent,
|
||||||
pushData: pushData,
|
pushData: pushData,
|
||||||
willNotGetACKByUser: willNotGetACKByUser,
|
encryptedHash: encryptedHash,
|
||||||
acknowledgeByServerAt: acknowledgeByServerAt,
|
acknowledgeByServerAt: acknowledgeByServerAt,
|
||||||
),
|
),
|
||||||
createCompanionCallback: ({
|
createCompanionCallback: ({
|
||||||
|
|
@ -7457,7 +7454,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
||||||
Value<int?> messageId = const Value.absent(),
|
Value<int?> messageId = const Value.absent(),
|
||||||
required Uint8List plaintextContent,
|
required Uint8List plaintextContent,
|
||||||
Value<Uint8List?> pushData = const Value.absent(),
|
Value<Uint8List?> pushData = const Value.absent(),
|
||||||
Value<bool> willNotGetACKByUser = const Value.absent(),
|
Value<Uint8List?> encryptedHash = const Value.absent(),
|
||||||
Value<DateTime?> acknowledgeByServerAt = const Value.absent(),
|
Value<DateTime?> acknowledgeByServerAt = const Value.absent(),
|
||||||
}) =>
|
}) =>
|
||||||
MessageRetransmissionsCompanion.insert(
|
MessageRetransmissionsCompanion.insert(
|
||||||
|
|
@ -7466,7 +7463,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
|
||||||
messageId: messageId,
|
messageId: messageId,
|
||||||
plaintextContent: plaintextContent,
|
plaintextContent: plaintextContent,
|
||||||
pushData: pushData,
|
pushData: pushData,
|
||||||
willNotGetACKByUser: willNotGetACKByUser,
|
encryptedHash: encryptedHash,
|
||||||
acknowledgeByServerAt: acknowledgeByServerAt,
|
acknowledgeByServerAt: acknowledgeByServerAt,
|
||||||
),
|
),
|
||||||
withReferenceMapper: (p0) => p0
|
withReferenceMapper: (p0) => p0
|
||||||
|
|
|
||||||
|
|
@ -2722,6 +2722,490 @@ i1.GeneratedColumn<bool> _column_68(String aliasedName) =>
|
||||||
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
'CHECK ("will_not_get_a_c_k_by_user" IN (0, 1))'),
|
'CHECK ("will_not_get_a_c_k_by_user" IN (0, 1))'),
|
||||||
defaultValue: const CustomExpression('0'));
|
defaultValue: const CustomExpression('0'));
|
||||||
|
|
||||||
|
final class Schema13 extends i0.VersionedSchema {
|
||||||
|
Schema13({required super.database}) : super(version: 13);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
contacts,
|
||||||
|
messages,
|
||||||
|
mediaUploads,
|
||||||
|
mediaDownloads,
|
||||||
|
signalIdentityKeyStores,
|
||||||
|
signalPreKeyStores,
|
||||||
|
signalSenderKeyStores,
|
||||||
|
signalSessionStores,
|
||||||
|
signalContactPreKeys,
|
||||||
|
signalContactSignedPreKeys,
|
||||||
|
messageRetransmissions,
|
||||||
|
];
|
||||||
|
late final Shape13 contacts = Shape13(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'contacts',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(user_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
_column_6,
|
||||||
|
_column_7,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_39,
|
||||||
|
_column_53,
|
||||||
|
_column_57,
|
||||||
|
_column_54,
|
||||||
|
_column_40,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
_column_13,
|
||||||
|
_column_14,
|
||||||
|
_column_55,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 messages = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'messages',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_17,
|
||||||
|
_column_18,
|
||||||
|
_column_19,
|
||||||
|
_column_48,
|
||||||
|
_column_49,
|
||||||
|
_column_20,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_52,
|
||||||
|
_column_23,
|
||||||
|
_column_24,
|
||||||
|
_column_25,
|
||||||
|
_column_26,
|
||||||
|
_column_27,
|
||||||
|
_column_28,
|
||||||
|
_column_29,
|
||||||
|
_column_30,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape7 mediaUploads = Shape7(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_uploads',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_41,
|
||||||
|
_column_42,
|
||||||
|
_column_56,
|
||||||
|
_column_44,
|
||||||
|
_column_45,
|
||||||
|
_column_46,
|
||||||
|
_column_47,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 mediaDownloads = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_downloads',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_50,
|
||||||
|
_column_51,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape2 signalIdentityKeyStores = Shape2(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_identity_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(device_id, name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_31,
|
||||||
|
_column_32,
|
||||||
|
_column_33,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 signalPreKeyStores = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_pre_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(pre_key_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_34,
|
||||||
|
_column_35,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape4 signalSenderKeyStores = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_sender_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(sender_key_name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_36,
|
||||||
|
_column_37,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 signalSessionStores = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_session_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(device_id, name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_31,
|
||||||
|
_column_32,
|
||||||
|
_column_38,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape14 signalContactPreKeys = Shape14(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_contact_pre_keys',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(contact_id, pre_key_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_58,
|
||||||
|
_column_34,
|
||||||
|
_column_35,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape15 signalContactSignedPreKeys = Shape15(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_contact_signed_pre_keys',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(contact_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_58,
|
||||||
|
_column_59,
|
||||||
|
_column_60,
|
||||||
|
_column_61,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape16 messageRetransmissions = Shape16(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'message_retransmissions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_62,
|
||||||
|
_column_63,
|
||||||
|
_column_64,
|
||||||
|
_column_65,
|
||||||
|
_column_66,
|
||||||
|
_column_67,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Schema14 extends i0.VersionedSchema {
|
||||||
|
Schema14({required super.database}) : super(version: 14);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
contacts,
|
||||||
|
messages,
|
||||||
|
mediaUploads,
|
||||||
|
mediaDownloads,
|
||||||
|
signalIdentityKeyStores,
|
||||||
|
signalPreKeyStores,
|
||||||
|
signalSenderKeyStores,
|
||||||
|
signalSessionStores,
|
||||||
|
signalContactPreKeys,
|
||||||
|
signalContactSignedPreKeys,
|
||||||
|
messageRetransmissions,
|
||||||
|
];
|
||||||
|
late final Shape13 contacts = Shape13(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'contacts',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(user_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
_column_6,
|
||||||
|
_column_7,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_39,
|
||||||
|
_column_53,
|
||||||
|
_column_57,
|
||||||
|
_column_54,
|
||||||
|
_column_40,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
_column_13,
|
||||||
|
_column_14,
|
||||||
|
_column_55,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 messages = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'messages',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_17,
|
||||||
|
_column_18,
|
||||||
|
_column_19,
|
||||||
|
_column_48,
|
||||||
|
_column_49,
|
||||||
|
_column_20,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_52,
|
||||||
|
_column_23,
|
||||||
|
_column_24,
|
||||||
|
_column_25,
|
||||||
|
_column_26,
|
||||||
|
_column_27,
|
||||||
|
_column_28,
|
||||||
|
_column_29,
|
||||||
|
_column_30,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape7 mediaUploads = Shape7(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_uploads',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_41,
|
||||||
|
_column_42,
|
||||||
|
_column_56,
|
||||||
|
_column_44,
|
||||||
|
_column_45,
|
||||||
|
_column_46,
|
||||||
|
_column_47,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 mediaDownloads = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_downloads',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_50,
|
||||||
|
_column_51,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape2 signalIdentityKeyStores = Shape2(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_identity_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(device_id, name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_31,
|
||||||
|
_column_32,
|
||||||
|
_column_33,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 signalPreKeyStores = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_pre_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(pre_key_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_34,
|
||||||
|
_column_35,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape4 signalSenderKeyStores = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_sender_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(sender_key_name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_36,
|
||||||
|
_column_37,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 signalSessionStores = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_session_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(device_id, name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_31,
|
||||||
|
_column_32,
|
||||||
|
_column_38,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape14 signalContactPreKeys = Shape14(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_contact_pre_keys',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(contact_id, pre_key_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_58,
|
||||||
|
_column_34,
|
||||||
|
_column_35,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape15 signalContactSignedPreKeys = Shape15(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_contact_signed_pre_keys',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(contact_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_58,
|
||||||
|
_column_59,
|
||||||
|
_column_60,
|
||||||
|
_column_61,
|
||||||
|
_column_10,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape18 messageRetransmissions = Shape18(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'message_retransmissions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_62,
|
||||||
|
_column_63,
|
||||||
|
_column_64,
|
||||||
|
_column_65,
|
||||||
|
_column_66,
|
||||||
|
_column_69,
|
||||||
|
_column_67,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape18 extends i0.VersionedTable {
|
||||||
|
Shape18({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<int> get retransmissionId =>
|
||||||
|
columnsByName['retransmission_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get contactId =>
|
||||||
|
columnsByName['contact_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get messageId =>
|
||||||
|
columnsByName['message_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get plaintextContent =>
|
||||||
|
columnsByName['plaintext_content']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get pushData =>
|
||||||
|
columnsByName['push_data']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get encryptedHash =>
|
||||||
|
columnsByName['encrypted_hash']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<DateTime> get acknowledgeByServerAt =>
|
||||||
|
columnsByName['acknowledge_by_server_at']!
|
||||||
|
as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> _column_69(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<i2.Uint8List>('encrypted_hash', aliasedName, true,
|
||||||
|
type: i1.DriftSqlType.blob);
|
||||||
i0.MigrationStepWithVersion migrationSteps({
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
|
|
@ -2734,6 +3218,8 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||||
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
||||||
required Future<void> Function(i1.Migrator m, Schema11 schema) from10To11,
|
required Future<void> Function(i1.Migrator m, Schema11 schema) from10To11,
|
||||||
required Future<void> Function(i1.Migrator m, Schema12 schema) from11To12,
|
required Future<void> Function(i1.Migrator m, Schema12 schema) from11To12,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema13 schema) from12To13,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema14 schema) from13To14,
|
||||||
}) {
|
}) {
|
||||||
return (currentVersion, database) async {
|
return (currentVersion, database) async {
|
||||||
switch (currentVersion) {
|
switch (currentVersion) {
|
||||||
|
|
@ -2792,6 +3278,16 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||||
final migrator = i1.Migrator(database, schema);
|
final migrator = i1.Migrator(database, schema);
|
||||||
await from11To12(migrator, schema);
|
await from11To12(migrator, schema);
|
||||||
return 12;
|
return 12;
|
||||||
|
case 12:
|
||||||
|
final schema = Schema13(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from12To13(migrator, schema);
|
||||||
|
return 13;
|
||||||
|
case 13:
|
||||||
|
final schema = Schema14(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from13To14(migrator, schema);
|
||||||
|
return 14;
|
||||||
default:
|
default:
|
||||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
}
|
}
|
||||||
|
|
@ -2810,6 +3306,8 @@ i1.OnUpgrade stepByStep({
|
||||||
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
||||||
required Future<void> Function(i1.Migrator m, Schema11 schema) from10To11,
|
required Future<void> Function(i1.Migrator m, Schema11 schema) from10To11,
|
||||||
required Future<void> Function(i1.Migrator m, Schema12 schema) from11To12,
|
required Future<void> Function(i1.Migrator m, Schema12 schema) from11To12,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema13 schema) from12To13,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema14 schema) from13To14,
|
||||||
}) =>
|
}) =>
|
||||||
i0.VersionedSchema.stepByStepHelper(
|
i0.VersionedSchema.stepByStepHelper(
|
||||||
step: migrationSteps(
|
step: migrationSteps(
|
||||||
|
|
@ -2824,4 +3322,6 @@ i1.OnUpgrade stepByStep({
|
||||||
from9To10: from9To10,
|
from9To10: from9To10,
|
||||||
from10To11: from10To11,
|
from10To11: from10To11,
|
||||||
from11To12: from11To12,
|
from11To12: from11To12,
|
||||||
|
from12To13: from12To13,
|
||||||
|
from13To14: from13To14,
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ class MessageContent {
|
||||||
return FlameSyncContent.fromJson(json);
|
return FlameSyncContent.fromJson(json);
|
||||||
case MessageKind.ack:
|
case MessageKind.ack:
|
||||||
return AckContent.fromJson(json);
|
return AckContent.fromJson(json);
|
||||||
|
case MessageKind.signalDecryptError:
|
||||||
|
return SignalDecryptErrorContent.fromJson(json);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -222,6 +224,24 @@ class ReopenedMediaFileContent extends MessageContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SignalDecryptErrorContent extends MessageContent {
|
||||||
|
List<int> encryptedHash;
|
||||||
|
SignalDecryptErrorContent({required this.encryptedHash});
|
||||||
|
|
||||||
|
static SignalDecryptErrorContent fromJson(Map json) {
|
||||||
|
return SignalDecryptErrorContent(
|
||||||
|
encryptedHash: List<int>.from(json['encryptedHash']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map toJson() {
|
||||||
|
return {
|
||||||
|
'encryptedHash': encryptedHash,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AckContent extends MessageContent {
|
class AckContent extends MessageContent {
|
||||||
int? messageIdToAck;
|
int? messageIdToAck;
|
||||||
int retransIdToAck;
|
int retransIdToAck;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
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:fixnum/fixnum.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
|
@ -10,6 +11,8 @@ import 'package:twonly/src/model/json/message.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.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.pb.dart';
|
import 'package:twonly/src/model/protobuf/push_notification/push_notification.pb.dart';
|
||||||
|
import 'package:twonly/src/services/api/server_messages.dart'
|
||||||
|
show messageGetsAck;
|
||||||
import 'package:twonly/src/services/api/utils.dart';
|
import 'package:twonly/src/services/api/utils.dart';
|
||||||
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||||
import 'package:twonly/src/services/signal/encryption.signal.dart';
|
import 'package:twonly/src/services/signal/encryption.signal.dart';
|
||||||
|
|
@ -24,137 +27,138 @@ Future tryTransmitMessages() async {
|
||||||
|
|
||||||
if (retransIds.isEmpty) return;
|
if (retransIds.isEmpty) return;
|
||||||
|
|
||||||
bool filterPreKeys = false;
|
|
||||||
|
|
||||||
if (retransIds.length > 100) {
|
|
||||||
filterPreKeys = true; // just a workaround until I can fix the real issue :/
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final retransId in retransIds) {
|
for (final retransId in retransIds) {
|
||||||
sendRetransmitMessage(retransId, filterPreKeys: filterPreKeys);
|
sendRetransmitMessage(retransId, fromRetransmissionDb: true);
|
||||||
//twonlyDB.messageRetransmissionDao.deleteRetransmissionById(retransId);
|
//twonlyDB.messageRetransmissionDao.deleteRetransmissionById(retransId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future sendRetransmitMessage(int retransId,
|
Future sendRetransmitMessage(int retransId,
|
||||||
{bool filterPreKeys = false}) async {
|
{bool fromRetransmissionDb = false}) async {
|
||||||
MessageRetransmission? retrans = await twonlyDB.messageRetransmissionDao
|
try {
|
||||||
.getRetransmissionById(retransId)
|
MessageRetransmission? retrans = await twonlyDB.messageRetransmissionDao
|
||||||
.getSingleOrNull();
|
.getRetransmissionById(retransId)
|
||||||
|
.getSingleOrNull();
|
||||||
|
|
||||||
if (retrans == null) {
|
if (retrans == null) {
|
||||||
Log.error("$retransId not found in database");
|
Log.error("$retransId not found in database");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageJson json = MessageJson.fromJson(
|
MessageJson json = MessageJson.fromJson(
|
||||||
jsonDecode(
|
jsonDecode(
|
||||||
utf8.decode(
|
utf8.decode(
|
||||||
gzip.decode(retrans.plaintextContent),
|
gzip.decode(retrans.plaintextContent),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
DateTime timestampToCheck = DateTime.parse("2025-06-24T12:00:00");
|
||||||
if (filterPreKeys && json.kind == MessageKind.pushKey) {
|
if (json.timestamp.isBefore(timestampToCheck)) {
|
||||||
if (!retrans.willNotGetACKByUser) {
|
Log.info("Deleting retransmission because it is before the update...");
|
||||||
Log.error("Why is willNotGetACKByUser false????");
|
await twonlyDB.messageRetransmissionDao
|
||||||
|
.deleteRetransmissionById(retransId);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Log.info("Filtering preKeys: ${json.kind} to ${retrans.contactId}");
|
|
||||||
await twonlyDB.messageRetransmissionDao.deleteRetransmissionById(retransId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Log.info("Retransmitting: ${json.kind} to ${retrans.contactId}");
|
|
||||||
// if (json.kind
|
|
||||||
// .contains(MessageKind.pushKey.name)) {
|
|
||||||
// await twonlyDB.messageRetransmissionDao.deleteRetransmissionById(retransId);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
Contact? contact = await twonlyDB.contactsDao
|
Log.info("Retransmitting: ${json.kind} to ${retrans.contactId}");
|
||||||
.getContactByUserId(retrans.contactId)
|
|
||||||
.getSingleOrNull();
|
|
||||||
if (contact == null || contact.deleted) {
|
|
||||||
Log.warn("Contact deleted $retransId or not found in database.");
|
|
||||||
if (retrans.messageId != null) {
|
|
||||||
await twonlyDB.messagesDao.updateMessageByMessageId(
|
|
||||||
retrans.messageId!,
|
|
||||||
MessagesCompanion(errorWhileSending: Value(true)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint8List? encryptedBytes = await signalEncryptMessage(
|
Contact? contact = await twonlyDB.contactsDao
|
||||||
retrans.contactId,
|
.getContactByUserId(retrans.contactId)
|
||||||
retrans.plaintextContent,
|
.getSingleOrNull();
|
||||||
);
|
if (contact == null || contact.deleted) {
|
||||||
|
Log.warn("Contact deleted $retransId or not found in database.");
|
||||||
if (encryptedBytes == null) {
|
|
||||||
Log.error("Could not encrypt the message. Aborting and trying again.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result resp = await apiService.sendTextMessage(
|
|
||||||
retrans.contactId,
|
|
||||||
encryptedBytes,
|
|
||||||
retrans.pushData,
|
|
||||||
);
|
|
||||||
|
|
||||||
bool retry = true;
|
|
||||||
|
|
||||||
if (resp.isError) {
|
|
||||||
Log.error("Could not retransmit message.");
|
|
||||||
if (resp.error == ErrorCode.UserIdNotFound) {
|
|
||||||
retry = false;
|
|
||||||
if (retrans.messageId != null) {
|
if (retrans.messageId != null) {
|
||||||
await twonlyDB.messagesDao.updateMessageByMessageId(
|
await twonlyDB.messagesDao.updateMessageByMessageId(
|
||||||
retrans.messageId!,
|
retrans.messageId!,
|
||||||
MessagesCompanion(errorWhileSending: Value(true)),
|
MessagesCompanion(errorWhileSending: Value(true)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await twonlyDB.contactsDao.updateContact(
|
return;
|
||||||
retrans.contactId,
|
|
||||||
ContactsCompanion(deleted: Value(true)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (resp.isSuccess) {
|
Uint8List? encryptedBytes = await signalEncryptMessage(
|
||||||
retry = false;
|
retrans.contactId,
|
||||||
if (retrans.messageId != null) {
|
retrans.plaintextContent,
|
||||||
await twonlyDB.messagesDao.updateMessageByMessageId(
|
);
|
||||||
retrans.messageId!,
|
|
||||||
MessagesCompanion(
|
|
||||||
acknowledgeByServer: Value(true),
|
|
||||||
errorWhileSending: Value(false),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!retry) {
|
if (encryptedBytes == null) {
|
||||||
if (!retrans.willNotGetACKByUser && json.kind == MessageKind.pushKey) {
|
Log.error("Could not encrypt the message. Aborting and trying again.");
|
||||||
Log.error("Why is willNotGetACKByUser false????");
|
return;
|
||||||
}
|
}
|
||||||
if (retrans.willNotGetACKByUser ||
|
|
||||||
json.kind == MessageKind.pushKey ||
|
final encryptedHash = (await Sha256().hash(encryptedBytes)).bytes;
|
||||||
json.kind == MessageKind.ack) {
|
|
||||||
await twonlyDB.messageRetransmissionDao
|
await twonlyDB.messageRetransmissionDao.updateRetransmission(
|
||||||
.deleteRetransmissionById(retransId);
|
retransId,
|
||||||
} else {
|
MessageRetransmissionsCompanion(
|
||||||
await twonlyDB.messageRetransmissionDao.updateRetransmission(
|
encryptedHash: Value(Uint8List.fromList(encryptedHash)),
|
||||||
retransId,
|
),
|
||||||
MessageRetransmissionsCompanion(
|
);
|
||||||
acknowledgeByServerAt: Value(DateTime.now()),
|
|
||||||
),
|
Result resp = await apiService.sendTextMessage(
|
||||||
);
|
retrans.contactId,
|
||||||
|
encryptedBytes,
|
||||||
|
retrans.pushData,
|
||||||
|
);
|
||||||
|
|
||||||
|
bool retry = true;
|
||||||
|
|
||||||
|
if (resp.isError) {
|
||||||
|
Log.error("Could not retransmit message.");
|
||||||
|
if (resp.error == ErrorCode.UserIdNotFound) {
|
||||||
|
retry = false;
|
||||||
|
if (retrans.messageId != null) {
|
||||||
|
await twonlyDB.messagesDao.updateMessageByMessageId(
|
||||||
|
retrans.messageId!,
|
||||||
|
MessagesCompanion(errorWhileSending: Value(true)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await twonlyDB.contactsDao.updateContact(
|
||||||
|
retrans.contactId,
|
||||||
|
ContactsCompanion(deleted: Value(true)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resp.isSuccess) {
|
||||||
|
retry = false;
|
||||||
|
if (retrans.messageId != null) {
|
||||||
|
await twonlyDB.messagesDao.updateMessageByMessageId(
|
||||||
|
retrans.messageId!,
|
||||||
|
MessagesCompanion(
|
||||||
|
acknowledgeByServer: Value(true),
|
||||||
|
errorWhileSending: Value(false),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!retry) {
|
||||||
|
if (!messageGetsAck(json.kind)) {
|
||||||
|
await twonlyDB.messageRetransmissionDao
|
||||||
|
.deleteRetransmissionById(retransId);
|
||||||
|
} else {
|
||||||
|
await twonlyDB.messageRetransmissionDao.updateRetransmission(
|
||||||
|
retransId,
|
||||||
|
MessageRetransmissionsCompanion(
|
||||||
|
acknowledgeByServerAt: Value(DateTime.now()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Log.error("error resending message: $e");
|
||||||
|
await twonlyDB.messageRetransmissionDao.deleteRetransmissionById(retransId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypts and stores the message and then sends it in the background
|
// encrypts and stores the message and then sends it in the background
|
||||||
Future encryptAndSendMessageAsync(int? messageId, int userId, MessageJson msg,
|
Future encryptAndSendMessageAsync(
|
||||||
{PushNotification? pushNotification,
|
int? messageId,
|
||||||
bool willNotGetACKByUser = false}) async {
|
int userId,
|
||||||
|
MessageJson msg, {
|
||||||
|
PushNotification? pushNotification,
|
||||||
|
}) async {
|
||||||
if (gIsDemoUser) {
|
if (gIsDemoUser) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +174,6 @@ Future encryptAndSendMessageAsync(int? messageId, int userId, MessageJson msg,
|
||||||
messageId: Value(messageId),
|
messageId: Value(messageId),
|
||||||
plaintextContent: Value(Uint8List(0)),
|
plaintextContent: Value(Uint8List(0)),
|
||||||
pushData: Value(pushData),
|
pushData: Value(pushData),
|
||||||
willNotGetACKByUser: Value(willNotGetACKByUser),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
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:fixnum/fixnum.dart';
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
|
|
@ -22,7 +23,6 @@ import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||||
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
import 'package:twonly/src/services/notifications/setup.notifications.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/signal/identity.signal.dart';
|
||||||
import 'package:twonly/src/services/signal/prekeys.signal.dart';
|
|
||||||
import 'package:twonly/src/services/thumbnail.service.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/utils/misc.dart';
|
||||||
|
|
@ -60,15 +60,20 @@ Future handleServerMessage(server.ServerToClient msg) async {
|
||||||
DateTime lastSignalDecryptMessage = DateTime.now().subtract(Duration(hours: 1));
|
DateTime lastSignalDecryptMessage = DateTime.now().subtract(Duration(hours: 1));
|
||||||
DateTime lastPushKeyRequest = DateTime.now().subtract(Duration(hours: 1));
|
DateTime lastPushKeyRequest = DateTime.now().subtract(Duration(hours: 1));
|
||||||
|
|
||||||
|
bool messageGetsAck(MessageKind kind) {
|
||||||
|
return kind != MessageKind.pushKey && kind != MessageKind.ack;
|
||||||
|
}
|
||||||
|
|
||||||
Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||||
MessageJson? message = await signalDecryptMessage(fromUserId, body);
|
MessageJson? message = await signalDecryptMessage(fromUserId, body);
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
|
final encryptedHash = (await Sha256().hash(body)).bytes;
|
||||||
await encryptAndSendMessageAsync(
|
await encryptAndSendMessageAsync(
|
||||||
null,
|
null,
|
||||||
fromUserId,
|
fromUserId,
|
||||||
MessageJson(
|
MessageJson(
|
||||||
kind: MessageKind.signalDecryptError,
|
kind: MessageKind.signalDecryptError,
|
||||||
content: MessageContent(),
|
content: SignalDecryptErrorContent(encryptedHash: encryptedHash),
|
||||||
timestamp: DateTime.now(),
|
timestamp: DateTime.now(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -82,9 +87,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||||
|
|
||||||
Log.info("Got: ${message.kind} from $fromUserId");
|
Log.info("Got: ${message.kind} from $fromUserId");
|
||||||
|
|
||||||
if (message.kind != MessageKind.ack &&
|
if (messageGetsAck(message.kind) && message.retransId != null) {
|
||||||
message.kind != MessageKind.pushKey &&
|
|
||||||
message.retransId != null) {
|
|
||||||
Log.info("Sending ACK for ${message.kind}");
|
Log.info("Sending ACK for ${message.kind}");
|
||||||
|
|
||||||
/// ACK every message
|
/// ACK every message
|
||||||
|
|
@ -99,7 +102,6 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||||
retransIdToAck: message.retransId!),
|
retransIdToAck: message.retransId!),
|
||||||
timestamp: DateTime.now(),
|
timestamp: DateTime.now(),
|
||||||
),
|
),
|
||||||
willNotGetACKByUser: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,15 +126,15 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MessageKind.signalDecryptError:
|
case MessageKind.signalDecryptError:
|
||||||
if (lastSignalDecryptMessage
|
Log.error(
|
||||||
.isBefore(DateTime.now().subtract(Duration(seconds: 60)))) {
|
"Got signal decrypt error from other user! Sending all non ACK messages again.");
|
||||||
Log.error(
|
|
||||||
"Got signal decrypt error from other user! Sending all non ACK messages again.");
|
final content = message.content;
|
||||||
lastSignalDecryptMessage = DateTime.now();
|
if (content is SignalDecryptErrorContent) {
|
||||||
await twonlyDB.signalDao.deleteAllPreKeysByContactId(fromUserId);
|
await twonlyDB.messageRetransmissionDao.resetAckStatusFor(
|
||||||
await requestNewPrekeysForContact(fromUserId);
|
fromUserId,
|
||||||
await twonlyDB.messageRetransmissionDao
|
Uint8List.fromList(content.encryptedHash),
|
||||||
.resetAckStatusForAllMessages(fromUserId);
|
);
|
||||||
tryTransmitMessages();
|
tryTransmitMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,6 @@ Future sendNewPushKey(int userId, PushKey pushKey) async {
|
||||||
pushKey.createdAtUnixTimestamp.toInt(),
|
pushKey.createdAtUnixTimestamp.toInt(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
willNotGetACKByUser: true, // hot fix, this can be removed later...
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -8,7 +7,6 @@ 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/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/notifications/pushkeys.notifications.dart';
|
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
import 'package:twonly/src/services/fcm.service.dart';
|
import 'package:twonly/src/services/fcm.service.dart';
|
||||||
|
|
@ -29,13 +27,6 @@ class NotificationView extends StatelessWidget {
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.settingsNotifyTroubleshooting),
|
title: Text(context.lang.settingsNotifyTroubleshooting),
|
||||||
subtitle: Text(context.lang.settingsNotifyTroubleshootingDesc),
|
subtitle: Text(context.lang.settingsNotifyTroubleshootingDesc),
|
||||||
onLongPress: (kDebugMode)
|
|
||||||
? () async {
|
|
||||||
await twonlyDB.messageRetransmissionDao
|
|
||||||
.resetAckStatusForAllMessages(537506372);
|
|
||||||
tryTransmitMessages();
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await initFCMAfterAuthenticated();
|
await initFCMAfterAuthenticated();
|
||||||
String? storedToken = await FlutterSecureStorage()
|
String? storedToken = await FlutterSecureStorage()
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ description: "twonly, a privacy-friendly way to connect with friends through sec
|
||||||
# Prevent accidental publishing to pub.dev.
|
# Prevent accidental publishing to pub.dev.
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
|
|
||||||
version: 0.0.43+43
|
version: 0.0.45+45
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.6.0
|
sdk: ^3.6.0
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ import 'schema_v9.dart' as v9;
|
||||||
import 'schema_v10.dart' as v10;
|
import 'schema_v10.dart' as v10;
|
||||||
import 'schema_v11.dart' as v11;
|
import 'schema_v11.dart' as v11;
|
||||||
import 'schema_v12.dart' as v12;
|
import 'schema_v12.dart' as v12;
|
||||||
|
import 'schema_v13.dart' as v13;
|
||||||
|
import 'schema_v14.dart' as v14;
|
||||||
|
|
||||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||||
@override
|
@override
|
||||||
|
|
@ -44,10 +46,14 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
||||||
return v11.DatabaseAtV11(db);
|
return v11.DatabaseAtV11(db);
|
||||||
case 12:
|
case 12:
|
||||||
return v12.DatabaseAtV12(db);
|
return v12.DatabaseAtV12(db);
|
||||||
|
case 13:
|
||||||
|
return v13.DatabaseAtV13(db);
|
||||||
|
case 14:
|
||||||
|
return v14.DatabaseAtV14(db);
|
||||||
default:
|
default:
|
||||||
throw MissingSchemaException(version, versions);
|
throw MissingSchemaException(version, versions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3845
test/drift/twonly_database/generated/schema_v13.dart
Normal file
3845
test/drift/twonly_database/generated/schema_v13.dart
Normal file
File diff suppressed because it is too large
Load diff
3881
test/drift/twonly_database/generated/schema_v14.dart
Normal file
3881
test/drift/twonly_database/generated/schema_v14.dart
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue