feature(@desktop/chat) Enhance message context menu with mark as unread (#12879)
* chore: bump status-go * feature(@desktop/chat) Enhance message context menu with mark as unread fixes #10329 linked with PR #12879 - Adds capacity to mark a message as unread - Adds capacity to mark a message with mention as unread - Adds persistence to the marking of the message (change can be seen at after reboot) - Adds marking in right click contextual menu
This commit is contained in:
parent
fd638de880
commit
7a5e691c90
|
@ -111,6 +111,12 @@ proc init*(self: Controller) =
|
|||
return
|
||||
self.delegate.onUnpinMessage(args.messageId)
|
||||
|
||||
self.events.on(SIGNAL_MESSAGE_MARKED_AS_UNREAD) do(e:Args):
|
||||
let args = MessageMarkMessageAsUnreadArgs(e)
|
||||
if (self.chatId != args.chatId):
|
||||
return
|
||||
self.delegate.onMarkMessageAsUnread(args.messageId)
|
||||
|
||||
self.events.on(SIGNAL_MESSAGE_REACTION_ADDED) do(e:Args):
|
||||
let args = MessageAddRemoveReactionArgs(e)
|
||||
if(self.chatId != args.chatId):
|
||||
|
@ -267,6 +273,9 @@ proc removeReaction*(self: Controller, messageId: string, emojiId: int, reaction
|
|||
proc pinUnpinMessage*(self: Controller, messageId: string, pin: bool) =
|
||||
self.messageService.pinUnpinMessage(self.chatId, messageId, pin)
|
||||
|
||||
proc markMessageAsUnread*(self: Controller, messageId: string) =
|
||||
self.messageService.asyncMarkMessageAsUnread(self.chatId, messageId)
|
||||
|
||||
proc getContactById*(self: Controller, contactId: string): ContactsDto =
|
||||
return self.contactService.getContactById(contactId)
|
||||
|
||||
|
|
|
@ -48,6 +48,12 @@ method onPinMessage*(self: AccessInterface, messageId: string, actionInitiatedBy
|
|||
method onUnpinMessage*(self: AccessInterface, messageId: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markMessageAsUnread*(self: AccessInterface, messageId: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onMarkMessageAsUnread*(self: AccessInterface, messageId: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method messagesAdded*(self: AccessInterface, messages: seq[MessageDto]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -510,12 +510,18 @@ method toggleReactionFromOthers*(self: Module, messageId: string, emojiId: int,
|
|||
method pinUnpinMessage*(self: Module, messageId: string, pin: bool) =
|
||||
self.controller.pinUnpinMessage(messageId, pin)
|
||||
|
||||
method markMessageAsUnread*(self: Module, messageId: string) =
|
||||
self.controller.markMessageAsUnread(messageId)
|
||||
|
||||
method onPinMessage*(self: Module, messageId: string, actionInitiatedBy: string) =
|
||||
self.view.model().pinUnpinMessage(messageId, true, actionInitiatedBy)
|
||||
|
||||
method onUnpinMessage*(self: Module, messageId: string) =
|
||||
self.view.model().pinUnpinMessage(messageId, false, "")
|
||||
|
||||
method onMarkMessageAsUnread*(self: Module, messageId: string) =
|
||||
self.view.model().markMessageAsUnread(messageId)
|
||||
|
||||
method getSectionId*(self: Module): string =
|
||||
return self.controller.getMySectionId()
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ QtObject:
|
|||
chatIcon: string
|
||||
chatType: int
|
||||
loading: bool
|
||||
keepUnread: bool
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.model.delete
|
||||
|
@ -36,6 +37,7 @@ QtObject:
|
|||
result.chatIcon = ""
|
||||
result.chatType = ChatType.Unknown.int
|
||||
result.loading = false
|
||||
result.keepUnread = false
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
@ -57,6 +59,25 @@ QtObject:
|
|||
proc unpinMessage*(self: View, messageId: string) {.slot.} =
|
||||
self.delegate.pinUnpinMessage(messageId, false)
|
||||
|
||||
proc keepUnreadChanged*(self: View) {.signal.}
|
||||
proc getKeepUnread*(self: View): bool {.slot.} =
|
||||
return self.keepUnread
|
||||
|
||||
QtProperty[bool] keepUnread:
|
||||
read = getKeepUnread
|
||||
notify = keepUnreadChanged
|
||||
|
||||
proc setKeepUnread*(self: View, value: bool) =
|
||||
self.keepUnread = value
|
||||
self.keepUnreadChanged()
|
||||
|
||||
proc markMessageAsUnread*(self: View, messageId: string) {.slot.} =
|
||||
self.delegate.markMessageAsUnread(messageId)
|
||||
self.setKeepUnread(true)
|
||||
|
||||
proc updateKeepUnread*(self: View, flag: bool) {.slot.} =
|
||||
self.setKeepUnread(flag)
|
||||
|
||||
proc getMessageByIdAsJson*(self: View, messageId: string): string {.slot.} =
|
||||
let jsonObj = self.model.getMessageByIdAsJson(messageId)
|
||||
if(jsonObj.isNil):
|
||||
|
|
|
@ -135,6 +135,12 @@ proc init*(self: Controller) =
|
|||
self.chatService.updateUnreadMessagesAndMentions(args.chatId, args.allMessagesMarked, args.messagesCount, args.messagesWithMentionsCount)
|
||||
self.delegate.onMarkAllMessagesRead(chat)
|
||||
|
||||
self.events.on(message_service.SIGNAL_MESSAGE_MARKED_AS_UNREAD) do(e:Args):
|
||||
let args = message_service.MessageMarkMessageAsUnreadArgs(e)
|
||||
let chat = self.chatService.getChatById(args.chatId)
|
||||
self.delegate.onMarkMessageAsUnread(chat)
|
||||
|
||||
|
||||
self.events.on(chat_service.SIGNAL_CHAT_LEFT) do(e: Args):
|
||||
let args = chat_service.ChatArgs(e)
|
||||
self.delegate.onCommunityChannelDeletedOrChatLeft(args.chatId)
|
||||
|
|
|
@ -94,6 +94,9 @@ method changeMutedOnChat*(self: AccessInterface, chatId: string, muted: bool) {.
|
|||
method onMarkAllMessagesRead*(self: AccessInterface, chat: ChatDto) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onMarkMessageAsUnread*(self: AccessInterface, chat: ChatDto) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onCommunityMuted*(self: AccessInterface, chatId: string, muted: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -899,6 +899,9 @@ method onJoinedCommunity*(self: Module) =
|
|||
method onMarkAllMessagesRead*(self: Module, chat: ChatDto) =
|
||||
self.updateBadgeNotifications(chat, hasUnreadMessages=false, unviewedMentionsCount=0)
|
||||
|
||||
method onMarkMessageAsUnread*(self: Module, chat: ChatDto) =
|
||||
self.updateBadgeNotifications(chat, hasUnreadMessages=true, chat.unviewedMentionsCount)
|
||||
|
||||
method markAllMessagesRead*(self: Module, chatId: string) =
|
||||
self.controller.markAllMessagesRead(chatId)
|
||||
|
||||
|
|
|
@ -784,6 +784,24 @@ QtObject:
|
|||
defer: index.delete
|
||||
self.dataChanged(index, index, @[ModelRole.Seen.int])
|
||||
|
||||
proc setMessageMarker*(self: Model, messageId: string) =
|
||||
self.firstUnseenMessageId = messageId
|
||||
self.resetNewMessagesMarker()
|
||||
|
||||
proc markMessageAsUnread*(self: Model, messageId: string) =
|
||||
self.setMessageMarker(messageId)
|
||||
|
||||
for i in 0 ..< self.items.len:
|
||||
let item = self.items[i]
|
||||
|
||||
if item.id == messageId and item.seen:
|
||||
item.seen = false
|
||||
let index = self.createIndex(i, 0, nil)
|
||||
defer: index.delete
|
||||
self.dataChanged(index, index, @[ModelRole.Seen.int])
|
||||
break
|
||||
|
||||
|
||||
proc markAsSeen*(self: Model, messages: seq[string]) =
|
||||
var messagesSet = toHashSet(messages)
|
||||
|
||||
|
|
|
@ -763,6 +763,15 @@ QtObject:
|
|||
except Exception as e:
|
||||
error "error while getting members", msg = e.msg, communityID, chatId
|
||||
|
||||
proc updateUnreadMessage*(self: Service, chatID: string, messagesCount:int, messagesWithMentionsCount:int) =
|
||||
var chat = self.getChatById(chatID)
|
||||
if chat.id == "":
|
||||
return
|
||||
|
||||
chat.unviewedMessagesCount = messagesCount
|
||||
chat.unviewedMentionsCount = messagesWithMentionsCount
|
||||
self.updateOrAddChat(chat)
|
||||
|
||||
proc updateUnreadMessagesAndMentions*(self: Service, chatID: string, markAllAsRead: bool, markAsReadCount: int, markAsReadMentionsCount: int) =
|
||||
var chat = self.getChatById(chatID)
|
||||
if chat.id == "":
|
||||
|
|
|
@ -126,14 +126,16 @@ const asyncMarkAllMessagesReadTask: Task = proc(argEncoded: string) {.gcsafe, ni
|
|||
let response = status_go.markAllMessagesFromChatWithIdAsRead(arg.chatId)
|
||||
|
||||
var activityCenterNotifications: JsonNode
|
||||
if response.result["activityCenterNotifications"] != nil:
|
||||
activityCenterNotifications = response.result["activityCenterNotifications"]
|
||||
discard response.result.getProp("activityCenterNotifications", activityCenterNotifications)
|
||||
|
||||
let responseJson = %*{
|
||||
"chatId": arg.chatId,
|
||||
"activityCenterNotifications": activityCenterNotifications,
|
||||
"error": response.error
|
||||
}
|
||||
|
||||
if activityCenterNotifications != nil:
|
||||
responseJson["activityCenterNotifications"] = activityCenterNotifications
|
||||
|
||||
arg.finish(responseJson)
|
||||
#################################################
|
||||
|
||||
|
@ -157,8 +159,7 @@ const asyncMarkCertainMessagesReadTask: Task = proc(argEncoded: string) {.gcsafe
|
|||
discard response.result.getProp("countWithMentions", countWithMentions)
|
||||
|
||||
var activityCenterNotifications: JsonNode
|
||||
if response.result["activityCenterNotifications"] != nil:
|
||||
activityCenterNotifications = response.result["activityCenterNotifications"]
|
||||
discard response.result.getProp("activityCenterNotifications", activityCenterNotifications)
|
||||
|
||||
var error = ""
|
||||
if(count == 0):
|
||||
|
@ -169,9 +170,12 @@ const asyncMarkCertainMessagesReadTask: Task = proc(argEncoded: string) {.gcsafe
|
|||
"messagesIds": arg.messagesIds,
|
||||
"count": count,
|
||||
"countWithMentions": countWithMentions,
|
||||
"activityCenterNotifications": activityCenterNotifications,
|
||||
"error": error
|
||||
}
|
||||
|
||||
if activityCenterNotifications != nil:
|
||||
responseJson["activityCenterNotifications"] = activityCenterNotifications
|
||||
|
||||
arg.finish(responseJson)
|
||||
|
||||
|
||||
|
@ -295,3 +299,43 @@ const asyncGetMessageByMessageIdTask: Task = proc(argEncoded: string) {.gcsafe,
|
|||
}
|
||||
arg.finish(output)
|
||||
|
||||
#################################################
|
||||
# Async mark message as unread
|
||||
#################################################
|
||||
|
||||
type
|
||||
AsyncMarkMessageAsUnreadTaskArg = ref object of QObjectTaskArg
|
||||
messageId*: string
|
||||
chatId*: string
|
||||
|
||||
const asyncMarkMessageAsUnreadTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[AsyncMarkMessageAsUnreadTaskArg](argEncoded)
|
||||
|
||||
var responseJson = %*{
|
||||
"chatId": arg.chatId,
|
||||
"messageId": arg.messageId,
|
||||
"messagesCount": 0,
|
||||
"messagesWithMentionsCount": 0,
|
||||
"error": ""
|
||||
}
|
||||
|
||||
try:
|
||||
let response = status_go.markMessageAsUnread(arg.chatId, arg.messageId)
|
||||
|
||||
var activityCenterNotifications: JsonNode
|
||||
discard response.result.getProp("activityCenterNotifications", activityCenterNotifications)
|
||||
|
||||
if activityCenterNotifications != nil:
|
||||
responseJson["activityCenterNotifications"] = activityCenterNotifications
|
||||
|
||||
responseJson["messagesCount"] = %response.result["count"]
|
||||
responseJson["messagesWithMentionsCount"] = %response.result["countWithMentions"]
|
||||
|
||||
if response.error != nil:
|
||||
responseJson["error"] = %response.error
|
||||
|
||||
except Exception as e:
|
||||
error "asyncMarkMessageAsUnreadTask failed", message = e.msg
|
||||
responseJson["error"] = %e.msg
|
||||
|
||||
arg.finish(responseJson)
|
|
@ -63,6 +63,7 @@ const SIGNAL_RELOAD_MESSAGES* = "reloadMessages"
|
|||
const SIGNAL_URLS_UNFURLED* = "urlsUnfurled"
|
||||
const SIGNAL_GET_MESSAGE_FINISHED* = "getMessageFinished"
|
||||
const SIGNAL_URLS_UNFURLING_PLAN_READY* = "urlsUnfurlingPlanReady"
|
||||
const SIGNAL_MESSAGE_MARKED_AS_UNREAD* = "messageMarkedAsUnread"
|
||||
|
||||
include async_tasks
|
||||
|
||||
|
@ -90,6 +91,12 @@ type
|
|||
messageId*: string
|
||||
actionInitiatedBy*: string
|
||||
|
||||
MessageMarkMessageAsUnreadArgs* = ref object of Args
|
||||
chatId*: string
|
||||
messageId*: string
|
||||
messagesCount*: int
|
||||
messagesWithMentionsCount*: int
|
||||
|
||||
MessagesMarkedAsReadArgs* = ref object of Args
|
||||
chatId*: string
|
||||
allMessagesMarked*: bool
|
||||
|
@ -581,6 +588,20 @@ QtObject:
|
|||
except Exception as e:
|
||||
error "error: ", procName="pinUnpinMessage", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc asyncMarkMessageAsUnread*(self: Service, chatId: string, messageId: string) =
|
||||
if (chatId.len == 0):
|
||||
error "empty chat id", procName="markAllMessagesRead"
|
||||
return
|
||||
|
||||
let arg = AsyncMarkMessageAsUnreadTaskArg(
|
||||
tptr: cast[ByteAddress](asyncMarkMessageAsUnreadTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onAsyncMarkMessageAsUnread",
|
||||
messageId: messageId,
|
||||
chatId: chatId
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc getMessageByMessageId*(self: Service, messageId: string): GetMessageResult =
|
||||
try:
|
||||
result = GetMessageResult()
|
||||
|
@ -723,8 +744,13 @@ QtObject:
|
|||
|
||||
let data = MessagesMarkedAsReadArgs(chatId: chatId, allMessagesMarked: true)
|
||||
self.events.emit(SIGNAL_MESSAGES_MARKED_AS_READ, data)
|
||||
self.events.emit(SIGNAL_PARSE_RAW_ACTIVITY_CENTER_NOTIFICATIONS,
|
||||
RawActivityCenterNotificationsArgs(activityCenterNotifications: responseObj{"activityCenterNotifications"}))
|
||||
|
||||
var activityCenterNotifications: JsonNode
|
||||
discard responseObj.getProp("activityCenterNotifications", activityCenterNotifications)
|
||||
|
||||
if activityCenterNotifications != nil:
|
||||
self.events.emit(SIGNAL_PARSE_RAW_ACTIVITY_CENTER_NOTIFICATIONS,
|
||||
RawActivityCenterNotificationsArgs(activityCenterNotifications: activityCenterNotifications))
|
||||
|
||||
proc markAllMessagesRead*(self: Service, chatId: string) =
|
||||
if (chatId.len == 0):
|
||||
|
@ -740,6 +766,49 @@ QtObject:
|
|||
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc onAsyncMarkMessageAsUnread*(self: Service, response: string) {.slot.} =
|
||||
try:
|
||||
let responseObj = response.parseJson
|
||||
|
||||
if responseObj.kind != JObject:
|
||||
raise newException(RpcException, "markMessageAsUnread response is not a json object")
|
||||
|
||||
var error: string
|
||||
discard responseObj.getProp("error", error)
|
||||
|
||||
if error.len > 0:
|
||||
error "error: ", procName="onAsyncMarkMessageAsUnread", errDescription=error
|
||||
return
|
||||
|
||||
var chatId, messageId: string
|
||||
var count, countWithMentions: int
|
||||
|
||||
discard responseObj.getProp("chatId", chatId)
|
||||
discard responseObj.getProp("messageId", messageId)
|
||||
discard responseObj.getProp("messagesCount", count)
|
||||
discard responseObj.getProp("messagesWithMentionsCount", countWithMentions)
|
||||
|
||||
let data = MessageMarkMessageAsUnreadArgs(
|
||||
chatId: chatId,
|
||||
messageId: messageId,
|
||||
messagesCount: count,
|
||||
messagesWithMentionsCount: countWithMentions
|
||||
)
|
||||
|
||||
self.chatService.updateUnreadMessage(chatId, count, countWithMentions)
|
||||
|
||||
self.events.emit(SIGNAL_MESSAGE_MARKED_AS_UNREAD, data)
|
||||
|
||||
var activityCenterNotifications: JsonNode
|
||||
discard responseObj.getProp("activityCenterNotifications", activityCenterNotifications)
|
||||
|
||||
if activityCenterNotifications != nil:
|
||||
self.events.emit(SIGNAL_PARSE_RAW_ACTIVITY_CENTER_NOTIFICATIONS,
|
||||
RawActivityCenterNotificationsArgs(activityCenterNotifications: activityCenterNotifications))
|
||||
|
||||
except Exception as e:
|
||||
error "error: ", procName="markMessageAsUnread", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc onMarkCertainMessagesRead*(self: Service, response: string) {.slot.} =
|
||||
let responseObj = response.parseJson
|
||||
|
||||
|
@ -774,8 +843,13 @@ QtObject:
|
|||
messagesCount: count,
|
||||
messagesWithMentionsCount: countWithMentions)
|
||||
self.events.emit(SIGNAL_MESSAGES_MARKED_AS_READ, data)
|
||||
self.events.emit(SIGNAL_PARSE_RAW_ACTIVITY_CENTER_NOTIFICATIONS,
|
||||
RawActivityCenterNotificationsArgs(activityCenterNotifications: responseObj{"activityCenterNotifications"}))
|
||||
|
||||
var activityCenterNotifications: JsonNode
|
||||
discard responseObj.getProp("activityCenterNotifications", activityCenterNotifications)
|
||||
|
||||
if activityCenterNotifications != nil:
|
||||
self.events.emit(SIGNAL_PARSE_RAW_ACTIVITY_CENTER_NOTIFICATIONS,
|
||||
RawActivityCenterNotificationsArgs(activityCenterNotifications: activityCenterNotifications))
|
||||
|
||||
proc markCertainMessagesRead*(self: Service, chatId: string, messagesIds: seq[string]) =
|
||||
if (chatId.len == 0):
|
||||
|
|
|
@ -32,6 +32,10 @@ proc pinUnpinMessage*(chatId: string, messageId: string, pin: bool): RpcResponse
|
|||
}]
|
||||
result = callPrivateRPC("sendPinMessage".prefix, payload)
|
||||
|
||||
proc markMessageAsUnread*(chatId: string, messageId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %*[chatId, messageId]
|
||||
result = callPrivateRPC("markMessageAsUnread".prefix, payload)
|
||||
|
||||
proc getMessageByMessageId*(messageId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [messageId]
|
||||
result = callPrivateRPC("messageByMessageID".prefix, payload)
|
||||
|
|
|
@ -352,3 +352,66 @@ suite "mark as seen":
|
|||
check(model.items[0].seen == true)
|
||||
check(model.items[1].seen == true)
|
||||
check(model.items[2].seen == true)
|
||||
|
||||
suite "mark message as unread":
|
||||
setup:
|
||||
let model = newModel()
|
||||
|
||||
var msg1 = createTestMessageItem("0xa", 1)
|
||||
msg1.seen = true
|
||||
var msg2 = createTestMessageItem("0xb", 2)
|
||||
msg2.seen = true
|
||||
var msg3 = createTestMessageItem("0xc", 3)
|
||||
msg3.seen = true
|
||||
|
||||
model.insertItemsBasedOnClock(@[msg1, msg2, msg3])
|
||||
require(model.items.len == 3)
|
||||
check(model.items[0].seen == true)
|
||||
check(model.items[1].seen == true)
|
||||
check(model.items[2].seen == true)
|
||||
|
||||
test "mark message as unread":
|
||||
model.markMessageAsUnread("0xa")
|
||||
check(model.items[2].seen == false)
|
||||
|
||||
model.markMessageAsUnread("0xb")
|
||||
check(model.items[1].seen == false)
|
||||
|
||||
model.markMessageAsUnread("0xc")
|
||||
check(model.items[0].seen == false)
|
||||
|
||||
test "mark an already unread message as unread":
|
||||
model.markMessageAsUnread("0xa")
|
||||
check(model.items[2].seen == false)
|
||||
model.markMessageAsUnread("0xa")
|
||||
check(model.items[2].seen == false)
|
||||
|
||||
model.markMessageAsUnread("0xb")
|
||||
check(model.items[1].seen == false)
|
||||
model.markMessageAsUnread("0xb")
|
||||
check(model.items[1].seen == false)
|
||||
|
||||
model.markMessageAsUnread("0xc")
|
||||
check(model.items[0].seen == false)
|
||||
model.markMessageAsUnread("0xc")
|
||||
check(model.items[0].seen == false)
|
||||
|
||||
test "mark all messages as unread":
|
||||
require(model.items.len == 3)
|
||||
|
||||
model.markMessageAsUnread("0xa")
|
||||
model.markMessageAsUnread("0xc")
|
||||
model.markMessageAsUnread("0xb")
|
||||
|
||||
|
||||
# Because new row is inserted for message marker
|
||||
require(model.items.len == 4)
|
||||
|
||||
check(model.items[0].seen == false)
|
||||
check(model.items[1].seen == false)
|
||||
|
||||
# message marker is inserted on top of the last inserted element
|
||||
# last inserted element is `0xc` which is at position 0
|
||||
# and marker is insert last at position : position('0xb') - 1 equals to position 2 here
|
||||
check(model.items[2].seen == true)
|
||||
check(model.items[3].seen == false)
|
|
@ -19,6 +19,7 @@ QtObject {
|
|||
readonly property int chatType: messageModule ? messageModule.chatType : Constants.chatType.unknown
|
||||
readonly property string chatColor: messageModule ? messageModule.chatColor : Style.current.blue
|
||||
readonly property string chatIcon: messageModule ? messageModule.chatIcon : ""
|
||||
readonly property bool keepUnread: messageModule ? messageModule.keepUnread : false
|
||||
|
||||
onMessageModuleChanged: {
|
||||
if(!messageModule)
|
||||
|
@ -36,6 +37,14 @@ QtObject {
|
|||
messageModule.loadMoreMessages()
|
||||
}
|
||||
|
||||
function setKeepUnread(flag: bool) {
|
||||
if (!messageModule) {
|
||||
return
|
||||
}
|
||||
|
||||
messageModule.updateKeepUnread(flag)
|
||||
}
|
||||
|
||||
function getMessageByIdAsJson (id) {
|
||||
if (!messageModule) {
|
||||
console.warn("getMessageByIdAsJson: Failed to parse message, because messageModule is not set")
|
||||
|
@ -124,6 +133,13 @@ QtObject {
|
|||
messageModule.deleteMessage(messageId)
|
||||
}
|
||||
|
||||
function markMessageAsUnread(messageId) {
|
||||
if (!messageModule) {
|
||||
return
|
||||
}
|
||||
messageModule.markMessageAsUnread(messageId)
|
||||
}
|
||||
|
||||
function warnAndDeleteMessage(messageId) {
|
||||
if (localAccountSensitiveSettings.showDeleteMessageWarning)
|
||||
Global.openDeleteMessagePopup(messageId, this)
|
||||
|
|
|
@ -52,13 +52,18 @@ Item {
|
|||
readonly property real scrollY: chatLogView.visibleArea.yPosition * chatLogView.contentHeight
|
||||
readonly property bool isMostRecentMessageInViewport: chatLogView.visibleArea.yPosition >= 0.999 - chatLogView.visibleArea.heightRatio
|
||||
readonly property var chatDetails: chatContentModule && chatContentModule.chatDetails || null
|
||||
readonly property bool keepUnread: messageStore.keepUnread
|
||||
|
||||
readonly property var loadMoreMessagesIfScrollBelowThreshold: Backpressure.oneInTimeQueued(root, 100, function() {
|
||||
if(scrollY < 1000) messageStore.loadMoreMessages()
|
||||
})
|
||||
|
||||
function setKeepUnread(flag: bool) {
|
||||
root.messageStore.setKeepUnread(flag)
|
||||
}
|
||||
|
||||
function markAllMessagesReadIfMostRecentMessageIsInViewport() {
|
||||
if (!isMostRecentMessageInViewport || !chatLogView.visible) {
|
||||
if (!isMostRecentMessageInViewport || !chatLogView.visible || keepUnread) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -107,6 +112,7 @@ Item {
|
|||
target: !!d.chatDetails ? d.chatDetails : null
|
||||
|
||||
function onActiveChanged() {
|
||||
d.setKeepUnread(false)
|
||||
d.markAllMessagesReadIfMostRecentMessageIsInViewport()
|
||||
d.loadMoreMessagesIfScrollBelowThreshold()
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ StatusMenu {
|
|||
signal toggleReaction(string messageId, int emojiId)
|
||||
signal deleteMessage(string messageId)
|
||||
signal editClicked(string messageId)
|
||||
signal markMessageAsUnread(string messageId)
|
||||
|
||||
width: Math.max(emojiContainer.visible ? emojiContainer.width : 0, 230)
|
||||
|
||||
|
@ -153,6 +154,17 @@ StatusMenu {
|
|||
}
|
||||
}
|
||||
|
||||
StatusAction {
|
||||
id: markMessageAsUnreadAction
|
||||
text: qsTr("Mark as unread")
|
||||
icon.name: "hide"
|
||||
enabled: !root.disabledForChat
|
||||
onTriggered: {
|
||||
root.markMessageAsUnread(root.messageId)
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
|
||||
StatusMenuSeparator {
|
||||
visible: deleteMessageAction.enabled &&
|
||||
(replyToMenuItem.enabled ||
|
||||
|
|
|
@ -980,6 +980,21 @@ Loader {
|
|||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: !root.editModeOn && delegate.hovered && !delegate.hideQuickActions
|
||||
visible: active
|
||||
sourceComponent: StatusFlatRoundButton {
|
||||
objectName: "markAsUnreadButton"
|
||||
width: d.chatButtonSize
|
||||
height: d.chatButtonSize
|
||||
icon.name: "hide"
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
tooltip.text: qsTr("Mark as unread")
|
||||
onClicked: {
|
||||
root.messageStore.markMessageAsUnread(root.messageId)
|
||||
}
|
||||
}
|
||||
},
|
||||
Loader {
|
||||
active: {
|
||||
if(!delegate.hovered)
|
||||
|
@ -1102,6 +1117,10 @@ Loader {
|
|||
root.chatId)
|
||||
}
|
||||
|
||||
onMarkMessageAsUnread: (messageId) => {
|
||||
root.messageStore.markMessageAsUnread(messageId)
|
||||
}
|
||||
|
||||
onToggleReaction: (messageId, emojiId) => {
|
||||
root.messageStore.toggleReaction(messageId, emojiId)
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit fe604b2806dfa51ea748c5e61c2a87cc7ffd9c4a
|
||||
Subproject commit 271778a1e07e585a12790b4e2226f13e36ea89f4
|
Loading…
Reference in New Issue