add profile section

add profile module

add boilerplate for profile section

add profile module

add profile module

fix variant

 use accounts service

get identityimage to work

cleanup

add other contacts services

add contacts service

make contact section compile with refactor

fix controller and service interfaces

add about section
This commit is contained in:
Iuri Matias 2021-10-13 17:31:04 -04:00
parent 70c1095b60
commit 4e3ecbf4b5
43 changed files with 1840 additions and 42 deletions

View File

@ -14,6 +14,10 @@ import ../../app_service/service/setting/service as setting_service
import ../../app_service/service/bookmarks/service as bookmark_service
import ../core/local_account_settings
import ../../app_service/service/profile/service as profile_service
import ../../app_service/service/settings/service as settings_service
import ../../app_service/service/contacts/service as contacts_service
import ../../app_service/service/about/service as about_service
import ../modules/startup/module as startup_module
import ../modules/main/module as main_module
@ -73,8 +77,13 @@ type
# Core
localAccountSettings: LocalAccountSettings
localAccountSettingsVariant: QVariant
mainModule: main_module.AccessInterface
profileService: profile_service.Service
settingsService: settings_service.Service
contactsService: contacts_service.Service
aboutService: about_service.Service
# Modules
startupModule: startup_module.AccessInterface
mainModule: main_module.AccessInterface
#################################################
# At the end of refactoring this will be moved to
@ -130,7 +139,10 @@ proc newAppController*(appService: AppService): AppController =
)
result.transactionService = transaction_service.newService(result.walletAccountService)
result.bookmarkService = bookmark_service.newService()
result.profileService = profile_service.newService()
result.settingsService = settings_service.newService()
result.contactsService = contacts_service.newService()
result.aboutService = about_service.newService()
# Core
result.localAccountSettingsVariant = newQVariant(
@ -155,7 +167,11 @@ proc newAppController*(appService: AppService): AppController =
result.collectibleService,
result.walletAccountService,
result.bookmarkService,
result.settingService
result.settingService,
result.profileService,
result.settingsService,
result.contactService,
result.aboutService,
)
#################################################
@ -166,6 +182,18 @@ proc newAppController*(appService: AppService): AppController =
result.connect()
#################################################
# Adding status and appService here now is just because of having a controll
# over order of execution while we integrating this refactoring architecture
# into the current app state.
# Once we complete refactoring process we will get rid of "status" part/lib.
#
# This to will be adapted to appropriate modules later:
# result.login = login.newController(appService.status, appService)
# result.onboarding = onboarding.newController(appService.status)
# singletonInstance.engine.setRootContextProperty("loginModel", result.login.variant)
# singletonInstance.engine.setRootContextProperty("onboardingModel", result.onboarding.variant)
#result.connect()
proc delete*(self: AppController) =
self.contactService.delete
self.chatService.delete
@ -192,6 +220,7 @@ proc delete*(self: AppController) =
self.collectibleService.delete
self.settingService.delete
self.walletAccountService.delete
self.aboutService.delete
proc startupDidLoad*(self: AppController) =
#################################################

View File

@ -6,9 +6,10 @@ import ../../core/global_singleton
import chat_section/module as chat_section_module
import wallet_section/module as wallet_section_module
import browser_section/module as browser_section_module
import profile_section/module as profile_section_module
import ../../../app_service/service/keychain/service as keychain_service
import ../../../app_service/service/accounts/service_interface as accounts_service
# import ../../../app_service/service/accounts/service_interface as accounts_service
import ../../../app_service/service/chat/service as chat_service
import ../../../app_service/service/community/service as community_service
import ../../../app_service/service/token/service as token_service
@ -19,6 +20,11 @@ import ../../../app_service/service/setting/service as setting_service
import ../../../app_service/service/bookmarks/service as bookmark_service
import eventemitter
import ../../../app_service/service/profile/service as profile_service
import ../../../app_service/service/accounts/service as accounts_service
import ../../../app_service/service/settings/service as settings_service
import ../../../app_service/service/contacts/service as contacts_service
import ../../../app_service/service/about/service as about_service
export io_interface
@ -42,6 +48,7 @@ type
communitySectionsModule: OrderedTable[string, chat_section_module.AccessInterface]
walletSectionModule: wallet_section_module.AccessInterface
browserSectionModule: browser_section_module.AccessInterface
profileSectionModule: profile_section_module.AccessInterface
moduleLoaded: bool
proc newModule*[T](
@ -56,7 +63,11 @@ proc newModule*[T](
collectibleService: collectible_service.Service,
walletAccountService: wallet_account_service.Service,
bookmarkService: bookmark_service.Service,
settingService: setting_service.Service
settingService: setting_service.Service,
profileService: profile_service.ServiceInterface,
settingsService: settings_service.ServiceInterface,
contactsService: contacts_service.ServiceInterface,
aboutService: about_service.ServiceInterface
): Module[T] =
result = Module[T]()
result.delegate = delegate
@ -87,9 +98,11 @@ proc newModule*[T](
)
result.browserSectionModule = browser_section_module.newModule(result, bookmarkService)
result.profileSectionModule = profile_section_module.newModule(result, accountsService, settingsService, profileService, contactsService, aboutService)
method delete*[T](self: Module[T]) =
self.chatSectionModule.delete
self.profileSectionModule.delete
for cModule in self.communitySectionsModule.values:
cModule.delete
self.communitySectionsModule.clear
@ -107,13 +120,15 @@ method load*[T](self: Module[T]) =
let chatSectionItem = initItem("chat", SectionType.Chat.int, "Chat", "",
"chat", "", 0, 0)
self.view.addItem(chatSectionItem)
echo "=> communitiesSection"
let communities = self.controller.getCommunities()
for c in communities:
self.view.addItem(initItem(c.id, SectionType.Community.int, c.name,
if not c.images.isNil: c.images.thumbnail else: "",
"", c.color, 0, 0))
echo "=> chatSection"
self.chatSectionModule.load()
for cModule in self.communitySectionsModule.values:
cModule.load()
@ -128,6 +143,7 @@ method load*[T](self: Module[T]) =
let browserSectionItem = initItem("browser", SectionType.Browser.int, "Browser")
self.view.addItem(browserSectionItem)
self.profileSectionModule.load()
proc checkIfModuleDidLoad [T](self: Module[T]) =
if self.moduleLoaded:
@ -146,6 +162,9 @@ proc checkIfModuleDidLoad [T](self: Module[T]) =
if(not self.browserSectionModule.isLoaded()):
return
if(not self.profileSectionModule.isLoaded()):
return
self.moduleLoaded = true
self.delegate.mainDidLoad()
@ -161,6 +180,9 @@ proc walletSectionDidLoad*[T](self: Module[T]) =
method browserSectionDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()
proc profileSectionDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()
method viewDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()

View File

@ -0,0 +1,28 @@
import ./controller_interface
import ../../../../../app_service/service/about/service as about_service
# import ./item as item
export controller_interface
type
Controller*[T: controller_interface.DelegateInterface] = ref object of controller_interface.AccessInterface
delegate: T
aboutService: about_service.ServiceInterface
proc newController*[T](delegate: T, aboutService: about_service.ServiceInterface): Controller[T] =
result = Controller[T]()
result.delegate = delegate
result.aboutService = aboutService
method delete*[T](self: Controller[T]) =
discard
method init*[T](self: Controller[T]) =
discard
method getAppVersion*[T](self: Controller[T]): string =
return self.aboutService.getAppVersion()
method getNodeVersion*[T](self: Controller[T]): string =
return self.aboutService.getNodeVersion()

View File

@ -0,0 +1,22 @@
import ../../../../../app_service/service/profile/service as profile_service
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method init*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getAppVersion*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getNodeVersion*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c

View File

@ -0,0 +1,23 @@
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method load*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getAppVersion*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getNodeVersion*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c

View File

@ -0,0 +1,41 @@
import NimQml, Tables
import ./io_interface, ./view, ./controller
import ../../../../core/global_singleton
import ../../../../../app_service/service/about/service as about_service
export io_interface
type
Module* [T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface
delegate: T
controller: controller.AccessInterface
view: View
viewVariant: QVariant
moduleLoaded: bool
proc newModule*[T](delegate: T, aboutService: about_service.ServiceInterface): Module[T] =
result = Module[T]()
result.delegate = delegate
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController[Module[T]](result, aboutService)
result.moduleLoaded = false
singletonInstance.engine.setRootContextProperty("aboutModule", result.viewVariant)
method delete*[T](self: Module[T]) =
self.view.delete
method load*[T](self: Module[T]) =
self.moduleLoaded = true
method isLoaded*[T](self: Module[T]): bool =
return self.moduleLoaded
method getAppVersion*[T](self: Module[T]): string =
return self.controller.getAppVersion()
method getNodeVersion*[T](self: Module[T]): string =
return self.controller.getNodeVersion()

View File

@ -0,0 +1,23 @@
import NimQml
# import ./controller_interface
import ./io_interface
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
proc delete*(self: View) =
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete)
result.QObject.setup
result.delegate = delegate
proc getCurrentVersion*(self: View): string {.slot.} =
return self.delegate.getAppVersion()
proc nodeVersion*(self: View): string {.slot.} =
return self.delegate.getNodeVersion()

View File

@ -0,0 +1,84 @@
import ./controller_interface
import ../../../../../app_service/service/contacts/service as contacts_service
import ../../../../../app_service/service/contacts/dto/contacts
import ../../../../../app_service/service/accounts/service as accounts_service
# import ./item as item
export controller_interface
type
Controller*[T: controller_interface.DelegateInterface] = ref object of controller_interface.AccessInterface
delegate: T
contactsService: contacts_service.ServiceInterface
accountsService: accounts_service.ServiceInterface
proc newController*[T](delegate: T, contactsService: contacts_service.ServiceInterface, accountsService: accounts_service.ServiceInterface): Controller[T] =
result = Controller[T]()
result.delegate = delegate
result.contactsService = contactsService
result.accountsService = accountsService
method delete*[T](self: Controller[T]) =
discard
method init*[T](self: Controller[T]) =
discard
method getContact*[T](self: Controller[T], id: string): ContactsDto =
return self.contactsService.getContact(id)
method generateAlias*[T](self: Controller[T], publicKey: string): string =
return self.accountsService.generateAlias(publicKey)
method addContact*[T](self: Controller[T], publicKey: string): void =
echo "Adding this from controller ", publicKey
self.contactsService.addContact(publicKey)
method rejectContactRequest*[T](self: Controller[T], publicKey: string): void =
self.contactsService.rejectContactRequest(publicKey)
method unblockContact*[T](self: Controller[T], publicKey: string): void =
self.contactsService.unblockContact(publicKey)
method blockContact*[T](self: Controller[T], publicKey: string): void =
self.contactsService.unblockContact(publicKey)
method removeContact*[T](self: Controller[T], publicKey: string): void =
self.contactsService.removeContact(publicKey)
method changeContactNickname*[T](self: Controller[T], accountKeyUID: string, publicKey: string, nicknameToSet: string): void =
self.contactsService.changeContactNickname(accountKeyUID, publicKey, nicknameToSet)
# method getProfile*[T](self: Controller[T]): item.Item =
# let loggedInAccount = self.accountsService.getLoggedInAccount()
# var pubKey = self.settingsService.getPubKey()
# var network = self.settingsService.getNetwork()
# var appearance = self.settingsService.getAppearance()
# var messagesFromContactsOnly = self.settingsService.getMessagesFromContactsOnly()
# var sendUserStatus = self.settingsService.getSendUserStatus()
# var currentUserStatus = self.settingsService.getCurrentUserStatus()
# var obj = self.settingsService.getIdentityImage(loggedInAccount.keyUid)
# var identityImage = item.IdentityImage(thumbnail: obj.thumbnail, large: obj.large)
# var item = item.Item(
# id: pubkey,
# alias: "",
# username: loggedInAccount.name,
# identicon: loggedInAccount.identicon,
# address: loggedInAccount.keyUid,
# ensName: "",
# ensVerified: false,
# localNickname: "",
# messagesFromContactsOnly: messagesFromContactsOnly,
# sendUserStatus: sendUserStatus,
# currentUserStatus: currentUserStatus,
# identityImage: identityImage,
# appearance: appearance,
# added: false,
# blocked: false,
# hasAddedUs: false
# )
# return item

View File

@ -0,0 +1,45 @@
import ../../../../../app_service/service/profile/service as profile_service
import ../../../../../app_service/service/contacts/dto/contacts as ContactDto
# import ./item
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method init*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
# method getProfile*(self: AccessInterface): Item {.base.} =
# raise newException(ValueError, "No implementation available")
method getContact*(self: AccessInterface, id: string): ContactDto.ContactsDto {.base.} =
raise newException(ValueError, "No implementation available")
method generateAlias*(self: AccessInterface, publicKey: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method addContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method rejectContactRequest*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method unblockContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method blockContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method removeContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method changeContactNickname*(self: AccessInterface, accountKeyUID: string, publicKey: string, nicknameToSet: string): void {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c

View File

@ -0,0 +1,43 @@
import ../../../../../app_service/service/contacts/dto/contacts
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method load*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getContact*(self: AccessInterface, id: string): ContactsDto {.base.} =
raise newException(ValueError, "No implementation available")
method generateAlias*(self: AccessInterface, publicKey: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method addContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method rejectContactRequest*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method unblockContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method blockContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method removeContact*(self: AccessInterface, publicKey: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method changeContactNickname*(self: AccessInterface, accountKeyUID: string, publicKey: string, nicknameToSet: string): void {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c

View File

@ -0,0 +1,118 @@
import NimQml, chronicles, sequtils, sugar, strutils, json
import status/utils as status_utils
import status/chat/chat
import status/types/profile
import status/ens as status_ens
import ./models/contact_list
QtObject:
type Model* = ref object of QObject
contactList*: ContactList
contactRequests*: ContactList
addedContacts*: ContactList
blockedContacts*: ContactList
proc setup(self: Model) =
self.QObject.setup
proc delete*(self: Model) =
self.contactList.delete
self.addedContacts.delete
self.contactRequests.delete
self.blockedContacts.delete
self.QObject.delete
proc newModel*(): Model =
new(result, delete)
result.contactList = newContactList()
result.contactRequests = newContactList()
result.addedContacts = newContactList()
result.blockedContacts = newContactList()
result.setup
proc contactListChanged*(self: Model) {.signal.}
proc contactRequestAdded*(self: Model, name: string, address: string) {.signal.}
proc updateContactList*(self: Model, contacts: seq[Profile]) =
for contact in contacts:
var requestAlreadyAdded = false
for existingContact in self.contactList.contacts:
if existingContact.address == contact.address and existingContact.requestReceived():
requestAlreadyAdded = true
break
self.contactList.updateContact(contact)
if contact.added:
self.addedContacts.updateContact(contact)
if contact.isBlocked():
self.blockedContacts.updateContact(contact)
if contact.requestReceived() and not contact.added and not contact.blocked:
self.contactRequests.updateContact(contact)
if not requestAlreadyAdded and contact.requestReceived():
# TODO add back userNameOrAlias call
self.contactRequestAdded(contact.username, contact.address)
# self.contactRequestAdded(status_ens.userNameOrAlias(contact), contact.address)
self.contactListChanged()
proc getContactList(self: Model): QVariant {.slot.} =
return newQVariant(self.contactList)
proc setContactList*(self: Model, contactList: seq[Profile]) =
self.contactList.setNewData(contactList)
self.addedContacts.setNewData(contactList.filter(c => c.added))
self.blockedContacts.setNewData(contactList.filter(c => c.blocked))
self.contactRequests.setNewData(contactList.filter(c => c.hasAddedUs and not c.added and not c.blocked))
self.contactListChanged()
QtProperty[QVariant] list:
read = getContactList
write = setContactList
notify = contactListChanged
proc getAddedContacts(self: Model): QVariant {.slot.} =
return newQVariant(self.addedContacts)
QtProperty[QVariant] addedContacts:
read = getAddedContacts
notify = contactListChanged
proc getBlockedContacts(self: Model): QVariant {.slot.} =
return newQVariant(self.blockedContacts)
QtProperty[QVariant] blockedContacts:
read = getBlockedContacts
notify = contactListChanged
proc isContactBlocked*(self: Model, pubkey: string): bool {.slot.} =
for contact in self.blockedContacts.contacts:
if contact.id == pubkey:
return true
return false
proc getContactRequests(self: Model): QVariant {.slot.} =
return newQVariant(self.contactRequests)
QtProperty[QVariant] contactRequests:
read = getContactRequests
notify = contactListChanged
proc isAdded*(self: Model, pubkey: string): bool {.slot.} =
for contact in self.addedContacts.contacts:
if contact.id == pubkey:
return true
return false
proc contactRequestReceived*(self: Model, pubkey: string): bool {.slot.} =
for contact in self.contactRequests.contacts:
if contact.id == pubkey:
return true
return false

View File

@ -0,0 +1,154 @@
import NimQml, chronicles
import Tables
import status/types/profile
from status/ens import nil
type
ContactRoles {.pure.} = enum
PubKey = UserRole + 1
Name = UserRole + 2,
Address = UserRole + 3
Identicon = UserRole + 4
IsContact = UserRole + 5
IsBlocked = UserRole + 6
Alias = UserRole + 7
EnsVerified = UserRole + 8
LocalNickname = UserRole + 9
ThumbnailImage = UserRole + 10
LargeImage = UserRole + 11
RequestReceived = UserRole + 12
QtObject:
type ContactList* = ref object of QAbstractListModel
contacts*: seq[Profile]
proc setup(self: ContactList) = self.QAbstractListModel.setup
proc delete(self: ContactList) =
self.contacts = @[]
self.QAbstractListModel.delete
proc newContactList*(): ContactList =
new(result, delete)
# TODO: (rramos) contacts should be a table[string, Profile] instead, with the key being the public key
# This is to optimize determining if a contact is part of the contact list or not
# (including those that do not have a system tag)
result.contacts = @[]
result.setup
method rowCount(self: ContactList, index: QModelIndex = nil): int =
return self.contacts.len
proc countChanged*(self: ContactList) {.signal.}
proc count*(self: ContactList): int {.slot.} =
self.contacts.len
QtProperty[int] count:
read = count
notify = countChanged
proc userName*(self: ContactList, pubKey: string, defaultValue: string = ""): string {.slot.} =
for contact in self.contacts:
if(contact.id != pubKey): continue
return ens.userNameOrAlias(contact)
return defaultValue
proc getContactIndexByPubkey(self: ContactList, pubkey: string): int {.slot.} =
var i = 0
for contact in self.contacts:
if (contact.id == pubkey):
return i
i = i + 1
return -1
proc rowData(self: ContactList, index: int, column: string): string {.slot.} =
let contact = self.contacts[index]
case column:
of "name": result = ens.userNameOrAlias(contact)
of "address": result = contact.address
of "identicon": result = contact.identicon
of "pubKey": result = contact.id
of "isContact": result = $contact.isContact()
of "isBlocked": result = $contact.isBlocked()
of "alias": result = contact.alias
of "ensVerified": result = $contact.ensVerified
of "localNickname": result = $contact.localNickname
of "thumbnailImage": result = $contact.identityImage.thumbnail
of "largeImage": result = $contact.identityImage.large
of "requestReceived": result = $contact.requestReceived()
method data(self: ContactList, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.contacts.len:
return
let contact = self.contacts[index.row]
case role.ContactRoles:
of ContactRoles.Name: result = newQVariant(ens.userNameOrAlias(contact))
of ContactRoles.Address: result = newQVariant(contact.address)
of ContactRoles.Identicon: result = newQVariant(contact.identicon)
of ContactRoles.PubKey: result = newQVariant(contact.id)
of ContactRoles.IsContact: result = newQVariant(contact.isContact())
of ContactRoles.IsBlocked: result = newQVariant(contact.isBlocked())
of ContactRoles.Alias: result = newQVariant(contact.alias)
of ContactRoles.EnsVerified: result = newQVariant(contact.ensVerified)
of ContactRoles.LocalNickname: result = newQVariant(contact.localNickname)
of ContactRoles.ThumbnailImage: result = newQVariant(contact.identityImage.thumbnail)
of ContactRoles.LargeImage: result = newQVariant(contact.identityImage.large)
of ContactRoles.RequestReceived: result = newQVariant(contact.requestReceived())
method roleNames(self: ContactList): Table[int, string] =
{
ContactRoles.Name.int:"name",
ContactRoles.Address.int:"address",
ContactRoles.Identicon.int:"identicon",
ContactRoles.PubKey.int:"pubKey",
ContactRoles.IsContact.int:"isContact",
ContactRoles.IsBlocked.int:"isBlocked",
ContactRoles.Alias.int:"alias",
ContactRoles.LocalNickname.int:"localNickname",
ContactRoles.EnsVerified.int:"ensVerified",
ContactRoles.ThumbnailImage.int:"thumbnailImage",
ContactRoles.LargeImage.int:"largeImage",
ContactRoles.RequestReceived.int:"requestReceived"
}.toTable
proc addContactToList*(self: ContactList, contact: Profile) =
self.beginInsertRows(newQModelIndex(), self.contacts.len, self.contacts.len)
self.contacts.add(contact)
self.endInsertRows()
self.countChanged()
proc hasAddedContacts(self: ContactList): bool {.slot.} =
for c in self.contacts:
if(c.isContact()): return true
return false
proc contactChanged*(self: ContactList, pubkey: string) {.signal.}
proc updateContact*(self: ContactList, contact: Profile) =
var found = false
let topLeft = self.createIndex(0, 0, nil)
let bottomRight = self.createIndex(self.contacts.len, 0, nil)
for c in self.contacts:
if(c.id != contact.id): continue
found = true
c.ensName = contact.ensName
c.ensVerified = contact.ensVerified
c.identityImage = contact.identityImage
c.added = contact.added
c.blocked = contact.blocked
if not found:
self.addContactToList(contact)
else:
self.dataChanged(topLeft, bottomRight, @[ContactRoles.Name.int])
self.contactChanged(contact.id)
proc setNewData*(self: ContactList, contactList: seq[Profile]) =
self.beginResetModel()
self.contacts = contactList
self.endResetModel()
self.countChanged()

View File

@ -0,0 +1,65 @@
import NimQml, Tables
import ./io_interface, ./view, ./controller
import ../../../../core/global_singleton
import ../../../../../app_service/service/contacts/service as contacts_service
import ../../../../../app_service/service/contacts/dto/contacts
import ../../../../../app_service/service/accounts/service as accounts_service
export io_interface
type
Module* [T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface
delegate: T
controller: controller.AccessInterface
view: View
viewVariant: QVariant
moduleLoaded: bool
proc newModule*[T](delegate: T, contactsService: contacts_service.ServiceInterface, accountsService: accounts_service.ServiceInterface): Module[T] =
result = Module[T]()
result.delegate = delegate
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
echo "Module loaded"
result.controller = controller.newController[Module[T]](result, contactsService, accountsService)
result.moduleLoaded = false
echo "Module set as root prop"
singletonInstance.engine.setRootContextProperty("contactsModule", result.viewVariant)
method delete*[T](self: Module[T]) =
self.view.delete
method load*[T](self: Module[T]) =
# let profile = self.controller.getProfile()
# self.view.setProfile(profile)
self.moduleLoaded = true
method isLoaded*[T](self: Module[T]): bool =
return self.moduleLoaded
method getContact*[T](self: Module[T], id: string): ContactsDto =
self.controller.getContact(id)
method generateAlias*[T](self: Module[T], publicKey: string): string =
self.controller.generateAlias(publicKey)
method addContact*[T](self: Module[T], publicKey: string): void =
self.controller.addContact(publicKey)
method rejectContactRequest*[T](self: Module[T], publicKey: string): void =
self.controller.rejectContactRequest(publicKey)
method unblockContact*[T](self: Module[T], publicKey: string): void =
self.controller.unblockContact(publicKey)
method blockContact*[T](self: Module[T], publicKey: string): void =
self.controller.blockContact(publicKey)
method removeContact*[T](self: Module[T], publicKey: string): void =
self.controller.removeContact(publicKey)
method changeContactNickname*[T](self: Module[T], accountKeyUID: string, publicKey: string, nicknameToSet: string): void =
self.controller.changeContactNickname(accountKeyUID, publicKey, nicknameToSet)

View File

@ -0,0 +1,158 @@
import NimQml, sequtils, sugar, json, strutils
# import ./item
import ../../../../../app_service/service/contacts/dto/contacts
import ./model
import status/types/profile
import models/[contact_list]
import ./io_interface
# import status/types/[identity_image, profile]
import ../../../../../app_service/[main]
import ../../../../../app_service/tasks/[qt, threadpool]
type
LookupContactTaskArg = ref object of QObjectTaskArg
value: string
# const lookupContactTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
# let arg = decode[LookupContactTaskArg](argEncoded)
# var id = arg.value
# if not id.startsWith("0x"):
# id = status_ens.pubkey(id)
# arg.finish(id)
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
model: Model
modelVariant: QVariant
contactToAdd*: ContactsDto
accountKeyUID*: string
proc delete*(self: View) =
self.model.delete
self.modelVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete)
result.QObject.setup
result.delegate = delegate
result.model = newModel()
result.modelVariant = newQVariant(result.model)
result.contactToAdd = ContactsDto()
proc modelChanged*(self: View) {.signal.}
proc getModel*(self: View): QVariant {.slot.} =
return self.modelVariant
QtProperty[QVariant] model:
read = getModel
notify = modelChanged
proc contactToAddChanged*(self: View) {.signal.}
proc getContactToAddUsername(self: View): QVariant {.slot.} =
var username = self.contactToAdd.alias;
if self.contactToAdd.ensVerified and self.contactToAdd.name != "":
username = self.contactToAdd.name
return newQVariant(username)
QtProperty[QVariant] contactToAddUsername:
read = getContactToAddUsername
notify = contactToAddChanged
proc getContactToAddPubKey(self: View): QVariant {.slot.} =
# TODO cofirm that id is the pubKey
return newQVariant(self.contactToAdd.id)
QtProperty[QVariant] contactToAddPubKey:
read = getContactToAddPubKey
notify = contactToAddChanged
proc ensWasResolved*(self: View, resolvedPubKey: string) {.signal.}
proc ensResolved(self: View, id: string) {.slot.} =
echo "Resolved", id
self.ensWasResolved(id)
# if id == "":
# self.contactToAddChanged()
# return
# let contact = self.delegate.getContact(id)
# if contact != nil:
# self.contactToAdd = contact
# else:
# self.contactToAdd = ContactsDto(
# id: id,
# alias: self.delegate.generateAlias(id),
# ensVerified: false
# )
# self.contactToAddChanged()
proc lookupContact(self: View, slot: string, value: string) =
# TODO reimplement the ENS search with the threadpool
self.ensResolved(value)
# let arg = LookupContactTaskArg(
# tptr: cast[ByteAddress](lookupContactTask),
# vptr: cast[ByteAddress](self.vptr),
# slot: slot,
# value: value
# )
# self.appService.threadpool.start(arg)
proc lookupContact*(self: View, value: string) {.slot.} =
if value == "":
return
self.lookupContact("ensResolved", value)
proc addContact*(self: View, publicKey: string) {.slot.} =
self.delegate.addContact(publicKey)
# TODO add back joining of timeline
# self.status.chat.join(status_utils.getTimelineChatId(publicKey), ChatType.Profile, "", publicKey)
proc rejectContactRequest*(self: View, publicKey: string) {.slot.} =
self.delegate.rejectContactRequest(publicKey)
proc rejectContactRequests*(self: View, publicKeysJSON: string) {.slot.} =
let publicKeys = publicKeysJSON.parseJson
for pubkey in publicKeys:
self.rejectContactRequest(pubkey.getStr)
proc acceptContactRequests*(self: View, publicKeysJSON: string) {.slot.} =
let publicKeys = publicKeysJSON.parseJson
for pubkey in publicKeys:
self.addContact(pubkey.getStr)
proc changeContactNickname*(self: View, publicKey: string, nickname: string) {.slot.} =
var nicknameToSet = nickname
if (nicknameToSet == ""):
nicknameToSet = DELETE_CONTACT
self.delegate.changeContactNickname(publicKey, nicknameToSet, self.accountKeyUID)
proc unblockContact*(self: View, publicKey: string) {.slot.} =
self.model.contactListChanged()
self.delegate.unblockContact(publicKey)
proc contactBlocked*(self: View, publicKey: string) {.signal.}
proc blockContact*(self: View, publicKey: string) {.slot.} =
self.model.contactListChanged()
self.contactBlocked(publicKey)
self.delegate.blockContact(publicKey)
proc removeContact*(self: View, publicKey: string) {.slot.} =
self.delegate.removeContact(publicKey)
# TODO add back leaving timeline
# let channelId = status_utils.getTimelineChatId(publicKey)
# if self.status.chat.hasChannel(channelId):
# self.status.chat.leave(channelId)

View File

@ -0,0 +1,30 @@
import Tables
import controller_interface
import ../../../../app_service/service/profile/service as profile_service
import ../../../../app_service/service/accounts/service as accounts_service
import ../../../../app_service/service/settings/service as settings_service
export controller_interface
type
Controller*[T: controller_interface.DelegateInterface] =
ref object of controller_interface.AccessInterface
delegate: T
profileService: profile_service.ServiceInterface
settingsService: settings_service.ServiceInterface
accountsService: accounts_service.ServiceInterface
proc newController*[T](delegate: T, accountsService: accounts_service.ServiceInterface, settingsService: settings_service.ServiceInterface, profileService: profile_service.ServiceInterface): Controller[T] =
result = Controller[T]()
result.delegate = delegate
result.profileService = profileService
result.settingsService = settingsService
result.accountsService = accountsService
method delete*[T](self: Controller[T]) =
discard
method init*[T](self: Controller[T]) =
discard

View File

@ -0,0 +1,16 @@
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method init*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c

View File

@ -0,0 +1,24 @@
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method load*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface
# Delegate for the view must be declared here due to use of QtObject and multi
# inheritance, which is not well supported in Nim.
method viewDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c
c.profileSectionDidLoad()

View File

@ -0,0 +1,17 @@
import NimQml
import item
QtObject:
type
Model* = ref object of QAbstractListModel
sections: seq[Item]
proc setup(self: Model) =
self.QAbstractListModel.setup
proc delete*(self: Model) =
self.QAbstractListModel.delete
proc newModel*(): Model =
new(result, delete)
result.setup

View File

@ -0,0 +1,64 @@
import NimQml
import io_interface, view, controller
import ../../../core/global_singleton
import ../../../../app_service/service/profile/service as profile_service
import ../../../../app_service/service/accounts/service as accounts_service
import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/contacts/service as contacts_service
import ../../../../app_service/service/about/service as about_service
import ./profile/module as profile_module
import ./contacts/module as contacts_module
import ./about/module as about_module
export io_interface
type
Module* [T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface
delegate: T
view: View
viewVariant: QVariant
controller: controller.AccessInterface
moduleLoaded: bool
profileModule: profile_module.AccessInterface
contactsModule: contacts_module.AccessInterface
aboutModule: about_module.AccessInterface
proc newModule*[T](delegate: T, accountsService: accounts_service.ServiceInterface, settingsService: settings_service.ServiceInterface, profileService: profile_service.ServiceInterface, contactsService: contacts_service.ServiceInterface, aboutService: about_service.ServiceInterface): Module[T] =
result = Module[T]()
result.delegate = delegate
result.view = view.newView()
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController[Module[T]](result, accountsService, settingsService, profileService)
result.moduleLoaded = false
result.profileModule = profile_module.newModule(result, accountsService, settingsService, profileService)
result.contactsModule = contacts_module.newModule(result, contactsService, accountsService)
result.aboutModule = about_module.newModule(result, aboutService)
singletonInstance.engine.setRootContextProperty("profileSectionModule", result.viewVariant)
method delete*[T](self: Module[T]) =
self.profileModule.delete
self.contactsModule.delete
self.aboutModule.delete
self.view.delete
self.viewVariant.delete
self.controller.delete
method load*[T](self: Module[T]) =
self.profileModule.load()
self.contactsModule.load()
self.aboutModule.load()
self.moduleLoaded = true
self.delegate.profileSectionDidLoad()
method isLoaded*[T](self: Module[T]): bool =
return self.moduleLoaded
method viewDidLoad*(self: Module) =
discard

View File

@ -0,0 +1,61 @@
import ./controller_interface
import ../../../../../app_service/service/profile/service as profile_service
import ../../../../../app_service/service/accounts/service as accounts_service
import ../../../../../app_service/service/settings/service as settings_service
import ./item as item
export controller_interface
type
Controller*[T: controller_interface.DelegateInterface] = ref object of controller_interface.AccessInterface
delegate: T
profileService: profile_service.ServiceInterface
settingsService: settings_service.ServiceInterface
accountsService: accounts_service.ServiceInterface
proc newController*[T](delegate: T, accountsService: accounts_service.ServiceInterface, settingsService: settings_service.ServiceInterface, profileService: profile_service.ServiceInterface): Controller[T] =
result = Controller[T]()
result.delegate = delegate
result.profileService = profileService
result.settingsService = settingsService
result.accountsService = accountsService
method delete*[T](self: Controller[T]) =
discard
method init*[T](self: Controller[T]) =
discard
method getProfile*[T](self: Controller[T]): item.Item =
let loggedInAccount = self.accountsService.getLoggedInAccount()
var pubKey = self.settingsService.getPubKey()
var network = self.settingsService.getNetwork()
var appearance = self.settingsService.getAppearance()
var messagesFromContactsOnly = self.settingsService.getMessagesFromContactsOnly()
var sendUserStatus = self.settingsService.getSendUserStatus()
var currentUserStatus = self.settingsService.getCurrentUserStatus()
var obj = self.settingsService.getIdentityImage(loggedInAccount.keyUid)
var identityImage = item.IdentityImage(thumbnail: obj.thumbnail, large: obj.large)
var item = item.Item(
id: pubkey,
alias: "",
username: loggedInAccount.name,
identicon: loggedInAccount.identicon,
address: loggedInAccount.keyUid,
ensName: "",
ensVerified: false,
localNickname: "",
messagesFromContactsOnly: messagesFromContactsOnly,
sendUserStatus: sendUserStatus,
currentUserStatus: currentUserStatus,
identityImage: identityImage,
appearance: appearance,
added: false,
blocked: false,
hasAddedUs: false
)
return item

View File

@ -0,0 +1,20 @@
import ../../../../../app_service/service/profile/service as profile_service
import ./item
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method init*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getProfile*(self: AccessInterface): Item {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c

View File

@ -0,0 +1,17 @@
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method load*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c

View File

@ -0,0 +1,26 @@
import strformat
type
IdentityImage* = ref object
thumbnail*: string
large*: string
type
Item* = object
id*, alias*, username*, identicon*, address*, ensName*, localNickname*: string
ensVerified*: bool
messagesFromContactsOnly*: bool
sendUserStatus*: bool
currentUserStatus*: int
identityImage*: IdentityImage
appearance*: int
added*: bool
blocked*: bool
hasAddedUs*: bool
proc `$`*(self: Item): string =
result = fmt"""ProfileDto(
username: {self.username},
identicon: {self.identicon},
messagesFromContactsOnly: {self.messagesFromContactsOnly}
)"""

View File

@ -0,0 +1,167 @@
import NimQml
import chronicles
import std/wrapnils
import status/types/profile
import ./item as item
QtObject:
type Model* = ref object of QObject
username*: string
identicon*: string
address*: string
identityImage*: item.IdentityImage
pubKey*: string
appearance*: int
ensVerified*: bool
messagesFromContactsOnly*: bool
sendUserStatus*: bool
currentUserStatus*: int
proc setup(self: Model) =
self.QObject.setup
proc delete*(self: Model) =
self.QObject.delete
proc newModel*(): Model =
new(result, delete)
result = Model()
result.pubKey = ""
result.username = ""
result.identicon = ""
result.appearance = 0
result.identityImage = item.IdentityImage(thumbnail: "", large: "")
result.ensVerified = false
result.messagesFromContactsOnly = false
result.sendUserStatus = false
result.currentUserStatus = 0
result.setup
proc identityImageChanged*(self: Model) {.signal.}
proc sendUserStatusChanged*(self: Model) {.signal.}
proc currentUserStatusChanged*(self: Model) {.signal.}
proc appearanceChanged*(self: Model) {.signal.}
proc messagesFromContactsOnlyChanged*(self: Model) {.signal.}
proc setProfile*(self: Model, profile: item.Item) =
self.username = profile.username
self.identicon = profile.identicon
self.messagesFromContactsOnly = profile.messagesFromContactsOnly
self.appearance = profile.appearance
self.pubKey = profile.id
self.address = profile.address
self.ensVerified = profile.ensVerified
self.identityImage = item.IdentityImage(thumbnail: profile.identityImage.thumbnail, large: profile.identityImage.large)
self.sendUserStatus = profile.sendUserStatus
self.currentUserStatus = profile.currentUserStatus
proc username*(self: Model): string {.slot.} = result = self.username
QtProperty[string] username:
read = username
proc identicon*(self: Model): string {.slot.} = result = self.identicon
QtProperty[string] identicon:
read = identicon
proc pubKey*(self: Model): string {.slot.} = self.pubKey
QtProperty[string] pubKey:
read = pubKey
proc address*(self: Model): string {.slot.} = self.address
QtProperty[string] address:
read = address
proc ensVerified*(self: Model): bool {.slot.} = self.ensVerified
QtProperty[bool] ensVerified:
read = ensVerified
proc appearance*(self: Model): int {.slot.} = result = self.appearance
proc setAppearance*(self: Model, appearance: int) {.slot.} =
if self.appearance == appearance:
return
self.appearance = appearance
self.appearanceChanged()
QtProperty[int] appearance:
read = appearance
write = setAppearance
notify = appearanceChanged
proc messagesFromContactsOnly*(self: Model): bool {.slot.} = result = self.messagesFromContactsOnly
proc setMessagesFromContactsOnly*(self: Model, messagesFromContactsOnly: bool) {.slot.} =
if self.messagesFromContactsOnly == messagesFromContactsOnly:
return
self.messagesFromContactsOnly = messagesFromContactsOnly
self.messagesFromContactsOnlyChanged()
QtProperty[bool] messagesFromContactsOnly:
read = messagesFromContactsOnly
write = setMessagesFromContactsOnly
notify = messagesFromContactsOnlyChanged
proc setIdentityImage*(self: Model, identityImage: item.IdentityImage) =
self.identityImage = identityImage
self.identityImageChanged()
proc removeIdentityImage*(self: Model) =
self.identityImage = item.IdentityImage(thumbnail: "", large: "")
self.identityImageChanged()
proc thumbnailImage*(self: Model): string {.slot.} =
if (?.self.identityImage.thumbnail != ""):
result = self.identityImage.thumbnail
else:
result = self.identicon
QtProperty[string] thumbnailImage:
read = thumbnailImage
notify = identityImageChanged
proc largeImage*(self: Model): string {.slot.} =
if (?.self.identityImage.large != ""):
result = self.identityImage.large
else:
result = self.identicon
QtProperty[string] largeImage:
read = largeImage
notify = identityImageChanged
proc hasIdentityImage*(self: Model): bool {.slot.} =
result = (?.self.identityImage.thumbnail != "")
result = false
QtProperty[bool] hasIdentityImage:
read = hasIdentityImage
notify = identityImageChanged
proc sendUserStatus*(self: Model): bool {.slot.} = result = self.sendUserStatus
proc setSendUserStatus*(self: Model, sendUserStatus: bool) {.slot.} =
if self.sendUserStatus == sendUserStatus:
return
self.sendUserStatus = sendUserStatus
self.sendUserStatusChanged()
QtProperty[bool] sendUserStatus:
read = sendUserStatus
write = setSendUserStatus
notify = sendUserStatusChanged
proc currentUserStatus*(self: Model): int {.slot.} = result = self.currentUserStatus
proc setCurrentUserStatus*(self: Model, currentUserStatus: int) {.slot.} =
if self.currentUserStatus == currentUserStatus:
return
self.currentUserStatus = currentUserStatus
self.currentUserStatusChanged()
QtProperty[int] currentUserStatus:
read = currentUserStatus
write = setCurrentUserStatus
notify = currentUserStatusChanged

View File

@ -0,0 +1,39 @@
import NimQml, Tables
import ./io_interface, ./view, ./controller, ./item
import ../../../../core/global_singleton
import ../../../../../app_service/service/profile/service as profile_service
import ../../../../../app_service/service/accounts/service as accounts_service
import ../../../../../app_service/service/settings/service as settings_service
export io_interface
type
Module* [T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface
delegate: T
controller: controller.AccessInterface
view: View
viewVariant: QVariant
moduleLoaded: bool
proc newModule*[T](delegate: T, accountsService: accounts_service.ServiceInterface, settingsService: settings_service.ServiceInterface, profileService: profile_service.ServiceInterface): Module[T] =
result = Module[T]()
result.delegate = delegate
result.view = newView(result)
result.viewVariant = result.view.getModel
result.controller = controller.newController[Module[T]](result, accountsService, settingsService, profileService)
result.moduleLoaded = false
singletonInstance.engine.setRootContextProperty("profileModule", result.viewVariant)
method delete*[T](self: Module[T]) =
self.view.delete
method load*[T](self: Module[T]) =
let profile = self.controller.getProfile()
self.view.setProfile(profile)
self.moduleLoaded = true
method isLoaded*[T](self: Module[T]): bool =
return self.moduleLoaded

View File

@ -0,0 +1,39 @@
import NimQml
import ./item
import ./model
import ./io_interface
import status/types/[identity_image, profile]
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
model: Model
modelVariant: QVariant
proc delete*(self: View) =
self.model.delete
self.modelVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete)
result.QObject.setup
result.delegate = delegate
result.model = newModel()
result.modelVariant = newQVariant(result.model)
proc modelChanged*(self: View) {.signal.}
proc getModel*(self: View): QVariant {.slot.} =
return self.modelVariant
QtProperty[QVariant] model:
read = getModel
notify = modelChanged
proc setProfile*(self: View, profile: Item) =
self.model.setProfile(profile)
self.modelChanged()

View File

@ -0,0 +1,15 @@
import NimQml
QtObject:
type
View* = ref object of QObject
proc setup(self: View) =
self.QObject.setup
proc delete*(self: View) =
self.QObject.delete
proc newView*(): View =
new(result, delete)
result.setup()

View File

View File

@ -0,0 +1,38 @@
import json, json_serialization, sequtils, chronicles
# import status/statusgo_backend_new/custom_tokens as custom_tokens
import status/statusgo_backend/settings as status_go_settings
import ./service_interface, ./dto
export service_interface
logScope:
topics = "settings-service"
const DESKTOP_VERSION {.strdefine.} = "0.0.0"
type
Service* = ref object of ServiceInterface
# profile: Dto
method delete*(self: Service) =
discard
proc newService*(): Service =
result = Service()
method init*(self: Service) =
try:
echo "init"
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
return
method getAppVersion*(self: Service): string =
return DESKTOP_VERSION
method getNodeVersion*(self: Service): string =
return status_go_settings.getWeb3ClientVersion()

View File

@ -0,0 +1,22 @@
import dto
export dto
type
ServiceInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for this service access.
method delete*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method init*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
# method getPubKey*(self: ServiceInterface): string {.base.} =
# raise newException(ValueError, "No implementation available")
method getAppVersion*(self: ServiceInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getNodeVersion*(self: ServiceInterface): string {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -39,6 +39,9 @@ method getImportedAccount*(self: Service): GeneratedAccountDto =
method isFirstTimeAccountLogin*(self: Service): bool =
return self.isFirstTimeAccountLogin
method generateAlias*(self: Service, publicKey: string): string =
return status_go.generateAlias(publicKey).result.getStr
method init*(self: Service) =
try:
let response = status_go.generateAddresses(PATHS)
@ -47,9 +50,7 @@ method init*(self: Service) =
proc(x: JsonNode): GeneratedAccountDto = toGeneratedAccountDto(x))
for account in self.generatedAccounts.mitems:
let responseAlias = status_go.generateAlias(
account.derivedAccounts.whisper.publicKey)
account.alias = responseAlias.result.getStr
account.alias = self.generateAlias(account.derivedAccounts.whisper.publicKey)
let responseIdenticon = status_go.generateIdenticon(
account.derivedAccounts.whisper.publicKey)
@ -277,9 +278,7 @@ method importMnemonic*(self: Service, mnemonic: string): bool =
let responseDerived = status_go.deriveAccounts(self.importedAccount.id, PATHS)
self.importedAccount.derivedAccounts = toDerivedAccounts(responseDerived.result)
let responseAlias = status_go.generateAlias(
self.importedAccount.derivedAccounts.whisper.publicKey)
self.importedAccount.alias = responseAlias.result.getStr
self.importedAccount.alias= self.generateAlias(self.importedAccount.derivedAccounts.whisper.publicKey)
let responseIdenticon = status_go.generateIdenticon(
self.importedAccount.derivedAccounts.whisper.publicKey)

View File

@ -51,4 +51,7 @@ method login*(self: ServiceInterface, account: AccountDto, password: string):
raise newException(ValueError, "No implementation available")
method clear*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
raise newException(ValueError, "No implementation available")
method generateAlias*(self: ServiceInterface, publicKey: string): string {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -4,6 +4,8 @@ import json, strformat
include ../../../common/json_utils
# const DELETE_CONTACT* = "delete_contact"
type
Images* = ref object
thumbnail*: string
@ -13,7 +15,7 @@ type ContactsDto* = ref object
id*: string
name*: string
ensVerified*: bool
alias: string
alias*: string
identicon*: string
lastUpdated*: int64
image*: Images
@ -21,7 +23,7 @@ type ContactsDto* = ref object
blocked*: bool
hasAddedUs*: bool
isSyncing*: bool
removed: bool
removed*: bool
proc `$`(self: Images): string =
result = fmt"""Images(
@ -32,8 +34,8 @@ proc `$`(self: Images): string =
proc `$`*(self: ContactsDto): string =
result = fmt"""ContactDto(
id: {self.id},
name: {self.name},
ensVerified: {self.ensVerified},
name: {self.name},
ensVerified: {self.ensVerified},
alias: {self.alias},
identicon: {self.identicon},
lastUpdated: {self.lastUpdated},

View File

@ -1,7 +1,10 @@
import Tables, json, sequtils, strformat, chronicles
import service_interface, ./dto/contacts
import status/statusgo_backend_new/contacts as status_go
import status/statusgo_backend_new/contacts as status_contacts
import status/statusgo_backend_new/accounts as status_accounts
import status/statusgo_backend_new/chat as status_chat
import status/statusgo_backend_new/utils as status_utils
export service_interface
@ -21,7 +24,7 @@ proc newService*(): Service =
method init*(self: Service) =
try:
let response = status_go.getContacts()
let response = status_contacts.getContacts()
let contacts = map(response.result.getElems(),
proc(x: JsonNode): ContactsDto = x.toContactsDto())
@ -32,4 +35,124 @@ method init*(self: Service) =
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
return
return
# method getContacts*(self: Service): seq[Profile] =
# return status_contacts.getContacts(false)
method getContact*(self: Service, id: string): ContactsDto =
return status_contacts.getContactByID(id).result.toContactsDto()
method getOrCreateContact*(self: Service, id: string): ContactsDto =
result = status_contacts.getContactByID(id).result.toContactsDto()
if result == nil:
let alias = $status_accounts.generateAlias(id)
result = ContactsDto(
id: id,
# username: alias,
# localNickname: "",
identicon: $status_accounts.generateIdenticon(id),
alias: alias,
# ensName: "",
ensVerified: false,
# appearance: 0,
added: false,
blocked: false,
hasAddedUs: false
)
proc saveContact(self: Service, contact: ContactsDto) =
var thumbnail = ""
var largeImage = ""
# if contact.identityImage != nil:
# thumbnail = contact.identityImage.thumbnail
# largeImage = contact.identityImage.large
# status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, largeImage, contact.added, contact.blocked, contact.hasAddedUs, contact.localNickname)
status_contacts.saveContact(contact.id, contact.ensVerified, "", contact.alias, contact.identicon, thumbnail, largeImage, contact.added, contact.blocked, contact.hasAddedUs, "")
method addContact*(self: Service, publicKey: string) =
var contact = self.getOrCreateContact(publicKey)
let updating = contact.added
if not updating:
contact.added = true
# discard status_chat.createProfileChat(contact.id)
else:
contact.blocked = false
# FIXME Save contact fails
try:
self.saveContact(contact)
except Exception as e:
echo "ERROROR ", e.msg
# self.events.emit("contactAdded", Args())
# sendContactUpdate(contact.id, accountKeyUID)
if updating:
let profile = ContactsDto(
id: contact.id,
# username: contact.alias,
identicon: contact.identicon,
alias: contact.alias,
# ensName: contact.ensName,
ensVerified: contact.ensVerified,
# appearance: 0,
added: contact.added,
blocked: contact.blocked,
hasAddedUs: contact.hasAddedUs,
# localNickname: contact.localNickname
)
# self.events.emit("contactUpdate", ContactUpdateArgs(contacts: @[profile]))
method rejectContactRequest*(self: Service, publicKey: string) =
let contact = status_contacts.getContactByID(publicKey).result.toContactsDto()
contact.hasAddedUs = false
self.saveContact(contact)
# self.events.emit("contactRemoved", Args())
# status_contacts.rejectContactRequest(publicKey)
method changeContactNickname*(self: Service, accountKeyUID: string, publicKey: string, nicknameToSet: string) =
# status_contacts.setNickName(publicKey, nicknameToSet, accountKeyUID)
var contact = self.getOrCreateContact(publicKey)
# let nickname =
# if (nicknameToSet == ""):
# contact.localNickname
# elif (nicknameToSet == DELETE_CONTACT):
# ""
# else:
# nicknameToSet
# contact.localNickname = nickname
self.saveContact(contact)
# self.events.emit("contactAdded", Args())
# sendContactUpdate(contact.id, accountKeyUID)
method unblockContact*(self: Service, publicKey: string) =
# status_contacts.unblockContact(publicKey)
var contact = status_contacts.getContactByID(publicKey).result.toContactsDto()
contact.blocked = false
self.saveContact(contact)
# self.events.emit("contactUnblocked", ContactIdArgs(id: publicKey))
method blockContact*(self: Service, publicKey: string) =
# status_contacts.blockContact(publicKey)
var contact = status_contacts.getContactByID(publicKey).result.toContactsDto()
contact.blocked = true
self.saveContact(contact)
# self.events.emit("contactBlocked", ContactIdArgs(id: publicKey))
method removeContact*(self: Service, publicKey: string) =
# status_contacts.removeContact(publicKey)
var contact = status_contacts.getContactByID(publicKey).result.toContactsDto()
contact.added = false
contact.hasAddedUs = false
self.saveContact(contact)
# self.events.emit("contactRemoved", Args())
# let channelId = status_utils.getTimelineChatId(publicKey)
# if status_chat.hasChannel(channelId):
# status_chat.leave(channelId)

View File

@ -11,3 +11,30 @@ method delete*(self: ServiceInterface) {.base.} =
method init*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getContact*(self: ServiceInterface, id: string): contacts_dto.ContactsDto {.base.} =
raise newException(ValueError, "No implementation available")
method getOrCreateContact*(self: ServiceInterface, id: string): contacts_dto.ContactsDto {.base.} =
raise newException(ValueError, "No implementation available")
method saveContact*(self: ServiceInterface, contact: contacts_dto.ContactsDto) {.base.} =
raise newException(ValueError, "No implementation available")
method addContact*(self: ServiceInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method rejectContactRequest*(self: ServiceInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method changeContactNickname*(self: ServiceInterface, accountKeyUID: string, publicKey: string, nicknameToSet: string) {.base.} =
raise newException(ValueError, "No implementation available")
method unblockContact*(self: ServiceInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method blockContact*(self: ServiceInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method removeContact*(self: ServiceInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -0,0 +1,33 @@
{.used.}
import json, strformat
include ../../common/json_utils
type Dto* = ref object
username*: string
identicon*: string
largeImage*: string
thumbnailImage*: string
hasIdentityImage*: bool
messagesFromContactsOnly*: bool
proc `$`*(self: Dto): string =
result = fmt"""ProfileDto(
username: {self.username},
identicon: {self.identicon},
largeImage: {self.largeImage},
thumbnailImage: {self.thumbnailImage},
hasIdentityImage: {self.hasIdentityImage},
messagesFromContactsOnly: {self.messagesFromContactsOnly}
)"""
proc toDto*(jsonObj: JsonNode): Dto =
result = Dto()
discard jsonObj.getProp("username", result.username)
discard jsonObj.getProp("identicon", result.identicon)
discard jsonObj.getProp("largeImage", result.largeImage)
discard jsonObj.getProp("thumbnailImage", result.thumbnailImage)
discard jsonObj.getProp("hasIdentityImage", result.hasIdentityImage)
discard jsonObj.getProp("messagesFromContactsOnly", result.messagesFromContactsOnly)

View File

@ -0,0 +1,38 @@
import json, sequtils, chronicles
import ./service_interface, ./dto
export service_interface
logScope:
topics = "profile-service"
type
Service* = ref object of ServiceInterface
profile: Dto
method delete*(self: Service) =
discard
proc newService*(): Service =
result = Service()
method init*(self: Service) =
try:
self.profile = self.getProfile()
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
return
method getProfile*(self: Service): Dto =
return Dto(
username: "test username",
identicon: "",
largeImage: "",
thumbnailImage: "",
hasIdentityImage: false,
messagesFromContactsOnly: false
)

View File

@ -0,0 +1,19 @@
import dto
export dto
type
ServiceInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for this service access.
method delete*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method init*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getProfile*(self: ServiceInterface): Dto {.base.} =
raise newException(ValueError, "No implementation available")
# method getTokens*(self: ServiceInterface, chainId: int): seq[Dto] {.base.} =
# raise newException(ValueError, "No implementation available")

View File

@ -0,0 +1,5 @@
type
IdentityImage* = ref object
thumbnail*: string
large*: string

View File

@ -0,0 +1,58 @@
import json, json_serialization, sequtils, chronicles
# import status/statusgo_backend_new/custom_tokens as custom_tokens
import status/statusgo_backend/settings as status_go_settings
import status/statusgo_backend/accounts as status_accounts
from status/types/setting import Setting
import ./service_interface, ./dto
export service_interface
logScope:
topics = "settings-service"
type
Service* = ref object of ServiceInterface
# profile: Dto
method delete*(self: Service) =
discard
proc newService*(): Service =
result = Service()
method init*(self: Service) =
try:
echo "init"
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
return
method getPubKey*(self: Service): string=
return status_go_settings.getSetting(Setting.PublicKey, "0x0")
method getNetwork*(self: Service): string =
const DEFAULT_NETWORK_NAME = "mainnet_rpc"
return status_go_settings.getSetting(Setting.Networks_CurrentNetwork, DEFAULT_NETWORK_NAME)
method getAppearance*(self: Service): int =
let appearance: int = status_go_settings.getSetting[int](Setting.Appearance, 0)
return appearance
method getMessagesFromContactsOnly*(self: Service): bool =
return status_go_settings.getSetting[bool](Setting.MessagesFromContactsOnly)
method getSendUserStatus*(self: Service): bool =
return status_go_settings.getSetting[bool](Setting.SendUserStatus)
method getCurrentUserStatus*(self: Service): int =
let userStatus = status_go_settings.getSetting[JsonNode](Setting.CurrentUserStatus)
return userStatus{"statusType"}.getInt()
method getIdentityImage*(self: Service, address: string): IdentityImage =
var obj = status_accounts.getIdentityImage(address)
var identityImage = IdentityImage(thumbnail: obj.thumbnail, large: obj.large)
return identityImage

View File

@ -0,0 +1,34 @@
import dto
export dto
type
ServiceInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for this service access.
method delete*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method init*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getPubKey*(self: ServiceInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getNetwork*(self: ServiceInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getAppearance*(self: ServiceInterface): int {.base.} =
raise newException(ValueError, "No implementation available")
method getMessagesFromContactsOnly*(self: ServiceInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getSendUserStatus*(self: ServiceInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getCurrentUserStatus*(self: ServiceInterface): int {.base.} =
raise newException(ValueError, "No implementation available")
method getIdentityImage*(self: ServiceInterface, address: string): IdentityImage {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -5,6 +5,11 @@ QtObject {
id: root
property var profileModelInst: profileModel
property var profileModuleInst: profileSectionModule
property var profile: profileModule
property var contactsModuleInst: contactsModule
property var aboutModuleInst: aboutModule
property var chatsModelInst: chatsModel
property var utilsModelInst: utilsModel
property var walletModelInst: walletModel
@ -15,32 +20,32 @@ QtObject {
property var permissionList: profileModelInst.dappList.permissionList
property var mailservers: profileModelInst.mailservers
property var mailserversList: profileModelInst.mailservers.list
property var contacts: profileModelInst.contacts
property var blockedContacts: profileModelInst.contacts.blockedContacts
property var addedContacts: profileModelInst.contacts.addedContacts
property var contacts: profileModelInst.contacts.model.list
property var blockedContacts: profileModelInst.contacts.model.blockedContacts
property var addedContacts: profileModelInst.contacts.model.addedContacts
property var mutedChatsContacts: profileModelInst.mutedChats.contacts
property var mutedChats: profileModelInst.mutedChats.chats
property var devicesList: profileModelInst.devices.list
property string ensRegisterAddress: utilsModelInst.ensRegisterAddress
property string etherscanLink: walletModelInst.utilsView.etherscanLink
property string pubKey: profileModelInst.profile.pubKey
property string pubKey: profile.pubKey
property string fleet: profileModelInst.fleets.fleet
property string bloomLevel: nodeModelInst.bloomLevel
property string currentNetwork: profileModelInst.network.current
property string preferredUsername: profileModelInst.ens.preferredUsername
property string firstEnsUsername: profileModelInst.ens.firstEnsUsername
property string username: profileModelInst.profile.username
property string identicon: profileModelInst.profile.identicon
property string profileLargeImage: profileModelInst.profile.largeImage
property string profileThumbnailImage: profileModelInst.profile.thumbnailImage
property string username: profile.username
property string identicon: profile.identicon
property string profileLargeImage: profile.largeImage
property string profileThumbnailImage: profile.thumbnailImage
property bool profileHasIdentityImage: profileModelInst.profile.hasIdentityImage
property bool profileHasIdentityImage: profile.hasIdentityImage
property bool automaticMailserverSelection: profileModelInst.mailservers.automaticSelection
property bool isWakuV2LightClient: nodeModelInst.WakuV2LightClient
property bool devicesSetup: profileModelInst.devices.isSetup
property bool mnemonicBackedUp: profileModelInst.mnemonic.isBackedUp
property bool messagesFromContactsOnly: profileModelInst.profile.messagesFromContactsOnly
property bool messagesFromContactsOnly: profile.messagesFromContactsOnly
property int profile_id: 0
property int contacts_id: 1
@ -188,11 +193,12 @@ QtObject {
}
function lookupContact(value) {
profileModelInst.contacts.lookupContact(value)
console.log('lookup ples', value, profileModelInst)
contactsModuleInst.lookupContact(value)
}
function addContact(pubKey) {
profileModelInst.contacts.addContact(pubKey)
contactsModuleInst.addContact(pubKey)
}
function generateAlias(pubKey) {
@ -208,19 +214,19 @@ QtObject {
}
function unblockContact(address) {
profileModelInst.contacts.unblockContact(address)
contactsModuleInst.unblockContact(address)
}
function blockContact(address) {
profileModelInst.contacts.blockContact(address)
contactsModuleInst.blockContact(address)
}
function isContactAdded(address) {
return profileModelInst.contacts.isAdded(address)
return contactsModuleInst.model.isAdded(address)
}
function removeContact(address) {
profileModelInst.contacts.removeContact(address)
contactsModuleInst.removeContact(address)
}
function ensDetails(username) {
@ -234,11 +240,11 @@ QtObject {
function validateEns(ensName, isStatus) {
profileModelInst.ens.validate(ensName, isStatus)
}
function registerEnsGasEstimate(username, address) {
return profileModelInst.ens.registerENSGasEstimate(username, address)
}
function registerEns(username, address, gasLimit, tipLimit, overallLimit, gasPrice, password) {
return profileModelInst.ens.registerENS(username,
address, gasLimit, tipLimit, overallLimit, gasPrice, password)
@ -317,11 +323,11 @@ QtObject {
}
function getCurrentVersion() {
return utilsModelInst.getCurrentVersion()
return aboutModuleInst.getCurrentVersion()
}
function nodeVersion() {
return profileModelInst.nodeVersion()
return aboutModuleInst.nodeVersion()
}
function checkForUpdates() {

View File

@ -164,6 +164,7 @@ Item {
}
property var lookupContact: Backpressure.debounce(addContactSearchInput, 400, function (value) {
console.log('Lookup', value)
root.isPending = true
searchResults.showProfileNotFoundMessage = false
root.store.lookupContact(value)
@ -196,8 +197,8 @@ Item {
Connections {
target: root.store.contacts
onEnsWasResolved: {
target: root.store.contactsModuleInst
onEnsWasResolved: function (resolvedPubKey) {
if (resolvedPubKey === "") {
searchResults.pubKey = ""
searchResults.showProfileNotFoundMessage = true