diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5888736d..008bc369 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## 0.3.7
+
+- Fix: Multiple UI issues
+
+## 0.3.6
+
+- Improve: Visibility of the verification badge
+
+## 0.3.5
+
+- Fix: Performance issue caused by an out-of-sync Signal session
+- Fix: Multiple smaller bug fixes
+
## 0.3.3
- Fix: Multiple UI issues
diff --git a/README.md b/README.md
index 0b1e68ee..c4ba2a2a 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,6 @@ If you decide to give twonly a try, please keep in mind that it is still in its
- End-to-End encryption using the [Signal Protocol](https://de.wikipedia.org/wiki/Signal-Protokoll)
- Open Source and can be downloaded directly from GitHub
- No email or phone number required to register
-- Privacy friendly - Everything is stored on the device
- The backend is hosted exclusively in Europe
## Roadmap
@@ -43,7 +42,6 @@ If you decide to give twonly a try, please keep in mind that it is still in its
### Currently
- Focus on user-friendliness so that people enjoy using the app
- - User discovery without a phone number
- Passwordless recovery without a phone number
- Implementation of features so that Snapchat can actually be replaced
- E2EE cloud backup of memories
@@ -63,36 +61,9 @@ If you discover a security issue in twonly, please adhere to the coordinated vul
us your report to security@twonly.eu. We also offer for critical security issues a small bug bounties, but we can not
guarantee a bounty currently :/
-
-
-## Development
-
-
-Setup Instructions (macOS)
-
-## Building
-
-Some dependencies are downloaded directly from the source as there are some new changes which are not yet published on
-pub.dev or because they require some special installation.
-
-```bash
-git submodule update --init --recursive
-
-cd dependencies/flutter_zxing
-git submodule update --init --recursive
-./scripts/update_ios_macos_src.s
-```
-
-## Debugging files
-
-```bash
-run-as eu.twonly.testing ls /data/user/0/eu.twonly.testing/
-```
-
-
+## Contribution
+Currently there are still some core features and rewrites open I want to do like the switch to the MLS protocol involving a huge rewrite in Rust. Because of this, contributions are currently not wanted. You can still view the code (if you find any security issues please contact me!). Also, issues are currently closed. If you find a bug, please use the in-app option as there you can upload your debug log which helps a lot.
## Signing Keys
diff --git a/lib/app.dart b/lib/app.dart
index c327d972..8a0dc086 100644
--- a/lib/app.dart
+++ b/lib/app.dart
@@ -5,9 +5,13 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/locator.dart';
+import 'package:twonly/src/constants/keyvalue.keys.dart';
+import 'package:twonly/src/constants/routes.keys.dart';
import 'package:twonly/src/localization/generated/app_localizations.dart';
+import 'package:twonly/src/model/json/onboarding_state.model.dart';
import 'package:twonly/src/providers/routing.provider.dart';
import 'package:twonly/src/providers/settings.provider.dart';
+import 'package:twonly/src/utils/keyvalue.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/pow.dart';
import 'package:twonly/src/visual/components/app_outdated.comp.dart';
@@ -18,7 +22,7 @@ import 'package:twonly/src/visual/views/home.view.dart';
import 'package:twonly/src/visual/views/onboarding/onboarding.view.dart';
import 'package:twonly/src/visual/views/onboarding/register.view.dart';
import 'package:twonly/src/visual/views/onboarding/setup.view.dart';
-import 'package:twonly/src/visual/views/recovery.view.dart';
+import 'package:twonly/src/visual/views/recovery_from_secure_storage.view.dart';
import 'package:twonly/src/visual/views/unlock_twonly.view.dart';
class App extends StatefulWidget {
@@ -151,6 +155,10 @@ class _AppMainWidgetState extends State {
Future initAsync() async {
Log.info('AppWidgetState: initAsync started');
+ final onboardingState = await KeyValueStore.getModel(
+ KeyValueKeys.onboardingState,
+ );
+ _showOnboarding = !onboardingState.hasOnboardingFinished;
if (userService.isUserCreated) {
if (_initialPage != 0) {
final count = await twonlyDB.contactsDao.getContactsCount();
@@ -180,8 +188,19 @@ class _AppMainWidgetState extends State {
} else {
_proofOfWork = (null, disabled);
}
+
+ if (onboardingState.hasStartedPasswordlessRecovery ||
+ onboardingState.emailRecoveryRequested) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ routerProvider.push(Routes.recoverPasswordless);
+ });
+ }
}
+ // await PasswordlessRecoveryService.handleRecoveryLink(
+ // 'https://me.twonly.eu/r/#7fdb8f08-0927-4e44-8761-038993414e48/1p7SKEzpxE3wSW9FQw60EUI4OpSW2U4EskdXLw8xg48',
+ // );
+
setState(() {
_isLoaded = true;
});
@@ -223,9 +242,13 @@ class _AppMainWidgetState extends State {
}
} else if (_showOnboarding) {
child = OnboardingView(
- callbackOnSuccess: () => setState(() {
- _showOnboarding = false;
- }),
+ callbackOnSuccess: () async {
+ await KeyValueStore.update(
+ key: KeyValueKeys.onboardingState,
+ update: (state) => state.hasOnboardingFinished = true,
+ );
+ if (mounted) setState(() => _showOnboarding = false);
+ },
);
} else {
child = RegisterView(
diff --git a/lib/core/bridge/callbacks/user_discovery.dart b/lib/core/bridge/callbacks/user_discovery.dart
new file mode 100644
index 00000000..569a0013
--- /dev/null
+++ b/lib/core/bridge/callbacks/user_discovery.dart
@@ -0,0 +1,173 @@
+// This file is automatically generated, so please do not edit it.
+// @generated by `flutter_rust_bridge`@ 2.12.0.
+
+// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
+
+import '../../bridge.dart';
+import '../../frb_generated.dart';
+import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
+
+// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`
+
+class UserDiscoveryStoreFlutter {
+ const UserDiscoveryStoreFlutter();
+
+ Future getAnnouncedUserByPublicId({
+ required PlatformInt64 publicId,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetAnnouncedUserByPublicId(
+ that: this,
+ publicId: publicId,
+ );
+
+ Future getConfig() => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetConfig(
+ that: this,
+ );
+
+ Future getContactPromotion({
+ required PlatformInt64 contactId,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactPromotion(
+ that: this,
+ contactId: contactId,
+ );
+
+ Future getContactVersion({
+ required PlatformInt64 contactId,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactVersion(
+ that: this,
+ contactId: contactId,
+ );
+
+ Future> getOtherPromotionsByPublicId({
+ required PlatformInt64 publicId,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOtherPromotionsByPublicId(
+ that: this,
+ publicId: publicId,
+ );
+
+ Future> getOwnPromotionsAfterVersion({
+ required int version,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOwnPromotionsAfterVersion(
+ that: this,
+ version: version,
+ );
+
+ Future getShareForContact({
+ required PlatformInt64 contactId,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetShareForContact(
+ that: this,
+ contactId: contactId,
+ );
+
+ Future pushNewUserRelation({
+ required PlatformInt64 fromContactId,
+ required AnnouncedUser announcedUser,
+ PlatformInt64? publicKeyVerifiedTimestamp,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushNewUserRelation(
+ that: this,
+ fromContactId: fromContactId,
+ announcedUser: announcedUser,
+ publicKeyVerifiedTimestamp: publicKeyVerifiedTimestamp,
+ );
+
+ Future pushOwnPromotionAndClearOldVersion({
+ required PlatformInt64 contactId,
+ required int version,
+ required List promotion,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushOwnPromotionAndClearOldVersion(
+ that: this,
+ contactId: contactId,
+ version: version,
+ promotion: promotion,
+ );
+
+ Future setContactVersion({
+ required PlatformInt64 contactId,
+ required List update,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetContactVersion(
+ that: this,
+ contactId: contactId,
+ update: update,
+ );
+
+ Future setShares({required List shares}) => RustLib
+ .instance
+ .api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetShares(
+ that: this,
+ shares: shares,
+ );
+
+ Future storeOtherPromotion({
+ required OtherPromotion promotion,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterStoreOtherPromotion(
+ that: this,
+ promotion: promotion,
+ );
+
+ Future updateConfig({required String update}) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterUpdateConfig(
+ that: this,
+ update: update,
+ );
+
+ @override
+ int get hashCode => 0;
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is UserDiscoveryStoreFlutter && runtimeType == other.runtimeType;
+}
+
+class UserDiscoveryUtilsFlutter {
+ const UserDiscoveryUtilsFlutter();
+
+ Future signData({required List inputData}) => RustLib
+ .instance
+ .api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterSignData(
+ that: this,
+ inputData: inputData,
+ );
+
+ Future verifySignature({
+ required List inputData,
+ required List pubkey,
+ required List signature,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifySignature(
+ that: this,
+ inputData: inputData,
+ pubkey: pubkey,
+ signature: signature,
+ );
+
+ Future verifyStoredPubkey({
+ required PlatformInt64 fromContactId,
+ required List pubkey,
+ }) => RustLib.instance.api
+ .crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifyStoredPubkey(
+ that: this,
+ fromContactId: fromContactId,
+ pubkey: pubkey,
+ );
+
+ @override
+ int get hashCode => 0;
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is UserDiscoveryUtilsFlutter && runtimeType == other.runtimeType;
+}
diff --git a/lib/core/bridge/wrapper.dart b/lib/core/bridge/wrapper.dart
new file mode 100644
index 00000000..a81cf112
--- /dev/null
+++ b/lib/core/bridge/wrapper.dart
@@ -0,0 +1,37 @@
+// This file is automatically generated, so please do not edit it.
+// @generated by `flutter_rust_bridge`@ 2.12.0.
+
+// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
+
+import '../frb_generated.dart';
+import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
+
+class RustUtils {
+ const RustUtils();
+
+ static Future> generateShares({
+ required List secret,
+ required int total,
+ required int threshold,
+ }) => RustLib.instance.api.crateBridgeWrapperRustUtilsGenerateShares(
+ secret: secret,
+ total: total,
+ threshold: threshold,
+ );
+
+ static Future recoverSecret({
+ required List shares,
+ required int threshold,
+ }) => RustLib.instance.api.crateBridgeWrapperRustUtilsRecoverSecret(
+ shares: shares,
+ threshold: threshold,
+ );
+
+ @override
+ int get hashCode => 0;
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is RustUtils && runtimeType == other.runtimeType;
+}
diff --git a/lib/core/bridge/wrapper/key_manager.dart b/lib/core/bridge/wrapper/key_manager.dart
index 46c57e90..6e6e5095 100644
--- a/lib/core/bridge/wrapper/key_manager.dart
+++ b/lib/core/bridge/wrapper/key_manager.dart
@@ -20,6 +20,12 @@ class RustKeyManager {
static Future getUserId() => RustLib.instance.api
.crateBridgeWrapperKeyManagerRustKeyManagerGetUserId();
+ static Future importSerialized({required List serializedBytes}) =>
+ RustLib.instance.api
+ .crateBridgeWrapperKeyManagerRustKeyManagerImportSerialized(
+ serializedBytes: serializedBytes,
+ );
+
static Future importSignalIdentity({
required List identityKeyPairStructure,
required PlatformInt64 registrationId,
@@ -53,6 +59,10 @@ class RustKeyManager {
signedPreKeyId: signedPreKeyId,
);
+ /// Serialize the key_manager. Needed for the passwordless_recovery feature.
+ static Future serialize() => RustLib.instance.api
+ .crateBridgeWrapperKeyManagerRustKeyManagerSerialize();
+
static Future setUserId({required PlatformInt64 userId}) => RustLib
.instance
.api
diff --git a/lib/core/frb_generated.dart b/lib/core/frb_generated.dart
index 8570e08f..b0b840d8 100644
--- a/lib/core/frb_generated.dart
+++ b/lib/core/frb_generated.dart
@@ -5,6 +5,8 @@
import 'bridge.dart';
import 'bridge/callbacks.dart';
+import 'bridge/callbacks/user_discovery.dart';
+import 'bridge/wrapper.dart';
import 'bridge/wrapper/backup.dart';
import 'bridge/wrapper/key_manager.dart';
import 'bridge/wrapper/user_discovery.dart';
@@ -74,7 +76,7 @@ class RustLib extends BaseEntrypoint {
String get codegenVersion => '2.12.0';
@override
- int get rustContentHash => -1867463121;
+ int get rustContentHash => 340781866;
static const kDefaultExternalLibraryLoaderConfig =
ExternalLibraryLoaderConfig(
@@ -210,6 +212,10 @@ abstract class RustLibApi extends BaseApi {
Future crateBridgeWrapperKeyManagerRustKeyManagerGetUserId();
+ Future crateBridgeWrapperKeyManagerRustKeyManagerImportSerialized({
+ required List serializedBytes,
+ });
+
Future crateBridgeWrapperKeyManagerRustKeyManagerImportSignalIdentity({
required List identityKeyPairStructure,
required PlatformInt64 registrationId,
@@ -230,6 +236,8 @@ abstract class RustLibApi extends BaseApi {
required PlatformInt64 signedPreKeyId,
});
+ Future crateBridgeWrapperKeyManagerRustKeyManagerSerialize();
+
Future crateBridgeWrapperKeyManagerRustKeyManagerSetUserId({
required PlatformInt64 userId,
});
@@ -238,6 +246,120 @@ abstract class RustLibApi extends BaseApi {
required PlatformInt64 signedPreKeyId,
required List record,
});
+
+ Future> crateBridgeWrapperRustUtilsGenerateShares({
+ required List secret,
+ required int total,
+ required int threshold,
+ });
+
+ Future crateBridgeWrapperRustUtilsRecoverSecret({
+ required List shares,
+ required int threshold,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetAnnouncedUserByPublicId({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 publicId,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetConfig({
+ required UserDiscoveryStoreFlutter that,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactPromotion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactVersion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ });
+
+ Future>
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOtherPromotionsByPublicId({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 publicId,
+ });
+
+ Future>
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOwnPromotionsAfterVersion({
+ required UserDiscoveryStoreFlutter that,
+ required int version,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetShareForContact({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushNewUserRelation({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 fromContactId,
+ required AnnouncedUser announcedUser,
+ PlatformInt64? publicKeyVerifiedTimestamp,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushOwnPromotionAndClearOldVersion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ required int version,
+ required List promotion,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetContactVersion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ required List update,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetShares({
+ required UserDiscoveryStoreFlutter that,
+ required List shares,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterStoreOtherPromotion({
+ required UserDiscoveryStoreFlutter that,
+ required OtherPromotion promotion,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterUpdateConfig({
+ required UserDiscoveryStoreFlutter that,
+ required String update,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterSignData({
+ required UserDiscoveryUtilsFlutter that,
+ required List inputData,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifySignature({
+ required UserDiscoveryUtilsFlutter that,
+ required List inputData,
+ required List pubkey,
+ required List signature,
+ });
+
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifyStoredPubkey({
+ required UserDiscoveryUtilsFlutter that,
+ required PlatformInt64 fromContactId,
+ required List pubkey,
+ });
}
class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
@@ -1116,6 +1238,41 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
argNames: [],
);
+ @override
+ Future crateBridgeWrapperKeyManagerRustKeyManagerImportSerialized({
+ required List serializedBytes,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_list_prim_u_8_loose(serializedBytes, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 21,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_unit,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeWrapperKeyManagerRustKeyManagerImportSerializedConstMeta,
+ argValues: [serializedBytes],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeWrapperKeyManagerRustKeyManagerImportSerializedConstMeta =>
+ const TaskConstMeta(
+ debugName: "rust_key_manager_import_serialized",
+ argNames: ["serializedBytes"],
+ );
+
@override
Future crateBridgeWrapperKeyManagerRustKeyManagerImportSignalIdentity({
required List identityKeyPairStructure,
@@ -1135,7 +1292,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
- funcId: 21,
+ funcId: 22,
port: port_,
);
},
@@ -1179,7 +1336,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
- funcId: 22,
+ funcId: 23,
port: port_,
);
},
@@ -1212,7 +1369,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
- funcId: 23,
+ funcId: 24,
port: port_,
);
},
@@ -1244,7 +1401,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
- funcId: 24,
+ funcId: 25,
port: port_,
);
},
@@ -1279,7 +1436,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
- funcId: 25,
+ funcId: 26,
port: port_,
);
},
@@ -1302,6 +1459,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
argNames: ["signedPreKeyId"],
);
+ @override
+ Future crateBridgeWrapperKeyManagerRustKeyManagerSerialize() {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 27,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeWrapperKeyManagerRustKeyManagerSerializeConstMeta,
+ argValues: [],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeWrapperKeyManagerRustKeyManagerSerializeConstMeta =>
+ const TaskConstMeta(
+ debugName: "rust_key_manager_serialize",
+ argNames: [],
+ );
+
@override
Future crateBridgeWrapperKeyManagerRustKeyManagerSetUserId({
required PlatformInt64 userId,
@@ -1314,7 +1503,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
- funcId: 26,
+ funcId: 28,
port: port_,
);
},
@@ -1351,7 +1540,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
- funcId: 27,
+ funcId: 29,
port: port_,
);
},
@@ -1374,6 +1563,717 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
argNames: ["signedPreKeyId", "record"],
);
+ @override
+ Future> crateBridgeWrapperRustUtilsGenerateShares({
+ required List secret,
+ required int total,
+ required int threshold,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_list_prim_u_8_loose(secret, serializer);
+ sse_encode_u_8(total, serializer);
+ sse_encode_u_8(threshold, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 30,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_list_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta: kCrateBridgeWrapperRustUtilsGenerateSharesConstMeta,
+ argValues: [secret, total, threshold],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta get kCrateBridgeWrapperRustUtilsGenerateSharesConstMeta =>
+ const TaskConstMeta(
+ debugName: "rust_utils_generate_shares",
+ argNames: ["secret", "total", "threshold"],
+ );
+
+ @override
+ Future crateBridgeWrapperRustUtilsRecoverSecret({
+ required List shares,
+ required int threshold,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_list_list_prim_u_8_strict(shares, serializer);
+ sse_encode_u_8(threshold, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 31,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta: kCrateBridgeWrapperRustUtilsRecoverSecretConstMeta,
+ argValues: [shares, threshold],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta get kCrateBridgeWrapperRustUtilsRecoverSecretConstMeta =>
+ const TaskConstMeta(
+ debugName: "rust_utils_recover_secret",
+ argNames: ["shares", "threshold"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetAnnouncedUserByPublicId({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 publicId,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(publicId, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 32,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_opt_box_autoadd_announced_user,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetAnnouncedUserByPublicIdConstMeta,
+ argValues: [that, publicId],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetAnnouncedUserByPublicIdConstMeta =>
+ const TaskConstMeta(
+ debugName:
+ "user_discovery_store_flutter_get_announced_user_by_public_id",
+ argNames: ["that", "publicId"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetConfig({
+ required UserDiscoveryStoreFlutter that,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 33,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_String,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetConfigConstMeta,
+ argValues: [that],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetConfigConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_get_config",
+ argNames: ["that"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactPromotion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(contactId, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 34,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_opt_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactPromotionConstMeta,
+ argValues: [that, contactId],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactPromotionConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_get_contact_promotion",
+ argNames: ["that", "contactId"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactVersion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(contactId, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 35,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_opt_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactVersionConstMeta,
+ argValues: [that, contactId],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetContactVersionConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_get_contact_version",
+ argNames: ["that", "contactId"],
+ );
+
+ @override
+ Future>
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOtherPromotionsByPublicId({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 publicId,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(publicId, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 36,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_list_other_promotion,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOtherPromotionsByPublicIdConstMeta,
+ argValues: [that, publicId],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOtherPromotionsByPublicIdConstMeta =>
+ const TaskConstMeta(
+ debugName:
+ "user_discovery_store_flutter_get_other_promotions_by_public_id",
+ argNames: ["that", "publicId"],
+ );
+
+ @override
+ Future>
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOwnPromotionsAfterVersion({
+ required UserDiscoveryStoreFlutter that,
+ required int version,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_u_32(version, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 37,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_list_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOwnPromotionsAfterVersionConstMeta,
+ argValues: [that, version],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetOwnPromotionsAfterVersionConstMeta =>
+ const TaskConstMeta(
+ debugName:
+ "user_discovery_store_flutter_get_own_promotions_after_version",
+ argNames: ["that", "version"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetShareForContact({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(contactId, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 38,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetShareForContactConstMeta,
+ argValues: [that, contactId],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterGetShareForContactConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_get_share_for_contact",
+ argNames: ["that", "contactId"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushNewUserRelation({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 fromContactId,
+ required AnnouncedUser announcedUser,
+ PlatformInt64? publicKeyVerifiedTimestamp,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(fromContactId, serializer);
+ sse_encode_box_autoadd_announced_user(announcedUser, serializer);
+ sse_encode_opt_box_autoadd_i_64(
+ publicKeyVerifiedTimestamp,
+ serializer,
+ );
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 39,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_unit,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushNewUserRelationConstMeta,
+ argValues: [
+ that,
+ fromContactId,
+ announcedUser,
+ publicKeyVerifiedTimestamp,
+ ],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushNewUserRelationConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_push_new_user_relation",
+ argNames: [
+ "that",
+ "fromContactId",
+ "announcedUser",
+ "publicKeyVerifiedTimestamp",
+ ],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushOwnPromotionAndClearOldVersion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ required int version,
+ required List promotion,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(contactId, serializer);
+ sse_encode_u_32(version, serializer);
+ sse_encode_list_prim_u_8_loose(promotion, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 40,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_unit,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushOwnPromotionAndClearOldVersionConstMeta,
+ argValues: [that, contactId, version, promotion],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterPushOwnPromotionAndClearOldVersionConstMeta =>
+ const TaskConstMeta(
+ debugName:
+ "user_discovery_store_flutter_push_own_promotion_and_clear_old_version",
+ argNames: ["that", "contactId", "version", "promotion"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetContactVersion({
+ required UserDiscoveryStoreFlutter that,
+ required PlatformInt64 contactId,
+ required List update,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_i_64(contactId, serializer);
+ sse_encode_list_prim_u_8_loose(update, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 41,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_unit,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetContactVersionConstMeta,
+ argValues: [that, contactId, update],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetContactVersionConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_set_contact_version",
+ argNames: ["that", "contactId", "update"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetShares({
+ required UserDiscoveryStoreFlutter that,
+ required List shares,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_list_list_prim_u_8_strict(shares, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 42,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_unit,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetSharesConstMeta,
+ argValues: [that, shares],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterSetSharesConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_set_shares",
+ argNames: ["that", "shares"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterStoreOtherPromotion({
+ required UserDiscoveryStoreFlutter that,
+ required OtherPromotion promotion,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_box_autoadd_other_promotion(promotion, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 43,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_unit,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterStoreOtherPromotionConstMeta,
+ argValues: [that, promotion],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterStoreOtherPromotionConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_store_other_promotion",
+ argNames: ["that", "promotion"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterUpdateConfig({
+ required UserDiscoveryStoreFlutter that,
+ required String update,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_store_flutter(that, serializer);
+ sse_encode_String(update, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 44,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_unit,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterUpdateConfigConstMeta,
+ argValues: [that, update],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryStoreFlutterUpdateConfigConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_store_flutter_update_config",
+ argNames: ["that", "update"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterSignData({
+ required UserDiscoveryUtilsFlutter that,
+ required List inputData,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_utils_flutter(that, serializer);
+ sse_encode_list_prim_u_8_loose(inputData, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 45,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_list_prim_u_8_strict,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterSignDataConstMeta,
+ argValues: [that, inputData],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterSignDataConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_utils_flutter_sign_data",
+ argNames: ["that", "inputData"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifySignature({
+ required UserDiscoveryUtilsFlutter that,
+ required List inputData,
+ required List pubkey,
+ required List signature,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_utils_flutter(that, serializer);
+ sse_encode_list_prim_u_8_loose(inputData, serializer);
+ sse_encode_list_prim_u_8_loose(pubkey, serializer);
+ sse_encode_list_prim_u_8_loose(signature, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 46,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_bool,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifySignatureConstMeta,
+ argValues: [that, inputData, pubkey, signature],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifySignatureConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_utils_flutter_verify_signature",
+ argNames: ["that", "inputData", "pubkey", "signature"],
+ );
+
+ @override
+ Future
+ crateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifyStoredPubkey({
+ required UserDiscoveryUtilsFlutter that,
+ required PlatformInt64 fromContactId,
+ required List pubkey,
+ }) {
+ return handler.executeNormal(
+ NormalTask(
+ callFfi: (port_) {
+ final serializer = SseSerializer(generalizedFrbRustBinding);
+ sse_encode_box_autoadd_user_discovery_utils_flutter(that, serializer);
+ sse_encode_i_64(fromContactId, serializer);
+ sse_encode_list_prim_u_8_loose(pubkey, serializer);
+ pdeCallFfi(
+ generalizedFrbRustBinding,
+ serializer,
+ funcId: 47,
+ port: port_,
+ );
+ },
+ codec: SseCodec(
+ decodeSuccessData: sse_decode_bool,
+ decodeErrorData: sse_decode_AnyhowException,
+ ),
+ constMeta:
+ kCrateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifyStoredPubkeyConstMeta,
+ argValues: [that, fromContactId, pubkey],
+ apiImpl: this,
+ ),
+ );
+ }
+
+ TaskConstMeta
+ get kCrateBridgeCallbacksUserDiscoveryUserDiscoveryUtilsFlutterVerifyStoredPubkeyConstMeta =>
+ const TaskConstMeta(
+ debugName: "user_discovery_utils_flutter_verify_stored_pubkey",
+ argNames: ["that", "fromContactId", "pubkey"],
+ );
+
Future Function(
int,
)
@@ -2002,6 +2902,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return dco_decode_init_config(raw);
}
+ @protected
+ OtherPromotion dco_decode_box_autoadd_other_promotion(dynamic raw) {
+ // Codec=Dco (DartCObject based), see doc to use other codecs
+ return dco_decode_other_promotion(raw);
+ }
+
+ @protected
+ UserDiscoveryStoreFlutter dco_decode_box_autoadd_user_discovery_store_flutter(
+ dynamic raw,
+ ) {
+ // Codec=Dco (DartCObject based), see doc to use other codecs
+ return dco_decode_user_discovery_store_flutter(raw);
+ }
+
+ @protected
+ UserDiscoveryUtilsFlutter dco_decode_box_autoadd_user_discovery_utils_flutter(
+ dynamic raw,
+ ) {
+ // Codec=Dco (DartCObject based), see doc to use other codecs
+ return dco_decode_user_discovery_utils_flutter(raw);
+ }
+
@protected
FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
@@ -2190,6 +3112,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return RustKeyManager();
}
+ @protected
+ RustUtils dco_decode_rust_utils(dynamic raw) {
+ // Codec=Dco (DartCObject based), see doc to use other codecs
+ final arr = raw as List;
+ if (arr.length != 0)
+ throw Exception('unexpected arr length: expect 0 but see ${arr.length}');
+ return RustUtils();
+ }
+
@protected
int dco_decode_u_32(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
@@ -2214,6 +3145,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return;
}
+ @protected
+ UserDiscoveryStoreFlutter dco_decode_user_discovery_store_flutter(
+ dynamic raw,
+ ) {
+ // Codec=Dco (DartCObject based), see doc to use other codecs
+ final arr = raw as List;
+ if (arr.length != 0)
+ throw Exception('unexpected arr length: expect 0 but see ${arr.length}');
+ return UserDiscoveryStoreFlutter();
+ }
+
+ @protected
+ UserDiscoveryUtilsFlutter dco_decode_user_discovery_utils_flutter(
+ dynamic raw,
+ ) {
+ // Codec=Dco (DartCObject based), see doc to use other codecs
+ final arr = raw as List;
+ if (arr.length != 0)
+ throw Exception('unexpected arr length: expect 0 but see ${arr.length}');
+ return UserDiscoveryUtilsFlutter();
+ }
+
@protected
BigInt dco_decode_usize(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
@@ -2318,6 +3271,30 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return (sse_decode_init_config(deserializer));
}
+ @protected
+ OtherPromotion sse_decode_box_autoadd_other_promotion(
+ SseDeserializer deserializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ return (sse_decode_other_promotion(deserializer));
+ }
+
+ @protected
+ UserDiscoveryStoreFlutter sse_decode_box_autoadd_user_discovery_store_flutter(
+ SseDeserializer deserializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ return (sse_decode_user_discovery_store_flutter(deserializer));
+ }
+
+ @protected
+ UserDiscoveryUtilsFlutter sse_decode_box_autoadd_user_discovery_utils_flutter(
+ SseDeserializer deserializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ return (sse_decode_user_discovery_utils_flutter(deserializer));
+ }
+
@protected
FlutterUserDiscovery sse_decode_flutter_user_discovery(
SseDeserializer deserializer,
@@ -2548,6 +3525,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return RustKeyManager();
}
+ @protected
+ RustUtils sse_decode_rust_utils(SseDeserializer deserializer) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ return RustUtils();
+ }
+
@protected
int sse_decode_u_32(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
@@ -2572,6 +3555,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
// Codec=Sse (Serialization based), see doc to use other codecs
}
+ @protected
+ UserDiscoveryStoreFlutter sse_decode_user_discovery_store_flutter(
+ SseDeserializer deserializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ return UserDiscoveryStoreFlutter();
+ }
+
+ @protected
+ UserDiscoveryUtilsFlutter sse_decode_user_discovery_utils_flutter(
+ SseDeserializer deserializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ return UserDiscoveryUtilsFlutter();
+ }
+
@protected
BigInt sse_decode_usize(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
@@ -2877,6 +3876,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
sse_encode_init_config(self, serializer);
}
+ @protected
+ void sse_encode_box_autoadd_other_promotion(
+ OtherPromotion self,
+ SseSerializer serializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ sse_encode_other_promotion(self, serializer);
+ }
+
+ @protected
+ void sse_encode_box_autoadd_user_discovery_store_flutter(
+ UserDiscoveryStoreFlutter self,
+ SseSerializer serializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ sse_encode_user_discovery_store_flutter(self, serializer);
+ }
+
+ @protected
+ void sse_encode_box_autoadd_user_discovery_utils_flutter(
+ UserDiscoveryUtilsFlutter self,
+ SseSerializer serializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ sse_encode_user_discovery_utils_flutter(self, serializer);
+ }
+
@protected
void sse_encode_flutter_user_discovery(
FlutterUserDiscovery self,
@@ -3108,6 +4134,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
// Codec=Sse (Serialization based), see doc to use other codecs
}
+ @protected
+ void sse_encode_rust_utils(RustUtils self, SseSerializer serializer) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ }
+
@protected
void sse_encode_u_32(int self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
@@ -3131,6 +4162,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
// Codec=Sse (Serialization based), see doc to use other codecs
}
+ @protected
+ void sse_encode_user_discovery_store_flutter(
+ UserDiscoveryStoreFlutter self,
+ SseSerializer serializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ }
+
+ @protected
+ void sse_encode_user_discovery_utils_flutter(
+ UserDiscoveryUtilsFlutter self,
+ SseSerializer serializer,
+ ) {
+ // Codec=Sse (Serialization based), see doc to use other codecs
+ }
+
@protected
void sse_encode_usize(BigInt self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
diff --git a/lib/core/frb_generated.io.dart b/lib/core/frb_generated.io.dart
index 938d45c5..6b1600a0 100644
--- a/lib/core/frb_generated.io.dart
+++ b/lib/core/frb_generated.io.dart
@@ -5,6 +5,8 @@
import 'bridge.dart';
import 'bridge/callbacks.dart';
+import 'bridge/callbacks/user_discovery.dart';
+import 'bridge/wrapper.dart';
import 'bridge/wrapper/backup.dart';
import 'bridge/wrapper/key_manager.dart';
import 'bridge/wrapper/user_discovery.dart';
@@ -134,6 +136,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
InitConfig dco_decode_box_autoadd_init_config(dynamic raw);
+ @protected
+ OtherPromotion dco_decode_box_autoadd_other_promotion(dynamic raw);
+
+ @protected
+ UserDiscoveryStoreFlutter dco_decode_box_autoadd_user_discovery_store_flutter(
+ dynamic raw,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter dco_decode_box_autoadd_user_discovery_utils_flutter(
+ dynamic raw,
+ );
+
@protected
FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw);
@@ -205,6 +220,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
RustKeyManager dco_decode_rust_key_manager(dynamic raw);
+ @protected
+ RustUtils dco_decode_rust_utils(dynamic raw);
+
@protected
int dco_decode_u_32(dynamic raw);
@@ -217,6 +235,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
void dco_decode_unit(dynamic raw);
+ @protected
+ UserDiscoveryStoreFlutter dco_decode_user_discovery_store_flutter(
+ dynamic raw,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter dco_decode_user_discovery_utils_flutter(
+ dynamic raw,
+ );
+
@protected
BigInt dco_decode_usize(dynamic raw);
@@ -266,6 +294,21 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
InitConfig sse_decode_box_autoadd_init_config(SseDeserializer deserializer);
+ @protected
+ OtherPromotion sse_decode_box_autoadd_other_promotion(
+ SseDeserializer deserializer,
+ );
+
+ @protected
+ UserDiscoveryStoreFlutter sse_decode_box_autoadd_user_discovery_store_flutter(
+ SseDeserializer deserializer,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter sse_decode_box_autoadd_user_discovery_utils_flutter(
+ SseDeserializer deserializer,
+ );
+
@protected
FlutterUserDiscovery sse_decode_flutter_user_discovery(
SseDeserializer deserializer,
@@ -357,6 +400,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
RustKeyManager sse_decode_rust_key_manager(SseDeserializer deserializer);
+ @protected
+ RustUtils sse_decode_rust_utils(SseDeserializer deserializer);
+
@protected
int sse_decode_u_32(SseDeserializer deserializer);
@@ -369,6 +415,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
void sse_decode_unit(SseDeserializer deserializer);
+ @protected
+ UserDiscoveryStoreFlutter sse_decode_user_discovery_store_flutter(
+ SseDeserializer deserializer,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter sse_decode_user_discovery_utils_flutter(
+ SseDeserializer deserializer,
+ );
+
@protected
BigInt sse_decode_usize(SseDeserializer deserializer);
@@ -517,6 +573,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
SseSerializer serializer,
);
+ @protected
+ void sse_encode_box_autoadd_other_promotion(
+ OtherPromotion self,
+ SseSerializer serializer,
+ );
+
+ @protected
+ void sse_encode_box_autoadd_user_discovery_store_flutter(
+ UserDiscoveryStoreFlutter self,
+ SseSerializer serializer,
+ );
+
+ @protected
+ void sse_encode_box_autoadd_user_discovery_utils_flutter(
+ UserDiscoveryUtilsFlutter self,
+ SseSerializer serializer,
+ );
+
@protected
void sse_encode_flutter_user_discovery(
FlutterUserDiscovery self,
@@ -634,6 +708,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
SseSerializer serializer,
);
+ @protected
+ void sse_encode_rust_utils(RustUtils self, SseSerializer serializer);
+
@protected
void sse_encode_u_32(int self, SseSerializer serializer);
@@ -646,6 +723,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
void sse_encode_unit(void self, SseSerializer serializer);
+ @protected
+ void sse_encode_user_discovery_store_flutter(
+ UserDiscoveryStoreFlutter self,
+ SseSerializer serializer,
+ );
+
+ @protected
+ void sse_encode_user_discovery_utils_flutter(
+ UserDiscoveryUtilsFlutter self,
+ SseSerializer serializer,
+ );
+
@protected
void sse_encode_usize(BigInt self, SseSerializer serializer);
diff --git a/lib/core/frb_generated.web.dart b/lib/core/frb_generated.web.dart
index 23c61b25..ed0ca4ee 100644
--- a/lib/core/frb_generated.web.dart
+++ b/lib/core/frb_generated.web.dart
@@ -8,6 +8,8 @@
import 'bridge.dart';
import 'bridge/callbacks.dart';
+import 'bridge/callbacks/user_discovery.dart';
+import 'bridge/wrapper.dart';
import 'bridge/wrapper/backup.dart';
import 'bridge/wrapper/key_manager.dart';
import 'bridge/wrapper/user_discovery.dart';
@@ -136,6 +138,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
InitConfig dco_decode_box_autoadd_init_config(dynamic raw);
+ @protected
+ OtherPromotion dco_decode_box_autoadd_other_promotion(dynamic raw);
+
+ @protected
+ UserDiscoveryStoreFlutter dco_decode_box_autoadd_user_discovery_store_flutter(
+ dynamic raw,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter dco_decode_box_autoadd_user_discovery_utils_flutter(
+ dynamic raw,
+ );
+
@protected
FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw);
@@ -207,6 +222,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
RustKeyManager dco_decode_rust_key_manager(dynamic raw);
+ @protected
+ RustUtils dco_decode_rust_utils(dynamic raw);
+
@protected
int dco_decode_u_32(dynamic raw);
@@ -219,6 +237,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
void dco_decode_unit(dynamic raw);
+ @protected
+ UserDiscoveryStoreFlutter dco_decode_user_discovery_store_flutter(
+ dynamic raw,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter dco_decode_user_discovery_utils_flutter(
+ dynamic raw,
+ );
+
@protected
BigInt dco_decode_usize(dynamic raw);
@@ -268,6 +296,21 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
InitConfig sse_decode_box_autoadd_init_config(SseDeserializer deserializer);
+ @protected
+ OtherPromotion sse_decode_box_autoadd_other_promotion(
+ SseDeserializer deserializer,
+ );
+
+ @protected
+ UserDiscoveryStoreFlutter sse_decode_box_autoadd_user_discovery_store_flutter(
+ SseDeserializer deserializer,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter sse_decode_box_autoadd_user_discovery_utils_flutter(
+ SseDeserializer deserializer,
+ );
+
@protected
FlutterUserDiscovery sse_decode_flutter_user_discovery(
SseDeserializer deserializer,
@@ -359,6 +402,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
RustKeyManager sse_decode_rust_key_manager(SseDeserializer deserializer);
+ @protected
+ RustUtils sse_decode_rust_utils(SseDeserializer deserializer);
+
@protected
int sse_decode_u_32(SseDeserializer deserializer);
@@ -371,6 +417,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
void sse_decode_unit(SseDeserializer deserializer);
+ @protected
+ UserDiscoveryStoreFlutter sse_decode_user_discovery_store_flutter(
+ SseDeserializer deserializer,
+ );
+
+ @protected
+ UserDiscoveryUtilsFlutter sse_decode_user_discovery_utils_flutter(
+ SseDeserializer deserializer,
+ );
+
@protected
BigInt sse_decode_usize(SseDeserializer deserializer);
@@ -519,6 +575,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
SseSerializer serializer,
);
+ @protected
+ void sse_encode_box_autoadd_other_promotion(
+ OtherPromotion self,
+ SseSerializer serializer,
+ );
+
+ @protected
+ void sse_encode_box_autoadd_user_discovery_store_flutter(
+ UserDiscoveryStoreFlutter self,
+ SseSerializer serializer,
+ );
+
+ @protected
+ void sse_encode_box_autoadd_user_discovery_utils_flutter(
+ UserDiscoveryUtilsFlutter self,
+ SseSerializer serializer,
+ );
+
@protected
void sse_encode_flutter_user_discovery(
FlutterUserDiscovery self,
@@ -636,6 +710,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
SseSerializer serializer,
);
+ @protected
+ void sse_encode_rust_utils(RustUtils self, SseSerializer serializer);
+
@protected
void sse_encode_u_32(int self, SseSerializer serializer);
@@ -648,6 +725,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl {
@protected
void sse_encode_unit(void self, SseSerializer serializer);
+ @protected
+ void sse_encode_user_discovery_store_flutter(
+ UserDiscoveryStoreFlutter self,
+ SseSerializer serializer,
+ );
+
+ @protected
+ void sse_encode_user_discovery_utils_flutter(
+ UserDiscoveryUtilsFlutter self,
+ SseSerializer serializer,
+ );
+
@protected
void sse_encode_usize(BigInt self, SseSerializer serializer);
diff --git a/lib/src/callbacks/user_discovery.callbacks.dart b/lib/src/callbacks/user_discovery.callbacks.dart
index 86bfc4df..1c0753b2 100644
--- a/lib/src/callbacks/user_discovery.callbacks.dart
+++ b/lib/src/callbacks/user_discovery.callbacks.dart
@@ -314,9 +314,11 @@ class UserDiscoveryCallbacks {
static Future getContactPromotion(int contactId) async {
try {
- final row = await (twonlyDB.select(
- twonlyDB.userDiscoveryOwnPromotions,
- )..where((tbl) => tbl.contactId.equals(contactId))).getSingleOrNull();
+ final query = twonlyDB.select(twonlyDB.userDiscoveryOwnPromotions)
+ ..where((tbl) => tbl.contactId.equals(contactId))
+ ..orderBy([(tbl) => OrderingTerm.desc(tbl.versionId)])
+ ..limit(1);
+ final row = await query.getSingleOrNull();
return row?.promotion;
} catch (e) {
Log.error(e);
diff --git a/lib/src/channels/video_compression.channel.dart b/lib/src/channels/video_compression.channel.dart
index f2f72993..58790b59 100644
--- a/lib/src/channels/video_compression.channel.dart
+++ b/lib/src/channels/video_compression.channel.dart
@@ -36,7 +36,7 @@ abstract class VideoCompressionChannel {
});
return outputPath;
} on PlatformException catch (e) {
- Log.error('Failed to compress video: $e');
+ Log.warn('Failed to compress video: $e');
return null;
} finally {
_currentProgressCallback = null;
diff --git a/lib/src/constants/keyvalue.keys.dart b/lib/src/constants/keyvalue.keys.dart
index 57db9890..9737cb9d 100644
--- a/lib/src/constants/keyvalue.keys.dart
+++ b/lib/src/constants/keyvalue.keys.dart
@@ -3,4 +3,5 @@ class KeyValueKeys {
'last_periodic_task_execution';
static const String currentBackupState = 'current_backup_state';
static const String backupRecoveryState = 'backup_recovery_state';
+ static const String onboardingState = 'onboarding_state';
}
diff --git a/lib/src/constants/routes.keys.dart b/lib/src/constants/routes.keys.dart
index 017745f0..43fc9cb0 100644
--- a/lib/src/constants/routes.keys.dart
+++ b/lib/src/constants/routes.keys.dart
@@ -16,6 +16,7 @@ class Routes {
static String profileContact(int contactId) => '/profile/contact/$contactId';
static const String cameraQRScanner = '/camera/qr_scanner';
+ static const String recoverPasswordless = '/recover/passwordless';
static const String settings = '/settings';
static const String settingsProfile = '/settings/profile';
@@ -35,8 +36,6 @@ class Routes {
'/settings/privacy/block_users';
static const String settingsPrivacyUserDiscovery =
'/settings/privacy/user_discovery';
- static const String settingsPrivacyProfileSelection =
- '/settings/privacy/profile_selection';
static const String settingsNotification = '/settings/notification';
static const String settingsStorage = '/settings/storage_data';
static const String settingsStorageManage = '/settings/storage_data/manage';
diff --git a/lib/src/database/daos/groups.dao.dart b/lib/src/database/daos/groups.dao.dart
index 929dc2e0..aa5d69c4 100644
--- a/lib/src/database/daos/groups.dao.dart
+++ b/lib/src/database/daos/groups.dao.dart
@@ -128,7 +128,7 @@ class GroupsDao extends DatabaseAccessor with _$GroupsDaoMixin {
final result = await _insertGroup(insertGroup);
if (result != null) {
- await into(groupMembers).insert(
+ await into(groupMembers).insertOnConflictUpdate(
GroupMembersCompanion(
groupId: Value(result.groupId),
contactId: Value(
diff --git a/lib/src/database/daos/key_verification.dao.dart b/lib/src/database/daos/key_verification.dao.dart
index 20fc47d8..eef18d6e 100644
--- a/lib/src/database/daos/key_verification.dao.dart
+++ b/lib/src/database/daos/key_verification.dao.dart
@@ -259,6 +259,54 @@ class KeyVerificationDao extends DatabaseAccessor
});
}
+ Stream watchUnverifiedGroupMembersCount(String groupId) {
+ final gm = groupMembers;
+ final directKv = alias(keyVerifications, 'directKv');
+ final ur = userDiscoveryUserRelations;
+ final verifierKv = alias(keyVerifications, 'verifierKv');
+
+ final query = select(gm).join([
+ leftOuterJoin(directKv, directKv.contactId.equalsExp(gm.contactId)),
+ leftOuterJoin(
+ ur,
+ ur.announcedUserId.equalsExp(gm.contactId) &
+ ur.publicKeyVerifiedTimestamp.isNotNull() &
+ ur.fromContactId.equalsExp(gm.contactId).not(),
+ ),
+ leftOuterJoin(
+ verifierKv,
+ verifierKv.contactId.equalsExp(ur.fromContactId),
+ ),
+ ])..where(gm.groupId.equals(groupId));
+
+ return query.watch().map((rows) {
+ if (rows.isEmpty) return 0;
+
+ final memberTrustMap = {};
+
+ for (final row in rows) {
+ final contactId = row.readTable(gm).contactId;
+ final isDirect = row.readTableOrNull(directKv) != null;
+ final isPartial = row.readTableOrNull(verifierKv) != null;
+
+ final current =
+ memberTrustMap[contactId] ?? (direct: false, partial: false);
+ memberTrustMap[contactId] = (
+ direct: current.direct || isDirect,
+ partial: current.partial || isPartial,
+ );
+ }
+
+ var count = 0;
+ for (final trust in memberTrustMap.values) {
+ if (!trust.direct && !trust.partial) {
+ count++;
+ }
+ }
+ return count;
+ });
+ }
+
Future addKeyVerification(
int contactId,
VerificationType type, {
diff --git a/lib/src/database/daos/mediafiles.dao.dart b/lib/src/database/daos/mediafiles.dao.dart
index 78f2d92f..889beb4e 100644
--- a/lib/src/database/daos/mediafiles.dao.dart
+++ b/lib/src/database/daos/mediafiles.dao.dart
@@ -1,12 +1,13 @@
import 'package:drift/drift.dart';
import 'package:hashlib/random.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
+import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
part 'mediafiles.dao.g.dart';
-@DriftAccessor(tables: [MediaFiles])
+@DriftAccessor(tables: [MediaFiles, Messages])
class MediaFilesDao extends DatabaseAccessor
with _$MediaFilesDaoMixin {
// this constructor is required so that the main database can create an instance
@@ -142,7 +143,9 @@ class MediaFilesDao extends DatabaseAccessor
final query =
(select(mediaFiles)..where((t) => t.stored.equals(true))).join([])
..groupBy([
- const CustomExpression