refactor: move signals to status and generate events

This commit is contained in:
Richard Ramos 2020-09-02 09:30:40 -04:00 committed by Iuri Matias
parent 9ef82a2d7a
commit e52d287cf9
22 changed files with 103 additions and 175 deletions

View File

@ -2,7 +2,7 @@ import NimQml, eventemitter, chronicles, tables
import ../../status/chat as chat_model
import ../../status/mailservers as mailserver_model
import ../../status/messages as messages_model
import ../../signals/types
import ../../status/signals/types
import ../../status/libstatus/types as status_types
import ../../status/libstatus/settings as status_settings
import ../../status/[chat, contacts, status]
@ -11,7 +11,7 @@ import view, views/channels_list, views/message_list
logScope:
topics = "chat-controller"
type ChatController* = ref object of SignalSubscriber
type ChatController* = ref object
view*: ChatsView
status*: Status
variant*: QVariant
@ -32,6 +32,8 @@ include signal_handling
proc init*(self: ChatController) =
self.handleMailserverEvents()
self.handleChatEvents()
self.handleSignals()
self.status.mailservers.init()
self.status.chat.init()
self.view.obtainAvailableStickerPacks()
@ -42,12 +44,3 @@ proc init*(self: ChatController) =
for sticker in recentStickers:
self.view.addRecentStickerToList(sticker)
self.status.chat.addStickerToRecent(sticker)
method onSignal(self: ChatController, data: Signal) =
case data.signalType:
of SignalType.Message: handleMessage(self, MessageSignal(data))
of SignalType.DiscoverySummary: handleDiscoverySummary(self, DiscoverySummarySignal(data))
of SignalType.EnvelopeSent: handleEnvelopeSent(self, EnvelopeSentSignal(data))
of SignalType.EnvelopeExpired: handleEnvelopeExpired(self, EnvelopeExpiredSignal(data))
else:
warn "Unhandled signal received", signalType = data.signalType

View File

@ -1,16 +1,20 @@
proc handleSignals(self: ChatController) =
self.status.events.on(SignalType.Message.event) do(e:Args):
var data = MessageSignal(e)
self.status.chat.update(data.chats, data.messages, data.emojiReactions)
proc handleMessage(self: ChatController, data: MessageSignal) =
self.status.chat.update(data.chats, data.messages, data.emojiReactions)
self.status.events.on(SignalType.DiscoverySummary.event) do(e:Args):
## Handle mailserver peers being added and removed
var data = DiscoverySummarySignal(e)
self.status.mailservers.peerSummaryChange(data.enodes)
proc handleDiscoverySummary(self: ChatController, data: DiscoverySummarySignal) =
## Handle mailserver peers being added and removed
self.status.mailservers.peerSummaryChange(data.enodes)
self.status.events.on(SignalType.EnvelopeSent.event) do(e:Args):
var data = EnvelopeSentSignal(e)
self.status.messages.updateStatus(data.messageIds)
proc handleEnvelopeSent(self: ChatController, data: EnvelopeSentSignal) =
self.status.messages.updateStatus(data.messageIds)
proc handleEnvelopeExpired(self: ChatController, data: EnvelopeExpiredSignal) =
for messageId in data.messageIds:
if self.status.messages.messages.hasKey(messageId):
let chatId = self.status.messages.messages[messageId].chatId
self.view.messageList[chatId].checkTimeout(messageId)
self.status.events.on(SignalType.EnvelopeExpired.event) do(e:Args):
var data = EnvelopeExpiredSignal(e)
for messageId in data.messageIds:
if self.status.messages.messages.hasKey(messageId):
let chatId = self.status.messages.messages[messageId].chatId
self.view.messageList[chatId].checkTimeout(messageId)

View File

@ -1,11 +1,11 @@
import NimQml, eventemitter, chronicles, options, std/wrapnils
import ../../status/libstatus/types as status_types
import ../../signals/types
import ../../status/signals/types
import ../../status/status
import view
import ../../status/accounts as status_accounts
type LoginController* = ref object of SignalSubscriber
type LoginController* = ref object
status*: Status
view*: LoginView
variant*: QVariant
@ -20,34 +20,29 @@ proc delete*(self: LoginController) =
self.variant.delete
self.view.delete
proc reset*(self: LoginController) =
self.view.removeAccounts()
proc handleNodeLogin(self: LoginController, response: NodeSignal) =
if not self.view.isCurrentFlow: return
if self.view.currentAccount.account != nil:
self.view.setLastLoginResponse(response.event)
if ?.response.event.error == "":
self.status.events.emit("login", AccountArgs(account: self.view.currentAccount.account.toAccount))
proc init*(self: LoginController) =
let nodeAccounts = self.status.accounts.openAccounts()
self.status.accounts.nodeAccounts = nodeAccounts
for nodeAccount in nodeAccounts:
self.view.addAccountToList(nodeAccount)
proc reset*(self: LoginController) =
self.view.removeAccounts()
self.status.events.on(SignalType.NodeStopped.event) do(e:Args):
self.status.events.emit("nodeStopped", Args())
self.view.onLoggedOut()
proc handleNodeStopped(self: LoginController, data: Signal) =
self.status.events.emit("nodeStopped", Args())
self.view.onLoggedOut()
self.status.events.on(SignalType.NodeReady.event) do(e:Args):
self.status.events.emit("nodeReady", Args())
proc handleNodeLogin(self: LoginController, data: Signal) =
if not self.view.isCurrentFlow: return
let response = NodeSignal(data)
if self.view.currentAccount.account != nil:
self.view.setLastLoginResponse(response.event)
if ?.response.event.error == "":
self.status.events.emit("login", AccountArgs(account: self.view.currentAccount.account.toAccount))
proc handleNodeReady(self: LoginController, data: Signal) =
self.status.events.emit("nodeReady", Args())
method onSignal(self: LoginController, data: Signal) =
case data.signalType:
of SignalType.NodeLogin: handleNodeLogin(self, data)
of SignalType.NodeStopped: handleNodeStopped(self, data)
of SignalType.NodeReady: handleNodeReady(self, data)
else:
discard
self.status.events.on(SignalType.NodeLogin.event) do(e:Args):
self.handleNodeLogin(NodeSignal(e))

View File

@ -1,5 +1,5 @@
import NimQml, Tables, json, nimcrypto, strformat, json_serialization
import ../../signals/types
import ../../status/signals/types
import ../../status/libstatus/types as status_types
import ../../status/libstatus/accounts as status_accounts
import ../../status/accounts as AccountModel

View File

@ -1,13 +1,14 @@
import NimQml, chronicles
import ../../signals/types
import ../../status/signals/types
import ../../status/[status, node, network]
import ../../status/libstatus/types as status_types
import eventemitter
import view
logScope:
topics = "node"
type NodeController* = ref object of SignalSubscriber
type NodeController* = ref object
status*: Status
view*: NodeView
variant*: QVariant
@ -23,18 +24,8 @@ proc delete*(self: NodeController) =
delete self.view
proc init*(self: NodeController) =
discard
self.status.events.on(SignalType.Wallet.event) do(e:Args):
self.view.setLastMessage(WalletSignal(e).content)
proc handleWalletSignal(self: NodeController, data: WalletSignal) =
self.view.setLastMessage(data.content)
proc handleDiscoverySummary(self: NodeController, data: DiscoverySummarySignal) =
self.status.network.peerSummaryChange(data.enodes)
method onSignal(self: NodeController, data: Signal) =
case data.signalType:
of SignalType.Wallet: handleWalletSignal(self, WalletSignal(data))
of SignalType.DiscoverySummary: handleDiscoverySummary(self, DiscoverySummarySignal(data))
else:
warn "Unhandled signal received", signalType = data.signalType
self.status.events.on(SignalType.DiscoverySummary.event) do(e:Args):
self.status.network.peerSummaryChange(DiscoverySummarySignal(e).enodes)

View File

@ -3,10 +3,10 @@ import ../../status/libstatus/types as status_types
import ../../status/libstatus/accounts as status_accounts
import ../../status/accounts as AccountModel
import ../../status/status
import ../../signals/types
import ../../status/signals/types
import view
type OnboardingController* = ref object of SignalSubscriber
type OnboardingController* = ref object
view*: OnboardingView
variant*: QVariant
status: Status
@ -21,24 +21,21 @@ proc delete*(self: OnboardingController) =
delete self.variant
delete self.view
proc init*(self: OnboardingController) =
let accounts = self.status.accounts.generateAddresses()
for account in accounts:
self.view.addAccountToList(account)
proc reset*(self: OnboardingController) =
self.view.removeAccounts()
proc handleNodeLogin(self: OnboardingController, data: Signal) =
proc handleNodeLogin(self: OnboardingController, response: NodeSignal) =
if not self.view.isCurrentFlow: return
let response = NodeSignal(data)
if self.view.currentAccount.account != nil:
self.view.setLastLoginResponse(response.event)
if ?.response.event.error == "":
self.status.events.emit("login", AccountArgs(account: self.view.currentAccount.account.toAccount))
method onSignal(self: OnboardingController, data: Signal) =
case data.signalType:
of SignalType.NodeLogin: handleNodeLogin(self, data)
else:
discard
proc init*(self: OnboardingController) =
let accounts = self.status.accounts.generateAddresses()
for account in accounts:
self.view.addAccountToList(account)
self.status.events.on(SignalType.NodeLogin.event) do(e:Args):
self.handleNodeLogin(NodeSignal(e))

View File

@ -1,6 +1,6 @@
import NimQml, Tables, json, nimcrypto, strformat, json_serialization, strutils
import ../../status/libstatus/types as status_types
import ../../signals/types
import ../../status/signals/types
import ../../status/accounts as AccountModel
import ../../status/[status, wallet]
import views/account_info

View File

@ -1,7 +1,7 @@
import NimQml, json, eventemitter, strutils, sugar, sequtils
import json_serialization
import ../../status/libstatus/mailservers as status_mailservers
import ../../signals/types
import ../../status/signals/types
import ../../status/libstatus/accounts/constants
import ../../status/libstatus/types as status_types
import ../../status/libstatus/settings as status_settings
@ -14,7 +14,7 @@ import view
import views/ens_manager
import chronicles
type ProfileController* = ref object of SignalSubscriber
type ProfileController* = ref object
view*: ProfileView
variant*: QVariant
status*: Status
@ -70,11 +70,11 @@ proc init*(self: ProfileController, account: Account) =
let contacts = self.status.contacts.getContacts()
self.view.setContactList(contacts)
method onSignal(self: ProfileController, data: Signal) =
let msgData = MessageSignal(data);
if msgData.contacts.len > 0:
# TODO: view should react to model changes
self.status.chat.updateContacts(msgData.contacts)
self.view.updateContactList(msgData.contacts)
if msgData.installations.len > 0:
self.view.addDevices(msgData.installations)
self.status.events.on(SignalType.Message.event) do(e: Args):
let msgData = MessageSignal(e);
if msgData.contacts.len > 0:
# TODO: view should react to model changes
self.status.chat.updateContacts(msgData.contacts)
self.view.updateContactList(msgData.contacts)
if msgData.installations.len > 0:
self.view.addDevices(msgData.installations)

View File

@ -5,12 +5,11 @@ import views/[asset_list, account_list, account_item]
import ../../status/libstatus/wallet as status_wallet
import ../../status/libstatus/settings as status_settings
import ../../status/libstatus/types as status_types
import ../../signals/types
import ../../status/signals/types
import ../../status/[status, wallet]
import ../../status/wallet/account as WalletTypes
type WalletController* = ref object of SignalSubscriber
type WalletController* = ref object
status: Status
view*: WalletView
variant*: QVariant
@ -46,6 +45,6 @@ proc init*(self: WalletController) =
self.view.setEtherscanLink(status_settings.getCurrentNetworkDetails().etherscanLink)
self.view.setSigningPhrase(status_settings.getSetting[string](Setting.SigningPhrase))
method onSignal(self: WalletController, data: Signal) =
debug "New signal received"
discard
self.status.events.on(SignalType.Wallet.event) do(e:Args):
var data = WalletSignal(e)
debug "New signal received"

View File

@ -6,8 +6,7 @@ import app/node/core as node
import app/profile/core as profile
import app/onboarding/core as onboarding
import app/login/core as login
import signals/core as signals
import status/signals/core as signals
import status/libstatus/types
import nim_status
import status/status as statuslib
@ -51,7 +50,7 @@ proc mainProc() =
let engine = newQQmlApplicationEngine()
let signalController = signals.newController(app)
let signalController = signals.newController(status)
# We need this global variable in order to be able to access the application
# from the non-closure callback passed to `libstatus.setSignalEventCallback`
@ -86,7 +85,6 @@ proc mainProc() =
wallet.init()
chat.init()
engine.setRootContextProperty("loginModel", login.variant)
engine.setRootContextProperty("onboardingModel", onboarding.variant)
@ -132,22 +130,6 @@ proc mainProc() =
# 2. Re-init controllers that don't require a running node
initControllers()
signalController.init()
signalController.addSubscriber(SignalType.Wallet, wallet)
signalController.addSubscriber(SignalType.Wallet, node)
signalController.addSubscriber(SignalType.DiscoverySummary, node)
signalController.addSubscriber(SignalType.Message, chat)
signalController.addSubscriber(SignalType.Message, profile)
signalController.addSubscriber(SignalType.DiscoverySummary, chat)
signalController.addSubscriber(SignalType.EnvelopeSent, chat)
signalController.addSubscriber(SignalType.EnvelopeExpired, chat)
signalController.addSubscriber(SignalType.NodeLogin, login)
signalController.addSubscriber(SignalType.NodeLogin, onboarding)
signalController.addSubscriber(SignalType.NodeStopped, login)
signalController.addSubscriber(SignalType.NodeStarted, login)
signalController.addSubscriber(SignalType.NodeReady, login)
engine.setRootContextProperty("signals", signalController.variant)
engine.load(newQUrl("qrc:///main.qml"))

View File

@ -7,7 +7,7 @@ import libstatus/types
import mailservers
import profile/profile
import chat/[chat, message]
import ../signals/messages
import signals/messages
import ens
import eth/common/eth_types
from eth/common/utils import parseAddress

View File

@ -5,7 +5,7 @@ import core
import utils as utils
import types as types
import accounts/constants
import ../../signals/types as signal_types
import ../signals/types as signal_types
import ../wallet/account
proc getNetworkConfig(currentNetwork: string): JsonNode =

View File

@ -1,7 +1,7 @@
import json, times, strutils, sequtils, chronicles, json_serialization
import core, utils
import ../chat/[chat, message]
import ../../signals/messages
import ../signals/messages
import ./types
import ./settings

View File

@ -1,4 +1,4 @@
import core, ./types, ../../signals/types as statusgo_types, ./accounts/constants, ./utils
import core, ./types, ../signals/types as statusgo_types, ./accounts/constants, ./utils
import json, tables, sugar, sequtils
import json_serialization
import locks

View File

@ -21,6 +21,9 @@ type SignalType* {.pure.} = enum
WhisperFilterAdded = "whisper.filter.added"
Unknown
proc event*(self:SignalType):string =
result = "signal:" & $self
type GasPricePrediction* = object
safeLow*: string
standard*: string

View File

@ -1,41 +1,28 @@
import NimQml, tables, json, chronicles, strutils, json_serialization
import ../status/libstatus/types as status_types
import NimQml, eventemitter, tables, json, chronicles, strutils, json_serialization
import ../libstatus/types as status_types
import types, messages, discovery, whisperFilter, envelopes, expired
import ../status
logScope:
topics = "signals"
QtObject:
type SignalsController* = ref object of QObject
app: QApplication
statusSignal: string
signalSubscribers*: Table[SignalType, seq[SignalSubscriber]]
variant*: QVariant
status*: Status
proc newController*(app: QApplication): SignalsController =
proc newController*(status: Status): SignalsController =
new(result)
result.app = app
result.statusSignal = ""
result.signalSubscribers = initTable[SignalType, seq[SignalSubscriber]]()
result.status = status
result.setup()
result.variant = newQVariant(result)
proc setup(self: SignalsController) =
self.QObject.setup
proc init*(self: SignalsController) =
discard
proc delete*(self: SignalsController) =
self.variant.delete
self.QObject.delete
self.signalSubscribers = initTable[SignalType, seq[SignalSubscriber]]()
proc addSubscriber*(self: SignalsController, signalType: SignalType, subscriber: SignalSubscriber) =
if not self.signalSubscribers.hasKey(signalType):
self.signalSubscribers[signalType] = @[]
self.signalSubscribers[signalType].add(subscriber)
proc processSignal(self: SignalsController, statusSignal: string) =
var jsonSignal: JsonNode
@ -58,8 +45,7 @@ QtObject:
signalType = SignalType.Unknown
return
var signal: Signal = Signal(signalType: signalType)
var signal: Signal
case signalType:
of SignalType.Message:
signal = messages.fromEvent(jsonSignal)
@ -78,27 +64,10 @@ QtObject:
else:
discard
signal.signalType = signalType
if not self.signalSubscribers.hasKey(signalType):
warn "Unhandled signal received", type = signalString
self.signalSubscribers[signalType] = @[]
for subscriber in self.signalSubscribers[signalType]:
subscriber.onSignal(signal)
proc statusSignal*(self: SignalsController): string {.slot.} =
result = self.statusSignal
self.status.events.emit(signalType.event, signal)
proc signalReceived*(self: SignalsController, signal: string) {.signal.}
proc receiveSignal(self: SignalsController, signal: string) {.slot.} =
self.statusSignal = signal
self.processSignal(signal)
self.signalReceived(signal)
QtProperty[string] statusSignal:
read = statusSignal
write = receiveSignal
notify = signalReceived

View File

@ -1,10 +1,10 @@
import json, random, re, strutils, sequtils, sugar, chronicles
import json_serialization
import ../status/libstatus/accounts as status_accounts
import ../status/libstatus/settings as status_settings
import ../status/libstatus/types as status_types
import ../status/chat/[chat, message]
import ../status/profile/[profile, devices]
import ../libstatus/accounts as status_accounts
import ../libstatus/settings as status_settings
import ../libstatus/types as status_types
import ../chat/[chat, message]
import ../profile/[profile, devices]
import types
proc toMessage*(jsonMsg: JsonNode): Message

View File

@ -1,11 +1,10 @@
import json, chronicles, json_serialization, tables
import ../status/libstatus/types
import ../status/chat/[chat, message]
import ../status/profile/[profile, devices]
import ../libstatus/types
import ../chat/[chat, message]
import ../profile/[profile, devices]
import eventemitter
type SignalSubscriber* = ref object of RootObj
type Signal* = ref object of RootObj
type Signal* = ref object of Args
signalType* {.serializedFieldName("type").}: SignalType
type StatusGoError* = object
@ -23,10 +22,6 @@ type EnvelopeSentSignal* = ref object of Signal
type EnvelopeExpiredSignal* = ref object of Signal
messageIds*: seq[string]
# Override this method
method onSignal*(self: SignalSubscriber, data: Signal) {.base.} =
error "onSignal must be overriden in controller. Signal is unhandled"
type MessageSignal* = ref object of Signal
messages*: seq[Message]
chats*: seq[Chat]