From 6849091460fcf1a6354fc13ab87c344fec110da1 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Sat, 10 Jul 2021 19:25:19 -0400 Subject: [PATCH] feat: community user status pt 2 --- src/app/chat/event_handling.nim | 6 ++++++ src/app/chat/signal_handling.nim | 2 +- src/app/chat/views/communities.nim | 9 ++++----- src/app/chat/views/community_item.nim | 8 ++++++-- src/app/chat/views/community_list.nim | 14 +++++++------- src/app/chat/views/messages.nim | 4 +--- src/status/chat.nim | 5 +++-- src/status/chat/chat.nim | 13 ++++++++++++- src/status/signals/messages.nim | 19 ++++++++++++++++++- src/status/signals/types.nim | 1 + ui/app/AppLayouts/Chat/ChatColumn/User.qml | 7 ++++--- .../CommunityComponents/CommunityUserList.qml | 5 +++-- ui/imports/Constants.qml | 4 ++++ vendor/status-go | 2 +- 14 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/app/chat/event_handling.nim b/src/app/chat/event_handling.nim index 723e45992c..bda12a3c1d 100644 --- a/src/app/chat/event_handling.nim +++ b/src/app/chat/event_handling.nim @@ -33,6 +33,12 @@ proc handleChatEvents(self: ChatController) = self.view.updateUsernames(evArgs.contacts) self.view.updateChats(evArgs.chats) self.view.pushMessages(evArgs.messages) + + # TODO: update current user status + + for statusUpdate in evArgs.statusUpdates: + self.view.communities.updateMemberVisibility(statusUpdate) + for message in evArgs.messages: if (message.replace != ""): # Delete the message that this message replaces diff --git a/src/app/chat/signal_handling.nim b/src/app/chat/signal_handling.nim index 2b546ca4bf..6491f83544 100644 --- a/src/app/chat/signal_handling.nim +++ b/src/app/chat/signal_handling.nim @@ -4,7 +4,7 @@ import proc handleSignals(self: ChatController) = self.status.events.on(SignalType.Message.event) do(e:Args): var data = MessageSignal(e) - self.status.chat.update(data.chats, data.messages, data.emojiReactions, data.communities, data.membershipRequests, data.pinnedMessages, data.activityCenterNotification) + self.status.chat.update(data.chats, data.messages, data.emojiReactions, data.communities, data.membershipRequests, data.pinnedMessages, data.activityCenterNotification, data.statusUpdates) self.status.events.on(SignalType.DiscoverySummary.event) do(e:Args): ## Handle mailserver peers being added and removed diff --git a/src/app/chat/views/communities.nim b/src/app/chat/views/communities.nim index 29336bfeff..a15f6f4fd6 100644 --- a/src/app/chat/views/communities.nim +++ b/src/app/chat/views/communities.nim @@ -66,11 +66,10 @@ QtObject: if unreadTotal != community.unviewedMessagesCount: community.unviewedMessagesCount = unreadTotal - proc updateMemberVisibility*(self: CommunitiesView, communityId, pubKey, timestamp: string) = - self.joinedCommunityList.updateMemberVisibility(communityId, pubKey, timestamp) - if communityId == self.activeCommunity.communityItem.id: - self.activeCommunity.setCommunityItem(self.joinedCommunityList.getCommunityById(communityId)) - self.activeCommunity.triggerMemberUpdate() + proc updateMemberVisibility*(self: CommunitiesView, statusUpdate: StatusUpdate) = + self.joinedCommunityList.updateMemberVisibility(statusUpdate) + self.activeCommunity.setCommunityItem(self.joinedCommunityList.getCommunityById(self.activeCommunity.communityItem.id)) + self.activeCommunity.triggerMemberUpdate() proc updateCommunityChat*(self: CommunitiesView, newChat: Chat) = var community = self.joinedCommunityList.getCommunityById(newChat.communityId) diff --git a/src/app/chat/views/community_item.nim b/src/app/chat/views/community_item.nim index a25aac2c13..d290691243 100644 --- a/src/app/chat/views/community_item.nim +++ b/src/app/chat/views/community_item.nim @@ -199,11 +199,15 @@ QtObject: self.members.triggerUpdate() proc memberLastSeen*(self: CommunityItemView, pubKey: string): string {.slot.} = - if self.communityItem.lastSeen.hasKey(pubKey): - result = self.communityItem.lastSeen[pubKey] + if self.communityItem.memberStatus.hasKey(pubKey): + result = $self.communityItem.memberStatus[pubKey].clock else: result = "0" + proc memberStatus*(self: CommunityItemView, pubKey: string): int {.slot.} = + if self.communityItem.memberStatus.hasKey(pubKey): + result = self.communityItem.memberStatus[pubKey].statusType.int + proc hasMember*(self: CommunityItemView, pubKey: string): bool {.slot.} = result = self.members.members.contains(pubKey) diff --git a/src/app/chat/views/community_list.nim b/src/app/chat/views/community_list.nim index 408006cc96..716bd1cd31 100644 --- a/src/app/chat/views/community_list.nim +++ b/src/app/chat/views/community_list.nim @@ -171,14 +171,14 @@ QtObject: if community.id == communityId: return community - proc updateMemberVisibility*(self: CommunityList, communityId, pubKey, timestamp: string) = + proc updateMemberVisibility*(self: CommunityList, statusUpdate: StatusUpdate) = for community in self.communities.mitems: - if community.id != communityId: continue - if community.lastSeen.haskey(pubKey): - if parseBiggestInt(timestamp) > parseBiggestInt(community.lastSeen[pubKey]): - community.lastSeen[pubKey] = timestamp + if not community.members.contains(statusUpdate.publicKey): continue + if community.memberStatus.haskey(statusUpdate.publicKey): + if statusUpdate.clock > community.memberStatus[statusUpdate.publicKey].clock: + community.memberStatus[statusUpdate.publicKey] = statusUpdate else: - community.lastSeen[pubKey] = timestamp + community.memberStatus[statusUpdate.publicKey] = statusUpdate break proc addChannelToCommunity*(self: CommunityList, communityId: string, chat: Chat) = @@ -209,7 +209,7 @@ QtObject: let topLeft = self.createIndex(index, index, nil) let bottomRight = self.createIndex(index, index, nil) var oldCommunity = self.communities[index] - community.lastSeen = oldCommunity.lastSeen + community.memberStatus = oldCommunity.memberStatus self.communities[index] = community self.dataChanged(topLeft, bottomRight, @[CommunityRoles.Name.int, CommunityRoles.Description.int, CommunityRoles.UnviewedMessagesCount.int, CommunityRoles.ThumbnailImage.int]) diff --git a/src/app/chat/views/messages.nim b/src/app/chat/views/messages.nim index 638412a369..92437a61f1 100644 --- a/src/app/chat/views/messages.nim +++ b/src/app/chat/views/messages.nim @@ -250,9 +250,7 @@ QtObject: if (channel == nil): channel = self.communities.getChannel(msg.chatId) if (channel == nil): - continue - else: - self.communities.updateMemberVisibility(channel.communityId, msg.fromAuthor, msg.timestamp) + continue if msg.chatId == self.channelView.activeChannel.id: discard self.status.chat.markMessagesSeen(msg.chatId, @[msg.id]) self.newMessagePushed() diff --git a/src/status/chat.nim b/src/status/chat.nim index e20c464d24..27f41e22c8 100644 --- a/src/status/chat.nim +++ b/src/status/chat.nim @@ -28,6 +28,7 @@ type communities*: seq[Community] communityMembershipRequests*: seq[CommunityMembershipRequest] activityCenterNotifications*: seq[ActivityCenterNotification] + statusUpdates*: seq[StatusUpdate] ChatIdArg* = ref object of Args chatId*: string @@ -89,7 +90,7 @@ proc newChatModel*(events: EventEmitter): ChatModel = proc delete*(self: ChatModel) = discard -proc update*(self: ChatModel, chats: seq[Chat], messages: seq[Message], emojiReactions: seq[Reaction], communities: seq[Community], communityMembershipRequests: seq[CommunityMembershipRequest], pinnedMessages: seq[Message], activityCenterNotifications: seq[ActivityCenterNotification]) = +proc update*(self: ChatModel, chats: seq[Chat], messages: seq[Message], emojiReactions: seq[Reaction], communities: seq[Community], communityMembershipRequests: seq[CommunityMembershipRequest], pinnedMessages: seq[Message], activityCenterNotifications: seq[ActivityCenterNotification], statusUpdates: seq[StatusUpdate]) = for chat in chats: self.channels[chat.id] = chat @@ -102,7 +103,7 @@ proc update*(self: ChatModel, chats: seq[Chat], messages: seq[Message], emojiRea if self.lastMessageTimestamps[chatId] > ts: self.lastMessageTimestamps[chatId] = ts - self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages,chats: chats, contacts: @[], emojiReactions: emojiReactions, communities: communities, communityMembershipRequests: communityMembershipRequests, pinnedMessages: pinnedMessages, activityCenterNotifications: activityCenterNotifications)) + self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages,chats: chats, contacts: @[], emojiReactions: emojiReactions, communities: communities, communityMembershipRequests: communityMembershipRequests, pinnedMessages: pinnedMessages, activityCenterNotifications: activityCenterNotifications, statusUpdates: statusUpdates)) proc hasChannel*(self: ChatModel, chatId: string): bool = self.channels.hasKey(chatId) diff --git a/src/status/chat/chat.nim b/src/status/chat/chat.nim index 1d63fe1c91..cce9b75747 100644 --- a/src/status/chat/chat.nim +++ b/src/status/chat/chat.nim @@ -107,6 +107,17 @@ type CommunityCategory* = object name*: string position*: int +type StatusUpdateType* {.pure.}= enum + Unknown = 0, + Online = 1, + DoNotDisturb = 2 + +type StatusUpdate* = object + publicKey*: string + statusType*: StatusUpdateType + clock*: int64 + text*: string + type Community* = object id*: string name*: string @@ -129,7 +140,7 @@ type Community* = object communityImage*: IdentityImage membershipRequests*: seq[CommunityMembershipRequest] communityColor*: string - lastSeen*: OrderedTable[string, string] + memberStatus*: OrderedTable[string, StatusUpdate] type ActivityCenterNotification* = ref object of RootObj id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat diff --git a/src/status/signals/messages.nim b/src/status/signals/messages.nim index 1216a20e52..e537df50d6 100644 --- a/src/status/signals/messages.nim +++ b/src/status/signals/messages.nim @@ -19,6 +19,8 @@ proc toMessage*(jsonMsg: JsonNode): Message proc toChat*(jsonChat: JsonNode): Chat +proc toStatusUpdate*(jsonStatusUpdate: JsonNode): StatusUpdate + proc toReaction*(jsonReaction: JsonNode): Reaction proc toCommunity*(jsonCommunity: JsonNode): Community @@ -52,6 +54,11 @@ proc fromEvent*(event: JsonNode): Signal = chat.mentionsCount.inc signal.chats.add(chat) + if event["event"]{"statusUpdates"} != nil: + for jsonStatusUpdate in event["event"]["statusUpdates"]: + var statusUpdate = jsonStatusUpdate.toStatusUpdate + signal.statusUpdates.add(statusUpdate) + if event["event"]{"installations"} != nil: for jsonInstallation in event["event"]["installations"]: signal.installations.add(jsonInstallation.toInstallation) @@ -196,6 +203,16 @@ proc toChat*(jsonChat: JsonNode): Chat = for jsonMember in jsonChat["membershipUpdateEvents"]: result.membershipUpdateEvents.add(jsonMember.toChatMembershipEvent) +proc toStatusUpdate*(jsonStatusUpdate: JsonNode): StatusUpdate = + let statusTypeInt = jsonStatusUpdate{"status-type"}.getInt + let statusType: StatusUpdateType = if statusTypeInt >= ord(low(StatusUpdateType)) or statusTypeInt <= ord(high(StatusUpdateType)): StatusUpdateType(statusTypeInt) else: StatusUpdateType.Unknown + result = StatusUpdate( + publicKey: jsonStatusUpdate{"public-key"}.getStr, + statusType: statusType, + clock: jsonStatusUpdate{"clock"}.getBiggestInt, + text: jsonStatusUpdate{"text"}.getStr + ) + proc toCommunity*(jsonCommunity: JsonNode): Community = result = Community( id: jsonCommunity{"id"}.getStr, @@ -217,7 +234,7 @@ proc toCommunity*(jsonCommunity: JsonNode): Community = communityImage: IdentityImage() ) - result.lastSeen = initOrderedTable[string, string]() + result.memberStatus = initOrderedTable[string, StatusUpdate]() if jsonCommunity.hasKey("images") and jsonCommunity["images"].kind != JNull: if jsonCommunity["images"].hasKey("thumbnail"): diff --git a/src/status/signals/types.nim b/src/status/signals/types.nim index 75f2e89886..6021a95bc8 100644 --- a/src/status/signals/types.nim +++ b/src/status/signals/types.nim @@ -37,6 +37,7 @@ type MessageSignal* = ref object of Signal communities*: seq[Community] membershipRequests*: seq[CommunityMembershipRequest] activityCenterNotification*: seq[ActivityCenterNotification] + statusUpdates*: seq[StatusUpdate] type CommunitySignal* = ref object of Signal community*: Community diff --git a/ui/app/AppLayouts/Chat/ChatColumn/User.qml b/ui/app/AppLayouts/Chat/ChatColumn/User.qml index f9154606b0..1e7cd47fa9 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/User.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/User.qml @@ -10,6 +10,7 @@ Item { property string name: "channelName" property string lastSeen: "" property string identicon + property int statusType: Constants.statusType_Online property bool hovered: false property bool enableMouseArea: true property var currentTime @@ -80,16 +81,16 @@ Item { width: 10 radius: 20 color: { - let lastSeenMinutesAgo = (currentTime - parseInt(lastSeen)) / 1000 / 60 + let lastSeenMinutesAgo = (currentTime/1000 - parseInt(lastSeen)) / 60 if (!chatsModel.isOnline) { return Style.current.darkGrey } if (isCurrentUser || lastSeenMinutesAgo < 5){ - return Style.current.green; + return statusType == Constants.statusType_DoNotDisturb ? Style.current.red : Style.current.green; } else if (lastSeenMinutesAgo < 20) { - return Style.current.orange + return statusType == Constants.statusType_DoNotDisturb ? Style.current.red : Style.current.orange; } return Style.current.darkGrey diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityUserList.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityUserList.qml index e159120ada..4441cde34e 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityUserList.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityUserList.qml @@ -42,11 +42,12 @@ Rectangle { property string nickname: appMain.getUserNickname(model.pubKey) publicKey: model.pubKey - name: !model.userName.endsWith(".eth") && !!nickname ? - nickname : Utils.removeStatusEns(model.userName) + name: chatsModel.communities.activeCommunity.memberLastSeen(model.pubKey) + "--" + ( !model.userName.endsWith(".eth") && !!nickname ? + nickname : Utils.removeStatusEns(model.userName)) identicon: model.identicon lastSeen: chatsModel.communities.activeCommunity.memberLastSeen(model.pubKey) currentTime: svRoot.currentTime + statusType: chatsModel.communities.activeCommunity.memberStatus(model.pubKey) } } } \ No newline at end of file diff --git a/ui/imports/Constants.qml b/ui/imports/Constants.qml index acace98129..994a785190 100644 --- a/ui/imports/Constants.qml +++ b/ui/imports/Constants.qml @@ -85,6 +85,10 @@ QtObject { readonly property string linux: "linux" readonly property string mac: "mac" + readonly property int statusType_Unknown: 0 + readonly property int statusType_Online: 1 + readonly property int statusType_DoNotDisturb: 2 + // Transaction states readonly property int addressRequested: 1 readonly property int declined: 2 diff --git a/vendor/status-go b/vendor/status-go index 003f384409..5b513bc791 160000 --- a/vendor/status-go +++ b/vendor/status-go @@ -1 +1 @@ -Subproject commit 003f384409b0c6471450543809e7aee568cce170 +Subproject commit 5b513bc791922a1aa3afdd02b16d2854e5d95296