Revert "Revert "Expand Local Notifications to support multiple Notification types (#2100)""
This reverts commit 5887337b88
.
This commit is contained in:
parent
8d9b85f103
commit
84db2fb472
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
"github.com/status-im/status-go/profiling"
|
"github.com/status-im/status-go/profiling"
|
||||||
"github.com/status-im/status-go/protocol"
|
"github.com/status-im/status-go/protocol"
|
||||||
|
localnotifications "github.com/status-im/status-go/services/local-notifications"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -399,11 +400,13 @@ func retrieveMessagesLoop(messenger *protocol.Messenger, tick time.Duration, can
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
_, err := messenger.RetrieveAll()
|
mr, err := messenger.RetrieveAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to retrieve raw messages", "err", err)
|
logger.Error("failed to retrieve raw messages", "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
localnotifications.SendMessageNotifications(mr.Notifications)
|
||||||
case <-cancel:
|
case <-cancel:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import "github.com/status-im/status-go/protocol/common"
|
||||||
|
|
||||||
|
type MessageNotificationBody struct {
|
||||||
|
Message *common.Message
|
||||||
|
Contact *Contact
|
||||||
|
Chat *Chat
|
||||||
|
}
|
|
@ -483,6 +483,16 @@ func (m *MessageHandler) HandleChatMessage(state *ReceivedMessageState) error {
|
||||||
// Add to response
|
// Add to response
|
||||||
state.Response.Messages = append(state.Response.Messages, receivedMessage)
|
state.Response.Messages = append(state.Response.Messages, receivedMessage)
|
||||||
|
|
||||||
|
// Create notification body to be eventually passed to `localnotifications.SendMessageNotifications()`
|
||||||
|
state.Response.Notifications = append(
|
||||||
|
state.Response.Notifications,
|
||||||
|
MessageNotificationBody{
|
||||||
|
Message: receivedMessage,
|
||||||
|
Contact: contact,
|
||||||
|
Chat: chat,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,13 @@ type MessengerResponse struct {
|
||||||
Mailservers []mailservers.Mailserver `json:"mailservers,omitempty"`
|
Mailservers []mailservers.Mailserver `json:"mailservers,omitempty"`
|
||||||
MailserverTopics []mailservers.MailserverTopic `json:"mailserverTopics,omitempty"`
|
MailserverTopics []mailservers.MailserverTopic `json:"mailserverTopics,omitempty"`
|
||||||
MailserverRanges []mailservers.ChatRequestRange `json:"mailserverRanges,omitempty"`
|
MailserverRanges []mailservers.ChatRequestRange `json:"mailserverRanges,omitempty"`
|
||||||
|
|
||||||
|
// Notifications a list of MessageNotificationBody derived from received messages that are useful to notify the user about
|
||||||
|
Notifications []MessageNotificationBody `json:"notifications"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessengerResponse) IsEmpty() bool {
|
func (m *MessengerResponse) IsEmpty() bool {
|
||||||
return len(m.Chats)+len(m.Messages)+len(m.Contacts)+len(m.Installations)+len(m.Invitations)+len(m.EmojiReactions)+len(m.Communities)+len(m.CommunityChanges)+len(m.Filters)+len(m.RemovedFilters)+len(m.RemovedChats)+len(m.MailserverTopics)+len(m.Mailservers)+len(m.MailserverRanges) == 0
|
return len(m.Chats)+len(m.Messages)+len(m.Contacts)+len(m.Installations)+len(m.Invitations)+len(m.EmojiReactions)+len(m.Communities)+len(m.CommunityChanges)+len(m.Filters)+len(m.RemovedFilters)+len(m.RemovedChats)+len(m.Notifications)+len(m.MailserverTopics)+len(m.Mailservers)+len(m.MailserverRanges) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge takes another response and appends the new Chats & new Messages and replaces
|
// Merge takes another response and appends the new Chats & new Messages and replaces
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/status-im/status-go/protocol/pushnotificationserver"
|
"github.com/status-im/status-go/protocol/pushnotificationserver"
|
||||||
"github.com/status-im/status-go/protocol/transport"
|
"github.com/status-im/status-go/protocol/transport"
|
||||||
"github.com/status-im/status-go/services/ext/mailservers"
|
"github.com/status-im/status-go/services/ext/mailservers"
|
||||||
|
localnotifications "github.com/status-im/status-go/services/local-notifications"
|
||||||
mailserversDB "github.com/status-im/status-go/services/mailservers"
|
mailserversDB "github.com/status-im/status-go/services/mailservers"
|
||||||
"github.com/status-im/status-go/services/wallet"
|
"github.com/status-im/status-go/services/wallet"
|
||||||
"github.com/status-im/status-go/signal"
|
"github.com/status-im/status-go/signal"
|
||||||
|
@ -197,6 +198,7 @@ func (s *Service) retrieveMessagesLoop(tick time.Duration, cancel <-chan struct{
|
||||||
}
|
}
|
||||||
if !response.IsEmpty() {
|
if !response.IsEmpty() {
|
||||||
PublisherSignalHandler{}.NewMessages(response)
|
PublisherSignalHandler{}.NewMessages(response)
|
||||||
|
localnotifications.SendMessageNotifications(response.Notifications)
|
||||||
}
|
}
|
||||||
case <-cancel:
|
case <-cancel:
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,6 +2,8 @@ package localnotifications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
@ -13,6 +15,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
|
"github.com/status-im/status-go/protocol"
|
||||||
"github.com/status-im/status-go/services/wallet"
|
"github.com/status-im/status-go/services/wallet"
|
||||||
"github.com/status-im/status-go/signal"
|
"github.com/status-im/status-go/signal"
|
||||||
)
|
)
|
||||||
|
@ -21,12 +24,24 @@ type PushCategory string
|
||||||
|
|
||||||
type transactionState string
|
type transactionState string
|
||||||
|
|
||||||
const walletDeeplinkPrefix = "status-im://wallet/"
|
type NotificationType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
walletDeeplinkPrefix = "status-im://wallet/"
|
||||||
|
|
||||||
failed transactionState = "failed"
|
failed transactionState = "failed"
|
||||||
inbound transactionState = "inbound"
|
inbound transactionState = "inbound"
|
||||||
outbound transactionState = "outbound"
|
outbound transactionState = "outbound"
|
||||||
|
|
||||||
|
CategoryTransaction PushCategory = "transaction"
|
||||||
|
CategoryMessage PushCategory = "newMessage"
|
||||||
|
|
||||||
|
TypeTransaction NotificationType = "transaction"
|
||||||
|
TypeMessage NotificationType = "message"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
marshalTypeMismatchErr = "notification type mismatch, expected '%s', Body could not be marshalled into this type"
|
||||||
)
|
)
|
||||||
|
|
||||||
type notificationBody struct {
|
type notificationBody struct {
|
||||||
|
@ -42,9 +57,23 @@ type notificationBody struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
|
ID common.Hash `json:"id"`
|
||||||
|
Platform float32 `json:"platform,omitempty"`
|
||||||
|
Body interface{}
|
||||||
|
BodyType NotificationType `json:"bodyType"`
|
||||||
|
Category PushCategory `json:"category,omitempty"`
|
||||||
|
Deeplink string `json:"deepLink,omitempty"`
|
||||||
|
Image string `json:"imageUrl,omitempty"`
|
||||||
|
IsScheduled bool `json:"isScheduled,omitempty"`
|
||||||
|
ScheduledTime string `json:"scheduleTime,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// notificationAlias is an interim struct used for json un/marshalling
|
||||||
|
type notificationAlias struct {
|
||||||
ID common.Hash `json:"id"`
|
ID common.Hash `json:"id"`
|
||||||
Platform float32 `json:"platform,omitempty"`
|
Platform float32 `json:"platform,omitempty"`
|
||||||
Body notificationBody `json:"body"`
|
Body json.RawMessage `json:"body"`
|
||||||
|
BodyType NotificationType `json:"bodyType"`
|
||||||
Category PushCategory `json:"category,omitempty"`
|
Category PushCategory `json:"category,omitempty"`
|
||||||
Deeplink string `json:"deepLink,omitempty"`
|
Deeplink string `json:"deepLink,omitempty"`
|
||||||
Image string `json:"imageUrl,omitempty"`
|
Image string `json:"imageUrl,omitempty"`
|
||||||
|
@ -102,6 +131,94 @@ func NewService(appDB *sql.DB, network uint64) *Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Notification) MarshalJSON() ([]byte, error) {
|
||||||
|
var body json.RawMessage
|
||||||
|
var err error
|
||||||
|
|
||||||
|
switch n.BodyType {
|
||||||
|
case TypeTransaction:
|
||||||
|
if nb, ok := n.Body.(*notificationBody); ok {
|
||||||
|
body, err = json.Marshal(nb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf(marshalTypeMismatchErr, n.BodyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
case TypeMessage:
|
||||||
|
if nmb, ok := n.Body.(*protocol.MessageNotificationBody); ok {
|
||||||
|
body, err = json.Marshal(nmb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf(marshalTypeMismatchErr, n.BodyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown NotificationType '%s'", n.BodyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
alias := notificationAlias{
|
||||||
|
n.ID,
|
||||||
|
n.Platform,
|
||||||
|
body,
|
||||||
|
n.BodyType,
|
||||||
|
n.Category,
|
||||||
|
n.Deeplink,
|
||||||
|
n.Image,
|
||||||
|
n.IsScheduled,
|
||||||
|
n.ScheduledTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Notification) UnmarshalJSON(data []byte) error {
|
||||||
|
var alias notificationAlias
|
||||||
|
err := json.Unmarshal(data, &alias)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
n.BodyType = alias.BodyType
|
||||||
|
n.Category = alias.Category
|
||||||
|
n.Platform = alias.Platform
|
||||||
|
n.ID = alias.ID
|
||||||
|
n.Image = alias.Image
|
||||||
|
n.Deeplink = alias.Deeplink
|
||||||
|
n.IsScheduled = alias.IsScheduled
|
||||||
|
n.ScheduledTime = alias.ScheduledTime
|
||||||
|
|
||||||
|
switch n.BodyType {
|
||||||
|
case TypeTransaction:
|
||||||
|
return n.unmarshalAndAttachBody(alias.Body, ¬ificationBody{})
|
||||||
|
|
||||||
|
case TypeMessage:
|
||||||
|
return n.unmarshalAndAttachBody(alias.Body, &protocol.MessageNotificationBody{})
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown NotificationType '%s'", n.BodyType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Notification) unmarshalAndAttachBody(body json.RawMessage, bodyStruct interface{}) error {
|
||||||
|
err := json.Unmarshal(body, &bodyStruct)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Body = bodyStruct
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushMessages(ns []*Notification) {
|
||||||
|
for _, n := range ns {
|
||||||
|
pushMessage(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func pushMessage(notification *Notification) {
|
func pushMessage(notification *Notification) {
|
||||||
log.Info("Pushing a new push notification", "info", notification)
|
log.Info("Pushing a new push notification", "info", notification)
|
||||||
signal.SendLocalNotifications(notification)
|
signal.SendLocalNotifications(notification)
|
||||||
|
@ -154,10 +271,11 @@ func (s *Service) buildTransactionNotification(rawTransfer wallet.Transfer) *Not
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Notification{
|
return &Notification{
|
||||||
|
BodyType: TypeTransaction,
|
||||||
ID: transfer.ID,
|
ID: transfer.ID,
|
||||||
Body: body,
|
Body: &body,
|
||||||
Deeplink: deeplink,
|
Deeplink: deeplink,
|
||||||
Category: "transaction",
|
Category: CategoryTransaction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,3 +473,19 @@ func (s *Service) Protocols() []p2p.Protocol {
|
||||||
func (s *Service) IsStarted() bool {
|
func (s *Service) IsStarted() bool {
|
||||||
return s.started
|
return s.started
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SendMessageNotifications(mnb []protocol.MessageNotificationBody) {
|
||||||
|
var ns []*Notification
|
||||||
|
for _, n := range mnb {
|
||||||
|
ns = append(ns, &Notification{
|
||||||
|
Body: n,
|
||||||
|
BodyType: TypeMessage,
|
||||||
|
Category: CategoryMessage,
|
||||||
|
Deeplink: "", // TODO find what if any Deeplink should be used here
|
||||||
|
Image: "", // TODO do we want to attach any image data contained on the MessageBody{}?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends notifications messages to the OS level application
|
||||||
|
pushMessages(ns)
|
||||||
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ func TestTransactionNotification(t *testing.T) {
|
||||||
|
|
||||||
require.NoError(t, utils.Eventually(func() error {
|
require.NoError(t, utils.Eventually(func() error {
|
||||||
if signalEvent == nil {
|
if signalEvent == nil {
|
||||||
return fmt.Errorf("Signal was not handled")
|
return fmt.Errorf("signal was not handled")
|
||||||
}
|
}
|
||||||
notification := struct {
|
notification := struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -130,10 +130,10 @@ func TestTransactionNotification(t *testing.T) {
|
||||||
require.NoError(t, json.Unmarshal(signalEvent, ¬ification))
|
require.NoError(t, json.Unmarshal(signalEvent, ¬ification))
|
||||||
|
|
||||||
if notification.Type != "local-notifications" {
|
if notification.Type != "local-notifications" {
|
||||||
return fmt.Errorf("Wrong signal was sent")
|
return fmt.Errorf("wrong signal was sent")
|
||||||
}
|
}
|
||||||
if notification.Event.Body.To != header.Address {
|
if notification.Event.Body.(*notificationBody).To != header.Address {
|
||||||
return fmt.Errorf("Transaction to address is wrong")
|
return fmt.Errorf("transaction to address is wrong")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}, 2*time.Second, 100*time.Millisecond))
|
}, 2*time.Second, 100*time.Millisecond))
|
||||||
|
|
Loading…
Reference in New Issue