refactor: removing mailserver controller and model

This commit is contained in:
Richard Ramos 2022-01-28 19:18:30 -04:00
parent f36bee6337
commit ad7f48d6ac
25 changed files with 230 additions and 362 deletions

View File

@ -165,8 +165,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.providerService = provider_service.newService(result.dappPermissionsService, result.settingsService)
result.savedAddressService = saved_address_service.newService(statusFoundation.events)
result.devicesService = devices_service.newService(statusFoundation.events, result.settingsService)
result.mailserversService = mailservers_service.newService(statusFoundation.events, statusFoundation.marathon,
result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration)
result.mailserversService = mailservers_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration)
result.nodeService = node_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.settingsService)
result.gifService = gif_service.newService(result.settingsService)
@ -326,6 +326,7 @@ proc load(self: AppController) =
self.communityService,
self.messageService,
self.gifService,
self.mailserversService
)
proc userLoggedIn*(self: AppController) =

View File

@ -1,10 +1,8 @@
import NimQml, chronicles, task_runner
import task_runner
import
eventemitter,
./fleets/fleet_configuration,
./tasks/marathon,
./tasks/marathon/mailserver/controller,
./tasks/marathon/mailserver/worker,
./tasks/threadpool,
./signals/signals_manager
@ -15,28 +13,19 @@ type StatusFoundation* = ref object
events*: EventEmitter
fleetConfiguration*: FleetConfiguration
threadpool*: ThreadPool
marathon*: Marathon
signalsManager*: SignalsManager
mailserverController*: MailserverController
mailserverWorker*: MailserverWorker
proc newStatusFoundation*(fleetConfig: string): StatusFoundation =
result = StatusFoundation()
result.events = createEventEmitter()
result.fleetConfiguration = newFleetConfiguration(fleetConfig)
result.mailserverController = newMailserverController(result.events)
result.mailserverWorker = newMailserverWorker(cast[ByteAddress](result.mailserverController.vptr))
result.threadpool = newThreadPool()
result.marathon = newMarathon(result.mailserverWorker)
result.signalsManager = newSignalsManager(result.events)
proc delete*(self: StatusFoundation) =
self.threadpool.teardown()
self.marathon.teardown()
self.mailserverWorker.teardown()
self.mailserverController.delete()
self.fleetConfiguration.delete()
self.signalsManager.delete()
proc onLoggedIn*(self: StatusFoundation) =
self.marathon.onLoggedIn()
discard

View File

@ -1,103 +0,0 @@
import NimQml, json_serialization, chronicles
import ../../../eventemitter
import ../../../fleets/fleet_configuration
import ../../../../../app_service/service/settings/service_interface as settings_service
import ../../../../../app_service/service/node_configuration/service_interface as node_config_service
import status/settings as status_settings
import status/mailservers as status_mailservers
import ../../common as task_runner_common
logScope:
topics = "mailserver controller"
const STATUS_MAILSERVER_PASS = "status-offline-inbox"
const STATUS_STORE_MESSAGES_TIMEOUT = 30
################################################################################
## ##
## NOTE: MailserverController runs on the main thread ##
## ##
################################################################################
QtObject:
type MailserverController* = ref object of QObject
events: EventEmitter
proc newMailserverController*(events: EventEmitter): MailserverController =
new(result)
result.events = events
result.setup()
proc setup(self: MailserverController) =
self.QObject.setup
proc delete*(self: MailserverController) =
self.QObject.delete
# In case of mailserver task, we need to fetch data directly from the `status-go`, and that's why direct calls to
# `status-lib` are made here. If we use services here, the state remains the same as it was in the moment when certain
# service is passed to the mailserver thread.
proc getCurrentSettings(self: MailserverController): SettingsDto =
try:
let response = status_settings.getSettings()
let settings = response.result.toSettingsDto()
return settings
except Exception as e:
let errDesription = e.msg
error "error: ", methodName="mailserver-getCurrentSettings", errDesription
proc getFleet*(self: MailserverController): string =
let settings = self.getCurrentSettings()
var fleet = settings_service.DEFAULT_FLEET
if(settings.fleet.len > 0):
fleet = settings.fleet
return fleet
proc getPinnedMailserver*(self: MailserverController): string =
let settings = self.getCurrentSettings()
let fleet = self.getFleet()
if (fleet == $Fleet.Prod):
return settings.pinnedMailserver.ethProd
elif (fleet == $Fleet.Staging):
return settings.pinnedMailserver.ethStaging
elif (fleet == $Fleet.Test):
return settings.pinnedMailserver.ethTest
elif (fleet == $Fleet.WakuV2Prod):
return settings.pinnedMailserver.wakuv2Prod
elif (fleet == $Fleet.WakuV2Test):
return settings.pinnedMailserver.wakuv2Test
elif (fleet == $Fleet.GoWakuTest):
return settings.pinnedMailserver.goWakuTest
return ""
proc requestAllHistoricMessages*(self: MailserverController) =
try:
discard status_mailservers.requestAllHistoricMessages()
except Exception as e:
let errDesription = e.msg
error "error: ", methodName="mailserver-requestAllHistoricMessages", errDesription
proc syncChatFromSyncedFrom*(self: MailserverController, chatId: string) =
try:
discard status_mailservers.syncChatFromSyncedFrom(chatId)
except Exception as e:
let errDesription = e.msg
error "error: ", methodName="mailserver-syncChatFromSyncedFrom", errDesription
proc fillGaps*(self: MailserverController, chatId: string, messageIds: seq[string]) =
try:
discard status_mailservers.fillGaps(chatId, messageIds)
except Exception as e:
let errDesription = e.msg
error "error: ", methodName="mailserver-fillGaps", errDesription
proc disconnectActiveMailserver*(self: MailserverController) =
try:
discard status_mailservers.disconnectActiveMailserver()
except Exception as e:
let errDesription = e.msg
error "error: ", methodName="mailserver-disconnectActiveMailserver", errDesription

View File

@ -1,45 +0,0 @@
import chronos, chronicles
import ../../../../../app_service/service/node_configuration/service_interface as node_config_service
import controller
logScope:
topics = "mailserver model"
type
MailserverModel* = ref object
mailserverController: MailserverController
proc newMailserverModel*(vptr: ByteAddress): MailserverModel =
result = MailserverModel()
result.mailserverController = cast[MailserverController](vptr)
proc disconnectActiveMailserver(self: MailserverModel) =
try:
warn "Disconnecting active mailserver due to error"
self.mailserverController.disconnectActiveMailserver()
except Exception as e:
error "error: ", errDescription=e.msg
proc requestMessages*(self: MailserverModel) =
try:
info "Requesting message history"
self.mailserverController.requestAllHistoricMessages()
except Exception as e:
error "error: ", errDescription=e.msg
self.disconnectActiveMailserver()
proc requestMoreMessages*(self: MailserverModel, chatId: string) =
try:
info "Requesting more messages for", chatId=chatId
self.mailserverController.syncChatFromSyncedFrom(chatId)
except Exception as e:
error "error: ", errDescription=e.msg
self.disconnectActiveMailserver()
proc fillGaps*(self: MailserverModel, chatId: string, messageIds: seq[string]) =
try:
info "Requesting fill gaps from", chatId=chatId
self.mailserverController.fillGaps(chatId, messageIds)
except Exception as e:
error "error: ", errDescription=e.msg
self.disconnectActiveMailserver()

View File

@ -1,142 +0,0 @@
import # std libs
json, tables
import # vendor libs
chronicles, chronos, json_serialization, task_runner
import # status-desktop libs
../worker, ./model, ../../qt, ../../common as task_runner_common,
../common as methuselash_common
export
chronos, task_runner_common, json_serialization
logScope:
topics = "mailserver worker"
type
MailserverWorker* = ref object of MarathonWorker
# below are all custom marathon task arg definitions
IsActiveMailserverAvailableTaskArg* = ref object of MarathonTaskArg
GetActiveMailserverTaskArg* = ref object of MarathonTaskArg
RequestMessagesTaskArg* = ref object of MarathonTaskArg
chatId*: string
FillGapsTaskArg* = ref object of MarathonTaskArg
chatId*: string
messageIds*: seq[string]
AddMailserverTopicTaskArg* = ref object of MarathonTaskArg
PeerSummaryChangeTaskArg* = ref object of MarathonTaskArg
peers*: seq[string]
GetMailserverTopicsByChatIdTaskArg* = ref object of MarathonTaskArg
chatId*: string
fetchRange*: int
GetMailserverTopicsByChatIdsTaskArg* = ref object of MarathonTaskArg
chatIds*: seq[string]
fetchRange*: int
const
WORKER_NAME = "mailserver"
# forward declarations
proc workerThread(arg: WorkerThreadArg) {.thread.}
proc newMailserverWorker*(vptr: ByteAddress): MailserverWorker =
new(result)
result.chanRecvFromWorker = newAsyncChannel[ThreadSafeString](-1)
result.chanSendToWorker = newAsyncChannel[ThreadSafeString](-1)
result.vptr = vptr
method name*(self: MailserverWorker): string = WORKER_NAME
method init*(self: MailserverWorker) =
self.chanRecvFromWorker.open()
self.chanSendToWorker.open()
let arg = WorkerThreadArg(
chanSendToMain: self.chanRecvFromWorker,
chanRecvFromMain: self.chanSendToWorker,
vptr: self.vptr
)
createThread(self.thread, workerThread, arg)
# block until we receive "ready"
discard $(self.chanRecvFromWorker.recvSync())
method teardown*(self: MailserverWorker) =
self.chanSendToWorker.sendSync("shutdown".safe)
self.chanRecvFromWorker.close()
self.chanSendToWorker.close()
trace "waiting for the control thread to stop"
joinThread(self.thread)
method onLoggedIn*(self: MailserverWorker) =
self.chanSendToWorker.sendSync("loggedIn".safe)
proc processMessage(mailserverModel: MailserverModel, received: string) =
let
parsed = parseJson(received)
messageType = parsed{"$type"}.getStr
methodName = parsed{"method"}.getStr()
trace "initiating mailserver task", methodName=methodName, messageType=messageType
case methodName
of "requestAllHistoricMessages":
let taskArg = decode[RequestMessagesTaskArg](received)
mailserverModel.requestMessages()
taskArg.finish("") # TODO:
of "requestMessages":
let taskArg = decode[RequestMessagesTaskArg](received)
mailserverModel.requestMessages()
of "requestMoreMessages":
let taskArg = decode[RequestMessagesTaskArg](received)
mailserverModel.requestMoreMessages(taskArg.chatId)
of "fillGaps":
let taskArg = decode[FillGapsTaskArg](received)
mailserverModel.fillGaps(taskArg.chatId, taskArg.messageIds)
else:
error "unknown message", message=received
proc worker(arg: WorkerThreadArg) {.async, gcsafe, nimcall.} =
let
chanSendToMain = arg.chanSendToMain
chanRecvFromMain = arg.chanRecvFromMain
chanSendToMain.open()
chanRecvFromMain.open()
trace "sending 'ready' to main thread"
await chanSendToMain.send("ready".safe)
let mailserverModel = newMailserverModel(arg.vptr)
var unprocessedMsgs: seq[string] = @[]
# wait for "loggedIn" before initing mailserverModel and continuing
while true:
let received = $(await chanRecvFromMain.recv())
if received == "loggedIn":
break
elif received == "shutdown":
trace "received 'shutdown'"
trace "stopping worker"
return
else:
unprocessedMsgs.add received
for msg in unprocessedMsgs.items:
mailserverModel.processMessage(msg)
while true:
trace "waiting for message"
let received = $(await chanRecvFromMain.recv())
case received
of "shutdown":
trace "received 'shutdown'"
trace "stopping worker"
break
else:
mailserverModel.processMessage(received)
proc workerThread(arg: WorkerThreadArg) =
waitFor worker(arg)

View File

@ -6,6 +6,7 @@ import ../../../../../../app_service/service/contacts/service as contact_service
import ../../../../../../app_service/service/community/service as community_service
import ../../../../../../app_service/service/chat/service as chat_service
import ../../../../../../app_service/service/message/service as message_service
import ../../../../../../app_service/service/mailservers/service as mailservers_service
import ../../../../../../app_service/service/eth/utils as eth_utils
import ../../../../../core/signals/types
import ../../../../../core/eventemitter
@ -28,10 +29,11 @@ type
communityService: community_service.Service
chatService: chat_service.Service
messageService: message_service.Service
mailserversService: mailservers_service.Service
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, contactService: contact_service.Service, communityService: community_service.Service,
chatService: chat_service.Service, messageService: message_service.Service):
chatService: chat_service.Service, messageService: message_service.Service, mailserversService: mailservers_service.Service):
Controller =
result = Controller()
result.delegate = delegate
@ -44,6 +46,7 @@ proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter
result.communityService = communityService
result.chatService = chatService
result.messageService = messageService
result.mailserversService = mailserversService
method delete*(self: Controller) =
discard
@ -225,3 +228,9 @@ method increaseLoadingMessagesPerPageFactor*(self: Controller) =
method resetLoadingMessagesPerPageFactor*(self: Controller) =
self.loadingMessagesPerPageFactor = 1
method requestMoreMessages*(self: Controller) =
self.mailserversService.requestMoreMessages(self.chatId)
method fillGaps*(self: Controller, messageId: string) =
self.mailserversService.fillGaps(self.chatId, messageId)

View File

@ -89,3 +89,9 @@ method increaseLoadingMessagesPerPageFactor*(self: AccessInterface) {.base.} =
method resetLoadingMessagesPerPageFactor*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method requestMoreMessages*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method fillGaps*(self: AccessInterface, messageId: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -11,6 +11,7 @@ import ../../../../../../app_service/service/contacts/service as contact_service
import ../../../../../../app_service/service/community/service as community_service
import ../../../../../../app_service/service/chat/service as chat_service
import ../../../../../../app_service/service/message/service as message_service
import ../../../../../../app_service/service/mailservers/service as mailservers_service
export io_interface
@ -18,6 +19,7 @@ logScope:
topics = "messages-module"
const CHAT_IDENTIFIER_MESSAGE_ID = "chat-identifier-message-id"
const FETCH_MORE_MESSAGES_MESSAGE_ID = "fetch-more_messages-message-id"
type
Module* = ref object of io_interface.AccessInterface
@ -29,18 +31,19 @@ type
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, contactService: contact_service.Service, communityService: community_service.Service,
chatService: chat_service.Service, messageService: message_service.Service):
chatService: chat_service.Service, messageService: message_service.Service, mailserversService: mailservers_service.Service):
Module =
result = Module()
result.delegate = delegate
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, sectionId, chatId, belongsToCommunity, contactService,
communityService, chatService, messageService)
communityService, chatService, messageService, mailserversService)
result.moduleLoaded = false
# Forward declaration
proc createChatIdentifierItem(self: Module): Item
proc createFetchMoreMessagesItem(self: Module): Item
method delete*(self: Module) =
self.view.delete
@ -55,7 +58,7 @@ method isLoaded*(self: Module): bool =
return self.moduleLoaded
method viewDidLoad*(self: Module) =
# The first message in the model must be always ChatIdentifier message.
self.view.model().appendItem(self.createFetchMoreMessagesItem())
self.view.model().appendItem(self.createChatIdentifierItem())
self.moduleLoaded = true
@ -64,6 +67,31 @@ method viewDidLoad*(self: Module) =
method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant
proc createFetchMoreMessagesItem(self: Module): Item =
let chatDto = self.controller.getChatDetails()
let isIdenticon = false
result = initItem(
FETCH_MORE_MESSAGES_MESSAGE_ID,
responseToMessageWithId = "",
senderId = chatDto.id,
senderDisplayName = "",
senderLocalName = "",
senderIcon = "",
isIdenticon,
amISender = false,
outgoingStatus = "",
text = "",
image = "",
messageContainsMentions = false,
seen = true,
timestamp = 0,
ContentType.FetchMoreMessagesButton,
messageType = -1,
sticker = "",
stickerPack = -1,
@[],
)
proc createChatIdentifierItem(self: Module): Item =
let chatDto = self.controller.getChatDetails()
var chatName = chatDto.name
@ -160,9 +188,9 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
# messages are sorted from the most recent to the least recent one
viewItems.add(item)
# ChatIdentifier message will be always the first message (the oldest one)
viewItems.add(self.createFetchMoreMessagesItem())
viewItems.add(self.createChatIdentifierItem())
# Delete the old ChatIdentifier message first
self.view.model().removeItem(FETCH_MORE_MESSAGES_MESSAGE_ID)
self.view.model().removeItem(CHAT_IDENTIFIER_MESSAGE_ID)
# Add new loaded messages
self.view.model().appendItems(viewItems)
@ -349,3 +377,9 @@ method scrollToMessage*(self: Module, messageId: string) =
self.controller.setSearchedMessageId(messageId)
if(not self.checkIfMessageLoadedAndScrollToItIfItIs()):
self.loadMoreMessages()
method requestMoreMessages*(self: Module) =
self.controller.requestMoreMessages()
method fillGaps*(self: Module, messageId: string) =
self.controller.fillGaps(messageId)

View File

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

View File

@ -142,3 +142,10 @@ QtObject:
proc scrollMessagesUp(self: View) {.signal.}
proc emitScrollMessagesUpSignal*(self: View) =
self.scrollMessagesUp()
proc requestMoreMessages(self: View) {.slot.} =
self.delegate.requestMoreMessages()
proc fillGaps(self: View, messageId: string) {.slot.} =
self.delegate.fillGaps(messageId)

View File

@ -18,6 +18,7 @@ import ../../../../../app_service/service/chat/service as chat_service
import ../../../../../app_service/service/community/service as community_service
import ../../../../../app_service/service/gif/service as gif_service
import ../../../../../app_service/service/message/service as message_service
import ../../../../../app_service/service/mailservers/service as mailservers_service
export io_interface
@ -38,7 +39,8 @@ type
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, sectionId: string, chatId: string,
belongsToCommunity: bool, isUsersListAvailable: bool, settingsService: settings_service.ServiceInterface,
contactService: contact_service.Service, chatService: chat_service.Service,
communityService: community_service.Service, messageService: message_service.Service, gifService: gif_service.Service):
communityService: community_service.Service, messageService: message_service.Service, gifService: gif_service.Service,
mailserversService: mailservers_service.Service):
Module =
result = Module()
result.delegate = delegate
@ -50,7 +52,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitt
result.inputAreaModule = input_area_module.newModule(result, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService)
result.messagesModule = messages_module.newModule(result, events, sectionId, chatId, belongsToCommunity,
contactService, communityService, chatService, messageService)
contactService, communityService, chatService, messageService, mailserversService)
result.usersModule = users_module.newModule(result, events, sectionId, chatId, belongsToCommunity, isUsersListAvailable,
contactService, communityService, messageService)

View File

@ -9,6 +9,7 @@ import ../../../../app_service/service/chat/service as chat_service
import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service
import ../../../../app_service/service/gif/service as gif_service
import ../../../../app_service/service/mailservers/service as mailservers_service
import ../../../core/eventemitter
@ -28,11 +29,13 @@ type
communityService: community_service.Service
messageService: message_service.Service
gifService: gif_service.Service
mailserversService: mailservers_service.Service
proc newController*(delegate: io_interface.AccessInterface, sectionId: string, isCommunity: bool, events: EventEmitter,
settingsService: settings_service.ServiceInterface, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service, gifService: gif_service.Service): Controller =
messageService: message_service.Service, gifService: gif_service.Service,
mailserversService: mailservers_service.Service): Controller =
result = Controller()
result.delegate = delegate
result.sectionId = sectionId
@ -44,6 +47,7 @@ proc newController*(delegate: io_interface.AccessInterface, sectionId: string, i
result.communityService = communityService
result.messageService = messageService
result.gifService = gifService
result.mailserversService = mailserversService
method delete*(self: Controller) =
discard
@ -98,7 +102,8 @@ method init*(self: Controller) =
self.chatService,
self.communityService,
self.messageService,
self.gifService
self.gifService,
self.mailserversService
)
self.events.on(SIGNAL_COMMUNITY_CHANNEL_DELETED) do(e:Args):
@ -191,13 +196,13 @@ method createPublicChat*(self: Controller, chatId: string) =
let response = self.chatService.createPublicChat(chatId)
if(response.success):
self.delegate.addNewChat(response.chatDto, false, self.events, self.settingsService, self.contactService, self.chatService,
self.communityService, self.messageService, self.gifService)
self.communityService, self.messageService, self.gifService, self.mailserversService)
method createOneToOneChat*(self: Controller, chatId: string, ensName: string) =
let response = self.chatService.createOneToOneChat(chatId, ensName)
if(response.success):
self.delegate.addNewChat(response.chatDto, false, self.events, self.settingsService, self.contactService, self.chatService,
self.communityService, self.messageService, self.gifService)
self.communityService, self.messageService, self.gifService, self.mailserversService)
method leaveChat*(self: Controller, chatId: string) =
self.chatService.leaveChat(chatId)
@ -255,7 +260,7 @@ method createGroupChat*(self: Controller, groupName: string, pubKeys: seq[string
let response = self.chatService.createGroupChat(groupName, pubKeys)
if(response.success):
self.delegate.addNewChat(response.chatDto, false, self.events, self.settingsService, self.contactService, self.chatService,
self.communityService, self.messageService, self.gifService)
self.communityService, self.messageService, self.gifService, self.mailserversService)
method joinGroup*(self: Controller) =
self.chatService.confirmJoiningGroup(self.getActiveChatId())
@ -264,7 +269,7 @@ method joinGroupChatFromInvitation*(self: Controller, groupName: string, chatId:
let response = self.chatService.createGroupChatFromInvitation(groupName, chatId, adminPK)
if(response.success):
self.delegate.addNewChat(response.chatDto, false, self.events, self.settingsService, self.contactService, self.chatService,
self.communityService, self.messageService, self.gifService)
self.communityService, self.messageService, self.gifService, self.mailserversService)
method acceptRequestToJoinCommunity*(self: Controller, requestId: string) =
self.communityService.acceptRequestToJoinCommunity(self.sectionId, requestId)

View File

@ -14,6 +14,7 @@ import ../../../../app_service/service/contacts/service as contact_service
import ../../../../app_service/service/chat/service as chat_service
import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service
import ../../../../app_service/service/mailservers/service as mailservers_service
import ../../../../app_service/service/gif/service as gif_service
export io_interface
@ -42,11 +43,12 @@ proc newModule*(
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service
): Module =
result = Module()
result.delegate = delegate
result.controller = controller.newController(result, sectionId, isCommunity, events, settingsService, contactService,
chatService, communityService, messageService, gifService)
chatService, communityService, messageService, gifService, mailserversService)
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.moduleLoaded = false
@ -76,10 +78,11 @@ proc addSubmodule(self: Module, chatId: string, belongToCommunity: bool, isUsers
chatService: chat_service.Service,
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service) =
gifService: gif_service.Service,
mailserversService: mailservers_service.Service) =
self.chatContentModules[chatId] = chat_content_module.newModule(self, events, self.controller.getMySectionId(), chatId,
belongToCommunity, isUsersListAvailable, settingsService, contactService, chatService, communityService,
messageService, gifService)
messageService, gifService, mailserversService)
proc removeSubmodule(self: Module, chatId: string) =
if(not self.chatContentModules.contains(chatId)):
@ -92,7 +95,8 @@ proc buildChatUI(self: Module, events: EventEmitter,
chatService: chat_service.Service,
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service) =
gifService: gif_service.Service,
mailserversService: mailservers_service.Service) =
let types = @[ChatType.OneToOne, ChatType.Public, ChatType.PrivateGroupChat]
let chats = self.controller.getChatDetailsForChatTypes(types)
@ -114,7 +118,7 @@ proc buildChatUI(self: Module, events: EventEmitter,
hasNotification, notificationsCount, c.muted, active = false, c.position, c.categoryId)
self.view.chatsModel().appendItem(item)
self.addSubmodule(c.id, false, isUsersListAvailable, events, settingsService, contactService, chatService,
communityService, messageService, gifService)
communityService, messageService, gifService, mailserversService)
# make the first Public chat active when load the app
if(selectedItemId.len == 0 and c.chatType == ChatType.Public):
@ -128,7 +132,8 @@ proc buildCommunityUI(self: Module, events: EventEmitter,
chatService: chat_service.Service,
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service) =
gifService: gif_service.Service,
mailserversService: mailservers_service.Service) =
var selectedItemId = ""
var selectedSubItemId = ""
let communities = self.controller.getJoinedCommunities()
@ -149,7 +154,7 @@ proc buildCommunityUI(self: Module, events: EventEmitter,
chatDto.muted, active = false, c.position, c.categoryId)
self.view.chatsModel().appendItem(channelItem)
self.addSubmodule(chatDto.id, true, true, events, settingsService, contactService, chatService, communityService,
messageService, gifService)
messageService, gifService, mailserversService)
# make the first channel which doesn't belong to any category active when load the app
if(selectedItemId.len == 0):
@ -179,7 +184,7 @@ proc buildCommunityUI(self: Module, events: EventEmitter,
false, c.position)
categoryChannels.add(channelItem)
self.addSubmodule(chatDto.id, true, true, events, settingsService, contactService, chatService, communityService,
messageService, gifService)
messageService, gifService, mailserversService)
# in case there is no channels beyond categories,
# make the first channel of the first category active when load the app
@ -237,14 +242,15 @@ method load*(self: Module, events: EventEmitter,
chatService: chat_service.Service,
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service) =
gifService: gif_service.Service,
mailserversService: mailservers_service.Service) =
self.controller.init()
self.view.load()
if(self.controller.isCommunity()):
self.buildCommunityUI(events, settingsService, contactService, chatService, communityService, messageService, gifService)
self.buildCommunityUI(events, settingsService, contactService, chatService, communityService, messageService, gifService, mailserversService)
else:
self.buildChatUI(events, settingsService, contactService, chatService, communityService, messageService, gifService)
self.buildChatUI(events, settingsService, contactService, chatService, communityService, messageService, gifService, mailserversService)
self.initContactRequestsModel() # we do this only in case of chat section (not in case of communities)
for cModule in self.chatContentModules.values:
@ -352,7 +358,8 @@ method addNewChat*(
chatService: chat_service.Service,
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service) =
gifService: gif_service.Service,
mailserversService: mailservers_service.Service) =
let hasNotification = chatDto.unviewedMessagesCount > 0 or chatDto.unviewedMentionsCount > 0
let notificationsCount = chatDto.unviewedMentionsCount
var chatName = chatDto.name
@ -373,7 +380,7 @@ method addNewChat*(
chatDto.chatType.int, amIChatAdmin, hasNotification, notificationsCount, chatDto.muted,
active = false, position = 0, chatDto.categoryId)
self.addSubmodule(chatDto.id, belongsToCommunity, isUsersListAvailable, events, settingsService, contactService, chatService,
communityService, messageService, gifService)
communityService, messageService, gifService, mailserversService)
self.chatContentModules[chatDto.id].load()
self.view.chatsModel().appendItem(item)
# make new added chat active one
@ -384,7 +391,7 @@ method addNewChat*(
chatDto.description, chatDto.chatType.int, amIChatAdmin, hasNotification, notificationsCount, chatDto.muted,
false, chatDto.position)
self.addSubmodule(chatDto.id, belongsToCommunity, isUsersListAvailable, events, settingsService, contactService, chatService,
communityService, messageService, gifService)
communityService, messageService, gifService, mailserversService)
self.chatContentModules[chatDto.id].load()
categoryItem.appendSubItem(channelItem)
self.setActiveItemSubItem(categoryItem.id, channelItem.id)

View File

@ -6,6 +6,7 @@ import ../../../../../app_service/service/chat/service as chat_service
import ../../../../../app_service/service/community/service as community_service
import ../../../../../app_service/service/message/service as message_service
import ../../../../../app_service/service/gif/service as gif_service
import ../../../../../app_service/service/mailservers/service as mailservers_service
import ../../../../core/eventemitter
@ -18,7 +19,8 @@ method load*(self: AccessInterface, events: EventEmitter,
chatService: chat_service.Service,
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service) {.base.} =
gifService: gif_service.Service,
mailserversService: mailservers_service.Service) {.base.} =
raise newException(ValueError, "No implementation available")
method isLoaded*(self: AccessInterface): bool {.base.} =

View File

@ -7,7 +7,8 @@ method makeChatWithIdActive*(self: AccessInterface, chatId: string) {.base.} =
method addNewChat*(self: AccessInterface, chatDto: ChatDto, belongsToCommunity: bool, events: EventEmitter,
settingsService: settings_service.ServiceInterface, contactService: contact_service.Service,
chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service, gifService: gif_service.Service) {.base.} =
messageService: message_service.Service, gifService: gif_service.Service,
mailserversService: mailservers_service.Service) {.base.} =
raise newException(ValueError, "No implementation available")
method onNewMessagesReceived*(self: AccessInterface, chatId: string, unviewedMessagesCount: int,

View File

@ -181,7 +181,6 @@ QtObject:
proc joinGroupChatFromInvitation*(self: View, groupName: string, chatId: string, adminPK: string) {.slot.} =
self.delegate.joinGroupChatFromInvitation(groupName, chatId, adminPK)
proc acceptRequestToJoinCommunity*(self: View, requestId: string) {.slot.} =
self.delegate.acceptRequestToJoinCommunity(requestId)

View File

@ -12,6 +12,7 @@ import ../../../app_service/service/community/service as community_service
import ../../../app_service/service/contacts/service as contacts_service
import ../../../app_service/service/message/service as message_service
import ../../../app_service/service/gif/service as gif_service
import ../../../app_service/service/mailservers/service as mailservers_service
import ../../../app_service/service/privacy/service as privacy_service
export controller_interface
@ -32,6 +33,7 @@ type
contactsService: contacts_service.Service
gifService: gif_service.Service
privacyService: privacy_service.Service
mailserversService: mailservers_service.Service
activeSectionId: string
proc newController*(delegate: io_interface.AccessInterface,
@ -45,6 +47,7 @@ proc newController*(delegate: io_interface.AccessInterface,
messageService: message_service.Service,
gifService: gif_service.Service,
privacyService: privacy_service.Service,
mailserversService: mailservers_service.Service
):
Controller =
result = Controller()
@ -59,6 +62,7 @@ proc newController*(delegate: io_interface.AccessInterface,
result.messageService = messageService
result.gifService = gifService
result.privacyService = privacyService
result.mailserversService = mailserversService
method delete*(self: Controller) =
discard
@ -95,6 +99,7 @@ method init*(self: Controller) =
self.communityService,
self.messageService,
self.gifService,
self.mailserversService
)
self.events.on(TOGGLE_SECTION) do(e:Args):
@ -112,6 +117,7 @@ method init*(self: Controller) =
self.communityService,
self.messageService,
self.gifService,
self.mailserversService
)
self.events.on(SIGNAL_COMMUNITY_LEFT) do(e:Args):

View File

@ -118,12 +118,13 @@ proc newModule*[T](
messageService,
gifService,
privacyService,
mailserversService
)
result.moduleLoaded = false
# Submodules
result.chatSectionModule = chat_section_module.newModule(result, events, conf.CHAT_SECTION_ID, false, settingsService,
contactsService, chatService, communityService, messageService, gifService)
contactsService, chatService, communityService, messageService, gifService, mailserversService)
result.communitySectionsModule = initOrderedTable[string, chat_section_module.AccessInterface]()
result.walletSectionModule = wallet_section_module.newModule[Module[T]](
result, events, tokenService,
@ -206,6 +207,7 @@ method load*[T](
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service
) =
singletonInstance.engine.setRootContextProperty("mainModule", self.viewVariant)
self.controller.init()
@ -226,6 +228,7 @@ method load*[T](
communityService,
messageService,
gifService,
mailserversService
)
var activeSection: SectionItem
@ -334,9 +337,9 @@ method load*[T](
activeSection = profileSettingsSectionItem
# Load all sections
self.chatSectionModule.load(events, settingsService, contactsService, chatService, communityService, messageService, gifService)
self.chatSectionModule.load(events, settingsService, contactsService, chatService, communityService, messageService, gifService, mailserversService)
for cModule in self.communitySectionsModule.values:
cModule.load(events, settingsService, contactsService, chatService, communityService, messageService, gifService)
cModule.load(events, settingsService, contactsService, chatService, communityService, messageService, gifService, mailserversService)
self.walletSectionModule.load()
# self.walletV2SectionModule.load()
self.browserSectionModule.load()
@ -522,6 +525,7 @@ method communityJoined*[T](
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service
) =
var firstCommunityJoined = false
if (self.communitySectionsModule.len == 0):
@ -537,8 +541,9 @@ method communityJoined*[T](
communityService,
messageService,
gifService,
mailserversService
)
self.communitySectionsModule[community.id].load(events, settingsService, contactsService, chatService, communityService, messageService, gifService)
self.communitySectionsModule[community.id].load(events, settingsService, contactsService, chatService, communityService, messageService, gifService, mailserversService)
let communitySectionItem = self.createCommunityItem(community)
if (firstCommunityJoined):

View File

@ -4,6 +4,7 @@ import ../../../../app_service/service/chat/service as chat_service
import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service
import ../../../../app_service/service/gif/service as gif_service
import ../../../../app_service/service/mailservers/service as mailservers_service
import ../../../core/eventemitter
@ -19,6 +20,7 @@ method load*(
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service
)
{.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -21,7 +21,8 @@ method communityJoined*(self: AccessInterface, community: CommunityDto, events:
chatService: chat_service.Service,
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service) {.base.} =
gifService: gif_service.Service,
mailserversService: mailservers_service.Service) {.base.} =
raise newException(ValueError, "No implementation available")
method communityEdited*(self: AccessInterface, community: CommunityDto) {.base.} =

View File

@ -4,7 +4,7 @@ import ./dto/mailserver as mailserver_dto
import ../../../app/core/signals/types
import ../../../app/core/fleets/fleet_configuration
import ../../../app/core/[main]
import ../../../app/core/tasks/marathon/mailserver/worker
import ../../../app/core/tasks/[qt, threadpool]
import ../settings/service_interface as settings_service
import ../node_configuration/service_interface as node_configuration_service
import status/mailservers as status_mailservers
@ -16,14 +16,53 @@ type
ActiveMailserverChangedArgs* = ref object of Args
nodeAddress*: string
MailserverAvailableArgs* = ref object of Args
RequestMessagesTaskArg = ref object of QObjectTaskArg
RequestMoreMessagesTaskArg = ref object of QObjectTaskArg
chatId*: string
FillGapsTaskArg* = ref object of QObjectTaskArg
chatId*: string
messageIds*: seq[string]
# Signals which may be emitted by this service:
const SIGNAL_ACTIVE_MAILSERVER_CHANGED* = "activeMailserverChanged"
const SIGNAL_MAILSERVER_AVAILABLE* = "mailserverAvailable"
const requestMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[RequestMessagesTaskArg](argEncoded)
try:
info "Requesting message history"
discard status_mailservers.requestAllHistoricMessages()
except Exception as e:
warn "Disconnecting active mailserver due to error", errDescription=e.msg
discard status_mailservers.disconnectActiveMailserver()
const requestMoreMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[RequestMoreMessagesTaskArg](argEncoded)
try:
info "Requesting additional message history for chat", chatId=arg.chatId
discard status_mailservers.syncChatFromSyncedFrom(arg.chatId)
except Exception as e:
warn "Disconnecting active mailserver due to error", errDescription=e.msg
discard status_mailservers.disconnectActiveMailserver()
const fillGapsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[FillGapsTaskArg](argEncoded)
try:
info "Requesting fill gaps", chatId=arg.chatId, messageIds=arg.messageIds
discard status_mailservers.fillGaps(arg.chatId, arg.messageIds)
except Exception as e:
warn "Disconnecting active mailserver due to error", errDescription=e.msg
discard status_mailservers.disconnectActiveMailserver()
QtObject:
type Service* = ref object of QObject
mailservers: seq[tuple[name: string, nodeAddress: string]]
events: EventEmitter
marathon: Marathon
threadpool: ThreadPool
settingsService: settings_service.ServiceInterface
nodeConfigurationService: node_configuration_service.ServiceInterface
fleetConfiguration: FleetConfiguration
@ -36,13 +75,14 @@ QtObject:
proc delete*(self: Service) =
self.QObject.delete
proc newService*(events: EventEmitter, marathon: Marathon, settingsService: settings_service.ServiceInterface,
proc newService*(events: EventEmitter, threadpool: ThreadPool,
settingsService: settings_service.ServiceInterface,
nodeConfigurationService: node_configuration_service.ServiceInterface,
fleetConfiguration: FleetConfiguration): Service =
new(result, delete)
result.QObject.setup
result.events = events
result.marathon = marathon
result.threadpool = threadpool
result.settingsService = settingsService
result.nodeConfigurationService = nodeConfigurationService
result.fleetConfiguration = fleetConfiguration
@ -52,6 +92,30 @@ QtObject:
self.initMailservers()
self.fetchMailservers()
proc requestMessages(self: Service) =
let arg = RequestMessagesTaskArg(
tptr: cast[ByteAddress](requestMessagesTask),
vptr: cast[ByteAddress](self.vptr)
)
self.threadpool.start(arg)
proc requestMoreMessages*(self: Service, chatId: string) =
let arg = RequestMoreMessagesTaskArg(
tptr: cast[ByteAddress](requestMoreMessagesTask),
vptr: cast[ByteAddress](self.vptr),
chatId: chatId
)
self.threadpool.start(arg)
proc fillGaps*(self: Service, chatId: string, messageId: string) =
let arg = FillGapsTaskArg(
tptr: cast[ByteAddress](fillGapsTask),
vptr: cast[ByteAddress](self.vptr),
chatId: chatId,
messageIds: @[messageId]
)
self.threadpool.start(arg)
proc doConnect(self: Service) =
self.events.on(SignalType.MailserverChanged.event) do(e: Args):
let receivedData = MailserverChangedSignal(e)
@ -60,6 +124,12 @@ QtObject:
let data = ActiveMailserverChangedArgs(nodeAddress: address)
self.events.emit(SIGNAL_ACTIVE_MAILSERVER_CHANGED, data)
self.events.on(SignalType.MailserverAvailable.event) do(e: Args):
info "mailserver available"
self.requestMessages()
let data = MailserverAvailableArgs()
self.events.emit(SIGNAL_MAILSERVER_AVAILABLE, data)
self.events.on(SignalType.HistoryRequestStarted.event) do(e: Args):
let h = HistoryRequestStartedSignal(e)
info "history request started", requestId=h.requestId, numBatches=h.numBatches

View File

@ -88,7 +88,6 @@ proc mainProc() =
let isProductionQVariant = newQVariant(if defined(production): true else: false)
let isExperimentalQVariant = newQVariant(isExperimental)
let signalsManagerQVariant = newQVariant(statusFoundation.signalsManager)
let mailserverControllerQVariant = newQVariant(statusFoundation.mailserverController)
QResource.registerResource(app.applicationDirPath & resourcesPath)
# Register events objects
@ -107,7 +106,6 @@ proc mainProc() =
singletonInstance.engine.setRootContextProperty("singleInstance", newQVariant(singleInstance))
singletonInstance.engine.setRootContextProperty("isExperimental", isExperimentalQVariant)
singletonInstance.engine.setRootContextProperty("signals", signalsManagerQVariant)
singletonInstance.engine.setRootContextProperty("mailserver", mailserverControllerQVariant)
singletonInstance.engine.setRootContextProperty("production", isProductionQVariant)
app.installEventFilter(dockShowAppEvent)
@ -119,7 +117,6 @@ proc mainProc() =
isProductionQVariant.delete()
isExperimentalQVariant.delete()
signalsManagerQVariant.delete()
mailserverControllerQVariant.delete()
networkAccessFactory.delete()
dockShowAppEvent.delete()
osThemeEvent.delete()

View File

@ -188,10 +188,21 @@ QtObject {
return msg
}
function getLinkPreviewData(url, uuid) {
if(!messageModule)
return
return messageModule.getLinkPreviewData(url, uuid)
}
function requestMoreMessages() {
if(!messageModule)
return
return messageModule.requestMoreMessages();
}
function fillGaps(messageId) {
if(!messageModule)
return
return messageModule.fillGaps(messageId);
}
}

View File

@ -244,10 +244,9 @@ Column {
id: gapComponent
GapComponent {
onClicked: {
// Not Refactored Yet - Should do it via messageStore
// root.chatsModel.messageView.fillGaps(messageStore.messageId);
// root.visible = false;
// root.height = 0;
messageStore.fillGaps(messageId)
root.visible = false;
root.height = 0;
}
}
}
@ -258,8 +257,7 @@ Column {
nextMessageIndex: root.nextMessageIndex
nextMsgTimestamp: root.nextMsgTimestamp
onTimerTriggered: {
// Not Refactored Yet - Should do it via messageStore
// root.chatsModel.requestMoreMessages(Constants.fetchRangeLast24Hours);
messageStore.requestMoreMessages();
}
}
}