refactor: re-enable async search of ENS names for contacts

Fixes #3986
This commit is contained in:
Jonathan Rainville 2021-11-01 12:04:00 -04:00 committed by Iuri Matias
parent b6d41b67d8
commit 8aec0c62e7
12 changed files with 216 additions and 196 deletions

View File

@ -125,7 +125,7 @@ proc newAppController*(appService: AppService): AppController =
result.keychainService = keychain_service.newService(appService.status.events)
result.settingService = setting_service.newService()
result.accountsService = accounts_service.newService()
result.contactsService = contacts_service.newService(appService.status.events)
result.contactsService = contacts_service.newService(appService.status.events, appService.threadpool)
result.chatService = chat_service.newService()
result.communityService = community_service.newService(result.chatService)
result.tokenService = token_service.newService(appService.status.events, result.settingService)

View File

@ -70,7 +70,7 @@ proc newModule*[T](
settingService: setting_service.Service,
profileService: profile_service.ServiceInterface,
settingsService: settings_service.ServiceInterface,
contactsService: contacts_service.ServiceInterface,
contactsService: contacts_service.Service,
aboutService: about_service.ServiceInterface,
dappPermissionsService: dapp_permissions_service.ServiceInterface,
languageService: language_service.ServiceInterface,
@ -106,7 +106,7 @@ proc newModule*[T](
)
result.browserSectionModule = browser_section_module.newModule(result, bookmarkService, settingsService, dappPermissionsService)
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService, profileService, contactsService, aboutService, languageService, mnemonicService, privacyService)
result.profileSectionModule = profile_section_module.newModule(result,events, accountsService, settingsService, profileService, contactsService, aboutService, languageService, mnemonicService, privacyService)
method delete*[T](self: Module[T]) =
self.chatSectionModule.delete

View File

@ -13,7 +13,7 @@ type
Controller*[T: controller_interface.DelegateInterface] = ref object of controller_interface.AccessInterface
delegate: io_interface.AccessInterface
events: EventEmitter
contactsService: contacts_service.ServiceInterface
contactsService: contacts_service.Service
accountsService: accounts_service.ServiceInterface
# forward declaration:
@ -21,7 +21,7 @@ method getContacts*[T](self: Controller[T]): seq[ContactsDto]
proc newController*[T](delegate: io_interface.AccessInterface,
events: EventEmitter,
contactsService: contacts_service.ServiceInterface,
contactsService: contacts_service.Service,
accountsService: accounts_service.ServiceInterface): Controller[T] =
result = Controller[T]()
result.delegate = delegate
@ -49,6 +49,9 @@ method init*[T](self: Controller[T]) =
let contacts = self.getContacts()
self.delegate.setContactList(contacts)
self.events.on(SIGNAL_CONTACT_LOOKED_UP) do(e: Args):
let args = LookupResolvedArgs(e)
self.delegate.contactLookedUp(args.id)
method getContacts*[T](self: Controller[T]): seq[ContactsDto] =
return self.contactsService.getContacts()
@ -77,35 +80,5 @@ method removeContact*[T](self: Controller[T], publicKey: string): void =
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
method lookupContact*[T](self: Controller[T], value: string): void =
self.contactsService.lookupContact(value)

View File

@ -39,6 +39,9 @@ method removeContact*(self: AccessInterface, publicKey: string): void {.base.} =
method changeContactNickname*(self: AccessInterface, accountKeyUID: string, publicKey: string, nicknameToSet: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method lookupContact*(self: AccessInterface, value: string): void {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.

View File

@ -40,6 +40,12 @@ method removeContact*(self: AccessInterface, publicKey: string): void {.base.} =
method changeContactNickname*(self: AccessInterface, accountKeyUID: string, publicKey: string, nicknameToSet: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method lookupContact*(self: AccessInterface, value: string): void {.base.} =
raise newException(ValueError, "No implementation available")
method contactLookedUp*(self: AccessInterface, id: string): void {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.

View File

@ -21,7 +21,7 @@ type
proc newModule*[T](delegate: T,
events: EventEmitter,
contactsService: contacts_service.ServiceInterface,
contactsService: contacts_service.Service,
accountsService: accounts_service.ServiceInterface):
Module[T] =
result = Module[T]()
@ -71,3 +71,9 @@ method removeContact*[T](self: Module[T], publicKey: string): void =
method changeContactNickname*[T](self: Module[T], accountKeyUID: string, publicKey: string, nicknameToSet: string): void =
self.controller.changeContactNickname(accountKeyUID, publicKey, nicknameToSet)
method lookupContact*[T](self: Module[T], value: string): void =
self.controller.lookupContact(value)
method contactLookedUp*[T](self: Module[T], id: string): void =
self.view.contactLookedUp(id)

View File

@ -12,17 +12,6 @@ import ./io_interface
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
@ -81,42 +70,31 @@ QtObject:
proc ensWasResolved*(self: View, resolvedPubKey: string) {.signal.}
proc ensResolved(self: View, id: string) {.slot.} =
echo "Resolved", id
proc contactLookedUp*(self: View, id: string) {.slot.} =
self.ensWasResolved(id)
# if id == "":
# self.contactToAddChanged()
# return
# let contact = self.delegate.getContact(id)
if id == "":
self.contactToAddChanged()
return
# if contact != nil:
# self.contactToAdd = contact
# else:
# self.contactToAdd = ContactsDto(
# id: id,
# alias: self.delegate.generateAlias(id),
# ensVerified: false
# )
# self.contactToAddChanged()
let contact = self.delegate.getContact(id)
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)
if contact != nil and contact.id != "":
self.contactToAdd = contact
else:
self.contactToAdd = ContactsDto(
id: id,
alias: self.delegate.generateAlias(id),
ensVerified: false
)
self.contactToAddChanged()
proc lookupContact*(self: View, value: string) {.slot.} =
if value == "":
return
self.lookupContact("ensResolved", value)
self.delegate.lookupContact(value)
proc addContact*(self: View, publicKey: string) {.slot.} =
self.delegate.addContact(publicKey)

View File

@ -42,7 +42,7 @@ proc newModule*[T](delegate: T,
accountsService: accounts_service.ServiceInterface,
settingsService: settings_service.ServiceInterface,
profileService: profile_service.ServiceInterface,
contactsService: contacts_service.ServiceInterface,
contactsService: contacts_service.Service,
aboutService: about_service.ServiceInterface,
languageService: language_service.ServiceInterface,
mnemonicService: mnemonic_service.ServiceInterface,

View File

@ -0,0 +1,19 @@
import status/ens as status_ens
include ../../common/json_utils
include ../../tasks/common
#################################################
# Async lookup ENS contact
#################################################
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)

View File

@ -1,6 +1,7 @@
import Tables, json, sequtils, strformat, chronicles
import NimQml, Tables, json, sequtils, strformat, chronicles, strutils
import eventemitter
import ../../tasks/[qt, threadpool]
import service_interface, ./dto/contacts
import status/statusgo_backend_new/contacts as status_contacts
@ -11,137 +12,172 @@ import status/contacts as old_status_contacts
export service_interface
include async_tasks
logScope:
topics = "contacts-service"
type
Service* = ref object of ServiceInterface
type
LookupResolvedArgs* = ref object of Args
id*: string
# Signals which may be emitted by this service:
const SIGNAL_CONTACT_LOOKED_UP* = "SIGNAL_CONTACT_LOOKED_UP"
QtObject:
type Service* = ref object of QObject
threadpool: ThreadPool
contacts: Table[string, ContactsDto] # [contact_id, ContactsDto]
events: EventEmitter
method delete*(self: Service) =
discard
proc delete*(self: Service) =
self.QObject.delete
proc newService*(events: EventEmitter): Service =
result = Service()
result.events = events
result.contacts = initTable[string, ContactsDto]()
proc newService*(events: EventEmitter, threadpool: ThreadPool): Service =
new(result, delete)
result.QObject.setup
result.events = events
result.threadpool = threadpool
result.contacts = initTable[string, ContactsDto]()
method init*(self: Service) =
discard
proc init*(self: Service) =
discard
method getContacts*(self: Service): seq[ContactsDto] =
let profiles = status_contacts.getContacts()
for profile in profiles.result:
result.add(profile.toContactsDto)
proc getContacts*(self: Service): seq[ContactsDto] =
let profiles = status_contacts.getContacts()
for profile in profiles.result:
result.add(profile.toContactsDto)
method getContact*(self: Service, id: string): ContactsDto =
return status_contacts.getContactByID(id).result.toContactsDto()
proc 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 or result.id == "":
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 getOrCreateContact*(self: Service, id: string): ContactsDto =
result = self.getContact(id)
if result == nil or result.id == "":
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
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, "")
# 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
proc 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:
if not updating:
contact.added = true
# discard status_chat.createProfileChat(contact.id)
else:
contact.blocked = false
self.saveContact(contact)
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
)
# TODO fix this to use ContactsDto
# self.events.emit("contactUpdate", ContactUpdateArgs(contacts: @[profile]))
proc rejectContactRequest*(self: Service, publicKey: string) =
let contact = self.getContact(publicKey)
contact.hasAddedUs = false
self.saveContact(contact)
self.events.emit("contactRemoved", Args())
# status_contacts.rejectContactRequest(publicKey)
proc 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)
proc unblockContact*(self: Service, publicKey: string) =
# status_contacts.unblockContact(publicKey)
var contact = self.getContact(publicKey)
contact.blocked = false
self.saveContact(contact)
self.events.emit("contactUnblocked", old_status_contacts.ContactIdArgs(id: publicKey))
self.saveContact(contact)
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
proc blockContact*(self: Service, publicKey: string) =
var contact = self.getContact(publicKey)
contact.blocked = true
self.saveContact(contact)
self.events.emit("contactBlocked", old_status_contacts.ContactIdArgs(id: publicKey))
proc removeContact*(self: Service, publicKey: string) =
# status_contacts.removeContact(publicKey)
var contact = self.getContact(publicKey)
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)
proc ensResolved*(self: Service, id: string) {.slot.} =
# var contact = self.getContact(id)
# if contact == nil or contact.id == "":
# contact = ContactsDto(
# id: id,
# alias: $status_accounts.generateAlias(id),
# ensVerified: false
# )
let data = LookupResolvedArgs(id: id)
self.events.emit(SIGNAL_CONTACT_LOOKED_UP, data)
proc lookupContact*(self: Service, value: string) =
let arg = LookupContactTaskArg(
tptr: cast[ByteAddress](lookupContactTask),
vptr: cast[ByteAddress](self.vptr),
slot: "ensResolved",
value: value
)
# TODO fix this to use ContactsDto
# 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", old_status_contacts.ContactIdArgs(id: publicKey))
method blockContact*(self: Service, publicKey: string) =
var contact = status_contacts.getContactByID(publicKey).result.toContactsDto()
contact.blocked = true
self.saveContact(contact)
self.events.emit("contactBlocked", old_status_contacts.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)
self.threadpool.start(arg)

View File

@ -186,7 +186,6 @@ QtObject {
}
function lookupContact(value) {
console.log('lookup ples', value, profileModelInst)
contactsModuleInst.lookupContact(value)
}

View File

@ -173,7 +173,6 @@ Item {
}
property var lookupContact: Backpressure.debounce(addContactSearchInput, 400, function (value) {
console.log('Lookup', value)
root.isPending = true
searchResults.showProfileNotFoundMessage = false
root.store.lookupContact(value)
@ -182,6 +181,7 @@ Item {
onOpened: {
addContactSearchInput.text = ""
searchResults.reset()
addContactSearchInput.forceActiveFocus()
}
Input {