mirror of
https://github.com/status-im/status-go.git
synced 2025-01-10 14:47:06 +00:00
dbed69d155
Fixes the slow login in mobile devices when users have joined large communities, such as the Status one. A user would get stuck for almost 20s in some devices. We identified that the step to set-up filters in the messenger is potentially expensive and that it is not critical to happen before the node.login signal is emitted. The solution presented in this PR is to set-up filters inside messenger.Start(), which the client already calls immediately after login. With this change, users of the mobile app can login pretty fast even when they joined large communities. They can immediately interact with other parts of the app even if filter initialization is running in the background, like Wallet, Activity Center, Settings, and Profile. Breaking changes: in the mobile repository, we had to change where the endpoint wakuext_startMessenger was called and the order of a few events to process chats. So essentially ordering, but no data changes. - Root issue https://github.com/status-im/status-mobile/issues/20059 - Related mobile PR https://github.com/status-im/status-mobile/pull/20173
198 lines
4.7 KiB
Go
198 lines
4.7 KiB
Go
package protocol
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
utils "github.com/status-im/status-go/common"
|
|
"github.com/status-im/status-go/multiaccounts/settings"
|
|
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
|
"github.com/status-im/status-go/server"
|
|
)
|
|
|
|
const (
|
|
maxBioLength = 240
|
|
)
|
|
|
|
var ErrInvalidBioLength = errors.New("invalid bio length")
|
|
var ErrDisplayNameDupeOfCommunityMember = errors.New("display name duplicates on of community members")
|
|
|
|
func (m *Messenger) SetDisplayName(displayName string) error {
|
|
currDisplayName, err := m.settings.DisplayName()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if utils.IsENSName(displayName) || currDisplayName == displayName {
|
|
return nil // Do nothing
|
|
}
|
|
|
|
if err = utils.ValidateDisplayName(&displayName); err != nil {
|
|
return err
|
|
}
|
|
|
|
isDupe, err := m.IsDisplayNameDupeOfCommunityMember(displayName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if isDupe {
|
|
return ErrDisplayNameDupeOfCommunityMember
|
|
}
|
|
|
|
m.account.Name = displayName
|
|
err = m.multiAccounts.UpdateDisplayName(m.account.KeyUID, displayName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = m.settings.SaveSettingField(settings.DisplayName, displayName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = m.UpdateKeypairName(m.account.KeyUID, displayName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = m.resetLastPublishedTimeForChatIdentity()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return m.publishContactCode()
|
|
}
|
|
|
|
func (m *Messenger) SaveSyncDisplayName(displayName string, clock uint64) error {
|
|
err := m.settings.SaveSyncSetting(settings.DisplayName, displayName, clock)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
preferredName, err := m.settings.GetPreferredUsername()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
preferredNameClock, err := m.settings.GetSettingLastSynced(settings.PreferredName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// When either the display name or preferred name changes, m.account.Name should be updated.
|
|
// However, a race condition can occur during BackupData, where m.account.Name could be incorrectly updated.
|
|
// The final value of m.account.Name depends on which backup message(BackedUpProfile/BackedUpSettings) arrives later.
|
|
// So we should check the clock of the preferred name and only update m.account.Name if it's older than the display name.
|
|
// Yet even if the preferred name clock is older, but the preferred name was empty, we should still update m.account.Name.
|
|
|
|
if preferredNameClock < clock || preferredName == "" {
|
|
m.account.Name = displayName
|
|
return m.multiAccounts.SaveAccount(*m.account)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ValidateBio(bio *string) error {
|
|
if utf8.RuneCountInString(*bio) > maxBioLength {
|
|
return ErrInvalidBioLength
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Messenger) SetBio(bio string) error {
|
|
currentBio, err := m.settings.Bio()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if currentBio == bio {
|
|
return nil // Do nothing
|
|
}
|
|
|
|
if err = ValidateBio(&bio); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = m.settings.SaveSettingField(settings.Bio, bio); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = m.resetLastPublishedTimeForChatIdentity(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return m.publishContactCode()
|
|
}
|
|
|
|
func (m *Messenger) setInstallationHostname() error {
|
|
imd, err := m.getOurInstallationMetadata()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// If the name and device are already set, don't do anything
|
|
if len(imd.Name) != 0 && len(imd.DeviceType) != 0 {
|
|
return nil
|
|
}
|
|
|
|
if len(imd.Name) == 0 {
|
|
deviceName, err := m.settings.DeviceName()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if deviceName != "" {
|
|
imd.Name = deviceName
|
|
} else {
|
|
hn, err := server.GetDeviceName()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// NOTE: imd.Name is always empty in this else branch, which leads to the
|
|
// result of Sprintf having a trailing whitespace.
|
|
imd.Name = fmt.Sprintf("%s %s", hn, imd.Name)
|
|
}
|
|
}
|
|
|
|
if len(imd.DeviceType) == 0 {
|
|
imd.DeviceType = runtime.GOOS
|
|
}
|
|
|
|
return m.setInstallationMetadata(m.installationID, imd)
|
|
|
|
}
|
|
|
|
func (m *Messenger) getOurInstallationMetadata() (*multidevice.InstallationMetadata, error) {
|
|
ourInstallation, ok := m.allInstallations.Load(m.installationID)
|
|
if !ok {
|
|
return nil, fmt.Errorf("messenger's installationID is not set or not loadable")
|
|
}
|
|
|
|
if ourInstallation.InstallationMetadata == nil {
|
|
return new(multidevice.InstallationMetadata), nil
|
|
}
|
|
|
|
return ourInstallation.InstallationMetadata, nil
|
|
}
|
|
|
|
func (m *Messenger) SetInstallationDeviceType(deviceType string) error {
|
|
if strings.TrimSpace(deviceType) == "" {
|
|
return errors.New("device type is empty")
|
|
}
|
|
|
|
imd, err := m.getOurInstallationMetadata()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// If the name is already set, don't do anything
|
|
if len(imd.DeviceType) != 0 {
|
|
return nil
|
|
}
|
|
|
|
imd.DeviceType = deviceType
|
|
return m.setInstallationMetadata(m.installationID, imd)
|
|
}
|