feat(Communities): implement drag and drop to reorder category channels

Closes: #2776
This commit is contained in:
B.Melnik 2021-07-28 15:40:51 +03:00 committed by Pascal Precht
parent 6561e0ea26
commit a362efecf4
11 changed files with 89 additions and 8 deletions

View File

@ -1,4 +1,5 @@
import NimQml, Tables
import algorithm
import ../../../status/chat/[chat, message]
import ../../../status/status
import ../../../status/accounts
@ -19,6 +20,7 @@ type
Id = UserRole + 11
Description = UserRole + 12
CategoryId = UserRole + 13
Position = UserRole + 14
QtObject:
type
@ -65,6 +67,7 @@ QtObject:
of ChannelsRoles.Id: result = newQVariant($chatItem.id)
of ChannelsRoles.CategoryId: result = newQVariant(chatItem.categoryId)
of ChannelsRoles.Description: result = newQVariant(chatItem.description)
of ChannelsRoles.Position: result = newQVariant(chatItem.position)
method roleNames(self: ChannelsList): Table[int, string] =
{
@ -80,12 +83,20 @@ QtObject:
ChannelsRoles.Muted.int: "muted",
ChannelsRoles.Id.int: "id",
ChannelsRoles.Description.int: "description",
ChannelsRoles.CategoryId.int: "categoryId"
ChannelsRoles.CategoryId.int: "categoryId",
ChannelsRoles.Position.int: "position"
}.toTable
proc sortChats(x, y: Chat): int =
if x.position < y.position: -1
elif x.position == y.position: 0
else: 1
proc setChats*(self: ChannelsList, chats: seq[Chat]) =
self.beginResetModel()
self.chats = chats
var copy = chats
copy.sort(sortChats)
self.chats = copy
self.endResetModel()
proc addChatItemToList*(self: ChannelsList, channel: Chat): int =
@ -165,7 +176,19 @@ QtObject:
self.chats[idx] = channel
self.dataChanged(topLeft, bottomRight, @[ChannelsRoles.Name.int, ChannelsRoles.Description.int, ChannelsRoles.ContentType.int, ChannelsRoles.LastMessage.int, ChannelsRoles.Timestamp.int, ChannelsRoles.UnreadMessages.int, ChannelsRoles.Identicon.int, ChannelsRoles.ChatType.int, ChannelsRoles.Color.int, ChannelsRoles.MentionsCount.int, ChannelsRoles.Muted.int])
self.dataChanged(topLeft, bottomRight,
@[ChannelsRoles.Name.int,
ChannelsRoles.Description.int,
ChannelsRoles.ContentType.int,
ChannelsRoles.LastMessage.int,
ChannelsRoles.Timestamp.int,
ChannelsRoles.UnreadMessages.int,
ChannelsRoles.Identicon.int,
ChannelsRoles.ChatType.int,
ChannelsRoles.Color.int,
ChannelsRoles.MentionsCount.int,
ChannelsRoles.Muted.int,
ChannelsRoles.Position.int])
proc clearUnreadMessages*(self: ChannelsList, channelId: string) =
let idx = self.chats.findIndexById(channelId)

View File

@ -186,6 +186,13 @@ QtObject:
read = muted
notify = mutedChanged
proc position*(self: ChatItemView): int {.slot.} = result = ?.self.chatItem.position
proc positionChanged*(self: ChatItemView) {.signal.}
QtProperty[int] position:
read = position
notify = positionChanged
proc contains*(self: ChatItemView, pubKey: string): bool {.slot.} =
if self.chatItem.isNil: return false
return self.chatItem.contains(pubKey)

View File

@ -23,6 +23,7 @@ proc mergeChat(community: var Community, chat: Chat): bool =
if (c.id == chat.id):
chat.canPost = community.chats[i].canPost
chat.categoryId = community.chats[i].categoryId
chat.position = community.chats[i].position
community.chats[i] = chat
return true
@ -341,7 +342,25 @@ QtObject:
except Exception as e:
error "Error creating the category", msg = e.msg
result = fmt"Error creating the category: {e.msg}"
proc reorderCommunityCategory*(self: CommunitiesView, communityId: string, categoryId: string, position: int): string {.slot} =
result = ""
try:
self.status.chat.reorderCommunityCategory(communityId, categoryId, position)
except Exception as e:
error "Error reorder the category", msg = e.msg
result = fmt"Error reorder the category: {e.msg}"
proc reorderCommunityChannel*(self: CommunitiesView, communityId: string, categoryId: string, chatId: string, position: int): string {.slot} =
result = ""
try:
self.status.chat.reorderCommunityChannel(communityId, categoryId, chatId, position)
except Exception as e:
error "Error reorder the channel", msg = e.msg
result = fmt"Error reorder the channel: {e.msg}"
proc setObservedCommunity*(self: CommunitiesView, communityId: string) {.slot.} =
if(communityId == ""): return
var community = self.communityList.getCommunityById(communityId)

View File

@ -486,6 +486,9 @@ QtObject:
proc deleteCommunityChat*(self: ChatModel, communityId: string, channelId: string) =
status_chat.deleteCommunityChat(communityId, channelId)
proc reorderCommunityCategory*(self: ChatModel, communityId: string, categoryId: string, position: int) =
status_chat.reorderCommunityCategory(communityId, categoryId, position)
proc createCommunityCategory*(self: ChatModel, communityId: string, name: string, channels: seq[string]): CommunityCategory =
result = status_chat.createCommunityCategory(communityId, name, channels)

View File

@ -88,6 +88,7 @@ type Chat* = ref object
muted*: bool
canPost*: bool
ensName*: string
position*: int
type RemovedMessage* = object
chatId*: string
@ -180,7 +181,8 @@ proc toJsonNode*(self: Chat): JsonNode =
"name": (if self.ensName != "": self.ensName else: self.name),
"timestamp": self.timestamp,
"unviewedMessagesCount": self.unviewedMessagesCount,
"joined": self.joined
"joined": self.joined,
"position": self.position
}
proc findIndexById*(self: seq[Chat], id: string): int =

View File

@ -425,6 +425,17 @@ proc reorderCommunityChat*(communityId: string, categoryId: string, chatId: stri
if rpcResult.contains("error"):
raise newException(StatusGoException, rpcResult["error"]["message"].getStr())
proc reorderCommunityCategory*(communityId: string, categoryId: string, position: int) =
let rpcResult = callPrivateRPC("reorderCommunityCategory".prefix, %*[
{
"communityId": communityId,
"categoryId": categoryId,
"position": position
}]).parseJSON()
if rpcResult.contains("error"):
raise newException(StatusGoException, rpcResult["error"]["message"].getStr())
proc deleteCommunityCategory*(communityId: string, categoryId: string) =
let rpcResult = callPrivateRPC("deleteCommunityCategory".prefix, %*[
{

View File

@ -259,7 +259,8 @@ proc toCommunity*(jsonCommunity: JsonNode): Community =
description: chat{"description"}.getStr,
canPost: chat{"canPost"}.getBool,
chatType: ChatType.CommunityChat,
private: chat{"permissions"}{"private"}.getBool
private: chat{"permissions"}{"private"}.getBool,
position: chat{"position"}.getInt
))
if jsonCommunity.hasKey("categories") and jsonCommunity["categories"].kind != JNull:
@ -452,4 +453,4 @@ proc toActivityCenterNotification*(jsonNotification: JsonNode): ActivityCenterNo
if jsonNotification.contains("message") and jsonNotification{"message"}.kind != JNull:
result.message = jsonNotification{"message"}.toMessage()
elif activityCenterNotificationType == ActivityCenterNotificationType.NewOneToOne and jsonNotification.contains("lastMessage") and jsonNotification{"lastMessage"}.kind != JNull:
result.message = jsonNotification{"lastMessage"}.toMessage()
result.message = jsonNotification{"lastMessage"}.toMessage()

View File

@ -124,7 +124,9 @@ Item {
return implicitHeight
}
draggableItems: true
chatList.model: chatsModel.communities.activeCommunity.chats
categoryList.model: chatsModel.communities.activeCommunity.categories
showCategoryActionButtons: chatsModel.communities.activeCommunity.admin
@ -133,6 +135,10 @@ Item {
onChatItemSelected: chatsModel.channelView.setActiveChannel(id)
onChatItemUnmuted: chatsModel.channelView.unmuteChatItem(id)
onChatItemReordered: function (categoryId, chatId, from, to) {
chatsModel.communities.reorderCommunityChannel(chatsModel.communities.activeCommunity.id, categoryId, chatId, to);
}
onCategoryAddButtonClicked: openPopup(createChannelPopup, {
communityId: chatsModel.communities.activeCommunity.id,
categoryId: id

View File

@ -299,7 +299,7 @@ StatusWindow {
property alias droppedUrls: rptDraggedPreviews.model
readonly property int chatView: Utils.getAppSectionIndex(Constants.chat)
readonly property int timelineView: Utils.getAppSectionIndex(Constants.timeline)
property bool enabled: containsDrag && loader.item &&
property bool enabled: containsDrag && drag.source.objectName !== "chatItem" && loader.item &&
(
// in chat view
(loader.item.currentView === chatView &&
@ -326,10 +326,17 @@ StatusWindow {
onDropped: (drop) => {
if (enabled) {
droppedOnValidScreen(drop)
} else {
drop.accepted = false
}
cleanup()
}
onEntered: {
if (!enabled) {
drag.accepted = false
return
}
// needed because drag.urls is not a normal js array
rptDraggedPreviews.model = drag.urls.filter(img => Utils.hasDragNDropImageExtension(img))
}

View File

@ -430,3 +430,5 @@ DISTFILES += \
shared/status/StatusRadioButtonRow.qml \
shared/status/StatusSettingsLineButton.qml \
sounds/ErrorSound.qml
DISTFILES += $$files("StatusQ/*", true)

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 20363e32ef96d4b5631ef4dd375bdb65252e6416
Subproject commit fe086b2fdd998dca50223e4da084eccfc5ab9555