store last seen time in lcg and handle unread counts #411
|
@ -1 +1 @@
|
||||||
2022-03-23-19-06-v1.6.0-13-g1acae32
|
2022-04-04-17-46-v1.6.0-15-g97defdf
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
2022-03-23-23-06-v1.6.0-13-g1acae32
|
2022-04-04-21-46-v1.6.0-15-g97defdf
|
|
@ -2,6 +2,8 @@
|
||||||
// Details: https://docs.openprivacy.ca/cwtch-security-handbook/profile_encryption_and_storage.html
|
// Details: https://docs.openprivacy.ca/cwtch-security-handbook/profile_encryption_and_storage.html
|
||||||
const DefaultPassword = "be gay do crime";
|
const DefaultPassword = "be gay do crime";
|
||||||
|
|
||||||
|
const LastMessageSeenTimeKey = "profile.lastMessageSeenTime";
|
||||||
|
|
||||||
abstract class Cwtch {
|
abstract class Cwtch {
|
||||||
// ignore: non_constant_identifier_names
|
// ignore: non_constant_identifier_names
|
||||||
Future<void> Start();
|
Future<void> Start();
|
||||||
|
|
|
@ -18,6 +18,8 @@ import '../config.dart';
|
||||||
import '../errorHandler.dart';
|
import '../errorHandler.dart';
|
||||||
import '../settings.dart';
|
import '../settings.dart';
|
||||||
|
|
||||||
|
typedef SeenMessageCallback = Function(String, int, DateTime);
|
||||||
|
|
||||||
// Class that handles libcwtch-go events (received either via ffi with an isolate or gomobile over a method channel from kotlin)
|
// Class that handles libcwtch-go events (received either via ffi with an isolate or gomobile over a method channel from kotlin)
|
||||||
// Takes Notifiers and triggers them on appropriate events
|
// Takes Notifiers and triggers them on appropriate events
|
||||||
class CwtchNotifier {
|
class CwtchNotifier {
|
||||||
|
@ -32,6 +34,8 @@ class CwtchNotifier {
|
||||||
String? notificationSimple;
|
String? notificationSimple;
|
||||||
String? notificationConversationInfo;
|
String? notificationConversationInfo;
|
||||||
|
|
||||||
|
SeenMessageCallback? seenMessageCallback;
|
||||||
|
|
||||||
CwtchNotifier(
|
CwtchNotifier(
|
||||||
ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN, NotificationsManager notificationManagerP, AppState appStateCN, ServerListState serverListStateCN) {
|
ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN, NotificationsManager notificationManagerP, AppState appStateCN, ServerListState serverListStateCN) {
|
||||||
profileCN = pcn;
|
profileCN = pcn;
|
||||||
|
@ -48,6 +52,10 @@ class CwtchNotifier {
|
||||||
this.notificationConversationInfo = notificationConversationInfo;
|
this.notificationConversationInfo = notificationConversationInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setMessageSeenCallback(SeenMessageCallback callback) {
|
||||||
|
seenMessageCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
void handleMessage(String type, dynamic data) {
|
void handleMessage(String type, dynamic data) {
|
||||||
//EnvironmentConfig.debugLog("NewEvent $type $data");
|
//EnvironmentConfig.debugLog("NewEvent $type $data");
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -164,6 +172,10 @@ class CwtchNotifier {
|
||||||
var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
|
var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
|
||||||
var notification = data["notification"];
|
var notification = data["notification"];
|
||||||
|
|
||||||
|
if (selectedConversation && seenMessageCallback != null) {
|
||||||
|
seenMessageCallback!(data["ProfileOnion"]!, identifier, DateTime.now().toUtc());
|
||||||
|
}
|
||||||
|
|
||||||
if (notification == "SimpleEvent") {
|
if (notification == "SimpleEvent") {
|
||||||
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
|
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
|
||||||
} else if (notification == "ContactInfo") {
|
} else if (notification == "ContactInfo") {
|
||||||
|
@ -229,6 +241,9 @@ class CwtchNotifier {
|
||||||
// and ensure that malicious contacts in groups can only set this timestamp to a value within the range of `last seen message time`
|
// and ensure that malicious contacts in groups can only set this timestamp to a value within the range of `last seen message time`
|
||||||
// and `local now`.
|
// and `local now`.
|
||||||
profileCN.getProfile(data["ProfileOnion"])?.newMessage(identifier, idx, timestampSent, senderHandle, senderImage, isAuto, data["Data"], contenthash, selectedProfile, selectedConversation);
|
profileCN.getProfile(data["ProfileOnion"])?.newMessage(identifier, idx, timestampSent, senderHandle, senderImage, isAuto, data["Data"], contenthash, selectedProfile, selectedConversation);
|
||||||
|
if (selectedConversation && seenMessageCallback != null) {
|
||||||
|
seenMessageCallback!(data["ProfileOnion"]!, identifier, DateTime.now().toUtc());
|
||||||
|
}
|
||||||
|
|
||||||
if (notification == "SimpleEvent") {
|
if (notification == "SimpleEvent") {
|
||||||
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
|
notificationManager.notify(notificationSimple ?? "New Message", "", 0);
|
||||||
|
|
|
@ -133,6 +133,7 @@ class CwtchFfi implements Cwtch {
|
||||||
}
|
}
|
||||||
library = DynamicLibrary.open(libraryPath);
|
library = DynamicLibrary.open(libraryPath);
|
||||||
cwtchNotifier = _cwtchNotifier;
|
cwtchNotifier = _cwtchNotifier;
|
||||||
|
cwtchNotifier.setMessageSeenCallback((String profile, int conversation, DateTime time) => {this.SetConversationAttribute(profile, conversation, LastMessageSeenTimeKey, time.toIso8601String())});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: non_constant_identifier_names
|
// ignore: non_constant_identifier_names
|
||||||
|
|
|
@ -35,6 +35,7 @@ class CwtchGomobile implements Cwtch {
|
||||||
CwtchGomobile(CwtchNotifier _cwtchNotifier) {
|
CwtchGomobile(CwtchNotifier _cwtchNotifier) {
|
||||||
print("gomobile.dart: CwtchGomobile()");
|
print("gomobile.dart: CwtchGomobile()");
|
||||||
cwtchNotifier = _cwtchNotifier;
|
cwtchNotifier = _cwtchNotifier;
|
||||||
|
cwtchNotifier.setMessageSeenCallback((String profile, int conversation, DateTime time) => {this.SetConversationAttribute(profile, conversation, LastMessageSeenTimeKey, time.toIso8601String())});
|
||||||
androidHomeDirectory = getApplicationDocumentsDirectory();
|
androidHomeDirectory = getApplicationDocumentsDirectory();
|
||||||
androidLibraryDir = appInfoPlatform.invokeMethod('getNativeLibDir');
|
androidLibraryDir = appInfoPlatform.invokeMethod('getNativeLibDir');
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
|
|
||||||
List<dynamic> contacts = jsonDecode(contactsJson);
|
List<dynamic> contacts = jsonDecode(contactsJson);
|
||||||
this._contacts.addAll(contacts.map((contact) {
|
this._contacts.addAll(contacts.map((contact) {
|
||||||
|
this._unreadMessages += contact["numUnread"] as int;
|
||||||
return ContactInfoState(this.onion, contact["identifier"], contact["onion"],
|
return ContactInfoState(this.onion, contact["identifier"], contact["onion"],
|
||||||
nickname: contact["name"],
|
nickname: contact["name"],
|
||||||
status: contact["status"],
|
status: contact["status"],
|
||||||
|
@ -164,12 +165,14 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
this._nickname = name;
|
this._nickname = name;
|
||||||
this._imagePath = picture;
|
this._imagePath = picture;
|
||||||
this._online = online;
|
this._online = online;
|
||||||
|
this._unreadMessages = 0;
|
||||||
this.replaceServers(serverJson);
|
this.replaceServers(serverJson);
|
||||||
|
|
||||||
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
|
if (contactsJson != null && contactsJson != "" && contactsJson != "null") {
|
||||||
List<dynamic> contacts = jsonDecode(contactsJson);
|
List<dynamic> contacts = jsonDecode(contactsJson);
|
||||||
contacts.forEach((contact) {
|
contacts.forEach((contact) {
|
||||||
var profileContact = this._contacts.getContact(contact["identifier"]);
|
var profileContact = this._contacts.getContact(contact["identifier"]);
|
||||||
|
this._unreadMessages += contact["numUnread"] as int;
|
||||||
if (profileContact != null) {
|
if (profileContact != null) {
|
||||||
profileContact.status = contact["status"];
|
profileContact.status = contact["status"];
|
||||||
profileContact.totalMessages = contact["numMessages"]; // Todo: trigger cache update (bulk upload)
|
profileContact.totalMessages = contact["numMessages"]; // Todo: trigger cache update (bulk upload)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cwtch/cwtch/cwtch.dart';
|
||||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||||
import 'package:cwtch/models/appstate.dart';
|
import 'package:cwtch/models/appstate.dart';
|
||||||
import 'package:cwtch/models/contact.dart';
|
import 'package:cwtch/models/contact.dart';
|
||||||
|
@ -38,6 +39,8 @@ void selectConversation(BuildContext context, int handle) {
|
||||||
// if in singlepane mode, push to the stack
|
// if in singlepane mode, push to the stack
|
||||||
var isLandscape = Provider.of<AppState>(context, listen: false).isLandscape(context);
|
var isLandscape = Provider.of<AppState>(context, listen: false).isLandscape(context);
|
||||||
if (Provider.of<Settings>(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle);
|
if (Provider.of<Settings>(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle);
|
||||||
|
// Set last message seen time in backend
|
||||||
|
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(Provider.of<ProfileInfoState>(context, listen: false).onion, handle, LastMessageSeenTimeKey, DateTime.now().toUtc().toIso8601String());
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushMessageView(BuildContext context, int handle) {
|
void _pushMessageView(BuildContext context, int handle) {
|
||||||
|
|
Loading…
Reference in New Issue