desktop support for notification settings

This commit is contained in:
Dan Ballard 2022-02-04 17:19:02 -05:00
parent c550437aa5
commit b382c3d349
6 changed files with 120 additions and 12 deletions

View File

@ -77,6 +77,7 @@ class CwtchNotifier {
server: null,
archived: false,
lastMessageTime: DateTime.now(), //show at the top of the contact list even if no messages yet
options: data["options"]
));
break;
case "NewServer":
@ -113,7 +114,8 @@ class CwtchNotifier {
status: status,
server: data["GroupServer"],
isGroup: true,
lastMessageTime: DateTime.now()));
lastMessageTime: DateTime.now(),
options: data["options"]));
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(int.parse(data["ConversationID"]), DateTime.now());
}
break;
@ -144,7 +146,7 @@ class CwtchNotifier {
}
break;
case "NewMessageFromPeer":
notificationManager.notify("New Message From Peer!");
var identifier = int.parse(data["ConversationID"]);
var messageID = int.parse(data["Index"]);
var timestamp = DateTime.tryParse(data['TimestampReceived'])!;
@ -154,6 +156,14 @@ class CwtchNotifier {
String? contenthash = data['ContentHash'];
var selectedProfile = appState.selectedProfile == data["ProfileOnion"];
var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
var notification = data["notification"];
if (notification == "SimpleEvent") {
notificationManager.notify(/*TODO l10n */ "New Message");
} else if (notification == "ContactInfo") {
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier);
notificationManager.notify(/*TODO l10n */ "New Message from " + (contact?.nickname ?? senderHandle.toString()));
}
profileCN.getProfile(data["ProfileOnion"])?.newMessage(
identifier,
@ -209,6 +219,7 @@ class CwtchNotifier {
String? contenthash = data['ContentHash'];
var selectedProfile = appState.selectedProfile == data["ProfileOnion"];
var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
var notification = data["notification"];
// Only bother to do anything if we know about the group and the provided index is greater than our current total...
if (currentTotal != null && idx >= currentTotal) {
@ -224,7 +235,12 @@ class CwtchNotifier {
// and `local now`.
profileCN.getProfile(data["ProfileOnion"])?.newMessage(identifier, idx, timestampSent, senderHandle, senderImage, isAuto, data["Data"], contenthash, selectedProfile, selectedConversation);
notificationManager.notify("New Message From Group!");
if (notification == "SimpleEvent") {
notificationManager.notify(/*TODO l10n */ "New Message");
} else if (notification == "ContactInfo") {
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier);
notificationManager.notify(/*TODO l10n */ "New Message from " + (contact?.nickname ?? senderHandle.toString()));
}
appState.notifyProfileUnread();
}
RemoteServerInfoState? server = profileCN.getProfile(data["ProfileOnion"])?.serverList.getServer(contact.server ?? "");

View File

@ -10,6 +10,9 @@ class ContactInfoState extends ChangeNotifier {
final String onion;
late String _nickname;
late bool _notificationsOptIn;
late bool _notificationsOptOut;
late bool _accepted;
late bool _blocked;
late String _status;
@ -44,7 +47,8 @@ class ContactInfoState extends ChangeNotifier {
numUnread = 0,
lastMessageTime,
server,
archived = false}) {
archived = false,
options = const {} }) {
this._nickname = nickname;
this._isGroup = isGroup;
this._accepted = accepted;
@ -58,6 +62,9 @@ class ContactInfoState extends ChangeNotifier {
this._lastMessageTime = lastMessageTime == null ? DateTime.fromMillisecondsSinceEpoch(0) : lastMessageTime;
this._server = server;
this._archived = archived;
print("Contact: $_nickname, Options: $options opt-in: ${options["notification-opt-in"]} opt-out: ${options["notification-opt-out"]} ");
this._notificationsOptIn = (options["notification-opt-in"] ?? "false") == "true";
this._notificationsOptOut = (options["notification-opt-out"] ?? "false") == "true";
this.messageCache = new MessageCache();
keys = Map<String, GlobalKey<MessageRowState>>();
}
@ -195,6 +202,18 @@ class ContactInfoState extends ChangeNotifier {
}
}
bool get notificationsOptIn => _notificationsOptIn;
set notificationsOptIn(bool newVal) {
_notificationsOptIn = newVal;
notifyListeners();
}
bool get notificationsOptOut => _notificationsOptOut;
set notificationsOptOut(bool newVal) {
_notificationsOptOut = newVal;
notifyListeners();
}
GlobalKey<MessageRowState> getMessageKey(int conversation, int message) {
String index = "c: " + conversation.toString() + " m:" + message.toString();
if (keys[index] == null) {

View File

@ -63,7 +63,8 @@ class ProfileInfoState extends ChangeNotifier {
isGroup: contact["isGroup"],
server: contact["groupServer"],
archived: contact["isArchived"] == true,
lastMessageTime: DateTime.fromMillisecondsSinceEpoch(1000 * int.parse(contact["lastMsgTime"])));
lastMessageTime: DateTime.fromMillisecondsSinceEpoch(1000 * int.parse(contact["lastMsgTime"])),
options: contact["options"]);
}));
// dummy set to invoke sort-on-load
@ -183,6 +184,7 @@ class ProfileInfoState extends ChangeNotifier {
isGroup: contact["isGroup"],
server: contact["groupServer"],
lastMessageTime: DateTime.fromMillisecondsSinceEpoch(1000 * int.parse(contact["lastMsgTime"])),
options: contact["options"],
));
}
unreadMessages += int.parse(contact["numUnread"]);

View File

@ -274,11 +274,11 @@ class Settings extends ChangeNotifier {
static NotificationPolicy notificationPolicyFromString(String? np) {
switch (np) {
case "None":
case "NotificationPolicy.None":
return NotificationPolicy.None;
case "OptIn":
case "NotificationPolicy.OptIn":
return NotificationPolicy.OptIn;
case "OptOut":
case "NotificationPolicy.OptOut":
return NotificationPolicy.OptOut;
}
return NotificationPolicy.OptOut;
@ -286,9 +286,9 @@ class Settings extends ChangeNotifier {
static NotificationContent notificationContentFromString(String? nc) {
switch (nc) {
case "SimpleEvent":
case "NotificationContent.SimpleEvent":
return NotificationContent.SimpleEvent;
case "ContactInfo":
case "NotificationContent.ContactInfo":
return NotificationContent.ContactInfo;
}
return NotificationContent.SimpleEvent;

View File

@ -130,7 +130,40 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
SizedBox(
height: 20,
),
// TODO
Visibility(
visible: Provider.of<Settings>(context, listen: false).notificationPolicy == NotificationPolicy.OptOut,
child: SwitchListTile(
title: Text(/*AppLocalizations.of(context)!.savePeerHistory*/"Notifications Opt Out", style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(/*AppLocalizations.of(context)!.savePeerHistoryDescription*/"The system blah blah..."),
secondary: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor),
value: Provider.of<ContactInfoState>(context).notificationsOptOut,
onChanged: (bool optOut) {
Provider.of<ContactInfoState>(context, listen: false).notificationsOptOut = optOut;
var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
const NotificationOptOutKey = "profile.notification-opt-out";
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, NotificationOptOutKey, optOut.toString());
},
activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
)),
Visibility(
visible: Provider.of<Settings>(context, listen: false).notificationPolicy == NotificationPolicy.OptIn,
child: SwitchListTile(
title: Text(/*AppLocalizations.of(context)!.savePeerHistory*/"Notifications Opt In", style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(/*AppLocalizations.of(context)!.savePeerHistoryDescription*/"The system blah blah..."),
secondary: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor),
value: Provider.of<ContactInfoState>(context).notificationsOptIn,
onChanged: (bool optIn) {
Provider.of<ContactInfoState>(context, listen: false).notificationsOptIn = optIn;
var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
const NotificationOptInKey = "profile.notification-opt-in";
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, NotificationOptInKey, optIn.toString());
},
activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
))
]),
Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, children: [

View File

@ -39,9 +39,13 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
@override
Widget build(BuildContext context) {
var handle = Provider.of<ContactInfoState>(context).nickname;
if (handle.isEmpty) {
handle = Provider.of<ContactInfoState>(context).onion;
}
return Scaffold(
appBar: AppBar(
title: Text(Provider.of<ContactInfoState>(context).onion),
title: Text(handle + " " + AppLocalizations.of(context)!.conversationSettings),
),
body: _buildSettingsList(),
);
@ -197,6 +201,40 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
child: Text(value),
);
}).toList())),
Visibility(
visible: Provider.of<Settings>(context, listen: false).notificationPolicy == NotificationPolicy.OptOut,
child: SwitchListTile(
title: Text(/*AppLocalizations.of(context)!.savePeerHistory*/"Notifications Opt Out", style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(/*AppLocalizations.of(context)!.savePeerHistoryDescription*/"The system blah blah..."),
secondary: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor),
value: Provider.of<ContactInfoState>(context).notificationsOptOut,
onChanged: (bool optOut) {
Provider.of<ContactInfoState>(context, listen: false).notificationsOptOut = optOut;
var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
const NotificationOptOutKey = "profile.notification-opt-out";
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, NotificationOptOutKey, optOut.toString());
},
activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
)),
Visibility(
visible: Provider.of<Settings>(context, listen: false).notificationPolicy == NotificationPolicy.OptIn,
child: SwitchListTile(
title: Text(/*AppLocalizations.of(context)!.savePeerHistory*/"Notifications Opt In", style: TextStyle(color: settings.current().mainTextColor)),
subtitle: Text(/*AppLocalizations.of(context)!.savePeerHistoryDescription*/"The system blah blah..."),
secondary: Icon(CwtchIcons.chat_bubble_empty_24px, color: settings.current().mainTextColor),
value: Provider.of<ContactInfoState>(context).notificationsOptIn,
onChanged: (bool optIn) {
Provider.of<ContactInfoState>(context, listen: false).notificationsOptIn = optIn;
var profileOnion = Provider.of<ContactInfoState>(context, listen: false).profileOnion;
var identifier = Provider.of<ContactInfoState>(context, listen: false).identifier;
const NotificationOptInKey = "profile.notification-opt-in";
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profileOnion, identifier, NotificationOptInKey, optIn.toString());
},
activeTrackColor: settings.theme.defaultButtonColor,
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
))
]),
Column(mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [
SizedBox(