From e42c84215d580d3ba67c171b601e1caef8e74249 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Tue, 8 Nov 2022 11:24:44 -0800
Subject: [PATCH] Add TrackServicesWithIdentity to fix offline issue with
 notifications

---
 bindings/follow.go        | 33 ++++++++++++++++++++---
 bindings/notifications.go | 57 ++++++++++++++++++---------------------
 2 files changed, 55 insertions(+), 35 deletions(-)

diff --git a/bindings/follow.go b/bindings/follow.go
index 64d1dc0fe..f739033b9 100644
--- a/bindings/follow.go
+++ b/bindings/follow.go
@@ -297,13 +297,38 @@ type TrackServicesCallback interface {
 	Callback(marshalData []byte, err error)
 }
 
+// TrackServicesWithIdentity will return via a callback the list of services the
+// backend keeps track of for the provided identity. This may be passed into
+// other bindings call which may need context on the available services for this
+// single identity. This will only return services for the given identity.
+//
+// Parameters:
+//   - e2eID - e2e object ID in the tracker.
+//   - cb - A TrackServicesCallback, which will be passed the marshalled
+//     message.ServiceList.
+func (c *Cmix) TrackServicesWithIdentity(e2eId int,
+	cb TrackServicesCallback) error {
+	// Retrieve the user from the tracker
+	user, err := e2eTrackerSingleton.get(e2eId)
+	if err != nil {
+		return err
+	}
+
+	receptionId := user.api.GetReceptionIdentity().ID
+	c.api.GetCmix().TrackServices(func(list message.ServiceList) {
+		res := make(message.ServiceList)
+		res[*receptionId] = list[*receptionId]
+		cb.Callback(json.Marshal(res))
+	})
+
+	return nil
+}
+
 // TrackServices will return via a callback the list of services the
 // backend keeps track of, which is formally referred to as a
 // [message.ServiceList]. This may be passed into other bindings call which
-// may need context on the available services for this client. This is the equivalent
-// of GetPreimages in APIv0. The callback will be called every time a new service
-// is added or an existing service is deleted. This serves as a way for
-// the caller to have the most up-to-date list of existing services.
+// may need context on the available services for this client. This will
+// provide services for all identities that the client tracks.
 //
 // Parameters:
 //   - cb - A TrackServicesCallback, which will be passed the marshalled
diff --git a/bindings/notifications.go b/bindings/notifications.go
index a7b67a69d..79f9cc511 100644
--- a/bindings/notifications.go
+++ b/bindings/notifications.go
@@ -82,34 +82,27 @@ type NotificationReport struct {
 // NotificationReports.
 //
 // Parameters:
-//   - e2eID - e2e object ID in the tracker
 //   - notificationCSV - the notification data received from the
 //     notifications' server.
 //   - marshalledServices - the JSON-marshalled list of services the backend
-//     keeps track of. Refer to Cmix.TrackServices for information about this. This
-//     is the equivalent to preimages in APIv0.
+//     keeps track of. Refer to Cmix.TrackServices or
+//     Cmix.TrackServicesWithIdentity for information about this.
 //
 // Returns:
 //   - []byte - A JSON marshalled NotificationReports. Some NotificationReport's
 //     within in this structure may have their NotificationReport.ForMe
 //     set to false. These may be ignored.
-func GetNotificationsReport(e2eId int, notificationCSV string,
+func GetNotificationsReport(notificationCSV string,
 	marshalledServices []byte) ([]byte, error) {
-	// Retrieve user
-	user, err := e2eTrackerSingleton.get(e2eId)
-	if err != nil {
-		return nil, err
-	}
 
+	// If services are retrieved using TrackServicesWithIdentity, this
+	// should return a single list.
 	serviceList := message.ServiceList{}
-	err = json.Unmarshal(marshalledServices, &serviceList)
+	err := json.Unmarshal(marshalledServices, &serviceList)
 	if err != nil {
 		return nil, err
 	}
 
-	// Retrieve the services for this user
-	services := serviceList[*user.api.GetReceptionIdentity().ID]
-
 	// Decode notifications' server data
 	notificationList, err := notifications.DecodeNotificationsCSV(notificationCSV)
 	if err != nil {
@@ -120,24 +113,26 @@ func GetNotificationsReport(e2eId int, notificationCSV string,
 	reportList := make([]*NotificationReport, len(notificationList))
 
 	// Iterate over data provided by server
-	for i := range notificationList {
-		notifData := notificationList[i]
-
-		// Iterate over all services
-		for j := range services {
-			// Pull data from services and from notification data
-			service := services[j]
-			messageHash := notifData.MessageHash
-			hash := service.HashFromMessageHash(notifData.MessageHash)
-
-			// Check if this notification data is recognized by
-			// this service, ie "ForMe"
-			if service.ForMeFromMessageHash(messageHash, hash) {
-				// Fill report list with service data
-				reportList[i] = &NotificationReport{
-					ForMe:  true,
-					Type:   service.Tag,
-					Source: service.Identifier,
+	for _, services := range serviceList {
+		for i := range notificationList {
+			notifData := notificationList[i]
+
+			// Iterate over all services
+			for j := range services {
+				// Pull data from services and from notification data
+				service := services[j]
+				messageHash := notifData.MessageHash
+				hash := service.HashFromMessageHash(notifData.MessageHash)
+
+				// Check if this notification data is recognized by
+				// this service, ie "ForMe"
+				if service.ForMeFromMessageHash(messageHash, hash) {
+					// Fill report list with service data
+					reportList[i] = &NotificationReport{
+						ForMe:  true,
+						Type:   service.Tag,
+						Source: service.Identifier,
+					}
 				}
 			}
 		}
-- 
GitLab