diff --git a/src/app/chat/event_handling.nim b/src/app/chat/event_handling.nim index 21dc65f834..1e0540559b 100644 --- a/src/app/chat/event_handling.nim +++ b/src/app/chat/event_handling.nim @@ -43,6 +43,12 @@ proc handleChatEvents(self: ChatController) = var msg = MessageSentArgs(e) self.view.markMessageAsSent(msg.chatId, msg.id) + self.status.events.on("chat:disconnected") do(e: Args): + self.view.setConnected(false) + + self.status.events.on("chat:connected") do(e: Args): + self.view.setConnected(true) + proc handleMailserverEvents(self: ChatController) = self.status.events.on("mailserverTopics") do(e: Args): self.status.mailservers.addTopics(TopicArgs(e).topics) diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index df5a2c1424..27fc5df86a 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -28,6 +28,7 @@ QtObject: recentStickers*: StickerList replyTo: string channelOpenTime*: Table[string, int64] + connected: bool proc setup(self: ChatsView) = self.QAbstractListModel.setup @@ -43,6 +44,7 @@ QtObject: proc newChatsView*(status: Status): ChatsView = new(result, delete) result.status = status + result.connected = false result.chats = newChannelsList(status) result.activeChannel = newChatItemView(status) result.messageList = initTable[string, ChatMessageList]() @@ -270,3 +272,16 @@ QtObject: proc ensResolved(self: ChatsView, pubKey: string) {.slot.} = self.ensWasResolved(pubKey) + + proc isConnected*(self: ChatsView): bool {.slot.} = + result = self.connected + + proc onlineStatusChanged(self: ChatsView, connected: bool) {.signal.} + + proc setConnected*(self: ChatsView, connected: bool) = + self.connected = connected + self.onlineStatusChanged(connected) + + QtProperty[bool] isOnline: + read = isConnected + notify = onlineStatusChanged diff --git a/src/app/node/core.nim b/src/app/node/core.nim index 2833b124b7..8e24a78d0d 100644 --- a/src/app/node/core.nim +++ b/src/app/node/core.nim @@ -1,6 +1,7 @@ import NimQml, chronicles import ../../signals/types -import ../../status/[status, node] +import ../../status/[status, node, network] +import ../../status/libstatus/types as status_types import view logScope: @@ -24,7 +25,16 @@ proc delete*(self: NodeController) = proc init*(self: NodeController) = discard +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) = - debug "New signal received" - var msg = cast[WalletSignal](data) - self.view.setLastMessage(msg.content) + 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 + diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index 0f5438c850..ea01c0ba99 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -107,6 +107,7 @@ proc mainProc() = 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) diff --git a/src/status/network.nim b/src/status/network.nim new file mode 100644 index 0000000000..7dd29ef070 --- /dev/null +++ b/src/status/network.nim @@ -0,0 +1,25 @@ +import chronicles, eventemitter + +logScope: + topics = "network-model" + +type + NetworkModel* = ref object + peers*: seq[string] + events*: EventEmitter + +proc newNetworkModel*(events: EventEmitter): NetworkModel = + result = NetworkModel() + result.events = events + result.peers = @[] + +proc peerSummaryChange*(self: NetworkModel, peers: seq[string]) = + if peers.len == 0: + self.events.emit("chat:disconnected", Args()) + + if peers.len > 0 and self.peers.len == 0: + self.events.emit("chat:connected", Args()) + + self.peers = peers + +proc peerCount*(self: NetworkModel): int = self.peers.len diff --git a/src/status/status.nim b/src/status/status.nim index 63aeef8f6a..8dca1a1a71 100644 --- a/src/status/status.nim +++ b/src/status/status.nim @@ -13,6 +13,7 @@ import mailservers as mailservers import messages as messages import contacts as contacts import profile +import network as network type Status* = ref object events*: EventEmitter @@ -24,6 +25,7 @@ type Status* = ref object node*: NodeModel profile*: ProfileModel contacts*: ContactModel + network*: NetworkModel proc newStatusInstance*(): Status = result = Status() @@ -37,6 +39,7 @@ proc newStatusInstance*(): Status = result.messages = messages.newMessagesModel(result.events) result.profile = profile.newProfileModel() result.contacts = contacts.newContactModel(result.events) + result.network = network.newNetworkModel(result.events) proc initNode*(self: Status) = libstatus_accounts.initNode() diff --git a/ui/app/AppLayouts/Chat/ChatColumn.qml b/ui/app/AppLayouts/Chat/ChatColumn.qml index 121984ef30..553a45e48a 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn.qml @@ -11,6 +11,7 @@ StackLayout { property int chatGroupsListViewCount: 0 property bool isReply: false property var appSettings + property bool isConnected: false Layout.fillHeight: true Layout.fillWidth: true Layout.minimumWidth: 300 @@ -26,7 +27,49 @@ StackLayout { Layout.fillWidth: true z: 60 spacing: 0 - TopBar {} + TopBar { + id: topBar + } + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + z: 60 + Rectangle { + id: connectedStatusRect + Layout.fillWidth: true + height: 40; + color: isConnected ? Style.current.green : Style.current.darkGrey + visible: false + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: Style.current.white + id: connectedStatusLbl + text: isConnected ? + qsTr("Connected") : + qsTr("Disconnected") + } + } + + Timer { + id: timer + } + + Connections { + target: chatsModel + onOnlineStatusChanged: { + isConnected = connected + if(connected){ + timer.setTimeout(function(){ + connectedStatusRect.visible = false; + }, 5000); + } else { + connectedStatusRect.visible = true; + } + } + } } RowLayout { diff --git a/ui/imports/Themes/DarkTheme.qml b/ui/imports/Themes/DarkTheme.qml index e8761b52a6..46bee4b5ea 100644 --- a/ui/imports/Themes/DarkTheme.qml +++ b/ui/imports/Themes/DarkTheme.qml @@ -11,6 +11,7 @@ Theme { property color transparent: "#00000000" property color darkGrey: "#939BA1" property color lightBlueText: "#8f9fec" + property color green: "#41cd52" property color darkBlue: "#3c55c9" property color darkBlueBtn: "#5a70dd" diff --git a/ui/imports/Themes/LightTheme.qml b/ui/imports/Themes/LightTheme.qml index 8001cca7f7..b306ac0562 100644 --- a/ui/imports/Themes/LightTheme.qml +++ b/ui/imports/Themes/LightTheme.qml @@ -16,7 +16,7 @@ Theme { property color red: "#FF2D55" property color lightRed: "#FFEAEE" property color green: "#4EBC60" - + property color background: white property color border: grey property color textColor: black