From 4a4f1b8bf9d06b83d14b1e5685e60da670464c74 Mon Sep 17 00:00:00 2001 From: MishkaRogachev Date: Thu, 9 Nov 2023 17:14:37 +0400 Subject: [PATCH] feat(Profile): Move profile showcase out of contact --- .../core/signals/remote_signals/messages.nim | 6 +++ .../modules/main/profile_section/module.nim | 2 +- .../profile_section/profile/controller.nim | 18 ++++----- .../profile_section/profile/io_interface.nim | 4 ++ .../main/profile_section/profile/module.nim | 26 +++++++------ .../service/contacts/dto/contacts.nim | 6 --- .../service/profile/async_tasks.nim | 19 +++++++++ .../dto/profile_showcase.nim} | 9 +++-- src/app_service/service/profile/service.nim | 39 ++++++++++++++++++- src/backend/accounts.nim | 4 ++ .../views/profile/ProfileShowcaseView.qml | 5 --- 11 files changed, 98 insertions(+), 40 deletions(-) rename src/app_service/service/{contacts/dto/contact_profile.nim => profile/dto/profile_showcase.nim} (90%) diff --git a/src/app/core/signals/remote_signals/messages.nim b/src/app/core/signals/remote_signals/messages.nim index fb56d71ccf..6065154a6c 100644 --- a/src/app/core/signals/remote_signals/messages.nim +++ b/src/app/core/signals/remote_signals/messages.nim @@ -13,6 +13,7 @@ import ../../../../app_service/service/devices/dto/[installation] import ../../../../app_service/service/settings/dto/[settings] import ../../../../app_service/service/saved_address/dto as saved_address_dto import ../../../../app_service/service/wallet_account/dto/[keypair_dto] +import ../../../../app_service/service/profile/dto/[profile_showcase] type MessageSignal* = ref object of Signal bookmarks*: seq[BookmarkDto] @@ -38,6 +39,7 @@ type MessageSignal* = ref object of Signal keypairs*: seq[KeypairDto] watchOnlyAccounts*: seq[WalletAccountDto] accountsPositions*: seq[WalletAccountDto] + updatedProfileShowcases*: seq[ProfileShowcaseDto] type MessageDeliveredSignal* = ref object of Signal chatId*: string @@ -156,5 +158,9 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal = for jsonAcc in e["accountsPositions"]: signal.accountsPositions.add(jsonAcc.toWalletAccountDto()) + if e.contains("updatedProfileShowcases"): + for jsonProfileShowcase in e["updatedProfileShowcases"]: + signal.updatedProfileShowcases.add(jsonProfileShowcase.toProfileShowcaseDto()) + result = signal diff --git a/src/app/modules/main/profile_section/module.nim b/src/app/modules/main/profile_section/module.nim index 66b54246d8..713ae8d18f 100644 --- a/src/app/modules/main/profile_section/module.nim +++ b/src/app/modules/main/profile_section/module.nim @@ -94,7 +94,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface, result.controller = controller.newController(result) result.moduleLoaded = false - result.profileModule = profile_module.newModule(result, events, profileService, settingsService, communityService, walletAccountService, contactsService) + result.profileModule = profile_module.newModule(result, events, profileService, settingsService, communityService, walletAccountService) result.contactsModule = contacts_module.newModule(result, events, contactsService, chatService) result.languageModule = language_module.newModule(result, events, languageService) result.privacyModule = privacy_module.newModule(result, events, settingsService, keychainService, privacyService, generalService) diff --git a/src/app/modules/main/profile_section/profile/controller.nim b/src/app/modules/main/profile_section/profile/controller.nim index 2bd2ef1c70..d40c80d6ea 100644 --- a/src/app/modules/main/profile_section/profile/controller.nim +++ b/src/app/modules/main/profile_section/profile/controller.nim @@ -7,7 +7,6 @@ import app_service/service/profile/service as profile_service import app_service/service/settings/service as settings_service import app_service/service/community/service as community_service import app_service/service/wallet_account/service as wallet_account_service -import app_service/service/contacts/service as contacts_service import app_service/common/social_links import app_service/service/profile/dto/profile_showcase_preferences @@ -20,7 +19,6 @@ type settingsService: settings_service.Service communityService: community_service.Service walletAccountService: wallet_account_service.Service - contactsService: contacts_service.Service proc newController*( delegate: io_interface.AccessInterface, @@ -28,8 +26,7 @@ proc newController*( profileService: profile_service.Service, settingsService: settings_service.Service, communityService: community_service.Service, - walletAccountService: wallet_account_service.Service, - contactsService: contacts_service.Service): Controller = + walletAccountService: wallet_account_service.Service): Controller = result = Controller() result.delegate = delegate result.events = events @@ -37,7 +34,6 @@ proc newController*( result.settingsService = settingsService result.communityService = communityService result.walletAccountService = walletAccountService - result.contactsService = contactsService proc delete*(self: Controller) = discard @@ -57,9 +53,9 @@ proc init*(self: Controller) = let args = ProfileShowcasePreferencesArgs(e) self.delegate.updateProfileShowcasePreferences(args.preferences) - self.events.on(SIGNAL_CONTACT_UPDATED) do(e: Args): - var args = ContactArgs(e) - self.delegate.onContactDetailsUpdated(args.contactId) + self.events.on(SIGNAL_PROFILE_SHOWCASE_FOR_CONTACT_UPDATED) do(e: Args): + let args = ProfileShowcaseForContactArgs(e) + self.delegate.updateProfileShowcase(args.profileShowcase) self.events.on(SIGNAL_COMMUNITIES_UPDATE) do(e: Args): let args = CommunitiesArgs(e) @@ -86,9 +82,6 @@ proc getAccountByAddress*(self: Controller, address: string): WalletAccountDto = proc getTokensByAddresses*(self: Controller, addresses: seq[string]): seq[WalletTokenDto] = return self.walletAccountService.getTokensByAddresses(addresses) -proc getContactById*(self: Controller, id: string): ContactsDto = - return self.contactsService.getContactById(id) - proc setSocialLinks*(self: Controller, links: SocialLinks) = self.settingsService.setSocialLinks(links) @@ -104,5 +97,8 @@ proc storeProfileShowcasePreferences*(self: Controller, preferences: ProfileShow proc requestProfileShowcasePreferences*(self: Controller) = self.profileService.requestProfileShowcasePreferences() +proc requestProfileShowcaseForContact*(self: Controller, contactId: string) = + self.profileService.requestProfileShowcaseForContact(contactId) + proc requestCommunityInfo*(self: Controller, communityId: string) = self.communityService.requestCommunityInfo(communityId) diff --git a/src/app/modules/main/profile_section/profile/io_interface.nim b/src/app/modules/main/profile_section/profile/io_interface.nim index 9019d2f699..b1d00f4d29 100644 --- a/src/app/modules/main/profile_section/profile/io_interface.nim +++ b/src/app/modules/main/profile_section/profile/io_interface.nim @@ -1,6 +1,7 @@ import NimQml import app_service/common/social_links +import app_service/service/profile/dto/profile_showcase import app_service/service/profile/dto/profile_showcase_preferences import app_service/service/community/dto/community @@ -62,6 +63,9 @@ method requestProfileShowcasePreferences*(self: AccessInterface) {.base.} = method requestProfileShowcase*(self: AccessInterface, publicKey: string) {.base.} = raise newException(ValueError, "No implementation available") +method updateProfileShowcase*(self: AccessInterface, profileShowcase: ProfileShowcaseDto) {.base.} = + raise newException(ValueError, "No implementation available") + method updateProfileShowcasePreferences*(self: AccessInterface, preferences: ProfileShowcasePreferencesDto) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/profile_section/profile/module.nim b/src/app/modules/main/profile_section/profile/module.nim index 4acc6d3dde..8bf22ae482 100644 --- a/src/app/modules/main/profile_section/profile/module.nim +++ b/src/app/modules/main/profile_section/profile/module.nim @@ -9,7 +9,7 @@ import app_service/service/profile/service as profile_service import app_service/service/settings/service as settings_service import app_service/service/community/service as community_service import app_service/service/wallet_account/service as wallet_account_service -import app_service/service/contacts/service as contacts_service +import app_service/service/profile/dto/profile_showcase import app_service/service/profile/dto/profile_showcase_preferences import app_service/common/social_links @@ -41,13 +41,12 @@ proc newModule*( profileService: profile_service.Service, settingsService: settings_service.Service, communityService: community_service.Service, - walletAccountService: wallet_account_service.Service, - contactsService: contacts_service.Service): Module = + walletAccountService: wallet_account_service.Service): Module = result = Module() result.delegate = delegate result.view = view.newView(result) result.viewVariant = newQVariant(result.view) - result.controller = controller.newController(result, events, profileService, settingsService, communityService, walletAccountService, contactsService) + result.controller = controller.newController(result, events, profileService, settingsService, communityService, walletAccountService) result.moduleLoaded = false method delete*(self: Module) = @@ -138,14 +137,18 @@ method requestProfileShowcase*(self: Module, publicKey: string) = self.view.clearModels() self.presentedPublicKey = publicKey - let contact = self.controller.getContactById(publicKey) + self.controller.requestProfileShowcaseForContact(publicKey) + +method updateProfileShowcase(self: Module, profileShowcase: ProfileShowcaseDto) = + if self.presentedPublicKey != profileShowcase.contactId: + return var profileCommunityItems: seq[ProfileShowcaseCommunityItem] = @[] var profileAccountItems: seq[ProfileShowcaseAccountItem] = @[] var profileCollectibleItems: seq[ProfileShowcaseCollectibleItem] = @[] var profileAssetItems: seq[ProfileShowcaseAssetItem] = @[] - for communityEntry in contact.profileShowcase.communities: + for communityEntry in profileShowcase.communities: let community = self.controller.getCommunityById(communityEntry.communityId) if community.id == "": self.controller.requestCommunityInfo(communityEntry.communityId) @@ -157,7 +160,7 @@ method requestProfileShowcase*(self: Module, publicKey: string) = self.view.updateProfileShowcaseCommunities(profileCommunityItems) var addresses: seq[string] = @[] - for account in contact.profileShowcase.accounts: + for account in profileShowcase.accounts: profileAccountItems.add(initProfileShowcaseAccountItem( account.address, account.name, @@ -168,7 +171,7 @@ method requestProfileShowcase*(self: Module, publicKey: string) = )) addresses.add(account.address) - for assetEntry in contact.profileShowcase.assets: + for assetEntry in profileShowcase.assets: for token in self.controller.getTokensByAddresses(addresses): if assetEntry.symbol == token.symbol: profileAssetItems.add(initProfileShowcaseAssetItem(token, ProfileShowcaseVisibility.ToEveryone, assetEntry.order)) @@ -178,6 +181,9 @@ method requestProfileShowcase*(self: Module, publicKey: string) = # TODO: collectibles, need wallet api to fetch collectible by uid method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowcasePreferencesDto) = + if self.presentedPublicKey != singletonInstance.userProfile.getPubKey(): + return + var profileCommunityItems: seq[ProfileShowcaseCommunityItem] = @[] var profileAccountItems: seq[ProfileShowcaseAccountItem] = @[] var profileCollectibleItems: seq[ProfileShowcaseCollectibleItem] = @[] @@ -215,10 +221,6 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca self.view.updateProfileShowcaseAssets(profileAssetItems) # TODO: collectibles, need wallet api to fetch collectible by uid -method onContactDetailsUpdated*(self: Module, contactId: string) = - if self.presentedPublicKey == contactId: - self.requestProfileShowcase(contactId) - method onCommunitiesUpdated*(self: Module, communities: seq[CommunityDto]) = var profileCommunityItems = self.view.getProfileShowcaseCommunities() diff --git a/src/app_service/service/contacts/dto/contacts.nim b/src/app_service/service/contacts/dto/contacts.nim index bd84242142..78d091fd50 100644 --- a/src/app_service/service/contacts/dto/contacts.nim +++ b/src/app_service/service/contacts/dto/contacts.nim @@ -2,7 +2,6 @@ import json, strformat, strutils import ../../../common/social_links -import ./contact_profile include ../../../common/json_utils include ../../../common/utils @@ -54,7 +53,6 @@ type ContactsDto* = object localNickname*: string bio*: string socialLinks*: SocialLinks - profileShowcase*: ProfileShowcase image*: Images added*: bool blocked*: bool @@ -169,10 +167,6 @@ proc toContactsDto*(jsonObj: JsonNode): ContactsDto = if(jsonObj.getProp("socialLinks", socialLinksObj)): result.socialLinks = toSocialLinks(socialLinksObj) - var profileShowcaseObj: JsonNode - if(jsonObj.getProp("profileShowcase", profileShowcaseObj)): - result.profileShowcase = toProfileShowcase(profileShowcaseObj) - discard jsonObj.getProp("added", result.added) discard jsonObj.getProp("blocked", result.blocked) discard jsonObj.getProp("hasAddedUs", result.hasAddedUs) diff --git a/src/app_service/service/profile/async_tasks.nim b/src/app_service/service/profile/async_tasks.nim index bff36a6652..de8f4b117f 100644 --- a/src/app_service/service/profile/async_tasks.nim +++ b/src/app_service/service/profile/async_tasks.nim @@ -17,3 +17,22 @@ const asyncGetProfileShowcasePreferencesTask: Task = proc(argEncoded: string) {. arg.finish(%* { "error": e.msg, }) + +type + AsyncGetProfileShowcaseForContactTaskArg = ref object of QObjectTaskArg + pubkey: string + +const asyncGetProfileShowcaseForContactTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = + let arg = decode[AsyncGetProfileShowcaseForContactTaskArg](argEncoded) + try: + let response = status_accounts.getProfileShowcaseForContact(arg.pubkey) + arg.finish(%* { + "publicKey": arg.pubkey, + "response": response, + "error": nil, + }) + except Exception as e: + arg.finish(%* { + "publicKey": arg.pubkey, + "error": e.msg, + }) diff --git a/src/app_service/service/contacts/dto/contact_profile.nim b/src/app_service/service/profile/dto/profile_showcase.nim similarity index 90% rename from src/app_service/service/contacts/dto/contact_profile.nim rename to src/app_service/service/profile/dto/profile_showcase.nim index 2c92298e73..89a9ebf17a 100644 --- a/src/app_service/service/contacts/dto/contact_profile.nim +++ b/src/app_service/service/profile/dto/profile_showcase.nim @@ -21,7 +21,8 @@ type ProfileShowcaseAsset* = ref object of RootObj symbol*: string order*: int -type ProfileShowcase* = ref object of RootObj +type ProfileShowcaseDto* = ref object of RootObj + contactId*: string communities*: seq[ProfileShowcaseCommunity] accounts*: seq[ProfileShowcaseAccount] collectibles*: seq[ProfileShowcaseCollectible] @@ -50,8 +51,10 @@ proc toProfileShowcaseAsset*(jsonObj: JsonNode): ProfileShowcaseAsset = discard jsonObj.getProp("symbol", result.symbol) discard jsonObj.getProp("order", result.order) -proc toProfileShowcase*(jsonObj: JsonNode): ProfileShowcase = - result = ProfileShowcase() +proc toProfileShowcaseDto*(jsonObj: JsonNode): ProfileShowcaseDto = + result = ProfileShowcaseDto() + + discard jsonObj.getProp("contactId", result.contactId) for jsonMsg in jsonObj["communities"]: result.communities.add(jsonMsg.toProfileShowcaseCommunity()) diff --git a/src/app_service/service/profile/service.nim b/src/app_service/service/profile/service.nim index e8e9b39d81..10e549cc4d 100644 --- a/src/app_service/service/profile/service.nim +++ b/src/app_service/service/profile/service.nim @@ -10,6 +10,7 @@ import ../../../app/core/tasks/[qt, threadpool] import ../../../backend/accounts as status_accounts import ../accounts/dto/accounts +import dto/profile_showcase import dto/profile_showcase_preferences include async_tasks @@ -21,8 +22,12 @@ type ProfileShowcasePreferencesArgs* = ref object of Args preferences*: ProfileShowcasePreferencesDto + ProfileShowcaseForContactArgs* = ref object of Args + profileShowcase*: ProfileShowcaseDto + # Signals which may be emitted by this service: const SIGNAL_PROFILE_SHOWCASE_PREFERENCES_UPDATED* = "profileShowcasePreferencesUpdated" +const SIGNAL_PROFILE_SHOWCASE_FOR_CONTACT_UPDATED* = "profileShowcaseForContactUpdated" QtObject: type Service* = ref object of QObject @@ -45,6 +50,13 @@ QtObject: let args = SettingsTextValueArgs(e) singletonInstance.userProfile.setDisplayName(args.value) + self.events.on(SignalType.Message.event) do(e: Args): + let receivedData = MessageSignal(e) + if receivedData.updatedProfileShowcases.len > 0: + for profileShowcase in receivedData.updatedProfileShowcases: + self.events.emit(SIGNAL_PROFILE_SHOWCASE_FOR_CONTACT_UPDATED, + ProfileShowcaseForContactArgs(profileShowcase: profileShowcase)) + proc storeIdentityImage*(self: Service, address: string, image: string, aX: int, aY: int, bX: int, bY: int): seq[Image] = try: let response = status_accounts.storeIdentityImage(address, image, aX, aY, bX, bY) @@ -93,15 +105,38 @@ QtObject: except Exception as e: error "error: ", procName="setDisplayName", errName = e.name, errDesription = e.msg + proc requestProfileShowcaseForContact*(self: Service, contactId: string) = + let arg = AsyncGetProfileShowcaseForContactTaskArg( + pubkey: contactId, + tptr: cast[ByteAddress](asyncGetProfileShowcaseForContactTask), + vptr: cast[ByteAddress](self.vptr), + slot: "asyncProfileShowcaseForContactLoaded", + ) + self.threadpool.start(arg) + + proc asyncProfileShowcaseForContactLoaded*(self: Service, rpcResponse: string) {.slot.} = + try: + let rpcResponseObj = rpcResponse.parseJson + if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "": + error "Error requesting profile showcase preferences", msg = rpcResponseObj{"error"} + return + + let profileShowcase = rpcResponseObj["response"]["result"].toProfileShowcaseDto() + + self.events.emit(SIGNAL_PROFILE_SHOWCASE_FOR_CONTACT_UPDATED, + ProfileShowcaseForContactArgs(profileShowcase: profileShowcase)) + except Exception as e: + error "Error requesting profile showcase for a contact", msg = e.msg + proc requestProfileShowcasePreferences*(self: Service) = let arg = QObjectTaskArg( tptr: cast[ByteAddress](asyncGetProfileShowcasePreferencesTask), vptr: cast[ByteAddress](self.vptr), - slot: "asyncProfileShowcaseLoaded", + slot: "asyncProfileShowcasePreferencesLoaded", ) self.threadpool.start(arg) - proc asyncProfileShowcaseLoaded*(self: Service, rpcResponse: string) {.slot.} = + proc asyncProfileShowcasePreferencesLoaded*(self: Service, rpcResponse: string) {.slot.} = try: let rpcResponseObj = rpcResponse.parseJson if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "": diff --git a/src/backend/accounts.nim b/src/backend/accounts.nim index 84c688a885..7573e9223e 100644 --- a/src/backend/accounts.nim +++ b/src/backend/accounts.nim @@ -474,6 +474,10 @@ proc verifyKeystoreFileForAccount*(address, password: string): RpcResponse[JsonN let payload = %* [address, password] return core.callPrivateRPC("accounts_verifyKeystoreFileForAccount", payload) +proc getProfileShowcaseForContact*(contactId: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [contactId] + result = callPrivateRPC("getProfileShowcaseForContact".prefix, payload) + proc getProfileShowcasePreferences*(): RpcResponse[JsonNode] {.raises: [Exception].} = result = callPrivateRPC("getProfileShowcasePreferences".prefix, %*[]) diff --git a/ui/imports/shared/views/profile/ProfileShowcaseView.qml b/ui/imports/shared/views/profile/ProfileShowcaseView.qml index 2071e62899..9c435add93 100644 --- a/ui/imports/shared/views/profile/ProfileShowcaseView.qml +++ b/ui/imports/shared/views/profile/ProfileShowcaseView.qml @@ -217,11 +217,6 @@ Control { } } ] - onClicked: { - if (root.readOnly) - return - root.walletStore.setFilterAddress(model.address) - } } } }