fix(LinkPreviews): Fixing gif hyperlink detection in StatusChatInput
The link preview model can be filtered, but the hyperlink detection needs an unfiltered model to properly highlight all URLs. This brought in the need to separate the urls model and the link previews model.
This commit is contained in:
parent
b9867c2463
commit
8ac6eb8916
|
@ -111,7 +111,7 @@ proc setLinkPreviewEnabledForThisMessage*(self: Controller, enabled: bool) =
|
||||||
self.delegate.setAskToEnableLinkPreview(false)
|
self.delegate.setAskToEnableLinkPreview(false)
|
||||||
|
|
||||||
proc resetLinkPreviews(self: Controller) =
|
proc resetLinkPreviews(self: Controller) =
|
||||||
self.delegate.setUrls(@[])
|
self.delegate.setLinkPreviewUrls(@[])
|
||||||
self.linkPreviewCache.clear()
|
self.linkPreviewCache.clear()
|
||||||
self.linkPreviewCurrentMessageSetting = self.linkPreviewPersistentSetting
|
self.linkPreviewCurrentMessageSetting = self.linkPreviewPersistentSetting
|
||||||
self.delegate.setAskToEnableLinkPreview(false)
|
self.delegate.setAskToEnableLinkPreview(false)
|
||||||
|
@ -201,12 +201,15 @@ proc canAskToEnableLinkPreview(self: Controller): bool =
|
||||||
proc setText*(self: Controller, text: string, unfurlNewUrls: bool) =
|
proc setText*(self: Controller, text: string, unfurlNewUrls: bool) =
|
||||||
if text == "":
|
if text == "":
|
||||||
self.resetLinkPreviews()
|
self.resetLinkPreviews()
|
||||||
|
self.delegate.setUrls(@[])
|
||||||
return
|
return
|
||||||
|
|
||||||
let urls = self.messageService.getTextUrls(text)
|
let urls = self.messageService.getTextUrls(text)
|
||||||
|
self.delegate.setUrls(urls)
|
||||||
|
|
||||||
let supportedUrls = urls.filter(x => not x.endsWith(".gif")) # GIFs are currently unfurled by receiver
|
let supportedUrls = urls.filter(x => not x.endsWith(".gif")) # GIFs are currently unfurled by receiver
|
||||||
self.delegate.setUrls(supportedUrls)
|
self.delegate.setLinkPreviewUrls(supportedUrls)
|
||||||
let newUrls = self.linkPreviewCache.unknownUrls(urls)
|
let newUrls = self.linkPreviewCache.unknownUrls(supportedUrls)
|
||||||
|
|
||||||
let askToEnableLinkPreview = len(newUrls) > 0 and self.canAskToEnableLinkPreview()
|
let askToEnableLinkPreview = len(newUrls) > 0 and self.canAskToEnableLinkPreview()
|
||||||
self.delegate.setAskToEnableLinkPreview(askToEnableLinkPreview)
|
self.delegate.setAskToEnableLinkPreview(askToEnableLinkPreview)
|
||||||
|
|
|
@ -102,7 +102,7 @@ method setText*(self: AccessInterface, text: string, unfurlUrls: bool) {.base.}
|
||||||
method getPlainText*(self: AccessInterface): string =
|
method getPlainText*(self: AccessInterface): string =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method setUrls*(self: AccessInterface, urls: seq[string]) {.base.} =
|
method setLinkPreviewUrls*(self: AccessInterface, urls: seq[string]) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method updateLinkPreviewsFromCache*(self: AccessInterface, urls: seq[string]) {.base.} =
|
method updateLinkPreviewsFromCache*(self: AccessInterface, urls: seq[string]) {.base.} =
|
||||||
|
@ -128,3 +128,6 @@ method setAskToEnableLinkPreview*(self: AccessInterface, value: bool) =
|
||||||
|
|
||||||
method setLinkPreviewEnabledForThisMessage*(self: AccessInterface, enabled: bool) =
|
method setLinkPreviewEnabledForThisMessage*(self: AccessInterface, enabled: bool) =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method setUrls*(self: AccessInterface, urls: seq[string]) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
|
@ -166,8 +166,8 @@ method clearLinkPreviewCache*(self: Module) {.slot.} =
|
||||||
method updateLinkPreviewsFromCache*(self: Module, urls: seq[string]) =
|
method updateLinkPreviewsFromCache*(self: Module, urls: seq[string]) =
|
||||||
self.view.updateLinkPreviewsFromCache(urls)
|
self.view.updateLinkPreviewsFromCache(urls)
|
||||||
|
|
||||||
method setUrls*(self: Module, urls: seq[string]) =
|
method setLinkPreviewUrls*(self: Module, urls: seq[string]) =
|
||||||
self.view.setUrls(urls)
|
self.view.setLinkPreviewUrls(urls)
|
||||||
|
|
||||||
method linkPreviewsFromCache*(self: Module, urls: seq[string]): Table[string, LinkPreview] =
|
method linkPreviewsFromCache*(self: Module, urls: seq[string]): Table[string, LinkPreview] =
|
||||||
return self.controller.linkPreviewsFromCache(urls)
|
return self.controller.linkPreviewsFromCache(urls)
|
||||||
|
@ -186,3 +186,6 @@ method setAskToEnableLinkPreview*(self: Module, value: bool) =
|
||||||
|
|
||||||
method setLinkPreviewEnabledForThisMessage*(self: Module, value: bool) =
|
method setLinkPreviewEnabledForThisMessage*(self: Module, value: bool) =
|
||||||
self.controller.setLinkPreviewEnabledForThisMessage(value)
|
self.controller.setLinkPreviewEnabledForThisMessage(value)
|
||||||
|
|
||||||
|
method setUrls*(self: Module, urls: seq[string]) =
|
||||||
|
self.view.setUrls(urls)
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
import NimQml, tables, sequtils
|
||||||
|
|
||||||
|
type
|
||||||
|
ModelRole {.pure.} = enum
|
||||||
|
Url = UserRole + 1
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type
|
||||||
|
Model* = ref object of QAbstractListModel
|
||||||
|
items: seq[string]
|
||||||
|
|
||||||
|
proc delete*(self: Model) =
|
||||||
|
self.items = @[]
|
||||||
|
self.QAbstractListModel.delete
|
||||||
|
|
||||||
|
proc setup(self: Model) =
|
||||||
|
self.QAbstractListModel.setup
|
||||||
|
|
||||||
|
proc newUrlsModel*(): Model =
|
||||||
|
new(result, delete)
|
||||||
|
result.setup
|
||||||
|
|
||||||
|
proc countChanged(self: Model) {.signal.}
|
||||||
|
|
||||||
|
proc getCount*(self: Model): int {.slot.} =
|
||||||
|
self.items.len
|
||||||
|
|
||||||
|
QtProperty[int] count:
|
||||||
|
read = getCount
|
||||||
|
notify = countChanged
|
||||||
|
|
||||||
|
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||||
|
return self.items.len
|
||||||
|
|
||||||
|
method roleNames(self: Model): Table[int, string] =
|
||||||
|
{
|
||||||
|
ModelRole.Url.int:"url"
|
||||||
|
}.toTable
|
||||||
|
|
||||||
|
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||||
|
if (not index.isValid):
|
||||||
|
return
|
||||||
|
|
||||||
|
if (index.row < 0 or index.row >= self.items.len):
|
||||||
|
return
|
||||||
|
|
||||||
|
let enumRole = role.ModelRole
|
||||||
|
|
||||||
|
case enumRole:
|
||||||
|
of ModelRole.Url:
|
||||||
|
let item = self.items[index.row]
|
||||||
|
result = newQVariant(item)
|
||||||
|
else:
|
||||||
|
result = newQVariant()
|
||||||
|
|
||||||
|
proc removeItemWithIndex(self: Model, ind: int) =
|
||||||
|
if(ind < 0 or ind >= self.items.len):
|
||||||
|
return
|
||||||
|
|
||||||
|
let parentModelIndex = newQModelIndex()
|
||||||
|
defer: parentModelIndex.delete
|
||||||
|
|
||||||
|
self.beginRemoveRows(parentModelIndex, ind, ind)
|
||||||
|
self.items.delete(ind)
|
||||||
|
self.endRemoveRows()
|
||||||
|
|
||||||
|
proc setUrls*(self: Model, urls: seq[string]) =
|
||||||
|
var itemsToInsert: seq[string]
|
||||||
|
var indexesToRemove: seq[int]
|
||||||
|
|
||||||
|
#remove
|
||||||
|
for i in 0 ..< self.items.len:
|
||||||
|
if not urls.anyIt(it == self.items[i]):
|
||||||
|
indexesToRemove.add(i)
|
||||||
|
|
||||||
|
while indexesToRemove.len > 0:
|
||||||
|
let index = pop(indexesToRemove)
|
||||||
|
self.removeItemWithIndex(index)
|
||||||
|
|
||||||
|
# Move or insert
|
||||||
|
for i in 0 ..< urls.len:
|
||||||
|
if self.items.anyIt(it == urls[i]):
|
||||||
|
continue
|
||||||
|
itemsToInsert.add(urls[i])
|
||||||
|
|
||||||
|
|
||||||
|
if itemsToInsert.len > 0:
|
||||||
|
let parentModelIndex = newQModelIndex()
|
||||||
|
defer: parentModelIndex.delete
|
||||||
|
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len + itemsToInsert.len - 1)
|
||||||
|
self.items = self.items & itemsToInsert
|
||||||
|
self.endInsertRows()
|
||||||
|
|
||||||
|
self.countChanged()
|
|
@ -2,6 +2,7 @@ import NimQml
|
||||||
import ./io_interface
|
import ./io_interface
|
||||||
import ./gif_column_model
|
import ./gif_column_model
|
||||||
import ./preserved_properties
|
import ./preserved_properties
|
||||||
|
import ./urls_model
|
||||||
import ../../../../../../app/modules/shared_models/link_preview_model as link_preview_model
|
import ../../../../../../app/modules/shared_models/link_preview_model as link_preview_model
|
||||||
import ../../../../../../app_service/service/gif/dto
|
import ../../../../../../app_service/service/gif/dto
|
||||||
|
|
||||||
|
@ -17,6 +18,8 @@ QtObject:
|
||||||
preservedPropertiesVariant: QVariant
|
preservedPropertiesVariant: QVariant
|
||||||
linkPreviewModel: link_preview_model.Model
|
linkPreviewModel: link_preview_model.Model
|
||||||
linkPreviewModelVariant: QVariant
|
linkPreviewModelVariant: QVariant
|
||||||
|
urlsModel: urls_model.Model
|
||||||
|
urlsModelVariant: QVariant
|
||||||
askToEnableLinkPreview: bool
|
askToEnableLinkPreview: bool
|
||||||
|
|
||||||
proc delete*(self: View) =
|
proc delete*(self: View) =
|
||||||
|
@ -24,10 +27,12 @@ QtObject:
|
||||||
self.gifColumnAModel.delete
|
self.gifColumnAModel.delete
|
||||||
self.gifColumnBModel.delete
|
self.gifColumnBModel.delete
|
||||||
self.gifColumnCModel.delete
|
self.gifColumnCModel.delete
|
||||||
self.preservedProperties.delete
|
|
||||||
self.preservedPropertiesVariant.delete
|
self.preservedPropertiesVariant.delete
|
||||||
self.linkPreviewModel.delete
|
self.preservedProperties.delete
|
||||||
self.linkPreviewModelVariant.delete
|
self.linkPreviewModelVariant.delete
|
||||||
|
self.linkPreviewModel.delete
|
||||||
|
self.urlsModelVariant.delete
|
||||||
|
self.urlsModel.delete
|
||||||
|
|
||||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
|
@ -41,6 +46,8 @@ QtObject:
|
||||||
result.preservedPropertiesVariant = newQVariant(result.preservedProperties)
|
result.preservedPropertiesVariant = newQVariant(result.preservedProperties)
|
||||||
result.linkPreviewModel = newLinkPreviewModel()
|
result.linkPreviewModel = newLinkPreviewModel()
|
||||||
result.linkPreviewModelVariant = newQVariant(result.linkPreviewModel)
|
result.linkPreviewModelVariant = newQVariant(result.linkPreviewModel)
|
||||||
|
result.urlsModel = newUrlsModel()
|
||||||
|
result.urlsModelVariant = newQVariant(result.urlsModel)
|
||||||
result.askToEnableLinkPreview = false
|
result.askToEnableLinkPreview = false
|
||||||
|
|
||||||
proc load*(self: View) =
|
proc load*(self: View) =
|
||||||
|
@ -223,7 +230,7 @@ QtObject:
|
||||||
let linkPreviews = self.delegate.linkPreviewsFromCache(urls)
|
let linkPreviews = self.delegate.linkPreviewsFromCache(urls)
|
||||||
self.linkPreviewModel.updateLinkPreviews(linkPreviews)
|
self.linkPreviewModel.updateLinkPreviews(linkPreviews)
|
||||||
|
|
||||||
proc setUrls*(self: View, urls: seq[string]) =
|
proc setLinkPreviewUrls*(self: View, urls: seq[string]) =
|
||||||
self.linkPreviewModel.setUrls(urls)
|
self.linkPreviewModel.setUrls(urls)
|
||||||
if(self.delegate.getLinkPreviewEnabled()):
|
if(self.delegate.getLinkPreviewEnabled()):
|
||||||
self.updateLinkPreviewsFromCache(urls)
|
self.updateLinkPreviewsFromCache(urls)
|
||||||
|
@ -253,8 +260,19 @@ QtObject:
|
||||||
self.delegate.setLinkPreviewEnabledForThisMessage(enabled)
|
self.delegate.setLinkPreviewEnabledForThisMessage(enabled)
|
||||||
let links = self.linkPreviewModel.getLinks()
|
let links = self.linkPreviewModel.getLinks()
|
||||||
self.linkPreviewModel.clearItems()
|
self.linkPreviewModel.clearItems()
|
||||||
self.setUrls(links)
|
self.setLinkPreviewUrls(links)
|
||||||
self.loadLinkPreviews(links)
|
self.loadLinkPreviews(links)
|
||||||
|
|
||||||
proc removeLinkPreviewData*(self: View, index: int) {.slot.} =
|
proc removeLinkPreviewData*(self: View, index: int) {.slot.} =
|
||||||
self.linkPreviewModel.removePreviewData(index)
|
self.linkPreviewModel.removePreviewData(index)
|
||||||
|
|
||||||
|
proc urlsModelChanged(self: View) {.signal.}
|
||||||
|
proc getUrlsModel*(self: View): QVariant {.slot.} =
|
||||||
|
return self.urlsModelVariant
|
||||||
|
|
||||||
|
proc setUrls*(self: View, urls: seq[string]) =
|
||||||
|
self.urlsModel.setUrls(urls)
|
||||||
|
|
||||||
|
QtProperty[QVariant] urlsModel:
|
||||||
|
read = getUrlsModel
|
||||||
|
notify = urlsModelChanged
|
||||||
|
|
|
@ -112,6 +112,7 @@ SplitView {
|
||||||
|
|
||||||
enabled: enabledCheckBox.checked
|
enabled: enabledCheckBox.checked
|
||||||
linkPreviewModel: fakeLinksModel
|
linkPreviewModel: fakeLinksModel
|
||||||
|
urlsModel: fakeLinksModel
|
||||||
askToEnableLinkPreview: askToEnableLinkPreviewSwitch.checked
|
askToEnableLinkPreview: askToEnableLinkPreviewSwitch.checked
|
||||||
onAskToEnableLinkPreviewChanged: {
|
onAskToEnableLinkPreviewChanged: {
|
||||||
if(askToEnableLinkPreview) {
|
if(askToEnableLinkPreview) {
|
||||||
|
|
|
@ -255,6 +255,7 @@ Item {
|
||||||
store: root.rootStore
|
store: root.rootStore
|
||||||
usersStore: d.activeUsersStore
|
usersStore: d.activeUsersStore
|
||||||
linkPreviewModel: d.activeChatContentModule.inputAreaModule.linkPreviewModel
|
linkPreviewModel: d.activeChatContentModule.inputAreaModule.linkPreviewModel
|
||||||
|
urlsModel: d.activeChatContentModule.inputAreaModule.urlsModel
|
||||||
askToEnableLinkPreview: {
|
askToEnableLinkPreview: {
|
||||||
if(!d.activeChatContentModule || !d.activeChatContentModule.inputAreaModule || !d.activeChatContentModule.inputAreaModule.preservedProperties)
|
if(!d.activeChatContentModule || !d.activeChatContentModule.inputAreaModule || !d.activeChatContentModule.inputAreaModule.preservedProperties)
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -65,6 +65,8 @@ Rectangle {
|
||||||
|
|
||||||
property var linkPreviewModel: null
|
property var linkPreviewModel: null
|
||||||
|
|
||||||
|
property var urlsModel: null
|
||||||
|
|
||||||
property bool askToEnableLinkPreview: false
|
property bool askToEnableLinkPreview: false
|
||||||
|
|
||||||
property var imageErrorMessageLocation: StatusChatInput.ImageErrorMessageLocation.Top // TODO: Remove this property?
|
property var imageErrorMessageLocation: StatusChatInput.ImageErrorMessageLocation.Top // TODO: Remove this property?
|
||||||
|
@ -1366,7 +1368,7 @@ Rectangle {
|
||||||
TextEditHyperlinksFormatter {
|
TextEditHyperlinksFormatter {
|
||||||
id: hyperlinksFormatter
|
id: hyperlinksFormatter
|
||||||
textEdit: messageInputField
|
textEdit: messageInputField
|
||||||
urlModel: control.linkPreviewModel
|
urlModel: control.urlsModel
|
||||||
highlightUrl: linkPreviewArea.hoveredUrl
|
highlightUrl: linkPreviewArea.hoveredUrl
|
||||||
enabled: messageInputField.enabled && messageInputField.textFormat == TextEdit.RichText
|
enabled: messageInputField.enabled && messageInputField.textFormat == TextEdit.RichText
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue