forked from Silverfish/proton-bridge
GODT-1346: GODT-1340 GODT-1315 QML changes
GODT-1365: Create ComboBox component GODT-1338: GODT-1343 Help view buttons GODT-1340: Not crashing, user list updating in main thread. GODT-1345: adding panic handlers
This commit is contained in:
@ -20,10 +20,17 @@
|
||||
package qt
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
|
||||
"github.com/therecipe/qt/core"
|
||||
)
|
||||
|
||||
func init() {
|
||||
QMLUser_QRegisterMetaType()
|
||||
QMLUserModel_QRegisterMetaType()
|
||||
}
|
||||
|
||||
// QMLUserModel stores list of of users
|
||||
type QMLUserModel struct {
|
||||
core.QAbstractListModel
|
||||
@ -33,72 +40,168 @@ type QMLUserModel struct {
|
||||
_ func() `constructor:"init"`
|
||||
_ func(row int) *core.QVariant `slot:"get"`
|
||||
|
||||
users []*QMLUser
|
||||
userIDs []string
|
||||
userByID map[string]*QMLUser
|
||||
access sync.RWMutex
|
||||
f *FrontendQt
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) init() {
|
||||
um.SetRoles(map[int]*core.QByteArray{
|
||||
int(core.Qt__UserRole + 1): newQByteArrayFromString("object"),
|
||||
})
|
||||
um.access.Lock()
|
||||
defer um.access.Unlock()
|
||||
um.SetCount(0)
|
||||
um.ConnectRowCount(um.rowCount)
|
||||
um.ConnectData(um.data)
|
||||
um.ConnectGet(um.get)
|
||||
um.users = []*QMLUser{}
|
||||
um.setCount()
|
||||
um.ConnectCount(func() int {
|
||||
um.access.RLock()
|
||||
defer um.access.RUnlock()
|
||||
return len(um.userIDs)
|
||||
})
|
||||
um.userIDs = []string{}
|
||||
um.userByID = map[string]*QMLUser{}
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) data(index *core.QModelIndex, property int) *core.QVariant {
|
||||
if !index.IsValid() {
|
||||
um.f.log.WithField("size", len(um.userIDs)).Info("Trying to get user by invalid index")
|
||||
return core.NewQVariant()
|
||||
}
|
||||
return um.get(index.Row())
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) get(index int) *core.QVariant {
|
||||
if index < 0 || index >= um.rowCount(nil) {
|
||||
um.access.Lock()
|
||||
defer um.access.Unlock()
|
||||
if index < 0 || index >= len(um.userIDs) {
|
||||
um.f.log.WithField("index", index).WithField("size", len(um.userIDs)).Info("Trying to get user by wrong index")
|
||||
return core.NewQVariant()
|
||||
}
|
||||
return um.users[index].ToVariant()
|
||||
|
||||
u, err := um.getUserByID(um.userIDs[index])
|
||||
if err != nil {
|
||||
um.f.log.WithError(err).Error("Cannot get user from backend")
|
||||
return core.NewQVariant()
|
||||
}
|
||||
return u.ToVariant()
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) getUserByID(userID string) (*QMLUser, error) {
|
||||
u, ok := um.userByID[userID]
|
||||
if ok {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
user, err := um.f.bridge.GetUser(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u = newQMLUserFromBacked(um, user)
|
||||
um.userByID[userID] = u
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) rowCount(*core.QModelIndex) int {
|
||||
return len(um.users)
|
||||
um.access.RLock()
|
||||
defer um.access.RUnlock()
|
||||
return len(um.userIDs)
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) setCount() {
|
||||
um.SetCount(len(um.users))
|
||||
um.SetCount(len(um.userIDs))
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) addUser(user *QMLUser) {
|
||||
um.BeginInsertRows(core.NewQModelIndex(), um.rowCount(nil), um.rowCount(nil))
|
||||
um.users = append(um.users, user)
|
||||
um.setCount()
|
||||
func (um *QMLUserModel) addUser(userID string) {
|
||||
um.BeginInsertRows(core.NewQModelIndex(), len(um.userIDs), len(um.userIDs))
|
||||
um.access.Lock()
|
||||
if um.indexByIDNotSafe(userID) < 0 {
|
||||
um.userIDs = append(um.userIDs, userID)
|
||||
}
|
||||
um.access.Unlock()
|
||||
um.EndInsertRows()
|
||||
um.setCount()
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) removeUser(row int) {
|
||||
um.BeginRemoveRows(core.NewQModelIndex(), row, row)
|
||||
um.users = append(um.users[:row], um.users[row+1:]...)
|
||||
um.setCount()
|
||||
um.access.Lock()
|
||||
id := um.userIDs[row]
|
||||
um.userIDs = append(um.userIDs[:row], um.userIDs[row+1:]...)
|
||||
delete(um.userByID, id)
|
||||
um.access.Unlock()
|
||||
um.EndRemoveRows()
|
||||
um.setCount()
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) clear() {
|
||||
um.BeginRemoveRows(core.NewQModelIndex(), 0, um.rowCount(nil))
|
||||
um.users = []*QMLUser{}
|
||||
um.setCount()
|
||||
um.EndRemoveRows()
|
||||
um.BeginResetModel()
|
||||
um.access.Lock()
|
||||
um.userIDs = []string{}
|
||||
um.userByID = map[string]*QMLUser{}
|
||||
um.SetCount(0)
|
||||
um.access.Unlock()
|
||||
um.EndResetModel()
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) indexByID(id string) int {
|
||||
for i, qu := range um.users {
|
||||
if id == qu.ID {
|
||||
func (um *QMLUserModel) load() {
|
||||
um.clear()
|
||||
|
||||
for _, user := range um.f.bridge.GetUsers() {
|
||||
um.addUser(user.ID())
|
||||
|
||||
// We need mark that all existing users already saw setup
|
||||
// guide. This it is OK to construct QML here because it is in main thread.
|
||||
u, err := um.getUserByID(user.ID())
|
||||
if err != nil {
|
||||
um.f.log.WithError(err).Error("Cannot get QMLUser while loading users")
|
||||
}
|
||||
u.SetSetupGuideSeen(true)
|
||||
}
|
||||
|
||||
// If there are no active accounts.
|
||||
if um.Count() == 0 {
|
||||
um.f.log.Info("No active accounts")
|
||||
}
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) userChanged(userID string) {
|
||||
index := um.indexByIDNotSafe(userID)
|
||||
user, err := um.f.bridge.GetUser(userID)
|
||||
|
||||
if user == nil || err != nil {
|
||||
if index >= 0 { // delete existing user
|
||||
um.removeUser(index)
|
||||
}
|
||||
// if not exiting do nothing
|
||||
return
|
||||
}
|
||||
|
||||
if index < 0 { // add non-existing user
|
||||
um.addUser(userID)
|
||||
return
|
||||
}
|
||||
|
||||
// update exiting user
|
||||
um.userByID[userID].update(user)
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) indexByIDNotSafe(wantID string) int {
|
||||
for i, id := range um.userIDs {
|
||||
if id == wantID {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (um *QMLUserModel) indexByID(id string) int {
|
||||
um.access.RLock()
|
||||
defer um.access.RUnlock()
|
||||
|
||||
return um.indexByIDNotSafe(id)
|
||||
}
|
||||
|
||||
// QMLUser holds data, slots and signals and for user.
|
||||
type QMLUser struct {
|
||||
core.QObject
|
||||
@ -116,18 +219,66 @@ type QMLUser struct {
|
||||
_ func(makeItActive bool) `slot:"toggleSplitMode"`
|
||||
_ func() `signal:"toggleSplitModeFinished"`
|
||||
_ func() `slot:"logout"`
|
||||
_ func() `slot:"remove"`
|
||||
_ func(address string) `slot:"configureAppleMail"`
|
||||
|
||||
ID string
|
||||
}
|
||||
|
||||
func newQMLUserFromBacked(um *QMLUserModel, user types.User) *QMLUser {
|
||||
qu := NewQMLUser(um)
|
||||
qu.ID = user.ID()
|
||||
|
||||
qu.update(user)
|
||||
|
||||
qu.ConnectToggleSplitMode(func(activateSplitMode bool) {
|
||||
go func() {
|
||||
defer um.f.panicHandler.HandlePanic()
|
||||
defer qu.ToggleSplitModeFinished()
|
||||
if activateSplitMode == user.IsCombinedAddressMode() {
|
||||
user.SwitchAddressMode()
|
||||
}
|
||||
qu.SetSplitMode(!user.IsCombinedAddressMode())
|
||||
}()
|
||||
})
|
||||
|
||||
qu.ConnectLogout(func() {
|
||||
qu.SetLoggedIn(false)
|
||||
go func() {
|
||||
defer um.f.panicHandler.HandlePanic()
|
||||
user.Logout()
|
||||
}()
|
||||
})
|
||||
|
||||
qu.ConnectRemove(func() {
|
||||
go func() {
|
||||
defer um.f.panicHandler.HandlePanic()
|
||||
|
||||
// TODO: remove preferences
|
||||
if err := um.f.bridge.DeleteUser(qu.ID, false); err != nil {
|
||||
um.f.log.WithError(err).Error("Failed to remove user")
|
||||
// TODO: notification
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
qu.ConnectConfigureAppleMail(func(address string) {
|
||||
go func() {
|
||||
defer um.f.panicHandler.HandlePanic()
|
||||
um.f.configureAppleMail(qu.ID, address)
|
||||
}()
|
||||
})
|
||||
|
||||
return qu
|
||||
}
|
||||
|
||||
func (qu *QMLUser) update(user types.User) {
|
||||
username := user.Username()
|
||||
qu.SetAvatarText(getInitials(username))
|
||||
qu.SetUsername(username)
|
||||
qu.SetLoggedIn(user.IsConnected())
|
||||
qu.SetSplitMode(!user.IsCombinedAddressMode())
|
||||
qu.SetSetupGuideSeen(true)
|
||||
qu.SetSetupGuideSeen(false)
|
||||
qu.SetUsedBytes(1.0) // TODO
|
||||
qu.SetTotalBytes(10000.0) // TODO
|
||||
qu.SetPassword(user.GetBridgePassword())
|
||||
|
||||
Reference in New Issue
Block a user