profile level unread notifications and in profile other profile unread notifications
This commit is contained in:
parent
ca03ddbc53
commit
a82ade8663
|
@ -65,8 +65,8 @@ android {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
// TODO: Add your own signing config for the release build.
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
// signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
signingConfig signingConfigs.release
|
// signingConfig signingConfigs.release
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:cwtch/models/profileservers.dart';
|
||||||
import 'package:cwtch/models/remoteserver.dart';
|
import 'package:cwtch/models/remoteserver.dart';
|
||||||
import 'package:cwtch/models/servers.dart';
|
import 'package:cwtch/models/servers.dart';
|
||||||
import 'package:cwtch/notification_manager.dart';
|
import 'package:cwtch/notification_manager.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'package:cwtch/torstatus.dart';
|
import 'package:cwtch/torstatus.dart';
|
||||||
|
@ -145,9 +146,10 @@ class CwtchNotifier {
|
||||||
var senderImage = data['Picture'];
|
var senderImage = data['Picture'];
|
||||||
var isAuto = data['Auto'] == "true";
|
var isAuto = data['Auto'] == "true";
|
||||||
String? contenthash = data['ContentHash'];
|
String? contenthash = data['ContentHash'];
|
||||||
var selectedConversation = appState.selectedProfile == data["ProfileOnion"] && appState.selectedConversation == identifier;
|
var selectedProfile = appState.selectedProfile == data["ProfileOnion"];
|
||||||
|
var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
|
||||||
|
|
||||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.newMessage(
|
profileCN.getProfile(data["ProfileOnion"])?.newMessage(
|
||||||
identifier,
|
identifier,
|
||||||
messageID,
|
messageID,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
@ -156,9 +158,10 @@ class CwtchNotifier {
|
||||||
isAuto,
|
isAuto,
|
||||||
data["Data"],
|
data["Data"],
|
||||||
contenthash,
|
contenthash,
|
||||||
|
selectedProfile,
|
||||||
selectedConversation,
|
selectedConversation,
|
||||||
);
|
);
|
||||||
|
appState.notifyProfileUnread();
|
||||||
break;
|
break;
|
||||||
case "PeerAcknowledgement":
|
case "PeerAcknowledgement":
|
||||||
// We don't use these anymore, IndexedAcknowledgement is more suited to the UI front end...
|
// We don't use these anymore, IndexedAcknowledgement is more suited to the UI front end...
|
||||||
|
@ -198,7 +201,8 @@ class CwtchNotifier {
|
||||||
var currentTotal = contact!.totalMessages;
|
var currentTotal = contact!.totalMessages;
|
||||||
var isAuto = data['Auto'] == "true";
|
var isAuto = data['Auto'] == "true";
|
||||||
String? contenthash = data['ContentHash'];
|
String? contenthash = data['ContentHash'];
|
||||||
var selectedConversation = appState.selectedProfile == data["ProfileOnion"] && appState.selectedConversation == identifier;
|
var selectedProfile = appState.selectedProfile == data["ProfileOnion"];
|
||||||
|
var selectedConversation = selectedProfile && appState.selectedConversation == identifier;
|
||||||
|
|
||||||
// Only bother to do anything if we know about the group and the provided index is greater than our current total...
|
// 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) {
|
if (currentTotal != null && idx >= currentTotal) {
|
||||||
|
@ -212,9 +216,10 @@ class CwtchNotifier {
|
||||||
// For now we perform some minimal checks on the sent timestamp to use to provide a useful ordering for honest contacts
|
// For now we perform some minimal checks on the sent timestamp to use to provide a useful ordering for honest contacts
|
||||||
// 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"])?.contactList.newMessage(identifier, idx, timestampSent, senderHandle, senderImage, isAuto, data["Data"], contenthash, selectedConversation);
|
profileCN.getProfile(data["ProfileOnion"])?.newMessage(identifier, idx, timestampSent, senderHandle, senderImage, isAuto, data["Data"], contenthash, selectedProfile, selectedConversation);
|
||||||
|
|
||||||
notificationManager.notify("New Message From Group!");
|
notificationManager.notify("New Message From Group!");
|
||||||
|
appState.notifyProfileUnread();
|
||||||
}
|
}
|
||||||
RemoteServerInfoState? server = profileCN.getProfile(data["ProfileOnion"])?.serverList.getServer(contact.server);
|
RemoteServerInfoState? server = profileCN.getProfile(data["ProfileOnion"])?.serverList.getServer(contact.server);
|
||||||
server?.updateSyncProgressFor(timestampSent);
|
server?.updateSyncProgressFor(timestampSent);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
enum ModalState { none, storageMigration }
|
enum ModalState { none, storageMigration }
|
||||||
|
@ -16,6 +18,13 @@ class AppState extends ChangeNotifier {
|
||||||
bool _disableFilePicker = false;
|
bool _disableFilePicker = false;
|
||||||
bool _focus = true;
|
bool _focus = true;
|
||||||
|
|
||||||
|
StreamController<bool> _profilesUnreadNotifyControler = StreamController<bool>();
|
||||||
|
late Stream<bool> profilesUnreadNotify;
|
||||||
|
|
||||||
|
AppState() {
|
||||||
|
profilesUnreadNotify = _profilesUnreadNotifyControler.stream.asBroadcastStream();
|
||||||
|
}
|
||||||
|
|
||||||
void SetCwtchInit() {
|
void SetCwtchInit() {
|
||||||
cwtchInit = true;
|
cwtchInit = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -82,4 +91,12 @@ class AppState extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isLandscape(BuildContext c) => MediaQuery.of(c).size.width > MediaQuery.of(c).size.height;
|
bool isLandscape(BuildContext c) => MediaQuery.of(c).size.width > MediaQuery.of(c).size.height;
|
||||||
|
|
||||||
|
void notifyProfileUnread() {
|
||||||
|
_profilesUnreadNotifyControler.add(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<bool> getUnreadProfileNotifyStream() {
|
||||||
|
return profilesUnreadNotify;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,24 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
this._contacts.resort();
|
this._contacts.resort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void newMessage(int identifier, int messageID, DateTime timestamp, String senderHandle, String senderImage, bool isAuto, String data, String? contenthash, bool selectedProfile, bool selectedConversation) {
|
||||||
|
if (!selectedProfile) {
|
||||||
|
unreadMessages++;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
contactList.newMessage(
|
||||||
|
identifier,
|
||||||
|
messageID,
|
||||||
|
timestamp,
|
||||||
|
senderHandle,
|
||||||
|
senderImage,
|
||||||
|
isAuto,
|
||||||
|
data,
|
||||||
|
contenthash,
|
||||||
|
selectedConversation);
|
||||||
|
}
|
||||||
|
|
||||||
void downloadInit(String fileKey, int numChunks) {
|
void downloadInit(String fileKey, int numChunks) {
|
||||||
this._downloads[fileKey] = FileDownloadProgress(numChunks, DateTime.now());
|
this._downloads[fileKey] = FileDownloadProgress(numChunks, DateTime.now());
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
|
@ -27,4 +27,8 @@ class ProfileListState extends ChangeNotifier {
|
||||||
_profiles.removeWhere((element) => element.onion == onion);
|
_profiles.removeWhere((element) => element.onion == onion);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generateUnreadCount(String selectedProfile) => _profiles.where( (p) => p.onion != selectedProfile ).fold(0, (i, p) => i + p.unreadMessages);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,8 @@ class CwtchDark extends OpaqueThemeType {
|
||||||
get portraitBlockedTextColor => lightGrey;
|
get portraitBlockedTextColor => lightGrey;
|
||||||
get portraitContactBadgeColor => hotPink;
|
get portraitContactBadgeColor => hotPink;
|
||||||
get portraitContactBadgeTextColor => whiteishPurple;
|
get portraitContactBadgeTextColor => whiteishPurple;
|
||||||
get portraitProfileBadgeColor => mauvePurple;
|
get portraitProfileBadgeColor => hotPink;
|
||||||
get portraitProfileBadgeTextColor => darkGreyPurple;
|
get portraitProfileBadgeTextColor => whiteishPurple;
|
||||||
get dropShadowColor => mauvePurple;
|
get dropShadowColor => mauvePurple;
|
||||||
get toolbarIconColor => settings; //whiteishPurple;
|
get toolbarIconColor => settings; //whiteishPurple;
|
||||||
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
|
get messageFromMeBackgroundColor => userBubble; // mauvePurple;
|
||||||
|
@ -112,7 +112,7 @@ class CwtchLight extends OpaqueThemeType {
|
||||||
get portraitBlockedTextColor => softGrey;
|
get portraitBlockedTextColor => softGrey;
|
||||||
get portraitContactBadgeColor => accent;
|
get portraitContactBadgeColor => accent;
|
||||||
get portraitContactBadgeTextColor => whitePurple;
|
get portraitContactBadgeTextColor => whitePurple;
|
||||||
get portraitProfileBadgeColor => brightPurple;
|
get portraitProfileBadgeColor => accent;
|
||||||
get portraitProfileBadgeTextColor => whitePurple;
|
get portraitProfileBadgeTextColor => whitePurple;
|
||||||
get dropShadowColor => purple;
|
get dropShadowColor => purple;
|
||||||
get toolbarIconColor => settings; //darkPurple;
|
get toolbarIconColor => settings; //darkPurple;
|
||||||
|
|
|
@ -76,6 +76,30 @@ class _ContactsViewState extends State<ContactsView> {
|
||||||
endDrawerEnableOpenDragGesture: false,
|
endDrawerEnableOpenDragGesture: false,
|
||||||
drawerEnableOpenDragGesture: false,
|
drawerEnableOpenDragGesture: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
leading: Row(children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.arrow_back),
|
||||||
|
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||||
|
onPressed: () {
|
||||||
|
Provider.of<AppState>(context, listen: false).selectedProfile = "";
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
StreamBuilder<bool>(
|
||||||
|
stream: Provider.of<AppState>(context).getUnreadProfileNotifyStream(),
|
||||||
|
builder: (BuildContext context, AsyncSnapshot<bool> unreadCountSnapshot) {
|
||||||
|
int unreadCount = Provider.of<ProfileListState>(context).generateUnreadCount(Provider.of<AppState>(context).selectedProfile ?? "") ;
|
||||||
|
|
||||||
|
return Visibility(
|
||||||
|
visible: unreadCount > 0,
|
||||||
|
child: CircleAvatar(
|
||||||
|
radius: 10.0,
|
||||||
|
backgroundColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor,
|
||||||
|
child: Text(unreadCount > 99 ? "99+" : unreadCount.toString(), style: TextStyle(color: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor, fontSize: 8.0)),
|
||||||
|
));
|
||||||
|
}),
|
||||||
|
]),
|
||||||
title: RepaintBoundary(
|
title: RepaintBoundary(
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
ProfileImage(
|
ProfileImage(
|
||||||
|
|
|
@ -33,7 +33,7 @@ class _ProfileRowState extends State<ProfileRow> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(6.0), //border size
|
padding: const EdgeInsets.all(6.0), //border size
|
||||||
child: ProfileImage(
|
child: ProfileImage(
|
||||||
badgeCount: 0,
|
badgeCount: profile.unreadMessages,
|
||||||
badgeColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor,
|
badgeColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor,
|
||||||
badgeTextColor: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor,
|
badgeTextColor: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor,
|
||||||
diameter: 64.0,
|
diameter: 64.0,
|
||||||
|
@ -83,6 +83,7 @@ class _ProfileRowState extends State<ProfileRow> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushContactList(ProfileInfoState profile, bool isLandscape) {
|
void _pushContactList(ProfileInfoState profile, bool isLandscape) {
|
||||||
|
Provider.of<ProfileInfoState>(context, listen: false).unreadMessages = 0;
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute<void>(
|
MaterialPageRoute<void>(
|
||||||
settings: RouteSettings(name: "conversations"),
|
settings: RouteSettings(name: "conversations"),
|
||||||
|
|
Loading…
Reference in New Issue