fix(@chat): display link urls

This commit is contained in:
Anthony Laibe 2022-01-25 13:56:53 +01:00 committed by Sale Djenic
parent 219d7b46c0
commit 16225a3af9
18 changed files with 154 additions and 56 deletions

View File

@ -89,7 +89,8 @@ method convertToItems*[T](
ContentType(n.message.contentType), ContentType(n.message.contentType),
n.message.messageType, n.message.messageType,
self.controller.decodeContentHash(n.message.sticker.hash), self.controller.decodeContentHash(n.message.sticker.hash),
n.message.sticker.pack n.message.sticker.pack,
n.message.links,
)) ))
return notification_item.initItem( return notification_item.initItem(

View File

@ -136,6 +136,10 @@ method init*(self: Controller) =
self.events.on(SignalType.HistoryRequestFailed.event) do(e:Args): self.events.on(SignalType.HistoryRequestFailed.event) do(e:Args):
self.delegate.setLoadingHistoryMessagesInProgress(false) self.delegate.setLoadingHistoryMessagesInProgress(false)
self.events.on(SIGNAL_MESSAGE_LINK_PREVIEW_DATA_LOADED) do(e: Args):
let args = LinkPreviewDataArgs(e)
self.delegate.onPreviewDataLoaded(args.response)
method getMySectionId*(self: Controller): string = method getMySectionId*(self: Controller): string =
return self.sectionId return self.sectionId
@ -190,3 +194,6 @@ method decodeContentHash*(self: Controller, hash: string): string =
method editMessage*(self: Controller, messageId: string, updatedMsg: string) = method editMessage*(self: Controller, messageId: string, updatedMsg: string) =
self.messageService.editMessage(messageId, updatedMsg) self.messageService.editMessage(messageId, updatedMsg)
method getLinkPreviewData*(self: Controller, link: string, uuid: string): string =
self.messageService.asyncGetLinkPreviewData(link, uuid)

View File

@ -63,9 +63,11 @@ method getMessageDetails*(self: AccessInterface, messageId: string):
method deleteMessage*(self: AccessInterface, messageId: string) {.base.} = method deleteMessage*(self: AccessInterface, messageId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method decodeContentHash*(self: AccessInterface, hash: string): string {.base.} = method decodeContentHash*(self: AccessInterface, hash: string): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method editMessage*(self: AccessInterface, messageId: string, updatedMsg: string) {.base.} = method editMessage*(self: AccessInterface, messageId: string, updatedMsg: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getLinkPreviewData*(self: AccessInterface, link: string, uuid: string): string {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -90,7 +90,8 @@ proc createChatIdentifierItem(self: Module): Item =
ContentType.ChatIdentifier, ContentType.ChatIdentifier,
messageType = -1, messageType = -1,
sticker = "", sticker = "",
stickerPack = -1 stickerPack = -1,
@[],
) )
method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: seq[ReactionDto], method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: seq[ReactionDto],
@ -120,7 +121,8 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
m.contentType.ContentType, m.contentType.ContentType,
m.messageType, m.messageType,
sticker = self.controller.decodeContentHash(m.sticker.hash), sticker = self.controller.decodeContentHash(m.sticker.hash),
m.sticker.pack m.sticker.pack,
m.links,
) )
for r in reactions: for r in reactions:
@ -177,7 +179,8 @@ method messageAdded*(self: Module, message: MessageDto) =
message.contentType.ContentType, message.contentType.ContentType,
message.messageType, message.messageType,
sticker = self.controller.decodeContentHash(message.sticker.hash), sticker = self.controller.decodeContentHash(message.sticker.hash),
message.sticker.pack message.sticker.pack,
message.links
) )
self.view.model().insertItemBasedOnTimestamp(item) self.view.model().insertItemBasedOnTimestamp(item)
@ -308,3 +311,9 @@ method updateChatIdentifier*(self: Module) =
method setLoadingHistoryMessagesInProgress*(self: Module, isLoading: bool) = method setLoadingHistoryMessagesInProgress*(self: Module, isLoading: bool) =
self.view.setLoadingHistoryMessagesInProgress(isLoading) self.view.setLoadingHistoryMessagesInProgress(isLoading)
method getLinkPreviewData*(self: Module, link: string, uuid: string): string =
return self.controller.getLinkPreviewData(link, uuid)
method onPreviewDataLoaded*(self: Module, previewData: string) =
self.view.onPreviewDataLoaded(previewData)

View File

@ -33,3 +33,9 @@ method editMessage*(self: AccessInterface, messageId: string, updatedMsg: string
method onHistoryCleared*(self: AccessInterface) {.base.} = method onHistoryCleared*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getLinkPreviewData*(self: AccessInterface, link: string, uuid: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method onPreviewDataLoaded*(self: AccessInterface, previewData: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -123,3 +123,11 @@ QtObject:
proc editMessage*(self: View, messageId: string, updatedMsg: string) {.slot.} = proc editMessage*(self: View, messageId: string, updatedMsg: string) {.slot.} =
self.delegate.editMessage(messageId, updatedMsg) self.delegate.editMessage(messageId, updatedMsg)
proc getLinkPreviewData*(self: View, link: string, uuid: string): string {.slot.} =
return self.delegate.getLinkPreviewData(link, uuid)
proc linkPreviewDataWasReceived*(self: View, previewData: string) {.signal.}
proc onPreviewDataLoaded*(self: View, previewData: string) {.slot.} =
self.linkPreviewDataWasReceived(previewData)

View File

@ -151,7 +151,8 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy:
m.contentType.ContentType, m.contentType.ContentType,
m.messageType, m.messageType,
self.controller.decodeContentHash(m.sticker.hash), self.controller.decodeContentHash(m.sticker.hash),
m.sticker.pack m.sticker.pack,
m.links,
) )
item.pinned = true item.pinned = true
item.pinnedBy = actionInitiatedBy item.pinnedBy = actionInitiatedBy

View File

@ -31,6 +31,7 @@ type
pinnedBy: string pinnedBy: string
editMode: bool editMode: bool
isEdited: bool isEdited: bool
links: seq[string]
proc initItem*( proc initItem*(
id, id,
@ -50,7 +51,8 @@ proc initItem*(
contentType: ContentType, contentType: ContentType,
messageType: int, messageType: int,
sticker: string, sticker: string,
stickerPack: int stickerPack: int,
links: seq[string],
): Item = ): Item =
result = Item() result = Item()
result.id = id result.id = id
@ -75,6 +77,7 @@ proc initItem*(
result.stickerPack = stickerPack result.stickerPack = stickerPack
result.editMode = false result.editMode = false
result.isEdited = false result.isEdited = false
result.links = links
proc `$`*(self: Item): string = proc `$`*(self: Item): string =
result = fmt"""Item( result = fmt"""Item(
@ -97,6 +100,7 @@ proc `$`*(self: Item): string =
messageReactions: [{$self.reactionsModel}], messageReactions: [{$self.reactionsModel}],
editMode:{$self.editMode}, editMode:{$self.editMode},
isEdited:{$self.isEdited} isEdited:{$self.isEdited}
links:{$self.links}
)""" )"""
proc id*(self: Item): string {.inline.} = proc id*(self: Item): string {.inline.} =
@ -199,6 +203,9 @@ proc addReaction*(self: Item, emojiId: EmojiId, didIReactWithThisEmoji: bool, us
proc removeReaction*(self: Item, emojiId: EmojiId, reactionId: string, didIRemoveThisReaction: bool) = proc removeReaction*(self: Item, emojiId: EmojiId, reactionId: string, didIRemoveThisReaction: bool) =
self.reactionsModel.removeReaction(emojiId, reactionId, didIRemoveThisReaction) self.reactionsModel.removeReaction(emojiId, reactionId, didIRemoveThisReaction)
proc links*(self: Item): seq[string] {.inline.} =
self.links
proc toJsonNode*(self: Item): JsonNode = proc toJsonNode*(self: Item): JsonNode =
result = %* { result = %* {
"id": self.id, "id": self.id,
@ -224,7 +231,8 @@ proc toJsonNode*(self: Item): JsonNode =
"pinned": self.pinned, "pinned": self.pinned,
"pinnedBy": self.pinnedBy, "pinnedBy": self.pinnedBy,
"editMode": self.editMode, "editMode": self.editMode,
"isEdited": self.isEdited "isEdited": self.isEdited,
"links": self.links
} }
proc editMode*(self: Item): bool {.inline.} = proc editMode*(self: Item): bool {.inline.} =

View File

@ -30,6 +30,7 @@ type
Reactions Reactions
EditMode EditMode
IsEdited IsEdited
Links
QtObject: QtObject:
type type
@ -89,7 +90,8 @@ QtObject:
ModelRole.PinnedBy.int:"pinnedBy", ModelRole.PinnedBy.int:"pinnedBy",
ModelRole.Reactions.int:"reactions", ModelRole.Reactions.int:"reactions",
ModelRole.EditMode.int: "editMode", ModelRole.EditMode.int: "editMode",
ModelRole.IsEdited.int: "isEdited" ModelRole.IsEdited.int: "isEdited",
ModelRole.Links.int: "links",
}.toTable }.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant = method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -153,6 +155,8 @@ QtObject:
result = newQVariant(item.editMode) result = newQVariant(item.editMode)
of ModelRole.IsEdited: of ModelRole.IsEdited:
result = newQVariant(item.isEdited) result = newQVariant(item.isEdited)
of ModelRole.Links:
result = newQVariant(item.links.join(" "))
proc findIndexForMessageId(self: Model, messageId: string): int = proc findIndexForMessageId(self: Model, messageId: string): int =
for i in 0 ..< self.items.len: for i in 0 ..< self.items.len:

View File

@ -1,6 +1,9 @@
include ../../common/json_utils include ../../common/json_utils
include ../../../app/core/tasks/common include ../../../app/core/tasks/common
import status/statusgo_backend_new/chat as status_go_chat
################################################# #################################################
# Async load messages # Async load messages
################################################# #################################################
@ -142,3 +145,32 @@ const asyncMarkCertainMessagesReadTask: Task = proc(argEncoded: string) {.gcsafe
} }
arg.finish(responseJson) arg.finish(responseJson)
################################################# #################################################
#################################################
# Async GetLinkPreviewData
#################################################
type
AsyncGetLinkPreviewDataTaskArg = ref object of QObjectTaskArg
link: string
uuid: string
const asyncGetLinkPreviewDataTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncGetLinkPreviewDataTaskArg](argEncoded)
var success = true
var result: JsonNode = %* {}
try:
let response = status_go_chat.getLinkPreviewData(arg.link)
result = response.result
except:
success = false
let responseJson = %*{
"link": arg.link,
"uuid": arg.uuid,
"success": success,
"result": result,
}
arg.finish(responseJson)

View File

@ -35,6 +35,7 @@ const SIGNAL_MESSAGE_REACTION_REMOVED* = "messageReactionRemoved"
const SIGNAL_MESSAGE_REACTION_FROM_OTHERS* = "messageReactionFromOthers" const SIGNAL_MESSAGE_REACTION_FROM_OTHERS* = "messageReactionFromOthers"
const SIGNAL_MESSAGE_DELETION* = "messageDeleted" const SIGNAL_MESSAGE_DELETION* = "messageDeleted"
const SIGNAL_MESSAGE_EDITED* = "messageEdited" const SIGNAL_MESSAGE_EDITED* = "messageEdited"
const SIGNAL_MESSAGE_LINK_PREVIEW_DATA_LOADED* = "messageLinkPreviewDataLoaded"
include async_tasks include async_tasks
@ -77,6 +78,9 @@ type
chatId*: string chatId*: string
message*: MessageDto message*: MessageDto
LinkPreviewDataArgs* = ref object of Args
response*: string
QtObject: QtObject:
type Service* = ref object of QObject type Service* = ref object of QObject
events: EventEmitter events: EventEmitter
@ -530,6 +534,19 @@ QtObject:
proc getNumOfPinnedMessages*(self: Service, chatId: string): int = proc getNumOfPinnedMessages*(self: Service, chatId: string): int =
return self.numOfPinnedMessagesPerChat[chatId] return self.numOfPinnedMessagesPerChat[chatId]
proc onAsyncGetLinkPreviewData*(self: Service, response: string) {.slot.} =
self.events.emit(SIGNAL_MESSAGE_LINK_PREVIEW_DATA_LOADED, LinkPreviewDataArgs(response: response))
proc asyncGetLinkPreviewData*(self: Service, link: string, uuid: string) =
let arg = AsyncGetLinkPreviewDataTaskArg(
tptr: cast[ByteAddress](asyncGetLinkPreviewDataTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onAsyncGetLinkPreviewData",
link: link,
uuid: uuid
)
self.threadpool.start(arg)
# See render-inline in status-react/src/status_im/ui/screens/chat/message/message.cljs # See render-inline in status-react/src/status_im/ui/screens/chat/message/message.cljs
proc renderInline(self: Service, parsedTextChild: ParsedTextChild): string = proc renderInline(self: Service, parsedTextChild: ParsedTextChild): string =
let value = escape_html(parsedTextChild.literal) let value = escape_html(parsedTextChild.literal)

View File

@ -129,6 +129,7 @@ ModalPopup {
pinnedMessage: model.pinned pinnedMessage: model.pinned
messagePinnedBy: model.pinnedBy messagePinnedBy: model.pinnedBy
reactionsModel: model.reactions reactionsModel: model.reactions
linkUrls: model.links
// This is possible since we have all data loaded before we load qml. // This is possible since we have all data loaded before we load qml.
// When we fetch messages to fulfill a gap we have to set them at once. // When we fetch messages to fulfill a gap we have to set them at once.

View File

@ -187,4 +187,11 @@ QtObject {
return msg return msg
} }
function getLinkPreviewData(url, uuid) {
if(!messageModule)
return
return messageModule.getLinkPreviewData(url, uuid)
}
} }

View File

@ -122,6 +122,7 @@ Item {
amISender: model.message.amISender amISender: model.message.amISender
messageImage: model.message.messageImage messageImage: model.message.messageImage
messageTimestamp: model.timestamp messageTimestamp: model.timestamp
linkUrls: model.links
//timestamp: model.message.timestamp //timestamp: model.message.timestamp
messageOutgoingStatus: model.message.outgoingStatus messageOutgoingStatus: model.message.outgoingStatus
messageContentType: model.message.contentType messageContentType: model.message.contentType

View File

@ -340,6 +340,7 @@ Item {
stickerPack: model.stickerPack stickerPack: model.stickerPack
editModeOn: model.editMode editModeOn: model.editMode
isEdited: model.isEdited isEdited: model.isEdited
linkUrls: model.links
// This is possible since we have all data loaded before we load qml. // This is possible since we have all data loaded before we load qml.
// When we fetch messages to fulfill a gap we have to set them at once. // When we fetch messages to fulfill a gap we have to set them at once.

View File

@ -52,6 +52,7 @@ Item {
} }
} }
property bool editModeOn: false property bool editModeOn: false
property string linkUrls: ""
signal openStickerPackPopup(string stickerPackId) signal openStickerPackPopup(string stickerPackId)
signal addEmoji(bool isProfileClick, bool isSticker, bool isImage , var image, bool emojiOnly, bool hideEmojiPicker) signal addEmoji(bool isProfileClick, bool isSticker, bool isImage , var image, bool emojiOnly, bool hideEmojiPicker)
@ -468,8 +469,6 @@ Item {
visible: !editModeOn visible: !editModeOn
ChatTextView { ChatTextView {
id: chatText id: chatText
// Not Refactored Yet
// store: rootStore
readonly property int leftPadding: chatImage.anchors.leftMargin + chatImage.width + chatHorizontalPadding readonly property int leftPadding: chatImage.anchors.leftMargin + chatImage.width + chatHorizontalPadding
visible: { visible: {
const urls = linkUrls.split(" ") const urls = linkUrls.split(" ")
@ -586,10 +585,9 @@ Item {
sourceComponent: Component { sourceComponent: Component {
LinksMessageView { LinksMessageView {
// Not Refactored Yet linkUrls: root.linkUrls
// store: rootStore
linkUrls: linkUrls
container: root.container container: root.container
messageStore: root.messageStore
isCurrentUser: isCurrentUser isCurrentUser: isCurrentUser
} }
} }

View File

@ -9,14 +9,14 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import shared.status 1.0 import shared.status 1.0
import shared.stores 1.0
import shared.panels 1.0 import shared.panels 1.0
import shared.stores 1.0
import shared.panels.chat 1.0 import shared.panels.chat 1.0
import shared.controls.chat 1.0 import shared.controls.chat 1.0
Column { Column {
id: root id: root
property var store property var messageStore
property var container property var container
property string linkUrls: "" property string linkUrls: ""
property bool isCurrentUser: false property bool isCurrentUser: false
@ -66,42 +66,37 @@ Column {
} }
} }
// Not Refactored Yet Connections {
// Connections { id: linkFetchConnections
// id: linkFetchConnections enabled: false
// enabled: false target: root.messageStore.messageModule
// target: root.store.chatsModelInst onLinkPreviewDataWasReceived: {
// onLinkPreviewDataWasReceived: { let response
// let response try {
// try { response = JSON.parse(previewData)
// response = JSON.parse(previewData) } catch (e) {
console.error(previewData, e)
return
}
if (response.uuid !== linkMessageLoader.uuid) return
linkFetchConnections.enabled = false
// } catch (e) { if (!response.success) {
// console.error(previewData, e) console.error("could not get preview data")
// return return undefined
// } }
linkData = response.result
// if (response.uuid !== linkMessageLoader.uuid) return if (linkData.contentType.startsWith("image/")) {
return linkMessageLoader.sourceComponent = unfurledImageComponent
// linkFetchConnections.enabled = false }
if (linkData.site && linkData.title) {
// if (!response.success) { linkData.address = link
// console.error(response.result.error) return linkMessageLoader.sourceComponent = unfurledLinkComponent
// return undefined }
// } }
}
// linkData = response.result
// if (linkData.contentType.startsWith("image/")) {
// return linkMessageLoader.sourceComponent = unfurledImageComponent
// }
// if (linkData.site && linkData.title) {
// linkData.address = link
// return linkMessageLoader.sourceComponent = unfurledLinkComponent
// }
// }
// }
// Not Refactored Yet // Not Refactored Yet
// Connections { // Connections {
@ -185,9 +180,8 @@ Column {
} }
linkFetchConnections.enabled = true linkFetchConnections.enabled = true
// Not Refactored Yet
return "" root.messageStore.getLinkPreviewData(link, linkMessageLoader.uuid)
// return root.store.chatsModelInst.getLinkPreviewData(link, linkMessageLoader.uuid)
} }
// setting the height to 0 allows the "enable link" dialog to // setting the height to 0 allows the "enable link" dialog to
// disappear correctly when RootStore.neverAskAboutUnfurlingAgain // disappear correctly when RootStore.neverAskAboutUnfurlingAgain
@ -226,7 +220,7 @@ Column {
Component { Component {
id: invitationBubble id: invitationBubble
InvitationBubbleView { InvitationBubbleView {
store: root.store // store: root.store
communityId: linkData.communityId communityId: linkData.communityId
isLink: true isLink: true
anchors.left: parent.left anchors.left: parent.left

View File

@ -37,6 +37,7 @@ Column {
property bool pinnedMessage: false property bool pinnedMessage: false
property string messagePinnedBy: "" property string messagePinnedBy: ""
property var reactionsModel: [] property var reactionsModel: []
property string linkUrls: ""
property int prevMessageIndex: -1 property int prevMessageIndex: -1
property var prevMessageAsJsonObj property var prevMessageAsJsonObj
@ -101,7 +102,6 @@ Column {
property string emojiReactions: "" property string emojiReactions: ""
property bool timeout: false property bool timeout: false
property bool hasMention: false property bool hasMention: false
property string linkUrls: ""
property bool placeholderMessage: false property bool placeholderMessage: false
property bool activityCenterMessage: false property bool activityCenterMessage: false
property bool read: true property bool read: true
@ -353,6 +353,7 @@ Column {
isCurrentUser: root.amISender isCurrentUser: root.amISender
isHovered: root.isHovered isHovered: root.isHovered
editModeOn: root.editModeOn editModeOn: root.editModeOn
linkUrls: root.linkUrls
onAddEmoji: { onAddEmoji: {
root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker) root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker)