mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 11:18:41 +00:00
follow request
This commit is contained in:
parent
b06c2e1cc8
commit
20c20eb1e1
19 changed files with 533 additions and 197 deletions
|
|
@ -36,10 +36,10 @@ void main() async {
|
||||||
|
|
||||||
var apiUrl = "ws://api.twonly.eu/api/client";
|
var apiUrl = "ws://api.twonly.eu/api/client";
|
||||||
var backupApiUrl = "ws://api2.twonly.eu/api/client";
|
var backupApiUrl = "ws://api2.twonly.eu/api/client";
|
||||||
if (!kReleaseMode) {
|
// if (!kReleaseMode) {
|
||||||
// Overwrite the domain in your local network so you can test the app locally
|
// Overwrite the domain in your local network so you can test the app locally
|
||||||
apiUrl = "ws://10.99.0.6:3030/api/client";
|
apiUrl = "ws://10.99.0.6:3030/api/client";
|
||||||
}
|
// }
|
||||||
|
|
||||||
apiProvider = ApiProvider(apiUrl: apiUrl, backupApiUrl: backupApiUrl);
|
apiProvider = ApiProvider(apiUrl: apiUrl, backupApiUrl: backupApiUrl);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"errorUnknown": "An unexpected error has occurred. Please try again later.",
|
"errorUnknown": "An unexpected error has occurred. Please try again later.",
|
||||||
"errorBadRequest": "The request could not be understood by the server due to malformed syntax. Please check your input and try again.",
|
"errorBadRequest": "The request could not be understood by the server due to malformed syntax. Please check your input and try again.",
|
||||||
"errorTooManyRequests": "You have made too many requests in a short period. Please wait a moment before trying again.",
|
"errorTooManyRequests": "You have made too many requests in a short period. Please wait a moment before trying again.",
|
||||||
"errorInternalError": "The server encountered an internal error. Please try again later.",
|
"errorInternalError": "The server is currently not available. Please try again later.",
|
||||||
"errorInvalidInvitationCode": "The invitation code you provided is invalid. Please check the code and try again.",
|
"errorInvalidInvitationCode": "The invitation code you provided is invalid. Please check the code and try again.",
|
||||||
"errorUsernameAlreadyTaken": "The username you want to use is already taken. Please choose a different username.",
|
"errorUsernameAlreadyTaken": "The username you want to use is already taken. Please choose a different username.",
|
||||||
"errorSignatureNotValid": "The provided signature is not valid. Please check your credentials and try again.",
|
"errorSignatureNotValid": "The provided signature is not valid. Please check your credentials and try again.",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
import 'package:cv/cv.dart';
|
import 'package:cv/cv.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
import 'package:logging/logging.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,
|
||||||
|
required this.accepted,
|
||||||
|
required this.requested});
|
||||||
final Int64 userId;
|
final Int64 userId;
|
||||||
final String displayName;
|
final String displayName;
|
||||||
|
final bool accepted;
|
||||||
|
final bool requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DbContacts extends CvModelBase {
|
class DbContacts extends CvModelBase {
|
||||||
|
|
@ -17,6 +24,12 @@ class DbContacts extends CvModelBase {
|
||||||
static const columnDisplayName = "display_name";
|
static const columnDisplayName = "display_name";
|
||||||
final displayName = CvField<String>(columnDisplayName);
|
final displayName = CvField<String>(columnDisplayName);
|
||||||
|
|
||||||
|
static const columnAccepted = "accepted";
|
||||||
|
final accepted = CvField<int>(columnAccepted);
|
||||||
|
|
||||||
|
static const columnRequested = "requested";
|
||||||
|
final requested = CvField<int>(columnRequested);
|
||||||
|
|
||||||
static const columnCreatedAt = "created_at";
|
static const columnCreatedAt = "created_at";
|
||||||
final createdAt = CvField<DateTime>(columnCreatedAt);
|
final createdAt = CvField<DateTime>(columnCreatedAt);
|
||||||
|
|
||||||
|
|
@ -25,25 +38,60 @@ class DbContacts extends CvModelBase {
|
||||||
CREATE TABLE $tableName (
|
CREATE TABLE $tableName (
|
||||||
$columnUserId INTEGER NOT NULL PRIMARY KEY,
|
$columnUserId INTEGER NOT NULL PRIMARY KEY,
|
||||||
$columnDisplayName TEXT,
|
$columnDisplayName TEXT,
|
||||||
|
$columnAccepted INT NOT NULL DEFAULT 0,
|
||||||
|
$columnRequested INT NOT NULL DEFAULT 0,
|
||||||
$columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
|
$columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
""";
|
""";
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<Contact>> getUsers() async {
|
@override
|
||||||
var users = await dbProvider.db!.query(tableName,
|
List<CvField> get fields =>
|
||||||
columns: [columnUserId, columnDisplayName, columnCreatedAt]);
|
[userId, displayName, accepted, requested, createdAt];
|
||||||
if (users.isEmpty) return [];
|
|
||||||
|
|
||||||
List<Contact> parsedUsers = [];
|
static Future<List<Contact>> getUsers() async {
|
||||||
for (int i = 0; i < users.length; i++) {
|
try {
|
||||||
parsedUsers.add(Contact(
|
var users = await dbProvider.db!.query(tableName, columns: [
|
||||||
userId: Int64(users.cast()[i][columnUserId]),
|
columnUserId,
|
||||||
displayName: users.cast()[i][columnDisplayName]));
|
columnDisplayName,
|
||||||
|
columnAccepted,
|
||||||
|
columnRequested,
|
||||||
|
columnCreatedAt
|
||||||
|
]);
|
||||||
|
if (users.isEmpty) return [];
|
||||||
|
|
||||||
|
List<Contact> parsedUsers = [];
|
||||||
|
for (int i = 0; i < users.length; i++) {
|
||||||
|
print(users[i]);
|
||||||
|
parsedUsers.add(
|
||||||
|
Contact(
|
||||||
|
userId: Int64(users.cast()[i][columnUserId]),
|
||||||
|
displayName: users.cast()[i][columnDisplayName],
|
||||||
|
accepted: users[i][columnAccepted] == 1,
|
||||||
|
requested: users[i][columnRequested] == 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return parsedUsers;
|
||||||
|
} catch (e) {
|
||||||
|
Logger("contacts_model/getUsers").shout("$e");
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
return parsedUsers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
static Future<bool> insertNewContact(
|
||||||
List<CvField> get fields => [userId, createdAt];
|
String username, int userId, bool requested) async {
|
||||||
|
try {
|
||||||
|
int a = requested ? 1 : 0;
|
||||||
|
await dbProvider.db!.insert(DbContacts.tableName, {
|
||||||
|
DbContacts.columnDisplayName: username,
|
||||||
|
DbContacts.columnUserId: userId,
|
||||||
|
DbContacts.columnRequested: a
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
Logger("contacts_model/getUsers").shout("$e");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import 'dart:convert';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
|
||||||
import 'package:twonly/src/utils/json.dart';
|
import 'package:twonly/src/utils/json.dart';
|
||||||
part 'message.g.dart';
|
part 'message.g.dart';
|
||||||
|
|
||||||
|
|
@ -14,23 +14,19 @@ class _MessageKind {
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class Message {
|
class Message {
|
||||||
@Int64Converter()
|
@Int64Converter()
|
||||||
final Int64 fromUserId;
|
|
||||||
final MessageKind kind;
|
final MessageKind kind;
|
||||||
final MessageContent? content;
|
final MessageContent? content;
|
||||||
DateTime timestamp;
|
DateTime timestamp;
|
||||||
|
|
||||||
Message(
|
Message({required this.kind, this.content, required this.timestamp});
|
||||||
{required this.fromUserId,
|
|
||||||
required this.kind,
|
|
||||||
this.content,
|
|
||||||
required this.timestamp});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Message(kind: $kind, content: $content, timestamp: $timestamp)';
|
return 'Message(kind: $kind, content: $content, timestamp: $timestamp)';
|
||||||
}
|
}
|
||||||
|
|
||||||
Message fromJson(Map<String, dynamic> json) {
|
static Message fromJson(String jsonString) {
|
||||||
|
Map<String, dynamic> json = jsonDecode(jsonString);
|
||||||
dynamic content;
|
dynamic content;
|
||||||
MessageKind kind = $enumDecode(_$MessageKindEnumMap, json['kind']);
|
MessageKind kind = $enumDecode(_$MessageKindEnumMap, json['kind']);
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|
@ -44,22 +40,19 @@ class Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Message(
|
return Message(
|
||||||
fromUserId: const Int64Converter().fromJson(json['fromUserId'] as String),
|
|
||||||
kind: kind,
|
kind: kind,
|
||||||
timestamp: DateTime.parse(json['timestamp'] as String),
|
timestamp: DateTime.parse(json['timestamp'] as String),
|
||||||
content: content,
|
content: content,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson(Message instance) {
|
String toJson() {
|
||||||
var json = <String, dynamic>{
|
var json = <String, dynamic>{
|
||||||
'fromUserId': const Int64Converter().toJson(instance.fromUserId),
|
'kind': _$MessageKindEnumMap[kind]!,
|
||||||
'kind': _$MessageKindEnumMap[instance.kind]!,
|
'timestamp': timestamp.toIso8601String(),
|
||||||
'timestamp': instance.timestamp.toIso8601String(),
|
'content': content
|
||||||
'content': instance.content
|
|
||||||
};
|
};
|
||||||
|
return jsonEncode(json);
|
||||||
return json;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ const _$MessageKindEnumMap = {
|
||||||
};
|
};
|
||||||
|
|
||||||
Message _$MessageFromJson(Map<String, dynamic> json) => Message(
|
Message _$MessageFromJson(Map<String, dynamic> json) => Message(
|
||||||
fromUserId: const Int64Converter().fromJson(json['fromUserId'] as String),
|
|
||||||
kind: $enumDecode(_$MessageKindEnumMap, json['kind']),
|
kind: $enumDecode(_$MessageKindEnumMap, json['kind']),
|
||||||
content: json['content'] == null
|
content: json['content'] == null
|
||||||
? null
|
? null
|
||||||
|
|
@ -31,7 +30,6 @@ Message _$MessageFromJson(Map<String, dynamic> json) => Message(
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$MessageToJson(Message instance) => <String, dynamic>{
|
Map<String, dynamic> _$MessageToJson(Message instance) => <String, dynamic>{
|
||||||
'fromUserId': const Int64Converter().toJson(instance.fromUserId),
|
|
||||||
'kind': _$MessageKindEnumMap[instance.kind]!,
|
'kind': _$MessageKindEnumMap[instance.kind]!,
|
||||||
'content': instance.content,
|
'content': instance.content,
|
||||||
'timestamp': instance.timestamp.toIso8601String(),
|
'timestamp': instance.timestamp.toIso8601String(),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
const String dbName = 'twonly.db';
|
const String dbName = 'twonly.db';
|
||||||
|
|
||||||
const int kVersion1 = 1;
|
const int kVersion1 = 3;
|
||||||
|
|
||||||
String tableLibSignal = 'LibSignal';
|
String tableLibSignal = 'LibSignal';
|
||||||
|
|
|
||||||
|
|
@ -641,6 +641,56 @@ class ApplicationData_GetUserByUsername extends $pb.GeneratedMessage {
|
||||||
void clearUsername() => clearField(1);
|
void clearUsername() => clearField(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ApplicationData_GetUserById extends $pb.GeneratedMessage {
|
||||||
|
factory ApplicationData_GetUserById({
|
||||||
|
$fixnum.Int64? userId,
|
||||||
|
}) {
|
||||||
|
final $result = create();
|
||||||
|
if (userId != null) {
|
||||||
|
$result.userId = userId;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
ApplicationData_GetUserById._() : super();
|
||||||
|
factory ApplicationData_GetUserById.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||||
|
factory ApplicationData_GetUserById.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.GetUserById', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
||||||
|
..aInt64(1, _omitFieldNames ? '' : 'userId')
|
||||||
|
..hasRequiredFields = false
|
||||||
|
;
|
||||||
|
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
ApplicationData_GetUserById clone() => ApplicationData_GetUserById()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated(
|
||||||
|
'Using this can add significant overhead to your binary. '
|
||||||
|
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||||
|
'Will be removed in next major version')
|
||||||
|
ApplicationData_GetUserById copyWith(void Function(ApplicationData_GetUserById) updates) => super.copyWith((message) => updates(message as ApplicationData_GetUserById)) as ApplicationData_GetUserById;
|
||||||
|
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static ApplicationData_GetUserById create() => ApplicationData_GetUserById._();
|
||||||
|
ApplicationData_GetUserById createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<ApplicationData_GetUserById> createRepeated() => $pb.PbList<ApplicationData_GetUserById>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static ApplicationData_GetUserById getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ApplicationData_GetUserById>(create);
|
||||||
|
static ApplicationData_GetUserById? _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);
|
||||||
|
}
|
||||||
|
|
||||||
class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage {
|
class ApplicationData_GetPrekeysByUserId extends $pb.GeneratedMessage {
|
||||||
factory ApplicationData_GetPrekeysByUserId({
|
factory ApplicationData_GetPrekeysByUserId({
|
||||||
$fixnum.Int64? userId,
|
$fixnum.Int64? userId,
|
||||||
|
|
@ -825,6 +875,7 @@ enum ApplicationData_ApplicationData {
|
||||||
getprekeysbyuserid,
|
getprekeysbyuserid,
|
||||||
getuploadtoken,
|
getuploadtoken,
|
||||||
uploaddata,
|
uploaddata,
|
||||||
|
getuserbyid,
|
||||||
notSet
|
notSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -835,6 +886,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
ApplicationData_GetPrekeysByUserId? getprekeysbyuserid,
|
ApplicationData_GetPrekeysByUserId? getprekeysbyuserid,
|
||||||
ApplicationData_GetUploadToken? getuploadtoken,
|
ApplicationData_GetUploadToken? getuploadtoken,
|
||||||
ApplicationData_UploadData? uploaddata,
|
ApplicationData_UploadData? uploaddata,
|
||||||
|
ApplicationData_GetUserById? getuserbyid,
|
||||||
}) {
|
}) {
|
||||||
final $result = create();
|
final $result = create();
|
||||||
if (textmessage != null) {
|
if (textmessage != null) {
|
||||||
|
|
@ -852,6 +904,9 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
if (uploaddata != null) {
|
if (uploaddata != null) {
|
||||||
$result.uploaddata = uploaddata;
|
$result.uploaddata = uploaddata;
|
||||||
}
|
}
|
||||||
|
if (getuserbyid != null) {
|
||||||
|
$result.getuserbyid = getuserbyid;
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
ApplicationData._() : super();
|
ApplicationData._() : super();
|
||||||
|
|
@ -864,15 +919,17 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
3 : ApplicationData_ApplicationData.getprekeysbyuserid,
|
3 : ApplicationData_ApplicationData.getprekeysbyuserid,
|
||||||
4 : ApplicationData_ApplicationData.getuploadtoken,
|
4 : ApplicationData_ApplicationData.getuploadtoken,
|
||||||
5 : ApplicationData_ApplicationData.uploaddata,
|
5 : ApplicationData_ApplicationData.uploaddata,
|
||||||
|
6 : ApplicationData_ApplicationData.getuserbyid,
|
||||||
0 : ApplicationData_ApplicationData.notSet
|
0 : ApplicationData_ApplicationData.notSet
|
||||||
};
|
};
|
||||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
||||||
..oo(0, [1, 2, 3, 4, 5])
|
..oo(0, [1, 2, 3, 4, 5, 6])
|
||||||
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textmessage', subBuilder: ApplicationData_TextMessage.create)
|
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textmessage', subBuilder: ApplicationData_TextMessage.create)
|
||||||
..aOM<ApplicationData_GetUserByUsername>(2, _omitFieldNames ? '' : 'getuserbyusername', subBuilder: ApplicationData_GetUserByUsername.create)
|
..aOM<ApplicationData_GetUserByUsername>(2, _omitFieldNames ? '' : 'getuserbyusername', subBuilder: ApplicationData_GetUserByUsername.create)
|
||||||
..aOM<ApplicationData_GetPrekeysByUserId>(3, _omitFieldNames ? '' : 'getprekeysbyuserid', subBuilder: ApplicationData_GetPrekeysByUserId.create)
|
..aOM<ApplicationData_GetPrekeysByUserId>(3, _omitFieldNames ? '' : 'getprekeysbyuserid', subBuilder: ApplicationData_GetPrekeysByUserId.create)
|
||||||
..aOM<ApplicationData_GetUploadToken>(4, _omitFieldNames ? '' : 'getuploadtoken', subBuilder: ApplicationData_GetUploadToken.create)
|
..aOM<ApplicationData_GetUploadToken>(4, _omitFieldNames ? '' : 'getuploadtoken', subBuilder: ApplicationData_GetUploadToken.create)
|
||||||
..aOM<ApplicationData_UploadData>(5, _omitFieldNames ? '' : 'uploaddata', subBuilder: ApplicationData_UploadData.create)
|
..aOM<ApplicationData_UploadData>(5, _omitFieldNames ? '' : 'uploaddata', subBuilder: ApplicationData_UploadData.create)
|
||||||
|
..aOM<ApplicationData_GetUserById>(6, _omitFieldNames ? '' : 'getuserbyid', subBuilder: ApplicationData_GetUserById.create)
|
||||||
..hasRequiredFields = false
|
..hasRequiredFields = false
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -954,6 +1011,17 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
void clearUploaddata() => clearField(5);
|
void clearUploaddata() => clearField(5);
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
ApplicationData_UploadData ensureUploaddata() => $_ensure(4);
|
ApplicationData_UploadData ensureUploaddata() => $_ensure(4);
|
||||||
|
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
ApplicationData_GetUserById get getuserbyid => $_getN(5);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
set getuserbyid(ApplicationData_GetUserById v) { setField(6, v); }
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
$core.bool hasGetuserbyid() => $_has(5);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
void clearGetuserbyid() => clearField(6);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
ApplicationData_GetUserById ensureGetuserbyid() => $_ensure(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Response_PreKey extends $pb.GeneratedMessage {
|
class Response_PreKey extends $pb.GeneratedMessage {
|
||||||
|
|
|
||||||
|
|
@ -117,11 +117,12 @@ const ApplicationData$json = {
|
||||||
'2': [
|
'2': [
|
||||||
{'1': 'textmessage', '3': 1, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.TextMessage', '9': 0, '10': 'textmessage'},
|
{'1': 'textmessage', '3': 1, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.TextMessage', '9': 0, '10': 'textmessage'},
|
||||||
{'1': 'getuserbyusername', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUserByUsername', '9': 0, '10': 'getuserbyusername'},
|
{'1': 'getuserbyusername', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUserByUsername', '9': 0, '10': 'getuserbyusername'},
|
||||||
|
{'1': 'getuserbyid', '3': 6, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUserById', '9': 0, '10': 'getuserbyid'},
|
||||||
{'1': 'getprekeysbyuserid', '3': 3, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetPrekeysByUserId', '9': 0, '10': 'getprekeysbyuserid'},
|
{'1': 'getprekeysbyuserid', '3': 3, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetPrekeysByUserId', '9': 0, '10': 'getprekeysbyuserid'},
|
||||||
{'1': 'getuploadtoken', '3': 4, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUploadToken', '9': 0, '10': 'getuploadtoken'},
|
{'1': 'getuploadtoken', '3': 4, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUploadToken', '9': 0, '10': 'getuploadtoken'},
|
||||||
{'1': 'uploaddata', '3': 5, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UploadData', '9': 0, '10': 'uploaddata'},
|
{'1': 'uploaddata', '3': 5, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UploadData', '9': 0, '10': 'uploaddata'},
|
||||||
],
|
],
|
||||||
'3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json],
|
'3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_GetUserById$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json],
|
||||||
'8': [
|
'8': [
|
||||||
{'1': 'ApplicationData'},
|
{'1': 'ApplicationData'},
|
||||||
],
|
],
|
||||||
|
|
@ -144,6 +145,14 @@ const ApplicationData_GetUserByUsername$json = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||||
|
const ApplicationData_GetUserById$json = {
|
||||||
|
'1': 'GetUserById',
|
||||||
|
'2': [
|
||||||
|
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||||
const ApplicationData_GetPrekeysByUserId$json = {
|
const ApplicationData_GetPrekeysByUserId$json = {
|
||||||
'1': 'GetPrekeysByUserId',
|
'1': 'GetPrekeysByUserId',
|
||||||
|
|
@ -175,18 +184,20 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
||||||
'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dG1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm'
|
'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dG1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm'
|
||||||
'VyLkFwcGxpY2F0aW9uRGF0YS5UZXh0TWVzc2FnZUgAUgt0ZXh0bWVzc2FnZRJjChFnZXR1c2Vy'
|
'VyLkFwcGxpY2F0aW9uRGF0YS5UZXh0TWVzc2FnZUgAUgt0ZXh0bWVzc2FnZRJjChFnZXR1c2Vy'
|
||||||
'Ynl1c2VybmFtZRgCIAEoCzIzLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldF'
|
'Ynl1c2VybmFtZRgCIAEoCzIzLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldF'
|
||||||
'VzZXJCeVVzZXJuYW1lSABSEWdldHVzZXJieXVzZXJuYW1lEmYKEmdldHByZWtleXNieXVzZXJp'
|
'VzZXJCeVVzZXJuYW1lSABSEWdldHVzZXJieXVzZXJuYW1lElEKC2dldHVzZXJieWlkGAYgASgL'
|
||||||
'ZBgDIAEoCzI0LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldFByZWtleXNCeV'
|
'Mi0uY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuR2V0VXNlckJ5SWRIAFILZ2V0dX'
|
||||||
'VzZXJJZEgAUhJnZXRwcmVrZXlzYnl1c2VyaWQSWgoOZ2V0dXBsb2FkdG9rZW4YBCABKAsyMC5j'
|
'NlcmJ5aWQSZgoSZ2V0cHJla2V5c2J5dXNlcmlkGAMgASgLMjQuY2xpZW50X3RvX3NlcnZlci5B'
|
||||||
'bGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5HZXRVcGxvYWRUb2tlbkgAUg5nZXR1cG'
|
'cHBsaWNhdGlvbkRhdGEuR2V0UHJla2V5c0J5VXNlcklkSABSEmdldHByZWtleXNieXVzZXJpZB'
|
||||||
'xvYWR0b2tlbhJOCgp1cGxvYWRkYXRhGAUgASgLMiwuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNh'
|
'JaCg5nZXR1cGxvYWR0b2tlbhgEIAEoCzIwLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25E'
|
||||||
'dGlvbkRhdGEuVXBsb2FkRGF0YUgAUgp1cGxvYWRkYXRhGjoKC1RleHRNZXNzYWdlEhcKB3VzZX'
|
'YXRhLkdldFVwbG9hZFRva2VuSABSDmdldHVwbG9hZHRva2VuEk4KCnVwbG9hZGRhdGEYBSABKA'
|
||||||
'JfaWQYASABKANSBnVzZXJJZBISCgRib2R5GAMgASgMUgRib2R5Gi8KEUdldFVzZXJCeVVzZXJu'
|
'syLC5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5VcGxvYWREYXRhSABSCnVwbG9h'
|
||||||
'YW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRotChJHZXRQcmVrZXlzQnlVc2VySWQSFw'
|
'ZGRhdGEaOgoLVGV4dE1lc3NhZ2USFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhIKBGJvZHkYAy'
|
||||||
'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkGiIKDkdldFVwbG9hZFRva2VuEhAKA2xlbhgBIAEoDVID'
|
'ABKAxSBGJvZHkaLwoRR2V0VXNlckJ5VXNlcm5hbWUSGgoIdXNlcm5hbWUYASABKAlSCHVzZXJu'
|
||||||
'bGVuGlsKClVwbG9hZERhdGESIQoMdXBsb2FkX3Rva2VuGAEgASgMUgt1cGxvYWRUb2tlbhIWCg'
|
'YW1lGiYKC0dldFVzZXJCeUlkEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBotChJHZXRQcmVrZX'
|
||||||
'ZvZmZzZXQYAiABKA1SBm9mZnNldBISCgRkYXRhGAMgASgMUgRkYXRhQhEKD0FwcGxpY2F0aW9u'
|
'lzQnlVc2VySWQSFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkGiIKDkdldFVwbG9hZFRva2VuEhAK'
|
||||||
'RGF0YQ==');
|
'A2xlbhgBIAEoDVIDbGVuGlsKClVwbG9hZERhdGESIQoMdXBsb2FkX3Rva2VuGAEgASgMUgt1cG'
|
||||||
|
'xvYWRUb2tlbhIWCgZvZmZzZXQYAiABKA1SBm9mZnNldBISCgRkYXRhGAMgASgMUgRkYXRhQhEK'
|
||||||
|
'D0FwcGxpY2F0aW9uRGF0YQ==');
|
||||||
|
|
||||||
@$core.Deprecated('Use responseDescriptor instead')
|
@$core.Deprecated('Use responseDescriptor instead')
|
||||||
const Response$json = {
|
const Response$json = {
|
||||||
|
|
|
||||||
|
|
@ -197,11 +197,15 @@ class V0 extends $pb.GeneratedMessage {
|
||||||
class NewMessage extends $pb.GeneratedMessage {
|
class NewMessage extends $pb.GeneratedMessage {
|
||||||
factory NewMessage({
|
factory NewMessage({
|
||||||
$core.List<$core.int>? body,
|
$core.List<$core.int>? body,
|
||||||
|
$fixnum.Int64? fromUserId,
|
||||||
}) {
|
}) {
|
||||||
final $result = create();
|
final $result = create();
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
$result.body = body;
|
$result.body = body;
|
||||||
}
|
}
|
||||||
|
if (fromUserId != null) {
|
||||||
|
$result.fromUserId = fromUserId;
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
NewMessage._() : super();
|
NewMessage._() : super();
|
||||||
|
|
@ -210,6 +214,7 @@ class NewMessage extends $pb.GeneratedMessage {
|
||||||
|
|
||||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'NewMessage', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create)
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'NewMessage', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create)
|
||||||
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'body', $pb.PbFieldType.OY)
|
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'body', $pb.PbFieldType.OY)
|
||||||
|
..aInt64(2, _omitFieldNames ? '' : 'fromUserId')
|
||||||
..hasRequiredFields = false
|
..hasRequiredFields = false
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -242,6 +247,15 @@ class NewMessage extends $pb.GeneratedMessage {
|
||||||
$core.bool hasBody() => $_has(0);
|
$core.bool hasBody() => $_has(0);
|
||||||
@$pb.TagNumber(1)
|
@$pb.TagNumber(1)
|
||||||
void clearBody() => clearField(1);
|
void clearBody() => clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$fixnum.Int64 get fromUserId => $_getI64(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set fromUserId($fixnum.Int64 v) { $_setInt64(1, v); }
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasFromUserId() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearFromUserId() => clearField(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Response_PreKey extends $pb.GeneratedMessage {
|
class Response_PreKey extends $pb.GeneratedMessage {
|
||||||
|
|
@ -316,6 +330,7 @@ class Response_UserData extends $pb.GeneratedMessage {
|
||||||
$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,
|
||||||
|
$core.List<$core.int>? username,
|
||||||
}) {
|
}) {
|
||||||
final $result = create();
|
final $result = create();
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
|
|
@ -336,6 +351,9 @@ class Response_UserData extends $pb.GeneratedMessage {
|
||||||
if (signedPrekeyId != null) {
|
if (signedPrekeyId != null) {
|
||||||
$result.signedPrekeyId = signedPrekeyId;
|
$result.signedPrekeyId = signedPrekeyId;
|
||||||
}
|
}
|
||||||
|
if (username != null) {
|
||||||
|
$result.username = username;
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
Response_UserData._() : super();
|
Response_UserData._() : super();
|
||||||
|
|
@ -349,6 +367,7 @@ class Response_UserData extends $pb.GeneratedMessage {
|
||||||
..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')
|
||||||
|
..a<$core.List<$core.int>>(7, _omitFieldNames ? '' : 'username', $pb.PbFieldType.OY)
|
||||||
..hasRequiredFields = false
|
..hasRequiredFields = false
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -420,6 +439,15 @@ 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)
|
||||||
|
$core.List<$core.int> get username => $_getN(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
set username($core.List<$core.int> v) { $_setBytes(6, v); }
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
$core.bool hasUsername() => $_has(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
void clearUsername() => clearField(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Response_Ok_Ok {
|
enum Response_Ok_Ok {
|
||||||
|
|
|
||||||
|
|
@ -54,13 +54,15 @@ final $typed_data.Uint8List v0Descriptor = $convert.base64Decode(
|
||||||
const NewMessage$json = {
|
const NewMessage$json = {
|
||||||
'1': 'NewMessage',
|
'1': 'NewMessage',
|
||||||
'2': [
|
'2': [
|
||||||
|
{'1': 'from_user_id', '3': 2, '4': 1, '5': 3, '10': 'fromUserId'},
|
||||||
{'1': 'body', '3': 1, '4': 1, '5': 12, '10': 'body'},
|
{'1': 'body', '3': 1, '4': 1, '5': 12, '10': 'body'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Descriptor for `NewMessage`. Decode as a `google.protobuf.DescriptorProto`.
|
/// Descriptor for `NewMessage`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
final $typed_data.Uint8List newMessageDescriptor = $convert.base64Decode(
|
final $typed_data.Uint8List newMessageDescriptor = $convert.base64Decode(
|
||||||
'CgpOZXdNZXNzYWdlEhIKBGJvZHkYASABKAxSBGJvZHk=');
|
'CgpOZXdNZXNzYWdlEiAKDGZyb21fdXNlcl9pZBgCIAEoA1IKZnJvbVVzZXJJZBISCgRib2R5GA'
|
||||||
|
'EgASgMUgRib2R5');
|
||||||
|
|
||||||
@$core.Deprecated('Use responseDescriptor instead')
|
@$core.Deprecated('Use responseDescriptor instead')
|
||||||
const Response$json = {
|
const Response$json = {
|
||||||
|
|
@ -90,12 +92,14 @@ const Response_UserData$json = {
|
||||||
'2': [
|
'2': [
|
||||||
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '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': 'username', '3': 7, '4': 1, '5': 12, '9': 0, '10': 'username', '17': true},
|
||||||
{'1': 'signed_prekey', '3': 4, '4': 1, '5': 12, '9': 1, '10': 'signedPrekey', '17': true},
|
{'1': 'public_identity_key', '3': 3, '4': 1, '5': 12, '9': 1, '10': 'publicIdentityKey', '17': true},
|
||||||
{'1': 'signed_prekey_signature', '3': 5, '4': 1, '5': 12, '9': 2, '10': 'signedPrekeySignature', '17': true},
|
{'1': 'signed_prekey', '3': 4, '4': 1, '5': 12, '9': 2, '10': 'signedPrekey', '17': true},
|
||||||
{'1': 'signed_prekey_id', '3': 6, '4': 1, '5': 3, '9': 3, '10': 'signedPrekeyId', '17': true},
|
{'1': 'signed_prekey_signature', '3': 5, '4': 1, '5': 12, '9': 3, '10': 'signedPrekeySignature', '17': true},
|
||||||
|
{'1': 'signed_prekey_id', '3': 6, '4': 1, '5': 3, '9': 4, '10': 'signedPrekeyId', '17': true},
|
||||||
],
|
],
|
||||||
'8': [
|
'8': [
|
||||||
|
{'1': '_username'},
|
||||||
{'1': '_public_identity_key'},
|
{'1': '_public_identity_key'},
|
||||||
{'1': '_signed_prekey'},
|
{'1': '_signed_prekey'},
|
||||||
{'1': '_signed_prekey_signature'},
|
{'1': '_signed_prekey_signature'},
|
||||||
|
|
@ -122,16 +126,17 @@ const Response_Ok$json = {
|
||||||
final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
|
final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
|
||||||
'CghSZXNwb25zZRIvCgJvaxgBIAEoCzIdLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuT2tIAF'
|
'CghSZXNwb25zZRIvCgJvaxgBIAEoCzIdLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuT2tIAF'
|
||||||
'ICb2sSKAoFZXJyb3IYAiABKA4yEC5lcnJvci5FcnJvckNvZGVIAFIFZXJyb3IaMAoGUHJlS2V5'
|
'ICb2sSKAoFZXJyb3IYAiABKA4yEC5lcnJvci5FcnJvckNvZGVIAFIFZXJyb3IaMAoGUHJlS2V5'
|
||||||
'Eg4KAmlkGAEgASgDUgJpZBIWCgZwcmVrZXkYAiABKAxSBnByZWtleRqGAwoIVXNlckRhdGESFw'
|
'Eg4KAmlkGAEgASgDUgJpZBIWCgZwcmVrZXkYAiABKAxSBnByZWtleRq0AwoIVXNlckRhdGESFw'
|
||||||
'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkEjsKB3ByZWtleXMYAiADKAsyIS5zZXJ2ZXJfdG9fY2xp'
|
'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkEjsKB3ByZWtleXMYAiADKAsyIS5zZXJ2ZXJfdG9fY2xp'
|
||||||
'ZW50LlJlc3BvbnNlLlByZUtleVIHcHJla2V5cxIzChNwdWJsaWNfaWRlbnRpdHlfa2V5GAMgAS'
|
'ZW50LlJlc3BvbnNlLlByZUtleVIHcHJla2V5cxIfCgh1c2VybmFtZRgHIAEoDEgAUgh1c2Vybm'
|
||||||
'gMSABSEXB1YmxpY0lkZW50aXR5S2V5iAEBEigKDXNpZ25lZF9wcmVrZXkYBCABKAxIAVIMc2ln'
|
'FtZYgBARIzChNwdWJsaWNfaWRlbnRpdHlfa2V5GAMgASgMSAFSEXB1YmxpY0lkZW50aXR5S2V5'
|
||||||
'bmVkUHJla2V5iAEBEjsKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAUgASgMSAJSFXNpZ25lZF'
|
'iAEBEigKDXNpZ25lZF9wcmVrZXkYBCABKAxIAlIMc2lnbmVkUHJla2V5iAEBEjsKF3NpZ25lZF'
|
||||||
'ByZWtleVNpZ25hdHVyZYgBARItChBzaWduZWRfcHJla2V5X2lkGAYgASgDSANSDnNpZ25lZFBy'
|
'9wcmVrZXlfc2lnbmF0dXJlGAUgASgMSANSFXNpZ25lZFByZWtleVNpZ25hdHVyZYgBARItChBz'
|
||||||
'ZWtleUlkiAEBQhYKFF9wdWJsaWNfaWRlbnRpdHlfa2V5QhAKDl9zaWduZWRfcHJla2V5QhoKGF'
|
'aWduZWRfcHJla2V5X2lkGAYgASgDSARSDnNpZ25lZFByZWtleUlkiAEBQgsKCV91c2VybmFtZU'
|
||||||
'9zaWduZWRfcHJla2V5X3NpZ25hdHVyZUITChFfc2lnbmVkX3ByZWtleV9pZBrBAQoCT2sSFAoE'
|
'IWChRfcHVibGljX2lkZW50aXR5X2tleUIQCg5fc2lnbmVkX3ByZWtleUIaChhfc2lnbmVkX3By'
|
||||||
'Tm9uZRgBIAEoCEgAUgROb25lEhgKBnVzZXJpZBgCIAEoA0gAUgZ1c2VyaWQSHgoJY2hhbGxlbm'
|
'ZWtleV9zaWduYXR1cmVCEwoRX3NpZ25lZF9wcmVrZXlfaWQawQEKAk9rEhQKBE5vbmUYASABKA'
|
||||||
'dlGAMgASgMSABSCWNoYWxsZW5nZRIiCgt1cGxvYWR0b2tlbhgEIAEoDEgAUgt1cGxvYWR0b2tl'
|
'hIAFIETm9uZRIYCgZ1c2VyaWQYAiABKANIAFIGdXNlcmlkEh4KCWNoYWxsZW5nZRgDIAEoDEgA'
|
||||||
'bhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXNlckRhdG'
|
'UgljaGFsbGVuZ2USIgoLdXBsb2FkdG9rZW4YBCABKAxIAFILdXBsb2FkdG9rZW4SQQoIdXNlcm'
|
||||||
'FIAFIIdXNlcmRhdGFCBAoCT2tCCgoIUmVzcG9uc2U=');
|
'RhdGEYBSABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlVzZXJEYXRhSABSCHVzZXJk'
|
||||||
|
'YXRhQgQKAk9rQgoKCFJlc3BvbnNl');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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/contacts_model.dart';
|
||||||
|
import 'package:twonly/src/model/json/message.dart';
|
||||||
import 'package:twonly/src/proto/api/client_to_server.pb.dart' as client;
|
import 'package:twonly/src/proto/api/client_to_server.pb.dart' as client;
|
||||||
import 'package:twonly/src/proto/api/client_to_server.pbserver.dart';
|
import 'package:twonly/src/proto/api/client_to_server.pbserver.dart';
|
||||||
import 'package:twonly/src/proto/api/error.pb.dart';
|
import 'package:twonly/src/proto/api/error.pb.dart';
|
||||||
|
|
@ -127,7 +131,6 @@ class ApiProvider {
|
||||||
messagesV0[msg.v0.seq] = msg;
|
messagesV0[msg.v0.seq] = msg;
|
||||||
} else {
|
} else {
|
||||||
_handleServerMessage(msg);
|
_handleServerMessage(msg);
|
||||||
log.shout("Got a new message from the server: $msg");
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.shout("Error parsing the servers message: $e");
|
log.shout("Error parsing the servers message: $e");
|
||||||
|
|
@ -137,7 +140,7 @@ class ApiProvider {
|
||||||
Future _handleServerMessage(server.ServerToClient msg) async {
|
Future _handleServerMessage(server.ServerToClient msg) async {
|
||||||
client.Response? response;
|
client.Response? response;
|
||||||
|
|
||||||
if (msg.v0.requestNewPreKeys) {
|
if (msg.v0.hasRequestNewPreKeys()) {
|
||||||
List<PreKeyRecord> localPreKeys = await SignalHelper.getPreKeys();
|
List<PreKeyRecord> localPreKeys = await SignalHelper.getPreKeys();
|
||||||
|
|
||||||
List<client.Response_PreKey> prekeysList = [];
|
List<client.Response_PreKey> prekeysList = [];
|
||||||
|
|
@ -149,10 +152,27 @@ class ApiProvider {
|
||||||
var prekeys = client.Response_Prekeys(prekeys: prekeysList);
|
var prekeys = client.Response_Prekeys(prekeys: prekeysList);
|
||||||
var ok = client.Response_Ok()..prekeys = prekeys;
|
var ok = client.Response_Ok()..prekeys = prekeys;
|
||||||
response = client.Response()..ok = ok;
|
response = client.Response()..ok = ok;
|
||||||
|
} else if (msg.v0.hasNewMessage()) {
|
||||||
|
Uint8List body = Uint8List.fromList(msg.v0.newMessage.body);
|
||||||
|
Int64 fromUserId = msg.v0.newMessage.fromUserId;
|
||||||
|
Message? message = await SignalHelper.getDecryptedText(fromUserId, body);
|
||||||
|
if (message != null) {
|
||||||
|
Result username = await getUsername(fromUserId);
|
||||||
|
if (username.isSuccess) {
|
||||||
|
print(username.value);
|
||||||
|
Uint8List name = username.value.userdata.username;
|
||||||
|
DbContacts.insertNewContact(
|
||||||
|
utf8.decode(name), fromUserId.toInt(), true);
|
||||||
|
print(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ok = client.Response_Ok()..none = true;
|
||||||
|
response = client.Response()..ok = ok;
|
||||||
|
} else {
|
||||||
|
log.shout("Got a new message from the server: $msg");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response == null) return;
|
|
||||||
|
|
||||||
var v0 = client.V0()
|
var v0 = client.V0()
|
||||||
..seq = msg.v0.seq
|
..seq = msg.v0.seq
|
||||||
..response = response;
|
..response = response;
|
||||||
|
|
@ -308,8 +328,7 @@ class ApiProvider {
|
||||||
Future<Result> register(String username, String? inviteCode) async {
|
Future<Result> register(String username, String? inviteCode) async {
|
||||||
final signalIdentity = await SignalHelper.getSignalIdentity();
|
final signalIdentity = await SignalHelper.getSignalIdentity();
|
||||||
if (signalIdentity == null) {
|
if (signalIdentity == null) {
|
||||||
return Result.error(
|
return Result.error(ErrorCode.InternalError);
|
||||||
"There was an fatal error. Try reinstalling the app.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final signalStore =
|
final signalStore =
|
||||||
|
|
@ -336,7 +355,18 @@ class ApiProvider {
|
||||||
|
|
||||||
final resp = await _sendRequestV0(req);
|
final resp = await _sendRequestV0(req);
|
||||||
if (resp == null) {
|
if (resp == null) {
|
||||||
return Result.error("Server is not reachable!");
|
return Result.error(ErrorCode.InternalError);
|
||||||
|
}
|
||||||
|
return _asResult(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Result> getUsername(Int64 userId) async {
|
||||||
|
var get = ApplicationData_GetUserById()..userId = userId;
|
||||||
|
var appData = ApplicationData()..getuserbyid = get;
|
||||||
|
var req = createClientToServerFromApplicationData(appData);
|
||||||
|
final resp = await _sendRequestV0(req);
|
||||||
|
if (resp == null) {
|
||||||
|
return Result.error(ErrorCode.InternalError);
|
||||||
}
|
}
|
||||||
return _asResult(resp);
|
return _asResult(resp);
|
||||||
}
|
}
|
||||||
|
|
@ -348,7 +378,22 @@ class ApiProvider {
|
||||||
|
|
||||||
final resp = await _sendRequestV0(req);
|
final resp = await _sendRequestV0(req);
|
||||||
if (resp == null) {
|
if (resp == null) {
|
||||||
return Result.error("Server is not reachable!");
|
return Result.error(ErrorCode.InternalError);
|
||||||
|
}
|
||||||
|
return _asResult(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Result> sendTextMessage(Int64 target, Uint8List msg) async {
|
||||||
|
var testMessage = ApplicationData_TextMessage()
|
||||||
|
..userId = target
|
||||||
|
..body = msg;
|
||||||
|
|
||||||
|
var appData = ApplicationData()..textmessage = testMessage;
|
||||||
|
var req = createClientToServerFromApplicationData(appData);
|
||||||
|
|
||||||
|
final resp = await _sendRequestV0(req);
|
||||||
|
if (resp == null) {
|
||||||
|
return Result.error(ErrorCode.InternalError);
|
||||||
}
|
}
|
||||||
return _asResult(resp);
|
return _asResult(resp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class DbProvider {
|
||||||
await _createDb(db);
|
await _createDb(db);
|
||||||
}, onUpgrade: (db, oldVersion, newVersion) async {
|
}, onUpgrade: (db, oldVersion, newVersion) async {
|
||||||
if (oldVersion < kVersion1) {
|
if (oldVersion < kVersion1) {
|
||||||
await _createDb(db);
|
//await _createDb(db);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ class ConnectPreKeyStore extends PreKeyStore {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> storePreKey(int preKeyId, PreKeyRecord record) async {
|
Future<void> storePreKey(int preKeyId, PreKeyRecord record) async {
|
||||||
if (await containsPreKey(preKeyId)) {
|
if (!await containsPreKey(preKeyId)) {
|
||||||
|
print(preKeyId);
|
||||||
await dbProvider.db!.insert(DB.tableName,
|
await dbProvider.db!.insert(DB.tableName,
|
||||||
{DB.columnPreKeyId: preKeyId, DB.columnPreKey: record.serialize()});
|
{DB.columnPreKeyId: preKeyId, DB.columnPreKey: record.serialize()});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class ConnectSessionStore extends SessionStore {
|
||||||
@override
|
@override
|
||||||
Future<void> storeSession(
|
Future<void> storeSession(
|
||||||
SignalProtocolAddress address, SessionRecord record) async {
|
SignalProtocolAddress address, SessionRecord record) async {
|
||||||
if (await containsSession(address)) {
|
if (!await containsSession(address)) {
|
||||||
await dbProvider.db!.insert(DB.tableName, {
|
await dbProvider.db!.insert(DB.tableName, {
|
||||||
DB.columnDeviceId: address.getDeviceId(),
|
DB.columnDeviceId: address.getDeviceId(),
|
||||||
DB.columnName: address.getName(),
|
DB.columnName: address.getName(),
|
||||||
|
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:developer';
|
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
|
||||||
import 'package:twonly/src/utils/signal.dart';
|
|
||||||
import 'connect_sender_key_store.dart';
|
|
||||||
import 'connect_signal_protocol_store.dart';
|
|
||||||
|
|
||||||
class SignalDataModel {
|
|
||||||
Uint8List userId;
|
|
||||||
ConnectSignalProtocolStore signalStore;
|
|
||||||
ConnectSenderKeyStore senderKeyStore;
|
|
||||||
SignalDataModel({
|
|
||||||
required this.userId,
|
|
||||||
required this.senderKeyStore,
|
|
||||||
required this.signalStore,
|
|
||||||
});
|
|
||||||
// Session validation
|
|
||||||
Future<Fingerprint?> generateSessionFingerPrint(String target) async {
|
|
||||||
try {
|
|
||||||
IdentityKey? targetIdentity = await signalStore
|
|
||||||
.getIdentity(SignalProtocolAddress(target, defaultDeviceId));
|
|
||||||
if (targetIdentity != null) {
|
|
||||||
final generator = NumericFingerprintGenerator(5200);
|
|
||||||
final localFingerprint = generator.createFor(
|
|
||||||
1,
|
|
||||||
userId,
|
|
||||||
(await signalStore.getIdentityKeyPair()).getPublicKey(),
|
|
||||||
Uint8List.fromList(utf8.encode(target)),
|
|
||||||
targetIdentity,
|
|
||||||
);
|
|
||||||
return localFingerprint;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreKeyBundle preKeyBundleFromJson(Map<String, dynamic> remoteBundle) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
Future<String?> getEncryptedText(String text, String target) async {
|
|
||||||
try {
|
|
||||||
SessionCipher session = SessionCipher.fromStore(
|
|
||||||
signalStore, SignalProtocolAddress(target, defaultDeviceId));
|
|
||||||
final ciphertext =
|
|
||||||
await session.encrypt(Uint8List.fromList(utf8.encode(text)));
|
|
||||||
Map<String, dynamic> data = {
|
|
||||||
"msg": base64Encode(ciphertext.serialize()),
|
|
||||||
"type": ciphertext.getType(),
|
|
||||||
};
|
|
||||||
return jsonEncode(data);
|
|
||||||
} catch (e) {
|
|
||||||
log(e.toString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> getDecryptedText(String source, String msg) async {
|
|
||||||
try {
|
|
||||||
SessionCipher session = SessionCipher.fromStore(
|
|
||||||
signalStore, SignalProtocolAddress(source, defaultDeviceId));
|
|
||||||
Map data = jsonDecode(msg);
|
|
||||||
if (data["type"] == CiphertextMessage.prekeyType) {
|
|
||||||
PreKeySignalMessage pre =
|
|
||||||
PreKeySignalMessage(base64Decode(data["msg"]));
|
|
||||||
Uint8List plaintext = await session.decrypt(pre);
|
|
||||||
String dectext = utf8.decode(plaintext);
|
|
||||||
return dectext;
|
|
||||||
} else if (data["type"] == CiphertextMessage.whisperType) {
|
|
||||||
SignalMessage signalMsg =
|
|
||||||
SignalMessage.fromSerialized(base64Decode(data["msg"]));
|
|
||||||
Uint8List plaintext = await session.decryptFromSignal(signalMsg);
|
|
||||||
String dectext = utf8.decode(plaintext);
|
|
||||||
return dectext;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log(e.toString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:twonly/main.dart';
|
import 'package:twonly/main.dart';
|
||||||
import 'package:twonly/src/model/contacts_model.dart';
|
import 'package:twonly/src/model/contacts_model.dart';
|
||||||
|
import 'package:twonly/src/model/json/message.dart';
|
||||||
|
import 'package:twonly/src/proto/api/error.pb.dart';
|
||||||
import 'package:twonly/src/providers/api_provider.dart';
|
import 'package:twonly/src/providers/api_provider.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
// ignore: library_prefixes
|
// ignore: library_prefixes
|
||||||
|
|
@ -12,11 +15,30 @@ Future<bool> addNewContact(String username) async {
|
||||||
final res = await apiProvider.getUserData(username);
|
final res = await apiProvider.getUserData(username);
|
||||||
|
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
|
bool added = await DbContacts.insertNewContact(
|
||||||
|
username, res.value.userdata.userId.toInt(), false);
|
||||||
|
|
||||||
|
if (!added) {
|
||||||
|
print("RETURN FALSE HIER!!!");
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (await SignalHelper.addNewContact(res.value.userdata)) {
|
if (await SignalHelper.addNewContact(res.value.userdata)) {
|
||||||
await dbProvider.db!.insert(DbContacts.tableName, {
|
Message msg =
|
||||||
DbContacts.columnDisplayName: username,
|
Message(kind: MessageKind.contactRequest, timestamp: DateTime.now());
|
||||||
DbContacts.columnUserId: res.value.userdata.userId.toInt()
|
|
||||||
});
|
Uint8List? bytes =
|
||||||
|
await SignalHelper.encryptMessage(msg, res.value.userdata.userId);
|
||||||
|
|
||||||
|
if (bytes == null) {
|
||||||
|
Logger("utils/api").shout("Error encryption message!");
|
||||||
|
return res.error(ErrorCode.InternalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result resp =
|
||||||
|
await apiProvider.sendTextMessage(res.value.userdata.userId, bytes);
|
||||||
|
|
||||||
|
return resp.isSuccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res.isSuccess;
|
return res.isSuccess;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:fixnum/fixnum.dart';
|
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/json/message.dart';
|
||||||
import 'package:twonly/src/model/json/signal_identity.dart';
|
import 'package:twonly/src/model/json/signal_identity.dart';
|
||||||
import 'package:twonly/src/proto/api/server_to_client.pb.dart';
|
import 'package:twonly/src/proto/api/server_to_client.pb.dart';
|
||||||
import 'package:twonly/src/signal/connect_signal_protocol_store.dart';
|
import 'package:twonly/src/signal/connect_signal_protocol_store.dart';
|
||||||
|
|
@ -86,13 +89,17 @@ Future<ConnectSignalProtocolStore?> getSignalStore() async {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SignalIdentity?> getSignalIdentity() async {
|
Future<SignalIdentity?> getSignalIdentity() async {
|
||||||
final storage = getSecureStorage();
|
try {
|
||||||
final signalIdentityJson = await storage.read(key: "signal_identity");
|
final storage = getSecureStorage();
|
||||||
if (signalIdentityJson == null) {
|
final signalIdentityJson = await storage.read(key: "signal_identity");
|
||||||
|
if (signalIdentityJson == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return SignalIdentity.fromJson(jsonDecode(signalIdentityJson));
|
||||||
|
} catch (e) {
|
||||||
|
Logger("signal.dart/getSignalIdentity").shout(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SignalIdentity.fromJson(jsonDecode(signalIdentityJson));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ConnectSignalProtocolStore> getSignalStoreFromIdentity(
|
Future<ConnectSignalProtocolStore> getSignalStoreFromIdentity(
|
||||||
|
|
@ -140,3 +147,99 @@ Future createIfNotExistsSignalIdentity() async {
|
||||||
await storage.write(
|
await storage.write(
|
||||||
key: "signal_identity", value: jsonEncode(storedSignalIdentity));
|
key: "signal_identity", value: jsonEncode(storedSignalIdentity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<Fingerprint?> generateSessionFingerPrint(String target) async {
|
||||||
|
// try {
|
||||||
|
// IdentityKey? targetIdentity = await signalStore
|
||||||
|
// .getIdentity(SignalProtocolAddress(target, defaultDeviceId));
|
||||||
|
// if (targetIdentity != null) {
|
||||||
|
// final generator = NumericFingerprintGenerator(5200);
|
||||||
|
// final localFingerprint = generator.createFor(
|
||||||
|
// 1,
|
||||||
|
// userId,
|
||||||
|
// (await signalStore.getIdentityKeyPair()).getPublicKey(),
|
||||||
|
// Uint8List.fromList(utf8.encode(target)),
|
||||||
|
// targetIdentity,
|
||||||
|
// );
|
||||||
|
// return localFingerprint;
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// } catch (e) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
Uint8List intToBytes(int value) {
|
||||||
|
final byteData = ByteData(4);
|
||||||
|
byteData.setInt32(0, value, Endian.big);
|
||||||
|
return byteData.buffer.asUint8List();
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytesToInt(Uint8List bytes) {
|
||||||
|
final byteData = ByteData.sublistView(bytes);
|
||||||
|
return byteData.getInt32(0, Endian.big);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Uint8List>? removeLastFourBytes(Uint8List original) {
|
||||||
|
if (original.length < 4) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final newList = Uint8List(original.length - 4);
|
||||||
|
newList.setAll(0, original.sublist(0, original.length - 4));
|
||||||
|
|
||||||
|
final lastFourBytes = original.sublist(original.length - 4);
|
||||||
|
return [newList, lastFourBytes];
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Uint8List?> encryptMessage(Message msg, Int64 target) async {
|
||||||
|
try {
|
||||||
|
ConnectSignalProtocolStore signalStore = (await getSignalStore())!;
|
||||||
|
|
||||||
|
SessionCipher session = SessionCipher.fromStore(
|
||||||
|
signalStore, SignalProtocolAddress(target.toString(), defaultDeviceId));
|
||||||
|
|
||||||
|
final ciphertext = await session
|
||||||
|
.encrypt(Uint8List.fromList(gzip.encode(utf8.encode(msg.toJson()))));
|
||||||
|
|
||||||
|
var b = BytesBuilder();
|
||||||
|
b.add(ciphertext.serialize());
|
||||||
|
b.add(intToBytes(ciphertext.getType()));
|
||||||
|
|
||||||
|
return b.takeBytes();
|
||||||
|
} catch (e) {
|
||||||
|
Logger("utils/signal").shout(e.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Message?> getDecryptedText(Int64 source, Uint8List msg) async {
|
||||||
|
try {
|
||||||
|
ConnectSignalProtocolStore signalStore = (await getSignalStore())!;
|
||||||
|
|
||||||
|
SessionCipher session = SessionCipher.fromStore(
|
||||||
|
signalStore, SignalProtocolAddress(source.toString(), defaultDeviceId));
|
||||||
|
|
||||||
|
List<Uint8List>? msgs = removeLastFourBytes(msg);
|
||||||
|
if (msgs == null) return null;
|
||||||
|
Uint8List body = msgs[0];
|
||||||
|
int type = bytesToInt(msgs[1]);
|
||||||
|
|
||||||
|
// gzip.decode(body);
|
||||||
|
|
||||||
|
Uint8List plaintext;
|
||||||
|
if (type == CiphertextMessage.prekeyType) {
|
||||||
|
PreKeySignalMessage pre = PreKeySignalMessage(body);
|
||||||
|
plaintext = await session.decrypt(pre);
|
||||||
|
} else if (type == CiphertextMessage.whisperType) {
|
||||||
|
SignalMessage signalMsg = SignalMessage.fromSerialized(body);
|
||||||
|
plaintext = await session.decryptFromSignal(signalMsg);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Message dectext = Message.fromJson(utf8.decode(gzip.decode(plaintext)));
|
||||||
|
return dectext;
|
||||||
|
} catch (e) {
|
||||||
|
Logger("utils/signal").shout(e.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:twonly/src/components/initialsavatar_component.dart';
|
import 'package:twonly/src/components/initialsavatar_component.dart';
|
||||||
|
import 'package:twonly/src/model/contacts_model.dart';
|
||||||
import 'package:twonly/src/views/search_username_view.dart';
|
import 'package:twonly/src/views/search_username_view.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'new_message_view.dart';
|
import 'new_message_view.dart';
|
||||||
|
|
@ -56,12 +57,19 @@ class ChatListView extends StatefulWidget {
|
||||||
|
|
||||||
class _ChatListViewState extends State<ChatListView> {
|
class _ChatListViewState extends State<ChatListView> {
|
||||||
int _secondsSinceOpen = 0;
|
int _secondsSinceOpen = 0;
|
||||||
|
int _newContactRequests = 0;
|
||||||
late Timer _timer;
|
late Timer _timer;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_startTimer();
|
_startTimer();
|
||||||
|
_checkNewContactRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future _checkNewContactRequests() async {
|
||||||
|
_newContactRequests = (await DbContacts.getUsers()).length;
|
||||||
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startTimer() {
|
void _startTimer() {
|
||||||
|
|
@ -172,17 +180,41 @@ class _ChatListViewState extends State<ChatListView> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(AppLocalizations.of(context)!.chatsTitle),
|
title: Text(AppLocalizations.of(context)!.chatsTitle),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
Stack(
|
||||||
icon: Icon(Icons.person_add), // User with add icon
|
children: [
|
||||||
onPressed: () {
|
IconButton(
|
||||||
Navigator.push(
|
icon: Icon(Icons.person_add), // User with add icon
|
||||||
context,
|
onPressed: () {
|
||||||
MaterialPageRoute(
|
Navigator.push(
|
||||||
builder: (context) => SearchUsernameView(),
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SearchUsernameView(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (_newContactRequests > 0)
|
||||||
|
Positioned(
|
||||||
|
right: 5,
|
||||||
|
top: 0,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(5.0), // Add some padding
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.red, // Background color
|
||||||
|
shape: BoxShape.circle, // Make it circular
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
_newContactRequests.toString(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white, // Text color
|
||||||
|
fontSize: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
},
|
)
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ListView.builder(
|
body: ListView.builder(
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
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:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:twonly/src/model/contacts_model.dart';
|
||||||
import 'package:twonly/src/utils/api.dart';
|
import 'package:twonly/src/utils/api.dart';
|
||||||
import 'package:twonly/src/views/register_view.dart';
|
import 'package:twonly/src/views/register_view.dart';
|
||||||
|
|
||||||
|
|
@ -14,28 +15,24 @@ class SearchUsernameView extends StatefulWidget {
|
||||||
|
|
||||||
class _SearchUsernameView extends State<SearchUsernameView> {
|
class _SearchUsernameView extends State<SearchUsernameView> {
|
||||||
final TextEditingController searchUserName = TextEditingController();
|
final TextEditingController searchUserName = TextEditingController();
|
||||||
|
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
|
||||||
Future _addNewUser(BuildContext context) async {
|
Future _addNewUser(BuildContext context) async {
|
||||||
Timer timer = Timer(Duration(milliseconds: 500), () {
|
setState(() {
|
||||||
setState(() {
|
_isLoading = true;
|
||||||
_isLoading = true;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final status = await addNewContact(searchUserName.text);
|
final status = await addNewContact(searchUserName.text);
|
||||||
|
|
||||||
timer.cancel();
|
|
||||||
// loaderDelay.timeout(Duration(microseconds: 0));
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
Logger("search_user_name").warning("Replace instead of pop");
|
Logger("search_user_name").warning("Replace instead of pop");
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
if (status) {
|
if (status) {
|
||||||
Navigator.pop(context);
|
// Navigator.pop(context);
|
||||||
} else if (context.mounted) {
|
} else if (context.mounted) {
|
||||||
showAlertDialog(
|
showAlertDialog(
|
||||||
context,
|
context,
|
||||||
|
|
@ -84,7 +81,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
|
||||||
controller: searchUserName,
|
controller: searchUserName,
|
||||||
decoration: getInputDecoration(
|
decoration: getInputDecoration(
|
||||||
AppLocalizations.of(context)!.searchUsernameInput))),
|
AppLocalizations.of(context)!.searchUsernameInput))),
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 20),
|
||||||
OutlinedButton.icon(
|
OutlinedButton.icon(
|
||||||
icon: Icon(Icons.qr_code),
|
icon: Icon(Icons.qr_code),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|
@ -93,9 +90,18 @@ class _SearchUsernameView extends State<SearchUsernameView> {
|
||||||
},
|
},
|
||||||
label: Text("QR-Code scannen"),
|
label: Text("QR-Code scannen"),
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 30),
|
||||||
const SizedBox(height: 40),
|
Container(
|
||||||
if (_isLoading) const Center(child: CircularProgressIndicator())
|
alignment: Alignment.centerLeft,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 4.0, vertical: 10),
|
||||||
|
child: Text(
|
||||||
|
"Neue Followanfragen",
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ContactsListView(),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -103,11 +109,73 @@ class _SearchUsernameView extends State<SearchUsernameView> {
|
||||||
padding: const EdgeInsets.only(bottom: 30.0),
|
padding: const EdgeInsets.only(bottom: 30.0),
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_addNewUser(context);
|
if (!_isLoading) _addNewUser(context);
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.arrow_right_rounded),
|
child: (_isLoading)
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Icon(Icons.arrow_right_rounded),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ContactsListView extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
State<ContactsListView> createState() => _ContactsListViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ContactsListViewState extends State<ContactsListView> {
|
||||||
|
List<Contact> _allContacts = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_loadContacts();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future _loadContacts() async {
|
||||||
|
List<Contact> allContacts = await DbContacts.getUsers();
|
||||||
|
_allContacts = allContacts.where((contact) => !contact.accepted).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: _allContacts.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final contact = _allContacts[index];
|
||||||
|
|
||||||
|
if (!contact.requested) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(contact.displayName),
|
||||||
|
subtitle: Text('Pending'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
title: Text(contact.displayName),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.close, color: Colors.red),
|
||||||
|
onPressed: () {
|
||||||
|
// Handle reject action
|
||||||
|
print('Rejected ${contact.displayName}');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.check, color: Colors.green),
|
||||||
|
onPressed: () {
|
||||||
|
// Handle accept action
|
||||||
|
print('Accepted ${contact.displayName}');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue