diff --git a/lib/src/components/initialsavatar_component.dart b/lib/src/components/initialsavatar_component.dart index ef86654..b8d8483 100644 --- a/lib/src/components/initialsavatar_component.dart +++ b/lib/src/components/initialsavatar_component.dart @@ -2,8 +2,10 @@ import 'package:flutter/material.dart'; class InitialsAvatar extends StatelessWidget { final String displayName; + final double? fontSize; - const InitialsAvatar({super.key, required this.displayName}); + const InitialsAvatar( + {super.key, required this.displayName, this.fontSize = 20}); @override Widget build(BuildContext context) { @@ -25,12 +27,13 @@ class InitialsAvatar extends StatelessWidget { return CircleAvatar( backgroundColor: avatarColor, + radius: fontSize, child: Text( initials, style: TextStyle( color: _getTextColor(avatarColor), fontWeight: FontWeight.normal, - fontSize: 20, + fontSize: fontSize, ), ), ); diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index bd1ea6e..654d514 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -8,6 +8,7 @@ "registerSubmitButton": "Register now!", "newMessageTitle": "New message", "chatsTitle": "Chats", + "shareImageTitle": "Share image", "shareImagedEditorSendImage": "Send", "shareImagedEditorSaveImage": "Save", "shareImagedEditorSavedImage": "Saved", diff --git a/lib/src/model/contacts_model.dart b/lib/src/model/contacts_model.dart index 440ffff..ffe0c21 100644 --- a/lib/src/model/contacts_model.dart +++ b/lib/src/model/contacts_model.dart @@ -1,11 +1,10 @@ -import 'dart:typed_data'; - import 'package:cv/cv.dart'; +import 'package:fixnum/fixnum.dart'; import 'package:twonly/main.dart'; class Contact { Contact({required this.userId, required this.displayName}); - final Uint8List userId; + final Int64 userId; final String displayName; } @@ -13,7 +12,7 @@ class DbContacts extends CvModelBase { static const tableName = "contacts"; static const columnUserId = "contact_user_id"; - final userId = CvField(columnUserId); + final userId = CvField(columnUserId); static const columnDisplayName = "display_name"; final displayName = CvField(columnDisplayName); @@ -24,7 +23,7 @@ class DbContacts extends CvModelBase { static String getCreateTableString() { return """ CREATE TABLE $tableName ( - $columnUserId BINARY(16) NOT NULL PRIMARY KEY, + $columnUserId INTEGER NOT NULL PRIMARY KEY, $columnDisplayName TEXT, $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ) @@ -39,7 +38,7 @@ class DbContacts extends CvModelBase { List parsedUsers = []; for (int i = 0; i < users.length; i++) { parsedUsers.add(Contact( - userId: users.cast()[i][columnUserId], + userId: Int64(users.cast()[i][columnUserId]), displayName: users.cast()[i][columnDisplayName])); } return parsedUsers; diff --git a/lib/src/model/signal_identity_json.dart b/lib/src/model/signal_identity_json.dart index 59835b3..dffd786 100644 --- a/lib/src/model/signal_identity_json.dart +++ b/lib/src/model/signal_identity_json.dart @@ -1,6 +1,8 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:fixnum/fixnum.dart'; import 'package:json_annotation/json_annotation.dart'; +import 'package:twonly/src/model/user_data_json.dart'; part 'signal_identity_json.g.dart'; class Uint8ListConverter implements JsonConverter { @@ -20,7 +22,10 @@ class Uint8ListConverter implements JsonConverter { class SignalIdentity { const SignalIdentity( {required this.identityKeyPairU8List, required this.registrationId}); - final int registrationId; + + @Int64Converter() + final Int64 registrationId; + @Uint8ListConverter() final Uint8List identityKeyPairU8List; factory SignalIdentity.fromJson(Map json) => diff --git a/lib/src/model/signal_identity_json.g.dart b/lib/src/model/signal_identity_json.g.dart index c498160..3aef2a0 100644 --- a/lib/src/model/signal_identity_json.g.dart +++ b/lib/src/model/signal_identity_json.g.dart @@ -10,12 +10,13 @@ SignalIdentity _$SignalIdentityFromJson(Map json) => SignalIdentity( identityKeyPairU8List: const Uint8ListConverter() .fromJson(json['identityKeyPairU8List'] as String), - registrationId: (json['registrationId'] as num).toInt(), + registrationId: + const Int64Converter().fromJson(json['registrationId'] as String), ); Map _$SignalIdentityToJson(SignalIdentity instance) => { - 'registrationId': instance.registrationId, + 'registrationId': const Int64Converter().toJson(instance.registrationId), 'identityKeyPairU8List': const Uint8ListConverter().toJson(instance.identityKeyPairU8List), }; diff --git a/lib/src/model/user_data_json.dart b/lib/src/model/user_data_json.dart index 1e59943..44bd02c 100644 --- a/lib/src/model/user_data_json.dart +++ b/lib/src/model/user_data_json.dart @@ -1,8 +1,21 @@ -import 'dart:typed_data'; import 'package:json_annotation/json_annotation.dart'; -import 'package:twonly/src/model/signal_identity_json.dart'; +import 'package:fixnum/fixnum.dart'; part 'user_data_json.g.dart'; +class Int64Converter implements JsonConverter { + const Int64Converter(); + + @override + Int64 fromJson(String json) { + return Int64.parseInt(json); + } + + @override + String toJson(Int64 object) { + return object.toString(); + } +} + @JsonSerializable() class UserData { const UserData( @@ -12,8 +25,9 @@ class UserData { final String username; final String displayName; - @Uint8ListConverter() - final Uint8List userId; + @Int64Converter() + final Int64 userId; + factory UserData.fromJson(Map json) => _$UserDataFromJson(json); Map toJson() => _$UserDataToJson(this); diff --git a/lib/src/model/user_data_json.g.dart b/lib/src/model/user_data_json.g.dart index 7040af4..ef2cd1d 100644 --- a/lib/src/model/user_data_json.g.dart +++ b/lib/src/model/user_data_json.g.dart @@ -7,7 +7,7 @@ part of 'user_data_json.dart'; // ************************************************************************** UserData _$UserDataFromJson(Map json) => UserData( - userId: const Uint8ListConverter().fromJson(json['userId'] as String), + userId: const Int64Converter().fromJson(json['userId'] as String), username: json['username'] as String, displayName: json['displayName'] as String, ); @@ -15,5 +15,5 @@ UserData _$UserDataFromJson(Map json) => UserData( Map _$UserDataToJson(UserData instance) => { 'username': instance.username, 'displayName': instance.displayName, - 'userId': const Uint8ListConverter().toJson(instance.userId), + 'userId': const Int64Converter().toJson(instance.userId), }; diff --git a/lib/src/proto/api/client_to_server.pb.dart b/lib/src/proto/api/client_to_server.pb.dart index 8ed2d89..b10bed4 100644 --- a/lib/src/proto/api/client_to_server.pb.dart +++ b/lib/src/proto/api/client_to_server.pb.dart @@ -364,7 +364,7 @@ class Handshake_GetChallenge extends $pb.GeneratedMessage { class Handshake_OpenSession extends $pb.GeneratedMessage { factory Handshake_OpenSession({ - $core.List<$core.int>? userId, + $fixnum.Int64? userId, $core.List<$core.int>? response, }) { final $result = create(); @@ -381,7 +381,7 @@ class Handshake_OpenSession extends $pb.GeneratedMessage { factory Handshake_OpenSession.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) - ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'userId', $pb.PbFieldType.OY) + ..aInt64(1, _omitFieldNames ? '' : 'userId') ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'response', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -408,9 +408,9 @@ class Handshake_OpenSession extends $pb.GeneratedMessage { static Handshake_OpenSession? _defaultInstance; @$pb.TagNumber(1) - $core.List<$core.int> get userId => $_getN(0); + $fixnum.Int64 get userId => $_getI64(0); @$pb.TagNumber(1) - set userId($core.List<$core.int> v) { $_setBytes(0, v); } + set userId($fixnum.Int64 v) { $_setInt64(0, v); } @$pb.TagNumber(1) $core.bool hasUserId() => $_has(0); @$pb.TagNumber(1) @@ -529,7 +529,7 @@ class Handshake extends $pb.GeneratedMessage { class ApplicationData_TextMessage extends $pb.GeneratedMessage { factory ApplicationData_TextMessage({ - $core.List<$core.int>? userId, + $fixnum.Int64? userId, $core.List<$core.int>? body, }) { final $result = create(); @@ -546,7 +546,7 @@ class ApplicationData_TextMessage extends $pb.GeneratedMessage { factory ApplicationData_TextMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.TextMessage', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) - ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'userId', $pb.PbFieldType.OY) + ..aInt64(1, _omitFieldNames ? '' : 'userId') ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'body', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -573,9 +573,9 @@ class ApplicationData_TextMessage extends $pb.GeneratedMessage { static ApplicationData_TextMessage? _defaultInstance; @$pb.TagNumber(1) - $core.List<$core.int> get userId => $_getN(0); + $fixnum.Int64 get userId => $_getI64(0); @$pb.TagNumber(1) - set userId($core.List<$core.int> v) { $_setBytes(0, v); } + set userId($fixnum.Int64 v) { $_setInt64(0, v); } @$pb.TagNumber(1) $core.bool hasUserId() => $_has(0); @$pb.TagNumber(1) @@ -643,7 +643,7 @@ class ApplicationData_GetUserByUsername extends $pb.GeneratedMessage { class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage { factory ApplicationData_GetPrekeysByUserId({ - $core.List<$core.int>? userId, + $fixnum.Int64? userId, }) { final $result = create(); if (userId != null) { @@ -656,7 +656,7 @@ class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage { factory ApplicationData_GetPrekeysByUserId.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.GetPrekeysByUserId', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) - ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'userId', $pb.PbFieldType.OY) + ..aInt64(1, _omitFieldNames ? '' : 'userId') ..hasRequiredFields = false ; @@ -682,9 +682,9 @@ class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage { static ApplicationData_GetPrekeysByUserId? _defaultInstance; @$pb.TagNumber(1) - $core.List<$core.int> get userId => $_getN(0); + $fixnum.Int64 get userId => $_getI64(0); @$pb.TagNumber(1) - set userId($core.List<$core.int> v) { $_setBytes(0, v); } + set userId($fixnum.Int64 v) { $_setInt64(0, v); } @$pb.TagNumber(1) $core.bool hasUserId() => $_has(0); @$pb.TagNumber(1) diff --git a/lib/src/proto/api/client_to_server.pbjson.dart b/lib/src/proto/api/client_to_server.pbjson.dart index ecb3c31..ef6e4a7 100644 --- a/lib/src/proto/api/client_to_server.pbjson.dart +++ b/lib/src/proto/api/client_to_server.pbjson.dart @@ -91,7 +91,7 @@ const Handshake_GetChallenge$json = { const Handshake_OpenSession$json = { '1': 'OpenSession', '2': [ - {'1': 'user_id', '3': 1, '4': 1, '5': 12, '10': 'userId'}, + {'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'}, {'1': 'response', '3': 2, '4': 1, '5': 12, '10': 'response'}, ], }; @@ -108,7 +108,7 @@ final $typed_data.Uint8List handshakeDescriptor = $convert.base64Decode( 'NpZ25lZFByZWtleRI2ChdzaWduZWRfcHJla2V5X3NpZ25hdHVyZRgFIAEoDFIVc2lnbmVkUHJl' 'a2V5U2lnbmF0dXJlEigKEHNpZ25lZF9wcmVrZXlfaWQYBiABKANSDnNpZ25lZFByZWtleUlkEi' 'cKD3JlZ2lzdHJhdGlvbl9pZBgHIAEoA1IOcmVnaXN0cmF0aW9uSWRCDgoMX2ludml0ZV9jb2Rl' - 'Gg4KDEdldENoYWxsZW5nZRpCCgtPcGVuU2Vzc2lvbhIXCgd1c2VyX2lkGAEgASgMUgZ1c2VySW' + 'Gg4KDEdldENoYWxsZW5nZRpCCgtPcGVuU2Vzc2lvbhIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySW' 'QSGgoIcmVzcG9uc2UYAiABKAxSCHJlc3BvbnNlQgsKCUhhbmRzaGFrZQ=='); @$core.Deprecated('Use applicationDataDescriptor instead') @@ -131,7 +131,7 @@ const ApplicationData$json = { const ApplicationData_TextMessage$json = { '1': 'TextMessage', '2': [ - {'1': 'user_id', '3': 1, '4': 1, '5': 12, '10': 'userId'}, + {'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'}, {'1': 'body', '3': 3, '4': 1, '5': 12, '10': 'body'}, ], }; @@ -148,7 +148,7 @@ const ApplicationData_GetUserByUsername$json = { const ApplicationData_GetPrekeysByUserId$json = { '1': 'GetPrekeysByUserId', '2': [ - {'1': 'user_id', '3': 1, '4': 1, '5': 12, '10': 'userId'}, + {'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'}, ], }; @@ -181,9 +181,9 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode( 'bGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5HZXRVcGxvYWRUb2tlbkgAUg5nZXR1cG' 'xvYWR0b2tlbhJOCgp1cGxvYWRkYXRhGAUgASgLMiwuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNh' 'dGlvbkRhdGEuVXBsb2FkRGF0YUgAUgp1cGxvYWRkYXRhGjoKC1RleHRNZXNzYWdlEhcKB3VzZX' - 'JfaWQYASABKAxSBnVzZXJJZBISCgRib2R5GAMgASgMUgRib2R5Gi8KEUdldFVzZXJCeVVzZXJu' + 'JfaWQYASABKANSBnVzZXJJZBISCgRib2R5GAMgASgMUgRib2R5Gi8KEUdldFVzZXJCeVVzZXJu' 'YW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRotChJHZXRQcmVrZXlzQnlVc2VySWQSFw' - 'oHdXNlcl9pZBgBIAEoDFIGdXNlcklkGiIKDkdldFVwbG9hZFRva2VuEhAKA2xlbhgBIAEoDVID' + 'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkGiIKDkdldFVwbG9hZFRva2VuEhAKA2xlbhgBIAEoDVID' 'bGVuGlsKClVwbG9hZERhdGESIQoMdXBsb2FkX3Rva2VuGAEgASgMUgt1cGxvYWRUb2tlbhIWCg' 'ZvZmZzZXQYAiABKA1SBm9mZnNldBISCgRkYXRhGAMgASgMUgRkYXRhQhEKD0FwcGxpY2F0aW9u' 'RGF0YQ=='); diff --git a/lib/src/proto/api/server_to_client.pb.dart b/lib/src/proto/api/server_to_client.pb.dart index 2e7b161..b73ca0c 100644 --- a/lib/src/proto/api/server_to_client.pb.dart +++ b/lib/src/proto/api/server_to_client.pb.dart @@ -310,13 +310,12 @@ class Response_PreKey extends $pb.GeneratedMessage { class Response_UserData extends $pb.GeneratedMessage { factory Response_UserData({ - $core.List<$core.int>? userId, + $fixnum.Int64? userId, $core.Iterable? prekeys, $core.List<$core.int>? publicIdentityKey, $core.List<$core.int>? signedPrekey, $core.List<$core.int>? signedPrekeySignature, $fixnum.Int64? signedPrekeyId, - $fixnum.Int64? registrationId, }) { final $result = create(); if (userId != null) { @@ -337,9 +336,6 @@ class Response_UserData extends $pb.GeneratedMessage { if (signedPrekeyId != null) { $result.signedPrekeyId = signedPrekeyId; } - if (registrationId != null) { - $result.registrationId = registrationId; - } return $result; } Response_UserData._() : super(); @@ -347,13 +343,12 @@ class Response_UserData extends $pb.GeneratedMessage { factory Response_UserData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response.UserData', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create) - ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'userId', $pb.PbFieldType.OY) + ..aInt64(1, _omitFieldNames ? '' : 'userId') ..pc(2, _omitFieldNames ? '' : 'prekeys', $pb.PbFieldType.PM, subBuilder: Response_PreKey.create) ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'publicIdentityKey', $pb.PbFieldType.OY) ..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'signedPrekey', $pb.PbFieldType.OY) ..a<$core.List<$core.int>>(5, _omitFieldNames ? '' : 'signedPrekeySignature', $pb.PbFieldType.OY) ..aInt64(6, _omitFieldNames ? '' : 'signedPrekeyId') - ..aInt64(7, _omitFieldNames ? '' : 'registrationId') ..hasRequiredFields = false ; @@ -379,9 +374,9 @@ class Response_UserData extends $pb.GeneratedMessage { static Response_UserData? _defaultInstance; @$pb.TagNumber(1) - $core.List<$core.int> get userId => $_getN(0); + $fixnum.Int64 get userId => $_getI64(0); @$pb.TagNumber(1) - set userId($core.List<$core.int> v) { $_setBytes(0, v); } + set userId($fixnum.Int64 v) { $_setInt64(0, v); } @$pb.TagNumber(1) $core.bool hasUserId() => $_has(0); @$pb.TagNumber(1) @@ -425,15 +420,6 @@ class Response_UserData extends $pb.GeneratedMessage { $core.bool hasSignedPrekeyId() => $_has(5); @$pb.TagNumber(6) void clearSignedPrekeyId() => clearField(6); - - @$pb.TagNumber(7) - $fixnum.Int64 get registrationId => $_getI64(6); - @$pb.TagNumber(7) - set registrationId($fixnum.Int64 v) { $_setInt64(6, v); } - @$pb.TagNumber(7) - $core.bool hasRegistrationId() => $_has(6); - @$pb.TagNumber(7) - void clearRegistrationId() => clearField(7); } enum Response_Ok_Ok { @@ -448,7 +434,7 @@ enum Response_Ok_Ok { class Response_Ok extends $pb.GeneratedMessage { factory Response_Ok({ $core.bool? none, - $core.List<$core.int>? userid, + $fixnum.Int64? userid, $core.List<$core.int>? challenge, $core.List<$core.int>? uploadtoken, Response_UserData? userdata, @@ -486,7 +472,7 @@ class Response_Ok extends $pb.GeneratedMessage { 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]) ..aOB(1, _omitFieldNames ? '' : 'None', protoName: 'None') - ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'userid', $pb.PbFieldType.OY) + ..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) ..aOM(5, _omitFieldNames ? '' : 'userdata', subBuilder: Response_UserData.create) @@ -527,9 +513,9 @@ class Response_Ok extends $pb.GeneratedMessage { void clearNone() => clearField(1); @$pb.TagNumber(2) - $core.List<$core.int> get userid => $_getN(1); + $fixnum.Int64 get userid => $_getI64(1); @$pb.TagNumber(2) - set userid($core.List<$core.int> v) { $_setBytes(1, v); } + set userid($fixnum.Int64 v) { $_setInt64(1, v); } @$pb.TagNumber(2) $core.bool hasUserid() => $_has(1); @$pb.TagNumber(2) diff --git a/lib/src/proto/api/server_to_client.pbjson.dart b/lib/src/proto/api/server_to_client.pbjson.dart index 095a24b..6ac2e9b 100644 --- a/lib/src/proto/api/server_to_client.pbjson.dart +++ b/lib/src/proto/api/server_to_client.pbjson.dart @@ -88,19 +88,17 @@ const Response_PreKey$json = { const Response_UserData$json = { '1': 'UserData', '2': [ - {'1': 'user_id', '3': 1, '4': 1, '5': 12, '10': 'userId'}, + {'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'}, {'1': 'prekeys', '3': 2, '4': 3, '5': 11, '6': '.server_to_client.Response.PreKey', '10': 'prekeys'}, {'1': 'public_identity_key', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'publicIdentityKey', '17': true}, {'1': 'signed_prekey', '3': 4, '4': 1, '5': 12, '9': 1, '10': 'signedPrekey', '17': true}, {'1': 'signed_prekey_signature', '3': 5, '4': 1, '5': 12, '9': 2, '10': 'signedPrekeySignature', '17': true}, - {'1': 'registration_id', '3': 7, '4': 1, '5': 3, '9': 3, '10': 'registrationId', '17': true}, - {'1': 'signed_prekey_id', '3': 6, '4': 1, '5': 3, '9': 4, '10': 'signedPrekeyId', '17': true}, + {'1': 'signed_prekey_id', '3': 6, '4': 1, '5': 3, '9': 3, '10': 'signedPrekeyId', '17': true}, ], '8': [ {'1': '_public_identity_key'}, {'1': '_signed_prekey'}, {'1': '_signed_prekey_signature'}, - {'1': '_registration_id'}, {'1': '_signed_prekey_id'}, ], }; @@ -110,7 +108,7 @@ 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': 12, '9': 0, '10': 'userid'}, + {'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': 'userdata', '3': 5, '4': 1, '5': 11, '6': '.server_to_client.Response.UserData', '9': 0, '10': 'userdata'}, @@ -124,17 +122,16 @@ const Response_Ok$json = { final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( 'CghSZXNwb25zZRIvCgJvaxgBIAEoCzIdLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuT2tIAF' 'ICb2sSKAoFZXJyb3IYAiABKA4yEC5lcnJvci5FcnJvckNvZGVIAFIFZXJyb3IaMAoGUHJlS2V5' - 'Eg4KAmlkGAEgASgDUgJpZBIWCgZwcmVrZXkYAiABKAxSBnByZWtleRrIAwoIVXNlckRhdGESFw' - 'oHdXNlcl9pZBgBIAEoDFIGdXNlcklkEjsKB3ByZWtleXMYAiADKAsyIS5zZXJ2ZXJfdG9fY2xp' + 'Eg4KAmlkGAEgASgDUgJpZBIWCgZwcmVrZXkYAiABKAxSBnByZWtleRqGAwoIVXNlckRhdGESFw' + 'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkEjsKB3ByZWtleXMYAiADKAsyIS5zZXJ2ZXJfdG9fY2xp' 'ZW50LlJlc3BvbnNlLlByZUtleVIHcHJla2V5cxIzChNwdWJsaWNfaWRlbnRpdHlfa2V5GAMgAS' 'gMSABSEXB1YmxpY0lkZW50aXR5S2V5iAEBEigKDXNpZ25lZF9wcmVrZXkYBCABKAxIAVIMc2ln' 'bmVkUHJla2V5iAEBEjsKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAUgASgMSAJSFXNpZ25lZF' - 'ByZWtleVNpZ25hdHVyZYgBARIsCg9yZWdpc3RyYXRpb25faWQYByABKANIA1IOcmVnaXN0cmF0' - 'aW9uSWSIAQESLQoQc2lnbmVkX3ByZWtleV9pZBgGIAEoA0gEUg5zaWduZWRQcmVrZXlJZIgBAU' - 'IWChRfcHVibGljX2lkZW50aXR5X2tleUIQCg5fc2lnbmVkX3ByZWtleUIaChhfc2lnbmVkX3By' - 'ZWtleV9zaWduYXR1cmVCEgoQX3JlZ2lzdHJhdGlvbl9pZEITChFfc2lnbmVkX3ByZWtleV9pZB' - 'rBAQoCT2sSFAoETm9uZRgBIAEoCEgAUgROb25lEhgKBnVzZXJpZBgCIAEoDEgAUgZ1c2VyaWQS' - 'HgoJY2hhbGxlbmdlGAMgASgMSABSCWNoYWxsZW5nZRIiCgt1cGxvYWR0b2tlbhgEIAEoDEgAUg' - 't1cGxvYWR0b2tlbhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVzcG9u' - 'c2UuVXNlckRhdGFIAFIIdXNlcmRhdGFCBAoCT2tCCgoIUmVzcG9uc2U='); + 'ByZWtleVNpZ25hdHVyZYgBARItChBzaWduZWRfcHJla2V5X2lkGAYgASgDSANSDnNpZ25lZFBy' + 'ZWtleUlkiAEBQhYKFF9wdWJsaWNfaWRlbnRpdHlfa2V5QhAKDl9zaWduZWRfcHJla2V5QhoKGF' + '9zaWduZWRfcHJla2V5X3NpZ25hdHVyZUITChFfc2lnbmVkX3ByZWtleV9pZBrBAQoCT2sSFAoE' + 'Tm9uZRgBIAEoCEgAUgROb25lEhgKBnVzZXJpZBgCIAEoA0gAUgZ1c2VyaWQSHgoJY2hhbGxlbm' + 'dlGAMgASgMSABSCWNoYWxsZW5nZRIiCgt1cGxvYWR0b2tlbhgEIAEoDEgAUgt1cGxvYWR0b2tl' + 'bhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXNlckRhdG' + 'FIAFIIdXNlcmRhdGFCBAoCT2tCCgoIUmVzcG9uc2U='); diff --git a/lib/src/providers/api_provider.dart b/lib/src/providers/api_provider.dart index b8874da..0fcccb7 100644 --- a/lib/src/providers/api_provider.dart +++ b/lib/src/providers/api_provider.dart @@ -33,6 +33,7 @@ class ApiProvider { final String apiUrl; final String? backupApiUrl; int _reconnectionDelay = 5; + bool _tryingToConnect = false; final log = Logger("api_provider"); Function(bool)? _connectionStateCallback; @@ -103,8 +104,11 @@ class ApiProvider { } void tryToReconnect() { + if (_tryingToConnect) return; + _tryingToConnect = true; Future.delayed(Duration(seconds: _reconnectionDelay)).then( (value) async { + _tryingToConnect = false; _reconnectionDelay = _reconnectionDelay + 2; if (_reconnectionDelay > 20) { _reconnectionDelay = 20; @@ -316,7 +320,7 @@ class ApiProvider { ..username = username ..publicIdentityKey = (await signalStore.getIdentityKeyPair()).getPublicKey().serialize() - ..registrationId = Int64(signalIdentity.registrationId) + ..registrationId = signalIdentity.registrationId ..signedPrekey = signedPreKey.getKeyPair().publicKey.serialize() ..signedPrekeySignature = signedPreKey.signature ..signedPrekeyId = Int64(signedPreKey.id); diff --git a/lib/src/settings/settings_view.dart b/lib/src/settings/settings_view.dart index 9dd36bd..435dd0c 100644 --- a/lib/src/settings/settings_view.dart +++ b/lib/src/settings/settings_view.dart @@ -14,36 +14,45 @@ class SettingsView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Settings'), - ), - body: Padding( - padding: const EdgeInsets.all(16), - // Glue the SettingsController to the theme selection DropdownButton. - // - // When a user selects a theme from the dropdown list, the - // SettingsController is updated, which rebuilds the MaterialApp. - child: DropdownButton( - // Read the selected themeMode from the controller - value: controller.themeMode, - // Call the updateThemeMode method any time the user selects a theme. - onChanged: controller.updateThemeMode, - items: const [ - DropdownMenuItem( - value: ThemeMode.system, - child: Text('System Theme'), - ), - DropdownMenuItem( - value: ThemeMode.light, - child: Text('Light Theme'), - ), - DropdownMenuItem( - value: ThemeMode.dark, - child: Text('Dark Theme'), - ) - ], + appBar: AppBar( + title: const Text('Settings'), ), - ), - ); + body: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + // Glue the SettingsController to the theme selection DropdownButton. + // + // When a user selects a theme from the dropdown list, the + // SettingsController is updated, which rebuilds the MaterialApp. + child: DropdownButton( + // Read the selected themeMode from the controller + value: controller.themeMode, + // Call the updateThemeMode method any time the user selects a theme. + onChanged: controller.updateThemeMode, + items: const [ + DropdownMenuItem( + value: ThemeMode.system, + child: Text('System Theme'), + ), + DropdownMenuItem( + value: ThemeMode.light, + child: Text('Light Theme'), + ), + DropdownMenuItem( + value: ThemeMode.dark, + child: Text('Dark Theme'), + ) + ], + ), + ), + ElevatedButton( + onPressed: () { + showLicensePage(context: context); + }, + child: Text('Show Licenses'), + ), + ], + )); } } diff --git a/lib/src/signal/signal_helper.dart b/lib/src/signal/signal_helper.dart index a527040..7a9529f 100644 --- a/lib/src/signal/signal_helper.dart +++ b/lib/src/signal/signal_helper.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:developer'; 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/signal_identity_json.dart'; @@ -121,10 +122,10 @@ class SignalHelper { } static Future addNewContact(Response_UserData userData) async { - final List userId = userData.userId; + final Int64 userId = userData.userId; - SignalProtocolAddress targetAddress = SignalProtocolAddress( - uint8ListToHex(userId), SignalHelper.defaultDeviceId); + SignalProtocolAddress targetAddress = + SignalProtocolAddress(userId.toString(), SignalHelper.defaultDeviceId); SignalProtocolStore? signalStore = await SignalHelper.getSignalStore(); if (signalStore == null) { @@ -161,7 +162,7 @@ class SignalHelper { .serialize(), 1)); PreKeyBundle preKeyBundle = PreKeyBundle( - userData.registrationId.toInt(), + userData.userId.toInt(), 1, tempPreKeyId, tempPrePublicKey, @@ -200,7 +201,7 @@ class SignalHelper { IdentityKeyPair.fromSerialized(signalIdentity.identityKeyPairU8List); return ConnectSignalProtocolStore( - identityKeyPair, signalIdentity.registrationId); + identityKeyPair, signalIdentity.registrationId.toInt()); } static Future> getPreKeys() async { @@ -235,7 +236,7 @@ class SignalHelper { final storedSignalIdentity = SignalIdentity( identityKeyPairU8List: identityKeyPair.serialize(), - registrationId: registrationId); + registrationId: Int64(registrationId)); await storage.write( key: "signal_identity", value: jsonEncode(storedSignalIdentity)); diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 14c836e..3fb4caa 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -102,7 +102,7 @@ Future addNewUser(String username) async { if (await SignalHelper.addNewContact(res.value.userdata)) { await dbProvider.db!.insert(DbContacts.tableName, { DbContacts.columnDisplayName: username, - DbContacts.columnUserId: res.value.userdata.userId + DbContacts.columnUserId: res.value.userdata.userId.toInt() }); } print("Add new user: ${res}"); diff --git a/lib/src/views/camera_preview_view.dart b/lib/src/views/camera_preview_view.dart index 6bb0a9e..1a3a484 100644 --- a/lib/src/views/camera_preview_view.dart +++ b/lib/src/views/camera_preview_view.dart @@ -136,7 +136,7 @@ class _CameraPreviewViewState extends State { if (tmp != _lastZoom) { cameraState.sensorConfig.setZoom(tmp); setState(() { - print(tmp); + (tmp); _lastZoom = tmp; }); } diff --git a/lib/src/views/onboarding_view.dart b/lib/src/views/onboarding_view.dart index 999cd1d..908638c 100644 --- a/lib/src/views/onboarding_view.dart +++ b/lib/src/views/onboarding_view.dart @@ -44,21 +44,21 @@ class OnboardingView extends StatelessWidget { ), ), ), - PageViewModel( - title: "Hard work", - body: - "We try everything to give you the best experience but developing and maintaining is hard work and requires thousand of hours.", - image: Center( - child: Padding( - padding: const EdgeInsets.only(top: 100), - child: Image.asset("assets/images/onboarding/04.png"), - ), - ), - ), + // PageViewModel( + // title: "Hard work", + // body: + // "We try everything to give you the best experience but developing and maintaining is hard work and requires thousand of hours.", + // image: Center( + // child: Padding( + // padding: const EdgeInsets.only(top: 100), + // child: Image.asset("assets/images/onboarding/04.png"), + // ), + // ), + // ), PageViewModel( title: "You are not the product!", body: - "Nothing is free. Either you pay with your personal informations or with money. Twonly gives you the chance to use an sustainable social media product without exploiting you by collection you personal data.", + "Nothing is free. Either you pay with your personal informations or with money. Twonly gives you the chance to use an social media product without exploiting you by collection you personal data.", image: Center( child: Padding( padding: const EdgeInsets.only(top: 100), @@ -71,7 +71,7 @@ class OnboardingView extends StatelessWidget { bodyWidget: Column( children: [ Text( - "You can test twonly free for 14 days and then decide it is worth for you.", + "You can test twonly free for 14 days and then decide if it is worth to you.", textAlign: TextAlign.center, style: TextStyle(fontSize: 18), ), diff --git a/lib/src/views/share_image_view.dart b/lib/src/views/share_image_view.dart index b840ec6..0ff85e1 100644 --- a/lib/src/views/share_image_view.dart +++ b/lib/src/views/share_image_view.dart @@ -1,3 +1,6 @@ +import 'dart:collection'; + +import 'package:fixnum/fixnum.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:twonly/src/components/initialsavatar_component.dart'; @@ -13,6 +16,7 @@ class ShareImageView extends StatefulWidget { class _ShareImageView extends State { List _knownUsers = []; + final HashSet _selectedUserIds = HashSet(); @override void initState() { @@ -31,13 +35,34 @@ class _ShareImageView extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(AppLocalizations.of(context)!.newMessageTitle), + title: Text(AppLocalizations.of(context)!.shareImageTitle), ), body: Padding( padding: EdgeInsets.only(bottom: 20, left: 10, top: 20, right: 10), child: Column( children: [ - UserCheckboxList(users: _knownUsers), + Container( + alignment: + Alignment.centerLeft, // Aligns the container to the left + padding: EdgeInsets.all(16.0), // Optional: Add some padding + child: Text( + 'Best friends', + style: TextStyle( + fontSize: 20, // Set the font size to 20 + ), + ), + ), + UserCheckboxList( + users: _knownUsers, + onChanged: (userId, checkedId) { + setState(() { + if (checkedId) { + _selectedUserIds.add(userId); + } else { + _selectedUserIds.remove(userId); + } + }); + }), const SizedBox(height: 10), // Expanded( // child: UserList(_filteredUsers), @@ -51,8 +76,10 @@ class _ShareImageView extends State { class UserCheckboxList extends StatelessWidget { final List users; + final Function(Int64, bool) onChanged; - UserCheckboxList({required this.users}); + const UserCheckboxList( + {super.key, required this.users, required this.onChanged}); @override Widget build(BuildContext context) { @@ -67,9 +94,14 @@ class UserCheckboxList extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Text(limitedUsers[firstUserIndex].displayName), + Expanded( + child: UserCheckbox( + user: limitedUsers[firstUserIndex], onChanged: onChanged)), if (secondUserIndex < limitedUsers.length) - Text(limitedUsers[secondUserIndex].displayName), + Expanded( + child: UserCheckbox( + user: limitedUsers[secondUserIndex], + onChanged: onChanged)), ], ); }), @@ -79,11 +111,12 @@ class UserCheckboxList extends StatelessWidget { class UserCheckbox extends StatefulWidget { final Contact user; + final Function(Int64, bool) onChanged; - UserCheckbox({required this.user}); + const UserCheckbox({super.key, required this.user, required this.onChanged}); @override - _UserCheckboxState createState() => _UserCheckboxState(); + State createState() => _UserCheckboxState(); } class _UserCheckboxState extends State { @@ -91,31 +124,56 @@ class _UserCheckboxState extends State { @override Widget build(BuildContext context) { - return Row( - children: [ - Checkbox( - value: isChecked, - onChanged: (bool? value) { - setState(() { - isChecked = value ?? false; - }); - }, - ), - CircleAvatar( - child: InitialsAvatar( - displayName: - widget.user.displayName), // Display first letter of the name - ), - SizedBox(width: 8), - Expanded( - child: Text( - widget.user.displayName.length > 10 - ? '${widget.user.displayName.substring(0, 10)}...' // Trim if too long - : widget.user.displayName, - overflow: TextOverflow.ellipsis, + return Container( + padding: + EdgeInsets.symmetric(horizontal: 3), // Padding inside the container + child: GestureDetector( + onTap: () { + setState(() { + isChecked = !isChecked; + widget.onChanged(widget.user.userId, isChecked); + }); + }, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10, vertical: 0), // Padding inside the container + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context).colorScheme.outline, + // color: Colors.blue, // Border color + width: 1.0, // Border width + ), + borderRadius: + BorderRadius.circular(8.0), // Optional: Rounded corners + ), + child: Row( + children: [ + InitialsAvatar( + fontSize: 15, + displayName: widget + .user.displayName), // Display first letter of the name + SizedBox(width: 8), + Expanded( + child: Text( + widget.user.displayName.length > 10 + ? '${widget.user.displayName.substring(0, 10)}...' // Trim if too long + : widget.user.displayName, + overflow: TextOverflow.ellipsis, + ), + ), + Checkbox( + value: isChecked, + onChanged: (bool? value) { + setState(() { + isChecked = value ?? false; + widget.onChanged(widget.user.userId, isChecked); + }); + }, + ), + ], ), ), - ], + ), ); } }