change user id to i64

This commit is contained in:
otsmr 2025-01-24 12:38:12 +01:00
parent b694b9d7fc
commit a499f5c635
18 changed files with 232 additions and 154 deletions

View file

@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
class InitialsAvatar extends StatelessWidget { class InitialsAvatar extends StatelessWidget {
final String displayName; final String displayName;
final double? fontSize;
const InitialsAvatar({super.key, required this.displayName}); const InitialsAvatar(
{super.key, required this.displayName, this.fontSize = 20});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -25,12 +27,13 @@ class InitialsAvatar extends StatelessWidget {
return CircleAvatar( return CircleAvatar(
backgroundColor: avatarColor, backgroundColor: avatarColor,
radius: fontSize,
child: Text( child: Text(
initials, initials,
style: TextStyle( style: TextStyle(
color: _getTextColor(avatarColor), color: _getTextColor(avatarColor),
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
fontSize: 20, fontSize: fontSize,
), ),
), ),
); );

View file

@ -8,6 +8,7 @@
"registerSubmitButton": "Register now!", "registerSubmitButton": "Register now!",
"newMessageTitle": "New message", "newMessageTitle": "New message",
"chatsTitle": "Chats", "chatsTitle": "Chats",
"shareImageTitle": "Share image",
"shareImagedEditorSendImage": "Send", "shareImagedEditorSendImage": "Send",
"shareImagedEditorSaveImage": "Save", "shareImagedEditorSaveImage": "Save",
"shareImagedEditorSavedImage": "Saved", "shareImagedEditorSavedImage": "Saved",

View file

@ -1,11 +1,10 @@
import 'dart:typed_data';
import 'package:cv/cv.dart'; import 'package:cv/cv.dart';
import 'package:fixnum/fixnum.dart';
import 'package:twonly/main.dart'; import 'package:twonly/main.dart';
class Contact { class Contact {
Contact({required this.userId, required this.displayName}); Contact({required this.userId, required this.displayName});
final Uint8List userId; final Int64 userId;
final String displayName; final String displayName;
} }
@ -13,7 +12,7 @@ class DbContacts extends CvModelBase {
static const tableName = "contacts"; static const tableName = "contacts";
static const columnUserId = "contact_user_id"; static const columnUserId = "contact_user_id";
final userId = CvField<Uint8List>(columnUserId); final userId = CvField<int>(columnUserId);
static const columnDisplayName = "display_name"; static const columnDisplayName = "display_name";
final displayName = CvField<String>(columnDisplayName); final displayName = CvField<String>(columnDisplayName);
@ -24,7 +23,7 @@ class DbContacts extends CvModelBase {
static String getCreateTableString() { static String getCreateTableString() {
return """ return """
CREATE TABLE $tableName ( CREATE TABLE $tableName (
$columnUserId BINARY(16) NOT NULL PRIMARY KEY, $columnUserId INTEGER NOT NULL PRIMARY KEY,
$columnDisplayName TEXT, $columnDisplayName TEXT,
$columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
) )
@ -39,7 +38,7 @@ class DbContacts extends CvModelBase {
List<Contact> parsedUsers = []; List<Contact> parsedUsers = [];
for (int i = 0; i < users.length; i++) { for (int i = 0; i < users.length; i++) {
parsedUsers.add(Contact( parsedUsers.add(Contact(
userId: users.cast()[i][columnUserId], userId: Int64(users.cast()[i][columnUserId]),
displayName: users.cast()[i][columnDisplayName])); displayName: users.cast()[i][columnDisplayName]));
} }
return parsedUsers; return parsedUsers;

View file

@ -1,6 +1,8 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:fixnum/fixnum.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:twonly/src/model/user_data_json.dart';
part 'signal_identity_json.g.dart'; part 'signal_identity_json.g.dart';
class Uint8ListConverter implements JsonConverter<Uint8List, String> { class Uint8ListConverter implements JsonConverter<Uint8List, String> {
@ -20,7 +22,10 @@ class Uint8ListConverter implements JsonConverter<Uint8List, String> {
class SignalIdentity { class SignalIdentity {
const SignalIdentity( const SignalIdentity(
{required this.identityKeyPairU8List, required this.registrationId}); {required this.identityKeyPairU8List, required this.registrationId});
final int registrationId;
@Int64Converter()
final Int64 registrationId;
@Uint8ListConverter() @Uint8ListConverter()
final Uint8List identityKeyPairU8List; final Uint8List identityKeyPairU8List;
factory SignalIdentity.fromJson(Map<String, dynamic> json) => factory SignalIdentity.fromJson(Map<String, dynamic> json) =>

View file

@ -10,12 +10,13 @@ SignalIdentity _$SignalIdentityFromJson(Map<String, dynamic> json) =>
SignalIdentity( SignalIdentity(
identityKeyPairU8List: const Uint8ListConverter() identityKeyPairU8List: const Uint8ListConverter()
.fromJson(json['identityKeyPairU8List'] as String), .fromJson(json['identityKeyPairU8List'] as String),
registrationId: (json['registrationId'] as num).toInt(), registrationId:
const Int64Converter().fromJson(json['registrationId'] as String),
); );
Map<String, dynamic> _$SignalIdentityToJson(SignalIdentity instance) => Map<String, dynamic> _$SignalIdentityToJson(SignalIdentity instance) =>
<String, dynamic>{ <String, dynamic>{
'registrationId': instance.registrationId, 'registrationId': const Int64Converter().toJson(instance.registrationId),
'identityKeyPairU8List': 'identityKeyPairU8List':
const Uint8ListConverter().toJson(instance.identityKeyPairU8List), const Uint8ListConverter().toJson(instance.identityKeyPairU8List),
}; };

View file

@ -1,8 +1,21 @@
import 'dart:typed_data';
import 'package:json_annotation/json_annotation.dart'; 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'; part 'user_data_json.g.dart';
class Int64Converter implements JsonConverter<Int64, String> {
const Int64Converter();
@override
Int64 fromJson(String json) {
return Int64.parseInt(json);
}
@override
String toJson(Int64 object) {
return object.toString();
}
}
@JsonSerializable() @JsonSerializable()
class UserData { class UserData {
const UserData( const UserData(
@ -12,8 +25,9 @@ class UserData {
final String username; final String username;
final String displayName; final String displayName;
@Uint8ListConverter() @Int64Converter()
final Uint8List userId; final Int64 userId;
factory UserData.fromJson(Map<String, dynamic> json) => factory UserData.fromJson(Map<String, dynamic> json) =>
_$UserDataFromJson(json); _$UserDataFromJson(json);
Map<String, dynamic> toJson() => _$UserDataToJson(this); Map<String, dynamic> toJson() => _$UserDataToJson(this);

View file

@ -7,7 +7,7 @@ part of 'user_data_json.dart';
// ************************************************************************** // **************************************************************************
UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData( UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
userId: const Uint8ListConverter().fromJson(json['userId'] as String), userId: const Int64Converter().fromJson(json['userId'] as String),
username: json['username'] as String, username: json['username'] as String,
displayName: json['displayName'] as String, displayName: json['displayName'] as String,
); );
@ -15,5 +15,5 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
'username': instance.username, 'username': instance.username,
'displayName': instance.displayName, 'displayName': instance.displayName,
'userId': const Uint8ListConverter().toJson(instance.userId), 'userId': const Int64Converter().toJson(instance.userId),
}; };

View file

@ -364,7 +364,7 @@ class Handshake_GetChallenge extends $pb.GeneratedMessage {
class Handshake_OpenSession extends $pb.GeneratedMessage { class Handshake_OpenSession extends $pb.GeneratedMessage {
factory Handshake_OpenSession({ factory Handshake_OpenSession({
$core.List<$core.int>? userId, $fixnum.Int64? userId,
$core.List<$core.int>? response, $core.List<$core.int>? response,
}) { }) {
final $result = create(); 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); 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) 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) ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'response', $pb.PbFieldType.OY)
..hasRequiredFields = false ..hasRequiredFields = false
; ;
@ -408,9 +408,9 @@ class Handshake_OpenSession extends $pb.GeneratedMessage {
static Handshake_OpenSession? _defaultInstance; static Handshake_OpenSession? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.List<$core.int> get userId => $_getN(0); $fixnum.Int64 get userId => $_getI64(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set userId($core.List<$core.int> v) { $_setBytes(0, v); } set userId($fixnum.Int64 v) { $_setInt64(0, v); }
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasUserId() => $_has(0); $core.bool hasUserId() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
@ -529,7 +529,7 @@ class Handshake extends $pb.GeneratedMessage {
class ApplicationData_TextMessage extends $pb.GeneratedMessage { class ApplicationData_TextMessage extends $pb.GeneratedMessage {
factory ApplicationData_TextMessage({ factory ApplicationData_TextMessage({
$core.List<$core.int>? userId, $fixnum.Int64? userId,
$core.List<$core.int>? body, $core.List<$core.int>? body,
}) { }) {
final $result = create(); 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); 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) 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) ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'body', $pb.PbFieldType.OY)
..hasRequiredFields = false ..hasRequiredFields = false
; ;
@ -573,9 +573,9 @@ class ApplicationData_TextMessage extends $pb.GeneratedMessage {
static ApplicationData_TextMessage? _defaultInstance; static ApplicationData_TextMessage? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.List<$core.int> get userId => $_getN(0); $fixnum.Int64 get userId => $_getI64(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set userId($core.List<$core.int> v) { $_setBytes(0, v); } set userId($fixnum.Int64 v) { $_setInt64(0, v); }
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasUserId() => $_has(0); $core.bool hasUserId() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
@ -643,7 +643,7 @@ class ApplicationData_GetUserByUsername extends $pb.GeneratedMessage {
class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage { class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage {
factory ApplicationData_GetPrekeysByUserId({ factory ApplicationData_GetPrekeysByUserId({
$core.List<$core.int>? userId, $fixnum.Int64? userId,
}) { }) {
final $result = create(); final $result = create();
if (userId != null) { 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); 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) 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 ..hasRequiredFields = false
; ;
@ -682,9 +682,9 @@ class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage {
static ApplicationData_GetPrekeysByUserId? _defaultInstance; static ApplicationData_GetPrekeysByUserId? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.List<$core.int> get userId => $_getN(0); $fixnum.Int64 get userId => $_getI64(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set userId($core.List<$core.int> v) { $_setBytes(0, v); } set userId($fixnum.Int64 v) { $_setInt64(0, v); }
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasUserId() => $_has(0); $core.bool hasUserId() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)

View file

@ -91,7 +91,7 @@ const Handshake_GetChallenge$json = {
const Handshake_OpenSession$json = { const Handshake_OpenSession$json = {
'1': 'OpenSession', '1': 'OpenSession',
'2': [ '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'}, {'1': 'response', '3': 2, '4': 1, '5': 12, '10': 'response'},
], ],
}; };
@ -108,7 +108,7 @@ final $typed_data.Uint8List handshakeDescriptor = $convert.base64Decode(
'NpZ25lZFByZWtleRI2ChdzaWduZWRfcHJla2V5X3NpZ25hdHVyZRgFIAEoDFIVc2lnbmVkUHJl' 'NpZ25lZFByZWtleRI2ChdzaWduZWRfcHJla2V5X3NpZ25hdHVyZRgFIAEoDFIVc2lnbmVkUHJl'
'a2V5U2lnbmF0dXJlEigKEHNpZ25lZF9wcmVrZXlfaWQYBiABKANSDnNpZ25lZFByZWtleUlkEi' 'a2V5U2lnbmF0dXJlEigKEHNpZ25lZF9wcmVrZXlfaWQYBiABKANSDnNpZ25lZFByZWtleUlkEi'
'cKD3JlZ2lzdHJhdGlvbl9pZBgHIAEoA1IOcmVnaXN0cmF0aW9uSWRCDgoMX2ludml0ZV9jb2Rl' 'cKD3JlZ2lzdHJhdGlvbl9pZBgHIAEoA1IOcmVnaXN0cmF0aW9uSWRCDgoMX2ludml0ZV9jb2Rl'
'Gg4KDEdldENoYWxsZW5nZRpCCgtPcGVuU2Vzc2lvbhIXCgd1c2VyX2lkGAEgASgMUgZ1c2VySW' 'Gg4KDEdldENoYWxsZW5nZRpCCgtPcGVuU2Vzc2lvbhIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySW'
'QSGgoIcmVzcG9uc2UYAiABKAxSCHJlc3BvbnNlQgsKCUhhbmRzaGFrZQ=='); 'QSGgoIcmVzcG9uc2UYAiABKAxSCHJlc3BvbnNlQgsKCUhhbmRzaGFrZQ==');
@$core.Deprecated('Use applicationDataDescriptor instead') @$core.Deprecated('Use applicationDataDescriptor instead')
@ -131,7 +131,7 @@ const ApplicationData$json = {
const ApplicationData_TextMessage$json = { const ApplicationData_TextMessage$json = {
'1': 'TextMessage', '1': 'TextMessage',
'2': [ '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'}, {'1': 'body', '3': 3, '4': 1, '5': 12, '10': 'body'},
], ],
}; };
@ -148,7 +148,7 @@ const ApplicationData_GetUserByUsername$json = {
const ApplicationData_GetPrekeysByUserId$json = { const ApplicationData_GetPrekeysByUserId$json = {
'1': 'GetPrekeysByUserId', '1': 'GetPrekeysByUserId',
'2': [ '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' 'bGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5HZXRVcGxvYWRUb2tlbkgAUg5nZXR1cG'
'xvYWR0b2tlbhJOCgp1cGxvYWRkYXRhGAUgASgLMiwuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNh' 'xvYWR0b2tlbhJOCgp1cGxvYWRkYXRhGAUgASgLMiwuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNh'
'dGlvbkRhdGEuVXBsb2FkRGF0YUgAUgp1cGxvYWRkYXRhGjoKC1RleHRNZXNzYWdlEhcKB3VzZX' 'dGlvbkRhdGEuVXBsb2FkRGF0YUgAUgp1cGxvYWRkYXRhGjoKC1RleHRNZXNzYWdlEhcKB3VzZX'
'JfaWQYASABKAxSBnVzZXJJZBISCgRib2R5GAMgASgMUgRib2R5Gi8KEUdldFVzZXJCeVVzZXJu' 'JfaWQYASABKANSBnVzZXJJZBISCgRib2R5GAMgASgMUgRib2R5Gi8KEUdldFVzZXJCeVVzZXJu'
'YW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRotChJHZXRQcmVrZXlzQnlVc2VySWQSFw' 'YW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRotChJHZXRQcmVrZXlzQnlVc2VySWQSFw'
'oHdXNlcl9pZBgBIAEoDFIGdXNlcklkGiIKDkdldFVwbG9hZFRva2VuEhAKA2xlbhgBIAEoDVID' 'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkGiIKDkdldFVwbG9hZFRva2VuEhAKA2xlbhgBIAEoDVID'
'bGVuGlsKClVwbG9hZERhdGESIQoMdXBsb2FkX3Rva2VuGAEgASgMUgt1cGxvYWRUb2tlbhIWCg' 'bGVuGlsKClVwbG9hZERhdGESIQoMdXBsb2FkX3Rva2VuGAEgASgMUgt1cGxvYWRUb2tlbhIWCg'
'ZvZmZzZXQYAiABKA1SBm9mZnNldBISCgRkYXRhGAMgASgMUgRkYXRhQhEKD0FwcGxpY2F0aW9u' 'ZvZmZzZXQYAiABKA1SBm9mZnNldBISCgRkYXRhGAMgASgMUgRkYXRhQhEKD0FwcGxpY2F0aW9u'
'RGF0YQ=='); 'RGF0YQ==');

View file

@ -310,13 +310,12 @@ class Response_PreKey extends $pb.GeneratedMessage {
class Response_UserData extends $pb.GeneratedMessage { class Response_UserData extends $pb.GeneratedMessage {
factory Response_UserData({ factory Response_UserData({
$core.List<$core.int>? userId, $fixnum.Int64? userId,
$core.Iterable<Response_PreKey>? prekeys, $core.Iterable<Response_PreKey>? prekeys,
$core.List<$core.int>? publicIdentityKey, $core.List<$core.int>? publicIdentityKey,
$core.List<$core.int>? signedPrekey, $core.List<$core.int>? signedPrekey,
$core.List<$core.int>? signedPrekeySignature, $core.List<$core.int>? signedPrekeySignature,
$fixnum.Int64? signedPrekeyId, $fixnum.Int64? signedPrekeyId,
$fixnum.Int64? registrationId,
}) { }) {
final $result = create(); final $result = create();
if (userId != null) { if (userId != null) {
@ -337,9 +336,6 @@ class Response_UserData extends $pb.GeneratedMessage {
if (signedPrekeyId != null) { if (signedPrekeyId != null) {
$result.signedPrekeyId = signedPrekeyId; $result.signedPrekeyId = signedPrekeyId;
} }
if (registrationId != null) {
$result.registrationId = registrationId;
}
return $result; return $result;
} }
Response_UserData._() : super(); 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); 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) 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<Response_PreKey>(2, _omitFieldNames ? '' : 'prekeys', $pb.PbFieldType.PM, subBuilder: Response_PreKey.create) ..pc<Response_PreKey>(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>>(3, _omitFieldNames ? '' : 'publicIdentityKey', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'signedPrekey', $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) ..a<$core.List<$core.int>>(5, _omitFieldNames ? '' : 'signedPrekeySignature', $pb.PbFieldType.OY)
..aInt64(6, _omitFieldNames ? '' : 'signedPrekeyId') ..aInt64(6, _omitFieldNames ? '' : 'signedPrekeyId')
..aInt64(7, _omitFieldNames ? '' : 'registrationId')
..hasRequiredFields = false ..hasRequiredFields = false
; ;
@ -379,9 +374,9 @@ class Response_UserData extends $pb.GeneratedMessage {
static Response_UserData? _defaultInstance; static Response_UserData? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.List<$core.int> get userId => $_getN(0); $fixnum.Int64 get userId => $_getI64(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set userId($core.List<$core.int> v) { $_setBytes(0, v); } set userId($fixnum.Int64 v) { $_setInt64(0, v); }
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasUserId() => $_has(0); $core.bool hasUserId() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
@ -425,15 +420,6 @@ class Response_UserData extends $pb.GeneratedMessage {
$core.bool hasSignedPrekeyId() => $_has(5); $core.bool hasSignedPrekeyId() => $_has(5);
@$pb.TagNumber(6) @$pb.TagNumber(6)
void clearSignedPrekeyId() => clearField(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 { enum Response_Ok_Ok {
@ -448,7 +434,7 @@ enum Response_Ok_Ok {
class Response_Ok extends $pb.GeneratedMessage { class Response_Ok extends $pb.GeneratedMessage {
factory Response_Ok({ factory Response_Ok({
$core.bool? none, $core.bool? none,
$core.List<$core.int>? userid, $fixnum.Int64? userid,
$core.List<$core.int>? challenge, $core.List<$core.int>? challenge,
$core.List<$core.int>? uploadtoken, $core.List<$core.int>? uploadtoken,
Response_UserData? userdata, 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) 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])
..aOB(1, _omitFieldNames ? '' : 'None', protoName: 'None') ..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>>(3, _omitFieldNames ? '' : 'challenge', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'uploadtoken', $pb.PbFieldType.OY) ..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'uploadtoken', $pb.PbFieldType.OY)
..aOM<Response_UserData>(5, _omitFieldNames ? '' : 'userdata', subBuilder: Response_UserData.create) ..aOM<Response_UserData>(5, _omitFieldNames ? '' : 'userdata', subBuilder: Response_UserData.create)
@ -527,9 +513,9 @@ class Response_Ok extends $pb.GeneratedMessage {
void clearNone() => clearField(1); void clearNone() => clearField(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.List<$core.int> get userid => $_getN(1); $fixnum.Int64 get userid => $_getI64(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
set userid($core.List<$core.int> v) { $_setBytes(1, v); } set userid($fixnum.Int64 v) { $_setInt64(1, v); }
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool hasUserid() => $_has(1); $core.bool hasUserid() => $_has(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)

View file

@ -88,19 +88,17 @@ const Response_PreKey$json = {
const Response_UserData$json = { const Response_UserData$json = {
'1': 'UserData', '1': 'UserData',
'2': [ '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': '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': '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', '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': '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': 3, '10': 'signedPrekeyId', '17': true},
{'1': 'signed_prekey_id', '3': 6, '4': 1, '5': 3, '9': 4, '10': 'signedPrekeyId', '17': true},
], ],
'8': [ '8': [
{'1': '_public_identity_key'}, {'1': '_public_identity_key'},
{'1': '_signed_prekey'}, {'1': '_signed_prekey'},
{'1': '_signed_prekey_signature'}, {'1': '_signed_prekey_signature'},
{'1': '_registration_id'},
{'1': '_signed_prekey_id'}, {'1': '_signed_prekey_id'},
], ],
}; };
@ -110,7 +108,7 @@ const Response_Ok$json = {
'1': 'Ok', '1': 'Ok',
'2': [ '2': [
{'1': 'None', '3': 1, '4': 1, '5': 8, '9': 0, '10': 'None'}, {'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': 'challenge', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'challenge'},
{'1': 'uploadtoken', '3': 4, '4': 1, '5': 12, '9': 0, '10': 'uploadtoken'}, {'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'}, {'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( final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
'CghSZXNwb25zZRIvCgJvaxgBIAEoCzIdLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuT2tIAF' 'CghSZXNwb25zZRIvCgJvaxgBIAEoCzIdLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuT2tIAF'
'ICb2sSKAoFZXJyb3IYAiABKA4yEC5lcnJvci5FcnJvckNvZGVIAFIFZXJyb3IaMAoGUHJlS2V5' 'ICb2sSKAoFZXJyb3IYAiABKA4yEC5lcnJvci5FcnJvckNvZGVIAFIFZXJyb3IaMAoGUHJlS2V5'
'Eg4KAmlkGAEgASgDUgJpZBIWCgZwcmVrZXkYAiABKAxSBnByZWtleRrIAwoIVXNlckRhdGESFw' 'Eg4KAmlkGAEgASgDUgJpZBIWCgZwcmVrZXkYAiABKAxSBnByZWtleRqGAwoIVXNlckRhdGESFw'
'oHdXNlcl9pZBgBIAEoDFIGdXNlcklkEjsKB3ByZWtleXMYAiADKAsyIS5zZXJ2ZXJfdG9fY2xp' 'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkEjsKB3ByZWtleXMYAiADKAsyIS5zZXJ2ZXJfdG9fY2xp'
'ZW50LlJlc3BvbnNlLlByZUtleVIHcHJla2V5cxIzChNwdWJsaWNfaWRlbnRpdHlfa2V5GAMgAS' 'ZW50LlJlc3BvbnNlLlByZUtleVIHcHJla2V5cxIzChNwdWJsaWNfaWRlbnRpdHlfa2V5GAMgAS'
'gMSABSEXB1YmxpY0lkZW50aXR5S2V5iAEBEigKDXNpZ25lZF9wcmVrZXkYBCABKAxIAVIMc2ln' 'gMSABSEXB1YmxpY0lkZW50aXR5S2V5iAEBEigKDXNpZ25lZF9wcmVrZXkYBCABKAxIAVIMc2ln'
'bmVkUHJla2V5iAEBEjsKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAUgASgMSAJSFXNpZ25lZF' 'bmVkUHJla2V5iAEBEjsKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAUgASgMSAJSFXNpZ25lZF'
'ByZWtleVNpZ25hdHVyZYgBARIsCg9yZWdpc3RyYXRpb25faWQYByABKANIA1IOcmVnaXN0cmF0' 'ByZWtleVNpZ25hdHVyZYgBARItChBzaWduZWRfcHJla2V5X2lkGAYgASgDSANSDnNpZ25lZFBy'
'aW9uSWSIAQESLQoQc2lnbmVkX3ByZWtleV9pZBgGIAEoA0gEUg5zaWduZWRQcmVrZXlJZIgBAU' 'ZWtleUlkiAEBQhYKFF9wdWJsaWNfaWRlbnRpdHlfa2V5QhAKDl9zaWduZWRfcHJla2V5QhoKGF'
'IWChRfcHVibGljX2lkZW50aXR5X2tleUIQCg5fc2lnbmVkX3ByZWtleUIaChhfc2lnbmVkX3By' '9zaWduZWRfcHJla2V5X3NpZ25hdHVyZUITChFfc2lnbmVkX3ByZWtleV9pZBrBAQoCT2sSFAoE'
'ZWtleV9zaWduYXR1cmVCEgoQX3JlZ2lzdHJhdGlvbl9pZEITChFfc2lnbmVkX3ByZWtleV9pZB' 'Tm9uZRgBIAEoCEgAUgROb25lEhgKBnVzZXJpZBgCIAEoA0gAUgZ1c2VyaWQSHgoJY2hhbGxlbm'
'rBAQoCT2sSFAoETm9uZRgBIAEoCEgAUgROb25lEhgKBnVzZXJpZBgCIAEoDEgAUgZ1c2VyaWQS' 'dlGAMgASgMSABSCWNoYWxsZW5nZRIiCgt1cGxvYWR0b2tlbhgEIAEoDEgAUgt1cGxvYWR0b2tl'
'HgoJY2hhbGxlbmdlGAMgASgMSABSCWNoYWxsZW5nZRIiCgt1cGxvYWR0b2tlbhgEIAEoDEgAUg' 'bhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXNlckRhdG'
't1cGxvYWR0b2tlbhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVzcG9u' 'FIAFIIdXNlcmRhdGFCBAoCT2tCCgoIUmVzcG9uc2U=');
'c2UuVXNlckRhdGFIAFIIdXNlcmRhdGFCBAoCT2tCCgoIUmVzcG9uc2U=');

View file

@ -33,6 +33,7 @@ class ApiProvider {
final String apiUrl; final String apiUrl;
final String? backupApiUrl; final String? backupApiUrl;
int _reconnectionDelay = 5; int _reconnectionDelay = 5;
bool _tryingToConnect = false;
final log = Logger("api_provider"); final log = Logger("api_provider");
Function(bool)? _connectionStateCallback; Function(bool)? _connectionStateCallback;
@ -103,8 +104,11 @@ class ApiProvider {
} }
void tryToReconnect() { void tryToReconnect() {
if (_tryingToConnect) return;
_tryingToConnect = true;
Future.delayed(Duration(seconds: _reconnectionDelay)).then( Future.delayed(Duration(seconds: _reconnectionDelay)).then(
(value) async { (value) async {
_tryingToConnect = false;
_reconnectionDelay = _reconnectionDelay + 2; _reconnectionDelay = _reconnectionDelay + 2;
if (_reconnectionDelay > 20) { if (_reconnectionDelay > 20) {
_reconnectionDelay = 20; _reconnectionDelay = 20;
@ -316,7 +320,7 @@ class ApiProvider {
..username = username ..username = username
..publicIdentityKey = ..publicIdentityKey =
(await signalStore.getIdentityKeyPair()).getPublicKey().serialize() (await signalStore.getIdentityKeyPair()).getPublicKey().serialize()
..registrationId = Int64(signalIdentity.registrationId) ..registrationId = signalIdentity.registrationId
..signedPrekey = signedPreKey.getKeyPair().publicKey.serialize() ..signedPrekey = signedPreKey.getKeyPair().publicKey.serialize()
..signedPrekeySignature = signedPreKey.signature ..signedPrekeySignature = signedPreKey.signature
..signedPrekeyId = Int64(signedPreKey.id); ..signedPrekeyId = Int64(signedPreKey.id);

View file

@ -17,7 +17,9 @@ class SettingsView extends StatelessWidget {
appBar: AppBar( appBar: AppBar(
title: const Text('Settings'), title: const Text('Settings'),
), ),
body: Padding( body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
// Glue the SettingsController to the theme selection DropdownButton. // Glue the SettingsController to the theme selection DropdownButton.
// //
@ -44,6 +46,13 @@ class SettingsView extends StatelessWidget {
], ],
), ),
), ),
); ElevatedButton(
onPressed: () {
showLicensePage(context: context);
},
child: Text('Show Licenses'),
),
],
));
} }
} }

View file

@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:fixnum/fixnum.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:twonly/src/model/signal_identity_json.dart'; import 'package:twonly/src/model/signal_identity_json.dart';
@ -121,10 +122,10 @@ class SignalHelper {
} }
static Future<bool> addNewContact(Response_UserData userData) async { static Future<bool> addNewContact(Response_UserData userData) async {
final List<int> userId = userData.userId; final Int64 userId = userData.userId;
SignalProtocolAddress targetAddress = SignalProtocolAddress( SignalProtocolAddress targetAddress =
uint8ListToHex(userId), SignalHelper.defaultDeviceId); SignalProtocolAddress(userId.toString(), SignalHelper.defaultDeviceId);
SignalProtocolStore? signalStore = await SignalHelper.getSignalStore(); SignalProtocolStore? signalStore = await SignalHelper.getSignalStore();
if (signalStore == null) { if (signalStore == null) {
@ -161,7 +162,7 @@ class SignalHelper {
.serialize(), .serialize(),
1)); 1));
PreKeyBundle preKeyBundle = PreKeyBundle( PreKeyBundle preKeyBundle = PreKeyBundle(
userData.registrationId.toInt(), userData.userId.toInt(),
1, 1,
tempPreKeyId, tempPreKeyId,
tempPrePublicKey, tempPrePublicKey,
@ -200,7 +201,7 @@ class SignalHelper {
IdentityKeyPair.fromSerialized(signalIdentity.identityKeyPairU8List); IdentityKeyPair.fromSerialized(signalIdentity.identityKeyPairU8List);
return ConnectSignalProtocolStore( return ConnectSignalProtocolStore(
identityKeyPair, signalIdentity.registrationId); identityKeyPair, signalIdentity.registrationId.toInt());
} }
static Future<List<PreKeyRecord>> getPreKeys() async { static Future<List<PreKeyRecord>> getPreKeys() async {
@ -235,7 +236,7 @@ class SignalHelper {
final storedSignalIdentity = SignalIdentity( final storedSignalIdentity = SignalIdentity(
identityKeyPairU8List: identityKeyPair.serialize(), identityKeyPairU8List: identityKeyPair.serialize(),
registrationId: registrationId); registrationId: Int64(registrationId));
await storage.write( await storage.write(
key: "signal_identity", value: jsonEncode(storedSignalIdentity)); key: "signal_identity", value: jsonEncode(storedSignalIdentity));

View file

@ -102,7 +102,7 @@ Future<bool> addNewUser(String username) async {
if (await SignalHelper.addNewContact(res.value.userdata)) { if (await SignalHelper.addNewContact(res.value.userdata)) {
await dbProvider.db!.insert(DbContacts.tableName, { await dbProvider.db!.insert(DbContacts.tableName, {
DbContacts.columnDisplayName: username, DbContacts.columnDisplayName: username,
DbContacts.columnUserId: res.value.userdata.userId DbContacts.columnUserId: res.value.userdata.userId.toInt()
}); });
} }
print("Add new user: ${res}"); print("Add new user: ${res}");

View file

@ -136,7 +136,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
if (tmp != _lastZoom) { if (tmp != _lastZoom) {
cameraState.sensorConfig.setZoom(tmp); cameraState.sensorConfig.setZoom(tmp);
setState(() { setState(() {
print(tmp); (tmp);
_lastZoom = tmp; _lastZoom = tmp;
}); });
} }

View file

@ -44,21 +44,21 @@ class OnboardingView extends StatelessWidget {
), ),
), ),
), ),
PageViewModel( // PageViewModel(
title: "Hard work", // title: "Hard work",
body: // body:
"We try everything to give you the best experience but developing and maintaining is hard work and requires thousand of hours.", // "We try everything to give you the best experience but developing and maintaining is hard work and requires thousand of hours.",
image: Center( // image: Center(
child: Padding( // child: Padding(
padding: const EdgeInsets.only(top: 100), // padding: const EdgeInsets.only(top: 100),
child: Image.asset("assets/images/onboarding/04.png"), // child: Image.asset("assets/images/onboarding/04.png"),
), // ),
), // ),
), // ),
PageViewModel( PageViewModel(
title: "You are not the product!", title: "You are not the product!",
body: 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( image: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.only(top: 100), padding: const EdgeInsets.only(top: 100),
@ -71,7 +71,7 @@ class OnboardingView extends StatelessWidget {
bodyWidget: Column( bodyWidget: Column(
children: [ children: [
Text( 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, textAlign: TextAlign.center,
style: TextStyle(fontSize: 18), style: TextStyle(fontSize: 18),
), ),

View file

@ -1,3 +1,6 @@
import 'dart:collection';
import 'package:fixnum/fixnum.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:twonly/src/components/initialsavatar_component.dart'; import 'package:twonly/src/components/initialsavatar_component.dart';
@ -13,6 +16,7 @@ class ShareImageView extends StatefulWidget {
class _ShareImageView extends State<ShareImageView> { class _ShareImageView extends State<ShareImageView> {
List<Contact> _knownUsers = []; List<Contact> _knownUsers = [];
final HashSet<Int64> _selectedUserIds = HashSet<Int64>();
@override @override
void initState() { void initState() {
@ -31,13 +35,34 @@ class _ShareImageView extends State<ShareImageView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(AppLocalizations.of(context)!.newMessageTitle), title: Text(AppLocalizations.of(context)!.shareImageTitle),
), ),
body: Padding( body: Padding(
padding: EdgeInsets.only(bottom: 20, left: 10, top: 20, right: 10), padding: EdgeInsets.only(bottom: 20, left: 10, top: 20, right: 10),
child: Column( child: Column(
children: [ 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), const SizedBox(height: 10),
// Expanded( // Expanded(
// child: UserList(_filteredUsers), // child: UserList(_filteredUsers),
@ -51,8 +76,10 @@ class _ShareImageView extends State<ShareImageView> {
class UserCheckboxList extends StatelessWidget { class UserCheckboxList extends StatelessWidget {
final List<Contact> users; final List<Contact> users;
final Function(Int64, bool) onChanged;
UserCheckboxList({required this.users}); const UserCheckboxList(
{super.key, required this.users, required this.onChanged});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -67,9 +94,14 @@ class UserCheckboxList extends StatelessWidget {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
Text(limitedUsers[firstUserIndex].displayName), Expanded(
child: UserCheckbox(
user: limitedUsers[firstUserIndex], onChanged: onChanged)),
if (secondUserIndex < limitedUsers.length) 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 { class UserCheckbox extends StatefulWidget {
final Contact user; final Contact user;
final Function(Int64, bool) onChanged;
UserCheckbox({required this.user}); const UserCheckbox({super.key, required this.user, required this.onChanged});
@override @override
_UserCheckboxState createState() => _UserCheckboxState(); State<UserCheckbox> createState() => _UserCheckboxState();
} }
class _UserCheckboxState extends State<UserCheckbox> { class _UserCheckboxState extends State<UserCheckbox> {
@ -91,21 +124,34 @@ class _UserCheckboxState extends State<UserCheckbox> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Container(
children: [ padding:
Checkbox( EdgeInsets.symmetric(horizontal: 3), // Padding inside the container
value: isChecked, child: GestureDetector(
onChanged: (bool? value) { onTap: () {
setState(() { setState(() {
isChecked = value ?? false; 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
), ),
CircleAvatar( borderRadius:
child: InitialsAvatar( BorderRadius.circular(8.0), // Optional: Rounded corners
displayName:
widget.user.displayName), // Display first letter of the name
), ),
child: Row(
children: [
InitialsAvatar(
fontSize: 15,
displayName: widget
.user.displayName), // Display first letter of the name
SizedBox(width: 8), SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text(
@ -115,7 +161,19 @@ class _UserCheckboxState extends State<UserCheckbox> {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ),
Checkbox(
value: isChecked,
onChanged: (bool? value) {
setState(() {
isChecked = value ?? false;
widget.onChanged(widget.user.userId, isChecked);
});
},
),
], ],
),
),
),
); );
} }
} }