From 6e147499040facd821a65428d9c4aebf551e01f0 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Fri, 22 May 2020 19:33:36 -0400 Subject: [PATCH] simplify controllers and views, make everything more consistent simplify controllers and views, make everything more consistent refactor wallet to use asset model move some of wallet logic away from the controller move ChatMessage to model move chatItem model organize models folder simplify chat message and chat item rename messageList to message_list simply addresses in the controller rename mailservers list refactor how profile is set refactor/simplify profile view refactor/simplify adding mailservers rename wallet view simplify wallet assets rename nodeView to view extract channel list view extract channel list view refactor channel list / chats view move signals out of app folder address code reviews --- src/app/chat/core.nim | 27 ++---- src/app/chat/messages.nim | 18 ---- src/app/chat/view.nim | 93 ++++++------------- src/app/chat/views/channels_list.nim | 68 ++++++++++++++ .../message_list.nim} | 3 +- src/app/node/core.nim | 4 +- src/app/node/{nodeView.nim => view.nim} | 0 src/app/onboarding/core.nim | 5 +- src/app/onboarding/view.nim | 10 +- src/app/profile/core.nim | 14 +-- src/app/profile/profileView.nim | 59 ------------ src/app/profile/view.nim | 40 ++++++++ .../mailservers_list.nim} | 13 +-- src/app/profile/views/profile_info.nim | 37 ++++++++ src/app/wallet/core.nim | 37 +++----- src/app/wallet/view.nim | 41 ++++++++ src/app/wallet/views/asset_list.nim | 56 +++++++++++ src/app/wallet/walletView.nim | 78 ---------------- src/models/accounts.nim | 7 ++ src/models/chat.nim | 5 + .../chat/chat_item.nim} | 10 ++ src/models/chat/chat_message.nim | 38 ++++++++ src/models/profile.nim | 11 +++ src/models/wallet.nim | 40 ++++++++ src/nim_status_client.nim | 5 +- src/{app => }/signals/core.nim | 2 +- src/{app => }/signals/messages.nim | 3 +- src/{app => }/signals/types.nim | 3 +- src/status/types.nim | 2 +- ui/app/AppLayouts/Chat/ChatLayout.qml | 2 +- ui/app/AppLayouts/Profile/LeftTab.qml | 4 +- ui/app/AppLayouts/Wallet/LeftTab.qml | 2 +- 32 files changed, 429 insertions(+), 308 deletions(-) delete mode 100644 src/app/chat/messages.nim create mode 100644 src/app/chat/views/channels_list.nim rename src/app/chat/{messageList.nim => views/message_list.nim} (97%) rename src/app/node/{nodeView.nim => view.nim} (100%) delete mode 100644 src/app/profile/profileView.nim create mode 100644 src/app/profile/view.nim rename src/app/profile/{mailserversList.nim => views/mailservers_list.nim} (81%) create mode 100644 src/app/profile/views/profile_info.nim create mode 100644 src/app/wallet/view.nim create mode 100644 src/app/wallet/views/asset_list.nim delete mode 100644 src/app/wallet/walletView.nim rename src/{app/chat/chatItem.nim => models/chat/chat_item.nim} (61%) create mode 100644 src/models/chat/chat_message.nim create mode 100644 src/models/profile.nim create mode 100644 src/models/wallet.nim rename src/{app => }/signals/core.nim (96%) rename src/{app => }/signals/messages.nim (99%) rename src/{app => }/signals/types.nim (98%) diff --git a/src/app/chat/core.nim b/src/app/chat/core.nim index 934390922d..cc2e46345c 100644 --- a/src/app/chat/core.nim +++ b/src/app/chat/core.nim @@ -1,11 +1,9 @@ import NimQml import json, eventemitter import ../../status/chat as status_chat -import view -import chatItem -import messages -import ../signals/types import ../../models/chat as chat_model +import ../../signals/types +import view type ChatController* = ref object of SignalSubscriber view*: ChatsView @@ -25,12 +23,8 @@ proc delete*(self: ChatController) = proc init*(self: ChatController) = self.model.events.on("messageSent") do(e: Args): var sentMessage = MsgArgs(e) - - let chatMessage = newChatMessage() - chatMessage.userName = sentMessage.payload["alias"].str + var chatMessage = sentMessage.payload.toChatMessage() chatMessage.message = sentMessage.message - chatMessage.timestamp = $sentMessage.payload["timestamp"] - chatMessage.identicon = sentMessage.payload["identicon"].str chatMessage.isCurrentUser = true self.view.pushMessage(sentMessage.chatId, chatMessage) @@ -45,18 +39,9 @@ method onSignal(self: ChatController, data: Signal) = var messageSignal = cast[MessageSignal](data) for c in messageSignal.chats: - let channel = newChatitem() - channel.name = c.name - channel.lastMessage = c.lastMessage.text - channel.timestamp = c.timestamp - channel.unviewedMessagesCount = c.unviewedMessagesCount - self.view.updateChat(channel) + let channel = c.toChatItem() + self.view.updateChat(channel) for message in messageSignal.messages: - let chatMessage = newChatMessage() - chatMessage.userName = message.alias - chatMessage.message = message.text - chatMessage.timestamp = message.timestamp #TODO convert to date/time? - chatMessage.identicon = message.identicon - chatMessage.isCurrentUser = message.isCurrentUser + let chatMessage = message.toChatMessage() self.view.pushMessage(message.chatId, chatMessage) diff --git a/src/app/chat/messages.nim b/src/app/chat/messages.nim deleted file mode 100644 index bdb6df9189..0000000000 --- a/src/app/chat/messages.nim +++ /dev/null @@ -1,18 +0,0 @@ - -type ChatMessage* = ref object - userName*: string - message*: string - timestamp*: string - identicon*: string - isCurrentUser*: bool - -proc delete*(self: ChatMessage) = - discard - -proc newChatMessage*(): ChatMessage = - result = ChatMessage() - result.userName = "" - result.message = "" - result.timestamp = "0" - result.identicon = "" - result.isCurrentUser = false diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index aa0b282b2e..9ddc1bdec2 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -1,22 +1,14 @@ import NimQml import Tables -import messages -import messageList -import chatItem +import views/channels_list +import views/message_list import ../../models/chat -type - RoleNames {.pure.} = enum - Name = UserRole + 1, - LastMessage = UserRole + 2 - Timestamp = UserRole + 3 - UnreadMessages = UserRole + 4 - QtObject: type ChatsView* = ref object of QAbstractListModel model: ChatModel - chats: seq[ChatItem] + chats: ChannelsList callResult: string messageList: Table[string, ChatMessageList] activeChannel: string @@ -28,53 +20,32 @@ QtObject: proc newChatsView*(model: ChatModel): ChatsView = new(result, delete) result.model = model - result.chats = @[] + result.chats = newChannelsList(result.model) result.activeChannel = "" result.messageList = initTable[string, ChatMessageList]() result.setup() - proc upsertChannel(self: ChatsView, channel: string) = - if not self.messageList.hasKey(channel): - self.messageList[channel] = newChatMessageList() + proc getChatsList(self: ChatsView): QVariant {.slot.} = + return newQVariant(self.chats) - method rowCount(self: ChatsView, index: QModelIndex = nil): int = self.chats.len - - method data(self: ChatsView, index: QModelIndex, role: int): QVariant = - if not index.isValid: - return - if index.row < 0 or index.row >= self.chats.len: - return - - let chatItem = self.chats[index.row] - let chatItemRole = role.RoleNames - case chatItemRole: - of RoleNames.Name: result = newQVariant(chatItem.name) - of RoleNames.Timestamp: result = newQVariant($chatItem.timestamp) - of RoleNames.LastMessage: result = newQVariant(chatItem.lastMessage) - of RoleNames.UnreadMessages: result = newQVariant(chatItem.unviewedMessagesCount) - - method roleNames(self: ChatsView): Table[int, string] = - { - RoleNames.Name.int:"name", - RoleNames.Timestamp.int:"timestamp", - RoleNames.LastMessage.int: "lastMessage", - RoleNames.UnreadMessages.int: "unviewedMessagesCount" - }.toTable + QtProperty[QVariant] chats: + read = getChatsList proc onSend*(self: ChatsView, inputJSON: string) {.slot.} = discard self.model.sendMessage(self.activeChannel, inputJSON) - proc pushMessage*(self:ChatsView, channel: string, message: ChatMessage) = - self.upsertChannel(channel) - self.messageList[channel].add(message) - proc activeChannel*(self: ChatsView): string {.slot.} = self.activeChannel proc activeChannelChanged*(self: ChatsView) {.signal.} proc setActiveChannelByIndex*(self: ChatsView, index: int) {.slot.} = - if self.activeChannel == self.chats[index].name: return - self.activeChannel = self.chats[index].name + let selectedChannel = self.chats.getChannel(index) + if self.activeChannel == selectedChannel.name: return + self.activeChannel = selectedChannel.name + self.activeChannelChanged() + + proc setActiveChannel*(self: ChatsView, channel: string) = + self.activeChannel = channel self.activeChannelChanged() QtProperty[string] activeChannel: @@ -82,6 +53,14 @@ QtObject: write = setActiveChannel notify = activeChannelChanged + proc upsertChannel(self: ChatsView, channel: string) = + if not self.messageList.hasKey(channel): + self.messageList[channel] = newChatMessageList() + + proc pushMessage*(self:ChatsView, channel: string, message: ChatMessage) = + self.upsertChannel(channel) + self.messageList[channel].add(message) + proc getMessageList(self: ChatsView): QVariant {.slot.} = self.upsertChannel(self.activeChannel) return newQVariant(self.messageList[self.activeChannel]) @@ -90,33 +69,13 @@ QtObject: read = getMessageList notify = activeChannelChanged - proc setActiveChannel*(self: ChatsView, channel: string) = - self.activeChannel = channel - self.activeChannelChanged() - - proc addToList(self: ChatsView, channel: string): int = - if(self.activeChannel == ""): self.setActiveChannel(channel) - var chatItem = newChatItem() - chatItem.name = channel - self.upsertChannel(channel) - self.beginInsertRows(newQModelIndex(), self.chats.len, self.chats.len) - self.chats.add(chatItem) - self.endInsertRows() - - result = self.chats.len - 1 - proc joinChat*(self: ChatsView, channel: string): int {.slot.} = self.setActiveChannel(channel) if self.model.hasChannel(channel): - result = self.chats.findByName(channel) + result = self.chats.chats.findByName(channel) else: self.model.join(channel) - result = self.addToList(channel) + result = self.chats.addChatItemToList(ChatItem(name: channel)) proc updateChat*(self: ChatsView, chat: ChatItem) = - var idx = self.chats.findByName(chat.name) - if idx > -1: - self.chats[idx] = chat - var x = self.createIndex(idx,0,nil) - var y = self.createIndex(idx,0,nil) - self.dataChanged(x, y, @[RoleNames.Timestamp.int, RoleNames.LastMessage.int, RoleNames.UnreadMessages.int]) + self.chats.updateChat(chat) diff --git a/src/app/chat/views/channels_list.nim b/src/app/chat/views/channels_list.nim new file mode 100644 index 0000000000..1684e82ddd --- /dev/null +++ b/src/app/chat/views/channels_list.nim @@ -0,0 +1,68 @@ +import NimQml +import Tables + +import ../../../models/chat + +type + ChannelsRoles {.pure.} = enum + Name = UserRole + 1, + LastMessage = UserRole + 2 + Timestamp = UserRole + 3 + UnreadMessages = UserRole + 4 + +QtObject: + type + ChannelsList* = ref object of QAbstractListModel + model*: ChatModel + chats*: seq[ChatItem] + + proc setup(self: ChannelsList) = self.QAbstractListModel.setup + + proc delete(self: ChannelsList) = self.QAbstractListModel.delete + + proc newChannelsList*(model: ChatModel): ChannelsList = + new(result, delete) + result.model = model + result.setup() + + method rowCount(self: ChannelsList, index: QModelIndex = nil): int = self.chats.len + + method data(self: ChannelsList, index: QModelIndex, role: int): QVariant = + if not index.isValid: + return + if index.row < 0 or index.row >= self.chats.len: + return + + let chatItem = self.chats[index.row] + let chatItemRole = role.ChannelsRoles + case chatItemRole: + of ChannelsRoles.Name: result = newQVariant(chatItem.name) + of ChannelsRoles.Timestamp: result = newQVariant($chatItem.timestamp) + of ChannelsRoles.LastMessage: result = newQVariant(chatItem.lastMessage) + of ChannelsRoles.UnreadMessages: result = newQVariant(chatItem.unviewedMessagesCount) + + method roleNames(self: ChannelsList): Table[int, string] = + { + ChannelsRoles.Name.int:"name", + ChannelsRoles.Timestamp.int:"timestamp", + ChannelsRoles.LastMessage.int: "lastMessage", + ChannelsRoles.UnreadMessages.int: "unviewedMessagesCount" + }.toTable + + proc addChatItemToList*(self: ChannelsList, channel: ChatItem): int = + self.beginInsertRows(newQModelIndex(), self.chats.len, self.chats.len) + self.chats.add(channel) + self.endInsertRows() + + result = self.chats.len - 1 + + proc getChannel*(self: ChannelsList, index: int): ChatItem = + self.chats[index] + + proc updateChat*(self: ChannelsList, chat: ChatItem) = + var idx = self.chats.findByName(chat.name) + if idx > -1: + self.chats[idx] = chat + var x = self.createIndex(idx,0,nil) + var y = self.createIndex(idx,0,nil) + self.dataChanged(x, y, @[ChannelsRoles.Timestamp.int, ChannelsRoles.LastMessage.int, ChannelsRoles.UnreadMessages.int]) diff --git a/src/app/chat/messageList.nim b/src/app/chat/views/message_list.nim similarity index 97% rename from src/app/chat/messageList.nim rename to src/app/chat/views/message_list.nim index 7f15692cd4..20882a26e8 100644 --- a/src/app/chat/messageList.nim +++ b/src/app/chat/views/message_list.nim @@ -1,4 +1,5 @@ -import NimQml, messages, Tables +import NimQml, Tables +import ../../../models/chat type ChatMessageRoles {.pure.} = enum diff --git a/src/app/node/core.nim b/src/app/node/core.nim index 6d8b9992e4..6f9f9fa4e0 100644 --- a/src/app/node/core.nim +++ b/src/app/node/core.nim @@ -1,8 +1,8 @@ import NimQml import chronicles import "../../status/core" as status -import ../signals/types -import nodeView +import ../../signals/types +import view logScope: topics = "node" diff --git a/src/app/node/nodeView.nim b/src/app/node/view.nim similarity index 100% rename from src/app/node/nodeView.nim rename to src/app/node/view.nim diff --git a/src/app/onboarding/core.nim b/src/app/onboarding/core.nim index 03ee867e77..90c733fa47 100644 --- a/src/app/onboarding/core.nim +++ b/src/app/onboarding/core.nim @@ -1,7 +1,6 @@ import NimQml import ../../models/accounts as Models -# import ../../constants/constants -import ../signals/types +import ../../signals/types import eventemitter import view @@ -24,4 +23,4 @@ proc init*(self: OnboardingController) = let accounts = self.model.generateAddresses() for account in accounts: - self.view.addAddressToList(account.name, account.photoPath, account.address) + self.view.addAddressToList(account.toAddress()) diff --git a/src/app/onboarding/view.nim b/src/app/onboarding/view.nim index 526bd0c444..dfe11d766f 100644 --- a/src/app/onboarding/view.nim +++ b/src/app/onboarding/view.nim @@ -10,10 +10,6 @@ type Identicon = UserRole + 2, Key = UserRole + 3 -type - Address* = ref object - username*, identicon*, key*: string - QtObject: type OnboardingView* = ref object of QAbstractListModel addresses*: seq[Address] @@ -32,11 +28,9 @@ QtObject: result.addresses = @[] result.setup - proc addAddressToList*(self: OnboardingView, username: string, identicon: string, key: string) {.slot.} = + proc addAddressToList*(self: OnboardingView, address: Address) = self.beginInsertRows(newQModelIndex(), self.addresses.len, self.addresses.len) - self.addresses.add(Address(username : username, - identicon : identicon, - key : key)) + self.addresses.add(address) self.endInsertRows() method rowCount(self: OnboardingView, index: QModelIndex = nil): int = diff --git a/src/app/profile/core.nim b/src/app/profile/core.nim index 2e96c0d9e1..3a47e7360c 100644 --- a/src/app/profile/core.nim +++ b/src/app/profile/core.nim @@ -3,9 +3,10 @@ import strformat import json import "../../status/core" as status import ../../status/mailservers as status_mailservers -import ../signals/types -import profileView +import ../../signals/types +import view import "../../status/types" as status_types +import ../../models/profile type ProfileController* = ref object of SignalSubscriber view*: ProfileView @@ -21,9 +22,10 @@ proc delete*(self: ProfileController) = delete self.variant proc init*(self: ProfileController, account: Account) = - self.view.setUsername(account.name) - self.view.setIdenticon(account.photoPath) + let profile = account.toProfileModel() + self.view.setNewProfile(profile) var mailservers = status_mailservers.getMailservers() - for mailserver in mailservers: - self.view.addMailserverToList(mailserver[0], mailserver[1]) + for mailserver_config in mailservers: + let mailserver = MailServer(name: mailserver_config[0], endpoint: mailserver_config[1]) + self.view.addMailServerToList(mailserver) diff --git a/src/app/profile/profileView.nim b/src/app/profile/profileView.nim deleted file mode 100644 index 532689b7b4..0000000000 --- a/src/app/profile/profileView.nim +++ /dev/null @@ -1,59 +0,0 @@ -import NimQml -import Tables -import mailserversList - -QtObject: - type ProfileView* = ref object of QObject - username*: string - identicon*: string - mailserversList*: MailServersList - - proc setup(self: ProfileView) = - self.QObject.setup - - proc delete*(self: ProfileView) = - self.QObject.delete - - proc newProfileView*(): ProfileView = - new(result, delete) - result.username = "" - result.identicon = "" - result.mailserversList = newMailServersList() - result.setup - - proc username*(self: ProfileView): string {.slot.} = - result = self.username - - proc receivedUsername*(self: ProfileView, username: string) {.signal.} - - proc addMailserverToList*(self: ProfileView, name: string, endpoint: string) {.slot.} = - self.mailserversList.add(name, endpoint) - - proc setUsername*(self: ProfileView, username: string) {.slot.} = - self.username = username - self.receivedUsername(username) - - QtProperty[string] username: - read = username - write = setUsername - notify = receivedUsername - - proc identicon*(self: ProfileView): string {.slot.} = - result = self.identicon - - proc getMailserversList(self: ProfileView): QVariant {.slot.} = - return newQVariant(self.mailserversList) - - QtProperty[QVariant] mailserversList: - read = getMailserversList - - proc receivedIdenticon*(self: ProfileView, identicon: string) {.signal.} - - proc setIdenticon*(self: ProfileView, identicon: string) {.slot.} = - self.identicon = identicon - self.receivedIdenticon(identicon) - - QtProperty[string] identicon: - read = identicon - write = setIdenticon - notify = receivedIdenticon diff --git a/src/app/profile/view.nim b/src/app/profile/view.nim new file mode 100644 index 0000000000..967cb6e288 --- /dev/null +++ b/src/app/profile/view.nim @@ -0,0 +1,40 @@ +import NimQml +import views/mailservers_list +import views/profile_info +import ../../models/profile + +QtObject: + type ProfileView* = ref object of QObject + profile*: ProfileInfoView + mailserversList*: MailServersList + + proc setup(self: ProfileView) = + self.QObject.setup + + proc delete*(self: ProfileView) = + self.QObject.delete + + proc newProfileView*(): ProfileView = + new(result, delete) + result = ProfileView() + result.profile = newProfileInfoView() + result.mailserversList = newMailServersList() + result.setup + + proc addMailServerToList*(self: ProfileView, mailserver: MailServer) = + self.mailserversList.addMailServerToList(mailserver) + + proc getMailserversList(self: ProfileView): QVariant {.slot.} = + return newQVariant(self.mailserversList) + + QtProperty[QVariant] mailserversList: + read = getMailserversList + + proc getProfile(self: ProfileView): QVariant {.slot.} = + return newQVariant(self.profile) + + proc setNewProfile*(self: ProfileView, profile: Profile) = + self.profile.setProfile(profile) + + QtProperty[QVariant] profile: + read = getProfile diff --git a/src/app/profile/mailserversList.nim b/src/app/profile/views/mailservers_list.nim similarity index 81% rename from src/app/profile/mailserversList.nim rename to src/app/profile/views/mailservers_list.nim index ed2977a4db..7bf3b37784 100644 --- a/src/app/profile/mailserversList.nim +++ b/src/app/profile/views/mailservers_list.nim @@ -1,16 +1,13 @@ import NimQml import Tables import strformat +import ../../../models/profile type - MailserverRoles {.pure.} = enum + MailServerRoles {.pure.} = enum Name = UserRole + 1, Endpoint = UserRole + 2 -type - MailServer* = ref object of QObject - name*, endpoint*: string - QtObject: type MailServersList* = ref object of QAbstractListModel mailservers*: seq[MailServer] @@ -43,9 +40,7 @@ QtObject: MailServerRoles.Endpoint.int:"endpoint", }.toTable - proc add*(self: MailServersList, name: string, endpoint: string) {.slot.} = + proc addMailServerToList*(self: MailServersList, mailserver: MailServer) = self.beginInsertRows(newQModelIndex(), self.mailservers.len, self.mailservers.len) - self.mailservers.add(MailServer(name: name, - endpoint: endpoint)) + self.mailservers.add(mailserver) self.endInsertRows() - diff --git a/src/app/profile/views/profile_info.nim b/src/app/profile/views/profile_info.nim new file mode 100644 index 0000000000..a33320b788 --- /dev/null +++ b/src/app/profile/views/profile_info.nim @@ -0,0 +1,37 @@ +import NimQml +import ../../../models/profile + +QtObject: + type ProfileInfoView* = ref object of QObject + username*: string + identicon*: string + + proc setup(self: ProfileInfoView) = + self.QObject.setup + + proc delete*(self: ProfileInfoView) = + self.QObject.delete + + proc newProfileInfoView*(): ProfileInfoView = + new(result, delete) + result = ProfileInfoView() + result.username = "" + result.identicon = "" + result.setup + + proc profileChanged*(self: ProfileInfoView) {.signal.} + + proc setProfile*(self: ProfileInfoView, profile: Profile) = + self.username = profile.username + self.identicon = profile.identicon + self.profileChanged() + + proc username*(self: ProfileInfoView): string {.slot.} = result = self.username + QtProperty[string] username: + read = username + notify = profileChanged + + proc identicon*(self: ProfileInfoView): string {.slot.} = result = self.identicon + QtProperty[string] identicon: + read = identicon + notify = profileChanged diff --git a/src/app/wallet/core.nim b/src/app/wallet/core.nim index b31dbfb705..f00d5aac6b 100644 --- a/src/app/wallet/core.nim +++ b/src/app/wallet/core.nim @@ -1,21 +1,22 @@ import NimQml +import eventemitter import strformat import strutils -import walletView +import view import ../../status/wallet as status_wallet -import ../signals/types - -var sendTransaction = proc(from_value: string, to: string, value: string, password: string): string = - status_wallet.sendTransaction(from_value, to, value, password) +import ../../models/wallet +import ../../signals/types type WalletController* = ref object of SignalSubscriber + model: WalletModel view*: WalletView variant*: QVariant -proc newController*(): WalletController = +proc newController*(events: EventEmitter): WalletController = result = WalletController() - result.view = newWalletView(sendTransaction) + result.model = newWalletModel(events) + result.view = newWalletView(result.model) result.variant = newQVariant(result.view) proc delete*(self: WalletController) = @@ -23,23 +24,11 @@ proc delete*(self: WalletController) = delete self.variant proc init*(self: WalletController) = - # 1. get balance of an address - var balance = status_wallet.getBalance("0x0000000000000000000000000000000000000000") - echo(fmt"balance in hex: {balance}") + var symbol = "ETH" + var eth_balance = self.model.getEthBalance("0x0000000000000000000000000000000000000000") + var usd_balance = self.model.getFiatValue(eth_balance, symbol, "USD") - # 2. convert balance to eth - var eth_value = status_wallet.hex2Eth(balance) - echo(fmt"balance in eth: {eth_value}") - - # 3. get usd price of 1 eth - var usd_eth_price = status_wallet.getPrice("ETH", "USD") - echo(fmt"usd_price: {usd_eth_price}") - - # 4. convert balance to usd - var usd_balance = parseFloat(eth_value) * parseFloat(usd_eth_price) - echo(fmt"balance in usd: {usd_balance}") + var asset = Asset(name:"Ethereum", symbol: symbol, value: fmt"{eth_balance:.6}", fiatValue: "$" & fmt"{usd_balance:.6}", image: fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg") + self.view.addAssetToList(asset) self.view.setDefaultAccount(status_wallet.getAccount()) - - let symbol = "ETH" - self.view.addAssetToList("Ethereum", symbol, fmt"{eth_value:.6}", "$" & fmt"{usd_balance:.6}", fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg") diff --git a/src/app/wallet/view.nim b/src/app/wallet/view.nim new file mode 100644 index 0000000000..06abdfb441 --- /dev/null +++ b/src/app/wallet/view.nim @@ -0,0 +1,41 @@ +import NimQml +import Tables +import views/asset_list +import ../../models/wallet + +QtObject: + type + WalletView* = ref object of QAbstractListModel + assets*: AssetsList + defaultAccount: string + model: WalletModel + + proc delete(self: WalletView) = + self.QAbstractListModel.delete + + proc setup(self: WalletView) = + self.QAbstractListModel.setup + + proc newWalletView*(model: WalletModel): WalletView = + new(result, delete) + result.model = model + result.assets = newAssetsList() + result.setup + + proc addAssetToList*(self: WalletView, asset: Asset) = + self.assets.addAssetToList(asset) + + proc getAssetsList(self: WalletView): QVariant {.slot.} = + return newQVariant(self.assets) + + QtProperty[QVariant] assets: + read = getAssetsList + + proc onSendTransaction*(self: WalletView, from_value: string, to: string, value: string, password: string): string {.slot.} = + result = self.model.sendTransaction(from_value, to, value, password) + + proc setDefaultAccount*(self: WalletView, account: string) = + self.defaultAccount = account + + proc getDefaultAccount*(self: WalletView): string {.slot.} = + return self.defaultAccount diff --git a/src/app/wallet/views/asset_list.nim b/src/app/wallet/views/asset_list.nim new file mode 100644 index 0000000000..7e03a80387 --- /dev/null +++ b/src/app/wallet/views/asset_list.nim @@ -0,0 +1,56 @@ +import NimQml +import Tables +import strformat +import ../../../models/wallet + +type + AssetRoles {.pure.} = enum + Name = UserRole + 1, + Symbol = UserRole + 2, + Value = UserRole + 3, + FiatValue = UserRole + 4, + Image = UserRole + 5 + +QtObject: + type AssetsList* = ref object of QAbstractListModel + assets*: seq[Asset] + + proc setup(self: AssetsList) = self.QAbstractListModel.setup + + proc delete(self: AssetsList) = + self.QAbstractListModel.delete + self.assets = @[] + + proc newAssetsList*(): AssetsList = + new(result, delete) + result.assets = @[] + result.setup + + method rowCount(self: AssetsList, index: QModelIndex = nil): int = + return self.assets.len + + method data(self: AssetsList, index: QModelIndex, role: int): QVariant = + if not index.isValid: + return + if index.row < 0 or index.row >= self.assets.len: + return + let asset = self.assets[index.row] + let assetRole = role.AssetRoles + case assetRole: + of AssetRoles.Name: result = newQVariant(asset.name) + of AssetRoles.Symbol: result = newQVariant(asset.symbol) + of AssetRoles.Value: result = newQVariant(asset.value) + of AssetRoles.FiatValue: result = newQVariant(asset.fiatValue) + of AssetRoles.Image: result = newQVariant(asset.image) + + method roleNames(self: AssetsList): Table[int, string] = + { AssetRoles.Name.int:"name", + AssetRoles.Symbol.int:"symbol", + AssetRoles.Value.int:"value", + AssetRoles.FiatValue.int:"fiatValue", + AssetRoles.Image.int:"image" }.toTable + + proc addAssetToList*(self: AssetsList, asset: Asset) = + self.beginInsertRows(newQModelIndex(), self.assets.len, self.assets.len) + self.assets.add(asset) + self.endInsertRows() diff --git a/src/app/wallet/walletView.nim b/src/app/wallet/walletView.nim deleted file mode 100644 index fa2fe74fd9..0000000000 --- a/src/app/wallet/walletView.nim +++ /dev/null @@ -1,78 +0,0 @@ -import NimQml -import Tables - -type - AssetRoles {.pure.} = enum - Name = UserRole + 1, - Symbol = UserRole + 2, - Value = UserRole + 3, - FiatValue = UserRole + 4, - Image = UserRole + 5 - -type - Asset* = ref object - name*, symbol*, value*, fiatValue*, image*: string - -QtObject: - type - WalletView* = ref object of QAbstractListModel - assets*: seq[Asset] - defaultAccount: string - sendTransaction: proc(from_value: string, to: string, value: string, password: string): string - - - proc delete(self: WalletView) = - self.QAbstractListModel.delete - self.assets = @[] - - proc setup(self: WalletView) = - self.QAbstractListModel.setup - - proc newWalletView*(sendTransaction: proc): WalletView = - new(result, delete) - result.sendTransaction = sendTransaction - result.assets = @[] - result.setup - - proc addAssetToList*(self: WalletView, name: string, symbol: string, value: string, fiatValue: string, image: string) {.slot.} = - self.beginInsertRows(newQModelIndex(), self.assets.len, self.assets.len) - self.assets.add(Asset(name : name, - symbol : symbol, - value : value, - fiatValue: fiatValue, - image: image)) - self.endInsertRows() - - proc setDefaultAccount*(self: WalletView, account: string) = - self.defaultAccount = account - - proc getDefaultAccount*(self: WalletView): string {.slot.} = - return self.defaultAccount - - method rowCount(self: WalletView, index: QModelIndex = nil): int = - return self.assets.len - - method data(self: WalletView, index: QModelIndex, role: int): QVariant = - if not index.isValid: - return - if index.row < 0 or index.row >= self.assets.len: - return - - let asset = self.assets[index.row] - let assetRole = role.AssetRoles - case assetRole: - of AssetRoles.Name: result = newQVariant(asset.name) - of AssetRoles.Symbol: result = newQVariant(asset.symbol) - of AssetRoles.Value: result = newQVariant(asset.value) - of AssetRoles.FiatValue: result = newQVariant(asset.fiatValue) - of AssetRoles.Image: result = newQVariant(asset.image) - - proc onSendTransaction*(self: WalletView, from_value: string, to: string, value: string, password: string): string {.slot.} = - result = self.sendTransaction(from_value, to, value, password) - - method roleNames(self: WalletView): Table[int, string] = - { AssetRoles.Name.int:"name", - AssetRoles.Symbol.int:"symbol", - AssetRoles.Value.int:"value", - AssetRoles.FiatValue.int:"fiatValue", - AssetRoles.Image.int:"image" }.toTable diff --git a/src/models/accounts.nim b/src/models/accounts.nim index df58de1c23..5eeaa44b7b 100644 --- a/src/models/accounts.nim +++ b/src/models/accounts.nim @@ -4,6 +4,13 @@ import ../status/accounts as status_accounts import ../status/utils import ../status/types +type + Address* = ref object + username*, identicon*, key*: string + +proc toAddress*(account: GeneratedAccount): Address = + result = Address(username: account.name, identicon: account.photoPath, key: account.address) + type AccountModel* = ref object generatedAddresses*: seq[GeneratedAccount] diff --git a/src/models/chat.nim b/src/models/chat.nim index 1579cdfb9f..22c5857ef5 100644 --- a/src/models/chat.nim +++ b/src/models/chat.nim @@ -3,6 +3,11 @@ import json, sets, eventemitter import ../status/utils import ../status/chat as status_chat +import chat/chat_item +import chat/chat_message +export chat_item +export chat_message + type MsgArgs* = ref object of Args message*: string chatId*: string diff --git a/src/app/chat/chatItem.nim b/src/models/chat/chat_item.nim similarity index 61% rename from src/app/chat/chatItem.nim rename to src/models/chat/chat_item.nim index e408965dc2..39fee3cc7a 100644 --- a/src/app/chat/chatItem.nim +++ b/src/models/chat/chat_item.nim @@ -1,3 +1,5 @@ +import ../../signals/types + type ChatItem* = ref object name*: string lastMessage*: string @@ -16,3 +18,11 @@ proc findByName*(self: seq[ChatItem], name: string): int = for item in self: inc result if(item.name == name): break + +proc toChatItem*(chat: Chat): ChatItem = + result = ChatItem( + name: chat.name, + lastMessage: chat.lastMessage.text, + timestamp: chat.timestamp, + unviewedMessagesCount: chat.unviewedMessagesCount + ) diff --git a/src/models/chat/chat_message.nim b/src/models/chat/chat_message.nim new file mode 100644 index 0000000000..2b9f952d05 --- /dev/null +++ b/src/models/chat/chat_message.nim @@ -0,0 +1,38 @@ +import json +import ../../signals/types + +type ChatMessage* = ref object + userName*: string + message*: string + timestamp*: string + identicon*: string + isCurrentUser*: bool + +proc delete*(self: ChatMessage) = + discard + +proc newChatMessage*(): ChatMessage = + result = ChatMessage() + result.userName = "" + result.message = "" + result.timestamp = "0" + result.identicon = "" + result.isCurrentUser = false + +proc toChatMessage*(payload: JsonNode): ChatMessage = + result = ChatMessage( + userName: payload["alias"].str, + message: payload["text"].str, + timestamp: $payload["timestamp"], + identicon: payload["identicon"].str, + isCurrentUser: false + ) + +proc toChatMessage*(message: Message): ChatMessage = + result = ChatMessage( + userName: message.alias, + message: message.text, + timestamp: message.timestamp, + identicon: message.identicon, + isCurrentUser: message.isCurrentUser + ) diff --git a/src/models/profile.nim b/src/models/profile.nim new file mode 100644 index 0000000000..225a2e8003 --- /dev/null +++ b/src/models/profile.nim @@ -0,0 +1,11 @@ +import eventemitter + +type + MailServer* = ref object + name*, endpoint*: string + +type Profile* = ref object + username*, identicon*: string + +proc toProfileModel*(obj: object): Profile = + result = Profile(username: obj.name, identicon: obj.photoPath) diff --git a/src/models/wallet.nim b/src/models/wallet.nim new file mode 100644 index 0000000000..e8ab317895 --- /dev/null +++ b/src/models/wallet.nim @@ -0,0 +1,40 @@ +import eventemitter +import json +import strformat +import strutils +import ../status/wallet as status_wallet + +type Asset* = ref object + name*, symbol*, value*, fiatValue*, image*: string + +type WalletModel* = ref object + events*: EventEmitter + +proc newWalletModel*(events: EventEmitter): WalletModel = + result = WalletModel() + result.events = events + +proc delete*(self: WalletModel) = + discard + +proc sendTransaction*(self: WalletModel, from_value: string, to: string, value: string, password: string): string = + status_wallet.sendTransaction(from_value, to, value, password) + +proc getEthBalance*(self: WalletModel, address: string): string = + var balance = status_wallet.getBalance(address) + echo(fmt"balance in hex: {balance}") + + # 2. convert balance to eth + var eth_value = status_wallet.hex2Eth(balance) + echo(fmt"balance in eth: {eth_value}") + eth_value + +proc getFiatValue*(self: WalletModel, eth_balance: string, symbol: string, fiat_symbol: string): float = + # 3. get usd price of 1 eth + var usd_eth_price = status_wallet.getPrice("ETH", "USD") + echo(fmt"usd_price: {usd_eth_price}") + + # 4. convert balance to usd + var usd_balance = parseFloat(eth_balance) * parseFloat(usd_eth_price) + echo(fmt"balance in usd: {usd_balance}") + usd_balance diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index aa48de34e2..9ba5fd23b3 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -4,7 +4,7 @@ import app/chat/core as chat import app/wallet/core as wallet import app/node/core as node import app/profile/core as profile -import app/signals/core as signals +import signals/core as signals import app/onboarding/core as onboarding import state import json @@ -41,7 +41,7 @@ proc mainProc() = var appState = state.newAppState() debug "Application State", title=appState.title - var wallet = wallet.newController() + var wallet = wallet.newController(events) engine.setRootContextProperty("assetsModel", wallet.variant) var chat = chat.newController(events) @@ -81,6 +81,7 @@ proc mainProc() = accountsModel.events.on("accountsReady") do(a: Args): appState.addChannel("test") appState.addChannel("test2") + appState.addChannel("status") engine.load("../ui/main.qml") diff --git a/src/app/signals/core.nim b/src/signals/core.nim similarity index 96% rename from src/app/signals/core.nim rename to src/signals/core.nim index d099ae66fc..fcb09fa105 100644 --- a/src/app/signals/core.nim +++ b/src/signals/core.nim @@ -1,5 +1,5 @@ import NimQml -import ../../status/types as status_types +import ../status/types as status_types import tables import json import types diff --git a/src/app/signals/messages.nim b/src/signals/messages.nim similarity index 99% rename from src/app/signals/messages.nim rename to src/signals/messages.nim index 7fb4a6d571..8281a130b4 100644 --- a/src/app/signals/messages.nim +++ b/src/signals/messages.nim @@ -32,7 +32,6 @@ proc toChat(jsonChat: JsonNode): Chat = lastMessage: jsonChat{"lastMessage"}.toMessage ) - proc toMessage(jsonMsg: JsonNode): Message = result = Message( alias: jsonMsg{"alias"}.getStr, @@ -54,4 +53,4 @@ proc toMessage(jsonMsg: JsonNode): Message = timestamp: $jsonMsg{"timestamp"}.getInt, whisperTimestamp: $jsonMsg{"whisperTimestamp"}.getInt, isCurrentUser: false # TODO: this must compare the fromAuthor against current user because the messages received from the mailserver will arrive as signals too, and those include the current user messages - ) \ No newline at end of file + ) diff --git a/src/app/signals/types.nim b/src/signals/types.nim similarity index 98% rename from src/app/signals/types.nim rename to src/signals/types.nim index 7236bd29b0..ca3a56ffd8 100644 --- a/src/app/signals/types.nim +++ b/src/signals/types.nim @@ -56,7 +56,6 @@ type Chat* = object # members ? # membershipUpdateEvents # ? - type MessageSignal* = ref object of Signal messages*: seq[Message] - chats*: seq[Chat] \ No newline at end of file + chats*: seq[Chat] diff --git a/src/status/types.nim b/src/status/types.nim index 2168c3ed6f..70e66da5f3 100644 --- a/src/status/types.nim +++ b/src/status/types.nim @@ -73,4 +73,4 @@ proc toAccount*(generatedAccount: GeneratedAccount): Account = photoPath: generatedAccount.photoPath) type AccountArgs* = ref object of Args - account*: Account \ No newline at end of file + account*: Account diff --git a/ui/app/AppLayouts/Chat/ChatLayout.qml b/ui/app/AppLayouts/Chat/ChatLayout.qml index d7628914e8..003f87c8eb 100644 --- a/ui/app/AppLayouts/Chat/ChatLayout.qml +++ b/ui/app/AppLayouts/Chat/ChatLayout.qml @@ -228,7 +228,7 @@ SplitView { id: chatGroupsListView anchors.topMargin: 24 anchors.fill: parent - model: chatsModel + model: chatsModel.chats delegate: chatViewDelegate } } diff --git a/ui/app/AppLayouts/Profile/LeftTab.qml b/ui/app/AppLayouts/Profile/LeftTab.qml index 32e1817745..90cac50396 100644 --- a/ui/app/AppLayouts/Profile/LeftTab.qml +++ b/ui/app/AppLayouts/Profile/LeftTab.qml @@ -41,7 +41,7 @@ ColumnLayout { Image { id: profileImg - source: profileModel.identicon + source: profileModel.profile.identicon width: 80 height: 80 fillMode: Image.PreserveAspectCrop @@ -68,7 +68,7 @@ ColumnLayout { Text { id: profileName - text: profileModel.username + text: profileModel.profile.username anchors.top: profileImg.bottom anchors.topMargin: 10 anchors.horizontalCenterOffset: 0 diff --git a/ui/app/AppLayouts/Wallet/LeftTab.qml b/ui/app/AppLayouts/Wallet/LeftTab.qml index f61ac069f0..7d36a142c2 100644 --- a/ui/app/AppLayouts/Wallet/LeftTab.qml +++ b/ui/app/AppLayouts/Wallet/LeftTab.qml @@ -268,7 +268,7 @@ ColumnLayout { id: listView anchors.topMargin: 36 anchors.fill: parent - model: assetsModel + model: assetsModel.assets delegate: assetViewDelegate } }