fix(@desktop/app-search): [base_bc] can't jump to a message from search results

- broken "jump to a section/chat/message" feature fixed
- added loading indicator while searching is in progress
- animation when we point to the searched message is in place again

Fixes #4577
This commit is contained in:
Sale Djenic 2022-01-27 12:28:27 +01:00
parent 5099ca4b3e
commit 25f7544b41
26 changed files with 269 additions and 99 deletions

View File

@ -1,4 +1,4 @@
import controller_interface import Tables, controller_interface, chronicles
import io_interface import io_interface
import ../../../global/app_sections_config as conf import ../../../global/app_sections_config as conf
@ -12,6 +12,19 @@ import ../../../core/eventemitter
export controller_interface export controller_interface
logScope:
topics = "app-search-module-controller"
type ResultItemDetails = object
sectionId*: string
channelId*: string
messageId*: string
method isEmpty(self: ResultItemDetails): bool =
self.sectionId.len == 0 and
self.channelId.len == 0 and
self.messageId.len == 0
type type
Controller* = ref object of controller_interface.AccessInterface Controller* = ref object of controller_interface.AccessInterface
delegate: io_interface.AccessInterface delegate: io_interface.AccessInterface
@ -25,6 +38,7 @@ type
searchLocation: string searchLocation: string
searchSubLocation: string searchSubLocation: string
searchTerm: string searchTerm: string
resultItems: Table[string, ResultItemDetails] # [resuiltItemId, ResultItemDetails]
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, contactsService: contact_service.Service, proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, contactsService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.Service, chatService: chat_service.Service, communityService: community_service.Service,
@ -36,9 +50,10 @@ proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter
result.chatService = chatService result.chatService = chatService
result.communityService = communityService result.communityService = communityService
result.messageService = messageService result.messageService = messageService
result.resultItems = initTable[string, ResultItemDetails]()
method delete*(self: Controller) = method delete*(self: Controller) =
discard self.resultItems.clear
method init*(self: Controller) = method init*(self: Controller) =
self.events.on(SIGNAL_SEARCH_MESSAGES_LOADED) do(e:Args): self.events.on(SIGNAL_SEARCH_MESSAGES_LOADED) do(e:Args):
@ -87,6 +102,7 @@ method getChatDetails*(self: Controller, communityId, chatId: string): ChatDto =
return self.chatService.getChatById(fullId) return self.chatService.getChatById(fullId)
method searchMessages*(self: Controller, searchTerm: string) = method searchMessages*(self: Controller, searchTerm: string) =
self.resultItems.clear
self.searchTerm = searchTerm self.searchTerm = searchTerm
var chats: seq[string] var chats: seq[string]
@ -122,4 +138,16 @@ method getOneToOneChatNameAndImage*(self: Controller, chatId: string):
method getContactNameAndImage*(self: Controller, contactId: string): method getContactNameAndImage*(self: Controller, contactId: string):
tuple[name: string, image: string, isIdenticon: bool] = tuple[name: string, image: string, isIdenticon: bool] =
return self.contactsService.getContactNameAndImage(contactId) return self.contactsService.getContactNameAndImage(contactId)
method addResultItemDetails*(self: Controller, itemId: string, sectionId = "", channelId = "", messageId = "") =
self.resultItems.add(itemId, ResultItemDetails(sectionId: sectionId, channelId: channelId, messageId: messageId))
method resultItemClicked*(self: Controller, itemId: string) =
let itemDetails = self.resultItems.getOrDefault(itemId)
if(itemDetails.isEmpty()):
# we shouldn't be here ever
info "important: we don't have stored details for a searched result item with id: ", itemId
return
self.messageService.switchTo(itemDetails.sectionId, itemDetails.channelId, itemDetails.messageId)

View File

@ -57,4 +57,11 @@ method getOneToOneChatNameAndImage*(self: AccessInterface, chatId: string):
method getContactNameAndImage*(self: AccessInterface, contactId: string): method getContactNameAndImage*(self: AccessInterface, contactId: string):
tuple[name: string, image: string, isIdenticon: bool] {.base.} = tuple[name: string, image: string, isIdenticon: bool] {.base.} =
raise newException(ValueError, "No implementation available")
method addResultItemDetails*(self: AccessInterface, itemId: string, sectionId = "", channelId = "", messageId = "")
{.base.} =
raise newException(ValueError, "No implementation available")
method resultItemClicked*(self: AccessInterface, itemId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -158,6 +158,7 @@ method onSearchMessagesDone*(self: Module, messages: seq[MessageDto]) =
let item = result_item.initItem(co.id, "", "", co.id, co.name, SEARCH_RESULT_COMMUNITIES_SECTION_NAME, let item = result_item.initItem(co.id, "", "", co.id, co.name, SEARCH_RESULT_COMMUNITIES_SECTION_NAME,
co.images.thumbnail, co.color, "", "", co.images.thumbnail, co.color, false) co.images.thumbnail, co.color, "", "", co.images.thumbnail, co.color, false)
self.controller.addResultItemDetails(co.id, co.id)
items.add(item) items.add(item)
# Add channels # Add channels
@ -170,6 +171,7 @@ method onSearchMessagesDone*(self: Module, messages: seq[MessageDto]) =
SEARCH_RESULT_CHANNELS_SECTION_NAME, chatDto.identicon, chatDto.color, "", "", chatDto.identicon, chatDto.color, SEARCH_RESULT_CHANNELS_SECTION_NAME, chatDto.identicon, chatDto.color, "", "", chatDto.identicon, chatDto.color,
false) false)
self.controller.addResultItemDetails(chatDto.id, co.id, chatDto.id)
channels.add(item) channels.add(item)
# Add chats # Add chats
@ -193,6 +195,7 @@ method onSearchMessagesDone*(self: Module, messages: seq[MessageDto]) =
let item = result_item.initItem(c.id, "", "", c.id, chatName, SEARCH_RESULT_CHATS_SECTION_NAME, chatImage, let item = result_item.initItem(c.id, "", "", c.id, chatName, SEARCH_RESULT_CHATS_SECTION_NAME, chatImage,
c.color, "", "", chatImage, c.color, isIdenticon) c.color, "", "", chatImage, c.color, isIdenticon)
self.controller.addResultItemDetails(c.id, conf.CHAT_SECTION_ID, c.id)
items.add(item) items.add(item)
# Add channels in order as requested by the design # Add channels in order as requested by the design
@ -218,6 +221,7 @@ method onSearchMessagesDone*(self: Module, messages: seq[MessageDto]) =
let item = result_item.initItem(m.id, m.text, $m.timestamp, m.`from`, senderName, let item = result_item.initItem(m.id, m.text, $m.timestamp, m.`from`, senderName,
SEARCH_RESULT_MESSAGES_SECTION_NAME, senderImage, "", chatName, "", chatImage, chatDto.color, isIdenticon) SEARCH_RESULT_MESSAGES_SECTION_NAME, senderImage, "", chatName, "", chatImage, chatDto.color, isIdenticon)
self.controller.addResultItemDetails(m.id, conf.CHAT_SECTION_ID, chatDto.id, m.id)
items.add(item) items.add(item)
else: else:
let community = self.controller.getCommunityById(chatDto.communityId) let community = self.controller.getCommunityById(chatDto.communityId)
@ -227,6 +231,11 @@ method onSearchMessagesDone*(self: Module, messages: seq[MessageDto]) =
SEARCH_RESULT_MESSAGES_SECTION_NAME, senderImage, "", community.name, channelName, community.images.thumbnail, SEARCH_RESULT_MESSAGES_SECTION_NAME, senderImage, "", community.name, channelName, community.images.thumbnail,
community.color, false) community.color, false)
self.controller.addResultItemDetails(m.id, chatDto.communityId, chatDto.id, m.id)
items.add(item) items.add(item)
self.view.searchResultModel().set(items) self.view.searchResultModel().set(items)
self.view.emitAppSearchCompletedSignal()
method resultItemClicked*(self: Module, itemId: string) =
self.controller.resultItemClicked(itemId)

View File

@ -11,4 +11,7 @@ method getSearchLocationObject*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method searchMessages*(self: AccessInterface, searchTerm: string) {.base.} = method searchMessages*(self: AccessInterface, searchTerm: string) {.base.} =
raise newException(ValueError, "No implementation available")
method resultItemClicked*(self: AccessInterface, itemId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -1,4 +1,4 @@
import NimQml, Tables, strutils import NimQml, Tables, strutils, strformat
import result_item import result_item
@ -33,15 +33,15 @@ QtObject:
new(result, delete) new(result, delete)
result.setup() result.setup()
################################################# proc `$`*(self: Model): string =
# Properties for i in 0 ..< self.resultList.len:
################################################# result &= fmt"""SearchResultMessageModel:
[{i}]:({$self.resultList[i]})
"""
proc countChanged*(self: Model) {.signal.} proc countChanged*(self: Model) {.signal.}
proc count*(self: Model): int {.slot.} = proc count*(self: Model): int {.slot.} =
self.resultList.len self.resultList.len
QtProperty[int] count: QtProperty[int] count:
read = count read = count
notify = countChanged notify = countChanged

View File

@ -58,4 +58,11 @@ QtObject:
self.delegate.getSearchLocationObject() self.delegate.getSearchLocationObject()
proc searchMessages*(self: View, searchTerm: string) {.slot.} = proc searchMessages*(self: View, searchTerm: string) {.slot.} =
self.delegate.searchMessages(searchTerm) self.delegate.searchMessages(searchTerm)
proc resultItemClicked*(self: View, itemId: string) {.slot.} =
self.delegate.resultItemClicked(itemId)
proc appSearchCompleted(self: View) {.signal.}
proc emitAppSearchCompletedSignal*(self: View) =
self.appSearchCompleted()

View File

@ -22,6 +22,7 @@ type
sectionId: string sectionId: string
chatId: string chatId: string
belongsToCommunity: bool belongsToCommunity: bool
searchedMessageId: string
contactService: contact_service.Service contactService: contact_service.Service
communityService: community_service.Service communityService: community_service.Service
chatService: chat_service.Service chatService: chat_service.Service
@ -140,6 +141,12 @@ method init*(self: Controller) =
let args = LinkPreviewDataArgs(e) let args = LinkPreviewDataArgs(e)
self.delegate.onPreviewDataLoaded(args.response) self.delegate.onPreviewDataLoaded(args.response)
self.events.on(SIGNAL_MAKE_SECTION_CHAT_ACTIVE) do(e: Args):
var args = ActiveSectionChatArgs(e)
if(self.sectionId != args.sectionId or self.chatId != args.chatId):
return
self.delegate.switchToMessage(args.messageId)
method getMySectionId*(self: Controller): string = method getMySectionId*(self: Controller): string =
return self.sectionId return self.sectionId
@ -196,4 +203,13 @@ 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 = method getLinkPreviewData*(self: Controller, link: string, uuid: string): string =
self.messageService.asyncGetLinkPreviewData(link, uuid) self.messageService.asyncGetLinkPreviewData(link, uuid)
method getSearchedMessageId*(self: Controller): string =
return self.searchedMessageId
method setSearchedMessageId*(self: Controller, searchedMessageId: string) =
self.searchedMessageId = searchedMessageId
method clearSearchedMessageId*(self: Controller) =
self.setSearchedMessageId("")

View File

@ -71,3 +71,12 @@ method editMessage*(self: AccessInterface, messageId: string, updatedMsg: string
method getLinkPreviewData*(self: AccessInterface, link: string, uuid: string): string {.base.} = method getLinkPreviewData*(self: AccessInterface, link: string, uuid: string): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getSearchedMessageId*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method setSearchedMessageId*(self: AccessInterface, searchedMessageId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method clearSearchedMessageId*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -156,6 +156,11 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
if(not self.view.getInitialMessagesLoaded()): if(not self.view.getInitialMessagesLoaded()):
self.view.initialMessagesAreLoaded() self.view.initialMessagesAreLoaded()
# check if this loading was caused by the click on a messages from the app search result
let searchedMessageId = self.controller.getSearchedMessageId()
if(searchedMessageId.len > 0):
self.switchToMessage(searchedMessageId)
method messageAdded*(self: Module, message: MessageDto) = method messageAdded*(self: Module, message: MessageDto) =
let sender = self.controller.getContactDetails(message.`from`) let sender = self.controller.getContactDetails(message.`from`)
@ -317,3 +322,12 @@ method getLinkPreviewData*(self: Module, link: string, uuid: string): string =
method onPreviewDataLoaded*(self: Module, previewData: string) = method onPreviewDataLoaded*(self: Module, previewData: string) =
self.view.onPreviewDataLoaded(previewData) self.view.onPreviewDataLoaded(previewData)
method switchToMessage*(self: Module, messageId: string) =
let index = self.view.model().findIndexForMessageId(messageId)
if(index != -1):
self.controller.clearSearchedMessageId()
self.view.emitSwitchToMessageSignal(index)
else:
self.controller.setSearchedMessageId(messageId)
self.loadMoreMessages()

View File

@ -36,4 +36,7 @@ method onMessageEdited*(self: AccessInterface, message: MessageDto) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method setLoadingHistoryMessagesInProgress*(self: AccessInterface, isLoading: bool) {.base.} = method setLoadingHistoryMessagesInProgress*(self: AccessInterface, isLoading: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method switchToMessage*(self: AccessInterface, messageId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -103,7 +103,6 @@ QtObject:
self.delegate.loadMoreMessages() self.delegate.loadMoreMessages()
proc messageSuccessfullySent*(self: View) {.signal.} proc messageSuccessfullySent*(self: View) {.signal.}
proc emitSendingMessageSuccessSignal*(self: View) = proc emitSendingMessageSuccessSignal*(self: View) =
self.messageSuccessfullySent() self.messageSuccessfullySent()
@ -130,4 +129,8 @@ QtObject:
proc linkPreviewDataWasReceived*(self: View, previewData: string) {.signal.} proc linkPreviewDataWasReceived*(self: View, previewData: string) {.signal.}
proc onPreviewDataLoaded*(self: View, previewData: string) {.slot.} = proc onPreviewDataLoaded*(self: View, previewData: string) {.slot.} =
self.linkPreviewDataWasReceived(previewData) self.linkPreviewDataWasReceived(previewData)
proc switchToMessage(self: View, messageIndex: int) {.signal.}
proc emitSwitchToMessageSignal*(self: View, messageIndex: int) =
self.switchToMessage(messageIndex)

View File

@ -130,6 +130,12 @@ method init*(self: Controller) =
var args = ChatRenameArgs(e) var args = ChatRenameArgs(e)
self.delegate.onChatRenamed(args.id, args.newName) self.delegate.onChatRenamed(args.id, args.newName)
self.events.on(SIGNAL_MAKE_SECTION_CHAT_ACTIVE) do(e: Args):
var args = ActiveSectionChatArgs(e)
if (self.sectionId != args.sectionId):
return
self.delegate.makeChatWithIdActive(args.chatId)
method getMySectionId*(self: Controller): string = method getMySectionId*(self: Controller): string =
return self.sectionId return self.sectionId

View File

@ -1,7 +1,7 @@
import NimQml, Tables, chronicles, json, sequtils import NimQml, Tables, chronicles, json, sequtils
import io_interface import io_interface
import ../io_interface as delegate_interface import ../io_interface as delegate_interface
import view, controller, item, sub_item, model, sub_model import view, controller, item, sub_item, model, sub_model, base_item
import ../../shared_models/contacts_item as contacts_item import ../../shared_models/contacts_item as contacts_item
import ../../shared_models/contacts_model as contacts_model import ../../shared_models/contacts_model as contacts_model
@ -275,11 +275,31 @@ method chatContentDidLoad*(self: Module) =
method setActiveItemSubItem*(self: Module, itemId: string, subItemId: string) = method setActiveItemSubItem*(self: Module, itemId: string, subItemId: string) =
self.controller.setActiveItemSubItem(itemId, subItemId) self.controller.setActiveItemSubItem(itemId, subItemId)
method makeChatWithIdActive*(self: Module, chatId: string) =
var item = self.view.chatsModel().getItemById(chatId)
var subItemId: string
if(item.isNil):
let subItem = self.view.chatsModel().getSubItemById(chatId)
if(subItem.isNil):
# Should never be here
error "trying to make chat/channel active for an unexisting id ", chatId, methodName="makeChatWithIdActive"
return
subItemId = subItem.BaseItem.id
item = self.view.chatsModel().getItemById(subItem.parentId())
if(item.isNil):
# Should never be here
error "unexisting parent item with id ", subItemId, methodName="makeChatWithIdActive"
return
# here, in this step we have appropriate item and subitem assigned
self.setActiveItemSubItem(item.BaseItem.id, subItemId)
method activeItemSubItemSet*(self: Module, itemId: string, subItemId: string) = method activeItemSubItemSet*(self: Module, itemId: string, subItemId: string) =
let item = self.view.chatsModel().getItemById(itemId) let item = self.view.chatsModel().getItemById(itemId)
if(item.isNil): if(item.isNil):
# Should never be here # Should never be here
error "chat-view unexisting item id: ", itemId error "chat-view unexisting item id: ", itemId, methodName="activeItemSubItemSet"
return return
# Chats from Chat section and chats from Community section which don't belong # Chats from Chat section and chats from Community section which don't belong
@ -299,7 +319,7 @@ method getModuleAsVariant*(self: Module): QVariant =
method getChatContentModule*(self: Module, chatId: string): QVariant = method getChatContentModule*(self: Module, chatId: string): QVariant =
if(not self.chatContentModules.contains(chatId)): if(not self.chatContentModules.contains(chatId)):
error "unexisting chat key: ", chatId error "unexisting chat key: ", chatId, methodName="getChatContentModule"
return return
return self.chatContentModules[chatId].getModuleAsVariant() return self.chatContentModules[chatId].getModuleAsVariant()
@ -312,11 +332,11 @@ method onActiveSectionChange*(self: Module, sectionId: string) =
method createPublicChat*(self: Module, chatId: string) = method createPublicChat*(self: Module, chatId: string) =
if(self.controller.isCommunity()): if(self.controller.isCommunity()):
debug "creating public chat is not allowed for community, most likely it's an error in qml" debug "creating public chat is not allowed for community, most likely it's an error in qml", methodName="createPublicChat"
return return
if(self.chatContentModules.hasKey(chatId)): if(self.chatContentModules.hasKey(chatId)):
error "error: public chat is already added", chatId error "error: public chat is already added", chatId, methodName="createPublicChat"
return return
self.controller.createPublicChat(chatId) self.controller.createPublicChat(chatId)
@ -386,7 +406,7 @@ method onCommunityChannelEdited*(self: Module, chat: ChatDto) =
method createOneToOneChat*(self: Module, chatId: string, ensName: string) = method createOneToOneChat*(self: Module, chatId: string, ensName: string) =
if(self.controller.isCommunity()): if(self.controller.isCommunity()):
debug "creating an one to one chat is not allowed for community, most likely it's an error in qml" debug "creating an one to one chat is not allowed for community, most likely it's an error in qml", methodName="createOneToOneChat"
return return
if(self.chatContentModules.hasKey(chatId)): if(self.chatContentModules.hasKey(chatId)):

View File

@ -1,6 +1,9 @@
method activeItemSubItemSet*(self: AccessInterface, itemId: string, subItemId: string) {.base.} = method activeItemSubItemSet*(self: AccessInterface, itemId: string, subItemId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method makeChatWithIdActive*(self: AccessInterface, chatId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method addNewChat*(self: AccessInterface, chatDto: ChatDto, belongsToCommunity: bool, events: EventEmitter, method addNewChat*(self: AccessInterface, chatDto: ChatDto, belongsToCommunity: bool, events: EventEmitter,
settingsService: settings_service.ServiceInterface, contactService: contact_service.Service, settingsService: settings_service.ServiceInterface, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.Service, chatService: chat_service.Service, communityService: community_service.Service,

View File

@ -1,4 +1,5 @@
import ../shared_models/section_item, controller_interface, io_interface, chronicles import ../shared_models/section_item, controller_interface, io_interface, chronicles
import ../../global/app_sections_config as conf
import ../../global/global_singleton import ../../global/global_singleton
import ../../global/app_signals import ../../global/app_signals
import ../../core/signals/types import ../../core/signals/types
@ -141,6 +142,11 @@ method init*(self: Controller) =
self.events.on(SIGNAL_MNEMONIC_REMOVAL) do(e: Args): self.events.on(SIGNAL_MNEMONIC_REMOVAL) do(e: Args):
self.delegate.mnemonicBackedUp() self.delegate.mnemonicBackedUp()
self.events.on(SIGNAL_MAKE_SECTION_CHAT_ACTIVE) do(e: Args):
var args = ActiveSectionChatArgs(e)
let sectionType = if args.sectionId == conf.CHAT_SECTION_ID: SectionType.Chat else: SectionType.Community
self.setActiveSection(args.sectionId, sectionType)
method getJoinedCommunities*(self: Controller): seq[CommunityDto] = method getJoinedCommunities*(self: Controller): seq[CommunityDto] =
return self.communityService.getJoinedCommunities() return self.communityService.getJoinedCommunities()

View File

@ -49,8 +49,9 @@ QtObject:
result.setup result.setup
proc `$`*(self: Model): string = proc `$`*(self: Model): string =
result = "MessageModel:\n"
for i in 0 ..< self.items.len: for i in 0 ..< self.items.len:
result &= fmt"""MessageModel: result &= fmt"""
[{i}]:({$self.items[i]}) [{i}]:({$self.items[i]})
""" """
@ -158,7 +159,7 @@ QtObject:
of ModelRole.Links: of ModelRole.Links:
result = newQVariant(item.links.join(" ")) 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:
if(self.items[i].id == messageId): if(self.items[i].id == messageId):
return i return i

View File

@ -157,7 +157,7 @@ QtObject:
proc getChatById*(self: Service, chatId: string): ChatDto = proc getChatById*(self: Service, chatId: string): ChatDto =
if(not self.chats.contains(chatId)): if(not self.chats.contains(chatId)):
error "trying to get chat data for an unexisting chat id" error "trying to get chat data for an unexisting chat id", chatId
return return
return self.chats[chatId] return self.chats[chatId]

View File

@ -36,6 +36,7 @@ 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" const SIGNAL_MESSAGE_LINK_PREVIEW_DATA_LOADED* = "messageLinkPreviewDataLoaded"
const SIGNAL_MAKE_SECTION_CHAT_ACTIVE* = "makeSectionChatActive"
include async_tasks include async_tasks
@ -81,6 +82,11 @@ type
LinkPreviewDataArgs* = ref object of Args LinkPreviewDataArgs* = ref object of Args
response*: string response*: string
ActiveSectionChatArgs* = ref object of Args
sectionId*: string
chatId*: string
messageId*: string
QtObject: QtObject:
type Service* = ref object of QObject type Service* = ref object of QObject
events: EventEmitter events: EventEmitter
@ -652,4 +658,13 @@ proc editMessage*(self: Service, messageId: string, updatedMsg: string) =
self.events.emit(SIGNAL_MESSAGE_EDITED, data) self.events.emit(SIGNAL_MESSAGE_EDITED, data)
except Exception as e: except Exception as e:
error "error: ", methodName="editMessage", errName = e.name, errDesription = e.msg error "error: ", methodName="editMessage", errName = e.name, errDesription = e.msg
proc switchTo*(self: Service, sectionId: string, chatId: string, messageId: string) =
## Calling this proc the app will switch to passed `sectionId`, after that if `chatId` is set
## it will make that chat an active one and at the end if `messageId` is set it will point to
## that message.
## We should use this proc (or just emit a signal bellow) when we want to switch to certain
## section and/or chat and/or message
let data = ActiveSectionChatArgs(sectionId: sectionId, chatId: chatId, messageId: messageId)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)

View File

@ -145,7 +145,12 @@ Item {
// } // }
// root.chatSectionModule.setActiveChannel(model.chatId); // root.chatSectionModule.setActiveChannel(model.chatId);
positionAtMessage(model.id);
// To position to appropriate message check how it's done in AppSearch module,
// similar may be done here, corresponding module for activity center just need to
// use the mechanism done there, send the signal form message service and
// and the rest is already handled.
// positionAtMessage(model.id);
} }
prevMessageIndex: root.previousNotificationIndex prevMessageIndex: root.previousNotificationIndex
prevMsgTimestamp: root.previousNotificationTimestamp prevMsgTimestamp: root.previousNotificationTimestamp

View File

@ -117,11 +117,6 @@ Item {
Global.applicationWindow.requestActivate() Global.applicationWindow.requestActivate()
} }
function positionAtMessage(messageId, isSearch = false) {
// Not Refactored Yet
// stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].message.scrollToMessage(messageId, isSearch);
}
Timer { Timer {
interval: 60000; // 1 min interval: 60000; // 1 min
running: true running: true
@ -341,10 +336,6 @@ Item {
// Connections { // Connections {
// target: root.rootStore.chatsModelInst.messageView // target: root.rootStore.chatsModelInst.messageView
// onSearchedMessageLoaded: {
// positionAtMessage(messageId, true);
// }
// onMessageNotificationPushed: function(messageId, communityId, chatId, msg, contentType, chatType, timestamp, identicon, username, hasMention, isAddedContact, channelName) { // onMessageNotificationPushed: function(messageId, communityId, chatId, msg, contentType, chatType, timestamp, identicon, username, hasMention, isAddedContact, channelName) {
// if (localAccountSensitiveSettings.notificationSetting == Constants.notifyAllMessages || // if (localAccountSensitiveSettings.notificationSetting == Constants.notifyAllMessages ||
// (localAccountSensitiveSettings.notificationSetting == Constants.notifyJustMentions && hasMention)) { // (localAccountSensitiveSettings.notificationSetting == Constants.notifyJustMentions && hasMention)) {

View File

@ -27,7 +27,6 @@ Item {
property bool stickersLoaded: false property bool stickersLoaded: false
property alias chatLogView: chatLogView property alias chatLogView: chatLogView
property alias scrollToMessage: chatLogView.scrollToMessage
property var messageContextMenuInst property var messageContextMenuInst
@ -38,6 +37,30 @@ Item {
signal openStickerPackPopup(string stickerPackId) signal openStickerPackPopup(string stickerPackId)
signal showReplyArea(string messageId, string author) signal showReplyArea(string messageId, string author)
Connections {
target: root.messageStore.messageModule
onMessageSuccessfullySent: {
chatLogView.scrollToBottom(true)
}
onSendingMessageFailed: {
sendingMsgFailedPopup.open();
}
onSwitchToMessage: {
chatLogView.positionViewAtIndex(messageIndex, ListView.Center);
chatLogView.itemAtIndex(messageIndex).startMessageFoundAnimation();
}
// Not Refactored Yet
// onNewMessagePushed: {
// if (!chatLogView.scrollToBottom()) {
// newMessages++
// }
// }
}
Item { Item {
id: loadingMessagesIndicator id: loadingMessagesIndicator
visible: messageStore.messageModule? messageStore.messageModule.loadingHistoryMessagesInProgress : false visible: messageStore.messageModule? messageStore.messageModule.loadingHistoryMessagesInProgress : false
@ -90,34 +113,6 @@ Item {
} }
} }
property var scrollToMessage: function (messageId, isSearch = false) {
// Not Refactored Yet
// delayPositioningViewTimer.msgId = messageId;
// delayPositioningViewTimer.isSearch = isSearch;
// delayPositioningViewTimer.restart();
}
// Timer {
// id: delayPositioningViewTimer
// interval: 1000
// property string msgId
// property bool isSearch
// onTriggered: {
// let item
// for (let i = 0; i < messages.rowCount(); i++) {
// item = messageListDelegate.items.get(i);
// if (item.model.messageId === msgId) {
// chatLogView.positionViewAtIndex(i, ListView.Beginning);
// if (isSearch) {
// chatLogView.itemAtIndex(i).startMessageFoundAnimation();
// }
// }
// }
// msgId = "";
// isSearch = false;
// }
// }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
visible: chatLogView.visibleArea.heightRatio < 1 visible: chatLogView.visibleArea.heightRatio < 1
} }
@ -223,25 +218,6 @@ Item {
// } // }
// } // }
Connections {
target: messageStore.messageModule
onMessageSuccessfullySent: {
chatLogView.scrollToBottom(true)
}
onSendingMessageFailed: {
sendingMsgFailedPopup.open();
}
// Not Refactored Yet
// onNewMessagePushed: {
// if (!chatLogView.scrollToBottom()) {
// newMessages++
// }
// }
}
// Connections { // Connections {
// Not Refactored Yet // Not Refactored Yet
// target: root.store.chatsModelInst.communities // target: root.store.chatsModelInst.communities

View File

@ -0,0 +1,40 @@
import QtQuick 2.13
QtObject {
id: root
property var appSearchModule
property var locationMenuModel: root.appSearchModule.locationMenuModel
property var resultModel: root.appSearchModule.resultModel
function searchMessages(searchTerm) {
if(!root.appSearchModule)
return
root.appSearchModule.searchMessages(searchTerm)
}
function setSearchLocation(location, subLocation) {
if(!root.appSearchModule)
return
root.appSearchModule.setSearchLocation(location, subLocation)
}
function prepareLocationMenuModel() {
if(!root.appSearchModule)
return
root.appSearchModule.prepareLocationMenuModel()
}
function getSearchLocationObject() {
if(!root.appSearchModule)
return ""
root.appSearchModule.getSearchLocationObject()
}
function resultItemClicked(itemId) {
if(!root.appSearchModule)
return
root.appSearchModule.resultItemClicked(itemId)
}
}

View File

@ -9,6 +9,10 @@ QtObject {
property var communitiesModuleInst: communitiesModule property var communitiesModuleInst: communitiesModule
property var observedCommunity: communitiesModuleInst.observedCommunity property var observedCommunity: communitiesModuleInst.observedCommunity
property AppSearchStore appSearchStore: AppSearchStore {
appSearchModule: root.mainModuleInst.appSearchModule
}
property ProfileSectionStore profileSectionStore: ProfileSectionStore { property ProfileSectionStore profileSectionStore: ProfileSectionStore {
} }

View File

@ -189,7 +189,7 @@ Item {
AppSearch{ AppSearch{
id: appSearch id: appSearch
store: mainModule.appSearchModule store: appMain.rootStore.appSearchStore
} }
StatusAppLayout { StatusAppLayout {

View File

@ -9,7 +9,7 @@ Item {
property var store property var store
readonly property var searchMessages: Backpressure.debounce(searchPopup, 400, function (value) { readonly property var searchMessages: Backpressure.debounce(searchPopup, 400, function (value) {
store.searchMessages(value) appSearch.store.searchMessages(value)
}) })
function openSearchPopup(){ function openSearchPopup(){
@ -17,7 +17,7 @@ Item {
} }
Connections { Connections {
target: store.locationMenuModel target: appSearch.store.locationMenuModel
onModelAboutToBeReset: { onModelAboutToBeReset: {
for (var i = 2; i <= searchPopupMenu.count; i++) { for (var i = 2; i <= searchPopupMenu.count; i++) {
//clear menu //clear menu
@ -28,13 +28,18 @@ Item {
} }
} }
Connections {
target: appSearch.store.appSearchModule
onAppSearchCompleted: searchPopup.loading = false
}
StatusSearchLocationMenu { StatusSearchLocationMenu {
id: searchPopupMenu id: searchPopupMenu
searchPopup: searchPopup searchPopup: searchPopup
locationModel: store.locationMenuModel locationModel: appSearch.store.locationMenuModel
onItemClicked: { onItemClicked: {
store.setSearchLocation(firstLevelItemValue, secondLevelItemValue) appSearch.store.setSearchLocation(firstLevelItemValue, secondLevelItemValue)
if(searchPopup.searchText !== "") if(searchPopup.searchText !== "")
searchMessages(searchPopup.searchText) searchMessages(searchPopup.searchText)
} }
@ -47,13 +52,14 @@ Item {
defaultSearchLocationText: qsTr("Anywhere") defaultSearchLocationText: qsTr("Anywhere")
searchOptionsPopupMenu: searchPopupMenu searchOptionsPopupMenu: searchPopupMenu
searchResults: store.resultModel searchResults: appSearch.store.resultModel
formatTimestampFn: function (ts) { formatTimestampFn: function (ts) {
return new Date(parseInt(ts, 10)).toLocaleString(Qt.locale(localAppSettings.locale)) return new Date(parseInt(ts, 10)).toLocaleString(Qt.locale(localAppSettings.locale))
} }
onSearchTextChanged: { onSearchTextChanged: {
searchPopup.loading = true
searchMessages(searchPopup.searchText); searchMessages(searchPopup.searchText);
} }
onAboutToHide: { onAboutToHide: {
@ -67,9 +73,9 @@ Item {
onOpened: { onOpened: {
searchPopup.resetSearchSelection(); searchPopup.resetSearchSelection();
searchPopup.forceActiveFocus() searchPopup.forceActiveFocus()
store.prepareLocationMenuModel() appSearch.store.prepareLocationMenuModel()
const jsonObj = store.getSearchLocationObject() const jsonObj = appSearch.store.getSearchLocationObject()
if (!jsonObj) { if (!jsonObj) {
return return
@ -78,7 +84,7 @@ Item {
let obj = JSON.parse(jsonObj) let obj = JSON.parse(jsonObj)
if (obj.location === "") { if (obj.location === "") {
if(obj.subLocation === "") { if(obj.subLocation === "") {
store.setSearchLocation("", "") appSearch.store.setSearchLocation("", "")
} }
else { else {
searchPopup.setSearchSelection(obj.subLocation.text, searchPopup.setSearchSelection(obj.subLocation.text,
@ -88,7 +94,7 @@ Item {
obj.subLocation.iconName, obj.subLocation.iconName,
obj.subLocation.identiconColor) obj.subLocation.identiconColor)
store.setSearchLocation("", obj.subLocation.value) appSearch.store.setSearchLocation("", obj.subLocation.value)
} }
} }
else { else {
@ -100,7 +106,7 @@ Item {
obj.subLocation.iconName, obj.subLocation.iconName,
obj.subLocation.identiconColor) obj.subLocation.identiconColor)
store.setSearchLocation(obj.location.value, obj.subLocation.value) appSearch.store.setSearchLocation(obj.location.value, obj.subLocation.value)
} }
else { else {
searchPopup.setSearchSelection(obj.location.title, searchPopup.setSearchSelection(obj.location.title,
@ -110,15 +116,13 @@ Item {
obj.location.iconName, obj.location.iconName,
obj.location.identiconColor) obj.location.identiconColor)
store.setSearchLocation(obj.location.value, obj.subLocation.value) appSearch.store.setSearchLocation(obj.location.value, obj.subLocation.value)
} }
} }
} }
onResultItemClicked: { onResultItemClicked: {
searchPopup.close() searchPopup.close()
appSearch.store.resultItemClicked(itemId)
// Not Refactored
//root.rootStore.chatsModelInst.switchToSearchedItem(itemId)
} }
onResultItemTitleClicked: { onResultItemTitleClicked: {

View File

@ -193,9 +193,9 @@ Column {
// return root.rootStore.showReactionAuthors(fromAccounts, emojiId) // return root.rootStore.showReactionAuthors(fromAccounts, emojiId)
// } // }
// function startMessageFoundAnimation() { function startMessageFoundAnimation() {
// messageLoader.item.startMessageFoundAnimation(); messageLoader.item.startMessageFoundAnimation();
// } }
///////////////////////////////////////////// /////////////////////////////////////////////