feat(sync)_: add AC notifications when initiating the sync fallback

Needed for https://github.com/status-im/status-desktop/issues/15750

Adds an AC notification when the syncing fails and the user is prompted to use a seed phrase instead.
There is one notification for the initiator (created) and one for the old account (received).
Once the flow is completed, ie the receiver presses Enable and sync,  the notifications are deleted
This commit is contained in:
Jonathan Rainville 2024-07-25 15:56:35 -04:00 committed by frank
parent 31538e7665
commit 837f682e0e
No known key found for this signature in database
GPG Key ID: B56FA1FC264D28FD
7 changed files with 302 additions and 163 deletions

View File

@ -40,6 +40,8 @@ const (
ActivityCenterNotificationTypeFirstCommunityTokenReceived
ActivityCenterNotificationTypeCommunityBanned
ActivityCenterNotificationTypeCommunityUnbanned
ActivityCenterNotificationTypeNewInstallationReceived
ActivityCenterNotificationTypeNewInstallationCreated
)
type ActivityCenterMembershipStatus int
@ -87,6 +89,7 @@ type ActivityCenterNotification struct {
MembershipStatus ActivityCenterMembershipStatus `json:"membershipStatus"`
Name string `json:"name"`
Author string `json:"author"`
InstallationID string `json:"installationId"`
Type ActivityCenterType `json:"type"`
LastMessage *common.Message `json:"lastMessage"`
Message *common.Message `json:"message"`

View File

@ -152,9 +152,10 @@ func (db sqlitePersistence) SaveActivityCenterNotification(notification *Activit
dismissed,
token_data,
deleted,
updated_at
updated_at,
installation_id
)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
`,
notification.ID,
notification.Timestamp,
@ -172,6 +173,7 @@ func (db sqlitePersistence) SaveActivityCenterNotification(notification *Activit
encodedTokenData,
notification.Deleted,
notification.UpdatedAt,
notification.InstallationID,
)
if err != nil {
return 0, err
@ -273,6 +275,7 @@ func (db sqlitePersistence) unmarshalActivityCenterNotificationRow(row *sql.Row)
var tokenDataBytes []byte
var name sql.NullString
var author sql.NullString
var installationID sql.NullString
notification := &ActivityCenterNotification{}
err := row.Scan(
&notification.ID,
@ -292,7 +295,9 @@ func (db sqlitePersistence) unmarshalActivityCenterNotificationRow(row *sql.Row)
&name,
&author,
&tokenDataBytes,
&notification.UpdatedAt)
&notification.UpdatedAt,
&installationID,
)
if err != nil {
return nil, err
@ -314,6 +319,10 @@ func (db sqlitePersistence) unmarshalActivityCenterNotificationRow(row *sql.Row)
notification.Author = author.String
}
if installationID.Valid {
notification.InstallationID = installationID.String
}
if len(tokenDataBytes) > 0 {
err = json.Unmarshal(tokenDataBytes, &notification.TokenData)
if err != nil {
@ -363,6 +372,7 @@ func (db sqlitePersistence) unmarshalActivityCenterNotificationRows(rows *sql.Ro
var tokenDataBytes []byte
var name sql.NullString
var author sql.NullString
var installationID sql.NullString
notification := &ActivityCenterNotification{}
err := rows.Scan(
&notification.ID,
@ -382,7 +392,9 @@ func (db sqlitePersistence) unmarshalActivityCenterNotificationRows(rows *sql.Ro
&author,
&tokenDataBytes,
&latestCursor,
&notification.UpdatedAt)
&notification.UpdatedAt,
&installationID,
)
if err != nil {
return "", nil, err
}
@ -403,6 +415,10 @@ func (db sqlitePersistence) unmarshalActivityCenterNotificationRows(rows *sql.Ro
notification.Author = author.String
}
if installationID.Valid {
notification.InstallationID = installationID.String
}
if len(tokenDataBytes) > 0 {
tokenData := &ActivityTokenData{}
if err = json.Unmarshal(tokenDataBytes, &tokenData); err != nil {
@ -543,7 +559,8 @@ func (db sqlitePersistence) buildActivityCenterQuery(tx *sql.Tx, params activity
a.author,
a.token_data,
substr('0000000000000000000000000000000000000000000000000000000000000000' || a.timestamp, -64, 64) || hex(a.id) as cursor,
a.updated_at
a.updated_at,
a.installation_id
FROM activity_center_notifications a
LEFT JOIN chats c
ON
@ -664,7 +681,8 @@ func (db sqlitePersistence) GetActivityCenterNotificationsByID(ids []types.HexBy
a.author,
a.token_data,
substr('0000000000000000000000000000000000000000000000000000000000000000' || a.timestamp, -64, 64) || hex(a.id) as cursor,
a.updated_at
a.updated_at,
a.installation_id
FROM activity_center_notifications a
LEFT JOIN chats c
ON
@ -704,7 +722,8 @@ func (db sqlitePersistence) GetActivityCenterNotificationByID(id types.HexBytes)
c.name,
a.author,
a.token_data,
a.updated_at
a.updated_at,
a.installation_id
FROM activity_center_notifications a
LEFT JOIN chats c
ON
@ -1338,7 +1357,8 @@ func (db sqlitePersistence) ActiveContactRequestNotification(contactID string) (
c.name,
a.author,
a.token_data,
a.updated_at
a.updated_at,
a.installation_id
FROM activity_center_notifications a
LEFT JOIN chats c ON c.id = a.chat_id
WHERE a.author = ?

View File

@ -3678,6 +3678,48 @@ func (m *Messenger) saveDataAndPrepareResponse(messageState *ReceivedMessageStat
}
}
if installation.Enabled {
// // Delete AC notif since the installation is now enabled
notification, err := m.persistence.GetActivityCenterNotificationByID(types.FromHex(id))
if err != nil {
return false
}
if notification != nil {
updatedAt := m.GetCurrentTimeInMillis()
notification.UpdatedAt = updatedAt
notification.Deleted = true
// we shouldn't sync deleted notification here,
// as the same user on different devices will receive the same message(CommunityCancelRequestToJoin) ?
err = m.persistence.DeleteActivityCenterNotificationByID(types.FromHex(id), updatedAt)
if err != nil {
m.logger.Error("failed to delete notification from Activity Center", zap.Error(err))
return false
}
// sending signal to client to remove the activity center notification from UI
messageState.Response.AddActivityCenterNotification(notification)
}
} else {
// Add activity center notification when we receive a new installation
if id != m.installationID {
notification := &ActivityCenterNotification{
ID: types.FromHex(id),
Type: ActivityCenterNotificationTypeNewInstallationReceived,
InstallationID: id,
Timestamp: m.getTimesource().GetCurrentTime(),
Read: false,
Deleted: false,
UpdatedAt: m.GetCurrentTimeInMillis(),
}
err = m.addActivityCenterNotification(messageState.Response, notification, nil)
if err != nil {
return false
}
}
}
return true
})
if err != nil {

View File

@ -9,6 +9,7 @@ import (
"go.uber.org/zap"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/images"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/encryption/multidevice"
@ -16,15 +17,45 @@ import (
"github.com/status-im/status-go/protocol/requests"
)
func (m *Messenger) EnableAndSyncInstallation(request *requests.EnableAndSyncInstallation) error {
func (m *Messenger) EnableAndSyncInstallation(request *requests.EnableAndSyncInstallation) (*MessengerResponse, error) {
if err := request.Validate(); err != nil {
return err
return nil, err
}
err := m.EnableInstallation(request.InstallationID)
if err != nil {
return err
return nil, err
}
return m.SyncDevices(context.Background(), "", "", nil)
response, err := m.SendPairInstallation(context.Background(), nil)
if err != nil {
return nil, err
}
err = m.SyncDevices(context.Background(), "", "", nil)
if err != nil {
return nil, err
}
// Delete AC notif
notification, err := m.persistence.GetActivityCenterNotificationByID(types.FromHex(request.InstallationID))
if err != nil {
return nil, err
}
if notification != nil {
updatedAt := m.GetCurrentTimeInMillis()
notification.UpdatedAt = updatedAt
notification.Deleted = true
// we shouldn't sync deleted notification here,
// as the same user on different devices will receive the same message(CommunityCancelRequestToJoin) ?
err = m.persistence.DeleteActivityCenterNotificationByID(types.FromHex(request.InstallationID), updatedAt)
if err != nil {
m.logger.Error("failed to delete notification from Activity Center", zap.Error(err))
return nil, err
}
// sending signal to client to remove the activity center notification from UI
response.AddActivityCenterNotification(notification)
}
return response, nil
}
func (m *Messenger) EnableInstallationAndPair(request *requests.EnableInstallationAndPair) (*MessengerResponse, error) {
@ -53,7 +84,26 @@ func (m *Messenger) EnableInstallationAndPair(request *requests.EnableInstallati
i.Enabled = true
}
m.allInstallations.Store(request.InstallationID, i)
return m.SendPairInstallation(context.Background(), nil)
response, err := m.SendPairInstallation(context.Background(), nil)
if err != nil {
return nil, err
}
notification := &ActivityCenterNotification{
ID: types.FromHex(request.InstallationID),
Type: ActivityCenterNotificationTypeNewInstallationCreated,
InstallationID: m.installationID, // Put our own installation ID, as we're the initiator of the pairing
Timestamp: m.getTimesource().GetCurrentTime(),
Read: false,
Deleted: false,
UpdatedAt: m.GetCurrentTimeInMillis(),
}
err = m.addActivityCenterNotification(response, notification, nil)
if err != nil {
return nil, err
}
return response, err
}
// SendPairInstallation sends a pair installation message

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
ALTER TABLE activity_center_notifications ADD COLUMN installation_id TEXT DEFAULT NULL;

View File

@ -1064,7 +1064,7 @@ func (api *PublicAPI) SyncDevices(ctx context.Context, name, picture string) err
return api.service.messenger.SyncDevices(ctx, name, picture, nil)
}
func (api *PublicAPI) EnableAndSyncInstallation(request *requests.EnableAndSyncInstallation) error {
func (api *PublicAPI) EnableAndSyncInstallation(request *requests.EnableAndSyncInstallation) (*protocol.MessengerResponse, error) {
return api.service.messenger.EnableAndSyncInstallation(request)
}