feat: allow users to mute and unmute channels

Closes #152
This commit is contained in:
Pascal Precht 2020-08-18 17:31:54 +02:00 committed by Iuri Matias
parent 3dac87df3d
commit ef22fb348d
8 changed files with 123 additions and 24 deletions

View File

@ -248,7 +248,8 @@ QtObject:
if self.channelOpenTime.getOrDefault(msg.chatId, high(int64)) < msg.timestamp.parseFloat.fromUnixFloat.toUnix: if self.channelOpenTime.getOrDefault(msg.chatId, high(int64)) < msg.timestamp.parseFloat.fromUnixFloat.toUnix:
if msg.chatId != self.activeChannel.id: if msg.chatId != self.activeChannel.id:
let channel = self.chats.getChannelById(msg.chatId) let channel = self.chats.getChannelById(msg.chatId)
self.messageNotificationPushed(msg.chatId, msg.text, msg.messageType, channel.chatType.int, msg.timestamp, msg.identicon, msg.alias) if not channel.muted:
self.messageNotificationPushed(msg.chatId, msg.text, msg.messageType, channel.chatType.int, msg.timestamp, msg.identicon, msg.alias)
else: else:
self.newMessagePushed() self.newMessagePushed()
@ -416,3 +417,26 @@ QtObject:
QtProperty[bool] isOnline: QtProperty[bool] isOnline:
read = isConnected read = isConnected
notify = onlineStatusChanged notify = onlineStatusChanged
proc muteChannel*(self: ChatsView, channelIndex: int) {.slot.} =
if (self.chats.chats.len == 0): return
let selectedChannel = self.chats.getChannel(channelIndex)
if (selectedChannel == nil): return
self.status.chat.muteChat(selectedChannel.id)
selectedChannel.muted = true
self.chats.updateChat(selectedChannel, false)
proc unmuteChannel*(self: ChatsView, channelIndex: int) {.slot.} =
if (self.chats.chats.len == 0): return
let selectedChannel = self.chats.getChannel(channelIndex)
if (selectedChannel == nil): return
self.status.chat.unmuteChat(selectedChannel.id)
selectedChannel.muted = false
self.chats.updateChat(selectedChannel, false)
proc channelIsMuted*(self: ChatsView, channelIndex: int): bool {.slot.} =
if (self.chats.chats.len == 0): return false
let selectedChannel = self.chats.getChannel(channelIndex)
if (selectedChannel == nil): return false
result = selectedChannel.muted

View File

@ -15,6 +15,7 @@ type
Color = UserRole + 7 Color = UserRole + 7
HasMentions = UserRole + 8 HasMentions = UserRole + 8
ContentType = UserRole + 9 ContentType = UserRole + 9
Muted = UserRole + 10
QtObject: QtObject:
type type
@ -66,6 +67,7 @@ QtObject:
of ChannelsRoles.ChatType: result = newQVariant(chatItem.chatType.int) of ChannelsRoles.ChatType: result = newQVariant(chatItem.chatType.int)
of ChannelsRoles.Color: result = newQVariant(chatItem.color) of ChannelsRoles.Color: result = newQVariant(chatItem.color)
of ChannelsRoles.HasMentions: result = newQVariant(chatItem.hasMentions) of ChannelsRoles.HasMentions: result = newQVariant(chatItem.hasMentions)
of ChannelsRoles.Muted: result = newQVariant(chatItem.muted.bool)
method roleNames(self: ChannelsList): Table[int, string] = method roleNames(self: ChannelsList): Table[int, string] =
{ {
@ -77,7 +79,8 @@ QtObject:
ChannelsRoles.ChatType.int: "chatType", ChannelsRoles.ChatType.int: "chatType",
ChannelsRoles.Color.int: "color", ChannelsRoles.Color.int: "color",
ChannelsRoles.HasMentions.int: "hasMentions", ChannelsRoles.HasMentions.int: "hasMentions",
ChannelsRoles.ContentType.int: "contentType" ChannelsRoles.ContentType.int: "contentType",
ChannelsRoles.Muted.int: "muted"
}.toTable }.toTable
proc addChatItemToList*(self: ChannelsList, channel: Chat): int = proc addChatItemToList*(self: ChannelsList, channel: Chat): int =
@ -137,7 +140,7 @@ QtObject:
else: else:
self.chats[0] = channel self.chats[0] = channel
self.dataChanged(topLeft, bottomRight, @[ChannelsRoles.Name.int, ChannelsRoles.ContentType.int, ChannelsRoles.LastMessage.int, ChannelsRoles.Timestamp.int, ChannelsRoles.UnreadMessages.int, ChannelsRoles.Identicon.int, ChannelsRoles.ChatType.int, ChannelsRoles.Color.int, ChannelsRoles.HasMentions.int]) self.dataChanged(topLeft, bottomRight, @[ChannelsRoles.Name.int, ChannelsRoles.ContentType.int, ChannelsRoles.LastMessage.int, ChannelsRoles.Timestamp.int, ChannelsRoles.UnreadMessages.int, ChannelsRoles.Identicon.int, ChannelsRoles.ChatType.int, ChannelsRoles.Color.int, ChannelsRoles.HasMentions.int, ChannelsRoles.Muted.int])
proc clearUnreadMessagesCount*(self: ChannelsList, channel: var Chat) = proc clearUnreadMessagesCount*(self: ChannelsList, channel: var Chat) =
let idx = self.chats.findIndexById(channel.id) let idx = self.chats.findIndexById(channel.id)
@ -149,7 +152,7 @@ QtObject:
channel.hasMentions = false channel.hasMentions = false
self.chats[idx] = channel self.chats[idx] = channel
self.dataChanged(topLeft, bottomRight, @[ChannelsRoles.Name.int, ChannelsRoles.ContentType.int, ChannelsRoles.LastMessage.int, ChannelsRoles.Timestamp.int, ChannelsRoles.UnreadMessages.int, ChannelsRoles.Identicon.int, ChannelsRoles.ChatType.int, ChannelsRoles.Color.int, ChannelsRoles.HasMentions.int]) self.dataChanged(topLeft, bottomRight, @[ChannelsRoles.Name.int, ChannelsRoles.ContentType.int, ChannelsRoles.LastMessage.int, ChannelsRoles.Timestamp.int, ChannelsRoles.UnreadMessages.int, ChannelsRoles.Identicon.int, ChannelsRoles.ChatType.int, ChannelsRoles.Color.int, ChannelsRoles.HasMentions.int, ChannelsRoles.Muted.int])
proc renderInline(self: ChannelsList, elem: TextItem): string = proc renderInline(self: ChannelsList, elem: TextItem): string =
case elem.textType: case elem.textType:

View File

@ -107,9 +107,13 @@ proc toChat*(jsonChat: JsonNode): Chat =
lastClockValue: jsonChat{"lastClockValue"}.getBiggestInt, lastClockValue: jsonChat{"lastClockValue"}.getBiggestInt,
deletedAtClockValue: jsonChat{"deletedAtClockValue"}.getBiggestInt, deletedAtClockValue: jsonChat{"deletedAtClockValue"}.getBiggestInt,
unviewedMessagesCount: jsonChat{"unviewedMessagesCount"}.getInt, unviewedMessagesCount: jsonChat{"unviewedMessagesCount"}.getInt,
hasMentions: false hasMentions: false,
muted: false
) )
if jsonChat.hasKey("muted") and jsonChat["muted"].kind != JNull:
result.muted = jsonChat["muted"].getBool
if jsonChat["lastMessage"].kind != JNull: if jsonChat["lastMessage"].kind != JNull:
result.lastMessage = jsonChat{"lastMessage"}.toMessage result.lastMessage = jsonChat{"lastMessage"}.toMessage

View File

@ -304,4 +304,10 @@ proc makeAdmin*(self: ChatModel, chatId: string, pubKey: string) =
self.emitUpdate(response) self.emitUpdate(response)
proc resendMessage*(self: ChatModel, messageId: string) = proc resendMessage*(self: ChatModel, messageId: string) =
discard status_chat.reSendChatMessage(messageId) discard status_chat.reSendChatMessage(messageId)
proc muteChat*(self: ChatModel, chatId: string) =
discard status_chat.muteChat(chatId)
proc unmuteChat*(self: ChatModel, chatId: string) =
discard status_chat.unmuteChat(chatId)

View File

@ -66,6 +66,7 @@ type Chat* = ref object
members*: seq[ChatMember] members*: seq[ChatMember]
membershipUpdateEvents*: seq[ChatMembershipEvent] membershipUpdateEvents*: seq[ChatMembershipEvent]
hasMentions*: bool hasMentions*: bool
muted*: bool
proc `$`*(self: Chat): string = proc `$`*(self: Chat): string =
result = fmt"Chat(id:{self.id}, name:{self.name}, active:{self.isActive}, type:{self.chatType})" result = fmt"Chat(id:{self.id}, name:{self.name}, active:{self.isActive}, type:{self.chatType})"

View File

@ -145,4 +145,10 @@ proc updateOutgoingMessageStatus*(messageId: string, status: string): string =
# TODO: handle errors # TODO: handle errors
proc reSendChatMessage*(messageId: string): string = proc reSendChatMessage*(messageId: string): string =
result = callPrivateRPC("reSendChatMessage".prefix, %*[messageId]) result = callPrivateRPC("reSendChatMessage".prefix, %*[messageId])
proc muteChat*(chatId: string): string =
result = callPrivateRPC("muteChat".prefix, %*[chatId])
proc unmuteChat*(chatId: string): string =
result = callPrivateRPC("unmuteChat".prefix, %*[chatId])

View File

@ -15,6 +15,7 @@ Rectangle {
property string searchStr: "" property string searchStr: ""
property bool isCompact: appSettings.compactMode property bool isCompact: appSettings.compactMode
property int contentType: 1 property int contentType: 1
property bool muted: false
id: wrapper id: wrapper
color: ListView.isCurrentItem ? Style.current.secondaryBackground : Style.current.transparent color: ListView.isCurrentItem ? Style.current.secondaryBackground : Style.current.transparent
@ -33,7 +34,7 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
if (mouse.button & Qt.RightButton) { if (mouse.button & Qt.RightButton) {
channelContextMenu.openMenu(index) channelContextMenu.openMenu(index, muted)
return; return;
} }
chatsModel.setActiveChannelByIndex(index) chatsModel.setActiveChannelByIndex(index)

View File

@ -25,6 +25,7 @@ ScrollView {
model: chatsModel.chats model: chatsModel.chats
delegate: Channel { delegate: Channel {
name: model.name name: model.name
muted: model.muted
lastMessage: model.lastMessage lastMessage: model.lastMessage
timestamp: model.timestamp timestamp: model.timestamp
chatType: model.chatType chatType: model.chatType
@ -52,15 +53,16 @@ ScrollView {
PopupMenu { PopupMenu {
property int channelIndex property int channelIndex
property bool channelMuted
id: channelContextMenu id: channelContextMenu
width: 175 width: 175
subMenuIcons: [ subMenuIcons: [
{ /* { */
source: Qt.resolvedUrl("../../../img/bell.svg"), /* source: Qt.resolvedUrl("../../../img/bell.svg"), */
width: 16, /* width: 16, */
height: 16 /* height: 16 */
}, /* }, */
{ {
source: Qt.resolvedUrl("../../../img/fetch.svg"), source: Qt.resolvedUrl("../../../img/fetch.svg"),
width: 16, width: 16,
@ -68,8 +70,9 @@ ScrollView {
} }
] ]
function openMenu(channelIndex) { function openMenu(channelIndex, muted) {
channelContextMenu.channelIndex = channelIndex channelContextMenu.channelIndex = channelIndex
channelContextMenu.channelMuted = muted
channelContextMenu.popup() channelContextMenu.popup()
} }
@ -83,17 +86,68 @@ ScrollView {
Separator {} Separator {}
PopupMenu { Action {
hasArrow: false text: channelContextMenu.channelMuted ?
title: qsTr("Mute Chat") qsTr("Unmute chat") :
qsTr("Mute chat")
// TODO implement mute chat in Model and call it here icon.source: "../../../img/bell.svg"
Action { text: qsTr("15 minutes"); icon.width: 0; } icon.width: 16
Action { text: qsTr("1 hour"); icon.width: 0; } icon.height: 16
Action { text: qsTr("8 hours"); icon.width: 0; } onTriggered: {
Action { text: qsTr("24 hours"); icon.width: 0; } if (chatsModel.channelIsMuted(channelContextMenu.channelIndex)) {
Action { text: qsTr("Until I turn it back on"); icon.width: 0; } chatsModel.unmuteChannel(channelContextMenu.channelIndex)
return
}
chatsModel.muteChannel(channelContextMenu.channelIndex)
}
} }
/* PopupMenu { */
/* hasArrow: false */
/* title: qstr("Mute chat") */
/* // TODO implement mute chat in Model and call it here */
/* Action { */
/* text: qsTr("15 minutes"); */
/* icon.width: 0; */
/* onTriggered: { */
/* chatsModel.muteChannel(channelContextMenu.channelIndex, Constants.muteChat15Minutes) */
/* } */
/* } */
/* Action { */
/* text: qsTr("1 hour"); */
/* icon.width: 0; */
/* onTriggered: { */
/* chatsModel.muteChannel(channelContextMenu.channelIndex, Constants.muteChatOneHour) */
/* } */
/* } */
/* Action { */
/* text: qsTr("8 hours"); */
/* icon.width: 0; */
/* onTriggered: { */
/* chatsModel.muteChannel(channelContextMenu.channelIndex, Constants.muteChatEightHours) */
/* } */
/* } */
/* Action { */
/* text: qsTr("24 hours"); */
/* icon.width: 0; */
/* onTriggered: { */
/* chatsModel.muteChannel(channelContextMenu.channelIndex, Constants.muteChat24Hours) */
/* } */
/* } */
/* Action { */
/* text: qsTr("Until I turn it back on"); */
/* icon.width: 0; */
/* onTriggered: { */
/* console.log(appSettings.mutedChannels) */
/* appSettings.mutedChannels.push({ */
/* name: "Foo" */
/* }) */
/* console.log(appSettings.mutedChannels) */
/* //chatsModel.muteChannel(channelContextMenu.channelIndex, Constants.muteChatUntilUnmuted) */
/* } */
/* } */
/* } */
Action { Action {
text: qsTr("Mark as Read") text: qsTr("Mark as Read")
icon.source: "../../../img/check-circle.svg" icon.source: "../../../img/check-circle.svg"