From c6c625df59423ea721cc2ace17c3d8cac9b49dd0 Mon Sep 17 00:00:00 2001 From: otsmr Date: Sat, 15 Mar 2025 01:48:27 +0100 Subject: [PATCH] authentication works --- android/app/build.gradle | 2 +- lib/main.dart | 2 + .../components/message_send_state_icon.dart | 110 +++++---- lib/src/database/database.dart | 9 +- lib/src/database/database.g.dart | 11 +- lib/src/model/json/message.dart | 14 +- lib/src/proto/api/client_to_server.pb.dart | 230 +++++++++++++----- .../proto/api/client_to_server.pbjson.dart | 68 ++++-- lib/src/proto/api/error.pbenum.dart | 12 + lib/src/proto/api/error.pbjson.dart | 11 +- lib/src/proto/api/server_to_client.pb.dart | 124 ++++++++-- .../proto/api/server_to_client.pbjson.dart | 33 ++- lib/src/providers/api_provider.dart | 120 +++++---- lib/src/services/fcm_service.dart | 34 +-- lib/src/utils/misc.dart | 13 +- lib/src/utils/signal.dart | 1 - lib/src/views/chats/search_username_view.dart | 33 +-- lib/src/views/onboarding/register_view.dart | 5 +- lib/src/views/settings/diagnostics_view.dart | 10 +- 19 files changed, 592 insertions(+), 250 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 30543a3..4d02e20 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -17,7 +17,7 @@ if (keystorePropertiesFile.exists()) { android { namespace = "com.example.connect" // compileSdk = flutter.compileSdkVersion - compileSdk 34 + compileSdk 35 //ndkVersion = flutter.ndkVersion ndkVersion = "25.1.8937393" diff --git a/lib/main.dart b/lib/main.dart index f859b2b..9299fb2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,6 +33,8 @@ void main() async { } }); + await deleteLogFile(); + await setupPushNotification(); await initMediaStorage(); await initFCMService(); diff --git a/lib/src/components/message_send_state_icon.dart b/lib/src/components/message_send_state_icon.dart index 61c0bac..a3318a2 100644 --- a/lib/src/components/message_send_state_icon.dart +++ b/lib/src/components/message_send_state_icon.dart @@ -1,3 +1,4 @@ +import 'dart:collection'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -52,9 +53,9 @@ class MessageSendStateIcon extends StatefulWidget { } class _MessageSendStateIconState extends State { - bool containsVideo = false; - bool containsText = false; - bool containsImage = false; + Message? videoMsg; + Message? textMsg; + Message? imageMsg; @override void initState() { @@ -62,7 +63,7 @@ class _MessageSendStateIconState extends State { for (Message msg in widget.messages) { if (msg.kind == MessageKind.textMessage) { - containsText = true; + textMsg = msg; } if (msg.kind == MessageKind.media) { MessageJson message = @@ -70,21 +71,17 @@ class _MessageSendStateIconState extends State { final content = message.content; if (content is MediaMessageContent) { if (content.isVideo) { - containsVideo = true; + videoMsg = msg; } else { - containsImage = true; + imageMsg = msg; } } } } } - @override - Widget build(BuildContext context) { - Widget icon = Placeholder(); - String text = ""; - - Widget loaderIcon = Row( + Widget getLoaderIcon(color) { + return Row( children: [ SizedBox( width: 10, @@ -94,39 +91,70 @@ class _MessageSendStateIconState extends State { SizedBox(width: 2), ], ); + } - MessageSendState state = messageSendStateFromMessage(message); + @override + Widget build(BuildContext context) { + List icons = []; + String text = ""; - switch (state) { - case MessageSendState.receivedOpened: - icon = Icon(Icons.crop_square, size: 14, color: color); - text = context.lang.messageSendState_Received; - break; - case MessageSendState.sendOpened: - icon = FaIcon(FontAwesomeIcons.paperPlane, size: 12, color: color); - text = context.lang.messageSendState_Opened; - break; - case MessageSendState.received: - icon = Icon(Icons.square_rounded, size: 14, color: color); - text = context.lang.messageSendState_Received; - break; - case MessageSendState.send: - icon = FaIcon(FontAwesomeIcons.solidPaperPlane, size: 12, color: color); - text = context.lang.messageSendState_Send; - break; - case MessageSendState.sending: - case MessageSendState.receiving: - icon = loaderIcon; - text = context.lang.messageSendState_Sending; - break; + Color twonlyColor = Theme.of(context).colorScheme.primary; + HashSet kindsAlreadyShown = HashSet(); + + for (final message in widget.messages) { + if (icons.length == 2) break; + if (message.contentJson == null) continue; + if (kindsAlreadyShown.contains(message.kind)) continue; + kindsAlreadyShown.add(message.kind); + + Widget icon = Placeholder(); + + MessageSendState state = messageSendStateFromMessage(message); + MessageJson msg = MessageJson.fromJson(jsonDecode(message.contentJson!)); + if (msg.content == null) continue; + Color color = getMessageColorFromType(msg.content!, twonlyColor); + + switch (state) { + case MessageSendState.receivedOpened: + icon = Icon(Icons.crop_square, size: 14, color: color); + text = context.lang.messageSendState_Received; + break; + case MessageSendState.sendOpened: + icon = FaIcon(FontAwesomeIcons.paperPlane, size: 12, color: color); + text = context.lang.messageSendState_Opened; + break; + case MessageSendState.received: + icon = Icon(Icons.square_rounded, size: 14, color: color); + text = context.lang.messageSendState_Received; + break; + case MessageSendState.send: + icon = + FaIcon(FontAwesomeIcons.solidPaperPlane, size: 12, color: color); + text = context.lang.messageSendState_Send; + break; + case MessageSendState.sending: + case MessageSendState.receiving: + icon = getLoaderIcon(color); + text = context.lang.messageSendState_Sending; + break; + } + + if (message.downloadState == DownloadState.pending) { + text = context.lang.messageSendState_TapToLoad; + } + if (message.downloadState == DownloadState.downloaded) { + text = context.lang.messageSendState_Loading; + icon = getLoaderIcon(color); + } + icons.add(icon); } - if (message.downloadState == DownloadState.pending) { - text = context.lang.messageSendState_TapToLoad; - } - if (message.downloadState == DownloadState.downloaded) { - text = context.lang.messageSendState_Loading; - icon = loaderIcon; + Widget icon = icons[0]; + + if (icons.length == 2) { + icon = Stack( + children: icons, + ); } return Row( diff --git a/lib/src/database/database.dart b/lib/src/database/database.dart index 1141c45..93d3cc6 100644 --- a/lib/src/database/database.dart +++ b/lib/src/database/database.dart @@ -99,8 +99,12 @@ class TwonlyDatabase extends _$TwonlyDatabase { // ------------ - Future insertContact(ContactsCompanion contact) { - return into(contacts).insert(contact); + Future insertContact(ContactsCompanion contact) async { + try { + return await into(contacts).insert(contact); + } catch (e) { + return 0; + } } Future incTotalMediaCounter(int contactId) async { @@ -140,6 +144,7 @@ class TwonlyDatabase extends _$TwonlyDatabase { Stream> watchNotAcceptedContacts() { return (select(contacts)..where((t) => t.accepted.equals(false))).watch(); + // return (select(contacts)).watch(); } Stream watchContact(int userid) { diff --git a/lib/src/database/database.g.dart b/lib/src/database/database.g.dart index 389ccb3..7310ce9 100644 --- a/lib/src/database/database.g.dart +++ b/lib/src/database/database.g.dart @@ -754,7 +754,9 @@ class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> { @override late final GeneratedColumnWithTypeConverter downloadState = GeneratedColumn('download_state', aliasedName, false, - type: DriftSqlType.int, requiredDuringInsert: true) + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: Constant(DownloadState.pending.index)) .withConverter($MessagesTable.$converterdownloadState); static const VerificationMeta _acknowledgeByServerMeta = const VerificationMeta('acknowledgeByServer'); @@ -1230,7 +1232,7 @@ class MessagesCompanion extends UpdateCompanion { this.responseToMessageId = const Value.absent(), this.responseToOtherMessageId = const Value.absent(), this.acknowledgeByUser = const Value.absent(), - required DownloadState downloadState, + this.downloadState = const Value.absent(), this.acknowledgeByServer = const Value.absent(), required MessageKind kind, this.contentJson = const Value.absent(), @@ -1238,7 +1240,6 @@ class MessagesCompanion extends UpdateCompanion { this.sendAt = const Value.absent(), this.updatedAt = const Value.absent(), }) : contactId = Value(contactId), - downloadState = Value(downloadState), kind = Value(kind); static Insertable custom({ Expression? contactId, @@ -1781,7 +1782,7 @@ typedef $$MessagesTableCreateCompanionBuilder = MessagesCompanion Function({ Value responseToMessageId, Value responseToOtherMessageId, Value acknowledgeByUser, - required DownloadState downloadState, + Value downloadState, Value acknowledgeByServer, required MessageKind kind, Value contentJson, @@ -2098,7 +2099,7 @@ class $$MessagesTableTableManager extends RootTableManager< Value responseToMessageId = const Value.absent(), Value responseToOtherMessageId = const Value.absent(), Value acknowledgeByUser = const Value.absent(), - required DownloadState downloadState, + Value downloadState = const Value.absent(), Value acknowledgeByServer = const Value.absent(), required MessageKind kind, Value contentJson = const Value.absent(), diff --git a/lib/src/model/json/message.dart b/lib/src/model/json/message.dart index 8337415..641ce72 100644 --- a/lib/src/model/json/message.dart +++ b/lib/src/model/json/message.dart @@ -10,24 +10,30 @@ enum MessageKind { ack } +Map messageKindColors = { + "video": Colors.deepPurple, + "text": Colors.lightBlue, + "image": Color.fromARGB(255, 214, 47, 47), +}; + Color getMessageColorFromType(MessageContent content, Color primary) { Color color; if (content is TextMessageContent) { - color = Colors.lightBlue; + color = messageKindColors["text"]!; } else { if (content is MediaMessageContent) { if (content.isRealTwonly) { color = primary; } else { if (content.isVideo) { - color = Colors.deepPurple; + color = messageKindColors["video"]!; } else { - color = const Color.fromARGB(255, 214, 47, 47); + color = messageKindColors["image"]!; } } } else { - return Colors.black; // this should not happen + return Colors.black; } } return color; diff --git a/lib/src/proto/api/client_to_server.pb.dart b/lib/src/proto/api/client_to_server.pb.dart index 3b5d3ce..9f88704 100644 --- a/lib/src/proto/api/client_to_server.pb.dart +++ b/lib/src/proto/api/client_to_server.pb.dart @@ -330,13 +330,13 @@ class Handshake_Register extends $pb.GeneratedMessage { void clearRegistrationId() => clearField(7); } -class Handshake_GetChallenge extends $pb.GeneratedMessage { - factory Handshake_GetChallenge() => create(); - Handshake_GetChallenge._() : super(); - factory Handshake_GetChallenge.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory Handshake_GetChallenge.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); +class Handshake_GetAuthChallenge extends $pb.GeneratedMessage { + factory Handshake_GetAuthChallenge() => create(); + Handshake_GetAuthChallenge._() : super(); + factory Handshake_GetAuthChallenge.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Handshake_GetAuthChallenge.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake.GetChallenge', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake.GetAuthChallenge', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) ..hasRequiredFields = false ; @@ -344,26 +344,26 @@ class Handshake_GetChallenge extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - Handshake_GetChallenge clone() => Handshake_GetChallenge()..mergeFromMessage(this); + Handshake_GetAuthChallenge clone() => Handshake_GetAuthChallenge()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - Handshake_GetChallenge copyWith(void Function(Handshake_GetChallenge) updates) => super.copyWith((message) => updates(message as Handshake_GetChallenge)) as Handshake_GetChallenge; + Handshake_GetAuthChallenge copyWith(void Function(Handshake_GetAuthChallenge) updates) => super.copyWith((message) => updates(message as Handshake_GetAuthChallenge)) as Handshake_GetAuthChallenge; $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static Handshake_GetChallenge create() => Handshake_GetChallenge._(); - Handshake_GetChallenge createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static Handshake_GetAuthChallenge create() => Handshake_GetAuthChallenge._(); + Handshake_GetAuthChallenge createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static Handshake_GetChallenge getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Handshake_GetChallenge? _defaultInstance; + static Handshake_GetAuthChallenge getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Handshake_GetAuthChallenge? _defaultInstance; } -class Handshake_OpenSession extends $pb.GeneratedMessage { - factory Handshake_OpenSession({ +class Handshake_GetAuthToken extends $pb.GeneratedMessage { + factory Handshake_GetAuthToken({ $fixnum.Int64? userId, $core.List<$core.int>? response, }) { @@ -376,11 +376,11 @@ class Handshake_OpenSession extends $pb.GeneratedMessage { } return $result; } - Handshake_OpenSession._() : super(); - factory Handshake_OpenSession.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory Handshake_OpenSession.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + Handshake_GetAuthToken._() : super(); + factory Handshake_GetAuthToken.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Handshake_GetAuthToken.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake.OpenSession', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake.GetAuthToken', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) ..aInt64(1, _omitFieldNames ? '' : 'userId') ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'response', $pb.PbFieldType.OY) ..hasRequiredFields = false @@ -390,22 +390,22 @@ class Handshake_OpenSession extends $pb.GeneratedMessage { 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - Handshake_OpenSession clone() => Handshake_OpenSession()..mergeFromMessage(this); + Handshake_GetAuthToken clone() => Handshake_GetAuthToken()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - Handshake_OpenSession copyWith(void Function(Handshake_OpenSession) updates) => super.copyWith((message) => updates(message as Handshake_OpenSession)) as Handshake_OpenSession; + Handshake_GetAuthToken copyWith(void Function(Handshake_GetAuthToken) updates) => super.copyWith((message) => updates(message as Handshake_GetAuthToken)) as Handshake_GetAuthToken; $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static Handshake_OpenSession create() => Handshake_OpenSession._(); - Handshake_OpenSession createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static Handshake_GetAuthToken create() => Handshake_GetAuthToken._(); + Handshake_GetAuthToken createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static Handshake_OpenSession getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Handshake_OpenSession? _defaultInstance; + static Handshake_GetAuthToken getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Handshake_GetAuthToken? _defaultInstance; @$pb.TagNumber(1) $fixnum.Int64 get userId => $_getI64(0); @@ -426,28 +426,97 @@ class Handshake_OpenSession extends $pb.GeneratedMessage { void clearResponse() => clearField(2); } +class Handshake_Authenticate extends $pb.GeneratedMessage { + factory Handshake_Authenticate({ + $fixnum.Int64? userId, + $core.List<$core.int>? authToken, + }) { + final $result = create(); + if (userId != null) { + $result.userId = userId; + } + if (authToken != null) { + $result.authToken = authToken; + } + return $result; + } + Handshake_Authenticate._() : super(); + factory Handshake_Authenticate.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Handshake_Authenticate.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake.Authenticate', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) + ..aInt64(1, _omitFieldNames ? '' : 'userId') + ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'authToken', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + Handshake_Authenticate clone() => Handshake_Authenticate()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + Handshake_Authenticate copyWith(void Function(Handshake_Authenticate) updates) => super.copyWith((message) => updates(message as Handshake_Authenticate)) as Handshake_Authenticate; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Handshake_Authenticate create() => Handshake_Authenticate._(); + Handshake_Authenticate createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static Handshake_Authenticate getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Handshake_Authenticate? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get userId => $_getI64(0); + @$pb.TagNumber(1) + set userId($fixnum.Int64 v) { $_setInt64(0, v); } + @$pb.TagNumber(1) + $core.bool hasUserId() => $_has(0); + @$pb.TagNumber(1) + void clearUserId() => clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get authToken => $_getN(1); + @$pb.TagNumber(2) + set authToken($core.List<$core.int> v) { $_setBytes(1, v); } + @$pb.TagNumber(2) + $core.bool hasAuthToken() => $_has(1); + @$pb.TagNumber(2) + void clearAuthToken() => clearField(2); +} + enum Handshake_Handshake { register, - getchallenge, - opensession, + getauthchallenge, + getauthtoken, + authenticate, notSet } class Handshake extends $pb.GeneratedMessage { factory Handshake({ Handshake_Register? register, - Handshake_GetChallenge? getchallenge, - Handshake_OpenSession? opensession, + Handshake_GetAuthChallenge? getauthchallenge, + Handshake_GetAuthToken? getauthtoken, + Handshake_Authenticate? authenticate, }) { final $result = create(); if (register != null) { $result.register = register; } - if (getchallenge != null) { - $result.getchallenge = getchallenge; + if (getauthchallenge != null) { + $result.getauthchallenge = getauthchallenge; } - if (opensession != null) { - $result.opensession = opensession; + if (getauthtoken != null) { + $result.getauthtoken = getauthtoken; + } + if (authenticate != null) { + $result.authenticate = authenticate; } return $result; } @@ -457,15 +526,17 @@ class Handshake extends $pb.GeneratedMessage { static const $core.Map<$core.int, Handshake_Handshake> _Handshake_HandshakeByTag = { 1 : Handshake_Handshake.register, - 2 : Handshake_Handshake.getchallenge, - 3 : Handshake_Handshake.opensession, + 2 : Handshake_Handshake.getauthchallenge, + 3 : Handshake_Handshake.getauthtoken, + 4 : Handshake_Handshake.authenticate, 0 : Handshake_Handshake.notSet }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) - ..oo(0, [1, 2, 3]) + ..oo(0, [1, 2, 3, 4]) ..aOM(1, _omitFieldNames ? '' : 'register', subBuilder: Handshake_Register.create) - ..aOM(2, _omitFieldNames ? '' : 'getchallenge', subBuilder: Handshake_GetChallenge.create) - ..aOM(3, _omitFieldNames ? '' : 'opensession', subBuilder: Handshake_OpenSession.create) + ..aOM(2, _omitFieldNames ? '' : 'getauthchallenge', subBuilder: Handshake_GetAuthChallenge.create) + ..aOM(3, _omitFieldNames ? '' : 'getauthtoken', subBuilder: Handshake_GetAuthToken.create) + ..aOM(4, _omitFieldNames ? '' : 'authenticate', subBuilder: Handshake_Authenticate.create) ..hasRequiredFields = false ; @@ -505,26 +576,37 @@ class Handshake extends $pb.GeneratedMessage { Handshake_Register ensureRegister() => $_ensure(0); @$pb.TagNumber(2) - Handshake_GetChallenge get getchallenge => $_getN(1); + Handshake_GetAuthChallenge get getauthchallenge => $_getN(1); @$pb.TagNumber(2) - set getchallenge(Handshake_GetChallenge v) { setField(2, v); } + set getauthchallenge(Handshake_GetAuthChallenge v) { setField(2, v); } @$pb.TagNumber(2) - $core.bool hasGetchallenge() => $_has(1); + $core.bool hasGetauthchallenge() => $_has(1); @$pb.TagNumber(2) - void clearGetchallenge() => clearField(2); + void clearGetauthchallenge() => clearField(2); @$pb.TagNumber(2) - Handshake_GetChallenge ensureGetchallenge() => $_ensure(1); + Handshake_GetAuthChallenge ensureGetauthchallenge() => $_ensure(1); @$pb.TagNumber(3) - Handshake_OpenSession get opensession => $_getN(2); + Handshake_GetAuthToken get getauthtoken => $_getN(2); @$pb.TagNumber(3) - set opensession(Handshake_OpenSession v) { setField(3, v); } + set getauthtoken(Handshake_GetAuthToken v) { setField(3, v); } @$pb.TagNumber(3) - $core.bool hasOpensession() => $_has(2); + $core.bool hasGetauthtoken() => $_has(2); @$pb.TagNumber(3) - void clearOpensession() => clearField(3); + void clearGetauthtoken() => clearField(3); @$pb.TagNumber(3) - Handshake_OpenSession ensureOpensession() => $_ensure(2); + Handshake_GetAuthToken ensureGetauthtoken() => $_ensure(2); + + @$pb.TagNumber(4) + Handshake_Authenticate get authenticate => $_getN(3); + @$pb.TagNumber(4) + set authenticate(Handshake_Authenticate v) { setField(4, v); } + @$pb.TagNumber(4) + $core.bool hasAuthenticate() => $_has(3); + @$pb.TagNumber(4) + void clearAuthenticate() => clearField(4); + @$pb.TagNumber(4) + Handshake_Authenticate ensureAuthenticate() => $_ensure(3); } class ApplicationData_TextMessage extends $pb.GeneratedMessage { @@ -792,12 +874,21 @@ class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage { } class ApplicationData_GetUploadToken extends $pb.GeneratedMessage { - factory ApplicationData_GetUploadToken() => create(); + factory ApplicationData_GetUploadToken({ + $core.int? recipientsCount, + }) { + final $result = create(); + if (recipientsCount != null) { + $result.recipientsCount = recipientsCount; + } + return $result; + } ApplicationData_GetUploadToken._() : super(); factory ApplicationData_GetUploadToken.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); factory ApplicationData_GetUploadToken.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.GetUploadToken', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) + ..a<$core.int>(1, _omitFieldNames ? '' : 'recipientsCount', $pb.PbFieldType.OU3) ..hasRequiredFields = false ; @@ -821,6 +912,15 @@ class ApplicationData_GetUploadToken extends $pb.GeneratedMessage { @$core.pragma('dart2js:noInline') static ApplicationData_GetUploadToken getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static ApplicationData_GetUploadToken? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get recipientsCount => $_getIZ(0); + @$pb.TagNumber(1) + set recipientsCount($core.int v) { $_setUnsignedInt32(0, v); } + @$pb.TagNumber(1) + $core.bool hasRecipientsCount() => $_has(0); + @$pb.TagNumber(1) + void clearRecipientsCount() => clearField(1); } class ApplicationData_UploadData extends $pb.GeneratedMessage { @@ -828,6 +928,7 @@ class ApplicationData_UploadData extends $pb.GeneratedMessage { $core.List<$core.int>? uploadToken, $core.int? offset, $core.List<$core.int>? data, + $core.List<$core.int>? checksum, }) { final $result = create(); if (uploadToken != null) { @@ -839,6 +940,9 @@ class ApplicationData_UploadData extends $pb.GeneratedMessage { if (data != null) { $result.data = data; } + if (checksum != null) { + $result.checksum = checksum; + } return $result; } ApplicationData_UploadData._() : super(); @@ -849,6 +953,7 @@ class ApplicationData_UploadData extends $pb.GeneratedMessage { ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'uploadToken', $pb.PbFieldType.OY) ..a<$core.int>(2, _omitFieldNames ? '' : 'offset', $pb.PbFieldType.OU3) ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'data', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'checksum', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -899,16 +1004,25 @@ class ApplicationData_UploadData extends $pb.GeneratedMessage { $core.bool hasData() => $_has(2); @$pb.TagNumber(3) void clearData() => clearField(3); + + @$pb.TagNumber(4) + $core.List<$core.int> get checksum => $_getN(3); + @$pb.TagNumber(4) + set checksum($core.List<$core.int> v) { $_setBytes(3, v); } + @$pb.TagNumber(4) + $core.bool hasChecksum() => $_has(3); + @$pb.TagNumber(4) + void clearChecksum() => clearField(4); } class ApplicationData_DownloadData extends $pb.GeneratedMessage { factory ApplicationData_DownloadData({ - $core.List<$core.int>? uploadToken, + $core.List<$core.int>? downloadToken, $core.int? offset, }) { final $result = create(); - if (uploadToken != null) { - $result.uploadToken = uploadToken; + if (downloadToken != null) { + $result.downloadToken = downloadToken; } if (offset != null) { $result.offset = offset; @@ -920,7 +1034,7 @@ class ApplicationData_DownloadData extends $pb.GeneratedMessage { factory ApplicationData_DownloadData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.DownloadData', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) - ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'uploadToken', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'downloadToken', $pb.PbFieldType.OY) ..a<$core.int>(2, _omitFieldNames ? '' : 'offset', $pb.PbFieldType.OU3) ..hasRequiredFields = false ; @@ -947,13 +1061,13 @@ class ApplicationData_DownloadData extends $pb.GeneratedMessage { static ApplicationData_DownloadData? _defaultInstance; @$pb.TagNumber(1) - $core.List<$core.int> get uploadToken => $_getN(0); + $core.List<$core.int> get downloadToken => $_getN(0); @$pb.TagNumber(1) - set uploadToken($core.List<$core.int> v) { $_setBytes(0, v); } + set downloadToken($core.List<$core.int> v) { $_setBytes(0, v); } @$pb.TagNumber(1) - $core.bool hasUploadToken() => $_has(0); + $core.bool hasDownloadToken() => $_has(0); @$pb.TagNumber(1) - void clearUploadToken() => clearField(1); + void clearDownloadToken() => clearField(1); @$pb.TagNumber(2) $core.int get offset => $_getIZ(1); diff --git a/lib/src/proto/api/client_to_server.pbjson.dart b/lib/src/proto/api/client_to_server.pbjson.dart index e8e3f97..80cabae 100644 --- a/lib/src/proto/api/client_to_server.pbjson.dart +++ b/lib/src/proto/api/client_to_server.pbjson.dart @@ -56,10 +56,11 @@ const Handshake$json = { '1': 'Handshake', '2': [ {'1': 'register', '3': 1, '4': 1, '5': 11, '6': '.client_to_server.Handshake.Register', '9': 0, '10': 'register'}, - {'1': 'getchallenge', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.Handshake.GetChallenge', '9': 0, '10': 'getchallenge'}, - {'1': 'opensession', '3': 3, '4': 1, '5': 11, '6': '.client_to_server.Handshake.OpenSession', '9': 0, '10': 'opensession'}, + {'1': 'getauthchallenge', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.Handshake.GetAuthChallenge', '9': 0, '10': 'getauthchallenge'}, + {'1': 'getauthtoken', '3': 3, '4': 1, '5': 11, '6': '.client_to_server.Handshake.GetAuthToken', '9': 0, '10': 'getauthtoken'}, + {'1': 'authenticate', '3': 4, '4': 1, '5': 11, '6': '.client_to_server.Handshake.Authenticate', '9': 0, '10': 'authenticate'}, ], - '3': [Handshake_Register$json, Handshake_GetChallenge$json, Handshake_OpenSession$json], + '3': [Handshake_Register$json, Handshake_GetAuthChallenge$json, Handshake_GetAuthToken$json, Handshake_Authenticate$json], '8': [ {'1': 'Handshake'}, ], @@ -83,33 +84,45 @@ const Handshake_Register$json = { }; @$core.Deprecated('Use handshakeDescriptor instead') -const Handshake_GetChallenge$json = { - '1': 'GetChallenge', +const Handshake_GetAuthChallenge$json = { + '1': 'GetAuthChallenge', }; @$core.Deprecated('Use handshakeDescriptor instead') -const Handshake_OpenSession$json = { - '1': 'OpenSession', +const Handshake_GetAuthToken$json = { + '1': 'GetAuthToken', '2': [ {'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'}, {'1': 'response', '3': 2, '4': 1, '5': 12, '10': 'response'}, ], }; +@$core.Deprecated('Use handshakeDescriptor instead') +const Handshake_Authenticate$json = { + '1': 'Authenticate', + '2': [ + {'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'}, + {'1': 'auth_token', '3': 2, '4': 1, '5': 12, '10': 'authToken'}, + ], +}; + /// Descriptor for `Handshake`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List handshakeDescriptor = $convert.base64Decode( 'CglIYW5kc2hha2USQgoIcmVnaXN0ZXIYASABKAsyJC5jbGllbnRfdG9fc2VydmVyLkhhbmRzaG' - 'FrZS5SZWdpc3RlckgAUghyZWdpc3RlchJOCgxnZXRjaGFsbGVuZ2UYAiABKAsyKC5jbGllbnRf' - 'dG9fc2VydmVyLkhhbmRzaGFrZS5HZXRDaGFsbGVuZ2VIAFIMZ2V0Y2hhbGxlbmdlEksKC29wZW' - '5zZXNzaW9uGAMgASgLMicuY2xpZW50X3RvX3NlcnZlci5IYW5kc2hha2UuT3BlblNlc3Npb25I' - 'AFILb3BlbnNlc3Npb24avAIKCFJlZ2lzdGVyEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZR' - 'IkCgtpbnZpdGVfY29kZRgCIAEoCUgAUgppbnZpdGVDb2RliAEBEi4KE3B1YmxpY19pZGVudGl0' - 'eV9rZXkYAyABKAxSEXB1YmxpY0lkZW50aXR5S2V5EiMKDXNpZ25lZF9wcmVrZXkYBCABKAxSDH' - 'NpZ25lZFByZWtleRI2ChdzaWduZWRfcHJla2V5X3NpZ25hdHVyZRgFIAEoDFIVc2lnbmVkUHJl' - 'a2V5U2lnbmF0dXJlEigKEHNpZ25lZF9wcmVrZXlfaWQYBiABKANSDnNpZ25lZFByZWtleUlkEi' - 'cKD3JlZ2lzdHJhdGlvbl9pZBgHIAEoA1IOcmVnaXN0cmF0aW9uSWRCDgoMX2ludml0ZV9jb2Rl' - 'Gg4KDEdldENoYWxsZW5nZRpCCgtPcGVuU2Vzc2lvbhIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySW' - 'QSGgoIcmVzcG9uc2UYAiABKAxSCHJlc3BvbnNlQgsKCUhhbmRzaGFrZQ=='); + 'FrZS5SZWdpc3RlckgAUghyZWdpc3RlchJaChBnZXRhdXRoY2hhbGxlbmdlGAIgASgLMiwuY2xp' + 'ZW50X3RvX3NlcnZlci5IYW5kc2hha2UuR2V0QXV0aENoYWxsZW5nZUgAUhBnZXRhdXRoY2hhbG' + 'xlbmdlEk4KDGdldGF1dGh0b2tlbhgDIAEoCzIoLmNsaWVudF90b19zZXJ2ZXIuSGFuZHNoYWtl' + 'LkdldEF1dGhUb2tlbkgAUgxnZXRhdXRodG9rZW4STgoMYXV0aGVudGljYXRlGAQgASgLMiguY2' + 'xpZW50X3RvX3NlcnZlci5IYW5kc2hha2UuQXV0aGVudGljYXRlSABSDGF1dGhlbnRpY2F0ZRq8' + 'AgoIUmVnaXN0ZXISGgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW1lEiQKC2ludml0ZV9jb2RlGA' + 'IgASgJSABSCmludml0ZUNvZGWIAQESLgoTcHVibGljX2lkZW50aXR5X2tleRgDIAEoDFIRcHVi' + 'bGljSWRlbnRpdHlLZXkSIwoNc2lnbmVkX3ByZWtleRgEIAEoDFIMc2lnbmVkUHJla2V5EjYKF3' + 'NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAUgASgMUhVzaWduZWRQcmVrZXlTaWduYXR1cmUSKAoQ' + 'c2lnbmVkX3ByZWtleV9pZBgGIAEoA1IOc2lnbmVkUHJla2V5SWQSJwoPcmVnaXN0cmF0aW9uX2' + 'lkGAcgASgDUg5yZWdpc3RyYXRpb25JZEIOCgxfaW52aXRlX2NvZGUaEgoQR2V0QXV0aENoYWxs' + 'ZW5nZRpDCgxHZXRBdXRoVG9rZW4SFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhoKCHJlc3Bvbn' + 'NlGAIgASgMUghyZXNwb25zZRpGCgxBdXRoZW50aWNhdGUSFwoHdXNlcl9pZBgBIAEoA1IGdXNl' + 'cklkEh0KCmF1dGhfdG9rZW4YAiABKAxSCWF1dGhUb2tlbkILCglIYW5kc2hha2U='); @$core.Deprecated('Use applicationDataDescriptor instead') const ApplicationData$json = { @@ -174,6 +187,9 @@ const ApplicationData_GetPrekeysByUserId$json = { @$core.Deprecated('Use applicationDataDescriptor instead') const ApplicationData_GetUploadToken$json = { '1': 'GetUploadToken', + '2': [ + {'1': 'recipients_count', '3': 1, '4': 1, '5': 13, '10': 'recipientsCount'}, + ], }; @$core.Deprecated('Use applicationDataDescriptor instead') @@ -183,6 +199,10 @@ const ApplicationData_UploadData$json = { {'1': 'upload_token', '3': 1, '4': 1, '5': 12, '10': 'uploadToken'}, {'1': 'offset', '3': 2, '4': 1, '5': 13, '10': 'offset'}, {'1': 'data', '3': 3, '4': 1, '5': 12, '10': 'data'}, + {'1': 'checksum', '3': 4, '4': 1, '5': 12, '9': 0, '10': 'checksum', '17': true}, + ], + '8': [ + {'1': '_checksum'}, ], }; @@ -190,7 +210,7 @@ const ApplicationData_UploadData$json = { const ApplicationData_DownloadData$json = { '1': 'DownloadData', '2': [ - {'1': 'upload_token', '3': 1, '4': 1, '5': 12, '10': 'uploadToken'}, + {'1': 'download_token', '3': 1, '4': 1, '5': 12, '10': 'downloadToken'}, {'1': 'offset', '3': 2, '4': 1, '5': 13, '10': 'offset'}, ], }; @@ -215,10 +235,12 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode( 'JuYW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRo1ChRVcGRhdGVHb29nbGVGY21Ub2tl' 'bhIdCgpnb29nbGVfZmNtGAEgASgJUglnb29nbGVGY20aJgoLR2V0VXNlckJ5SWQSFwoHdXNlcl' '9pZBgBIAEoA1IGdXNlcklkGi0KEkdldFByZWtleXNCeVVzZXJJZBIXCgd1c2VyX2lkGAEgASgD' - 'UgZ1c2VySWQaEAoOR2V0VXBsb2FkVG9rZW4aWwoKVXBsb2FkRGF0YRIhCgx1cGxvYWRfdG9rZW' - '4YASABKAxSC3VwbG9hZFRva2VuEhYKBm9mZnNldBgCIAEoDVIGb2Zmc2V0EhIKBGRhdGEYAyAB' - 'KAxSBGRhdGEaSQoMRG93bmxvYWREYXRhEiEKDHVwbG9hZF90b2tlbhgBIAEoDFILdXBsb2FkVG' - '9rZW4SFgoGb2Zmc2V0GAIgASgNUgZvZmZzZXRCEQoPQXBwbGljYXRpb25EYXRh'); + 'UgZ1c2VySWQaOwoOR2V0VXBsb2FkVG9rZW4SKQoQcmVjaXBpZW50c19jb3VudBgBIAEoDVIPcm' + 'VjaXBpZW50c0NvdW50GokBCgpVcGxvYWREYXRhEiEKDHVwbG9hZF90b2tlbhgBIAEoDFILdXBs' + 'b2FkVG9rZW4SFgoGb2Zmc2V0GAIgASgNUgZvZmZzZXQSEgoEZGF0YRgDIAEoDFIEZGF0YRIfCg' + 'hjaGVja3N1bRgEIAEoDEgAUghjaGVja3N1bYgBAUILCglfY2hlY2tzdW0aTQoMRG93bmxvYWRE' + 'YXRhEiUKDmRvd25sb2FkX3Rva2VuGAEgASgMUg1kb3dubG9hZFRva2VuEhYKBm9mZnNldBgCIA' + 'EoDVIGb2Zmc2V0QhEKD0FwcGxpY2F0aW9uRGF0YQ=='); @$core.Deprecated('Use responseDescriptor instead') const Response$json = { diff --git a/lib/src/proto/api/error.pbenum.dart b/lib/src/proto/api/error.pbenum.dart index d2d4a26..e098fff 100644 --- a/lib/src/proto/api/error.pbenum.dart +++ b/lib/src/proto/api/error.pbenum.dart @@ -31,6 +31,12 @@ class ErrorCode extends $pb.ProtobufEnum { static const ErrorCode InvalidUpdateToken = ErrorCode._(1012, _omitEnumNames ? '' : 'InvalidUpdateToken'); static const ErrorCode InvalidOffset = ErrorCode._(1013, _omitEnumNames ? '' : 'InvalidOffset'); static const ErrorCode InvalidGoogleFcmToken = ErrorCode._(1014, _omitEnumNames ? '' : 'InvalidGoogleFcmToken'); + static const ErrorCode UploadTokenIsBlocked = ErrorCode._(1015, _omitEnumNames ? '' : 'UploadTokenIsBlocked'); + static const ErrorCode UploadChecksumInvalid = ErrorCode._(1016, _omitEnumNames ? '' : 'UploadChecksumInvalid'); + static const ErrorCode InvalidDownloadToken = ErrorCode._(1017, _omitEnumNames ? '' : 'InvalidDownloadToken'); + static const ErrorCode ApiEndpointNotFound = ErrorCode._(1018, _omitEnumNames ? '' : 'ApiEndpointNotFound'); + static const ErrorCode AuthTokenNotValid = ErrorCode._(1019, _omitEnumNames ? '' : 'AuthTokenNotValid'); + static const ErrorCode InvalidPreKeys = ErrorCode._(1020, _omitEnumNames ? '' : 'InvalidPreKeys'); static const $core.List values = [ Unknown, @@ -50,6 +56,12 @@ class ErrorCode extends $pb.ProtobufEnum { InvalidUpdateToken, InvalidOffset, InvalidGoogleFcmToken, + UploadTokenIsBlocked, + UploadChecksumInvalid, + InvalidDownloadToken, + ApiEndpointNotFound, + AuthTokenNotValid, + InvalidPreKeys, ]; static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/lib/src/proto/api/error.pbjson.dart b/lib/src/proto/api/error.pbjson.dart index 68b54d9..ddf9c07 100644 --- a/lib/src/proto/api/error.pbjson.dart +++ b/lib/src/proto/api/error.pbjson.dart @@ -34,6 +34,12 @@ const ErrorCode$json = { {'1': 'InvalidUpdateToken', '2': 1012}, {'1': 'InvalidOffset', '2': 1013}, {'1': 'InvalidGoogleFcmToken', '2': 1014}, + {'1': 'UploadTokenIsBlocked', '2': 1015}, + {'1': 'UploadChecksumInvalid', '2': 1016}, + {'1': 'InvalidDownloadToken', '2': 1017}, + {'1': 'ApiEndpointNotFound', '2': 1018}, + {'1': 'AuthTokenNotValid', '2': 1019}, + {'1': 'InvalidPreKeys', '2': 1020}, ], }; @@ -46,5 +52,8 @@ final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode( 'bGljS2V5EO8HEiAKG1Nlc3Npb25BbHJlYWR5QXV0aGVudGljYXRlZBDwBxIcChdTZXNzaW9uTm' '90QXV0aGVudGljYXRlZBDxBxIaChVPbmx5T25lU2Vzc2lvbkFsbG93ZWQQ8gcSFwoSVXBsb2Fk' 'TGltaXRSZWFjaGVkEPMHEhcKEkludmFsaWRVcGRhdGVUb2tlbhD0BxISCg1JbnZhbGlkT2Zmc2' - 'V0EPUHEhoKFUludmFsaWRHb29nbGVGY21Ub2tlbhD2Bw=='); + 'V0EPUHEhoKFUludmFsaWRHb29nbGVGY21Ub2tlbhD2BxIZChRVcGxvYWRUb2tlbklzQmxvY2tl' + 'ZBD3BxIaChVVcGxvYWRDaGVja3N1bUludmFsaWQQ+AcSGQoUSW52YWxpZERvd25sb2FkVG9rZW' + '4Q+QcSGAoTQXBpRW5kcG9pbnROb3RGb3VuZBD6BxIWChFBdXRoVG9rZW5Ob3RWYWxpZBD7BxIT' + 'Cg5JbnZhbGlkUHJlS2V5cxD8Bw=='); diff --git a/lib/src/proto/api/server_to_client.pb.dart b/lib/src/proto/api/server_to_client.pb.dart index f6f6d03..799a420 100644 --- a/lib/src/proto/api/server_to_client.pb.dart +++ b/lib/src/proto/api/server_to_client.pb.dart @@ -86,6 +86,7 @@ enum V0_Kind { newMessage, requestNewPreKeys, downloaddata, + error, notSet } @@ -96,6 +97,7 @@ class V0 extends $pb.GeneratedMessage { NewMessage? newMessage, $core.bool? requestNewPreKeys, DownloadData? downloaddata, + $0.ErrorCode? error, }) { final $result = create(); if (seq != null) { @@ -113,6 +115,9 @@ class V0 extends $pb.GeneratedMessage { if (downloaddata != null) { $result.downloaddata = downloaddata; } + if (error != null) { + $result.error = error; + } return $result; } V0._() : super(); @@ -124,15 +129,17 @@ class V0 extends $pb.GeneratedMessage { 3 : V0_Kind.newMessage, 4 : V0_Kind.requestNewPreKeys, 5 : V0_Kind.downloaddata, + 6 : V0_Kind.error, 0 : V0_Kind.notSet }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'V0', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create) - ..oo(0, [2, 3, 4, 5]) + ..oo(0, [2, 3, 4, 5, 6]) ..a<$fixnum.Int64>(1, _omitFieldNames ? '' : 'seq', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO) ..aOM(2, _omitFieldNames ? '' : 'response', subBuilder: Response.create) ..aOM(3, _omitFieldNames ? '' : 'newMessage', protoName: 'newMessage', subBuilder: NewMessage.create) ..aOB(4, _omitFieldNames ? '' : 'RequestNewPreKeys', protoName: 'RequestNewPreKeys') ..aOM(5, _omitFieldNames ? '' : 'downloaddata', subBuilder: DownloadData.create) + ..e<$0.ErrorCode>(6, _omitFieldNames ? '' : 'error', $pb.PbFieldType.OE, defaultOrMaker: $0.ErrorCode.Unknown, valueOf: $0.ErrorCode.valueOf, enumValues: $0.ErrorCode.values) ..hasRequiredFields = false ; @@ -210,6 +217,15 @@ class V0 extends $pb.GeneratedMessage { void clearDownloaddata() => clearField(5); @$pb.TagNumber(5) DownloadData ensureDownloaddata() => $_ensure(4); + + @$pb.TagNumber(6) + $0.ErrorCode get error => $_getN(5); + @$pb.TagNumber(6) + set error($0.ErrorCode v) { setField(6, v); } + @$pb.TagNumber(6) + $core.bool hasError() => $_has(5); + @$pb.TagNumber(6) + void clearError() => clearField(6); } class NewMessage extends $pb.GeneratedMessage { @@ -560,12 +576,71 @@ class Response_UserData extends $pb.GeneratedMessage { void clearUsername() => clearField(7); } +class Response_UploadToken extends $pb.GeneratedMessage { + factory Response_UploadToken({ + $core.List<$core.int>? uploadToken, + $core.Iterable<$core.List<$core.int>>? downloadTokens, + }) { + final $result = create(); + if (uploadToken != null) { + $result.uploadToken = uploadToken; + } + if (downloadTokens != null) { + $result.downloadTokens.addAll(downloadTokens); + } + return $result; + } + Response_UploadToken._() : super(); + factory Response_UploadToken.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Response_UploadToken.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response.UploadToken', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create) + ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'uploadToken', $pb.PbFieldType.OY) + ..p<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'downloadTokens', $pb.PbFieldType.PY) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + Response_UploadToken clone() => Response_UploadToken()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + Response_UploadToken copyWith(void Function(Response_UploadToken) updates) => super.copyWith((message) => updates(message as Response_UploadToken)) as Response_UploadToken; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response_UploadToken create() => Response_UploadToken._(); + Response_UploadToken createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static Response_UploadToken getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response_UploadToken? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get uploadToken => $_getN(0); + @$pb.TagNumber(1) + set uploadToken($core.List<$core.int> v) { $_setBytes(0, v); } + @$pb.TagNumber(1) + $core.bool hasUploadToken() => $_has(0); + @$pb.TagNumber(1) + void clearUploadToken() => clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.List<$core.int>> get downloadTokens => $_getList(1); +} + enum Response_Ok_Ok { none, userid, - challenge, + authchallenge, uploadtoken, userdata, + authtoken, notSet } @@ -573,9 +648,10 @@ class Response_Ok extends $pb.GeneratedMessage { factory Response_Ok({ $core.bool? none, $fixnum.Int64? userid, - $core.List<$core.int>? challenge, - $core.List<$core.int>? uploadtoken, + $core.List<$core.int>? authchallenge, + Response_UploadToken? uploadtoken, Response_UserData? userdata, + $core.List<$core.int>? authtoken, }) { final $result = create(); if (none != null) { @@ -584,8 +660,8 @@ class Response_Ok extends $pb.GeneratedMessage { if (userid != null) { $result.userid = userid; } - if (challenge != null) { - $result.challenge = challenge; + if (authchallenge != null) { + $result.authchallenge = authchallenge; } if (uploadtoken != null) { $result.uploadtoken = uploadtoken; @@ -593,6 +669,9 @@ class Response_Ok extends $pb.GeneratedMessage { if (userdata != null) { $result.userdata = userdata; } + if (authtoken != null) { + $result.authtoken = authtoken; + } return $result; } Response_Ok._() : super(); @@ -602,18 +681,20 @@ class Response_Ok extends $pb.GeneratedMessage { static const $core.Map<$core.int, Response_Ok_Ok> _Response_Ok_OkByTag = { 1 : Response_Ok_Ok.none, 2 : Response_Ok_Ok.userid, - 3 : Response_Ok_Ok.challenge, + 3 : Response_Ok_Ok.authchallenge, 4 : Response_Ok_Ok.uploadtoken, 5 : Response_Ok_Ok.userdata, + 6 : Response_Ok_Ok.authtoken, 0 : Response_Ok_Ok.notSet }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response.Ok', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5]) + ..oo(0, [1, 2, 3, 4, 5, 6]) ..aOB(1, _omitFieldNames ? '' : 'None', protoName: 'None') ..aInt64(2, _omitFieldNames ? '' : 'userid') - ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'challenge', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'uploadtoken', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'authchallenge', $pb.PbFieldType.OY) + ..aOM(4, _omitFieldNames ? '' : 'uploadtoken', subBuilder: Response_UploadToken.create) ..aOM(5, _omitFieldNames ? '' : 'userdata', subBuilder: Response_UserData.create) + ..a<$core.List<$core.int>>(6, _omitFieldNames ? '' : 'authtoken', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -660,22 +741,24 @@ class Response_Ok extends $pb.GeneratedMessage { void clearUserid() => clearField(2); @$pb.TagNumber(3) - $core.List<$core.int> get challenge => $_getN(2); + $core.List<$core.int> get authchallenge => $_getN(2); @$pb.TagNumber(3) - set challenge($core.List<$core.int> v) { $_setBytes(2, v); } + set authchallenge($core.List<$core.int> v) { $_setBytes(2, v); } @$pb.TagNumber(3) - $core.bool hasChallenge() => $_has(2); + $core.bool hasAuthchallenge() => $_has(2); @$pb.TagNumber(3) - void clearChallenge() => clearField(3); + void clearAuthchallenge() => clearField(3); @$pb.TagNumber(4) - $core.List<$core.int> get uploadtoken => $_getN(3); + Response_UploadToken get uploadtoken => $_getN(3); @$pb.TagNumber(4) - set uploadtoken($core.List<$core.int> v) { $_setBytes(3, v); } + set uploadtoken(Response_UploadToken v) { setField(4, v); } @$pb.TagNumber(4) $core.bool hasUploadtoken() => $_has(3); @$pb.TagNumber(4) void clearUploadtoken() => clearField(4); + @$pb.TagNumber(4) + Response_UploadToken ensureUploadtoken() => $_ensure(3); @$pb.TagNumber(5) Response_UserData get userdata => $_getN(4); @@ -687,6 +770,15 @@ class Response_Ok extends $pb.GeneratedMessage { void clearUserdata() => clearField(5); @$pb.TagNumber(5) Response_UserData ensureUserdata() => $_ensure(4); + + @$pb.TagNumber(6) + $core.List<$core.int> get authtoken => $_getN(5); + @$pb.TagNumber(6) + set authtoken($core.List<$core.int> v) { $_setBytes(5, v); } + @$pb.TagNumber(6) + $core.bool hasAuthtoken() => $_has(5); + @$pb.TagNumber(6) + void clearAuthtoken() => clearField(6); } enum Response_Response { diff --git a/lib/src/proto/api/server_to_client.pbjson.dart b/lib/src/proto/api/server_to_client.pbjson.dart index 0a799ae..1bfa2d9 100644 --- a/lib/src/proto/api/server_to_client.pbjson.dart +++ b/lib/src/proto/api/server_to_client.pbjson.dart @@ -38,6 +38,7 @@ const V0$json = { {'1': 'newMessage', '3': 3, '4': 1, '5': 11, '6': '.server_to_client.NewMessage', '9': 0, '10': 'newMessage'}, {'1': 'RequestNewPreKeys', '3': 4, '4': 1, '5': 8, '9': 0, '10': 'RequestNewPreKeys'}, {'1': 'downloaddata', '3': 5, '4': 1, '5': 11, '6': '.server_to_client.DownloadData', '9': 0, '10': 'downloaddata'}, + {'1': 'error', '3': 6, '4': 1, '5': 14, '6': '.error.ErrorCode', '9': 0, '10': 'error'}, ], '8': [ {'1': 'Kind'}, @@ -50,7 +51,8 @@ final $typed_data.Uint8List v0Descriptor = $convert.base64Decode( 'llbnQuUmVzcG9uc2VIAFIIcmVzcG9uc2USPgoKbmV3TWVzc2FnZRgDIAEoCzIcLnNlcnZlcl90' 'b19jbGllbnQuTmV3TWVzc2FnZUgAUgpuZXdNZXNzYWdlEi4KEVJlcXVlc3ROZXdQcmVLZXlzGA' 'QgASgISABSEVJlcXVlc3ROZXdQcmVLZXlzEkQKDGRvd25sb2FkZGF0YRgFIAEoCzIeLnNlcnZl' - 'cl90b19jbGllbnQuRG93bmxvYWREYXRhSABSDGRvd25sb2FkZGF0YUIGCgRLaW5k'); + 'cl90b19jbGllbnQuRG93bmxvYWREYXRhSABSDGRvd25sb2FkZGF0YRIoCgVlcnJvchgGIAEoDj' + 'IQLmVycm9yLkVycm9yQ29kZUgAUgVlcnJvckIGCgRLaW5k'); @$core.Deprecated('Use newMessageDescriptor instead') const NewMessage$json = { @@ -89,7 +91,7 @@ const Response$json = { {'1': 'ok', '3': 1, '4': 1, '5': 11, '6': '.server_to_client.Response.Ok', '9': 0, '10': 'ok'}, {'1': 'error', '3': 2, '4': 1, '5': 14, '6': '.error.ErrorCode', '9': 0, '10': 'error'}, ], - '3': [Response_PreKey$json, Response_UserData$json, Response_Ok$json], + '3': [Response_PreKey$json, Response_UserData$json, Response_UploadToken$json, Response_Ok$json], '8': [ {'1': 'Response'}, ], @@ -125,14 +127,24 @@ const Response_UserData$json = { ], }; +@$core.Deprecated('Use responseDescriptor instead') +const Response_UploadToken$json = { + '1': 'UploadToken', + '2': [ + {'1': 'upload_token', '3': 1, '4': 1, '5': 12, '10': 'uploadToken'}, + {'1': 'download_tokens', '3': 2, '4': 3, '5': 12, '10': 'downloadTokens'}, + ], +}; + @$core.Deprecated('Use responseDescriptor instead') const Response_Ok$json = { '1': 'Ok', '2': [ {'1': 'None', '3': 1, '4': 1, '5': 8, '9': 0, '10': 'None'}, {'1': 'userid', '3': 2, '4': 1, '5': 3, '9': 0, '10': 'userid'}, - {'1': 'challenge', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'challenge'}, - {'1': 'uploadtoken', '3': 4, '4': 1, '5': 12, '9': 0, '10': 'uploadtoken'}, + {'1': 'authchallenge', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'authchallenge'}, + {'1': 'authtoken', '3': 6, '4': 1, '5': 12, '9': 0, '10': 'authtoken'}, + {'1': 'uploadtoken', '3': 4, '4': 1, '5': 11, '6': '.server_to_client.Response.UploadToken', '9': 0, '10': 'uploadtoken'}, {'1': 'userdata', '3': 5, '4': 1, '5': 11, '6': '.server_to_client.Response.UserData', '9': 0, '10': 'userdata'}, ], '8': [ @@ -152,9 +164,12 @@ final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( '9wcmVrZXlfc2lnbmF0dXJlGAUgASgMSANSFXNpZ25lZFByZWtleVNpZ25hdHVyZYgBARItChBz' 'aWduZWRfcHJla2V5X2lkGAYgASgDSARSDnNpZ25lZFByZWtleUlkiAEBQgsKCV91c2VybmFtZU' 'IWChRfcHVibGljX2lkZW50aXR5X2tleUIQCg5fc2lnbmVkX3ByZWtleUIaChhfc2lnbmVkX3By' - 'ZWtleV9zaWduYXR1cmVCEwoRX3NpZ25lZF9wcmVrZXlfaWQawQEKAk9rEhQKBE5vbmUYASABKA' - 'hIAFIETm9uZRIYCgZ1c2VyaWQYAiABKANIAFIGdXNlcmlkEh4KCWNoYWxsZW5nZRgDIAEoDEgA' - 'UgljaGFsbGVuZ2USIgoLdXBsb2FkdG9rZW4YBCABKAxIAFILdXBsb2FkdG9rZW4SQQoIdXNlcm' - 'RhdGEYBSABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlVzZXJEYXRhSABSCHVzZXJk' - 'YXRhQgQKAk9rQgoKCFJlc3BvbnNl'); + 'ZWtleV9zaWduYXR1cmVCEwoRX3NpZ25lZF9wcmVrZXlfaWQaWQoLVXBsb2FkVG9rZW4SIQoMdX' + 'Bsb2FkX3Rva2VuGAEgASgMUgt1cGxvYWRUb2tlbhInCg9kb3dubG9hZF90b2tlbnMYAiADKAxS' + 'DmRvd25sb2FkVG9rZW5zGpECCgJPaxIUCgROb25lGAEgASgISABSBE5vbmUSGAoGdXNlcmlkGA' + 'IgASgDSABSBnVzZXJpZBImCg1hdXRoY2hhbGxlbmdlGAMgASgMSABSDWF1dGhjaGFsbGVuZ2US' + 'HgoJYXV0aHRva2VuGAYgASgMSABSCWF1dGh0b2tlbhJKCgt1cGxvYWR0b2tlbhgEIAEoCzImLn' + 'NlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXBsb2FkVG9rZW5IAFILdXBsb2FkdG9rZW4SQQoI' + 'dXNlcmRhdGEYBSABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlVzZXJEYXRhSABSCH' + 'VzZXJkYXRhQgQKAk9rQgoKCFJlc3BvbnNl'); diff --git a/lib/src/providers/api_provider.dart b/lib/src/providers/api_provider.dart index 7753b47..39b5aac 100644 --- a/lib/src/providers/api_provider.dart +++ b/lib/src/providers/api_provider.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:collection'; +import 'dart:convert'; import 'dart:math'; import 'package:fixnum/fixnum.dart'; import 'package:flutter/foundation.dart'; @@ -62,6 +63,7 @@ class ApiProvider { // Function is called after the user is authenticated at the server Future onAuthenticated() async { + isAuthenticated = true; initFCMAfterAuthenticated(); } @@ -118,7 +120,6 @@ class ApiProvider { globalCallbackConnectionState(false); _channel = null; isAuthenticated = false; - // tryToReconnect(); } void _onError(dynamic e) { @@ -126,29 +127,6 @@ class ApiProvider { globalCallbackConnectionState(false); _channel = null; isAuthenticated = false; - tryToReconnect(); - } - - void tryToReconnect() { - return; - // if (globalIsAppInBackground) return; - // if (reconnectionTimer != null) { - // reconnectionTimer!.cancel(); - // } - - // final int randomDelay = Random().nextInt(20); - // final int delay = _reconnectionDelay + randomDelay; - - // debugPrint("Delay reconnection $delay"); - - // reconnectionTimer = Timer(Duration(seconds: delay), () async { - // // increase delay but set a maximum of 60 seconds (including the random delay) - // _reconnectionDelay = _reconnectionDelay * 2; - // if (_reconnectionDelay > 40) { - // _reconnectionDelay = 40; - // } - // await connect(); - // }); } void _onData(dynamic msgBuffer) { @@ -189,7 +167,7 @@ class ApiProvider { } } - Future _sendRequestV0(ClientToServer request, + Future sendRequestSync(ClientToServer request, {bool authenticated = true}) async { if (_channel == null) { log.shout("sending request, but api is not connected."); @@ -218,7 +196,7 @@ class ApiProvider { await authenticate(); if (isAuthenticated) { // this will send the request one more time. - return _sendRequestV0(request, authenticated: false); + return sendRequestSync(request, authenticated: false); } else { log.shout("Session is not authenticated."); return Result.error(ErrorCode.InternalError); @@ -229,48 +207,86 @@ class ApiProvider { return res; } + Future tryAuthenticateWithToken(int userId) async { + final storage = getSecureStorage(); + String? apiAuthToken = await storage.read(key: "api_auth_token"); + + if (apiAuthToken != null) { + final authenticate = Handshake_Authenticate() + ..userId = Int64(userId) + ..authToken = base64Decode(apiAuthToken); + + final handshake = Handshake()..authenticate = authenticate; + final req = createClientToServerFromHandshake(handshake); + + final result = await sendRequestSync(req, authenticated: false); + + if (result.isSuccess) { + log.info("Authenticated using api_auth_token"); + onAuthenticated(); + return true; + } + if (result.isError) { + if (result.error != ErrorCode.AuthTokenNotValid) { + log.shout("Error while authenticating using token", result); + return false; + } + } + } + return false; + } + Future authenticate() async { if (isAuthenticated) return; if (await SignalHelper.getSignalIdentity() == null) { return; } - var handshake = Handshake()..getchallenge = Handshake_GetChallenge(); - var req = createClientToServerFromHandshake(handshake); + final userData = await getUser(); + if (userData == null) return; - final result = await _sendRequestV0(req, authenticated: false); - if (result.isError) { - log.shout("Error auth", result); + if (await tryAuthenticateWithToken(userData.userId)) { return; } - final challenge = result.value.challenge; + var handshake = Handshake() + ..getauthchallenge = Handshake_GetAuthChallenge(); + var req = createClientToServerFromHandshake(handshake); + + final result = await sendRequestSync(req, authenticated: false); + if (result.isError) { + log.shout("Error requesting auth challenge", result); + return; + } + + final challenge = result.value.authchallenge; final privKey = await SignalHelper.getPrivateKey(); if (privKey == null) return; final random = getRandomUint8List(32); final signature = sign(privKey.serialize(), challenge, random); - final userData = await getUser(); - if (userData == null) return; - - var open = Handshake_OpenSession() + final getAuthToken = Handshake_GetAuthToken() ..response = signature ..userId = Int64(userData.userId); - var opensession = Handshake()..opensession = open; + final getauthtoken = Handshake()..getauthtoken = getAuthToken; - var req2 = createClientToServerFromHandshake(opensession); + var req2 = createClientToServerFromHandshake(getauthtoken); - final result2 = await _sendRequestV0(req2, authenticated: false); + final result2 = await sendRequestSync(req2, authenticated: false); if (result2.isError) { - log.shout("send request failed: ${result2.error}"); + log.shout("Error while sending auth challenge: ${result2.error}"); return; } - log.info("Authenticated!"); - onAuthenticated(); - isAuthenticated = true; + Uint8List apiAuthToken = result2.value.authtoken; + String apiAuthTokenB64 = base64Encode(apiAuthToken); + + final storage = getSecureStorage(); + await storage.write(key: "api_auth_token", value: apiAuthTokenB64); + + await tryAuthenticateWithToken(userData.userId); } Future register(String username, String? inviteCode) async { @@ -301,30 +317,30 @@ class ApiProvider { var handshake = Handshake()..register = register; var req = createClientToServerFromHandshake(handshake); - return await _sendRequestV0(req); + return await sendRequestSync(req); } Future getUsername(int userId) async { var get = ApplicationData_GetUserById()..userId = Int64(userId); var appData = ApplicationData()..getuserbyid = get; var req = createClientToServerFromApplicationData(appData); - return await _sendRequestV0(req); + return await sendRequestSync(req); } Future getUploadToken() async { var get = ApplicationData_GetUploadToken(); var appData = ApplicationData()..getuploadtoken = get; var req = createClientToServerFromApplicationData(appData); - return await _sendRequestV0(req); + return await sendRequestSync(req); } Future triggerDownload(List token, int offset) async { var get = ApplicationData_DownloadData() - ..uploadToken = token + ..downloadToken = token ..offset = offset; var appData = ApplicationData()..downloaddata = get; var req = createClientToServerFromApplicationData(appData); - return await _sendRequestV0(req); + return await sendRequestSync(req); } Future uploadData( @@ -335,7 +351,7 @@ class ApiProvider { ..offset = offset; var appData = ApplicationData()..uploaddata = get; var req = createClientToServerFromApplicationData(appData); - final result = await _sendRequestV0(req); + final result = await sendRequestSync(req); return result; } @@ -343,14 +359,14 @@ class ApiProvider { var get = ApplicationData_GetUserByUsername()..username = username; var appData = ApplicationData()..getuserbyusername = get; var req = createClientToServerFromApplicationData(appData); - return await _sendRequestV0(req); + return await sendRequestSync(req); } Future updateFCMToken(String googleFcm) async { var get = ApplicationData_UpdateGoogleFcmToken()..googleFcm = googleFcm; var appData = ApplicationData()..updategooglefcmtoken = get; var req = createClientToServerFromApplicationData(appData); - return await _sendRequestV0(req); + return await sendRequestSync(req); } Future sendTextMessage(int target, Uint8List msg) async { @@ -361,6 +377,6 @@ class ApiProvider { var appData = ApplicationData()..textmessage = testMessage; var req = createClientToServerFromApplicationData(appData); - return await _sendRequestV0(req); + return await sendRequestSync(req); } } diff --git a/lib/src/services/fcm_service.dart b/lib/src/services/fcm_service.dart index 013031a..0f87461 100644 --- a/lib/src/services/fcm_service.dart +++ b/lib/src/services/fcm_service.dart @@ -18,23 +18,27 @@ Future initFCMAfterAuthenticated() async { String? storedToken = await storage.read(key: "google_fcm"); - final fcmToken = await FirebaseMessaging.instance.getToken(); - if (fcmToken == null) { - Logger("init_fcm_service").shout("Error getting fcmToken"); - return; - } + try { + final fcmToken = await FirebaseMessaging.instance.getToken(); + if (fcmToken == null) { + Logger("init_fcm_service").shout("Error getting fcmToken"); + return; + } - if (storedToken == null || fcmToken != storedToken) { - await apiProvider.updateFCMToken(fcmToken); - await storage.write(key: "google_fcm", value: fcmToken); - } + if (storedToken == null || fcmToken != storedToken) { + await apiProvider.updateFCMToken(fcmToken); + await storage.write(key: "google_fcm", value: fcmToken); + } - FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) async { - await apiProvider.updateFCMToken(fcmToken); - await storage.write(key: "google_fcm", value: fcmToken); - }).onError((err) { - // Logger("init_fcm_service").shout("Error getting fcmToken"); - }); + FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) async { + await apiProvider.updateFCMToken(fcmToken); + await storage.write(key: "google_fcm", value: fcmToken); + }).onError((err) { + // Logger("init_fcm_service").shout("Error getting fcmToken"); + }); + } catch (e) { + Logger("fcm_service").shout("Error loading fcmToken: $e"); + } } Future initFCMService() async { diff --git a/lib/src/utils/misc.dart b/lib/src/utils/misc.dart index e198acd..b55de21 100644 --- a/lib/src/utils/misc.dart +++ b/lib/src/utils/misc.dart @@ -1,6 +1,5 @@ import 'dart:io'; import 'dart:math'; -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart'; @@ -44,8 +43,20 @@ Future writeLogToFile(LogRecord record) async { await logFile.writeAsString(logMessage, mode: FileMode.append); } +Future deleteLogFile() async { + final directory = await getApplicationDocumentsDirectory(); + final logFile = File('${directory.path}/app.log'); + + if (await logFile.exists()) { + await logFile.delete(); + return true; + } + return false; +} + // Just a helper function to get the secure storage FlutterSecureStorage getSecureStorage() { + // ignore: no_leading_underscores_for_local_identifiers AndroidOptions _getAndroidOptions() => const AndroidOptions( encryptedSharedPreferences: true, ); diff --git a/lib/src/utils/signal.dart b/lib/src/utils/signal.dart index d63ebc0..ba1d855 100644 --- a/lib/src/utils/signal.dart +++ b/lib/src/utils/signal.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:fixnum/fixnum.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; import 'package:logging/logging.dart'; import 'package:twonly/src/model/json/message.dart'; diff --git a/lib/src/views/chats/search_username_view.dart b/lib/src/views/chats/search_username_view.dart index 1e61bae..1521120 100644 --- a/lib/src/views/chats/search_username_view.dart +++ b/lib/src/views/chats/search_username_view.dart @@ -12,6 +12,7 @@ import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/providers/api/api.dart'; // ignore: library_prefixes import 'package:twonly/src/utils/signal.dart' as SignalHelper; +import 'package:twonly/src/utils/storage.dart'; class SearchUsernameView extends StatefulWidget { const SearchUsernameView({super.key}); @@ -23,8 +24,14 @@ class SearchUsernameView extends StatefulWidget { class _SearchUsernameView extends State { final TextEditingController searchUserName = TextEditingController(); bool _isLoading = false; + bool hasRequestedUsers = false; Future _addNewUser(BuildContext context) async { + final user = await getUser(); + if (user == null || user.username == searchUserName.text) { + return; + } + setState(() { _isLoading = true; }); @@ -44,14 +51,14 @@ class _SearchUsernameView extends State { int added = await twonlyDatabase.insertContact(ContactsCompanion( username: Value(searchUserName.text), - userId: Value(res.value.userdata.userId), + userId: Value(res.value.userdata.userId.toInt()), requested: Value(false), )); if (added > 0) { if (await SignalHelper.addNewContact(res.value.userdata)) { encryptAndSendMessage( - res.value.userdata.userId, + res.value.userdata.userId.toInt(), MessageJson( kind: MessageKind.contactRequest, timestamp: DateTime.now(), @@ -120,23 +127,21 @@ class _SearchUsernameView extends State { label: Text(context.lang.searchUsernameQrCodeBtn), ), SizedBox(height: 30), + if (hasRequestedUsers) + HeadLineComponent( + context.lang.searchUsernameNewFollowerTitle, + ), StreamBuilder( stream: contacts, builder: (context, snapshot) { - if (!snapshot.hasData || snapshot.data != null) { + if (!snapshot.hasData || + snapshot.data == null || + snapshot.data!.isEmpty) { + hasRequestedUsers = false; return Container(); } - final contacts = snapshot.data!; - if (contacts.isEmpty) { - return Container(); - } - return Row(children: [ - HeadLineComponent( - context.lang.searchUsernameNewFollowerTitle), - Expanded( - child: ContactsListView(contacts), - ) - ]); + hasRequestedUsers = true; + return Expanded(child: ContactsListView(snapshot.data!)); }, ) ], diff --git a/lib/src/views/onboarding/register_view.dart b/lib/src/views/onboarding/register_view.dart index 336da17..f07e6b7 100644 --- a/lib/src/views/onboarding/register_view.dart +++ b/lib/src/views/onboarding/register_view.dart @@ -39,7 +39,10 @@ class _RegisterViewState extends State { if (res.isSuccess) { Logger("create_new_user").info("Got user_id ${res.value} from server"); final userData = UserData( - userId: res.value.userid, username: username, displayName: username); + userId: res.value.userid.toInt(), + username: username, + displayName: username, + ); storage.write(key: "user_data", value: jsonEncode(userData)); } diff --git a/lib/src/views/settings/diagnostics_view.dart b/lib/src/views/settings/diagnostics_view.dart index 6356bd2..b141d7c 100644 --- a/lib/src/views/settings/diagnostics_view.dart +++ b/lib/src/views/settings/diagnostics_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'dart:io'; import 'package:path_provider/path_provider.dart'; import 'package:flutter/services.dart'; +import 'package:twonly/src/utils/misc.dart'; class DiagnosticsView extends StatelessWidget { const DiagnosticsView({super.key}); @@ -45,17 +46,14 @@ class DiagnosticsView extends StatelessWidget { ), TextButton( onPressed: () async { - final directory = - await getApplicationDocumentsDirectory(); - final logFile = File('${directory.path}/app.log'); - - if (await logFile.exists()) { - await logFile.delete(); + if (await deleteLogFile()) { + if (!context.mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Log file deleted!')), ); } else { + if (!context.mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Log file does not exist.')),