diff --git a/protocol/communities/community_categories.go b/protocol/communities/community_categories.go index 315f38a6b..f76090e37 100644 --- a/protocol/communities/community_categories.go +++ b/protocol/communities/community_categories.go @@ -151,25 +151,61 @@ func (o *Community) ReorderCategories(categoryID string, newPosition int) (*Comm return nil, ErrNotAdmin } + if _, exists := o.config.CommunityDescription.Categories[categoryID]; !exists { + return nil, ErrCategoryNotFound + } + if newPosition > 0 && newPosition >= len(o.config.CommunityDescription.Categories) { newPosition = len(o.config.CommunityDescription.Categories) - 1 } else if newPosition < 0 { newPosition = 0 } - o.config.CommunityDescription.Categories[categoryID].Position = int32(newPosition) + category := o.config.CommunityDescription.Categories[categoryID] + if category.Position == int32(newPosition) { + return nil, ErrNoChangeInPosition + } + decrease := false + if category.Position > int32(newPosition) { + decrease = true + } + + // Sorting the categories because maps are not guaranteed to keep order s := make(sortSlice, 0, len(o.config.CommunityDescription.Categories)) - for catID, category := range o.config.CommunityDescription.Categories { - - position := category.Position - if category.CategoryId != categoryID && position >= int32(newPosition) { - position = position + 1 - } - + for k, v := range o.config.CommunityDescription.Categories { s = append(s, sorterHelperIdx{ - pos: position, - catID: catID, + pos: v.Position, + catID: k, + }) + } + sort.Sort(s) + var communityCategories []*protobuf.CommunityCategory + for _, currCat := range s { + communityCategories = append(communityCategories, o.config.CommunityDescription.Categories[currCat.catID]) + } + + var sortedCategoryIDs []string + for _, v := range communityCategories { + if v != category && ((decrease && v.Position < int32(newPosition)) || (!decrease && v.Position <= int32(newPosition))) { + sortedCategoryIDs = append(sortedCategoryIDs, v.CategoryId) + } + } + + sortedCategoryIDs = append(sortedCategoryIDs, categoryID) + + for _, v := range communityCategories { + if v.CategoryId == categoryID || (decrease && v.Position < int32(newPosition)) || (!decrease && v.Position <= int32(newPosition)) { + continue + } + sortedCategoryIDs = append(sortedCategoryIDs, v.CategoryId) + } + + s = make(sortSlice, 0, len(o.config.CommunityDescription.Categories)) + for i, k := range sortedCategoryIDs { + s = append(s, sorterHelperIdx{ + pos: int32(i), + catID: k, }) } @@ -200,8 +236,10 @@ func (o *Community) ReorderChat(categoryID string, chatID string, newPosition in return nil, ErrNotAdmin } - if _, exists := o.config.CommunityDescription.Categories[categoryID]; !exists { - return nil, ErrCategoryNotFound + if categoryID != "" { + if _, exists := o.config.CommunityDescription.Categories[categoryID]; !exists { + return nil, ErrCategoryNotFound + } } var chat *protobuf.CommunityChat @@ -258,10 +296,19 @@ func (o *Community) SortCategoryChats(changes *CommunityChanges, categoryID stri } func (o *Community) insertAndSort(changes *CommunityChanges, categoryID string, chat *protobuf.CommunityChat, newPosition int) { + // We sort the chats here because maps are not guaranteed to keep order var catChats []string - for k, c := range o.config.CommunityDescription.Chats { - if c.CategoryId == categoryID { - catChats = append(catChats, k) + sortedChats := make(sortSlice, 0, len(o.config.CommunityDescription.Chats)) + for k, v := range o.config.CommunityDescription.Chats { + sortedChats = append(sortedChats, sorterHelperIdx{ + pos: v.Position, + chatID: k, + }) + } + sort.Sort(sortedChats) + for _, k := range sortedChats { + if o.config.CommunityDescription.Chats[k.chatID].CategoryId == categoryID { + catChats = append(catChats, k.chatID) } } @@ -271,28 +318,45 @@ func (o *Community) insertAndSort(changes *CommunityChanges, categoryID string, newPosition = 0 } - sortedChats := make(sortSlice, 0, len(catChats)) - for _, k := range catChats { - position := chat.Position - if o.config.CommunityDescription.Chats[k] != chat && position >= int32(newPosition) { - position = position + 1 - } - - sortedChats = append(sortedChats, sorterHelperIdx{ - pos: position, - chatID: k, - }) + if int32(newPosition) == chat.Position { + return } - sort.Sort(sortedChats) + decrease := false + if chat.Position > int32(newPosition) { + decrease = true + } - for i, chatSortHelper := range sortedChats { - if o.config.CommunityDescription.Chats[chatSortHelper.chatID].Position != int32(i) { - o.config.CommunityDescription.Chats[chatSortHelper.chatID].Position = int32(i) - if changes.ChatsModified[chatSortHelper.chatID] != nil { - changes.ChatsModified[chatSortHelper.chatID].PositionModified = i + idx := -1 + currChatID := "" + var sortedChatIDs []string + for i, k := range catChats { + if o.config.CommunityDescription.Chats[k] != chat && ((decrease && o.config.CommunityDescription.Chats[k].Position < int32(newPosition)) || (!decrease && o.config.CommunityDescription.Chats[k].Position <= int32(newPosition))) { + sortedChatIDs = append(sortedChatIDs, k) + } else { + if o.config.CommunityDescription.Chats[k] == chat { + idx = i + currChatID = k + } + } + } + + sortedChatIDs = append(sortedChatIDs, currChatID) + + for i, k := range catChats { + if i == idx || (decrease && o.config.CommunityDescription.Chats[k].Position < int32(newPosition)) || (!decrease && o.config.CommunityDescription.Chats[k].Position <= int32(newPosition)) { + continue + } + sortedChatIDs = append(sortedChatIDs, k) + } + + for i, sortedChatID := range sortedChatIDs { + if o.config.CommunityDescription.Chats[sortedChatID].Position != int32(i) { + o.config.CommunityDescription.Chats[sortedChatID].Position = int32(i) + if changes.ChatsModified[sortedChatID] != nil { + changes.ChatsModified[sortedChatID].PositionModified = i } else { - changes.ChatsModified[chatSortHelper.chatID] = &CommunityChatChanges{ + changes.ChatsModified[sortedChatID] = &CommunityChatChanges{ MembersAdded: make(map[string]*protobuf.CommunityMember), MembersRemoved: make(map[string]*protobuf.CommunityMember), PositionModified: i, diff --git a/protocol/communities/errors.go b/protocol/communities/errors.go index e46ad4f6c..4afb598b8 100644 --- a/protocol/communities/errors.go +++ b/protocol/communities/errors.go @@ -4,6 +4,7 @@ import "errors" var ErrChatNotFound = errors.New("chat not found") var ErrCategoryNotFound = errors.New("category not found") +var ErrNoChangeInPosition = errors.New("no change in category position") var ErrChatAlreadyAssigned = errors.New("chat already assigned to a category") var ErrOrgNotFound = errors.New("community not found") var ErrChatAlreadyExists = errors.New("chat already exists") diff --git a/protocol/requests/delete_community_category.go b/protocol/requests/delete_community_category.go index c945d5a24..5211f02ea 100644 --- a/protocol/requests/delete_community_category.go +++ b/protocol/requests/delete_community_category.go @@ -6,8 +6,8 @@ import ( "github.com/status-im/status-go/eth-node/types" ) -var ErrDeleteCommunityCategoryInvalidCommunityID = errors.New("set-community-chat-category: invalid community id") -var ErrDeleteCommunityCategoryInvalidCategoryID = errors.New("set-community-chat-category: invalid category id") +var ErrDeleteCommunityCategoryInvalidCommunityID = errors.New("delete-community-category: invalid community id") +var ErrDeleteCommunityCategoryInvalidCategoryID = errors.New("delete-community-category: invalid category id") type DeleteCommunityCategory struct { CommunityID types.HexBytes `json:"communityId"` diff --git a/protocol/requests/reorder_community_category.go b/protocol/requests/reorder_community_category.go index c4da6c5e2..002adc529 100644 --- a/protocol/requests/reorder_community_category.go +++ b/protocol/requests/reorder_community_category.go @@ -6,9 +6,9 @@ import ( "github.com/status-im/status-go/eth-node/types" ) -var ErrReorderCommunityCategoryInvalidCommunityID = errors.New("edit-community-category: invalid community id") -var ErrReorderCommunityCategoryInvalidCategoryID = errors.New("edit-community-category: invalid category id") -var ErrReorderCommunityCategoryInvalidPosition = errors.New("edit-community-category: invalid position") +var ErrReorderCommunityCategoryInvalidCommunityID = errors.New("reorder-community-category: invalid community id") +var ErrReorderCommunityCategoryInvalidCategoryID = errors.New("reorder-community-category: invalid category id") +var ErrReorderCommunityCategoryInvalidPosition = errors.New("reorder-community-category: invalid position") type ReorderCommunityCategories struct { CommunityID types.HexBytes `json:"communityId"` @@ -22,7 +22,7 @@ func (j *ReorderCommunityCategories) Validate() error { } if len(j.CategoryID) == 0 { - return ErrEditCommunityCategoryInvalidCategoryID + return ErrReorderCommunityCategoryInvalidCategoryID } if j.Position < 0 { diff --git a/protocol/requests/reorder_community_chat.go b/protocol/requests/reorder_community_chat.go index 71d381e01..86ee4db0b 100644 --- a/protocol/requests/reorder_community_chat.go +++ b/protocol/requests/reorder_community_chat.go @@ -6,10 +6,9 @@ import ( "github.com/status-im/status-go/eth-node/types" ) -var ErrReorderCommunityChatInvalidCommunityID = errors.New("edit-community-category: invalid community id") -var ErrReorderCommunityChatInvalidCategoryID = errors.New("edit-community-category: invalid category id") -var ErrReorderCommunityChatInvalidChatID = errors.New("edit-community-category: invalid chat id") -var ErrReorderCommunityChatInvalidPosition = errors.New("edit-community-category: invalid position") +var ErrReorderCommunityChatInvalidCommunityID = errors.New("reorder-community-chat: invalid community id") +var ErrReorderCommunityChatInvalidChatID = errors.New("reorder-community-chat: invalid chat id") +var ErrReorderCommunityChatInvalidPosition = errors.New("reorder-community-chat: invalid position") type ReorderCommunityChat struct { CommunityID types.HexBytes `json:"communityId"` @@ -23,10 +22,6 @@ func (j *ReorderCommunityChat) Validate() error { return ErrReorderCommunityChatInvalidCommunityID } - if len(j.CategoryID) == 0 { - return ErrReorderCommunityChatInvalidCategoryID - } - if len(j.ChatID) == 0 { return ErrReorderCommunityChatInvalidChatID }