mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 16:28:40 +00:00
drift ready for contacts and messages
This commit is contained in:
parent
cfd6bd92cb
commit
5866d3e7e4
21 changed files with 314 additions and 173 deletions
|
|
@ -1,5 +1,9 @@
|
|||
import 'package:twonly/src/database/database.dart';
|
||||
import 'package:twonly/src/providers/api_provider.dart';
|
||||
import 'package:twonly/src/providers/db_provider.dart';
|
||||
|
||||
late ApiProvider apiProvider;
|
||||
|
||||
// uses for background notification
|
||||
late DbProvider dbProvider;
|
||||
late TwonlyDatabase twonlyDatabase;
|
||||
|
|
|
|||
|
|
@ -41,16 +41,13 @@ void main() async {
|
|||
await dbProvider.ready;
|
||||
|
||||
apiProvider = ApiProvider();
|
||||
twonlyDatabase = TwonlyDatabase();
|
||||
|
||||
FlutterForegroundTask.initCommunicationPort();
|
||||
|
||||
runApp(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
Provider<TwonlyDatabase>(
|
||||
create: (context) => TwonlyDatabase(),
|
||||
dispose: (context, db) => db.close(),
|
||||
),
|
||||
ChangeNotifierProvider(create: (_) => SendNextMediaTo()),
|
||||
ChangeNotifierProvider(create: (_) => settingsController),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:collection';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/verified_shield.dart';
|
||||
import 'package:twonly/src/database/contacts_db.dart';
|
||||
import 'package:twonly/src/database/database.dart';
|
||||
|
|
@ -141,7 +142,7 @@ class UserCheckbox extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
StreamBuilder(
|
||||
stream: context.db.watchFlameCounter(user.userId),
|
||||
stream: twonlyDatabase.watchFlameCounter(user.userId),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData && snapshot.data! != 0) {
|
||||
return Container();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:drift_flutter/drift_flutter.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:twonly/src/database/contacts_db.dart';
|
||||
import 'package:twonly/src/database/messages_db.dart';
|
||||
|
|
@ -45,6 +46,11 @@ class TwonlyDatabase extends _$TwonlyDatabase {
|
|||
.watch();
|
||||
}
|
||||
|
||||
Future<List<Message>> getAllMessagesForRetransmitting() {
|
||||
return (select(messages)..where((t) => t.acknowledgeByServer.equals(false)))
|
||||
.get();
|
||||
}
|
||||
|
||||
Future openedAllTextMessages(int contactId) {
|
||||
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
|
||||
return (update(messages)
|
||||
|
|
@ -55,12 +61,61 @@ class TwonlyDatabase extends _$TwonlyDatabase {
|
|||
.write(updates);
|
||||
}
|
||||
|
||||
Future updateMessageByOtherUser(
|
||||
int userId, int messageId, MessagesCompanion updatedValues) {
|
||||
return (update(messages)
|
||||
..where((c) =>
|
||||
c.contactId.equals(userId) & c.messageId.equals(messageId)))
|
||||
.write(updatedValues);
|
||||
}
|
||||
|
||||
Future updateMessageByOtherMessageId(
|
||||
int userId, int messageOtherId, MessagesCompanion updatedValues) {
|
||||
return (update(messages)
|
||||
..where((c) =>
|
||||
c.contactId.equals(userId) &
|
||||
c.messageOtherId.equals(messageOtherId)))
|
||||
.write(updatedValues);
|
||||
}
|
||||
|
||||
Future updateMessageByMessageId(
|
||||
int messageId, MessagesCompanion updatedValues) {
|
||||
return (update(messages)..where((c) => c.messageId.equals(messageId)))
|
||||
.write(updatedValues);
|
||||
}
|
||||
|
||||
Future<int?> insertMessage(MessagesCompanion message) async {
|
||||
try {
|
||||
return await into(messages).insert(message);
|
||||
} catch (e) {
|
||||
Logger("twonlyDatabase").shout("Error while inserting message: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteMessageById(int messageId) {
|
||||
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
||||
}
|
||||
|
||||
// ------------
|
||||
|
||||
Future<int> insertContact(ContactsCompanion contact) {
|
||||
return into(contacts).insert(contact);
|
||||
}
|
||||
|
||||
Future incTotalMediaCounter(int contactId) async {
|
||||
return (update(contacts)..where((t) => t.userId.equals(contactId)))
|
||||
.write(ContactsCompanion(
|
||||
totalMediaCounter: Value(
|
||||
(await (select(contacts)..where((t) => t.userId.equals(contactId)))
|
||||
.get())
|
||||
.first
|
||||
.totalMediaCounter +
|
||||
1,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
SingleOrNullSelectable<Contact> getContactByUserId(int userId) {
|
||||
return select(contacts)..where((t) => t.userId.equals(userId));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ class Messages extends Table {
|
|||
IntColumn get responseToOtherMessageId => integer().nullable()();
|
||||
|
||||
BoolColumn get acknowledgeByUser => boolean().withDefault(Constant(false))();
|
||||
IntColumn get downloadState => intEnum<DownloadState>()();
|
||||
IntColumn get downloadState => intEnum<DownloadState>()
|
||||
.withDefault(Constant(DownloadState.pending.index))();
|
||||
|
||||
BoolColumn get acknowledgeByServer =>
|
||||
boolean().withDefault(Constant(false))();
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import 'dart:convert';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/app.dart';
|
||||
import '../../../../.blocked/archives/contacts_model.dart';
|
||||
import 'package:twonly/src/database/database.dart';
|
||||
import 'package:twonly/src/database/messages_db.dart';
|
||||
import 'package:twonly/src/model/json/message.dart';
|
||||
import '../../../../.blocked/archives/messages_model.dart';
|
||||
import 'package:twonly/src/proto/api/error.pb.dart';
|
||||
import 'package:twonly/src/providers/api/api_utils.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
|
|
@ -17,8 +16,10 @@ import 'package:twonly/src/utils/misc.dart';
|
|||
import 'package:twonly/src/utils/signal.dart' as SignalHelper;
|
||||
|
||||
Future tryTransmitMessages() async {
|
||||
List<DbMessage> retransmit =
|
||||
await DbMessages.getAllMessagesForRetransmitting();
|
||||
List<Message> retransmit =
|
||||
await twonlyDatabase.getAllMessagesForRetransmitting();
|
||||
|
||||
|
||||
if (retransmit.isEmpty) return;
|
||||
|
||||
Logger("api.dart").info("try sending messages: ${retransmit.length}");
|
||||
|
|
@ -30,12 +31,16 @@ Future tryTransmitMessages() async {
|
|||
Uint8List? bytes = box.get("retransmit-$msgId-textmessage");
|
||||
if (bytes != null) {
|
||||
Result resp = await apiProvider.sendTextMessage(
|
||||
retransmit[i].otherUserId,
|
||||
retransmit[i].contactId,
|
||||
bytes,
|
||||
);
|
||||
|
||||
if (resp.isSuccess) {
|
||||
DbMessages.acknowledgeMessageByServer(msgId);
|
||||
await twonlyDatabase.updateMessageByMessageId(
|
||||
msgId,
|
||||
MessagesCompanion(acknowledgeByServer: Value(true))
|
||||
);
|
||||
|
||||
box.delete("retransmit-$msgId-textmessage");
|
||||
} else {
|
||||
// in case of error do nothing. As the message is not removed the app will try again when relaunched
|
||||
|
|
@ -44,9 +49,9 @@ Future tryTransmitMessages() async {
|
|||
|
||||
Uint8List? encryptedMedia = await box.get("retransmit-$msgId-media");
|
||||
if (encryptedMedia != null) {
|
||||
final content = retransmit[i].messageContent;
|
||||
final content = MessageJson.fromJson(jsonDecode(retransmit[i].contentJson!)).content;
|
||||
if (content is MediaMessageContent) {
|
||||
uploadMediaFile(msgId, retransmit[i].otherUserId, encryptedMedia,
|
||||
uploadMediaFile(msgId, retransmit[i].contactId, encryptedMedia,
|
||||
content.isRealTwonly, content.maxShowTime, retransmit[i].sendAt);
|
||||
}
|
||||
}
|
||||
|
|
@ -54,7 +59,7 @@ Future tryTransmitMessages() async {
|
|||
}
|
||||
|
||||
// this functions ensures that the message is received by the server and in case of errors will try again later
|
||||
Future<Result> encryptAndSendMessage(int userId, Message msg) async {
|
||||
Future<Result> encryptAndSendMessage(int userId, MessageJson msg) async {
|
||||
Uint8List? bytes = await SignalHelper.encryptMessage(msg, userId);
|
||||
|
||||
if (bytes == null) {
|
||||
|
|
@ -71,7 +76,12 @@ Future<Result> encryptAndSendMessage(int userId, Message msg) async {
|
|||
|
||||
if (resp.isSuccess) {
|
||||
if (msg.messageId != null) {
|
||||
DbMessages.acknowledgeMessageByServer(msg.messageId!);
|
||||
|
||||
|
||||
await twonlyDatabase.updateMessageByMessageId(
|
||||
msg.messageId!,
|
||||
MessagesCompanion(acknowledgeByServer: Value(true))
|
||||
);
|
||||
box.delete("retransmit-${msg.messageId}-textmessage");
|
||||
}
|
||||
}
|
||||
|
|
@ -84,15 +94,18 @@ Future sendTextMessage(int target, String message) async {
|
|||
|
||||
DateTime messageSendAt = DateTime.now();
|
||||
|
||||
int? messageId = await DbMessages.insertMyMessage(
|
||||
target.toInt(),
|
||||
MessageKind.textMessage,
|
||||
content,
|
||||
messageSendAt,
|
||||
);
|
||||
int? messageId = await twonlyDatabase.insertMessage(MessagesCompanion(
|
||||
contactId: Value(target),
|
||||
kind: Value(MessageKind.textMessage),
|
||||
sendAt: Value(messageSendAt),
|
||||
downloadState: Value(DownloadState.downloaded),
|
||||
contentJson: Value(jsonEncode(content.toJson()))
|
||||
),);
|
||||
|
||||
|
||||
if (messageId == null) return;
|
||||
|
||||
Message msg = Message(
|
||||
MessageJson msg = MessageJson(
|
||||
kind: MessageKind.textMessage,
|
||||
messageId: messageId,
|
||||
content: content,
|
||||
|
|
@ -160,13 +173,19 @@ Future uploadMediaFile(
|
|||
box.delete("retransmit-$messageId-media");
|
||||
box.delete("retransmit-$messageId-uploadtoken");
|
||||
|
||||
await DbContacts.updateTotalMediaCounter(target.toInt());
|
||||
twonlyDatabase.incTotalMediaCounter(target);
|
||||
twonlyDatabase.updateContact(
|
||||
target,
|
||||
ContactsCompanion(
|
||||
lastMessageReceived: Value(messageSendAt),
|
||||
),
|
||||
);
|
||||
|
||||
// Ensures the retransmit of the message
|
||||
await encryptAndSendMessage(
|
||||
target,
|
||||
Message(
|
||||
kind: MessageKind.image,
|
||||
MessageJson(
|
||||
kind: MessageKind.media,
|
||||
messageId: messageId,
|
||||
content: MediaMessageContent(
|
||||
downloadToken: uploadToken,
|
||||
|
|
@ -210,17 +229,19 @@ class SendImage {
|
|||
}
|
||||
|
||||
messageSendAt = DateTime.now();
|
||||
messageId = await DbMessages.insertMyMessage(
|
||||
userId.toInt(),
|
||||
MessageKind.image,
|
||||
MediaMessageContent(
|
||||
int? messageId = await twonlyDatabase.insertMessage(MessagesCompanion(
|
||||
contactId: Value(userId),
|
||||
kind: Value(MessageKind.media),
|
||||
sendAt: Value(messageSendAt!),
|
||||
downloadState: Value(DownloadState.pending),
|
||||
contentJson: Value(jsonEncode(MediaMessageContent(
|
||||
downloadToken: [],
|
||||
maxShowTime: maxShowTime,
|
||||
isRealTwonly: isRealTwonly,
|
||||
isVideo: false,
|
||||
),
|
||||
messageSendAt!,
|
||||
);
|
||||
).toJson()))
|
||||
));
|
||||
|
||||
// should only happen when there is no space left on the smartphone -> abort message
|
||||
if (messageId == null) return;
|
||||
|
||||
|
|
@ -295,9 +316,15 @@ Future tryDownloadMedia(int messageId, int fromUserId, List<int> mediaToken,
|
|||
if (media != null && media.isNotEmpty) {
|
||||
offset = media.length;
|
||||
}
|
||||
globalCallBackOnDownloadChange(mediaToken, true);
|
||||
box.put("${mediaToken}_messageId", messageId);
|
||||
box.put("${mediaToken}_fromUserId", fromUserId);
|
||||
final update =
|
||||
MessagesCompanion(downloadState: Value(DownloadState.downloading));
|
||||
await twonlyDatabase.updateMessageByOtherUser(
|
||||
fromUserId,
|
||||
messageId,
|
||||
update
|
||||
);
|
||||
apiProvider.triggerDownload(mediaToken, offset);
|
||||
}
|
||||
|
||||
|
|
@ -326,7 +353,12 @@ Future<Uint8List?> getDownloadedMedia(
|
|||
}
|
||||
if (media == null) return null;
|
||||
|
||||
await userOpenedOtherMessage(otherUserId, messageOtherId);
|
||||
// await userOpenedOtherMessage(otherUserId, messageOtherId);
|
||||
notifyContactAboutOpeningMessage(otherUserId, messageOtherId);
|
||||
twonlyDatabase.updateMessageByOtherMessageId(otherUserId, messageOtherId, MessagesCompanion(
|
||||
openedAt: Value(DateTime.now())
|
||||
));
|
||||
|
||||
box.delete(mediaToken.toString());
|
||||
box.put("${mediaToken}_downloaded", "deleted");
|
||||
box.delete("${mediaToken}_messageId");
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/app.dart';
|
||||
import '../../../../.blocked/archives/contacts_model.dart';
|
||||
import 'package:twonly/src/database/database.dart';
|
||||
import 'package:twonly/src/database/messages_db.dart';
|
||||
import 'package:twonly/src/model/json/message.dart';
|
||||
import '../../../../.blocked/archives/messages_model.dart';
|
||||
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/error.pb.dart';
|
||||
|
|
@ -27,7 +28,7 @@ Future handleServerMessage(server.ServerToClient msg) async {
|
|||
response = await handleRequestNewPreKey();
|
||||
} else if (msg.v0.hasNewMessage()) {
|
||||
Uint8List body = Uint8List.fromList(msg.v0.newMessage.body);
|
||||
Int64 fromUserId = msg.v0.newMessage.fromUserId;
|
||||
int fromUserId = msg.v0.newMessage.fromUserId.toInt();
|
||||
response = await handleNewMessage(fromUserId, body);
|
||||
} else if (msg.v0.hasDownloaddata()) {
|
||||
response = await handleDownloadData(msg.v0.downloaddata);
|
||||
|
|
@ -62,18 +63,13 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
|||
// media file was deleted by the server. remove the media from device
|
||||
|
||||
if (messageId != null) {
|
||||
int? fromUserId = await DbMessages.deleteMessageById(messageId);
|
||||
await twonlyDatabase.deleteMessageById(messageId);
|
||||
box.delete(boxId);
|
||||
if (fromUserId != null) {
|
||||
globalCallBackOnMessageChange(fromUserId, messageId);
|
||||
}
|
||||
box.delete("${data.uploadToken}_fromUserId");
|
||||
box.delete("${data.uploadToken}_downloaded");
|
||||
globalCallBackOnDownloadChange(data.uploadToken, false);
|
||||
var ok = client.Response_Ok()..none = true;
|
||||
return client.Response()..ok = ok;
|
||||
} else {
|
||||
globalCallBackOnDownloadChange(data.uploadToken, false);
|
||||
var ok = client.Response_Ok()..none = true;
|
||||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
|
@ -111,9 +107,15 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
|||
.shout("error decrypting the message: ${data.uploadToken}");
|
||||
}
|
||||
|
||||
final update =
|
||||
MessagesCompanion(downloadState: Value(DownloadState.downloaded));
|
||||
await twonlyDatabase.updateMessageByOtherUser(
|
||||
fromUserId,
|
||||
messageId!,
|
||||
update,
|
||||
);
|
||||
|
||||
box.delete(boxId);
|
||||
await globalCallBackOnMessageChange(fromUserId, messageId);
|
||||
globalCallBackOnDownloadChange(data.uploadToken, false);
|
||||
}
|
||||
} else {
|
||||
box.put(boxId, downloadedBytes);
|
||||
|
|
@ -123,52 +125,72 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
|||
return client.Response()..ok = ok;
|
||||
}
|
||||
|
||||
Future<client.Response> handleNewMessage(
|
||||
Int64 fromUserId, Uint8List body) async {
|
||||
Message? message = await SignalHelper.getDecryptedText(fromUserId, body);
|
||||
Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
||||
MessageJson? message = await SignalHelper.getDecryptedText(fromUserId, body);
|
||||
if (message != null) {
|
||||
switch (message.kind) {
|
||||
case MessageKind.contactRequest:
|
||||
Result username = await apiProvider.getUsername(fromUserId);
|
||||
if (username.isSuccess) {
|
||||
Uint8List name = username.value.userdata.username;
|
||||
DbContacts.insertNewContact(
|
||||
utf8.decode(name), fromUserId.toInt(), true);
|
||||
localPushNotificationNewMessage(fromUserId.toInt(), message, 999999);
|
||||
|
||||
int added = await twonlyDatabase.insertContact(ContactsCompanion(
|
||||
username: Value(utf8.decode(name)),
|
||||
userId: Value(fromUserId),
|
||||
requested: Value(true),
|
||||
));
|
||||
if (added > 0) {
|
||||
localPushNotificationNewMessage(
|
||||
fromUserId.toInt(),
|
||||
message,
|
||||
999999,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MessageKind.opened:
|
||||
await DbMessages.otherUserOpenedMyMessage(
|
||||
fromUserId.toInt(),
|
||||
final update = MessagesCompanion(openedAt: Value(message.timestamp));
|
||||
await twonlyDatabase.updateMessageByOtherUser(
|
||||
fromUserId,
|
||||
message.messageId!,
|
||||
message.timestamp,
|
||||
update,
|
||||
);
|
||||
break;
|
||||
case MessageKind.rejectRequest:
|
||||
DbContacts.deleteUser(fromUserId.toInt());
|
||||
await twonlyDatabase.deleteContactByUserId(fromUserId);
|
||||
break;
|
||||
case MessageKind.acceptRequest:
|
||||
DbContacts.acceptUser(fromUserId.toInt());
|
||||
final update = ContactsCompanion(accepted: Value(true));
|
||||
twonlyDatabase.updateContact(fromUserId, update);
|
||||
localPushNotificationNewMessage(fromUserId.toInt(), message, 8888888);
|
||||
break;
|
||||
case MessageKind.ack:
|
||||
DbMessages.acknowledgeMessageByUser(
|
||||
fromUserId.toInt(), message.messageId!);
|
||||
final update = MessagesCompanion(acknowledgeByUser: Value(true));
|
||||
await twonlyDatabase.updateMessageByOtherUser(
|
||||
fromUserId,
|
||||
message.messageId!,
|
||||
update,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
if (message.kind != MessageKind.textMessage &&
|
||||
message.kind != MessageKind.video &&
|
||||
message.kind != MessageKind.image) {
|
||||
message.kind != MessageKind.media) {
|
||||
Logger("handleServerMessages")
|
||||
.shout("Got unknown MessageKind $message");
|
||||
} else {
|
||||
String content = jsonEncode(message.content.toJson());
|
||||
int? messageId = await DbMessages.insertOtherMessage(
|
||||
fromUserId.toInt(),
|
||||
message.kind,
|
||||
message.messageId!,
|
||||
content,
|
||||
message.timestamp);
|
||||
String content = jsonEncode(message.content!.toJson());
|
||||
|
||||
final update = MessagesCompanion(
|
||||
contactId: Value(fromUserId),
|
||||
kind: Value(message.kind),
|
||||
messageOtherId: Value(message.messageId),
|
||||
contentJson: Value(content),
|
||||
sendAt: Value(message.timestamp),
|
||||
);
|
||||
|
||||
final messageId = await twonlyDatabase.insertMessage(
|
||||
update,
|
||||
);
|
||||
|
||||
if (messageId == null) {
|
||||
return client.Response()..error = ErrorCode.InternalError;
|
||||
|
|
@ -176,7 +198,7 @@ Future<client.Response> handleNewMessage(
|
|||
|
||||
encryptAndSendMessage(
|
||||
fromUserId,
|
||||
Message(
|
||||
MessageJson(
|
||||
kind: MessageKind.ack,
|
||||
messageId: message.messageId!,
|
||||
content: MessageContent(),
|
||||
|
|
@ -184,19 +206,25 @@ Future<client.Response> handleNewMessage(
|
|||
),
|
||||
);
|
||||
|
||||
if (message.kind == MessageKind.video ||
|
||||
message.kind == MessageKind.image) {
|
||||
await DbContacts.updateTotalMediaCounter(fromUserId.toInt());
|
||||
if (message.kind == MessageKind.media) {
|
||||
twonlyDatabase.updateContact(
|
||||
fromUserId,
|
||||
ContactsCompanion(
|
||||
lastMessageReceived: Value(message.timestamp),
|
||||
),
|
||||
);
|
||||
|
||||
twonlyDatabase.incTotalMediaCounter(fromUserId);
|
||||
|
||||
if (!globalIsAppInBackground) {
|
||||
final content = message.content;
|
||||
if (content is MediaMessageContent) {
|
||||
List<int> downloadToken = content.downloadToken;
|
||||
tryDownloadMedia(messageId, fromUserId.toInt(), downloadToken);
|
||||
tryDownloadMedia(messageId, fromUserId, downloadToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
localPushNotificationNewMessage(
|
||||
fromUserId.toInt(), message, messageId);
|
||||
localPushNotificationNewMessage(fromUserId, message, messageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class ApiProvider {
|
|||
|
||||
// reconnection params
|
||||
Timer? reconnectionTimer;
|
||||
int _reconnectionDelay = 5;
|
||||
// int _reconnectionDelay = 5;
|
||||
|
||||
final HashMap<Int64, server.ServerToClient?> messagesV0 = HashMap();
|
||||
IOWebSocketChannel? _channel;
|
||||
|
|
@ -68,7 +68,7 @@ class ApiProvider {
|
|||
Future onConnected() async {
|
||||
await authenticate();
|
||||
globalCallbackConnectionState(true);
|
||||
_reconnectionDelay = 5;
|
||||
// _reconnectionDelay = 5;
|
||||
|
||||
if (!globalIsAppInBackground) {
|
||||
tryTransmitMessages();
|
||||
|
|
@ -131,24 +131,24 @@ class ApiProvider {
|
|||
|
||||
void tryToReconnect() {
|
||||
return;
|
||||
if (globalIsAppInBackground) return;
|
||||
if (reconnectionTimer != null) {
|
||||
reconnectionTimer!.cancel();
|
||||
}
|
||||
// if (globalIsAppInBackground) return;
|
||||
// if (reconnectionTimer != null) {
|
||||
// reconnectionTimer!.cancel();
|
||||
// }
|
||||
|
||||
final int randomDelay = Random().nextInt(20);
|
||||
final int delay = _reconnectionDelay + randomDelay;
|
||||
// final int randomDelay = Random().nextInt(20);
|
||||
// final int delay = _reconnectionDelay + randomDelay;
|
||||
|
||||
debugPrint("Delay reconnection $delay");
|
||||
// debugPrint("Delay reconnection $delay");
|
||||
|
||||
reconnectionTimer = Timer(Duration(seconds: delay), () async {
|
||||
// increase delay but set a maximum of 60 seconds (including the random delay)
|
||||
_reconnectionDelay = _reconnectionDelay * 2;
|
||||
if (_reconnectionDelay > 40) {
|
||||
_reconnectionDelay = 40;
|
||||
}
|
||||
await connect();
|
||||
});
|
||||
// reconnectionTimer = Timer(Duration(seconds: delay), () async {
|
||||
// // increase delay but set a maximum of 60 seconds (including the random delay)
|
||||
// _reconnectionDelay = _reconnectionDelay * 2;
|
||||
// if (_reconnectionDelay > 40) {
|
||||
// _reconnectionDelay = 40;
|
||||
// }
|
||||
// await connect();
|
||||
// });
|
||||
}
|
||||
|
||||
void _onData(dynamic msgBuffer) {
|
||||
|
|
@ -289,7 +289,7 @@ class ApiProvider {
|
|||
..username = username
|
||||
..publicIdentityKey =
|
||||
(await signalStore.getIdentityKeyPair()).getPublicKey().serialize()
|
||||
..registrationId = signalIdentity.registrationId
|
||||
..registrationId = Int64(signalIdentity.registrationId)
|
||||
..signedPrekey = signedPreKey.getKeyPair().publicKey.serialize()
|
||||
..signedPrekeySignature = signedPreKey.signature
|
||||
..signedPrekeyId = Int64(signedPreKey.id);
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ Future initFCMService() async {
|
|||
});
|
||||
}
|
||||
|
||||
late TwonlyDatabase bgTwonlyDB;
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
// Wenn Tasks länger als 30 Sekunden ausgeführt werden, wird der Prozess möglicherweise automatisch vom Gerät beendet.
|
||||
|
|
@ -75,7 +73,7 @@ Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
|||
Logger("firebase-background")
|
||||
.shout('Handling a background message: ${message.messageId}');
|
||||
|
||||
bgTwonlyDB = TwonlyDatabase();
|
||||
twonlyDatabase = TwonlyDatabase();
|
||||
|
||||
apiProvider = ApiProvider();
|
||||
await apiProvider.connect();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import 'dart:io';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/database/contacts_db.dart';
|
||||
import 'package:twonly/src/database/database.dart';
|
||||
import 'package:twonly/src/model/json/message.dart' as my;
|
||||
|
||||
|
|
@ -164,10 +166,9 @@ String getPushNotificationText(String key, String userName) {
|
|||
}
|
||||
|
||||
Future localPushNotificationNewMessage(
|
||||
int fromUserId, my.Message message, int messageId) async {
|
||||
Contact? user = await TwonlyDatabase.provider
|
||||
.getContactByUserId(fromUserId)
|
||||
.getSingleOrNull();
|
||||
int fromUserId, my.MessageJson message, int messageId) async {
|
||||
Contact? user =
|
||||
await twonlyDatabase.getContactByUserId(fromUserId).getSingleOrNull();
|
||||
|
||||
if (user == null) return;
|
||||
|
||||
|
|
@ -176,23 +177,25 @@ Future localPushNotificationNewMessage(
|
|||
final content = message.content;
|
||||
|
||||
if (content is my.TextMessageContent) {
|
||||
msg = getPushNotificationText("newTextMessage", user.displayName);
|
||||
msg =
|
||||
getPushNotificationText("newTextMessage", getContactDisplayName(user));
|
||||
} else if (content is my.MediaMessageContent) {
|
||||
if (content.isRealTwonly) {
|
||||
msg = getPushNotificationText("newTwonly", user.displayName);
|
||||
msg = getPushNotificationText("newTwonly", getContactDisplayName(user));
|
||||
} else if (content.isVideo) {
|
||||
msg = getPushNotificationText("newVideo", user.displayName);
|
||||
msg = getPushNotificationText("newVideo", getContactDisplayName(user));
|
||||
} else {
|
||||
msg = getPushNotificationText("newImage", user.displayName);
|
||||
msg = getPushNotificationText("newImage", getContactDisplayName(user));
|
||||
}
|
||||
}
|
||||
|
||||
if (message.kind == my.MessageKind.contactRequest) {
|
||||
msg = getPushNotificationText("contactRequest", user.displayName);
|
||||
msg =
|
||||
getPushNotificationText("contactRequest", getContactDisplayName(user));
|
||||
}
|
||||
|
||||
if (message.kind == my.MessageKind.acceptRequest) {
|
||||
msg = getPushNotificationText("acceptRequest", user.displayName);
|
||||
msg = getPushNotificationText("acceptRequest", getContactDisplayName(user));
|
||||
}
|
||||
|
||||
if (msg == "") {
|
||||
|
|
@ -213,7 +216,7 @@ Future localPushNotificationNewMessage(
|
|||
NotificationDetails(android: androidNotificationDetails);
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
messageId,
|
||||
user.displayName,
|
||||
getContactDisplayName(user),
|
||||
msg,
|
||||
notificationDetails,
|
||||
payload: message.kind.index.toString(),
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ List<Uint8List>? removeLastFourBytes(Uint8List original) {
|
|||
return [newList, lastFourBytes];
|
||||
}
|
||||
|
||||
Future<Uint8List?> encryptBytes(Uint8List bytes, Int64 target) async {
|
||||
Future<Uint8List?> encryptBytes(Uint8List bytes, int target) async {
|
||||
try {
|
||||
ConnectSignalProtocolStore signalStore = (await getSignalStore())!;
|
||||
|
||||
|
|
@ -248,7 +248,7 @@ Future<Uint8List?> decryptBytes(Uint8List bytes, int target) async {
|
|||
}
|
||||
}
|
||||
|
||||
Future<Uint8List?> encryptMessage(Message msg, int target) async {
|
||||
Future<Uint8List?> encryptMessage(MessageJson msg, int target) async {
|
||||
try {
|
||||
ConnectSignalProtocolStore signalStore = (await getSignalStore())!;
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ Future<Uint8List?> encryptMessage(Message msg, int target) async {
|
|||
}
|
||||
}
|
||||
|
||||
Future<Message?> getDecryptedText(Int64 source, Uint8List msg) async {
|
||||
Future<MessageJson?> getDecryptedText(int source, Uint8List msg) async {
|
||||
try {
|
||||
ConnectSignalProtocolStore signalStore = (await getSignalStore())!;
|
||||
|
||||
|
|
@ -293,8 +293,8 @@ Future<Message?> getDecryptedText(Int64 source, Uint8List msg) async {
|
|||
} else {
|
||||
return null;
|
||||
}
|
||||
Message dectext =
|
||||
Message.fromJson(jsonDecode(utf8.decode(gzip.decode(plaintext))));
|
||||
MessageJson dectext =
|
||||
MessageJson.fromJson(jsonDecode(utf8.decode(gzip.decode(plaintext))));
|
||||
return dectext;
|
||||
} catch (e) {
|
||||
Logger("utils/signal").shout(e.toString());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/image_editor/action_button.dart';
|
||||
import 'package:twonly/src/components/media_view_sizing.dart';
|
||||
import 'package:twonly/src/components/notification_badge.dart';
|
||||
|
|
@ -55,7 +56,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
Future updateAsync(int userId) async {
|
||||
if (sendNextMediaToUserName != null) return;
|
||||
Contact? contact =
|
||||
await context.db.getContactByUserId(userId).getSingleOrNull();
|
||||
await twonlyDatabase.getContactByUserId(userId).getSingleOrNull();
|
||||
if (contact != null) {
|
||||
sendNextMediaToUserName = getContactDisplayName(contact);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:typed_data';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/best_friends_selector.dart';
|
||||
import 'package:twonly/src/components/flame.dart';
|
||||
import 'package:twonly/src/components/headline.dart';
|
||||
import 'package:twonly/src/components/initialsavatar.dart';
|
||||
import 'package:twonly/src/components/verified_shield.dart';
|
||||
import '../../../../.blocked/archives/contacts_model.dart';
|
||||
import 'package:twonly/src/database/contacts_db.dart';
|
||||
import 'package:twonly/src/database/database.dart';
|
||||
import 'package:twonly/src/providers/api/api.dart';
|
||||
import 'package:twonly/src/providers/messages_change_provider.dart';
|
||||
import 'package:twonly/src/providers/send_next_media_to.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/views/home_view.dart';
|
||||
|
|
@ -31,43 +32,55 @@ class ShareImageView extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ShareImageView extends State<ShareImageView> {
|
||||
List<Contact> _users = [];
|
||||
List<Contact> contacts = [];
|
||||
List<Contact> _otherUsers = [];
|
||||
List<Contact> _bestFriends = [];
|
||||
int maxTotalMediaCounter = 0;
|
||||
Uint8List? imageBytes;
|
||||
bool sendingImage = false;
|
||||
final HashSet<Int64> _selectedUserIds = HashSet<Int64>();
|
||||
final HashSet<int> _selectedUserIds = HashSet<int>();
|
||||
final TextEditingController searchUserName = TextEditingController();
|
||||
bool showRealTwonlyWarning = false;
|
||||
late StreamSubscription<List<Contact>> contactSub;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadAsync();
|
||||
}
|
||||
|
||||
Future<void> _loadAsync() async {
|
||||
int? sendNextMediaToUserId =
|
||||
context.read<SendNextMediaTo>().sendNextMediaToUserId;
|
||||
if (sendNextMediaToUserId != null) {
|
||||
_selectedUserIds.add(Int64(sendNextMediaToUserId));
|
||||
_selectedUserIds.add(sendNextMediaToUserId);
|
||||
}
|
||||
_users = await DbContacts.getActiveUsers();
|
||||
_updateUsers(_users);
|
||||
imageBytes = await widget.imageBytesFuture;
|
||||
setState(() {});
|
||||
|
||||
Stream<List<Contact>> allContacts =
|
||||
twonlyDatabase.watchContactsForChatList();
|
||||
|
||||
contactSub = allContacts.listen((allContacts) {
|
||||
setState(() {
|
||||
contacts = allContacts;
|
||||
});
|
||||
updateUsers(allContacts);
|
||||
});
|
||||
|
||||
//_users = await DbContacts.getActiveUsers();
|
||||
// _updateUsers(_users);
|
||||
// imageBytes = await widget.imageBytesFuture;
|
||||
// setState(() {});
|
||||
}
|
||||
|
||||
Future _updateUsers(List<Contact> users) async {
|
||||
Map<int, int> flameCounters =
|
||||
context.read<MessagesChangeProvider>().flamesCounter;
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
contactSub.cancel();
|
||||
}
|
||||
|
||||
Future updateUsers(List<Contact> users) async {
|
||||
// Sort contacts by flameCounter and then by totalMediaCounter
|
||||
users.sort((a, b) {
|
||||
// First, compare by flameCounter
|
||||
int flameComparison = (flameCounters[b.userId.toInt()] ?? 0)
|
||||
.compareTo((flameCounters[a.userId.toInt()] ?? 0));
|
||||
int flameComparison = (getFlameCounterFromContact(b))
|
||||
.compareTo((getFlameCounterFromContact(a)));
|
||||
if (flameComparison != 0) {
|
||||
return flameComparison; // Sort by flameCounter in descending order
|
||||
}
|
||||
|
|
@ -87,8 +100,7 @@ class _ShareImageView extends State<ShareImageView> {
|
|||
List<Contact> otherUsers = [];
|
||||
|
||||
for (var contact in users) {
|
||||
if ((flameCounters[contact.userId.toInt()] ?? 0) > 0 &&
|
||||
bestFriends.length < 6) {
|
||||
if ((getFlameCounterFromContact(contact)) > 0 && bestFriends.length < 6) {
|
||||
bestFriends.add(contact);
|
||||
} else {
|
||||
otherUsers.add(contact);
|
||||
|
|
@ -103,19 +115,20 @@ class _ShareImageView extends State<ShareImageView> {
|
|||
|
||||
Future _filterUsers(String query) async {
|
||||
if (query.isEmpty) {
|
||||
_updateUsers(_users);
|
||||
updateUsers(contacts);
|
||||
return;
|
||||
}
|
||||
List<Contact> usersFiltered = _users
|
||||
.where((user) =>
|
||||
user.displayName.toLowerCase().contains(query.toLowerCase()))
|
||||
List<Contact> usersFiltered = contacts
|
||||
.where((user) => getContactDisplayName(user)
|
||||
.toLowerCase()
|
||||
.contains(query.toLowerCase()))
|
||||
.toList();
|
||||
_updateUsers(usersFiltered);
|
||||
updateUsers(usersFiltered);
|
||||
}
|
||||
|
||||
void updateStatus(Int64 userId, bool checked) {
|
||||
void updateStatus(int userId, bool checked) {
|
||||
if (widget.isRealTwonly) {
|
||||
Contact user = _users.firstWhere((x) => x.userId == userId);
|
||||
Contact user = contacts.firstWhere((x) => x.userId == userId);
|
||||
if (!user.verified) {
|
||||
showRealTwonlyWarning = true;
|
||||
setState(() {});
|
||||
|
|
@ -248,26 +261,24 @@ class UserList extends StatelessWidget {
|
|||
required this.updateStatus,
|
||||
required this.isRealTwonly,
|
||||
});
|
||||
final Function(Int64, bool) updateStatus;
|
||||
final Function(int, bool) updateStatus;
|
||||
final List<Contact> users;
|
||||
final int maxTotalMediaCounter;
|
||||
final bool isRealTwonly;
|
||||
final HashSet<Int64> selectedUserIds;
|
||||
final HashSet<int> selectedUserIds;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Step 1: Sort the users alphabetically
|
||||
users.sort((a, b) => a.displayName.compareTo(b.displayName));
|
||||
|
||||
Map<int, int> flameCounters =
|
||||
context.watch<MessagesChangeProvider>().flamesCounter;
|
||||
users.sort(
|
||||
(a, b) => getContactDisplayName(a).compareTo(getContactDisplayName(b)));
|
||||
|
||||
return ListView.builder(
|
||||
restorationId: 'new_message_users_list',
|
||||
itemCount: users.length,
|
||||
itemBuilder: (BuildContext context, int i) {
|
||||
Contact user = users[i];
|
||||
int flameCounter = flameCounters[user.userId.toInt()] ?? 0;
|
||||
int flameCounter = getFlameCounterFromContact(user);
|
||||
return ListTile(
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start, // Center horizontally
|
||||
|
|
@ -278,7 +289,7 @@ class UserList extends StatelessWidget {
|
|||
padding: const EdgeInsets.only(right: 1),
|
||||
child: VerifiedShield(user),
|
||||
),
|
||||
Text(user.displayName),
|
||||
Text(getContactDisplayName(user)),
|
||||
if (flameCounter >= 1)
|
||||
FlameCounterWidget(
|
||||
user,
|
||||
|
|
@ -289,7 +300,7 @@ class UserList extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
leading: InitialsAvatar(
|
||||
displayName: user.displayName,
|
||||
getContactDisplayName(user),
|
||||
fontSize: 15,
|
||||
),
|
||||
trailing: Checkbox(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'dart:convert';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/animate_icon.dart';
|
||||
import 'package:twonly/src/components/initialsavatar.dart';
|
||||
import 'package:twonly/src/components/message_send_state_icon.dart';
|
||||
|
|
@ -164,7 +165,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
|||
}
|
||||
|
||||
Future initStreams() async {
|
||||
Stream<Contact> contact = context.db.watchContact(widget.userid);
|
||||
Stream<Contact> contact = twonlyDatabase.watchContact(widget.userid);
|
||||
userSub = contact.listen((contact) {
|
||||
setState(() {
|
||||
user = contact;
|
||||
|
|
@ -172,7 +173,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
|||
});
|
||||
|
||||
Stream<List<Message>> msgStream =
|
||||
context.db.watchAllMessagesFrom(widget.userid);
|
||||
twonlyDatabase.watchAllMessagesFrom(widget.userid);
|
||||
messageSub = msgStream.listen((msgs) {
|
||||
if (!context.mounted) return;
|
||||
var updated = false;
|
||||
|
|
@ -186,7 +187,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
|||
}
|
||||
}
|
||||
if (updated) {
|
||||
context.db.openedAllTextMessages(widget.userid);
|
||||
twonlyDatabase.openedAllTextMessages(widget.userid);
|
||||
} else {
|
||||
// The stream should be get an update, so only update the UI when all are opened
|
||||
setState(() {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/flame.dart';
|
||||
import 'package:twonly/src/components/initialsavatar.dart';
|
||||
import 'package:twonly/src/components/message_send_state_icon.dart';
|
||||
|
|
@ -32,7 +33,7 @@ class ChatListView extends StatefulWidget {
|
|||
class _ChatListViewState extends State<ChatListView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Stream<List<Contact>> contacts = context.db.watchContactsForChatList();
|
||||
Stream<List<Contact>> contacts = twonlyDatabase.watchContactsForChatList();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -50,7 +51,7 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
// title:
|
||||
actions: [
|
||||
StreamBuilder(
|
||||
stream: context.db.watchContactsRequested(),
|
||||
stream: twonlyDatabase.watchContactsRequested(),
|
||||
builder: (context, snapshot) {
|
||||
var count = 0;
|
||||
if (snapshot.hasData && snapshot.data != null) {
|
||||
|
|
@ -193,8 +194,8 @@ class _UserListItem extends State<UserListItem> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final notOpenedMessages =
|
||||
context.db.watchMessageNotOpened(widget.user.userId);
|
||||
final lastMessage = context.db.watchLastMessage(widget.user.userId);
|
||||
twonlyDatabase.watchMessageNotOpened(widget.user.userId);
|
||||
final lastMessage = twonlyDatabase.watchLastMessage(widget.user.userId);
|
||||
|
||||
// if (widget.lastMessage != null) {
|
||||
// state = widget.lastMessage!.getSendState();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|||
import 'package:lottie/lottie.dart';
|
||||
import 'package:no_screenshot/no_screenshot.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/animate_icon.dart';
|
||||
import 'package:twonly/src/components/media_view_sizing.dart';
|
||||
import 'package:twonly/src/database/database.dart';
|
||||
|
|
@ -56,7 +57,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
|
||||
Future asyncLoadNextMedia() async {
|
||||
Stream<List<Message>> messages =
|
||||
context.db.watchMessageNotOpened(widget.userId);
|
||||
twonlyDatabase.watchMessageNotOpened(widget.userId);
|
||||
|
||||
_subscription = messages.listen((messages) {
|
||||
for (Message msg in messages) {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
|
|||
return;
|
||||
}
|
||||
|
||||
int added = await context.db.insertContact(ContactsCompanion(
|
||||
int added = await twonlyDatabase.insertContact(ContactsCompanion(
|
||||
username: Value(searchUserName.text),
|
||||
userId: Value(res.value.userdata.userId),
|
||||
requested: Value(false),
|
||||
|
|
@ -89,7 +89,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
|
|||
);
|
||||
}
|
||||
|
||||
Stream<List<Contact>> contacts = context.db.watchNotAcceptedContacts();
|
||||
Stream<List<Contact>> contacts = twonlyDatabase.watchNotAcceptedContacts();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -189,7 +189,8 @@ class _ContactsListViewState extends State<ContactsListView> {
|
|||
color: const Color.fromARGB(164, 244, 67, 54)),
|
||||
onPressed: () async {
|
||||
final update = ContactsCompanion(blocked: Value(true));
|
||||
await context.db.updateContact(contact.userId, update);
|
||||
await twonlyDatabase.updateContact(
|
||||
contact.userId, update);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
@ -198,7 +199,8 @@ class _ContactsListViewState extends State<ContactsListView> {
|
|||
child: IconButton(
|
||||
icon: Icon(Icons.close, color: Colors.red),
|
||||
onPressed: () async {
|
||||
await context.db.deleteContactByUserId(contact.userId);
|
||||
await twonlyDatabase
|
||||
.deleteContactByUserId(contact.userId);
|
||||
encryptAndSendMessage(
|
||||
contact.userId,
|
||||
MessageJson(
|
||||
|
|
@ -214,7 +216,7 @@ class _ContactsListViewState extends State<ContactsListView> {
|
|||
icon: Icon(Icons.check, color: Colors.green),
|
||||
onPressed: () async {
|
||||
final update = ContactsCompanion(accepted: Value(true));
|
||||
await context.db.updateContact(contact.userId, update);
|
||||
await twonlyDatabase.updateContact(contact.userId, update);
|
||||
encryptAndSendMessage(
|
||||
contact.userId,
|
||||
MessageJson(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:drift/drift.dart' hide Column;
|
|||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/format_long_string.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/database/contacts_db.dart';
|
||||
|
|
@ -36,7 +37,7 @@ class _ContactVerifyViewState extends State<ContactVerifyView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Stream<Contact?> contact = context.db
|
||||
Stream<Contact?> contact = twonlyDatabase
|
||||
.getContactByUserId(widget.contact.userId)
|
||||
.watchSingleOrNull();
|
||||
|
||||
|
|
@ -144,7 +145,7 @@ class _ContactVerifyViewState extends State<ContactVerifyView> {
|
|||
onPressed: () {
|
||||
final update =
|
||||
ContactsCompanion(verified: Value(false));
|
||||
context.db.updateContact(contact.userId, update);
|
||||
twonlyDatabase.updateContact(contact.userId, update);
|
||||
},
|
||||
label: Text(
|
||||
context.lang.contactVerifyNumberClearVerification),
|
||||
|
|
@ -154,7 +155,7 @@ class _ContactVerifyViewState extends State<ContactVerifyView> {
|
|||
icon: FaIcon(FontAwesomeIcons.shieldHeart),
|
||||
onPressed: () {
|
||||
final update = ContactsCompanion(verified: Value(true));
|
||||
context.db.updateContact(contact.userId, update);
|
||||
twonlyDatabase.updateContact(contact.userId, update);
|
||||
},
|
||||
label: Text(context.lang.contactVerifyNumberMarkAsVerified),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/alert_dialog.dart';
|
||||
import 'package:twonly/src/components/better_list_title.dart';
|
||||
import 'package:twonly/src/components/flame.dart';
|
||||
|
|
@ -24,7 +25,7 @@ class _ContactViewState extends State<ContactView> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Stream<Contact?> contact =
|
||||
context.db.getContactByUserId(widget.userId).watchSingleOrNull();
|
||||
twonlyDatabase.getContactByUserId(widget.userId).watchSingleOrNull();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -76,7 +77,7 @@ class _ContactViewState extends State<ContactView> {
|
|||
|
||||
if (context.mounted && nickName != null && nickName != "") {
|
||||
final update = ContactsCompanion(nickName: Value(nickName));
|
||||
context.db.updateContact(contact.userId, update);
|
||||
twonlyDatabase.updateContact(contact.userId, update);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
@ -106,7 +107,8 @@ class _ContactViewState extends State<ContactView> {
|
|||
if (block) {
|
||||
final update = ContactsCompanion(blocked: Value(true));
|
||||
if (context.mounted) {
|
||||
await context.db.updateContact(contact.userId, update);
|
||||
await twonlyDatabase.updateContact(
|
||||
contact.userId, update);
|
||||
}
|
||||
if (context.mounted) {
|
||||
Navigator.popUntil(context, (route) => route.isFirst);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/views/settings/privacy_view_block_users.dart';
|
||||
|
||||
|
|
@ -26,7 +27,7 @@ class _PrivacyViewState extends State<PrivacyView> {
|
|||
ListTile(
|
||||
title: Text(context.lang.settingsPrivacyBlockUsers),
|
||||
subtitle: StreamBuilder(
|
||||
stream: context.db.watchContactsBlocked(),
|
||||
stream: twonlyDatabase.watchContactsBlocked(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data != null) {
|
||||
return Text(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:drift/drift.dart' hide Column;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/initialsavatar.dart';
|
||||
import 'package:twonly/src/database/contacts_db.dart';
|
||||
import 'package:twonly/src/database/database.dart';
|
||||
|
|
@ -20,7 +21,7 @@ class _PrivacyViewBlockUsers extends State<PrivacyViewBlockUsers> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
allUsers = context.db.watchAllContacts();
|
||||
allUsers = twonlyDatabase.watchAllContacts();
|
||||
loadAsync();
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +105,7 @@ class UserList extends StatelessWidget {
|
|||
Future block(BuildContext context, int userId, bool? value) async {
|
||||
if (value != null) {
|
||||
final update = ContactsCompanion(blocked: Value(!value));
|
||||
await context.db.updateContact(userId, update);
|
||||
await twonlyDatabase.updateContact(userId, update);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue