mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 02:12:13 +00:00
handling server messages
This commit is contained in:
parent
6517473603
commit
f2493a2b56
27 changed files with 13369 additions and 70 deletions
|
|
@ -1,13 +1,12 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:twonly/core/frb_generated.dart';
|
||||
import 'package:twonly/main.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
setUpAll(() async => RustLib.init());
|
||||
testWidgets('Can call rust function', (tester) async {
|
||||
await tester.pumpWidget(const MyApp());
|
||||
expect(find.textContaining('Result: `Hello, Tom!`'), findsOneWidget);
|
||||
});
|
||||
// testWidgets('Can call rust function', (tester) async {
|
||||
// await tester.pumpWidget(const MyApp());
|
||||
// expect(find.textContaining('Result: `Hello, Tom!`'), findsOneWidget);
|
||||
// });
|
||||
}
|
||||
|
|
@ -22,11 +22,11 @@ class FlutterUserDiscovery {
|
|||
receivedVersion: receivedVersion,
|
||||
);
|
||||
|
||||
static Future<void> handleUserDiscoveryMessages({
|
||||
static Future<void> handleNewMessages({
|
||||
required PlatformInt64 contactId,
|
||||
required List<Uint8List> messages,
|
||||
}) => RustLib.instance.api
|
||||
.crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessages(
|
||||
.crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleNewMessages(
|
||||
contactId: contactId,
|
||||
messages: messages,
|
||||
);
|
||||
|
|
@ -42,7 +42,7 @@ class FlutterUserDiscovery {
|
|||
publicKey: publicKey,
|
||||
);
|
||||
|
||||
static Future<bool> shouldRequestNewMessages({
|
||||
static Future<Uint8List?> shouldRequestNewMessages({
|
||||
required PlatformInt64 contactId,
|
||||
required List<int> version,
|
||||
}) => RustLib.instance.api
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
|||
String get codegenVersion => '2.12.0';
|
||||
|
||||
@override
|
||||
int get rustContentHash => 523281685;
|
||||
int get rustContentHash => -630534473;
|
||||
|
||||
static const kDefaultExternalLibraryLoaderConfig =
|
||||
ExternalLibraryLoaderConfig(
|
||||
|
|
@ -92,7 +92,7 @@ abstract class RustLibApi extends BaseApi {
|
|||
});
|
||||
|
||||
Future<void>
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessages({
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleNewMessages({
|
||||
required PlatformInt64 contactId,
|
||||
required List<Uint8List> messages,
|
||||
});
|
||||
|
|
@ -104,7 +104,7 @@ abstract class RustLibApi extends BaseApi {
|
|||
required List<int> publicKey,
|
||||
});
|
||||
|
||||
Future<bool>
|
||||
Future<Uint8List?>
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryShouldRequestNewMessages({
|
||||
required PlatformInt64 contactId,
|
||||
required List<int> version,
|
||||
|
|
@ -228,7 +228,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
|
||||
@override
|
||||
Future<void>
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessages({
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleNewMessages({
|
||||
required PlatformInt64 contactId,
|
||||
required List<Uint8List> messages,
|
||||
}) {
|
||||
|
|
@ -250,7 +250,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
decodeErrorData: sse_decode_AnyhowException,
|
||||
),
|
||||
constMeta:
|
||||
kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessagesConstMeta,
|
||||
kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleNewMessagesConstMeta,
|
||||
argValues: [contactId, messages],
|
||||
apiImpl: this,
|
||||
),
|
||||
|
|
@ -258,9 +258,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
}
|
||||
|
||||
TaskConstMeta
|
||||
get kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleUserDiscoveryMessagesConstMeta =>
|
||||
get kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryHandleNewMessagesConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: 'flutter_user_discovery_handle_user_discovery_messages',
|
||||
debugName: 'flutter_user_discovery_handle_new_messages',
|
||||
argNames: ['contactId', 'messages'],
|
||||
);
|
||||
|
||||
|
|
@ -305,7 +305,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
);
|
||||
|
||||
@override
|
||||
Future<bool>
|
||||
Future<Uint8List?>
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryShouldRequestNewMessages({
|
||||
required PlatformInt64 contactId,
|
||||
required List<int> version,
|
||||
|
|
@ -324,7 +324,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
);
|
||||
},
|
||||
codec: SseCodec(
|
||||
decodeSuccessData: sse_decode_bool,
|
||||
decodeSuccessData: sse_decode_opt_list_prim_u_8_strict,
|
||||
decodeErrorData: sse_decode_AnyhowException,
|
||||
),
|
||||
constMeta:
|
||||
|
|
|
|||
|
|
@ -216,10 +216,10 @@ class UserDiscoveryCallbacks {
|
|||
await twonlyDB
|
||||
.into(twonlyDB.userDiscoveryAnnouncedUsers)
|
||||
.insertOnConflictUpdate(
|
||||
UserDiscoveryAnnouncedUser(
|
||||
announcedUserId: announcedUser.userId,
|
||||
announcedPublicKey: announcedUser.publicKey,
|
||||
publicId: announcedUser.publicId,
|
||||
UserDiscoveryAnnouncedUsersCompanion(
|
||||
announcedUserId: Value(announcedUser.userId),
|
||||
announcedPublicKey: Value(announcedUser.publicKey),
|
||||
publicId: Value(announcedUser.publicId),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,4 +18,90 @@ class UserDiscoveryDao extends DatabaseAccessor<TwonlyDB>
|
|||
// of this object.
|
||||
// ignore: matching_super_parameters
|
||||
UserDiscoveryDao(super.db);
|
||||
|
||||
/// 1. Get count for contacts which are in announced but not in the contacts table
|
||||
|
||||
/// Returns all users which are not yet in the contacts table but have no data loaded (e.g. Avatar, username and display name)
|
||||
Future<List<UserDiscoveryAnnouncedUser>>
|
||||
getNewAnnouncementsWithoutData() async {
|
||||
final query =
|
||||
select(userDiscoveryAnnouncedUsers).join([
|
||||
leftOuterJoin(
|
||||
contacts,
|
||||
contacts.userId.equalsExp(
|
||||
userDiscoveryAnnouncedUsers.announcedUserId,
|
||||
),
|
||||
),
|
||||
])
|
||||
// Apply filters:
|
||||
// 1. The user must NOT exist in the contacts table
|
||||
// 2. The username must be null
|
||||
..where(
|
||||
contacts.userId.isNull() &
|
||||
userDiscoveryAnnouncedUsers.username.isNull(),
|
||||
);
|
||||
|
||||
return (await query.get())
|
||||
.map((row) => row.readTable(userDiscoveryAnnouncedUsers))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<Map<UserDiscoveryAnnouncedUser, List<(int, DateTime?)>>>
|
||||
getAnnouncedUsersWithRelations() async {
|
||||
final query = select(userDiscoveryAnnouncedUsers).join([
|
||||
innerJoin(
|
||||
userDiscoveryUserRelations,
|
||||
userDiscoveryUserRelations.announcedUserId.equalsExp(
|
||||
userDiscoveryAnnouncedUsers.announcedUserId,
|
||||
),
|
||||
),
|
||||
]);
|
||||
|
||||
final rows = await query.get();
|
||||
|
||||
final results = <UserDiscoveryAnnouncedUser, List<(int, DateTime?)>>{};
|
||||
|
||||
for (final row in rows) {
|
||||
final user = row.readTable(userDiscoveryAnnouncedUsers);
|
||||
final relation = row.readTable(userDiscoveryUserRelations);
|
||||
|
||||
final relationData = (
|
||||
relation.fromContactId,
|
||||
relation.publicKeyVerifiedTimestamp,
|
||||
);
|
||||
|
||||
if (!results.containsKey(user)) {
|
||||
results[user] = [];
|
||||
}
|
||||
results[user]!.add(relationData);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
Stream<int> watchNewAnnouncementsWithDataCount() {
|
||||
final countExp = userDiscoveryAnnouncedUsers.announcedUserId.count();
|
||||
|
||||
final query = selectOnly(userDiscoveryAnnouncedUsers)
|
||||
..addColumns([countExp])
|
||||
..where(
|
||||
// Filters: Has a username AND has not been shown to the user yet
|
||||
userDiscoveryAnnouncedUsers.username.isNotNull() &
|
||||
userDiscoveryAnnouncedUsers.wasShownToTheUser.equals(false) &
|
||||
userDiscoveryAnnouncedUsers.isHidden.equals(false),
|
||||
);
|
||||
|
||||
return query.watchSingle().map((row) => row.read(countExp) ?? 0);
|
||||
}
|
||||
|
||||
Future<void> updateAnnouncedUser(
|
||||
int announcedUserId,
|
||||
UserDiscoveryAnnouncedUsersCompanion updatedValues,
|
||||
) async {
|
||||
await (update(
|
||||
userDiscoveryAnnouncedUsers,
|
||||
)..where((c) => c.announcedUserId.equals(announcedUserId))).write(
|
||||
updatedValues,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2713
lib/src/database/schemas/twonly_db/drift_schema_v14.json
Normal file
2713
lib/src/database/schemas/twonly_db/drift_schema_v14.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,13 @@ class UserDiscoveryAnnouncedUsers extends Table {
|
|||
BlobColumn get announcedPublicKey => blob()();
|
||||
IntColumn get publicId => integer().unique()();
|
||||
|
||||
// When a new user got announced this data will be requested without adding the users to the contacts...
|
||||
TextColumn get username => text().nullable()();
|
||||
|
||||
BoolColumn get wasShownToTheUser =>
|
||||
boolean().withDefault(const Constant(false))();
|
||||
BoolColumn get isHidden => boolean().withDefault(const Constant(false))();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {announcedUserId};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
TwonlyDB.forTesting(DatabaseConnection super.connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 13;
|
||||
int get schemaVersion => 14;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return driftDatabase(
|
||||
|
|
@ -191,6 +191,20 @@ class TwonlyDB extends _$TwonlyDB {
|
|||
schema.contacts.mediaSendCounter,
|
||||
);
|
||||
},
|
||||
from13To14: (m, schema) async {
|
||||
await m.addColumn(
|
||||
schema.userDiscoveryAnnouncedUsers,
|
||||
schema.userDiscoveryAnnouncedUsers.wasShownToTheUser,
|
||||
);
|
||||
await m.addColumn(
|
||||
schema.userDiscoveryAnnouncedUsers,
|
||||
schema.userDiscoveryAnnouncedUsers.isHidden,
|
||||
);
|
||||
await m.addColumn(
|
||||
schema.userDiscoveryAnnouncedUsers,
|
||||
schema.userDiscoveryAnnouncedUsers.username,
|
||||
);
|
||||
},
|
||||
)(m, from, to);
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9537,11 +9537,55 @@ class $UserDiscoveryAnnouncedUsersTable extends UserDiscoveryAnnouncedUsers
|
|||
requiredDuringInsert: true,
|
||||
defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE'),
|
||||
);
|
||||
static const VerificationMeta _usernameMeta = const VerificationMeta(
|
||||
'username',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<String> username = GeneratedColumn<String>(
|
||||
'username',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _wasShownToTheUserMeta = const VerificationMeta(
|
||||
'wasShownToTheUser',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<bool> wasShownToTheUser = GeneratedColumn<bool>(
|
||||
'was_shown_to_the_user',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.bool,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||
'CHECK ("was_shown_to_the_user" IN (0, 1))',
|
||||
),
|
||||
defaultValue: const Constant(false),
|
||||
);
|
||||
static const VerificationMeta _isHiddenMeta = const VerificationMeta(
|
||||
'isHidden',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<bool> isHidden = GeneratedColumn<bool>(
|
||||
'is_hidden',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.bool,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||
'CHECK ("is_hidden" IN (0, 1))',
|
||||
),
|
||||
defaultValue: const Constant(false),
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
announcedUserId,
|
||||
announcedPublicKey,
|
||||
publicId,
|
||||
username,
|
||||
wasShownToTheUser,
|
||||
isHidden,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
|
|
@ -9583,6 +9627,27 @@ class $UserDiscoveryAnnouncedUsersTable extends UserDiscoveryAnnouncedUsers
|
|||
} else if (isInserting) {
|
||||
context.missing(_publicIdMeta);
|
||||
}
|
||||
if (data.containsKey('username')) {
|
||||
context.handle(
|
||||
_usernameMeta,
|
||||
username.isAcceptableOrUnknown(data['username']!, _usernameMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('was_shown_to_the_user')) {
|
||||
context.handle(
|
||||
_wasShownToTheUserMeta,
|
||||
wasShownToTheUser.isAcceptableOrUnknown(
|
||||
data['was_shown_to_the_user']!,
|
||||
_wasShownToTheUserMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('is_hidden')) {
|
||||
context.handle(
|
||||
_isHiddenMeta,
|
||||
isHidden.isAcceptableOrUnknown(data['is_hidden']!, _isHiddenMeta),
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -9607,6 +9672,18 @@ class $UserDiscoveryAnnouncedUsersTable extends UserDiscoveryAnnouncedUsers
|
|||
DriftSqlType.int,
|
||||
data['${effectivePrefix}public_id'],
|
||||
)!,
|
||||
username: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}username'],
|
||||
),
|
||||
wasShownToTheUser: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.bool,
|
||||
data['${effectivePrefix}was_shown_to_the_user'],
|
||||
)!,
|
||||
isHidden: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.bool,
|
||||
data['${effectivePrefix}is_hidden'],
|
||||
)!,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -9621,10 +9698,16 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
final int announcedUserId;
|
||||
final Uint8List announcedPublicKey;
|
||||
final int publicId;
|
||||
final String? username;
|
||||
final bool wasShownToTheUser;
|
||||
final bool isHidden;
|
||||
const UserDiscoveryAnnouncedUser({
|
||||
required this.announcedUserId,
|
||||
required this.announcedPublicKey,
|
||||
required this.publicId,
|
||||
this.username,
|
||||
required this.wasShownToTheUser,
|
||||
required this.isHidden,
|
||||
});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
|
|
@ -9632,6 +9715,11 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
map['announced_user_id'] = Variable<int>(announcedUserId);
|
||||
map['announced_public_key'] = Variable<Uint8List>(announcedPublicKey);
|
||||
map['public_id'] = Variable<int>(publicId);
|
||||
if (!nullToAbsent || username != null) {
|
||||
map['username'] = Variable<String>(username);
|
||||
}
|
||||
map['was_shown_to_the_user'] = Variable<bool>(wasShownToTheUser);
|
||||
map['is_hidden'] = Variable<bool>(isHidden);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -9640,6 +9728,11 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
announcedUserId: Value(announcedUserId),
|
||||
announcedPublicKey: Value(announcedPublicKey),
|
||||
publicId: Value(publicId),
|
||||
username: username == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(username),
|
||||
wasShownToTheUser: Value(wasShownToTheUser),
|
||||
isHidden: Value(isHidden),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -9654,6 +9747,9 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
json['announcedPublicKey'],
|
||||
),
|
||||
publicId: serializer.fromJson<int>(json['publicId']),
|
||||
username: serializer.fromJson<String?>(json['username']),
|
||||
wasShownToTheUser: serializer.fromJson<bool>(json['wasShownToTheUser']),
|
||||
isHidden: serializer.fromJson<bool>(json['isHidden']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
|
@ -9663,6 +9759,9 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
'announcedUserId': serializer.toJson<int>(announcedUserId),
|
||||
'announcedPublicKey': serializer.toJson<Uint8List>(announcedPublicKey),
|
||||
'publicId': serializer.toJson<int>(publicId),
|
||||
'username': serializer.toJson<String?>(username),
|
||||
'wasShownToTheUser': serializer.toJson<bool>(wasShownToTheUser),
|
||||
'isHidden': serializer.toJson<bool>(isHidden),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -9670,10 +9769,16 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
int? announcedUserId,
|
||||
Uint8List? announcedPublicKey,
|
||||
int? publicId,
|
||||
Value<String?> username = const Value.absent(),
|
||||
bool? wasShownToTheUser,
|
||||
bool? isHidden,
|
||||
}) => UserDiscoveryAnnouncedUser(
|
||||
announcedUserId: announcedUserId ?? this.announcedUserId,
|
||||
announcedPublicKey: announcedPublicKey ?? this.announcedPublicKey,
|
||||
publicId: publicId ?? this.publicId,
|
||||
username: username.present ? username.value : this.username,
|
||||
wasShownToTheUser: wasShownToTheUser ?? this.wasShownToTheUser,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
);
|
||||
UserDiscoveryAnnouncedUser copyWithCompanion(
|
||||
UserDiscoveryAnnouncedUsersCompanion data,
|
||||
|
|
@ -9686,6 +9791,11 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
? data.announcedPublicKey.value
|
||||
: this.announcedPublicKey,
|
||||
publicId: data.publicId.present ? data.publicId.value : this.publicId,
|
||||
username: data.username.present ? data.username.value : this.username,
|
||||
wasShownToTheUser: data.wasShownToTheUser.present
|
||||
? data.wasShownToTheUser.value
|
||||
: this.wasShownToTheUser,
|
||||
isHidden: data.isHidden.present ? data.isHidden.value : this.isHidden,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -9694,7 +9804,10 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
return (StringBuffer('UserDiscoveryAnnouncedUser(')
|
||||
..write('announcedUserId: $announcedUserId, ')
|
||||
..write('announcedPublicKey: $announcedPublicKey, ')
|
||||
..write('publicId: $publicId')
|
||||
..write('publicId: $publicId, ')
|
||||
..write('username: $username, ')
|
||||
..write('wasShownToTheUser: $wasShownToTheUser, ')
|
||||
..write('isHidden: $isHidden')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -9704,6 +9817,9 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
announcedUserId,
|
||||
$driftBlobEquality.hash(announcedPublicKey),
|
||||
publicId,
|
||||
username,
|
||||
wasShownToTheUser,
|
||||
isHidden,
|
||||
);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
|
|
@ -9714,7 +9830,10 @@ class UserDiscoveryAnnouncedUser extends DataClass
|
|||
other.announcedPublicKey,
|
||||
this.announcedPublicKey,
|
||||
) &&
|
||||
other.publicId == this.publicId);
|
||||
other.publicId == this.publicId &&
|
||||
other.username == this.username &&
|
||||
other.wasShownToTheUser == this.wasShownToTheUser &&
|
||||
other.isHidden == this.isHidden);
|
||||
}
|
||||
|
||||
class UserDiscoveryAnnouncedUsersCompanion
|
||||
|
|
@ -9722,27 +9841,42 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
final Value<int> announcedUserId;
|
||||
final Value<Uint8List> announcedPublicKey;
|
||||
final Value<int> publicId;
|
||||
final Value<String?> username;
|
||||
final Value<bool> wasShownToTheUser;
|
||||
final Value<bool> isHidden;
|
||||
const UserDiscoveryAnnouncedUsersCompanion({
|
||||
this.announcedUserId = const Value.absent(),
|
||||
this.announcedPublicKey = const Value.absent(),
|
||||
this.publicId = const Value.absent(),
|
||||
this.username = const Value.absent(),
|
||||
this.wasShownToTheUser = const Value.absent(),
|
||||
this.isHidden = const Value.absent(),
|
||||
});
|
||||
UserDiscoveryAnnouncedUsersCompanion.insert({
|
||||
this.announcedUserId = const Value.absent(),
|
||||
required Uint8List announcedPublicKey,
|
||||
required int publicId,
|
||||
this.username = const Value.absent(),
|
||||
this.wasShownToTheUser = const Value.absent(),
|
||||
this.isHidden = const Value.absent(),
|
||||
}) : announcedPublicKey = Value(announcedPublicKey),
|
||||
publicId = Value(publicId);
|
||||
static Insertable<UserDiscoveryAnnouncedUser> custom({
|
||||
Expression<int>? announcedUserId,
|
||||
Expression<Uint8List>? announcedPublicKey,
|
||||
Expression<int>? publicId,
|
||||
Expression<String>? username,
|
||||
Expression<bool>? wasShownToTheUser,
|
||||
Expression<bool>? isHidden,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (announcedUserId != null) 'announced_user_id': announcedUserId,
|
||||
if (announcedPublicKey != null)
|
||||
'announced_public_key': announcedPublicKey,
|
||||
if (publicId != null) 'public_id': publicId,
|
||||
if (username != null) 'username': username,
|
||||
if (wasShownToTheUser != null) 'was_shown_to_the_user': wasShownToTheUser,
|
||||
if (isHidden != null) 'is_hidden': isHidden,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -9750,11 +9884,17 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
Value<int>? announcedUserId,
|
||||
Value<Uint8List>? announcedPublicKey,
|
||||
Value<int>? publicId,
|
||||
Value<String?>? username,
|
||||
Value<bool>? wasShownToTheUser,
|
||||
Value<bool>? isHidden,
|
||||
}) {
|
||||
return UserDiscoveryAnnouncedUsersCompanion(
|
||||
announcedUserId: announcedUserId ?? this.announcedUserId,
|
||||
announcedPublicKey: announcedPublicKey ?? this.announcedPublicKey,
|
||||
publicId: publicId ?? this.publicId,
|
||||
username: username ?? this.username,
|
||||
wasShownToTheUser: wasShownToTheUser ?? this.wasShownToTheUser,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -9772,6 +9912,15 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
if (publicId.present) {
|
||||
map['public_id'] = Variable<int>(publicId.value);
|
||||
}
|
||||
if (username.present) {
|
||||
map['username'] = Variable<String>(username.value);
|
||||
}
|
||||
if (wasShownToTheUser.present) {
|
||||
map['was_shown_to_the_user'] = Variable<bool>(wasShownToTheUser.value);
|
||||
}
|
||||
if (isHidden.present) {
|
||||
map['is_hidden'] = Variable<bool>(isHidden.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -9780,7 +9929,10 @@ class UserDiscoveryAnnouncedUsersCompanion
|
|||
return (StringBuffer('UserDiscoveryAnnouncedUsersCompanion(')
|
||||
..write('announcedUserId: $announcedUserId, ')
|
||||
..write('announcedPublicKey: $announcedPublicKey, ')
|
||||
..write('publicId: $publicId')
|
||||
..write('publicId: $publicId, ')
|
||||
..write('username: $username, ')
|
||||
..write('wasShownToTheUser: $wasShownToTheUser, ')
|
||||
..write('isHidden: $isHidden')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
|
@ -19690,12 +19842,18 @@ typedef $$UserDiscoveryAnnouncedUsersTableCreateCompanionBuilder =
|
|||
Value<int> announcedUserId,
|
||||
required Uint8List announcedPublicKey,
|
||||
required int publicId,
|
||||
Value<String?> username,
|
||||
Value<bool> wasShownToTheUser,
|
||||
Value<bool> isHidden,
|
||||
});
|
||||
typedef $$UserDiscoveryAnnouncedUsersTableUpdateCompanionBuilder =
|
||||
UserDiscoveryAnnouncedUsersCompanion Function({
|
||||
Value<int> announcedUserId,
|
||||
Value<Uint8List> announcedPublicKey,
|
||||
Value<int> publicId,
|
||||
Value<String?> username,
|
||||
Value<bool> wasShownToTheUser,
|
||||
Value<bool> isHidden,
|
||||
});
|
||||
|
||||
final class $$UserDiscoveryAnnouncedUsersTableReferences
|
||||
|
|
@ -19769,6 +19927,21 @@ class $$UserDiscoveryAnnouncedUsersTableFilterComposer
|
|||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get username => $composableBuilder(
|
||||
column: $table.username,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<bool> get wasShownToTheUser => $composableBuilder(
|
||||
column: $table.wasShownToTheUser,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<bool> get isHidden => $composableBuilder(
|
||||
column: $table.isHidden,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
Expression<bool> userDiscoveryUserRelationsRefs(
|
||||
Expression<bool> Function($$UserDiscoveryUserRelationsTableFilterComposer f)
|
||||
f,
|
||||
|
|
@ -19820,6 +19993,21 @@ class $$UserDiscoveryAnnouncedUsersTableOrderingComposer
|
|||
column: $table.publicId,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get username => $composableBuilder(
|
||||
column: $table.username,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<bool> get wasShownToTheUser => $composableBuilder(
|
||||
column: $table.wasShownToTheUser,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<bool> get isHidden => $composableBuilder(
|
||||
column: $table.isHidden,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$UserDiscoveryAnnouncedUsersTableAnnotationComposer
|
||||
|
|
@ -19844,6 +20032,17 @@ class $$UserDiscoveryAnnouncedUsersTableAnnotationComposer
|
|||
GeneratedColumn<int> get publicId =>
|
||||
$composableBuilder(column: $table.publicId, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<String> get username =>
|
||||
$composableBuilder(column: $table.username, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<bool> get wasShownToTheUser => $composableBuilder(
|
||||
column: $table.wasShownToTheUser,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
GeneratedColumn<bool> get isHidden =>
|
||||
$composableBuilder(column: $table.isHidden, builder: (column) => column);
|
||||
|
||||
Expression<T> userDiscoveryUserRelationsRefs<T extends Object>(
|
||||
Expression<T> Function(
|
||||
$$UserDiscoveryUserRelationsTableAnnotationComposer a,
|
||||
|
|
@ -19919,20 +20118,32 @@ class $$UserDiscoveryAnnouncedUsersTableTableManager
|
|||
Value<int> announcedUserId = const Value.absent(),
|
||||
Value<Uint8List> announcedPublicKey = const Value.absent(),
|
||||
Value<int> publicId = const Value.absent(),
|
||||
Value<String?> username = const Value.absent(),
|
||||
Value<bool> wasShownToTheUser = const Value.absent(),
|
||||
Value<bool> isHidden = const Value.absent(),
|
||||
}) => UserDiscoveryAnnouncedUsersCompanion(
|
||||
announcedUserId: announcedUserId,
|
||||
announcedPublicKey: announcedPublicKey,
|
||||
publicId: publicId,
|
||||
username: username,
|
||||
wasShownToTheUser: wasShownToTheUser,
|
||||
isHidden: isHidden,
|
||||
),
|
||||
createCompanionCallback:
|
||||
({
|
||||
Value<int> announcedUserId = const Value.absent(),
|
||||
required Uint8List announcedPublicKey,
|
||||
required int publicId,
|
||||
Value<String?> username = const Value.absent(),
|
||||
Value<bool> wasShownToTheUser = const Value.absent(),
|
||||
Value<bool> isHidden = const Value.absent(),
|
||||
}) => UserDiscoveryAnnouncedUsersCompanion.insert(
|
||||
announcedUserId: announcedUserId,
|
||||
announcedPublicKey: announcedPublicKey,
|
||||
publicId: publicId,
|
||||
username: username,
|
||||
wasShownToTheUser: wasShownToTheUser,
|
||||
isHidden: isHidden,
|
||||
),
|
||||
withReferenceMapper: (p0) => p0
|
||||
.map(
|
||||
|
|
|
|||
|
|
@ -6932,6 +6932,454 @@ i1.GeneratedColumn<int> _column_229(String aliasedName) =>
|
|||
$customConstraints: 'NOT NULL DEFAULT 0',
|
||||
defaultValue: const i1.CustomExpression('0'),
|
||||
);
|
||||
|
||||
final class Schema14 extends i0.VersionedSchema {
|
||||
Schema14({required super.database}) : super(version: 14);
|
||||
@override
|
||||
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||
contacts,
|
||||
groups,
|
||||
mediaFiles,
|
||||
messages,
|
||||
messageHistories,
|
||||
reactions,
|
||||
groupMembers,
|
||||
receipts,
|
||||
receivedReceipts,
|
||||
signalIdentityKeyStores,
|
||||
signalPreKeyStores,
|
||||
signalSenderKeyStores,
|
||||
signalSessionStores,
|
||||
messageActions,
|
||||
groupHistories,
|
||||
keyVerifications,
|
||||
verificationTokens,
|
||||
userDiscoveryAnnouncedUsers,
|
||||
userDiscoveryUserRelations,
|
||||
userDiscoveryOtherPromotions,
|
||||
userDiscoveryOwnPromotions,
|
||||
userDiscoveryShares,
|
||||
];
|
||||
late final Shape47 contacts = Shape47(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'contacts',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(user_id)'],
|
||||
columns: [
|
||||
_column_106,
|
||||
_column_107,
|
||||
_column_108,
|
||||
_column_109,
|
||||
_column_110,
|
||||
_column_111,
|
||||
_column_112,
|
||||
_column_113,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_116,
|
||||
_column_117,
|
||||
_column_118,
|
||||
_column_211,
|
||||
_column_228,
|
||||
_column_229,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape23 groups = Shape23(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'groups',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(group_id)'],
|
||||
columns: [
|
||||
_column_119,
|
||||
_column_120,
|
||||
_column_121,
|
||||
_column_122,
|
||||
_column_123,
|
||||
_column_124,
|
||||
_column_125,
|
||||
_column_126,
|
||||
_column_127,
|
||||
_column_128,
|
||||
_column_129,
|
||||
_column_130,
|
||||
_column_131,
|
||||
_column_132,
|
||||
_column_133,
|
||||
_column_134,
|
||||
_column_118,
|
||||
_column_135,
|
||||
_column_136,
|
||||
_column_137,
|
||||
_column_138,
|
||||
_column_139,
|
||||
_column_140,
|
||||
_column_141,
|
||||
_column_142,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape36 mediaFiles = Shape36(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'media_files',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(media_id)'],
|
||||
columns: [
|
||||
_column_143,
|
||||
_column_144,
|
||||
_column_145,
|
||||
_column_146,
|
||||
_column_147,
|
||||
_column_148,
|
||||
_column_149,
|
||||
_column_207,
|
||||
_column_150,
|
||||
_column_151,
|
||||
_column_152,
|
||||
_column_153,
|
||||
_column_154,
|
||||
_column_155,
|
||||
_column_156,
|
||||
_column_157,
|
||||
_column_118,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape25 messages = Shape25(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'messages',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(message_id)'],
|
||||
columns: [
|
||||
_column_158,
|
||||
_column_159,
|
||||
_column_160,
|
||||
_column_144,
|
||||
_column_161,
|
||||
_column_162,
|
||||
_column_163,
|
||||
_column_164,
|
||||
_column_165,
|
||||
_column_153,
|
||||
_column_166,
|
||||
_column_167,
|
||||
_column_168,
|
||||
_column_169,
|
||||
_column_118,
|
||||
_column_170,
|
||||
_column_171,
|
||||
_column_172,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape26 messageHistories = Shape26(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'message_histories',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_173,
|
||||
_column_174,
|
||||
_column_175,
|
||||
_column_161,
|
||||
_column_118,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape27 reactions = Shape27(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'reactions',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(message_id, sender_id, emoji)'],
|
||||
columns: [_column_174, _column_176, _column_177, _column_118],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape38 groupMembers = Shape38(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'group_members',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(group_id, contact_id)'],
|
||||
columns: [
|
||||
_column_158,
|
||||
_column_178,
|
||||
_column_179,
|
||||
_column_180,
|
||||
_column_209,
|
||||
_column_210,
|
||||
_column_181,
|
||||
_column_118,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape37 receipts = Shape37(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'receipts',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(receipt_id)'],
|
||||
columns: [
|
||||
_column_182,
|
||||
_column_183,
|
||||
_column_184,
|
||||
_column_185,
|
||||
_column_186,
|
||||
_column_208,
|
||||
_column_187,
|
||||
_column_188,
|
||||
_column_189,
|
||||
_column_190,
|
||||
_column_191,
|
||||
_column_118,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape30 receivedReceipts = Shape30(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'received_receipts',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(receipt_id)'],
|
||||
columns: [_column_182, _column_118],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape31 signalIdentityKeyStores = Shape31(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_identity_key_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(device_id, name)'],
|
||||
columns: [_column_192, _column_193, _column_194, _column_118],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape32 signalPreKeyStores = Shape32(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_pre_key_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(pre_key_id)'],
|
||||
columns: [_column_195, _column_196, _column_118],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape11 signalSenderKeyStores = Shape11(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_sender_key_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(sender_key_name)'],
|
||||
columns: [_column_197, _column_198],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape33 signalSessionStores = Shape33(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_session_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(device_id, name)'],
|
||||
columns: [_column_192, _column_193, _column_199, _column_118],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape34 messageActions = Shape34(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'message_actions',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(message_id, contact_id, type)'],
|
||||
columns: [_column_174, _column_183, _column_144, _column_200],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape35 groupHistories = Shape35(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'group_histories',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(group_history_id)'],
|
||||
columns: [
|
||||
_column_201,
|
||||
_column_158,
|
||||
_column_202,
|
||||
_column_203,
|
||||
_column_204,
|
||||
_column_205,
|
||||
_column_206,
|
||||
_column_144,
|
||||
_column_200,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape40 keyVerifications = Shape40(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'key_verifications',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(contact_id)'],
|
||||
columns: [_column_183, _column_144, _column_118],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape41 verificationTokens = Shape41(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'verification_tokens',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [_column_212, _column_213, _column_118],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape48 userDiscoveryAnnouncedUsers = Shape48(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_discovery_announced_users',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(announced_user_id)'],
|
||||
columns: [
|
||||
_column_214,
|
||||
_column_215,
|
||||
_column_216,
|
||||
_column_230,
|
||||
_column_231,
|
||||
_column_232,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape43 userDiscoveryUserRelations = Shape43(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_discovery_user_relations',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(announced_user_id, from_contact_id)'],
|
||||
columns: [_column_217, _column_218, _column_219],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape44 userDiscoveryOtherPromotions = Shape44(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_discovery_other_promotions',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: ['PRIMARY KEY(from_contact_id, promotion_id)'],
|
||||
columns: [
|
||||
_column_218,
|
||||
_column_220,
|
||||
_column_221,
|
||||
_column_222,
|
||||
_column_223,
|
||||
_column_219,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape45 userDiscoveryOwnPromotions = Shape45(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_discovery_own_promotions',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [_column_224, _column_183, _column_225],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape46 userDiscoveryShares = Shape46(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_discovery_shares',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [_column_226, _column_227, _column_175],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
}
|
||||
|
||||
class Shape48 extends i0.VersionedTable {
|
||||
Shape48({required super.source, required super.alias}) : super.aliased();
|
||||
i1.GeneratedColumn<int> get announcedUserId =>
|
||||
columnsByName['announced_user_id']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<i2.Uint8List> get announcedPublicKey =>
|
||||
columnsByName['announced_public_key']!
|
||||
as i1.GeneratedColumn<i2.Uint8List>;
|
||||
i1.GeneratedColumn<int> get publicId =>
|
||||
columnsByName['public_id']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<String> get username =>
|
||||
columnsByName['username']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<int> get wasShownToTheUser =>
|
||||
columnsByName['was_shown_to_the_user']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get isHidden =>
|
||||
columnsByName['is_hidden']! as i1.GeneratedColumn<int>;
|
||||
}
|
||||
|
||||
i1.GeneratedColumn<String> _column_230(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>(
|
||||
'username',
|
||||
aliasedName,
|
||||
true,
|
||||
type: i1.DriftSqlType.string,
|
||||
$customConstraints: 'NULL',
|
||||
);
|
||||
i1.GeneratedColumn<int> _column_231(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>(
|
||||
'was_shown_to_the_user',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i1.DriftSqlType.int,
|
||||
$customConstraints:
|
||||
'NOT NULL DEFAULT 0 CHECK (was_shown_to_the_user IN (0, 1))',
|
||||
defaultValue: const i1.CustomExpression('0'),
|
||||
);
|
||||
i1.GeneratedColumn<int> _column_232(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>(
|
||||
'is_hidden',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i1.DriftSqlType.int,
|
||||
$customConstraints: 'NOT NULL DEFAULT 0 CHECK (is_hidden IN (0, 1))',
|
||||
defaultValue: const i1.CustomExpression('0'),
|
||||
);
|
||||
i0.MigrationStepWithVersion migrationSteps({
|
||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||
|
|
@ -6945,6 +7393,7 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||
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, Schema13 schema) from12To13,
|
||||
required Future<void> Function(i1.Migrator m, Schema14 schema) from13To14,
|
||||
}) {
|
||||
return (currentVersion, database) async {
|
||||
switch (currentVersion) {
|
||||
|
|
@ -7008,6 +7457,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||
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:
|
||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||
}
|
||||
|
|
@ -7027,6 +7481,7 @@ i1.OnUpgrade stepByStep({
|
|||
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, Schema13 schema) from12To13,
|
||||
required Future<void> Function(i1.Migrator m, Schema14 schema) from13To14,
|
||||
}) => i0.VersionedSchema.stepByStepHelper(
|
||||
step: migrationSteps(
|
||||
from1To2: from1To2,
|
||||
|
|
@ -7041,5 +7496,6 @@ i1.OnUpgrade stepByStep({
|
|||
from10To11: from10To11,
|
||||
from11To12: from11To12,
|
||||
from12To13: from12To13,
|
||||
from13To14: from13To14,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3141,6 +3141,12 @@ abstract class AppLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'When the typing indicator is turned off, you can\'t see when others are typing a message.'**
|
||||
String get settingsTypingIndicationSubtitle;
|
||||
|
||||
/// No description provided for @scanQrOrShow.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Scan / Show QR'**
|
||||
String get scanQrOrShow;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -1761,4 +1761,7 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@override
|
||||
String get settingsTypingIndicationSubtitle =>
|
||||
'Bei deaktivierten Tipp-Indikatoren kannst du nicht sehen, wenn andere gerade eine Nachricht tippen.';
|
||||
|
||||
@override
|
||||
String get scanQrOrShow => 'QR scannen / anzeigen';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1749,4 +1749,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get settingsTypingIndicationSubtitle =>
|
||||
'When the typing indicator is turned off, you can\'t see when others are typing a message.';
|
||||
|
||||
@override
|
||||
String get scanQrOrShow => 'Scan / Show QR';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1749,4 +1749,7 @@ class AppLocalizationsSv extends AppLocalizations {
|
|||
@override
|
||||
String get settingsTypingIndicationSubtitle =>
|
||||
'When the typing indicator is turned off, you can\'t see when others are typing a message.';
|
||||
|
||||
@override
|
||||
String get scanQrOrShow => 'Scan / Show QR';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
|||
import 'package:twonly/src/services/signal/identity.signal.dart';
|
||||
import 'package:twonly/src/services/signal/utils.signal.dart';
|
||||
import 'package:twonly/src/services/subscription.service.dart';
|
||||
import 'package:twonly/src/services/user_discovery.service.dart';
|
||||
import 'package:twonly/src/utils/keyvalue.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
|
|
@ -100,6 +101,7 @@ class ApiService {
|
|||
unawaited(retransmitAllMessages());
|
||||
unawaited(tryDownloadAllMediaFiles());
|
||||
unawaited(reuploadMediaFiles());
|
||||
|
||||
twonlyDB.markUpdated();
|
||||
unawaited(syncFlameCounters());
|
||||
unawaited(setupNotificationWithUsers());
|
||||
|
|
@ -108,6 +110,8 @@ class ApiService {
|
|||
unawaited(fetchMissingGroupPublicKey());
|
||||
unawaited(checkForDeletedUsernames());
|
||||
|
||||
unawaited(UserDiscoveryService.checkForNewAnnouncedUsers());
|
||||
|
||||
if (gUser.userStudyParticipantsToken != null) {
|
||||
// In case the user participates in the user study, call the handler after authenticated, to be sure there is a internet connection
|
||||
unawaited(handleUserStudyUpload());
|
||||
|
|
|
|||
78
lib/src/services/api/client2client/user_discovery.c2c.dart
Normal file
78
lib/src/services/api/client2client/user_discovery.c2c.dart
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||
import 'package:twonly/src/services/api/messages.dart';
|
||||
import 'package:twonly/src/services/user_discovery.service.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
|
||||
Future<void> checkForUserDiscoveryChanges(
|
||||
int fromUserId,
|
||||
List<int> receivedVersion,
|
||||
) async {
|
||||
final currentVersion = await UserDiscoveryService.shouldRequestNewMessages(
|
||||
fromUserId,
|
||||
receivedVersion,
|
||||
);
|
||||
|
||||
if (currentVersion != null) {
|
||||
await sendCipherText(
|
||||
fromUserId,
|
||||
EncryptedContent(
|
||||
userDiscoveryRequest: EncryptedContent_UserDiscoveryRequest(
|
||||
currentVersion: currentVersion.toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleUserDiscoveryRequest(
|
||||
int fromUserId,
|
||||
EncryptedContent_UserDiscoveryRequest request,
|
||||
) async {
|
||||
if (!gUser.isUserDiscoveryEnabled) {
|
||||
Log.warn('Got a user discovery request while it is disabled');
|
||||
return;
|
||||
}
|
||||
final contact = await twonlyDB.contactsDao.getContactById(fromUserId);
|
||||
if (contact == null) return;
|
||||
|
||||
if (contact.mediaSendCounter < gUser.minimumRequiredImagesExchanged) {
|
||||
Log.warn(
|
||||
'Got a request to update user discovery, but mediaSendCounter (${contact.mediaSendCounter}) < ${gUser.minimumRequiredImagesExchanged}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final newMessages = await UserDiscoveryService.getNewMessages(
|
||||
fromUserId,
|
||||
request.currentVersion,
|
||||
);
|
||||
if (newMessages != null && newMessages.isNotEmpty) {
|
||||
await sendCipherText(
|
||||
fromUserId,
|
||||
EncryptedContent(
|
||||
userDiscoveryUpdate: EncryptedContent_UserDiscoveryUpdate(
|
||||
messages: newMessages,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Log.info('Got update request, but there are no new updates for the user');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleUserDiscoveryUpdate(
|
||||
int fromUserId,
|
||||
EncryptedContent_UserDiscoveryUpdate update,
|
||||
) async {
|
||||
if (!gUser.isUserDiscoveryEnabled) {
|
||||
Log.warn('Got a user discovery update while it is disabled');
|
||||
return;
|
||||
}
|
||||
await UserDiscoveryService.handleNewMessages(
|
||||
fromUserId,
|
||||
update.messages.map(Uint8List.fromList).toList(),
|
||||
);
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import 'package:twonly/src/model/protobuf/client/generated/push_notification.pb.
|
|||
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||
import 'package:twonly/src/services/signal/encryption.signal.dart';
|
||||
import 'package:twonly/src/services/signal/session.signal.dart';
|
||||
import 'package:twonly/src/services/user_discovery.service.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
|
||||
|
|
@ -344,6 +345,17 @@ Future<(Uint8List, Uint8List?)?> sendCipherText(
|
|||
}
|
||||
encryptedContent.senderProfileCounter = Int64(gUser.avatarCounter);
|
||||
|
||||
if (gUser.isUserDiscoveryEnabled) {
|
||||
final contact = await twonlyDB.contactsDao.getContactById(contactId);
|
||||
if (contact != null &&
|
||||
contact.mediaSendCounter >= gUser.minimumRequiredImagesExchanged) {
|
||||
final version = await UserDiscoveryService.getCurrentVersion();
|
||||
if (version != null) {
|
||||
encryptedContent.senderUserDiscoveryVersion = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final response = pb.Message()
|
||||
..type = pb.Message_Type.CIPHERTEXT
|
||||
..encryptedContent = encryptedContent.writeToBuffer();
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import 'package:twonly/src/services/api/client2client/prekeys.c2c.dart';
|
|||
import 'package:twonly/src/services/api/client2client/pushkeys.c2c.dart';
|
||||
import 'package:twonly/src/services/api/client2client/reaction.c2c.dart';
|
||||
import 'package:twonly/src/services/api/client2client/text_message.c2c.dart';
|
||||
import 'package:twonly/src/services/api/client2client/user_discovery.c2c.dart';
|
||||
import 'package:twonly/src/services/api/messages.dart';
|
||||
import 'package:twonly/src/services/group.services.dart';
|
||||
import 'package:twonly/src/services/notifications/background.notifications.dart';
|
||||
|
|
@ -262,6 +263,12 @@ Future<(EncryptedContent?, PlaintextContent?)> handleEncryptedMessage(
|
|||
await twonlyDB.receiptsDao.markMessagesForRetry(fromUserId);
|
||||
|
||||
final senderProfileCounter = await checkForProfileUpdate(fromUserId, content);
|
||||
if (gUser.isUserDiscoveryEnabled && content.hasSenderUserDiscoveryVersion()) {
|
||||
await checkForUserDiscoveryChanges(
|
||||
fromUserId,
|
||||
content.senderUserDiscoveryVersion,
|
||||
);
|
||||
}
|
||||
|
||||
if (content.hasContactRequest()) {
|
||||
if (!await handleContactRequest(fromUserId, content.contactRequest)) {
|
||||
|
|
@ -291,6 +298,22 @@ Future<(EncryptedContent?, PlaintextContent?)> handleEncryptedMessage(
|
|||
return (null, null);
|
||||
}
|
||||
|
||||
if (content.hasUserDiscoveryRequest()) {
|
||||
await handleUserDiscoveryRequest(
|
||||
fromUserId,
|
||||
content.userDiscoveryRequest,
|
||||
);
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
if (content.hasUserDiscoveryUpdate()) {
|
||||
await handleUserDiscoveryUpdate(
|
||||
fromUserId,
|
||||
content.userDiscoveryUpdate,
|
||||
);
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
if (content.hasPushKeys()) {
|
||||
await handlePushKey(fromUserId, content.pushKeys);
|
||||
return (null, null);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,43 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:twonly/core/bridge/wrapper/user_discovery.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/database/twonly.db.dart';
|
||||
import 'package:twonly/src/model/protobuf/client/generated/user_discovery/types.pb.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/qr.dart';
|
||||
import 'package:twonly/src/utils/storage.dart';
|
||||
|
||||
class UserDiscoveryService {
|
||||
static Future<void> checkForNewAnnouncedUsers() async {
|
||||
final announcedUsers = await twonlyDB.userDiscoveryDao
|
||||
.getNewAnnouncementsWithoutData();
|
||||
|
||||
for (final announcedUser in announcedUsers) {
|
||||
final userdata = await apiService.getUserById(
|
||||
announcedUser.announcedUserId,
|
||||
);
|
||||
if (userdata == null) continue;
|
||||
if (userdata.publicIdentityKey !=
|
||||
announcedUser.announcedPublicKey.toList()) {
|
||||
Log.error(
|
||||
'Server delivered a different public key then received from the announcement.',
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
Log.info('Updating the username from the announced user');
|
||||
|
||||
// Updating the username, so the data will not be requested again..
|
||||
await twonlyDB.userDiscoveryDao.updateAnnouncedUser(
|
||||
announcedUser.announcedUserId,
|
||||
UserDiscoveryAnnouncedUsersCompanion(
|
||||
username: Value(utf8.decode(userdata.username)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> initializeOrUpdate({
|
||||
required int threshold,
|
||||
required int minimumRequiredImagesExchanged,
|
||||
|
|
@ -44,6 +74,50 @@ class UserDiscoveryService {
|
|||
return UserDiscoveryVersion.fromBuffer(version);
|
||||
}
|
||||
|
||||
static Future<Uint8List?> shouldRequestNewMessages(
|
||||
int fromUserId,
|
||||
List<int> receivedVersion,
|
||||
) async {
|
||||
try {
|
||||
return await FlutterUserDiscovery.shouldRequestNewMessages(
|
||||
contactId: fromUserId,
|
||||
version: receivedVersion,
|
||||
);
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<List<Uint8List>?> getNewMessages(
|
||||
int fromUserId,
|
||||
List<int> receivedVersion,
|
||||
) async {
|
||||
try {
|
||||
return await FlutterUserDiscovery.getNewMessages(
|
||||
contactId: fromUserId,
|
||||
receivedVersion: receivedVersion,
|
||||
);
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> handleNewMessages(
|
||||
int fromUserId,
|
||||
List<Uint8List> messages,
|
||||
) async {
|
||||
try {
|
||||
return await FlutterUserDiscovery.handleNewMessages(
|
||||
contactId: fromUserId,
|
||||
messages: messages,
|
||||
);
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> disable() async {
|
||||
await updateUserdata((u) {
|
||||
u.isUserDiscoveryEnabled = false;
|
||||
|
|
|
|||
|
|
@ -167,17 +167,17 @@ class _SearchUsernameView extends State<AddNewUserView> {
|
|||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: IconButton(
|
||||
onPressed: () =>
|
||||
context.push(Routes.settingsPublicProfile),
|
||||
icon: const FaIcon(FontAwesomeIcons.qrcode),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
OutlinedButton.icon(
|
||||
onPressed: () => context.push(Routes.settingsPublicProfile),
|
||||
icon: const FaIcon(FontAwesomeIcons.qrcode),
|
||||
label: Text(context.lang.scanQrOrShow),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (contacts.isNotEmpty)
|
||||
HeadLineComponent(
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
GlobalKey searchForOtherUsers = GlobalKey();
|
||||
bool showFeedbackShortcut = false;
|
||||
|
||||
int _countContactRequest = 0;
|
||||
int _countAnnouncedUsers = 0;
|
||||
late StreamSubscription<int?> _countContactRequestStream;
|
||||
late StreamSubscription<int?> _countAnnouncedStream;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
initAsync();
|
||||
|
|
@ -52,6 +57,24 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
});
|
||||
});
|
||||
|
||||
_countContactRequestStream = twonlyDB.contactsDao
|
||||
.watchContactsRequestedCount()
|
||||
.listen((update) {
|
||||
if (update != null) {
|
||||
setState(() {
|
||||
_countContactRequest = update;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_countContactRequestStream = twonlyDB.userDiscoveryDao
|
||||
.watchNewAnnouncementsWithDataCount()
|
||||
.listen((update) {
|
||||
setState(() {
|
||||
_countAnnouncedUsers = update;
|
||||
});
|
||||
});
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final changeLog = await rootBundle.loadString('CHANGELOG.md');
|
||||
final changeLogHash = (await compute(
|
||||
|
|
@ -80,6 +103,8 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
@override
|
||||
void dispose() {
|
||||
_contactsSub.cancel();
|
||||
_countContactRequestStream.cancel();
|
||||
_countAnnouncedStream.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -132,23 +157,38 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
),
|
||||
actions: [
|
||||
const FeedbackIconButton(),
|
||||
StreamBuilder(
|
||||
stream: twonlyDB.contactsDao.watchContactsRequestedCount(),
|
||||
builder: (context, snapshot) {
|
||||
var count = 0;
|
||||
if (snapshot.hasData && snapshot.data != null) {
|
||||
count = snapshot.data!;
|
||||
}
|
||||
return NotificationBadge(
|
||||
count: count.toString(),
|
||||
child: IconButton(
|
||||
key: searchForOtherUsers,
|
||||
icon: const FaIcon(FontAwesomeIcons.userPlus, size: 18),
|
||||
onPressed: () => context.push(Routes.chatsAddNewUser),
|
||||
Stack(
|
||||
children: [
|
||||
if (_countAnnouncedUsers + _countContactRequest > 0)
|
||||
Positioned.fill(
|
||||
child: Center(
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: context.color.primary,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
Center(
|
||||
child: NotificationBadge(
|
||||
count: (_countAnnouncedUsers + _countContactRequest)
|
||||
.toString(),
|
||||
child: IconButton(
|
||||
color: (_countAnnouncedUsers + _countContactRequest > 0)
|
||||
? Colors.black
|
||||
: null,
|
||||
key: searchForOtherUsers,
|
||||
icon: const FaIcon(FontAwesomeIcons.userPlus, size: 18),
|
||||
onPressed: () => context.push(Routes.chatsAddNewUser),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await context.push(Routes.settings);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@ impl FlutterUserDiscovery {
|
|||
.await?)
|
||||
}
|
||||
|
||||
pub async fn should_request_new_messages(contact_id: i64, version: &[u8]) -> Result<bool> {
|
||||
pub async fn should_request_new_messages(
|
||||
contact_id: i64,
|
||||
version: &[u8],
|
||||
) -> Result<Option<Vec<u8>>> {
|
||||
Ok(get_twonly_flutter()?
|
||||
.user_discovery
|
||||
.get()
|
||||
|
|
@ -47,15 +50,12 @@ impl FlutterUserDiscovery {
|
|||
.await?)
|
||||
}
|
||||
|
||||
pub async fn handle_user_discovery_messages(
|
||||
contact_id: i64,
|
||||
messages: Vec<Vec<u8>>,
|
||||
) -> Result<()> {
|
||||
pub async fn handle_new_messages(contact_id: i64, messages: Vec<Vec<u8>>) -> Result<()> {
|
||||
Ok(get_twonly_flutter()?
|
||||
.user_discovery
|
||||
.get()
|
||||
.await
|
||||
.handle_user_discovery_messages(contact_id, messages)
|
||||
.handle_new_messages(contact_id, messages)
|
||||
.await?)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
|
|||
default_rust_auto_opaque = RustAutoOpaqueMoi,
|
||||
);
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0";
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 523281685;
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -630534473;
|
||||
|
||||
// Section: executor
|
||||
|
||||
|
|
@ -77,19 +77,19 @@ let api_received_version = <Vec<u8>>::sse_decode(&mut deserializer);deserializer
|
|||
})().await)
|
||||
} })
|
||||
}
|
||||
fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_user_discovery_messages_impl(
|
||||
fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_new_messages_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||
rust_vec_len_: i32,
|
||||
data_len_: i32,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec,_,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_user_discovery_handle_user_discovery_messages", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec,_,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_user_discovery_handle_new_messages", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || {
|
||||
let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) };
|
||||
let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
||||
let api_contact_id = <i64>::sse_decode(&mut deserializer);
|
||||
let api_messages = <Vec<Vec<u8>>>::sse_decode(&mut deserializer);deserializer.end(); move |context| async move {
|
||||
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move {
|
||||
let output_ok = crate::bridge::wrapper::user_discovery::FlutterUserDiscovery::handle_user_discovery_messages(api_contact_id, api_messages).await?; Ok(output_ok)
|
||||
let output_ok = crate::bridge::wrapper::user_discovery::FlutterUserDiscovery::handle_new_messages(api_contact_id, api_messages).await?; Ok(output_ok)
|
||||
})().await)
|
||||
} })
|
||||
}
|
||||
|
|
@ -900,7 +900,7 @@ fn pde_ffi_dispatcher_primary_impl(
|
|||
match func_id {
|
||||
1 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl(port, ptr, rust_vec_len, data_len),
|
||||
2 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
3 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_user_discovery_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
3 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
4 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_initialize_or_update_impl(port, ptr, rust_vec_len, data_len),
|
||||
5 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_should_request_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
6 => wire__crate__bridge__callbacks__init_flutter_callbacks_impl(port, ptr, rust_vec_len, data_len),
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
&self,
|
||||
contact_id: UserID,
|
||||
version: &[u8],
|
||||
) -> Result<bool> {
|
||||
) -> Result<Option<Vec<u8>>> {
|
||||
let received_version = UserDiscoveryVersion::decode(version)?;
|
||||
let stored_version = match self.store.get_contact_version(contact_id).await? {
|
||||
Some(buf) => UserDiscoveryVersion::decode(buf.as_slice())?,
|
||||
|
|
@ -247,8 +247,13 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
stored.promotion = %stored_version.promotion,
|
||||
"Comparing version numbers"
|
||||
);
|
||||
Ok(received_version.announcement > stored_version.announcement
|
||||
|| received_version.promotion > stored_version.promotion)
|
||||
if received_version.announcement > stored_version.announcement
|
||||
|| received_version.promotion > stored_version.promotion
|
||||
{
|
||||
Ok(Some(stored_version.encode_to_vec()))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn get_contact_version(&self, contact_id: UserID) -> Result<Option<Vec<u8>>> {
|
||||
|
|
@ -257,7 +262,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
|
||||
/// Returns the latest version for this discovery.
|
||||
/// Before calling this function the application must sure that contact_id is qualified to be announced.
|
||||
pub async fn handle_user_discovery_messages(
|
||||
pub async fn handle_new_messages(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
messages: Vec<Vec<u8>>,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ async fn assert_new_messages<S: UserDiscoveryStore>(
|
|||
assert_eq!(
|
||||
to.1.should_request_new_messages(from.0 as UserID, to_received_version)
|
||||
.await
|
||||
.unwrap(),
|
||||
.unwrap()
|
||||
.is_some(),
|
||||
has_new_messages
|
||||
);
|
||||
}
|
||||
|
|
@ -53,7 +54,8 @@ async fn request_and_handle_messages<S: UserDiscoveryStore>(
|
|||
assert_eq!(
|
||||
to.1.should_request_new_messages(from.0 as UserID, to_received_version)
|
||||
.await
|
||||
.unwrap(),
|
||||
.unwrap()
|
||||
.is_some(),
|
||||
true
|
||||
);
|
||||
|
||||
|
|
@ -72,7 +74,7 @@ async fn request_and_handle_messages<S: UserDiscoveryStore>(
|
|||
|
||||
assert!(new_messages.len() <= messages_count);
|
||||
|
||||
to.1.handle_user_discovery_messages(from.0 as UserID, new_messages)
|
||||
to.1.handle_new_messages(from.0 as UserID, new_messages)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -82,7 +84,8 @@ async fn request_and_handle_messages<S: UserDiscoveryStore>(
|
|||
&from.1.get_current_version().await.unwrap()
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
.unwrap()
|
||||
.is_some(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import 'schema_v10.dart' as v10;
|
|||
import 'schema_v11.dart' as v11;
|
||||
import 'schema_v12.dart' as v12;
|
||||
import 'schema_v13.dart' as v13;
|
||||
import 'schema_v14.dart' as v14;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
|
|
@ -48,10 +49,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
|||
return v12.DatabaseAtV12(db);
|
||||
case 13:
|
||||
return v13.DatabaseAtV13(db);
|
||||
case 14:
|
||||
return v14.DatabaseAtV14(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
|
||||
}
|
||||
|
|
|
|||
9556
test/drift/twonly_db/generated/schema_v14.dart
Normal file
9556
test/drift/twonly_db/generated/schema_v14.dart
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue