Feat: New showcase models for a contact (#13998)

* Feat: New showcase models for a contact

* feat(ProfileShowcase): Integrate the new profile showcase backend

* fix(Storybook): Fix ProfileShowcaseModelsPage

* fix: fetch only requested profile showcase data

Support PR for https://github.com/status-im/status-go/pull/4982

* feat: Load and validate profile showcase for a contact in two steps

* fix: fetching criteria for profile showcase collectibles

* fix: review fixes

---------

Co-authored-by: Alex Jbanca <alexjb@status.im>
This commit is contained in:
Mikhail Rogachev 2024-03-29 12:43:49 +01:00 committed by GitHub
parent c710f0e809
commit 839f2c6b21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 1247 additions and 2207 deletions

View File

@ -13,7 +13,6 @@ 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]
@ -40,7 +39,7 @@ type MessageSignal* = ref object of Signal
keypairs*: seq[KeypairDto]
watchOnlyAccounts*: seq[WalletAccountDto]
accountsPositions*: seq[WalletAccountDto]
updatedProfileShowcases*: seq[ProfileShowcaseDto]
updatedProfileShowcaseContactIDs*: seq[string]
type MessageDeliveredSignal* = ref object of Signal
chatId*: string
@ -167,8 +166,8 @@ 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())
if e.contains("updatedProfileShowcaseContactIDs"):
for contactId in e["updatedProfileShowcaseContactIDs"]:
signal.updatedProfileShowcaseContactIDs.add(contactId.getStr())
result = signal

View File

@ -1,9 +1,11 @@
import sugar, sequtils
import io_interface
import ../../../../core/eventemitter
import ../../../../../app_service/service/contacts/service as contacts_service
import ../../../../../app_service/service/chat/service as chat_service
import ../../../../../app_service/service/message/dto/message as message_dto
import app_service/service/contacts/service as contacts_service
import app_service/service/chat/service as chat_service
import app_service/service/network/service as network_service
import app_service/service/message/dto/message as message_dto
type
Controller* = ref object of RootObj
@ -11,16 +13,19 @@ type
events: EventEmitter
contactsService: contacts_service.Service
chatService: chat_service.Service
networkService: network_service.Service
proc newController*(delegate: io_interface.AccessInterface,
events: EventEmitter,
contactsService: contacts_service.Service,
chatService: chat_service.Service): Controller =
chatService: chat_service.Service,
networkService: network_service.Service): Controller =
result = Controller()
result.delegate = delegate
result.events = events
result.contactsService = contactsService
result.chatService = chatService
result.networkService = networkService
proc delete*(self: Controller) =
discard
@ -90,6 +95,18 @@ proc init*(self: Controller) =
let args = ContactInfoRequestArgs(e)
self.delegate.onContactInfoRequestFinished(args.publicKey, args.ok)
self.events.on(SIGNAL_CONTACT_PROFILE_SHOWCASE_UPDATED) do(e: Args):
let args = ProfileShowcaseContactIdArgs(e)
self.delegate.onProfileShowcaseUpdated(args.contactId)
self.events.on(SIGNAL_CONTACT_PROFILE_SHOWCASE_LOADED) do(e: Args):
let args = ProfileShowcaseForContactArgs(e)
self.delegate.loadProfileShowcase(args.profileShowcase, args.validated)
self.events.on(SIGNAL_CONTACT_SHOWCASE_ACCOUNTS_BY_ADDRESS_FETCHED) do(e: Args):
let args = ProfileShowcaseForContactArgs(e)
self.delegate.onProfileShowcaseAccountsByAddressFetched(args.profileShowcase.accounts)
proc getContacts*(self: Controller, group: ContactsGroup): seq[ContactsDto] =
return self.contactsService.getContactsByGroup(group)
@ -180,3 +197,12 @@ proc shareUserUrlWithChatKey*(self: Controller, pubkey: string): string =
proc shareUserUrlWithENS*(self: Controller, pubkey: string): string =
self.contactsService.shareUserUrlWithENS(pubkey)
proc requestProfileShowcaseForContact*(self: Controller, contactId: string, validated: bool) =
self.contactsService.requestProfileShowcaseForContact(contactId, validated)
proc fetchProfileShowcaseAccountsByAddress*(self: Controller, address: string) =
self.contactsService.fetchProfileShowcaseAccountsByAddress(address)
proc getChainIds*(self: Controller): seq[int] =
self.networkService.getCurrentNetworks().map(n => n.chainId)

View File

@ -2,6 +2,8 @@ import NimQml
import ../../../../../app_service/service/contacts/dto/contacts as contacts
import ../../../../../app_service/service/contacts/dto/status_update
import app_service/service/contacts/dto/profile_showcase
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
@ -139,3 +141,24 @@ method shareUserUrlWithChatKey*(self: AccessInterface, pubkey: string): string {
method shareUserUrlWithENS*(self: AccessInterface, pubkey: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method requestProfileShowcase*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onProfileShowcaseUpdated*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method loadProfileShowcase*(self: AccessInterface, profileShowcase: ProfileShowcaseDto, validated: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method fetchProfileShowcaseAccountsByAddress*(self: AccessInterface, address: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onProfileShowcaseAccountsByAddressFetched*(self: AccessInterface, accounts: seq[ProfileShowcaseAccount]) {.base.} =
raise newException(ValueError, "No implementation available")
method getShowcaseCollectiblesModel*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")
method isShowcaseForAContactLoading*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -0,0 +1,78 @@
import NimQml, tables, strutils, sequtils, json
type
ShowcaseContactAccountItem* = object of RootObj
address*: string
name*: string
emoji*: string
colorId*: string
showcasePosition*: int
type
ModelRole {.pure.} = enum
Address
Name
Emoji
ColorId
ShowcasePosition
QtObject:
type
ShowcaseContactAccountModel* = ref object of QAbstractListModel
items: seq[ShowcaseContactAccountItem]
proc delete(self: ShowcaseContactAccountModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: ShowcaseContactAccountModel) =
self.QAbstractListModel.setup
proc newShowcaseContactAccountModel*(): ShowcaseContactAccountModel =
new(result, delete)
result.setup
proc items*(self: ShowcaseContactAccountModel): seq[ShowcaseContactAccountItem] =
self.items
method rowCount(self: ShowcaseContactAccountModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: ShowcaseContactAccountModel): Table[int, string] =
{
ModelRole.Address.int: "address",
ModelRole.Name.int: "name",
ModelRole.Emoji.int: "emoji",
ModelRole.ColorId.int: "colorId",
ModelRole.ShowcasePosition.int: "showcasePosition",
}.toTable
method data(self: ShowcaseContactAccountModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Address:
result = newQVariant(item.address)
of ModelRole.Name:
result = newQVariant(item.name)
of ModelRole.Emoji:
result = newQVariant(item.emoji)
of ModelRole.ColorId:
result = newQVariant(item.colorId)
of ModelRole.ShowcasePosition:
result = newQVariant(item.showcasePosition)
proc setItems*(self: ShowcaseContactAccountModel, items: seq[ShowcaseContactAccountItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
proc clear*(self: ShowcaseContactAccountModel) {.slot.} =
self.setItems(@[])

View File

@ -0,0 +1,63 @@
import NimQml, tables, strutils, sequtils, json
type
ShowcaseContactGenericItem* = object of RootObj
showcaseKey*: string
showcasePosition*: int
type
ModelRole {.pure.} = enum
ShowcaseKey
ShowcasePosition
QtObject:
type
ShowcaseContactGenericModel* = ref object of QAbstractListModel
items: seq[ShowcaseContactGenericItem]
proc delete(self: ShowcaseContactGenericModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: ShowcaseContactGenericModel) =
self.QAbstractListModel.setup
proc newShowcaseContactGenericModel*(): ShowcaseContactGenericModel =
new(result, delete)
result.setup
proc items*(self: ShowcaseContactGenericModel): seq[ShowcaseContactGenericItem] =
self.items
method rowCount(self: ShowcaseContactGenericModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: ShowcaseContactGenericModel): Table[int, string] =
{
ModelRole.ShowcaseKey.int: "showcaseKey",
ModelRole.ShowcasePosition.int: "showcasePosition",
}.toTable
method data(self: ShowcaseContactGenericModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.ShowcaseKey:
result = newQVariant(item.showcaseKey)
of ModelRole.ShowcasePosition:
result = newQVariant(item.showcasePosition)
proc setItems*(self: ShowcaseContactGenericModel, items: seq[ShowcaseContactGenericItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
proc clear*(self: ShowcaseContactGenericModel) {.slot.} =
self.setItems(@[])

View File

@ -0,0 +1,68 @@
import NimQml, tables, strutils, sequtils, json
type
ShowcaseContactSocialLinkItem* = object of RootObj
url*: string
text*: string
showcasePosition*: int
type
ModelRole {.pure.} = enum
Url
Text
ShowcasePosition
QtObject:
type
ShowcaseContactSocialLinkModel* = ref object of QAbstractListModel
items: seq[ShowcaseContactSocialLinkItem]
proc delete(self: ShowcaseContactSocialLinkModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: ShowcaseContactSocialLinkModel) =
self.QAbstractListModel.setup
proc newShowcaseContactSocialLinkModel*(): ShowcaseContactSocialLinkModel =
new(result, delete)
result.setup
proc items*(self: ShowcaseContactSocialLinkModel): seq[ShowcaseContactSocialLinkItem] =
self.items
method rowCount(self: ShowcaseContactSocialLinkModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: ShowcaseContactSocialLinkModel): Table[int, string] =
{
ModelRole.Url.int: "url",
ModelRole.Text.int: "text",
ModelRole.ShowcasePosition.int: "showcasePosition",
}.toTable
method data(self: ShowcaseContactSocialLinkModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Url:
result = newQVariant(item.url)
of ModelRole.Text:
result = newQVariant(item.text)
of ModelRole.ShowcasePosition:
result = newQVariant(item.showcasePosition)
proc setItems*(self: ShowcaseContactSocialLinkModel, items: seq[ShowcaseContactSocialLinkItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
proc clear*(self: ShowcaseContactSocialLinkModel) {.slot.} =
self.setItems(@[])

View File

@ -7,38 +7,66 @@ import ../io_interface as delegate_interface
import ../../../../global/global_singleton
import ../../../../core/eventemitter
import ../../../../../app_service/common/types
import ../../../../../app_service/service/contacts/dto/contacts as contacts_dto
import ../../../../../app_service/service/contacts/service as contacts_service
import ../../../../../app_service/service/chat/service as chat_service
import app_service/common/types
import app_service/service/contacts/dto/contacts as contacts_dto
import app_service/service/contacts/service as contacts_service
import app_service/service/chat/service as chat_service
import app_service/service/network/service as network_service
import app/modules/shared_modules/collectibles/controller as collectiblesc
import backend/collectibles as backend_collectibles
import app_service/service/contacts/dto/profile_showcase
import models/showcase_contact_generic_model
import models/showcase_contact_accounts_model
import models/showcase_contact_social_links_model
export io_interface
const COLLECTIBLES_CACHE_AGE_SECONDS = 60
logScope:
topics = "profile-section-contacts-module"
type
Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface
controller: Controller
controller: controller.Controller
collectiblesController: collectiblesc.Controller
view: View
viewVariant: QVariant
moduleLoaded: bool
showcasePublicKey: string
showcaseForAContactLoading: bool
proc newModule*(delegate: delegate_interface.AccessInterface,
events: EventEmitter,
contactsService: contacts_service.Service,
chatService: chat_service.Service):
chatService: chat_service.Service,
networkService: network_service.Service):
Module =
result = Module()
result.delegate = delegate
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, contactsService, chatService)
result.controller = controller.newController(result, events, contactsService, chatService, networkService)
result.collectiblesController = collectiblesc.newController(
requestId = int32(backend_collectibles.CollectiblesRequestID.ProfileShowcase),
loadType = collectiblesc.LoadType.AutoLoadSingleUpdate,
networkService = networkService,
events = events,
fetchCriteria = backend_collectibles.FetchCriteria(
fetchType: backend_collectibles.FetchType.FetchIfCacheOld,
maxCacheAgeSeconds: COLLECTIBLES_CACHE_AGE_SECONDS
)
)
result.moduleLoaded = false
result.showcaseForAContactLoading = false
method delete*(self: Module) =
self.view.delete
self.viewVariant.delete
self.collectiblesController.delete
proc createItemFromPublicKey(self: Module, publicKey: string): UserItem =
let contactDetails = self.controller.getContactDetails(publicKey)
@ -303,3 +331,98 @@ method shareUserUrlWithChatKey*(self: Module, pubkey: string): string =
method shareUserUrlWithENS*(self: Module, pubkey: string): string =
return self.controller.shareUserUrlWithENS(pubkey)
# Profile showcase for a contanct related stuff
method requestProfileShowcase*(self: Module, publicKey: string) =
if self.showcasePublicKey != publicKey:
self.view.clearShowcaseModels()
self.showcasePublicKey = publicKey
self.showcaseForAContactLoading = true
self.view.emitShowcaseForAContactLoadingChangedSignal()
self.controller.requestProfileShowcaseForContact(publicKey, false)
method onProfileShowcaseUpdated(self: Module, publicKey: string) =
if self.showcasePublicKey == publicKey:
self.controller.requestProfileShowcaseForContact(publicKey, true)
method loadProfileShowcase(self: Module, profileShowcase: ProfileShowcaseDto, validated: bool) =
if self.showcasePublicKey != profileShowcase.contactId:
warn "Got profile showcase for wrong contact id"
return
var communityItems: seq[ShowcaseContactGenericItem] = @[]
for community in profileShowcase.communities:
if not validated or community.membershipStatus == ProfileShowcaseMembershipStatus.ProvenMember:
communityItems.add(ShowcaseContactGenericItem(
showcaseKey: community.communityId,
showcasePosition: community.order
))
self.view.loadProfileShowcaseContactCommunities(communityItems)
var accountItems: seq[ShowcaseContactAccountItem] = @[]
var accountAddresses: seq[string] = @[]
for account in profileShowcase.accounts:
accountItems.add(ShowcaseContactAccountItem(
address: account.address,
name: account.name,
emoji: account.emoji,
colorId: account.colorId,
showcasePosition: account.order
))
accountAddresses.add(account.address)
self.view.loadProfileShowcaseContactAccounts(accountItems)
var collectibleItems: seq[ShowcaseContactGenericItem] = @[]
var collectibleChainIds: seq[int] = @[]
for collectible in profileShowcase.collectibles:
collectibleItems.add(ShowcaseContactGenericItem(
showcaseKey: collectible.toCombinedCollectibleId(),
showcasePosition: collectible.order
))
collectibleChainIds.add(collectible.chainId)
self.view.loadProfileShowcaseContactCollectibles(collectibleItems)
var assetItems: seq[ShowcaseContactGenericItem] = @[]
for token in profileShowcase.verifiedTokens:
assetItems.add(ShowcaseContactGenericItem(
showcaseKey: token.symbol,
showcasePosition: token.order
))
for token in profileShowcase.unverifiedTokens:
assetItems.add(ShowcaseContactGenericItem(
showcaseKey: token.toCombinedTokenId(),
showcasePosition: token.order
))
self.view.loadProfileShowcaseContactAssets(assetItems)
var socialLinkItems: seq[ShowcaseContactSocialLinkItem] = @[]
for socialLink in profileShowcase.socialLinks:
socialLinkItems.add(ShowcaseContactSocialLinkItem(
url: socialLink.url,
text: socialLink.text,
showcasePosition: socialLink.order
))
self.view.loadProfileShowcaseContactSocialLinks(socialLinkItems)
if validated:
self.showcaseForAContactLoading = false
self.view.emitShowcaseForAContactLoadingChangedSignal()
else:
# NOTE: this implementation does not respect testnet setting
# to fix use SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED and getChainIds() to intersect with collectibleChainIds
self.collectiblesController.setFilterAddressesAndChains(accountAddresses, collectibleChainIds)
self.controller.requestProfileShowcaseForContact(self.showcasePublicKey, true)
method fetchProfileShowcaseAccountsByAddress*(self: Module, address: string) =
self.controller.fetchProfileShowcaseAccountsByAddress(address)
method onProfileShowcaseAccountsByAddressFetched*(self: Module, accounts: seq[ProfileShowcaseAccount]) =
let jsonObj = % accounts
self.view.emitProfileShowcaseAccountsByAddressFetchedSignal($jsonObj)
method getShowcaseCollectiblesModel*(self: Module): QVariant =
return self.collectiblesController.getModelAsVariant()
method isShowcaseForAContactLoading*(self: Module): bool =
return self.showcaseForAContactLoading

View File

@ -3,6 +3,10 @@ import NimQml
import ../../../shared_models/user_model
import ./io_interface
import models/showcase_contact_generic_model
import models/showcase_contact_accounts_model
import models/showcase_contact_social_links_model
QtObject:
type
View* = ref object of QObject
@ -20,6 +24,17 @@ QtObject:
# receivedButRejectedContactRequestsModelVariant: QVariant
# sentButRejectedContactRequestsModel: Model
# sentButRejectedContactRequestsModelVariant: QVariant
showcaseContactCommunitiesModel: ShowcaseContactGenericModel
showcaseContactCommunitiesModelVariant: QVariant
showcaseContactAccountsModel: ShowcaseContactAccountModel
showcaseContactAccountsModelVariant: QVariant
showcaseContactCollectiblesModel: ShowcaseContactGenericModel
showcaseContactCollectiblesModelVariant: QVariant
showcaseContactAssetsModel: ShowcaseContactGenericModel
showcaseContactAssetsModelVariant: QVariant
showcaseContactSocialLinksModel: ShowcaseContactSocialLinkModel
showcaseContactSocialLinksModelVariant: QVariant
proc delete*(self: View) =
self.myMutualContactsModel.delete
@ -35,6 +50,16 @@ QtObject:
# self.receivedButRejectedContactRequestsModelVariant.delete
# self.sentButRejectedContactRequestsModelVariant.delete
# self.sentButRejectedContactRequestsModel.delete
self.showcaseContactCommunitiesModel.delete
self.showcaseContactCommunitiesModelVariant.delete
self.showcaseContactAccountsModel.delete
self.showcaseContactAccountsModelVariant.delete
self.showcaseContactCollectiblesModel.delete
self.showcaseContactCollectiblesModelVariant.delete
self.showcaseContactAssetsModel.delete
self.showcaseContactAssetsModelVariant.delete
self.showcaseContactSocialLinksModel.delete
self.showcaseContactSocialLinksModelVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
@ -54,6 +79,16 @@ QtObject:
# result.receivedButRejectedContactRequestsModelVariant = newQVariant(result.receivedButRejectedContactRequestsModel)
# result.sentButRejectedContactRequestsModel = newModel()
# result.sentButRejectedContactRequestsModelVariant = newQVariant(result.sentButRejectedContactRequestsModel)
result.showcaseContactCommunitiesModel = newShowcaseContactGenericModel()
result.showcaseContactCommunitiesModelVariant = newQVariant(result.showcaseContactCommunitiesModel)
result.showcaseContactAccountsModel = newShowcaseContactAccountModel()
result.showcaseContactAccountsModelVariant = newQVariant(result.showcaseContactAccountsModel)
result.showcaseContactCollectiblesModel = newShowcaseContactGenericModel()
result.showcaseContactCollectiblesModelVariant = newQVariant(result.showcaseContactCollectiblesModel)
result.showcaseContactAssetsModel = newShowcaseContactGenericModel()
result.showcaseContactAssetsModelVariant = newQVariant(result.showcaseContactAssetsModel)
result.showcaseContactSocialLinksModel = newShowcaseContactSocialLinkModel()
result.showcaseContactSocialLinksModelVariant = newQVariant(result.showcaseContactSocialLinksModel)
proc load*(self: View) =
self.delegate.viewDidLoad()
@ -205,3 +240,78 @@ QtObject:
proc onContactInfoRequestFinished*(self: View, publicKey: string, ok: bool) {.slot.} =
self.contactInfoRequestFinished(publicKey, ok)
# Showcase models for a contact
proc getShowcaseContactCommunitiesModel(self: View): QVariant {.slot.} =
return self.showcaseContactCommunitiesModelVariant
QtProperty[QVariant] showcaseContactCommunitiesModel:
read = getShowcaseContactCommunitiesModel
proc getShowcaseContactAccountsModel(self: View): QVariant {.slot.} =
return self.showcaseContactAccountsModelVariant
QtProperty[QVariant] showcaseContactAccountsModel:
read = getShowcaseContactAccountsModel
proc getShowcaseContactCollectiblesModel(self: View): QVariant {.slot.} =
return self.showcaseContactCollectiblesModelVariant
QtProperty[QVariant] showcaseContactCollectiblesModel:
read = getShowcaseContactCollectiblesModel
proc getShowcaseContactAssetsModel(self: View): QVariant {.slot.} =
return self.showcaseContactAssetsModelVariant
QtProperty[QVariant] showcaseContactAssetsModel:
read = getShowcaseContactAssetsModel
proc getShowcaseContactSocialLinksModel(self: View): QVariant {.slot.} =
return self.showcaseContactSocialLinksModelVariant
QtProperty[QVariant] showcaseContactSocialLinksModel:
read = getShowcaseContactSocialLinksModel
# Support models for showcase for a contact
proc showcaseCollectiblesModelChanged*(self: View) {.signal.}
proc getShowcaseCollectiblesModel(self: View): QVariant {.slot.} =
return self.delegate.getShowcaseCollectiblesModel()
QtProperty[QVariant] showcaseCollectiblesModel:
read = getShowcaseCollectiblesModel
notify = showcaseCollectiblesModelChanged
proc showcaseForAContactLoadingChanged*(self: View) {.signal.}
proc emitShowcaseForAContactLoadingChangedSignal*(self: View) =
self.showcaseForAContactLoadingChanged()
proc isShowcaseForAContactLoading*(self: View): bool {.signal.} =
return self.delegate.isShowcaseForAContactLoading()
QtProperty[QVariant] showcaseForAContactLoading:
read = isShowcaseForAContactLoading
notify = showcaseForAContactLoadingChanged
proc fetchProfileShowcaseAccountsByAddress*(self: View, address: string) {.slot.} =
self.delegate.fetchProfileShowcaseAccountsByAddress(address)
proc profileShowcaseAccountsByAddressFetched*(self: View, accounts: string) {.signal.}
proc emitProfileShowcaseAccountsByAddressFetchedSignal*(self: View, accounts: string) =
self.profileShowcaseAccountsByAddressFetched(accounts)
proc requestProfileShowcase(self: View, publicKey: string) {.slot.} =
self.delegate.requestProfileShowcase(publicKey)
proc clearShowcaseModels*(self: View) {.slot.} =
self.showcaseContactCommunitiesModel.clear()
self.showcaseContactAccountsModel.clear()
self.showcaseContactCollectiblesModel.clear()
self.showcaseContactAssetsModel.clear()
self.showcaseContactSocialLinksModel.clear()
proc loadProfileShowcaseContactCommunities*(self: View, items: seq[ShowcaseContactGenericItem]) =
self.showcaseContactCommunitiesModel.setItems(items)
proc loadProfileShowcaseContactAccounts*(self: View, items: seq[ShowcaseContactAccountItem]) =
self.showcaseContactAccountsModel.setItems(items)
proc loadProfileShowcaseContactCollectibles*(self: View, items: seq[ShowcaseContactGenericItem]) =
self.showcaseContactCollectiblesModel.setItems(items)
proc loadProfileShowcaseContactAssets*(self: View, items: seq[ShowcaseContactGenericItem]) =
self.showcaseContactAssetsModel.setItems(items)
proc loadProfileShowcaseContactSocialLinks*(self: View, items: seq[ShowcaseContactSocialLinkItem]) =
self.showcaseContactSocialLinksModel.setItems(items)

View File

@ -96,8 +96,8 @@ 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, networkService, tokenService)
result.contactsModule = contacts_module.newModule(result, events, contactsService, chatService)
result.profileModule = profile_module.newModule(result, events, profileService, settingsService, communityService, walletAccountService, tokenService)
result.contactsModule = contacts_module.newModule(result, events, contactsService, chatService, networkService)
result.languageModule = language_module.newModule(result, events, languageService)
result.privacyModule = privacy_module.newModule(result, events, settingsService, keychainService, privacyService, generalService)
result.aboutModule = about_module.newModule(result, events, aboutService)

View File

@ -1,4 +1,3 @@
import sugar, sequtils
import io_interface
import app/global/app_signals
@ -7,7 +6,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/network/service as network_service
import app_service/service/token/service as token_service
import app_service/common/social_links
import app_service/common/types
@ -22,7 +20,6 @@ type
settingsService: settings_service.Service
communityService: community_service.Service
walletAccountService: wallet_account_service.Service
networkService: network_service.Service
tokenService: token_service.Service
proc newController*(
@ -32,7 +29,6 @@ proc newController*(
settingsService: settings_service.Service,
communityService: community_service.Service,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service): Controller =
result = Controller()
result.delegate = delegate
@ -41,7 +37,6 @@ proc newController*(
result.settingsService = settingsService
result.communityService = communityService
result.walletAccountService = walletAccountService
result.networkService = networkService
result.tokenService = tokenService
proc delete*(self: Controller) =
@ -64,21 +59,9 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_PROFILE_SHOWCASE_PREFERENCES_SAVE_FAILED) do(e: Args):
self.delegate.onProfileShowcasePreferencesSaveFailed()
self.events.on(SIGNAL_PROFILE_SHOWCASE_PREFERENCES_UPDATED) do(e: Args):
self.events.on(SIGNAL_PROFILE_SHOWCASE_PREFERENCES_LOADED) do(e: Args):
let args = ProfileShowcasePreferencesArgs(e)
self.delegate.updateProfileShowcasePreferences(args.preferences)
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_PROFILE_SHOWCASE_ACCOUNTS_BY_ADDRESS_FETCHED) do(e: Args):
let args = ProfileShowcaseForContactArgs(e)
self.delegate.onProfileShowcaseAccountsByAddressFetched(args.profileShowcase.accounts)
self.events.on(SIGNAL_COMMUNITIES_UPDATE) do(e: Args):
let args = CommunitiesArgs(e)
self.delegate.onCommunitiesUpdated(args.communities)
self.delegate.loadProfileShowcasePreferences(args.preferences)
proc storeIdentityImage*(self: Controller, address: string, image: string, aX: int, aY: int, bX: int, bY: int): bool =
len(self.profileService.storeIdentityImage(address, image, aX, aY, bX, bY)) > 0
@ -101,9 +84,6 @@ proc getAccountByAddress*(self: Controller, address: string): WalletAccountDto =
proc getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAccountDto] =
self.walletAccountService.getWalletAccounts(true)
proc getChainIds*(self: Controller): seq[int] =
self.networkService.getCurrentNetworks().map(n => n.chainId)
proc setSocialLinks*(self: Controller, links: SocialLinks) =
self.settingsService.setSocialLinks(links)
@ -113,19 +93,13 @@ proc getBio*(self: Controller): string =
proc setBio*(self: Controller, bio: string): bool =
self.settingsService.saveBio(bio)
proc storeProfileShowcasePreferences*(self: Controller, preferences: ProfileShowcasePreferencesDto, revealedAddresses: seq[string]) =
proc saveProfileShowcasePreferences*(self: Controller, preferences: ProfileShowcasePreferencesDto, revealedAddresses: seq[string]) =
self.profileService.saveProfileShowcasePreferences(preferences)
self.events.emit(MARK_WALLET_ADDRESSES_AS_SHOWN, WalletAddressesArgs(addresses: revealedAddresses))
proc requestProfileShowcasePreferences*(self: Controller) =
self.profileService.requestProfileShowcasePreferences()
proc requestProfileShowcaseForContact*(self: Controller, contactId: string) =
self.profileService.requestProfileShowcaseForContact(contactId)
proc fetchProfileShowcaseAccountsByAddress*(self: Controller, address: string) =
self.profileService.fetchProfileShowcaseAccountsByAddress(address)
proc getProfileShowcaseSocialLinksLimit*(self: Controller): int =
self.profileService.getProfileShowcaseSocialLinksLimit()

View File

@ -1,14 +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
import models/profile_preferences_community_item
import models/profile_preferences_account_item
import models/profile_preferences_collectible_item
import models/profile_preferences_asset_item
import models/profile_save_data
@ -28,9 +21,6 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")
method getCollectiblesModel*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")
method getBio*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
@ -67,38 +57,13 @@ method getProfileShowcaseSocialLinksLimit*(self: AccessInterface): int {.base.}
method getProfileShowcaseEntriesLimit*(self: AccessInterface): int {.base.} =
raise newException(ValueError, "No implementation available")
method storeProfileShowcasePreferences*(self: AccessInterface,
communities: seq[ProfileShowcaseCommunityItem],
accounts: seq[ProfileShowcaseAccountItem],
collectibles: seq[ProfileShowcaseCollectibleItem],
assets: seq[ProfileShowcaseAssetItem]) {.base.} =
raise newException(ValueError, "No implementation available")
method requestProfileShowcasePreferences*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method setIsFirstShowcaseInteraction*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method requestProfileShowcase*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method fetchProfileShowcaseAccountsByAddress*(self: AccessInterface, address: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onProfileShowcaseAccountsByAddressFetched*(self: AccessInterface, accounts: seq[ProfileShowcaseAccount]) {.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")
method onContactDetailsUpdated*(self: AccessInterface, contactId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onCommunitiesUpdated*(self: AccessInterface, communities: seq[CommunityDto]) {.base.} =
method loadProfileShowcasePreferences*(self: AccessInterface, preferences: ProfileShowcasePreferencesDto) {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface

View File

@ -1,68 +0,0 @@
import json, strutils, stint, json_serialization, tables
import profile_preferences_base_item
import app_service/service/profile/dto/profile_showcase_preferences
include app_service/common/json_utils
include app_service/common/utils
type
ProfileShowcaseAccountItem* = ref object of ProfileShowcaseBaseItem
address*: string
name*: string
emoji*: string
colorId*: string
proc initProfileShowcaseAccountItem*(
address: string,
name: string,
emoji: string,
colorId: string,
visibility: ProfileShowcaseVisibility,
order: int): ProfileShowcaseAccountItem =
result = ProfileShowcaseAccountItem()
result.address = address
result.name = name
result.emoji = emoji
result.colorId = colorId
result.showcaseVisibility = visibility
result.order = order
proc toProfileShowcaseAccountItem*(jsonObj: JsonNode): ProfileShowcaseAccountItem =
result = ProfileShowcaseAccountItem()
discard jsonObj.getProp("address", result.address)
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("emoji", result.emoji)
discard jsonObj.getProp("colorId", result.colorId)
discard jsonObj.getProp("order", result.order)
var visibilityInt: int
if (jsonObj.getProp("showcaseVisibility", visibilityInt) and
(visibilityInt >= ord(low(ProfileShowcaseVisibility)) and
visibilityInt <= ord(high(ProfileShowcaseVisibility)))):
result.showcaseVisibility = ProfileShowcaseVisibility(visibilityInt)
proc toShowcasePreferenceItem*(self: ProfileShowcaseAccountItem): ProfileShowcaseAccountPreference =
result = ProfileShowcaseAccountPreference()
result.address = self.address
result.showcaseVisibility = self.showcaseVisibility
result.order = self.order
proc name*(self: ProfileShowcaseAccountItem): string {.inline.} =
self.name
proc address*(self: ProfileShowcaseAccountItem): string {.inline.} =
self.address
proc walletType*(self: ProfileShowcaseAccountItem): string {.inline.} =
self.walletType
proc emoji*(self: ProfileShowcaseAccountItem): string {.inline.} =
self.emoji
proc colorId*(self: ProfileShowcaseAccountItem): string {.inline.} =
self.colorId

View File

@ -1,209 +0,0 @@
import NimQml, tables, strutils, sequtils, json
import profile_preferences_account_item
import app_service/service/profile/dto/profile_showcase_preferences
type
ModelRole {.pure.} = enum
ShowcaseVisibility = UserRole + 1
Order
Address
Name
Emoji
ColorId
QtObject:
type
ProfileShowcaseAccountsModel* = ref object of QAbstractListModel
items: seq[ProfileShowcaseAccountItem]
proc delete(self: ProfileShowcaseAccountsModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: ProfileShowcaseAccountsModel) =
self.QAbstractListModel.setup
proc newProfileShowcaseAccountsModel*(): ProfileShowcaseAccountsModel =
new(result, delete)
result.setup
proc countChanged(self: ProfileShowcaseAccountsModel) {.signal.}
proc getCount(self: ProfileShowcaseAccountsModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
proc hiddenCountChanged(self: ProfileShowcaseAccountsModel) {.signal.}
proc getHiddenCount(self: ProfileShowcaseAccountsModel): int {.slot.} =
result = 0
for i, item in self.items:
if item.showcaseVisibility == ProfileShowcaseVisibility.ToNoOne:
result += 1
QtProperty[int] hiddenCount:
read = getHiddenCount
notify = hiddenCountChanged
proc recalcOrder(self: ProfileShowcaseAccountsModel) =
for order, item in self.items:
item.order = order
proc items*(self: ProfileShowcaseAccountsModel): seq[ProfileShowcaseAccountItem] =
self.items
method rowCount(self: ProfileShowcaseAccountsModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: ProfileShowcaseAccountsModel): Table[int, string] =
{
ModelRole.ShowcaseVisibility.int: "showcaseVisibility",
ModelRole.Order.int: "order",
ModelRole.Address.int: "address",
ModelRole.Name.int: "name",
ModelRole.Emoji.int: "emoji",
ModelRole.ColorId.int: "colorId",
}.toTable
method data(self: ProfileShowcaseAccountsModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.ShowcaseVisibility:
result = newQVariant(item.showcaseVisibility.int)
of ModelRole.Order:
result = newQVariant(item.order)
of ModelRole.Address:
result = newQVariant(item.address)
of ModelRole.Name:
result = newQVariant(item.name)
of ModelRole.Emoji:
result = newQVariant(item.emoji)
of ModelRole.ColorId:
result = newQVariant(item.colorId)
proc findIndexForAccount(self: ProfileShowcaseAccountsModel, address: string): int =
for index in 0 ..< self.items.len:
if (self.items[index].address == address):
return index
return -1
proc hasItemInShowcase*(self: ProfileShowcaseAccountsModel, address: string): bool {.slot.} =
let ind = self.findIndexForAccount(address)
if ind == -1:
return false
return self.items[ind].showcaseVisibility != ProfileShowcaseVisibility.ToNoOne
proc baseModelFilterConditionsMayHaveChanged*(self: ProfileShowcaseAccountsModel) {.signal.}
proc appendItem*(self: ProfileShowcaseAccountsModel, item: ProfileShowcaseAccountItem) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItemImpl(self: ProfileShowcaseAccountsModel, item: ProfileShowcaseAccountItem) =
let ind = self.findIndexForAccount(item.address)
if ind == -1:
self.appendItem(item)
else:
self.items[ind] = item
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index)
self.hiddenCountChanged()
proc upsertItemJson(self: ProfileShowcaseAccountsModel, itemJson: string) {.slot.} =
self.upsertItemImpl(itemJson.parseJson.toProfileShowcaseAccountItem())
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItem*(self: ProfileShowcaseAccountsModel, item: ProfileShowcaseAccountItem) =
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItems*(self: ProfileShowcaseAccountsModel, items: seq[ProfileShowcaseAccountItem]) =
for item in items:
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc reset*(self: ProfileShowcaseAccountsModel, items: seq[ProfileShowcaseAccountItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc clear*(self: ProfileShowcaseAccountsModel) {.slot.} =
self.reset(@[])
proc remove*(self: ProfileShowcaseAccountsModel, index: int) {.slot.} =
if index < 0 or index >= self.items.len:
return
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginRemoveRows(parentModelIndex, index, index)
self.items.delete(index)
self.endRemoveRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc removeEntry*(self: ProfileShowcaseAccountsModel, address: string) {.slot.} =
let ind = self.findIndexForAccount(address)
if ind != -1:
self.remove(ind)
proc move*(self: ProfileShowcaseAccountsModel, fromRow: int, toRow: int, dummyCount: int = 1) {.slot.} =
if fromRow < 0 or fromRow >= self.items.len:
return
let sourceIndex = newQModelIndex()
defer: sourceIndex.delete
let destIndex = newQModelIndex()
defer: destIndex.delete
var destRow = toRow
if toRow > fromRow:
inc(destRow)
self.beginMoveRows(sourceIndex, fromRow, fromRow, destIndex, destRow)
let item = self.items[fromRow]
self.items.delete(fromRow)
self.items.insert(@[item], toRow)
self.recalcOrder()
self.endMoveRows()
proc setVisibilityByIndex*(self: ProfileShowcaseAccountsModel, ind: int, visibility: int) {.slot.} =
if (visibility >= ord(low(ProfileShowcaseVisibility)) and
visibility <= ord(high(ProfileShowcaseVisibility)) and
ind >= 0 and ind < self.items.len):
self.items[ind].showcaseVisibility = ProfileShowcaseVisibility(visibility)
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.ShowcaseVisibility.int])
self.baseModelFilterConditionsMayHaveChanged()
self.hiddenCountChanged()
proc setVisibility*(self: ProfileShowcaseAccountsModel, address: string, visibility: int) {.slot.} =
let index = self.findIndexForAccount(address)
if index != -1:
self.setVisibilityByIndex(index, visibility)

View File

@ -1,68 +0,0 @@
import json, strutils, stint, json_serialization, tables
import profile_preferences_base_item
import app_service/service/profile/dto/profile_showcase_preferences
import app_service/service/token/service_items
import app/modules/shared_models/currency_amount
include app_service/common/json_utils
include app_service/common/utils
type
ProfileShowcaseAssetItem* = ref object of ProfileShowcaseBaseItem
contractAddress*: string
communityId*: string
chainId*: int
symbol*: string
name*: string
enabledNetworkBalance*: CurrencyAmount
decimals*: int
proc initProfileShowcaseVerifiedToken*(token: TokenBySymbolItem, visibility: ProfileShowcaseVisibility, order: int): ProfileShowcaseAssetItem =
result = ProfileShowcaseAssetItem()
result.showcaseVisibility = visibility
result.order = order
result.symbol = token.symbol
result.name = token.name
result.enabledNetworkBalance = newCurrencyAmount()
result.decimals = token.decimals
# TODO: initProfileShowcaseUnverifiedToken
proc toProfileShowcaseAssetItem*(jsonObj: JsonNode): ProfileShowcaseAssetItem =
result = ProfileShowcaseAssetItem()
discard jsonObj.getProp("order", result.order)
var visibilityInt: int
if (jsonObj.getProp("showcaseVisibility", visibilityInt) and
(visibilityInt >= ord(low(ProfileShowcaseVisibility)) and
visibilityInt <= ord(high(ProfileShowcaseVisibility)))):
result.showcaseVisibility = ProfileShowcaseVisibility(visibilityInt)
discard jsonObj.getProp("address", result.contractAddress)
discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("symbol", result.symbol)
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("decimals", result.decimals)
result.enabledNetworkBalance = newCurrencyAmount(jsonObj{"enabledNetworkBalance"}.getFloat, result.symbol, result.decimals, false)
proc toShowcaseVerifiedTokenPreference*(self: ProfileShowcaseAssetItem): ProfileShowcaseVerifiedTokenPreference =
result = ProfileShowcaseVerifiedTokenPreference()
result.symbol = self.symbol
result.showcaseVisibility = self.showcaseVisibility
result.order = self.order
proc toShowcaseUnverifiedTokenPreference*(self: ProfileShowcaseAssetItem): ProfileShowcaseUnverifiedTokenPreference =
result = ProfileShowcaseUnverifiedTokenPreference()
result.contractAddress = self.contractAddress
result.chainId = self.chainId
result.showcaseVisibility = self.showcaseVisibility
result.order = self.order

View File

@ -1,217 +0,0 @@
import NimQml, tables, strutils, sequtils, json
import profile_preferences_asset_item
import app_service/service/profile/dto/profile_showcase_preferences
type
ModelRole {.pure.} = enum
ShowcaseVisibility = UserRole + 1
Order
Address
CommunityId
Symbol
Name
EnabledNetworkBalance
Decimals
QtObject:
type
ProfileShowcaseAssetsModel* = ref object of QAbstractListModel
items: seq[ProfileShowcaseAssetItem]
proc delete(self: ProfileShowcaseAssetsModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: ProfileShowcaseAssetsModel) =
self.QAbstractListModel.setup
proc newProfileShowcaseAssetsModel*(): ProfileShowcaseAssetsModel =
new(result, delete)
result.setup
proc countChanged(self: ProfileShowcaseAssetsModel) {.signal.}
proc getCount(self: ProfileShowcaseAssetsModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
proc hiddenCountChanged(self: ProfileShowcaseAssetsModel) {.signal.}
proc getHiddenCount(self: ProfileShowcaseAssetsModel): int {.slot.} =
result = 0
for i, item in self.items:
if item.showcaseVisibility == ProfileShowcaseVisibility.ToNoOne:
result += 1
QtProperty[int] hiddenCount:
read = getHiddenCount
notify = hiddenCountChanged
proc recalcOrder(self: ProfileShowcaseAssetsModel) =
for order, item in self.items:
item.order = order
proc items*(self: ProfileShowcaseAssetsModel): seq[ProfileShowcaseAssetItem] =
self.items
method rowCount(self: ProfileShowcaseAssetsModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: ProfileShowcaseAssetsModel): Table[int, string] =
{
ModelRole.ShowcaseVisibility.int: "showcaseVisibility",
ModelRole.Order.int: "order",
ModelRole.Address.int: "address",
ModelRole.CommunityId.int: "communityId",
ModelRole.Symbol.int: "symbol",
ModelRole.Name.int: "name",
ModelRole.EnabledNetworkBalance.int: "enabledNetworkBalance",
ModelRole.Decimals.int: "decimals",
}.toTable
method data(self: ProfileShowcaseAssetsModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.ShowcaseVisibility:
result = newQVariant(item.showcaseVisibility.int)
of ModelRole.Order:
result = newQVariant(item.order)
of ModelRole.Address:
result = newQVariant(item.contractAddress)
of ModelRole.CommunityId:
result = newQVariant(item.communityId)
of ModelRole.Symbol:
result = newQVariant(item.symbol)
of ModelRole.Name:
result = newQVariant(item.name)
of ModelRole.EnabledNetworkBalance:
result = newQVariant(item.enabledNetworkBalance)
of ModelRole.Decimals:
result = newQVariant(item.decimals)
proc findIndexForAsset(self: ProfileShowcaseAssetsModel, symbol: string): int =
for i in 0 ..< self.items.len:
if (self.items[i].symbol == symbol):
return i
return -1
proc hasItemInShowcase*(self: ProfileShowcaseAssetsModel, symbol: string): bool {.slot.} =
let ind = self.findIndexForAsset(symbol)
if ind == -1:
return false
return self.items[ind].showcaseVisibility != ProfileShowcaseVisibility.ToNoOne
proc baseModelFilterConditionsMayHaveChanged*(self: ProfileShowcaseAssetsModel) {.signal.}
proc appendItem*(self: ProfileShowcaseAssetsModel, item: ProfileShowcaseAssetItem) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItemImpl(self: ProfileShowcaseAssetsModel, item: ProfileShowcaseAssetItem) =
let ind = self.findIndexForAsset(item.symbol)
if ind == -1:
self.appendItem(item)
else:
self.items[ind] = item
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index)
self.hiddenCountChanged()
proc upsertItemJson(self: ProfileShowcaseAssetsModel, itemJson: string) {.slot.} =
self.upsertItemImpl(itemJson.parseJson.toProfileShowcaseAssetItem())
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItem*(self: ProfileShowcaseAssetsModel, item: ProfileShowcaseAssetItem) =
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItems*(self: ProfileShowcaseAssetsModel, items: seq[ProfileShowcaseAssetItem]) =
for item in items:
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc reset*(self: ProfileShowcaseAssetsModel, items: seq[ProfileShowcaseAssetItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc clear*(self: ProfileShowcaseAssetsModel) {.slot.} =
self.reset(@[])
proc remove*(self: ProfileShowcaseAssetsModel, index: int) {.slot.} =
if index < 0 or index >= self.items.len:
return
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginRemoveRows(parentModelIndex, index, index)
self.items.delete(index)
self.endRemoveRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc removeEntry*(self: ProfileShowcaseAssetsModel, symbol: string) {.slot.} =
let ind = self.findIndexForAsset(symbol)
if ind != -1:
self.remove(ind)
proc move*(self: ProfileShowcaseAssetsModel, fromRow: int, toRow: int, dummyCount: int = 1) {.slot.} =
if fromRow < 0 or fromRow >= self.items.len:
return
let sourceIndex = newQModelIndex()
defer: sourceIndex.delete
let destIndex = newQModelIndex()
defer: destIndex.delete
var destRow = toRow
if toRow > fromRow:
inc(destRow)
self.beginMoveRows(sourceIndex, fromRow, fromRow, destIndex, destRow)
let item = self.items[fromRow]
self.items.delete(fromRow)
self.items.insert(@[item], toRow)
self.recalcOrder()
self.endMoveRows()
proc setVisibilityByIndex*(self: ProfileShowcaseAssetsModel, ind: int, visibility: int) {.slot.} =
if (visibility >= ord(low(ProfileShowcaseVisibility)) and
visibility <= ord(high(ProfileShowcaseVisibility)) and
ind >= 0 and ind < self.items.len):
self.items[ind].showcaseVisibility = ProfileShowcaseVisibility(visibility)
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.ShowcaseVisibility.int])
self.baseModelFilterConditionsMayHaveChanged()
self.hiddenCountChanged()
proc setVisibility*(self: ProfileShowcaseAssetsModel, symbol: string, visibility: int) {.slot.} =
let index = self.findIndexForAsset(symbol)
if index != -1:
self.setVisibilityByIndex(index, visibility)

View File

@ -1,12 +0,0 @@
import app_service/service/profile/dto/profile_showcase_preferences
type
ProfileShowcaseBaseItem* = object of RootObj
showcaseVisibility*: ProfileShowcaseVisibility
order*: int
proc showcaseVisibility*(self: ProfileShowcaseBaseItem): ProfileShowcaseVisibility {.inline.} =
self.showcaseVisibility
proc order*(self: ProfileShowcaseBaseItem): int {.inline.} =
self.order

View File

@ -1,67 +0,0 @@
import json, strutils, stew/shims/strformat, stint, json_serialization, tables
import profile_preferences_base_item
import app_service/service/profile/dto/profile_showcase_preferences
import app/modules/shared_models/collectibles_entry
include app_service/common/json_utils
include app_service/common/utils
type
ProfileShowcaseCollectibleItem* = ref object of ProfileShowcaseBaseItem
chainId*: int
tokenId*: string
contractAddress*: string
communityId*: string
name*: string
collectionName*: string
imageUrl*: string
backgroundColor*: string
loading*: bool
proc initProfileShowcaseCollectibleItem*(collectible: CollectiblesEntry, visibility: ProfileShowcaseVisibility, order: int): ProfileShowcaseCollectibleItem =
result = ProfileShowcaseCollectibleItem()
result.contractAddress = collectible.getContractAddress()
result.chainId = collectible.getChainID()
result.tokenId = collectible.getTokenIDAsString()
result.communityId = collectible.getCommunityId()
result.name = collectible.getName()
result.collectionName = collectible.getCollectionName()
result.imageUrl = collectible.getImageURL()
result.backgroundColor = collectible.getBackgroundColor()
result.showcaseVisibility = visibility
result.order = order
result.loading = false
proc toProfileShowcaseCollectibleItem*(jsonObj: JsonNode): ProfileShowcaseCollectibleItem =
result = ProfileShowcaseCollectibleItem()
discard jsonObj.getProp("order", result.order)
var visibilityInt: int
if (jsonObj.getProp("showcaseVisibility", visibilityInt) and
(visibilityInt >= ord(low(ProfileShowcaseVisibility)) and
visibilityInt <= ord(high(ProfileShowcaseVisibility)))):
result.showcaseVisibility = ProfileShowcaseVisibility(visibilityInt)
discard jsonObj.getProp("chainId", result.chainId)
discard jsonObj.getProp("tokenId", result.tokenId)
discard jsonObj.getProp("contractAddress", result.contractAddress)
discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("collectionName", result.collectionName)
discard jsonObj.getProp("imageUrl", result.imageUrl)
discard jsonObj.getProp("backgroundColor", result.backgroundColor)
proc toShowcasePreferenceItem*(self: ProfileShowcaseCollectibleItem): ProfileShowcaseCollectiblePreference =
result = ProfileShowcaseCollectiblePreference()
result.chainId = self.chainId
result.tokenId = self.tokenId
result.contractAddress = self.contractAddress
result.showcaseVisibility = self.showcaseVisibility
result.order = self.order
# NOTE: should be same as CollectiblesEntry::getID
proc getID*(self: ProfileShowcaseCollectibleItem): string =
return fmt"{self.chainId}+{self.contractAddress}+{self.tokenId}"

View File

@ -1,234 +0,0 @@
import NimQml, tables, strutils, sequtils, json
import profile_preferences_collectible_item
import app_service/service/profile/dto/profile_showcase_preferences
type
ModelRole {.pure.} = enum
Uid = UserRole + 1,
ChainId
ContractAddress
TokenId
Name
ImageUrl
BackgroundColor
CollectionName
IsLoading
CommunityId
ShowcaseVisibility
Order
QtObject:
type
ProfileShowcaseCollectiblesModel* = ref object of QAbstractListModel
items: seq[ProfileShowcaseCollectibleItem]
proc delete(self: ProfileShowcaseCollectiblesModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: ProfileShowcaseCollectiblesModel) =
self.QAbstractListModel.setup
proc newProfileShowcaseCollectiblesModel*(): ProfileShowcaseCollectiblesModel =
new(result, delete)
result.setup
proc countChanged(self: ProfileShowcaseCollectiblesModel) {.signal.}
proc getCount(self: ProfileShowcaseCollectiblesModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
proc hiddenCountChanged(self: ProfileShowcaseCollectiblesModel) {.signal.}
proc getHiddenCount(self: ProfileShowcaseCollectiblesModel): int {.slot.} =
result = 0
for i, item in self.items:
if item.showcaseVisibility == ProfileShowcaseVisibility.ToNoOne:
result += 1
QtProperty[int] hiddenCount:
read = getHiddenCount
notify = hiddenCountChanged
proc recalcOrder(self: ProfileShowcaseCollectiblesModel) =
for order, item in self.items:
item.order = order
proc items*(self: ProfileShowcaseCollectiblesModel): seq[ProfileShowcaseCollectibleItem] =
self.items
method rowCount(self: ProfileShowcaseCollectiblesModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: ProfileShowcaseCollectiblesModel): Table[int, string] =
{
ModelRole.Uid.int:"uid",
ModelRole.ChainId.int: "chainId",
ModelRole.ContractAddress.int: "contractAddress",
ModelRole.TokenId.int: "tokenId",
ModelRole.Name.int: "name",
ModelRole.ImageUrl.int: "imageUrl",
ModelRole.BackgroundColor.int: "backgroundColor",
ModelRole.CollectionName.int: "collectionName",
ModelRole.IsLoading.int: "isLoading",
ModelRole.CommunityId.int: "communityId",
ModelRole.ShowcaseVisibility.int: "showcaseVisibility",
ModelRole.Order.int: "order",
}.toTable
method data(self: ProfileShowcaseCollectiblesModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Uid:
result = newQVariant(item.getID())
of ModelRole.ChainId:
result = newQVariant(item.chainId)
of ModelRole.ContractAddress:
result = newQVariant(item.contractAddress)
of ModelRole.TokenId:
result = newQVariant(item.tokenId)
of ModelRole.Name:
result = newQVariant(item.name)
of ModelRole.ImageUrl:
result = newQVariant(item.imageUrl)
of ModelRole.BackgroundColor:
result = newQVariant(item.backgroundColor)
of ModelRole.CollectionName:
result = newQVariant(item.collectionName)
of ModelRole.IsLoading:
result = newQVariant(item.loading)
of ModelRole.CommunityId:
result = newQVariant(item.communityId)
of ModelRole.ShowcaseVisibility:
result = newQVariant(item.showcaseVisibility.int)
of ModelRole.Order:
result = newQVariant(item.order)
proc findIndexForCollectible(self: ProfileShowcaseCollectiblesModel, uid: string): int =
for i in 0 ..< self.items.len:
if (self.items[i].getID() == uid):
return i
return -1
proc hasItemInShowcase*(self: ProfileShowcaseCollectiblesModel, uid: string): bool {.slot.} =
let ind = self.findIndexForCollectible(uid)
if ind == -1:
return false
return self.items[ind].showcaseVisibility != ProfileShowcaseVisibility.ToNoOne
proc baseModelFilterConditionsMayHaveChanged*(self: ProfileShowcaseCollectiblesModel) {.signal.}
proc appendItem*(self: ProfileShowcaseCollectiblesModel, item: ProfileShowcaseCollectibleItem) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItemImpl(self: ProfileShowcaseCollectiblesModel, item: ProfileShowcaseCollectibleItem) =
let ind = self.findIndexForCollectible(item.getID())
if ind == -1:
self.appendItem(item)
else:
self.items[ind] = item
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index)
self.hiddenCountChanged()
proc upsertItemJson(self: ProfileShowcaseCollectiblesModel, itemJson: string) {.slot.} =
self.upsertItemImpl(itemJson.parseJson.toProfileShowcaseCollectibleItem())
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItem*(self: ProfileShowcaseCollectiblesModel, item: ProfileShowcaseCollectibleItem) =
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItems*(self: ProfileShowcaseCollectiblesModel, items: seq[ProfileShowcaseCollectibleItem]) =
for item in items:
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc reset*(self: ProfileShowcaseCollectiblesModel, items: seq[ProfileShowcaseCollectibleItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc clear*(self: ProfileShowcaseCollectiblesModel) {.slot.} =
self.reset(@[])
proc remove*(self: ProfileShowcaseCollectiblesModel, index: int) {.slot.} =
if index < 0 or index >= self.items.len:
return
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginRemoveRows(parentModelIndex, index, index)
self.items.delete(index)
self.endRemoveRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc removeEntry*(self: ProfileShowcaseCollectiblesModel, uid: string) {.slot.} =
let ind = self.findIndexForCollectible(uid)
if ind != -1:
self.remove(ind)
proc move*(self: ProfileShowcaseCollectiblesModel, fromRow: int, toRow: int, dummyCount: int = 1) {.slot.} =
if fromRow < 0 or fromRow >= self.items.len:
return
let sourceIndex = newQModelIndex()
defer: sourceIndex.delete
let destIndex = newQModelIndex()
defer: destIndex.delete
var destRow = toRow
if toRow > fromRow:
inc(destRow)
self.beginMoveRows(sourceIndex, fromRow, fromRow, destIndex, destRow)
let item = self.items[fromRow]
self.items.delete(fromRow)
self.items.insert(@[item], toRow)
self.recalcOrder()
self.endMoveRows()
proc setVisibilityByIndex*(self: ProfileShowcaseCollectiblesModel, ind: int, visibility: int) {.slot.} =
if (visibility >= ord(low(ProfileShowcaseVisibility)) and
visibility <= ord(high(ProfileShowcaseVisibility)) and
ind >= 0 and ind < self.items.len):
self.items[ind].showcaseVisibility = ProfileShowcaseVisibility(visibility)
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.ShowcaseVisibility.int])
self.baseModelFilterConditionsMayHaveChanged()
self.hiddenCountChanged()
proc setVisibility*(self: ProfileShowcaseCollectiblesModel, uid: string, visibility: int) {.slot.} =
let index = self.findIndexForCollectible(uid)
if index != -1:
self.setVisibilityByIndex(index, visibility)

View File

@ -1,224 +0,0 @@
import NimQml, tables, strutils, sequtils, json
import profile_preferences_community_item
import app_service/service/profile/dto/profile_showcase_preferences
type
ModelRole {.pure.} = enum
ShowcaseVisibility
Order
Id
Name
MemberRole
Image
Color
Description
MembersCount
Loading
QtObject:
type
ProfileShowcaseCommunitiesModel* = ref object of QAbstractListModel
items: seq[ProfileShowcaseCommunityItem]
proc delete(self: ProfileShowcaseCommunitiesModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: ProfileShowcaseCommunitiesModel) =
self.QAbstractListModel.setup
proc newProfileShowcaseCommunitiesModel*(): ProfileShowcaseCommunitiesModel =
new(result, delete)
result.setup
proc countChanged(self: ProfileShowcaseCommunitiesModel) {.signal.}
proc getCount(self: ProfileShowcaseCommunitiesModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
proc hiddenCountChanged(self: ProfileShowcaseCommunitiesModel) {.signal.}
proc getHiddenCount(self: ProfileShowcaseCommunitiesModel): int {.slot.} =
result = 0
for i, item in self.items:
if item.showcaseVisibility == ProfileShowcaseVisibility.ToNoOne:
result += 1
QtProperty[int] hiddenCount:
read = getHiddenCount
notify = hiddenCountChanged
proc recalcOrder(self: ProfileShowcaseCommunitiesModel) =
for order, item in self.items:
item.order = order
proc items*(self: ProfileShowcaseCommunitiesModel): seq[ProfileShowcaseCommunityItem] =
self.items
method rowCount(self: ProfileShowcaseCommunitiesModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: ProfileShowcaseCommunitiesModel): Table[int, string] =
{
ModelRole.Id.int: "id",
ModelRole.ShowcaseVisibility.int: "showcaseVisibility",
ModelRole.Order.int: "order",
ModelRole.Name.int: "name",
ModelRole.MemberRole.int: "memberRole",
ModelRole.Image.int: "image",
ModelRole.Color.int: "color",
ModelRole.Description.int: "description",
ModelRole.MembersCount.int: "membersCount",
ModelRole.Loading.int: "loading",
}.toTable
method data(self: ProfileShowcaseCommunitiesModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.ShowcaseVisibility:
result = newQVariant(item.showcaseVisibility.int)
of ModelRole.Order:
result = newQVariant(item.order)
of ModelRole.Id:
result = newQVariant(item.id)
of ModelRole.Name:
result = newQVariant(item.name)
of ModelRole.MemberRole:
result = newQVariant(item.memberRole.int)
of ModelRole.Image:
result = newQVariant(item.image)
of ModelRole.Color:
result = newQVariant(item.color)
of ModelRole.Description:
result = newQVariant(item.description)
of ModelRole.MembersCount:
result = newQVariant(item.membersCount)
of ModelRole.Loading:
result = newQVariant(item.loading)
proc findIndexForCommunity(self: ProfileShowcaseCommunitiesModel, id: string): int =
for i in 0 ..< self.items.len:
if (self.items[i].id == id):
return i
return -1
proc hasItemInShowcase*(self: ProfileShowcaseCommunitiesModel, id: string): bool {.slot.} =
let ind = self.findIndexForCommunity(id)
if ind == -1:
return false
return self.items[ind].showcaseVisibility != ProfileShowcaseVisibility.ToNoOne
proc baseModelFilterConditionsMayHaveChanged*(self: ProfileShowcaseCommunitiesModel) {.signal.}
proc appendItem*(self: ProfileShowcaseCommunitiesModel, item: ProfileShowcaseCommunityItem) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItemImpl(self: ProfileShowcaseCommunitiesModel, item: ProfileShowcaseCommunityItem) =
let ind = self.findIndexForCommunity(item.id)
if ind == -1:
self.appendItem(item)
else:
self.items[ind] = item
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index)
self.hiddenCountChanged()
proc upsertItemJson(self: ProfileShowcaseCommunitiesModel, itemJson: string) {.slot.} =
self.upsertItemImpl(itemJson.parseJson.toProfileShowcaseCommunityItem())
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItem*(self: ProfileShowcaseCommunitiesModel, item: ProfileShowcaseCommunityItem) =
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc upsertItems*(self: ProfileShowcaseCommunitiesModel, items: seq[ProfileShowcaseCommunityItem]) =
for item in items:
self.upsertItemImpl(item)
self.recalcOrder()
self.baseModelFilterConditionsMayHaveChanged()
proc reset*(self: ProfileShowcaseCommunitiesModel, items: seq[ProfileShowcaseCommunityItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc clear*(self: ProfileShowcaseCommunitiesModel) {.slot.} =
self.reset(@[])
proc remove*(self: ProfileShowcaseCommunitiesModel, index: int) {.slot.} =
if index < 0 or index >= self.items.len:
return
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginRemoveRows(parentModelIndex, index, index)
self.items.delete(index)
self.endRemoveRows()
self.countChanged()
self.hiddenCountChanged()
self.baseModelFilterConditionsMayHaveChanged()
proc removeEntry*(self: ProfileShowcaseCommunitiesModel, id: string) {.slot.} =
let ind = self.findIndexForCommunity(id)
if ind != -1:
self.remove(ind)
proc move*(self: ProfileShowcaseCommunitiesModel, fromRow: int, toRow: int, dummyCount: int = 1) {.slot.} =
if fromRow < 0 or fromRow >= self.items.len:
return
let sourceIndex = newQModelIndex()
defer: sourceIndex.delete
let destIndex = newQModelIndex()
defer: destIndex.delete
var destRow = toRow
if toRow > fromRow:
inc(destRow)
self.beginMoveRows(sourceIndex, fromRow, fromRow, destIndex, destRow)
let item = self.items[fromRow]
self.items.delete(fromRow)
self.items.insert(@[item], toRow)
self.recalcOrder()
self.endMoveRows()
proc setVisibilityByIndex*(self: ProfileShowcaseCommunitiesModel, ind: int, visibility: int) {.slot.} =
if (visibility >= ord(low(ProfileShowcaseVisibility)) and
visibility <= ord(high(ProfileShowcaseVisibility)) and
ind >= 0 and ind < self.items.len):
self.items[ind].showcaseVisibility = ProfileShowcaseVisibility(visibility)
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.ShowcaseVisibility.int])
self.baseModelFilterConditionsMayHaveChanged()
self.hiddenCountChanged()
proc setVisibility*(self: ProfileShowcaseCommunitiesModel, id: string, visibility: int) {.slot.} =
let index = self.findIndexForCommunity(id)
if index != -1:
self.setVisibilityByIndex(index, visibility)

View File

@ -1,88 +0,0 @@
import json, strutils, stint, json_serialization, tables
import profile_preferences_base_item
import app_service/service/community/dto/community
import app_service/service/profile/dto/profile_showcase_preferences
include app_service/common/json_utils
include app_service/common/utils
type
ProfileShowcaseCommunityItem* = ref object of ProfileShowcaseBaseItem
id*: string
name*: string
memberRole*: MemberRole
image*: string
color*: string
description*: string
membersCount*: int
loading*: bool
proc initProfileShowcaseCommunityItem*(community: CommunityDto, visibility: ProfileShowcaseVisibility, order: int): ProfileShowcaseCommunityItem =
result = ProfileShowcaseCommunityItem()
result.showcaseVisibility = visibility
result.order = order
result.id = community.id
result.name = community.name
result.memberRole = community.memberRole
result.image = community.images.thumbnail
result.color = community.color
result.description = community.description
result.membersCount = len(community.members)
result.loading = false
proc initProfileShowcaseCommunityLoadingItem*(communityId: string, visibility: ProfileShowcaseVisibility, order: int): ProfileShowcaseCommunityItem =
result = ProfileShowcaseCommunityItem()
result.showcaseVisibility = visibility
result.order = order
result.id = communityId
result.loading = true
proc toProfileShowcaseCommunityItem*(jsonObj: JsonNode): ProfileShowcaseCommunityItem =
result = ProfileShowcaseCommunityItem()
discard jsonObj.getProp("order", result.order)
var visibilityInt: int
if (jsonObj.getProp("showcaseVisibility", visibilityInt) and
(visibilityInt >= ord(low(ProfileShowcaseVisibility)) and
visibilityInt <= ord(high(ProfileShowcaseVisibility)))):
result.showcaseVisibility = ProfileShowcaseVisibility(visibilityInt)
discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("memberRole", result.memberRole)
discard jsonObj.getProp("image", result.image)
discard jsonObj.getProp("color", result.color)
result.loading = false
proc toShowcasePreferenceItem*(self: ProfileShowcaseCommunityItem): ProfileShowcaseCommunityPreference =
result = ProfileShowcaseCommunityPreference()
result.communityId = self.id
result.showcaseVisibility = self.showcaseVisibility
result.order = self.order
proc patchFromCommunity*(self: ProfileShowcaseCommunityItem, community: CommunityDto) =
self.name = community.name
self.memberRole = community.memberRole
self.image = community.images.thumbnail
self.color = community.color
self.description = community.description
self.membersCount = len(community.members)
self.loading = false
proc name*(self: ProfileShowcaseCommunityItem): string {.inline.} =
self.name
proc memberRole*(self: ProfileShowcaseCommunityItem): MemberRole {.inline.} =
self.memberRole
proc image*(self: ProfileShowcaseCommunityItem): string {.inline.} =
self.image
proc color*(self: ProfileShowcaseCommunityItem): string {.inline.} =
self.color

View File

@ -1,4 +1,4 @@
import NimQml, chronicles, sequtils, sugar, json, strutils
import NimQml, chronicles, sequtils, sugar, strutils
import ./io_interface, ./view, ./controller
import ../io_interface as delegate_interface
@ -9,28 +9,17 @@ 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/network/service as network_service
import app_service/service/profile/dto/profile_showcase
import app_service/service/profile/dto/profile_showcase_preferences
import app_service/service/token/service as token_service
import app_service/common/social_links
import app/modules/shared_models/social_links_model
import app/modules/shared_models/social_link_item
import app/modules/shared_modules/collectibles/controller as collectiblesc
# TODO: remove usage of old models
import models/profile_preferences_community_item
import models/profile_preferences_account_item
import models/profile_preferences_collectible_item
import models/profile_preferences_asset_item
import models/showcase_preferences_generic_model
import models/showcase_preferences_social_links_model
import models/profile_save_data
import backend/collectibles as backend_collectibles
export io_interface
logScope:
@ -40,11 +29,9 @@ type
Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface
controller: controller.Controller
collectiblesController: collectiblesc.Controller
view: View
viewVariant: QVariant
moduleLoaded: bool
presentedPublicKey: string
proc newModule*(
delegate: delegate_interface.AccessInterface,
@ -53,26 +40,18 @@ proc newModule*(
settingsService: settings_service.Service,
communityService: community_service.Service,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_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, networkService, tokenService)
result.collectiblesController = collectiblesc.newController(
requestId = int32(backend_collectibles.CollectiblesRequestID.ProfileShowcase),
loadType = collectiblesc.LoadType.AutoLoadSingleUpdate,
networkService = networkService,
events = events
)
result.controller = controller.newController(result, events, profileService, settingsService, communityService, walletAccountService, tokenService)
result.moduleLoaded = false
method delete*(self: Module) =
self.view.delete
self.viewVariant.delete
self.controller.delete
self.collectiblesController.delete
method load*(self: Module) =
self.controller.init()
@ -84,9 +63,6 @@ method isLoaded*(self: Module): bool =
method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant
method getCollectiblesModel*(self: Module): QVariant =
return self.collectiblesController.getModelAsVariant()
proc updateSocialLinks(self: Module, socialLinks: SocialLinks) =
var socialLinkItems = toSocialLinkItems(socialLinks)
self.view.socialLinksSaved(socialLinkItems)
@ -153,11 +129,6 @@ method saveProfileIdentity*(self: Module, identity: IdentitySaveData) =
self.view.emitProfileIdentitySaveFailedSignal()
method saveProfileShowcasePreferences*(self: Module, showcase: ShowcaseSaveData) =
# TODO: remove this check within old api
if self.presentedPublicKey != singletonInstance.userProfile.getPubKey():
error "Attempt to save preferences with wrong public key"
return
var showcasePreferences = ProfileShowcasePreferencesDto()
for _, showcaseCommunity in showcase.communities:
@ -219,89 +190,12 @@ method saveProfileShowcasePreferences*(self: Module, showcase: ShowcaseSaveData)
order: showcaseSocialLink.showcasePosition
))
self.controller.storeProfileShowcasePreferences(showcasePreferences, revealedAddresses)
self.controller.saveProfileShowcasePreferences(showcasePreferences, revealedAddresses)
method requestProfileShowcasePreferences(self: Module) =
let myPublicKey = singletonInstance.userProfile.getPubKey()
if self.presentedPublicKey != myPublicKey:
self.view.clearModels()
self.presentedPublicKey = myPublicKey
self.controller.requestProfileShowcasePreferences()
method requestProfileShowcase*(self: Module, publicKey: string) =
if publicKey == singletonInstance.userProfile.getPubKey():
self.requestProfileShowcasePreferences()
return
if self.presentedPublicKey != publicKey:
self.view.clearModels()
self.presentedPublicKey = publicKey
self.controller.requestProfileShowcaseForContact(publicKey)
method fetchProfileShowcaseAccountsByAddress*(self: Module, address: string) =
self.controller.fetchProfileShowcaseAccountsByAddress(address)
method onProfileShowcaseAccountsByAddressFetched*(self: Module, accounts: seq[ProfileShowcaseAccount]) =
let jsonObj = % accounts
self.view.emitProfileShowcaseAccountsByAddressFetchedSignal($jsonObj)
method updateProfileShowcase(self: Module, profileShowcase: ProfileShowcaseDto) =
if self.presentedPublicKey != profileShowcase.contactId:
return
# Communities for a contact
var profileCommunityItems: seq[ProfileShowcaseCommunityItem] = @[]
for communityProfile in profileShowcase.communities:
let community = self.controller.getCommunityById(communityProfile.communityId)
if community.id == "":
# Fetch the community, however, we do not the shard info, so hopefully we can fetch it
self.controller.requestCommunityInfo(communityProfile.communityId, shard = nil)
profileCommunityItems.add(initProfileShowcaseCommunityLoadingItem(
communityProfile.communityId, ProfileShowcaseVisibility.ToEveryone, communityProfile.order))
else:
profileCommunityItems.add(initProfileShowcaseCommunityItem(
community, ProfileShowcaseVisibility.ToEveryone, communityProfile.order))
self.view.updateProfileShowcaseCommunities(profileCommunityItems)
# Accounts for a contact, reuse addresses for collectibles and token balances
var profileAccountItems: seq[ProfileShowcaseAccountItem] = @[]
var accountAddresses: seq[string] = @[]
for account in profileShowcase.accounts:
profileAccountItems.add(initProfileShowcaseAccountItem(
account.address, account.name, account.emoji, account.colorId,
ProfileShowcaseVisibility.ToEveryone, account.order))
accountAddresses.add(account.address)
self.view.updateProfileShowcaseAccounts(profileAccountItems)
# Collectibles for a contact
let chainIds = self.controller.getChainIds()
self.collectiblesController.setFilterAddressesAndChains(accountAddresses, chainIds)
var profileCollectibleItems: seq[ProfileShowcaseCollectibleItem] = @[]
for collectibleProfile in profileShowcase.collectibles:
let collectible = self.collectiblesController.getItemForData(collectibleProfile.tokenId, collectibleProfile.contractAddress, collectibleProfile.chainId)
if collectible != nil:
profileCollectibleItems.add(initProfileShowcaseCollectibleItem(
collectible, ProfileShowcaseVisibility.ToEveryone, collectibleProfile.order))
self.view.updateProfileShowcaseCollectibles(profileCollectibleItems)
# Verified tokens for a contact
var profileAssetItems: seq[ProfileShowcaseAssetItem] = @[]
for tokenProfile in profileShowcase.verifiedTokens:
# NOTE: not yet working for external wallet accounts
for token in self.controller.getTokenBySymbolList():
if tokenProfile.symbol == token.symbol:
profileAssetItems.add(initProfileShowcaseVerifiedToken(token, ProfileShowcaseVisibility.ToEveryone, tokenProfile.order))
# TODO: Unverified tokens for a contact
self.view.updateProfileShowcaseAssets(profileAssetItems)
method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowcasePreferencesDto) =
if self.presentedPublicKey != singletonInstance.userProfile.getPubKey():
return
method loadProfileShowcasePreferences(self: Module, preferences: ProfileShowcasePreferencesDto) =
var communityItems: seq[ShowcasePreferencesGenericItem] = @[]
for community in preferences.communities:
communityItems.add(ShowcasePreferencesGenericItem(
@ -309,7 +203,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: community.showcaseVisibility,
showcasePosition: community.order
))
self.view.updateProfileShowcasePreferencesCommunities(communityItems)
self.view.loadProfileShowcasePreferencesCommunities(communityItems)
var accountItems: seq[ShowcasePreferencesGenericItem] = @[]
for account in preferences.accounts:
@ -318,7 +212,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: account.showcaseVisibility,
showcasePosition: account.order
))
self.view.updateProfileShowcasePreferencesAccounts(accountItems)
self.view.loadProfileShowcasePreferencesAccounts(accountItems)
var collectibleItems: seq[ShowcasePreferencesGenericItem] = @[]
for collectible in preferences.collectibles:
@ -327,7 +221,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: collectible.showcaseVisibility,
showcasePosition: collectible.order
))
self.view.updateProfileShowcasePreferencesCollectibles(collectibleItems)
self.view.loadProfileShowcasePreferencesCollectibles(collectibleItems)
var assetItems: seq[ShowcasePreferencesGenericItem] = @[]
for token in preferences.verifiedTokens:
@ -342,7 +236,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: token.showcaseVisibility,
showcasePosition: token.order
))
self.view.updateProfileShowcasePreferencesAssets(assetItems)
self.view.loadProfileShowcasePreferencesAssets(assetItems)
var socialLinkItems: seq[ShowcasePreferencesSocialLinkItem] = @[]
for socialLink in preferences.socialLinks:
@ -351,61 +245,4 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
text: socialLink.text,
showcasePosition: socialLink.order
))
self.view.updateProfileShowcasePreferencesSocialLinks(socialLinkItems)
# TODO: remove the code for old models
var profileCommunityItems: seq[ProfileShowcaseCommunityItem] = @[]
for communityProfile in preferences.communities:
let community = self.controller.getCommunityById(communityProfile.communityId)
if community.id == "":
warn "Unknown community added to our own profile showcase" , communityId = communityProfile.communityId
else:
profileCommunityItems.add(initProfileShowcaseCommunityItem(
community, communityProfile.showcaseVisibility, communityProfile.order))
self.view.updateProfileShowcaseCommunities(profileCommunityItems)
# For profile preferences we are using all the addresses for colletibles and token balances
# TODO: add wallet accounts model instance here to remove QML dependency from the wallet module
let accountAddresses = self.controller.getWalletAccounts().map(acc => acc.address) # filter(acc => acc.walletType != WalletTypeWatch).
# Accounts profile preferences
var profileAccountItems: seq[ProfileShowcaseAccountItem] = @[]
for preference in preferences.accounts:
let account = self.controller.getAccountByAddress(preference.address)
if account == nil:
error "Can't find an account with address ", address=preference.address
continue
profileAccountItems.add(initProfileShowcaseAccountItem(
account.address, account.name, account.emoji, account.colorId,
preference.showcaseVisibility, preference.order))
self.view.updateProfileShowcaseAccounts(profileAccountItems)
# Collectibles profile preferences
let chainIds = self.controller.getChainIds()
self.collectiblesController.setFilterAddressesAndChains(accountAddresses, chainIds)
var profileCollectibleItems: seq[ProfileShowcaseCollectibleItem] = @[]
for collectibleProfile in preferences.collectibles:
let collectible = self.collectiblesController.getItemForData(collectibleProfile.tokenId, collectibleProfile.contractAddress, collectibleProfile.chainId)
if collectible != nil:
profileCollectibleItems.add(initProfileShowcaseCollectibleItem(
collectible, collectibleProfile.showcaseVisibility, collectibleProfile.order))
self.view.updateProfileShowcaseCollectibles(profileCollectibleItems)
var profileAssetItems: seq[ProfileShowcaseAssetItem] = @[]
for tokenProfile in preferences.verifiedTokens:
for token in self.controller.getTokenBySymbolList():
if tokenProfile.symbol == token.symbol:
profileAssetItems.add(initProfileShowcaseVerifiedToken(token, tokenProfile.showcaseVisibility, tokenProfile.order))
self.view.updateProfileShowcaseAssets(profileAssetItems)
method onCommunitiesUpdated*(self: Module, communities: seq[CommunityDto]) =
var profileCommunityItems = self.view.getProfileShowcaseCommunities()
for community in communities:
for item in profileCommunityItems:
if item.id == community.id:
item.patchFromCommunity(community)
self.view.updateProfileShowcaseCommunities(profileCommunityItems)
self.view.loadProfileShowcasePreferencesSocialLinks(socialLinkItems)

View File

@ -1,19 +1,9 @@
import NimQml, json, sequtils, sugar, std/algorithm
import NimQml, json, sequtils
import io_interface
import app/modules/shared_models/social_links_model
import app/modules/shared_models/social_link_item
# TODO remove old models
import models/profile_preferences_communities_model
import models/profile_preferences_community_item
import models/profile_preferences_accounts_model
import models/profile_preferences_account_item
import models/profile_preferences_collectibles_model
import models/profile_preferences_collectible_item
import models/profile_preferences_assets_model
import models/profile_preferences_asset_item
import models/profile_save_data
import models/showcase_preferences_generic_model
import models/showcase_preferences_social_links_model
@ -27,14 +17,6 @@ QtObject:
socialLinksModelVariant: QVariant
temporarySocialLinksModel: SocialLinksModel # used for editing purposes
temporarySocialLinksModelVariant: QVariant
profileShowcaseCommunitiesModel: ProfileShowcaseCommunitiesModel
profileShowcaseCommunitiesModelVariant: QVariant
profileShowcaseAccountsModel: ProfileShowcaseAccountsModel
profileShowcaseAccountsModelVariant: QVariant
profileShowcaseCollectiblesModel: ProfileShowcaseCollectiblesModel
profileShowcaseCollectiblesModelVariant: QVariant
profileShowcaseAssetsModel: ProfileShowcaseAssetsModel
profileShowcaseAssetsModelVariant: QVariant
showcasePreferencesCommunitiesModel: ShowcasePreferencesGenericModel
showcasePreferencesCommunitiesModelVariant: QVariant
@ -48,20 +30,11 @@ QtObject:
showcasePreferencesSocialLinksModelVariant: QVariant
proc delete*(self: View) =
self.QObject.delete
# TODO: remove old models
self.socialLinksModel.delete
self.socialLinksModelVariant.delete
self.temporarySocialLinksModel.delete
self.temporarySocialLinksModelVariant.delete
self.profileShowcaseCommunitiesModel.delete
self.profileShowcaseCommunitiesModelVariant.delete
self.profileShowcaseAccountsModel.delete
self.profileShowcaseAccountsModelVariant.delete
self.profileShowcaseCollectiblesModel.delete
self.profileShowcaseCollectiblesModelVariant.delete
self.profileShowcaseAssetsModel.delete
self.profileShowcaseAssetsModelVariant.delete
self.showcasePreferencesCommunitiesModel.delete
self.showcasePreferencesCommunitiesModelVariant.delete
@ -73,6 +46,7 @@ QtObject:
self.showcasePreferencesAssetsModelVariant.delete
self.showcasePreferencesSocialLinksModel.delete
self.showcasePreferencesSocialLinksModelVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete)
@ -83,14 +57,6 @@ QtObject:
result.socialLinksModelVariant = newQVariant(result.socialLinksModel)
result.temporarySocialLinksModel = newSocialLinksModel()
result.temporarySocialLinksModelVariant = newQVariant(result.temporarySocialLinksModel)
result.profileShowcaseCommunitiesModel = newProfileShowcaseCommunitiesModel()
result.profileShowcaseCommunitiesModelVariant = newQVariant(result.profileShowcaseCommunitiesModel)
result.profileShowcaseAccountsModel = newProfileShowcaseAccountsModel()
result.profileShowcaseAccountsModelVariant = newQVariant(result.profileShowcaseAccountsModel)
result.profileShowcaseCollectiblesModel = newProfileShowcaseCollectiblesModel()
result.profileShowcaseCollectiblesModelVariant = newQVariant(result.profileShowcaseCollectiblesModel)
result.profileShowcaseAssetsModel = newProfileShowcaseAssetsModel()
result.profileShowcaseAssetsModelVariant = newQVariant(result.profileShowcaseAssetsModel)
result.showcasePreferencesCommunitiesModel = newShowcasePreferencesGenericModel()
result.showcasePreferencesCommunitiesModelVariant = newQVariant(result.showcasePreferencesCommunitiesModel)
@ -213,72 +179,30 @@ QtObject:
proc emitProfileShowcasePreferencesSaveFailedSignal*(self: View) =
self.profileShowcasePreferencesSaveFailed()
# TODO: remove old models
proc getCollectiblesModel(self: View): QVariant {.slot.} =
return self.delegate.getCollectiblesModel()
QtProperty[QVariant] collectiblesModel:
read = getCollectiblesModel
proc getProfileShowcaseCommunitiesModel(self: View): QVariant {.slot.} =
return self.profileShowcaseCommunitiesModelVariant
QtProperty[QVariant] profileShowcaseCommunitiesModel:
read = getProfileShowcaseCommunitiesModel
proc getProfileShowcaseAccountsModel(self: View): QVariant {.slot.} =
return self.profileShowcaseAccountsModelVariant
QtProperty[QVariant] profileShowcaseAccountsModel:
read = getProfileShowcaseAccountsModel
proc getProfileShowcaseCollectiblesModel(self: View): QVariant {.slot.} =
return self.profileShowcaseCollectiblesModelVariant
QtProperty[QVariant] profileShowcaseCollectiblesModel:
read = getProfileShowcaseCollectiblesModel
proc getProfileShowcaseAssetsModel(self: View): QVariant {.slot.} =
return self.profileShowcaseAssetsModelVariant
QtProperty[QVariant] profileShowcaseAssetsModel:
read = getProfileShowcaseAssetsModel
proc getProfileShowcasePreferencesCommunitiesModel(self: View): QVariant {.slot.} =
proc getShowcasePreferencesCommunitiesModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesCommunitiesModelVariant
QtProperty[QVariant] showcasePreferencesCommunitiesModel:
read = getProfileShowcasePreferencesCommunitiesModel
read = getShowcasePreferencesCommunitiesModel
proc getProfileShowcasePreferencesAccountsModel(self: View): QVariant {.slot.} =
proc getShowcasePreferencesAccountsModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesAccountsModelVariant
QtProperty[QVariant] showcasePreferencesAccountsModel:
read = getProfileShowcasePreferencesAccountsModel
read = getShowcasePreferencesAccountsModel
proc getProfileShowcasePreferencesCollectiblesModel(self: View): QVariant {.slot.} =
proc getShowcasePreferencesCollectiblesModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesCollectiblesModelVariant
QtProperty[QVariant] showcasePreferencesCollectiblesModel:
read = getProfileShowcasePreferencesCollectiblesModel
read = getShowcasePreferencesCollectiblesModel
proc getProfileShowcasePreferencesAssetsModel(self: View): QVariant {.slot.} =
proc getShowcasePreferencesAssetsModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesAssetsModelVariant
QtProperty[QVariant] showcasePreferencesAssetsModel:
read = getProfileShowcasePreferencesAssetsModel
read = getShowcasePreferencesAssetsModel
proc getProfileShowcasePreferencesSocialLinksModel(self: View): QVariant {.slot.} =
proc getShowcasePreferencesSocialLinksModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesSocialLinksModelVariant
QtProperty[QVariant] showcasePreferencesSocialLinksModel:
read = getProfileShowcasePreferencesSocialLinksModel
proc clearModels*(self: View) {.slot.} =
self.profileShowcaseCommunitiesModel.clear()
self.profileShowcaseAccountsModel.clear()
self.profileShowcaseCollectiblesModel.clear()
self.profileShowcaseAssetsModel.clear()
read = getShowcasePreferencesSocialLinksModel
proc saveProfileIdentity(self: View, profileData: string) {.slot.} =
let profileDataObj = profileData.parseJson
@ -296,49 +220,23 @@ QtObject:
proc getProfileShowcaseEntriesLimit*(self: View): int {.slot.} =
self.delegate.getProfileShowcaseEntriesLimit()
proc requestProfileShowcase(self: View, publicKey: string) {.slot.} =
self.delegate.requestProfileShowcase(publicKey)
proc requestProfileShowcasePreferences(self: View) {.slot.} =
self.delegate.requestProfileShowcasePreferences()
proc setIsFirstShowcaseInteraction(self: View) {.slot.} =
self.delegate.setIsFirstShowcaseInteraction()
proc getProfileShowcaseCommunities*(self: View): seq[ProfileShowcaseCommunityItem] =
return self.profileShowcaseCommunitiesModel.items()
proc updateProfileShowcasePreferencesCommunities*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
proc loadProfileShowcasePreferencesCommunities*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesCommunitiesModel.setItems(items)
proc updateProfileShowcasePreferencesAccounts*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
proc loadProfileShowcasePreferencesAccounts*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesAccountsModel.setItems(items)
proc updateProfileShowcasePreferencesCollectibles*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
proc loadProfileShowcasePreferencesCollectibles*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesCollectiblesModel.setItems(items)
proc updateProfileShowcasePreferencesAssets*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
proc loadProfileShowcasePreferencesAssets*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesAssetsModel.setItems(items)
proc updateProfileShowcasePreferencesSocialLinks*(self: View, items: seq[ShowcasePreferencesSocialLinkItem]) =
proc loadProfileShowcasePreferencesSocialLinks*(self: View, items: seq[ShowcasePreferencesSocialLinkItem]) =
self.showcasePreferencesSocialLinksModel.setItems(items)
# TODO: remove setters for old models
proc updateProfileShowcaseCommunities*(self: View, communities: seq[ProfileShowcaseCommunityItem]) =
self.profileShowcaseCommunitiesModel.reset(communities.sorted((a, b) => cmp(a.order, b.order), SortOrder.Ascending))
proc updateProfileShowcaseAccounts*(self: View, accounts: seq[ProfileShowcaseAccountItem]) =
self.profileShowcaseAccountsModel.reset(accounts.sorted((a, b) => cmp(a.order, b.order), SortOrder.Ascending))
proc updateProfileShowcaseCollectibles*(self: View, collectibles: seq[ProfileShowcaseCollectibleItem]) =
self.profileShowcaseCollectiblesModel.reset(collectibles.sorted((a, b) => cmp(a.order, b.order), SortOrder.Ascending))
proc updateProfileShowcaseAssets*(self: View, assets: seq[ProfileShowcaseAssetItem]) =
self.profileShowcaseAssetsModel.reset(assets.sorted((a, b) => cmp(a.order, b.order), SortOrder.Ascending))
proc fetchProfileShowcaseAccountsByAddress*(self: View, address: string) {.slot.} =
self.delegate.fetchProfileShowcaseAccountsByAddress(address)
proc profileShowcaseAccountsByAddressFetched*(self: View, accounts: string) {.signal.}
proc emitProfileShowcaseAccountsByAddressFetchedSignal*(self: View, accounts: string) =
self.profileShowcaseAccountsByAddressFetched(accounts)

View File

@ -68,10 +68,51 @@ const asyncRequestContactInfoTask: Task = proc(argEncoded: string) {.gcsafe, nim
arg.finish(%* {
"publicKey": arg.pubkey,
"response": response,
"error": nil,
"error": "",
})
except Exception as e:
arg.finish(%* {
"publicKey": arg.pubkey,
"error": e.msg,
})
type
AsyncGetProfileShowcaseForContactTaskArg = ref object of QObjectTaskArg
pubkey: string
validate: bool
const asyncGetProfileShowcaseForContactTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncGetProfileShowcaseForContactTaskArg](argEncoded)
try:
let response = status_go.getProfileShowcaseForContact(arg.pubkey, arg.validate)
arg.finish(%* {
"publicKey": arg.pubkey,
"validated": arg.validate,
"response": response,
"error": "",
})
except Exception as e:
arg.finish(%* {
"publicKey": arg.pubkey,
"validated": arg.validate,
"error": e.msg,
})
type
FetchProfileShowcaseAccountsTaskArg = ref object of QObjectTaskArg
address: string
const fetchProfileShowcaseAccountsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[FetchProfileShowcaseAccountsTaskArg](argEncoded)
var response = %* {
"response": "",
"error": "",
}
try:
let rpcResponse = status_accounts.getProfileShowcaseAccountsByAddress(arg.address)
if not rpcResponse.error.isNil:
raise newException(CatchableError, rpcResponse.error.message)
response["response"] = rpcResponse.result
except Exception as e:
response["error"] = %* e.msg
arg.finish(response)

View File

@ -1,10 +1,16 @@
import json, json_serialization
import json, json_serialization, stew/shims/strformat
include ../../../common/json_utils
type ProfileShowcaseMembershipStatus* {.pure.}= enum
Unproven = 0,
ProvenMember = 1,
NotAMember = 2,
type ProfileShowcaseCommunity* = ref object of RootObj
communityId*: string
order*: int
membershipStatus*: ProfileShowcaseMembershipStatus
type ProfileShowcaseAccount* = ref object of RootObj
contactId*: string
@ -43,10 +49,19 @@ type ProfileShowcaseDto* = ref object of RootObj
unverifiedTokens*: seq[ProfileShowcaseUnverifiedToken]
socialLinks*: seq[ProfileShowcaseSocialLink]
proc toProfileShowcaseMembershipStatus*(jsonObj: JsonNode): ProfileShowcaseMembershipStatus =
var membershipStatusInt: int
if (jsonObj.getProp("membershipStatus", membershipStatusInt) and
(membershipStatusInt >= ord(low(ProfileShowcaseMembershipStatus)) and
membershipStatusInt <= ord(high(ProfileShowcaseMembershipStatus)))):
return ProfileShowcaseMembershipStatus(membershipStatusInt)
return ProfileShowcaseMembershipStatus.Unproven
proc toProfileShowcaseCommunity*(jsonObj: JsonNode): ProfileShowcaseCommunity =
result = ProfileShowcaseCommunity()
discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("order", result.order)
result.membershipStatus = jsonObj.toProfileShowcaseMembershipStatus()
proc toProfileShowcaseAccount*(jsonObj: JsonNode): ProfileShowcaseAccount =
result = ProfileShowcaseAccount()
@ -113,3 +128,10 @@ proc `%`*(x: ProfileShowcaseAccount): JsonNode =
result["colorId"] = % x.colorId
result["emoji"] = % x.emoji
result["order"] = % x.order
# TODO: refactor to utils function on code cleanup stage
proc toCombinedCollectibleId*(self: ProfileShowcaseCollectible): string =
return fmt"{self.chainId}+{self.contractAddress}+{self.tokenId}"
proc toCombinedTokenId*(self: ProfileShowcaseUnverifiedToken): string =
return fmt"{self.chainId}+{self.contractAddress}"

View File

@ -17,6 +17,8 @@ import ../visual_identity/service as procs_from_visual_identity_service
import ./dto/contacts as contacts_dto
import ./dto/status_update as status_update_dto
import ./dto/contact_details
import ./dto/profile_showcase
import ../../../backend/contacts as status_contacts
import ../../../backend/accounts as status_accounts
@ -60,6 +62,13 @@ type
chatId*: string
messages*: JsonNode
ProfileShowcaseForContactArgs* = ref object of Args
profileShowcase*: ProfileShowcaseDto
validated*: bool
ProfileShowcaseContactIdArgs* = ref object of Args
contactId*: string
# Signals which may be emitted by this service:
const SIGNAL_ENS_RESOLVED* = "ensResolved"
const SIGNAL_CONTACT_ADDED* = "contactAdded"
@ -84,6 +93,10 @@ const SIGNAL_CONTACT_VERIFICATION_UPDATED* = "contactVerificationRequestUpdated"
const SIGNAL_CONTACT_INFO_REQUEST_FINISHED* = "contactInfoRequestFinished"
const SIGNAL_APPEND_CHAT_MESSAGES* = "appendChatMessages"
const SIGNAL_CONTACT_PROFILE_SHOWCASE_UPDATED* = "contactProfileShowcaseUpdated"
const SIGNAL_CONTACT_PROFILE_SHOWCASE_LOADED* = "contactProfileShowcaseLoaded"
const SIGNAL_CONTACT_SHOWCASE_ACCOUNTS_BY_ADDRESS_FETCHED* = "profileShowcaseAccountsByAddressFetched"
type
ContactsGroup* {.pure.} = enum
AllKnownContacts
@ -223,7 +236,12 @@ QtObject:
else:
self.events.emit(SIGNAL_CONTACT_VERIFICATION_ADDED, data)
self.events.on(SignalType.Message.event) do(e: Args):
let receivedData = MessageSignal(e)
if receivedData.updatedProfileShowcaseContactIDs.len > 0:
for contactId in receivedData.updatedProfileShowcaseContactIDs:
self.events.emit(SIGNAL_CONTACT_PROFILE_SHOWCASE_UPDATED,
ProfileShowcaseContactIdArgs(contactId: contactId))
self.events.on(SignalType.StatusUpdatesTimedout.event) do(e:Args):
var receivedData = StatusUpdatesTimedoutSignal(e)
if(receivedData.statusUpdates.len > 0):
@ -881,3 +899,58 @@ QtObject:
return response.result.getStr
except Exception as e:
error "Error getting user url with ens name", msg = e.msg, pubkey
proc requestProfileShowcaseForContact*(self: Service, contactId: string, validate: bool) =
let arg = AsyncGetProfileShowcaseForContactTaskArg(
pubkey: contactId,
validate: validate,
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 for a contact", msg = rpcResponseObj{"error"}
return
let profileShowcase = rpcResponseObj["response"]["result"].toProfileShowcaseDto()
let validated = rpcResponseObj["validated"].getBool
self.events.emit(SIGNAL_CONTACT_PROFILE_SHOWCASE_LOADED,
ProfileShowcaseForContactArgs(
profileShowcase: profileShowcase,
validated: validated
))
except Exception as e:
error "Error requesting profile showcase for a contact", msg = e.msg
proc fetchProfileShowcaseAccountsByAddress*(self: Service, address: string) =
let arg = FetchProfileShowcaseAccountsTaskArg(
address: address,
tptr: cast[ByteAddress](fetchProfileShowcaseAccountsTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onProfileShowcaseAccountsByAddressFetched",
)
self.threadpool.start(arg)
proc onProfileShowcaseAccountsByAddressFetched*(self: Service, rpcResponse: string) {.slot.} =
var data = ProfileShowcaseForContactArgs(
profileShowcase: ProfileShowcaseDto(
accounts: @[],
),
)
try:
let rpcResponseObj = rpcResponse.parseJson
if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "":
raise newException(CatchableError, rpcResponseObj{"error"}.getStr)
if rpcResponseObj{"response"}.kind != JArray:
raise newException(CatchableError, "invalid response")
data.profileShowcase.accounts = map(rpcResponseObj{"response"}.getElems(), proc(x: JsonNode): ProfileShowcaseAccount = toProfileShowcaseAccount(x))
except Exception as e:
error "onProfileShowcaseAccountsByAddressFetched", msg = e.msg
self.events.emit(SIGNAL_CONTACT_SHOWCASE_ACCOUNTS_BY_ADDRESS_FETCHED, data)

View File

@ -11,50 +11,12 @@ const asyncGetProfileShowcasePreferencesTask: Task = proc(argEncoded: string) {.
let response = status_accounts.getProfileShowcasePreferences()
arg.finish(%* {
"response": response,
"error": nil,
})
except Exception as e:
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,
})
type
FetchProfileShowcaseAccountsTaskArg = ref object of QObjectTaskArg
address: string
const fetchProfileShowcaseAccountsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[FetchProfileShowcaseAccountsTaskArg](argEncoded)
var response = %* {
"response": "",
"error": "",
}
try:
let rpcResponse = status_accounts.getProfileShowcaseAccountsByAddress(arg.address)
if not rpcResponse.error.isNil:
raise newException(CatchableError, rpcResponse.error.message)
response["response"] = rpcResponse.result
})
except Exception as e:
response["error"] = %* e.msg
arg.finish(response)
arg.finish(%* {
"error": e.msg,
})
type
SaveProfileShowcasePreferencesTaskArg = ref object of QObjectTaskArg
@ -66,7 +28,7 @@ const saveProfileShowcasePreferencesTask: Task = proc(argEncoded: string) {.gcsa
let response = status_accounts.setProfileShowcasePreferences(arg.preferences.toJsonNode())
arg.finish(%* {
"response": response,
"error": nil,
"error": "",
})
except Exception as e:
arg.finish(%* {

View File

@ -10,7 +10,6 @@ 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
@ -22,17 +21,10 @@ 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_PREFERENCES_LOADED* = "profileShowcasePreferencesLoaded"
const SIGNAL_PROFILE_SHOWCASE_PREFERENCES_SAVE_SUCCEEDED* = "profileShowcasePreferencesSaveSucceeded"
const SIGNAL_PROFILE_SHOWCASE_PREFERENCES_SAVE_FAILED* = "profileShowcasePreferencesSaveFailed"
const SIGNAL_PROFILE_SHOWCASE_ACCOUNTS_BY_ADDRESS_FETCHED* = "profileShowcaseAccountsByAddressFetched"
# TODO: move to contacts service
const SIGNAL_PROFILE_SHOWCASE_FOR_CONTACT_UPDATED* = "profileShowcaseForContactUpdated"
QtObject:
type Service* = ref object of QObject
@ -55,13 +47,6 @@ 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)
@ -114,56 +99,6 @@ QtObject:
error "error: ", procName="setDisplayName", errName = e.name, errDesription = e.msg
return false
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 for a contact", 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 fetchProfileShowcaseAccountsByAddress*(self: Service, address: string) =
let arg = FetchProfileShowcaseAccountsTaskArg(
address: address,
tptr: cast[ByteAddress](fetchProfileShowcaseAccountsTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onProfileShowcaseAccountsByAddressFetched",
)
self.threadpool.start(arg)
proc onProfileShowcaseAccountsByAddressFetched*(self: Service, rpcResponse: string) {.slot.} =
var data = ProfileShowcaseForContactArgs(
profileShowcase: ProfileShowcaseDto(
accounts: @[],
),
)
try:
let rpcResponseObj = rpcResponse.parseJson
if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "":
raise newException(CatchableError, rpcResponseObj{"error"}.getStr)
if rpcResponseObj{"response"}.kind != JArray:
raise newException(CatchableError, "invalid response")
data.profileShowcase.accounts = map(rpcResponseObj{"response"}.getElems(), proc(x: JsonNode): ProfileShowcaseAccount = toProfileShowcaseAccount(x))
except Exception as e:
error "onProfileShowcaseAccountsByAddressFetched", msg = e.msg
self.events.emit(SIGNAL_PROFILE_SHOWCASE_ACCOUNTS_BY_ADDRESS_FETCHED, data)
proc requestProfileShowcasePreferences*(self: Service) =
let arg = QObjectTaskArg(
tptr: cast[ByteAddress](asyncGetProfileShowcasePreferencesTask),
@ -181,7 +116,7 @@ QtObject:
let preferences = rpcResponseObj["response"]["result"].toProfileShowcasePreferencesDto()
self.events.emit(SIGNAL_PROFILE_SHOWCASE_PREFERENCES_UPDATED,
self.events.emit(SIGNAL_PROFILE_SHOWCASE_PREFERENCES_LOADED,
ProfileShowcasePreferencesArgs(preferences: preferences))
except Exception as e:
error "Error requesting profile showcase preferences", msg = e.msg

View File

@ -474,10 +474,6 @@ proc verifyKeystoreFileForAccount*(address, password: string): RpcResponse[JsonN
let payload = %* [address, password]
return core.callPrivateRPC("accounts_verifyKeystoreFileForAccount", payload)
proc getProfileShowcaseForContact*(contactId: string): RpcResponse[JsonNode] =
let payload = %* [contactId]
result = callPrivateRPC("getProfileShowcaseForContact".prefix, payload)
proc getProfileShowcaseAccountsByAddress*(address: string): RpcResponse[JsonNode] =
let payload = %* [address]
result = callPrivateRPC("getProfileShowcaseAccountsByAddress".prefix, payload)

View File

@ -144,3 +144,7 @@ proc shareUserUrlWithChatKey*(pubkey: string): RpcResponse[JsonNode] =
proc shareUserUrlWithENS*(pubkey: string): RpcResponse[JsonNode] =
result = callPrivateRPC("shareUserURLWithENS".prefix, %*[pubkey])
proc getProfileShowcaseForContact*(contactId: string, validate: bool): RpcResponse[JsonNode] =
let payload = %* [contactId, validate]
result = callPrivateRPC("getProfileShowcaseForContact".prefix, payload)

View File

@ -288,6 +288,14 @@ SplitView {
onCloseRequested: logs.logEvent("closeRequested()")
sendToAccountEnabled: true
showcaseCommunitiesModel: CommunitiesModel {}
showcaseAccountsModel: WalletAccountsModel {}
showcaseCollectiblesModel: ManageCollectiblesModel {}
showcaseSocialLinksModel: assetsStore.groupedAccountAssetsModel
// TODO: showcaseAssetsModel
profileStore: QtObject {
readonly property string pubkey: "0xdeadbeef"
readonly property string ensName: name.text
@ -298,14 +306,6 @@ SplitView {
function copyToClipboard(text) {
logs.logEvent("profileStore::copyToClipboard", ["text"], arguments)
}
function requestProfileShowcase(publicKey) {
logs.logEvent("profileStore::requestProfileShowcase", ["publicKey"], arguments)
}
readonly property var profileShowcaseCommunitiesModel: CommunitiesModel {}
readonly property var profileShowcaseAccountsModel: WalletAccountsModel {}
readonly property var profileShowcaseCollectiblesModel: ManageCollectiblesModel {}
readonly property var profileShowcaseAssetsModel: assetsStore.groupedAccountAssetsModel
}
contactsStore: QtObject {
@ -364,32 +364,10 @@ SplitView {
logs.logEvent("contactsStore::changeContactNickname", ["publicKey", "newNickname", "displayName", "isEdit"], arguments)
localNickname.text = newNickname
}
}
walletStore: QtObject {
function setFilterAddress(address) {
logs.logEvent("walletStore::setFilterAddress", ["address"], arguments)
function requestProfileShowcase(publicKey) {
logs.logEvent("contactsStore::requestProfileShowcase", ["publicKey"], arguments)
}
function getSavedAddress(address) {
return {
name: "My Status Saved Account",
address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7000",
ens: false,
colorId: Constants.walletAccountColors.primary,
chainShortNames: "",
isTest: false
}
}
function createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames) {
logs.logEvent("walletStore::createOrUpdateSavedAddress", ["name", "address", "ens", "colorId", "chainShortNames"],
arguments)
}
}
networkConnectionStore: QtObject {
readonly property bool sendBuyBridgeEnabled: true
}
}
}

View File

@ -17,27 +17,12 @@ Item {
ListModel {
id: communitiesModel
ListElement { showcaseKey: "1"; name: "Crypto Kitties" }
ListElement { showcaseKey: "1"; name: "Crypto Kitties"; showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts; showcasePosition: 0 }
ListElement { showcaseKey: "2"; name: "Status" }
ListElement { showcaseKey: "3"; name: "Fun Stuff" }
ListElement { showcaseKey: "3"; name: "Fun Stuff"; showcaseVisibility: Constants.ShowcaseVisibility.Contacts; showcasePosition: 9}
ListElement { showcaseKey: "4"; name: "Other Stuff" }
}
ListModel {
id: communitiesShowcaseModel
ListElement {
showcaseKey: "1"
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
showcasePosition: 0
}
ListElement {
showcaseKey: "3"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
showcasePosition: 9
}
}
ListModel {
id: comboBoxModel
@ -59,7 +44,6 @@ Item {
id: dirtyState
sourceModel: communitiesModel
showcaseModel: communitiesShowcaseModel
}
MovableModel {
@ -77,72 +61,36 @@ Item {
Layout.fillHeight: true
Layout.margins: 10
rows: 3
columns: 3
rows: 2
columns: 2
spacing: 10
flow: Grid.TopToBottom
Label {
text: "Backend models"
font.pixelSize: 22
padding: 10
}
GenericListView {
width: grid.width / 3 - grid.spacing
width: grid.width / 2 - grid.spacing
height: 300
model: communitiesModel
label: "COMMUNITIES MODEL"
label: "COMMUNITIES MODEL - Backend model"
}
GenericListView {
width: grid.width / 3 - grid.spacing
height: 300
model: communitiesShowcaseModel
label: "SHOWCASE MODEL"
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"]
}
Label {
text: "Internal models"
font.pixelSize: 22
padding: 10
}
GenericListView {
width: grid.width / 3 - grid.spacing
height: 300
model: dirtyState.joined_
label: "JOINED MODEL"
}
GenericListView {
width: grid.width / 3 - grid.spacing
width: grid.width / 2 - grid.spacing
height: 300
model: dirtyState.writable_
label: "WRITABLE MODEL"
label: "WRITABLE MODEL - Internal Model"
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition", "name"]
}
Label {
text: "Display models"
font.pixelSize: 22
padding: 10
}
GenericListView {
width: grid.width / 3 - grid.spacing
width: grid.width / 2 - grid.spacing
height: 300
model: movableModel
label: "IN SHOWCASE"
label: "IN SHOWCASE - output"
movable: true
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"]
@ -185,11 +133,11 @@ Item {
}
GenericListView {
width: grid.width / 3 - grid.spacing
width: grid.width / 2 - grid.spacing
height: 300
model: dirtyState.hiddenModel
label: "HIDDEN"
label: "HIDDEN - output"
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"]
@ -208,8 +156,13 @@ Item {
onClicked: {
const toBeSaved = dirtyState.currentState()
communitiesShowcaseModel.clear()
communitiesShowcaseModel.append(toBeSaved)
for (let i = 0; i < communitiesModel.count; i++) {
const item = communitiesModel.get(i)
const found = toBeSaved.find((x) => x.showcaseKey === item.showcaseKey)
item.showcaseVisibility = !!found ? found.showcaseVisibility : Constants.ShowcaseVisibility.NoOne
item.showcasePosition = !!found ? found.showcasePosition : 0
}
}
Layout.alignment: Qt.AlignHCenter

View File

@ -18,162 +18,91 @@ ColumnLayout {
ListModel {
id: accountsModel
ListElement { address: "1"; name: "Crypto Kitties" }
ListElement { address: "2"; name: "Status" }
ListElement { address: "3"; name: "Fun Stuff" }
ListElement { address: "4"; name: "Other Stuff" }
ListElement {
address: "1"
name: "Crypto Kitties"
showcaseKey: "1"
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
showcasePosition: 0
}
ListElement {
address: "2"
name: "Status"
showcaseKey: "2"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
}
ListElement {
address: "3";
name: "Fun Stuff"
showcaseKey: "3"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
}
ListElement {
address: "4"
name: "Other Stuff"
showcaseKey: "4"
showcaseVisibility: Constants.ShowcaseVisibility.NoOne
}
}
ListModel {
id: socialLinksModel
ListElement { uuid: "1"; text: "Twitter"; url: "https://twitter.com/status" }
ListElement { uuid: "2"; text: "Personal Site"; url: "https://status.im" }
ListElement { uuid: "3"; text: "Github"; url: "https://github.com" }
ListElement { uuid: "4"; text: "Youtube"; url: "https://youtube.com" }
ListElement { uuid: "5"; text: "Discord"; url: "https://discord.com" }
ListElement { uuid: "6"; text: "Telegram"; url: "https://t.me/status" }
ListElement { uuid: "7"; text: "Custom"; url: "https://status.im" }
ListElement { showcaseKey: "1"; showcasePosition: 0; text: "Twitter"; url: "https://twitter.com/status" }
ListElement { showcaseKey: "2"; showcasePosition: 1; text: "Personal Site"; url: "https://status.im" }
ListElement { showcaseKey: "3"; showcasePosition: 2; text: "Github"; url: "https://github.com" }
ListElement { showcaseKey: "4"; showcasePosition: 3; text: "Youtube"; url: "https://youtube.com" }
ListElement { showcaseKey: "5"; showcasePosition: 4; text: "Discord"; url: "https://discord.com" }
ListElement { showcaseKey: "6"; showcasePosition: 5; text: "Telegram"; url: "https://t.me/status" }
ListElement { showcaseKey: "7"; showcasePosition: 6; text: "Custom"; url: "https://status.im" }
}
ListModel {
id: accountsShowcaseModel
ListElement {
address: "1"
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
order: 0
name: "name"
colorId: "colorId"
emoji: "emoji"
}
ListElement {
address: "2"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
order: 1
name: "name"
colorId: "colorId"
emoji: "emoji"
}
ListElement {
address: "3"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
order: 2
name: "name"
colorId: "colorId"
emoji: "emoji"
}
}
ListModel {
id: accounts13
ListElement { accountAddress: "1" }
ListElement { accountAddress: "3" }
}
ListModel {
id: accounts3
ListElement { accountAddress: "3" }
}
ListModel {
id: accounts123
ListElement { accountAddress: "1" }
ListElement { accountAddress: "2" }
ListElement { accountAddress: "3" }
}
ListModel {
id: accounts14
ListElement { accountAddress: "1" }
ListElement { accountAddress: "4" }
}
ListModel {
id: collectiblesListModel
ListElement { item: 1 }
ListElement { item: 2 }
ListElement { item: 3 }
ListElement { item: 4 }
}
SortFilterProxyModel {
id: collectiblesModel
sourceModel: collectiblesListModel
proxyRoles: [
FastExpressionRole {
name: "ownership"
expression: {
if (index == 0) {
return accounts13
} else if (index == 1) {
return accounts3
} else if (index == 2) {
return accounts123
} else if (index == 3) {
return accounts14
}
return undefined
}
},
FastExpressionRole {
name: "uid"
expression: {
return index + 1
}
},
FastExpressionRole {
name: "name"
expression: {
return "Collectible " + (index + 1)
}
}
ListElement {
uid: 1
name: "Collectible 1"
showcaseKey: "1"
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
showcasePosition: 0
ownership: [
ListElement { accountAddress: "1" },
ListElement { accountAddress: "3" }
]
}
ListModel {
id: collectiblesShowcaseModel
ListElement {
uid: "1"
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
order: 0
name: "name"
backgroundColor: "backgroundColor"
chainId: "chainId"
communityId: "communityId"
collectionName: "collectionName"
imageUrl: "imageUrl"
isLoading: "isLoading"
contractAddress: "contractAddress"
tokenId: "tokenId"
uid: 2
name: "Collectible 2"
showcaseKey: "2"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
showcasePosition: 2
ownership: [
ListElement { accountAddress: "1" },
ListElement { accountAddress: "2" },
ListElement { accountAddress: "3" }
]
}
ListElement {
uid: "2"
uid: 3
name: "Collectible 3"
showcaseKey: "3"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
order: 2
name: "name"
backgroundColor: "backgroundColor"
chainId: "chainId"
communityId: "communityId"
collectionName: "collectionName"
imageUrl: "imageUrl"
isLoading: "isLoading"
contractAddress: "contractAddress"
tokenId: "tokenId"
showcasePosition: 1
ownership: [
ListElement { accountAddress: "3" }
]
}
ListElement {
uid: "3"
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
order: 1
name: "name"
backgroundColor: "backgroundColor"
chainId: "chainId"
communityId: "communityId"
collectionName: "collectionName"
imageUrl: "imageUrl"
isLoading: "isLoading"
contractAddress: "contractAddress"
tokenId: "tokenId"
uid: 4
name: "Collectible 4"
showcaseKey: "4"
showcaseVisibility: Constants.ShowcaseVisibility.NoOne
showcasePosition: 3
ownership: [
ListElement { accountAddress: "1" },
ListElement { accountAddress: "4" }
]
}
}
@ -181,11 +110,7 @@ ColumnLayout {
id: showcaseModels
accountsSourceModel: accountsModel
accountsShowcaseModel: accountsShowcaseModel
collectiblesSourceModel: collectiblesModel
collectiblesShowcaseModel: collectiblesShowcaseModel
socialLinksSourceModel: socialLinksModel
}
@ -223,22 +148,14 @@ ColumnLayout {
Component {
id: collectiblesView
Flickable {
contentWidth: grid.width
contentHeight: grid.height
clip: true
Grid {
RowLayout {
id: grid
rows: 3
columns: 4
spacing: 10
//anchors.fill: parent
flow: Grid.TopToBottom
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Label {
text: "Backend models"
@ -247,22 +164,18 @@ ColumnLayout {
}
GenericListView {
width: 300
height: 300
Layout.fillWidth: true
Layout.fillHeight: true
model: accountsModel
label: "ACCOUNTS MODEL"
}
GenericListView {
width: 300
height: 300
model: accountsShowcaseModel
label: "SHOWCASE MODEL"
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"]
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Label {
text: "Display models"
font.pixelSize: 22
@ -270,8 +183,8 @@ ColumnLayout {
}
GenericListView {
width: 420
height: 300
Layout.fillWidth: true
Layout.fillHeight: true
model: showcaseModels.accountsVisibleModel
label: "IN SHOWCASE"
@ -312,8 +225,8 @@ ColumnLayout {
}
GenericListView {
width: 420
height: 300
Layout.fillWidth: true
Layout.fillHeight: true
model: showcaseModels.accountsHiddenModel
@ -330,30 +243,28 @@ ColumnLayout {
Constants.ShowcaseVisibility.IdVerifiedContacts)
}
}
}
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
Label {
text: "Backend models"
font.pixelSize: 22
padding: 10
}
GenericListView {
width: 270
height: 300
Layout.fillWidth: true
Layout.fillHeight: true
model: collectiblesModel
label: "COLLECTIBLES MODEL"
}
GenericListView {
width: 270
height: 300
model: collectiblesShowcaseModel
label: "SHOWCASE MODEL"
roles: ["uid", "showcaseVisibility", "order"]
}
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
Label {
text: "Display models"
font.pixelSize: 22
@ -361,13 +272,13 @@ ColumnLayout {
}
GenericListView {
width: 610
height: 300
Layout.fillHeight: true
Layout.fillWidth: true
model: showcaseModels.collectiblesVisibleModel
label: "IN SHOWCASE"
movable: true
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"]
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition", "maxVisibility"]
onMoveRequested: {
showcaseModels.changeCollectiblePosition(from, to);
@ -403,8 +314,8 @@ ColumnLayout {
}
GenericListView {
width: 610
height: 300
Layout.fillHeight: true
Layout.fillWidth: true
model: showcaseModels.collectiblesHiddenModel
@ -524,18 +435,28 @@ ColumnLayout {
Button {
text: "SAVE"
//TODO: enable when showcaseModels backend APIs is integrated
enabled: false
onClicked: {
const accountsToBeSaved = showcaseModels.accountsCurrentState()
const collectiblesToBeSaved = showcaseModels.collectiblesCurrentState()
accountsShowcaseModel.clear()
accountsShowcaseModel.append(accountsToBeSaved)
for (let index = 0; index < accountsModel.count; index++) {
let account = accountsModel.get(index)
const showcaseAccount = accountsToBeSaved.find(item => item.showcaseKey === account.showcaseKey)
collectiblesShowcaseModel.clear()
collectiblesShowcaseModel.append(collectiblesToBeSaved)
account.showcasePosition = !!showcaseAccount ? showcaseAccount.showcasePosition : 0
account.showcaseVisibility = !!showcaseAccount ? showcaseAccount.showcaseVisibility : Constants.ShowcaseVisibility.NoOne
accountsModel.set(index, account)
}
for (let index = 0; index < collectiblesModel.count; index++) {
let collectible = collectiblesModel.get(index)
const showcaseCollectible = collectiblesToBeSaved.find(item => item.showcaseKey === collectible.showcaseKey)
collectible.showcasePosition = !!showcaseCollectible ? showcaseCollectible.showcasePosition : 0
collectible.showcaseVisibility = !!showcaseCollectible ? showcaseCollectible.showcaseVisibility : Constants.ShowcaseVisibility.NoOne
collectiblesModel.set(index, collectible)
}
}
Layout.alignment: Qt.AlignHCenter

View File

@ -134,21 +134,22 @@ StatusSectionLayout {
active: false
asynchronous: true
sourceComponent: MyProfileView {
id: myProfileView
implicitWidth: parent.width
implicitHeight: parent.height
walletAssetsStore: root.walletAssetsStore
currencyStore: root.currencyStore
walletStore: root.store.walletStore
profileStore: root.store.profileStore
privacyStore: root.store.privacyStore
contactsStore: root.store.contactsStore
networkConnectionStore: root.networkConnectionStore
communitiesModel: root.store.communitiesList
sendToAccountEnabled: root.networkConnectionStore.sendBuyBridgeEnabled
sectionTitle: root.store.getNameForSubsection(Constants.settingsSubsection.profile)
contentWidth: d.contentWidth
sideBySidePreview: d.sideBySidePreviewAvailable
toastClashesWithDirtyBubble: d.toastClashesWithDirtyBubble
communitiesShowcaseModel: root.store.ownShowcaseCommunitiesModel
accountsShowcaseModel: root.store.ownShowcaseAccountsModel
collectiblesShowcaseModel: root.store.ownShowcaseCollectiblesModel
socialLinksShowcaseModel: root.store.ownShowcaseSocialLinksModel
}
}
@ -434,13 +435,7 @@ StatusSectionLayout {
showRightPanel: d.isProfilePanelActive && d.sideBySidePreviewAvailable
rightPanelWidth: d.rightPanelWidth
rightPanel: MyProfilePreview {
profileStore: root.store.profileStore
contactsStore: root.store.contactsStore
networkConnectionStore: root.networkConnectionStore
dirtyValues: d.isProfilePanelActive ? profileContainer.currentItem.dirtyValues : ({})
dirty: d.isProfilePanelActive ? profileContainer.currentItem.dirty : false
}
rightPanel: d.isProfilePanelActive ? profileContainer.currentItem.sideBySidePreviewComponent : null
Connections {
target: root.store.keycardStore.keycardModule

View File

@ -18,16 +18,7 @@ import utils 1.0
QObject {
id: root
property alias sourceModel: joined.leftModel
property alias showcaseModel: joined.rightModel
/**
* True if the showcase model is in single model mode, i.e. the showcase
* model is part of the source model. False if the showcase model is a
* separate model.
*/
property bool singleModelMode: !joined.rightModel
property alias sourceModel: writable.sourceModel
/**
* Model holding elements from 'sourceModel' intended to be visible in the
* showcase, sorted by 'position' role. Includes roles from both input models.
@ -95,7 +86,6 @@ QObject {
// internals, debug purpose only
readonly property alias writable_: writable
readonly property alias joined_: joined
component HiddenFilter: AnyOf {
UndefinedFilter {
@ -108,16 +98,9 @@ QObject {
}
}
LeftJoinModel {
id: joined
joinRole: "showcaseKey"
}
VisibilityAndPositionDirtyStateModel {
id: writable
sourceModel: root.singleModelMode ? root.sourceModel : joined
visibilityHidden: Constants.ShowcaseVisibility.NoOne
}

View File

@ -13,9 +13,10 @@ QObject {
// Communities input models
property alias communitiesSourceModel: communitySFPM.sourceModel
property alias communitiesShowcaseModel: communityJoinedModel.leftModel
// adapted models
readonly property alias adaptedCommunitiesSourceModel: communitySFPM
readonly property alias adaptedCommunitiesSourceModel: communityJoinedModel
// Accounts input models
property alias accountsSourceModel: accountsSFPM.sourceModel
@ -23,11 +24,15 @@ QObject {
// adapted models
readonly property alias adaptedAccountsSourceModel: accountsSFPM
//helpers
property var isAddressSaved: (address) => false
// Collectibles input models
property alias collectiblesSourceModel: collectiblesSFPM.sourceModel
property alias collectiblesShowcaseModel: collectiblesJoinedModel.leftModel
// adapted models
readonly property alias adaptedCollectiblesSourceModel: collectiblesSFPM
readonly property alias adaptedCollectiblesSourceModel: collectiblesJoinedModel
// Social links input models
property alias socialLinksSourceModel: socialLinksSFPM.sourceModel
@ -35,6 +40,12 @@ QObject {
// adapted models
readonly property alias adaptedSocialLinksSourceModel: socialLinksSFPM
component JoinModel: LeftJoinModel {
joinRole: "showcaseKey"
}
// Communities proxies
SortFilterProxyModel {
id: communitySFPM
proxyRoles: [
@ -42,10 +53,20 @@ QObject {
name: "showcaseKey"
expression: model.id
expectedRoles: ["id"]
},
FastExpressionRole {
name: "membersCount"
expression: model.members.count
expectedRoles: ["members"]
}
]
}
JoinModel {
id: communityJoinedModel
rightModel: communitySFPM
}
SortFilterProxyModel {
id: accountsSFPM
proxyRoles: [
@ -53,10 +74,17 @@ QObject {
name: "showcaseKey"
expression: model.address
expectedRoles: ["address"]
},
FastExpressionRole {
name: "saved"
expression: root.isAddressSaved(model.address)
expectedRoles: ["address"]
}
]
}
// Collectibles proxies
SortFilterProxyModel {
id: collectiblesSFPM
proxyRoles: [
@ -68,6 +96,13 @@ QObject {
]
}
JoinModel {
id: collectiblesJoinedModel
rightModel: collectiblesSFPM
}
// Social links proxies
SortFilterProxyModel {
id: socialLinksSFPM
proxyRoles: [

View File

@ -23,8 +23,7 @@ QObject {
// COMMUNITIES
// Input models
property alias communitiesSourceModel: modelAdapter.communitiesSourceModel
property alias communitiesShowcaseModel: communities.showcaseModel
property alias communitiesSourceModel: communities.sourceModel
property string communitiesSearcherText
// Output models
@ -47,8 +46,7 @@ QObject {
// ACCOUNTS
// Input models
property alias accountsSourceModel: modelAdapter.accountsSourceModel
property alias accountsShowcaseModel: accounts.showcaseModel
property alias accountsSourceModel: accounts.sourceModel
property string accountsSearcherText
// Output models
@ -78,8 +76,7 @@ QObject {
// COLLECTIBLES
// Input models
property alias collectiblesSourceModel: modelAdapter.collectiblesSourceModel
property alias collectiblesShowcaseModel: collectibles.showcaseModel
property alias collectiblesSourceModel: collectiblesFilter.sourceModel
property string collectiblesSearcherText
// Output models
@ -102,7 +99,7 @@ QObject {
// SOCIAL LINKS
// Input models
property alias socialLinksSourceModel: modelAdapter.socialLinksSourceModel
property alias socialLinksSourceModel: socialLinks.sourceModel
// Output models
readonly property alias socialLinksVisibleModel: socialLinks.visibleModel
@ -139,10 +136,6 @@ QObject {
})
}
ProfileShowcaseModelAdapter {
id: modelAdapter
}
ProfileShowcaseDirtyState {
id: communities
@ -150,7 +143,6 @@ QObject {
return ProfileUtils.getMemberRoleText(memberRole)
}
sourceModel: modelAdapter.adaptedCommunitiesSourceModel
searcherFilter: FastExpressionFilter {
expression: {
root.communitiesSearcherText
@ -164,7 +156,6 @@ QObject {
ProfileShowcaseDirtyState {
id: accounts
sourceModel: modelAdapter.adaptedAccountsSourceModel
searcherFilter: FastExpressionFilter {
expression: {
root.accountsSearcherText
@ -194,9 +185,6 @@ QObject {
ProfileShowcaseDirtyState {
id: socialLinks
sourceModel: modelAdapter.adaptedSocialLinksSourceModel
singleModelMode: true
}
@ -204,7 +192,6 @@ QObject {
id: collectiblesFilter
delayed: true
sourceModel: modelAdapter.adaptedCollectiblesSourceModel
proxyRoles: FastExpressionRole {
name: "maxVisibility"

View File

@ -0,0 +1,127 @@
import QtQml 2.15
import QtQml.Models 2.15
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
import SortFilterProxyModel 0.2
import utils 1.0
QObject {
id: root
// Communities input models
property alias communitiesSourceModel: communitySFPM.sourceModel
property alias communitiesShowcaseModel: communityJoinedModel.rightModel
// adapted models
readonly property alias adaptedCommunitiesSourceModel: communityJoinedModel
// Accounts input models
property alias accountsSourceModel: accountsSFPM.sourceModel
property alias accountsShowcaseModel: accountsJoinedModel.rightModel
// adapted models
readonly property alias adaptedAccountsSourceModel: accountsJoinedModel
// Collectibles input models
property alias collectiblesSourceModel: collectiblesSFPM.sourceModel
property alias collectiblesShowcaseModel: collectiblesJoinedModel.rightModel
// adapted models
readonly property alias adaptedCollectiblesSourceModel: collectiblesJoinedModel
// Social links input models
property alias socialLinksSourceModel: socialLinksSFPM.sourceModel
// adapted models
readonly property alias adaptedSocialLinksSourceModel: socialLinksSFPM
component JoinModel: LeftJoinModel {
joinRole: "showcaseKey"
}
//
// Communities proxies
//
SortFilterProxyModel {
id: communitySFPM
proxyRoles: [
FastExpressionRole {
name: "showcaseKey"
expression: model.id
expectedRoles: ["id"]
},
FastExpressionRole {
name: "membersCount"
expression: model.members.count
expectedRoles: ["members"]
}
]
}
JoinModel {
id: communityJoinedModel
leftModel: communitySFPM
}
//
// Accounts proxies
//
SortFilterProxyModel {
id: accountsSFPM
proxyRoles: [
FastExpressionRole {
name: "showcaseKey"
expression: model.address
expectedRoles: ["address"]
}
]
}
JoinModel {
id: accountsJoinedModel
leftModel: accountsSFPM
}
//
// Collectibles proxies
//
SortFilterProxyModel {
id: collectiblesSFPM
proxyRoles: [
FastExpressionRole {
name: "showcaseKey"
expression: model.uid
expectedRoles: ["uid"]
}
]
}
JoinModel {
id: collectiblesJoinedModel
leftModel: collectiblesSFPM
}
//
// Social links proxies
//
SortFilterProxyModel {
id: socialLinksSFPM
proxyRoles: [
FastExpressionRole {
name: "showcaseKey"
expression: model.url
expectedRoles: ["url"]
},
FastExpressionRole {
name: "showcaseVisibility"
expression: getShowcaseVisibility()
function getShowcaseVisibility() {
return Constants.ShowcaseVisibility.Everyone
}
}
]
}
}

View File

@ -1,4 +1,5 @@
ProfileShowcaseDirtyState 1.0 ProfileShowcaseDirtyState.qml
ProfileShowcaseModelAdapter 1.0 ProfileShowcaseModelAdapter.qml
ProfileShowcaseSettingsModelAdapter 1.0 ProfileShowcaseSettingsModelAdapter.qml
ProfileShowcaseModels 1.0 ProfileShowcaseModels.qml
VisibilityAndPositionDirtyStateModel 1.0 VisibilityAndPositionDirtyStateModel.qml

View File

@ -16,6 +16,23 @@ QtObject {
property var receivedContactRequestsModel: contactsModule.receivedContactRequestsModel
property var sentContactRequestsModel: contactsModule.sentContactRequestsModel
readonly property var showcasePublicKey: contactsModule.showcasePublicKey
// Showcase models for a contact with showcasePublicKey
readonly property var showcaseContactCommunitiesModel: contactsModule.showcaseContactCommunitiesModel
readonly property var showcaseContactAccountsModel: contactsModule.showcaseContactAccountsModel
readonly property var showcaseContactCollectiblesModel: contactsModule.showcaseContactCollectiblesModel
readonly property var showcaseContactAssetsModel: contactsModule.showcaseContactAssetsModel
readonly property var showcaseContactSocialLinksModel: contactsModule.showcaseContactSocialLinksModel
// Support models for showcase for a contact with showcasePublicKey
readonly property var showcaseCollectiblesModel: contactsModule.showcaseCollectiblesModel
// Sets showcasePublicKey and updates showcase models with corresponding data
function requestProfileShowcase(publicKey) {
root.contactsModule.requestProfileShowcase(publicKey)
}
// Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
// property var receivedButRejectedContactRequestsModel: contactsModule.receivedButRejectedContactRequestsModel
// property var sentButRejectedContactRequestsModel: contactsModule.sentButRejectedContactRequestsModel

View File

@ -2,6 +2,10 @@ import QtQuick 2.13
import utils 1.0
import AppLayouts.Chat.stores 1.0
import AppLayouts.Communities.stores 1.0
import AppLayouts.Profile.helpers 1.0
import StatusQ.Core.Utils 0.1
import SortFilterProxyModel 0.2
@ -154,6 +158,51 @@ QtObject {
}
}
readonly property alias ownShowcaseCommunitiesModel: ownShowcaseModels.adaptedCommunitiesSourceModel
readonly property alias ownShowcaseAccountsModel: ownShowcaseModels.adaptedAccountsSourceModel
readonly property alias ownShowcaseCollectiblesModel: ownShowcaseModels.adaptedCollectiblesSourceModel
readonly property alias ownShowcaseSocialLinksModel: ownShowcaseModels.adaptedSocialLinksSourceModel
readonly property alias contactShowcaseCommunitiesModel: contactShowcaseModels.adaptedCommunitiesSourceModel
readonly property alias contactShowcaseAccountsModel: contactShowcaseModels.adaptedAccountsSourceModel
readonly property alias contactShowcaseCollectiblesModel: contactShowcaseModels.adaptedCollectiblesSourceModel
readonly property alias contactShowcaseSocialLinksModel: contactShowcaseModels.adaptedSocialLinksSourceModel
function requestContactShowcase(address) {
root.contactsStore.requestProfileShowcase(address)
}
function requestOwnShowcase() {
root.profileStore.requestProfileShowcasePreferences()
}
readonly property QObject d: QObject {
ProfileShowcaseSettingsModelAdapter {
id: ownShowcaseModels
communitiesSourceModel: root.communitiesList
communitiesShowcaseModel: root.profileStore.showcasePreferencesCommunitiesModel
accountsSourceModel: root.walletStore.ownAccounts
accountsShowcaseModel: root.profileStore.showcasePreferencesAccountsModel
collectiblesSourceModel: root.walletStore.collectibles
collectiblesShowcaseModel: root.profileStore.showcasePreferencesCollectiblesModel
socialLinksSourceModel: root.profileStore.showcasePreferencesSocialLinksModel
}
ProfileShowcaseModelAdapter {
id: contactShowcaseModels
communitiesSourceModel: root.communitiesModuleInst.model
communitiesShowcaseModel: root.contactsStore.showcaseContactCommunitiesModel
accountsSourceModel: root.contactsStore.showcaseContactAccountsModel
collectiblesSourceModel: root.contactsStore.showcaseCollectiblesModel
collectiblesShowcaseModel: root.contactsStore.showcaseContactCollectiblesModel
socialLinksSourceModel: root.contactsStore.showcaseContactSocialLinksModel
isAddressSaved: (address) => {
return false
}
}
}
function importCommunity(communityKey) {
root.communitiesModuleInst.importCommunity(communityKey);
}

View File

@ -29,20 +29,12 @@ QtObject {
readonly property bool isWalletEnabled: Global.appIsReady? mainModule.sectionsModel.getItemEnabledBySectionType(Constants.appSection.wallet) : true
readonly property var collectiblesModel: profileModule.collectiblesModel
readonly property var showcasePreferencesCommunitiesModel: profileModule.showcasePreferencesCommunitiesModel
readonly property var showcasePreferencesAccountsModel: profileModule.showcasePreferencesAccountsModel
readonly property var showcasePreferencesCollectiblesModel: profileModule.showcasePreferencesCollectiblesModel
readonly property var showcasePreferencesAssetsModel: profileModule.showcasePreferencesAssetsModel
readonly property var showcasePreferencesSocialLinksModel: profileModule.showcasePreferencesSocialLinksModel
// TODO: remove old models
readonly property var profileShowcaseCommunitiesModel: profileModule.profileShowcaseCommunitiesModel
readonly property var profileShowcaseAccountsModel: profileModule.profileShowcaseAccountsModel
readonly property var profileShowcaseCollectiblesModel: profileModule.profileShowcaseCollectiblesModel
readonly property var profileShowcaseAssetsModel: profileModule.profileShowcaseAssetsModel
readonly property bool isFirstShowcaseInteraction: localAccountSettings.isFirstShowcaseInteraction
property var details: Utils.getContactDetailsAsJson(pubkey)
@ -118,10 +110,6 @@ QtObject {
root.profileModule.requestProfileShowcasePreferences()
}
function requestProfileShowcase(publicKey) {
root.profileModule.requestProfileShowcase(publicKey)
}
function setIsFirstShowcaseInteraction() {
root.profileModule.setIsFirstShowcaseInteraction()
}

View File

@ -28,27 +28,24 @@ import AppLayouts.Wallet.stores 1.0
SettingsContentBase {
id: root
property WalletStore walletStore
property ProfileStore profileStore
property PrivacyStore privacyStore
property ContactsStore contactsStore
property NetworkConnectionStore networkConnectionStore
required property WalletAssetsStore walletAssetsStore
required property CurrenciesStore currencyStore
property var communitiesModel
property bool sendToAccountEnabled: false
property alias communitiesShowcaseModel: showcaseModels.communitiesSourceModel
property alias accountsShowcaseModel: showcaseModels.accountsSourceModel
property alias collectiblesShowcaseModel: showcaseModels.collectiblesSourceModel
property alias socialLinksShowcaseModel: showcaseModels.socialLinksSourceModel
property bool sideBySidePreview
property bool toastClashesWithDirtyBubble
readonly property alias sideBySidePreviewComponent: myProfilePreviewComponent
property QtObject dirtyValues: QtObject {
property string displayName: descriptionPanel.displayName.text
property string bio: descriptionPanel.bio.text
property url profileLargeImage: profileHeader.previewIcon
property var socialLinks: priv.showcaseModels.socialLinksVisibleModel
property var communitiesModel: priv.showcaseModels.communitiesVisibleModel
property var accountsModel: priv.showcaseModels.accountsVisibleModel
property var collectiblesModel: priv.showcaseModels.collectiblesVisibleModel
readonly property QtObject liveValues: QtObject {
readonly property string displayName: descriptionPanel.displayName.text
readonly property string bio: descriptionPanel.bio.text
readonly property url profileLargeImage: profileHeader.previewIcon
}
enum TabIndex {
@ -126,7 +123,7 @@ SettingsContentBase {
onVisibleChanged: if (visible) profileStore.requestProfileShowcasePreferences()
Component.onCompleted: profileStore.requestProfileShowcasePreferences()
readonly property var priv: QtObject {
property QObject priv: QObject {
id: priv
readonly property bool hasAnyProfileShowcaseChanges: showcaseModels.dirty
@ -137,19 +134,11 @@ SettingsContentBase {
profileHeader.icon !== profileStore.profileLargeImage
property ProfileShowcaseModels showcaseModels: ProfileShowcaseModels {
communitiesSourceModel: root.communitiesModel
communitiesShowcaseModel: root.profileStore.showcasePreferencesCommunitiesModel
id: showcaseModels
communitiesSearcherText: profileShowcaseCommunitiesPanel.searcherText
accountsSourceModel: root.walletStore.ownAccounts
accountsShowcaseModel: root.profileStore.showcasePreferencesAccountsModel
accountsSearcherText: profileShowcaseAccountsPanel.searcherText
collectiblesSourceModel: root.profileStore.collectiblesModel
collectiblesShowcaseModel: root.profileStore.showcasePreferencesCollectiblesModel
collectiblesSearcherText: profileShowcaseCollectiblesPanel.searcherText
socialLinksSourceModel: root.profileStore.showcasePreferencesSocialLinksModel
}
// Used to track which are the expected backend responses (they can be 0, 1 or 2) depending on the dirty changes
@ -363,8 +352,8 @@ SettingsContentBase {
// id: profileShowcaseAssetsPanel
// baseModel: root.walletAssetsStore.groupedAccountAssetsModel // TODO: instantiate an assets model in profile module
// showcaseModel: root.profileStore.profileShowcaseAssetsModel
// addAccountsButtonVisible: root.profileStore.profileShowcaseAccountsModel.hiddenCount > 0
// showcaseModel: root.contactsStore.showcaseContactAssetsModel
// addAccountsButtonVisible: root.contactsStore.showcaseContactAccountsModel.hiddenCount > 0
// formatCurrencyAmount: function(amount, symbol) {
// return root.currencyStore.formatCurrencyAmount(amount, symbol)
// }
@ -401,10 +390,33 @@ SettingsContentBase {
publicKey: root.contactsStore.myPublicKey
profileStore: root.profileStore
contactsStore: root.contactsStore
networkConnectionStore: root.networkConnectionStore
sendToAccountEnabled: root.sendToAccountEnabled
onClosed: destroy()
dirtyValues: root.dirtyValues
dirtyValues: root.liveValues
dirty: root.dirty
showcaseCommunitiesModel: priv.showcaseModels.communitiesVisibleModel
showcaseAccountsModel: priv.showcaseModels.accountsVisibleModel
showcaseCollectiblesModel: priv.showcaseModels.collectiblesVisibleModel
showcaseSocialLinksModel: priv.showcaseModels.socialLinksVisibleModel
//showcaseAssetsModel: priv.showcaseModels.assetsVisibleModel
}
}
Component {
id: myProfilePreviewComponent
MyProfilePreview {
profileStore: root.profileStore
contactsStore: root.contactsStore
sendToAccountEnabled: root.sendToAccountEnabled
dirtyValues: root.liveValues
dirty: root.dirty
showcaseCommunitiesModel: priv.showcaseModels.communitiesVisibleModel
showcaseAccountsModel: priv.showcaseModels.accountsVisibleModel
showcaseCollectiblesModel: priv.showcaseModels.collectiblesVisibleModel
showcaseSocialLinksModel: priv.showcaseModels.socialLinksVisibleModel
//showcaseAssetsModel: priv.showcaseModels.assetsVisibleModel
}
}

View File

@ -8,10 +8,17 @@ import StatusQ.Core.Theme 0.1
Item {
property alias profileStore: profilePreview.profileStore
property alias contactsStore: profilePreview.contactsStore
property alias networkConnectionStore: profilePreview.networkConnectionStore
property alias sendToAccountEnabled: profilePreview.sendToAccountEnabled
property alias dirtyValues: profilePreview.dirtyValues
property alias dirty: profilePreview.dirty
property alias showcaseCommunitiesModel: profilePreview.showcaseCommunitiesModel
property alias showcaseAccountsModel: profilePreview.showcaseAccountsModel
property alias showcaseCollectiblesModel: profilePreview.showcaseCollectiblesModel
property alias showcaseSocialLinksModel: profilePreview.showcaseSocialLinksModel
property alias showcaseAssetsModel: profilePreview.showcaseAssetsModel
implicitHeight: profilePreview.implicitHeight
+ profilePreview.anchors.topMargin
+ profilePreview.anchors.bottomMargin

View File

@ -173,7 +173,7 @@ StatusModal {
mainModule.resolveENS(name, d.uuid)
});
property var profileModuleInst: SharedStores.RootStore.profileSectionModuleInst.profileModule
property var contactsModuleInst: SharedStores.RootStore.profileSectionModuleInst.contactsModule
/// Ensures that the \c root.address and \c root.chainShortNames are not reset when the initial text is set
property bool initialized: false
@ -215,7 +215,7 @@ StatusModal {
d.checkingContactsAddressInProgress = true
d.contactsWithSameAddress = 0
d.profileModuleInst.fetchProfileShowcaseAccountsByAddress(d.address)
d.contactsModuleInst.fetchProfileShowcaseAccountsByAddress(d.address)
return
}
@ -294,7 +294,7 @@ StatusModal {
}
Connections {
target: d.profileModuleInst
target: d.contactsModuleInst
function onProfileShowcaseAccountsByAddressFetched(accounts: string) {
d.cardsModel.clear()
d.checkingContactsAddressInProgress = false

View File

@ -535,10 +535,22 @@ QtObject {
id: profilePopupComponent
ProfileDialog {
id: profilePopup
property bool isCurrentUser: publicKey === rootStore.profileSectionStore.profileStore.pubkey
profileStore: rootStore.profileSectionStore.profileStore
contactsStore: rootStore.profileSectionStore.contactsStore
networkConnectionStore: root.networkConnectionStore
sendToAccountEnabled: root.networkConnectionStore.sendBuyBridgeEnabled
showcaseCommunitiesModel: isCurrentUser ? rootStore.profileSectionStore.ownShowcaseCommunitiesModel : rootStore.profileSectionStore.contactShowcaseCommunitiesModel
showcaseAccountsModel: isCurrentUser ? rootStore.profileSectionStore.ownShowcaseAccountsModel : rootStore.profileSectionStore.contactShowcaseAccountsModel
showcaseCollectiblesModel: isCurrentUser ? rootStore.profileSectionStore.ownShowcaseCollectiblesModel : rootStore.profileSectionStore.contactShowcaseCollectiblesModel
showcaseSocialLinksModel: isCurrentUser ? rootStore.profileSectionStore.ownShowcaseSocialLinksModel : rootStore.profileSectionStore.contactShowcaseSocialLinksModel
onOpened: {
isCurrentUser ? rootStore.profileSectionStore.requestOwnShowcase()
: rootStore.profileSectionStore.requestContactShowcase(publicKey)
}
onClosed: {
if (profilePopup.parentPopup) {
profilePopup.parentPopup.close()

View File

@ -9,14 +9,20 @@ StatusDialog {
property var parentPopup
property string publicKey
property alias publicKey: profileView.publicKey
property var profileStore
property var contactsStore
property var networkConnectionStore
property alias profileStore: profileView.profileStore
property alias contactsStore: profileView.contactsStore
property alias sendToAccountEnabled: profileView.sendToAccountEnabled
property var dirtyValues: ({})
property bool dirty: false
property alias showcaseCommunitiesModel: profileView.showcaseCommunitiesModel
property alias showcaseAccountsModel: profileView.showcaseAccountsModel
property alias showcaseCollectiblesModel: profileView.showcaseCollectiblesModel
property alias showcaseSocialLinksModel: profileView.showcaseSocialLinksModel
property alias showcaseAssetsModel: profileView.showcaseAssetsModel
property alias dirtyValues: profileView.dirtyValues
property alias dirty: profileView.dirty
width: 640
padding: 0
@ -25,12 +31,8 @@ StatusDialog {
footer: null
contentItem: ProfileDialogView {
publicKey: root.publicKey
profileStore: root.profileStore
contactsStore: root.contactsStore
networkConnectionStore: root.networkConnectionStore
id: profileView
onCloseRequested: root.close()
dirtyValues: root.dirtyValues
dirty: root.dirty
}
}

View File

@ -32,12 +32,18 @@ Pane {
property var profileStore
property var contactsStore
property var walletStore: WalletNS.RootStore
property var networkConnectionStore
property alias sendToAccountEnabled: showcaseView.sendToAccountEnabled
property var dirtyValues: ({})
property bool dirty: false
property var showcaseCommunitiesModel
property var showcaseAccountsModel
property var showcaseCollectiblesModel
property var showcaseSocialLinksModel
property var showcaseAssetsModel
signal closeRequested()
padding: 0
@ -599,22 +605,24 @@ Pane {
// Profile Showcase
ProfileShowcaseView {
id: showcaseView
Layout.fillWidth: true
Layout.topMargin: -column.spacing
Layout.preferredHeight: 300
currentTabIndex: showcaseTabBar.currentIndex
publicKey: root.publicKey
mainDisplayName: d.mainDisplayName
readOnly: root.readOnly
profileStore: root.profileStore
walletStore: root.walletStore
networkConnectionStore: root.networkConnectionStore
livePreview: root.dirty
livePreviewValues: root.dirtyValues
communitiesModel: root.showcaseCommunitiesModel
accountsModel: root.showcaseAccountsModel
collectiblesModel: root.showcaseCollectiblesModel
// socialLinksModel: root.showcaseSocialLinksModel
// assetsModel: root.showcaseAssetsModel
onCloseRequested: root.closeRequested()
onCopyToClipboard: root.profileStore.copyToClipboard(text)
}
}
}

View File

@ -20,19 +20,18 @@ Control {
property alias currentTabIndex: stackLayout.currentIndex
property string publicKey
property string mainDisplayName
property bool readOnly
property var profileStore
property var walletStore
property var networkConnectionStore
property alias communitiesModel: communitiesProxyModel.sourceModel
property alias accountsModel: accountsProxyModel.sourceModel
property alias collectiblesModel: collectiblesProxyModel.sourceModel
property alias assetsModel: assetsProxyModel.sourceModel
property alias socialLinksModel: socialLinksProxyModel.sourceModel
property bool livePreview: false
property var livePreviewValues: ({})
required property string mainDisplayName
required property bool readOnly
required property bool sendToAccountEnabled
signal closeRequested()
onVisibleChanged: if (visible && !livePreview) profileStore.requestProfileShowcase(publicKey)
signal copyToClipboard(string text)
horizontalPadding: readOnly ? 20 : 40 // smaller in settings/preview
topPadding: Style.current.bigPadding
@ -41,70 +40,45 @@ Control {
id: d
readonly property string copyLiteral: qsTr("Copy")
readonly property var timer: Timer {
id: timer
}
readonly property var communitiesModel: root.livePreview ? liveCommunitiesModel
: communitiesStoreModel
readonly property var accountsModel: root.livePreview ? root.livePreviewValues.accountsModel
: accountsStoreModel
readonly property var collectiblesModel: root.livePreview ? root.livePreviewValues.collectiblesModel
: collectiblesStoreModel
// TODO: add dirty values to the livePreviewValues once assets are supported
// readonly property assetsModel: root.livePreview ? root.livePreviewValues.assetsModel
// : root.profileStore.profileShowcaseAssetsModel
readonly property var assetsModel: root.profileStore.profileShowcaseAssetsModel
readonly property var socialLinksModel: root.livePreview ? root.livePreviewValues.socialLinksModel
: root.profileStore.socialLinksModel
SortFilterProxyModel {
id: liveCommunitiesModel
sourceModel: root.livePreviewValues.communitiesModel
proxyRoles: [
FastExpressionRole {
name: "membersCount"
expression: model.members.count
expectedRoles: ["members"]
component PositionSFPM: SortFilterProxyModel {
sorters: [
RoleSorter {
roleName: "showcasePosition"
}
]
filters: AnyOf {
inverted: true
UndefinedFilter {
roleName: "showcaseVisibility"
}
SortFilterProxyModel {
id: communitiesStoreModel
sourceModel: root.profileStore.profileShowcaseCommunitiesModel
filters: [
ValueFilter {
roleName: "showcaseVisibility"
value: Constants.ShowcaseVisibility.NoOne
inverted: true
},
ValueFilter {
roleName: "loading"
value: false
}
]
}
SortFilterProxyModel {
id: accountsStoreModel
sourceModel: root.profileStore.profileShowcaseAccountsModel
filters: ValueFilter {
roleName: "showcaseVisibility"
value: Constants.ShowcaseVisibility.NoOne
inverted: true
}
}
SortFilterProxyModel {
id: collectiblesStoreModel
sourceModel: root.profileStore.profileShowcaseCollectiblesModel
filters: ValueFilter {
roleName: "showcaseVisibility"
value: Constants.ShowcaseVisibility.NoOne
inverted: true
PositionSFPM {
id: communitiesProxyModel
}
PositionSFPM {
id: accountsProxyModel
}
PositionSFPM {
id: collectiblesProxyModel
}
PositionSFPM {
id: assetsProxyModel
}
PositionSFPM {
id: socialLinksProxyModel
}
background: StatusDialogBackground {
@ -139,31 +113,33 @@ Control {
Layout.fillWidth: true
Layout.fillHeight: true
id: communitiesView
model: communitiesProxyModel
rightMargin: Style.current.halfPadding
cellWidth: (width-rightMargin)/2
cellHeight: cellWidth/2
visible: count
model: d.communitiesModel
ScrollBar.vertical: StatusScrollBar { }
delegate: StatusListItem { // TODO custom delegate
width: GridView.view.cellWidth - Style.current.smallPadding
height: GridView.view.cellHeight - Style.current.smallPadding
title: model.name
title: model.name ?? ""
statusListItemTitle.font.pixelSize: 17
statusListItemTitle.font.bold: true
subTitle: model.description
tertiaryTitle: qsTr("%n member(s)", "", model.membersCount)
asset.name: model.image ?? model.name
subTitle: model.description ?? ""
tertiaryTitle: qsTr("%n member(s)", "", model.membersCount ?? 0)
asset.name: model.image ?? model.name ?? ""
asset.isImage: asset.name.startsWith(Constants.dataImagePrefix)
asset.isLetterIdenticon: !model.image
asset.color: model.color
asset.color: model.color ?? ""
asset.width: 40
asset.height: 40
border.width: 1
border.color: Theme.palette.baseColor2
loading: !model.id
components: [
StatusIcon {
visible: model.memberRole === Constants.memberRole.owner ||
visible: !!model.memberRole &&
model.memberRole === Constants.memberRole.owner ||
model.memberRole === Constants.memberRole.admin ||
model.memberRole === Constants.memberRole.tokenMaster
anchors.verticalCenter: parent.verticalCenter
@ -172,7 +148,7 @@ Control {
}
]
onClicked: {
if (root.readOnly)
if (root.readOnly || loading)
return
root.closeRequested()
Global.switchToCommunity(model.id)
@ -198,24 +174,12 @@ Control {
Layout.fillWidth: true
Layout.fillHeight: true
id: accountsView
model: accountsProxyModel
spacing: Style.current.halfPadding
visible: count
model: d.accountsModel
delegate: StatusListItem {
id: accountDelegate
property bool saved: {
let savedAddress = root.walletStore.getSavedAddress(model.address)
if (savedAddress.name !== "")
return true
if (!!root.walletStore.lastCreatedSavedAddress) {
if (root.walletStore.lastCreatedSavedAddress.address.toLowerCase() === model.address.toLowerCase()) {
return !!root.walletStore.lastCreatedSavedAddress.error
}
}
return false
}
border.width: 1
border.color: Theme.palette.baseColor2
width: ListView.view.width
@ -237,8 +201,8 @@ Control {
StatusFlatButton {
anchors.verticalCenter: parent.verticalCenter
size: StatusBaseButton.Size.Small
enabled: !accountDelegate.saved
text: accountDelegate.saved ? qsTr("Address saved") : qsTr("Save Address")
enabled: !model.saved
text: model.saved ? qsTr("Address saved") : qsTr("Save Address")
onClicked: {
// From here, we should just run add saved address popup
Global.openAddEditSavedAddressesPopup({
@ -252,7 +216,7 @@ Control {
type: StatusFlatRoundButton.Type.Secondary
icon.name: "send"
tooltip.text: qsTr("Send")
enabled: root.networkConnectionStore.sendBuyBridgeEnabled
enabled: root.sendToAccountEnabled
onClicked: {
Global.openSendModal(model.address)
}
@ -264,10 +228,8 @@ Control {
tooltip.text: d.copyLiteral
onClicked: {
tooltip.text = qsTr("Copied")
root.profileStore.copyToClipboard(model.address)
d.timer.setTimeout(function() {
tooltip.text = d.copyLiteral
}, 2000);
root.copyToClipboard(model.address)
Backpressure.setTimeout(this, 2000, () => tooltip.text = d.copyLiteral)
}
}
]
@ -292,12 +254,11 @@ Control {
Layout.fillWidth: true
Layout.fillHeight: true
id: collectiblesView
model: collectiblesProxyModel
rightMargin: Style.current.halfPadding
cellWidth: (width-rightMargin)/4
cellHeight: cellWidth
visible: count
// TODO Issue #11637: Dedicated controller for user's list of collectibles (no watch-only entries)
model: d.collectiblesModel
ScrollBar.vertical: StatusScrollBar { }
delegate: StatusRoundedImage {
width: GridView.view.cellWidth - Style.current.smallPadding
@ -306,7 +267,8 @@ Control {
border.color: Theme.palette.directColor7
color: !!model.backgroundColor ? model.backgroundColor : "transparent"
radius: Style.current.radius
showLoadingIndicator: model.isLoading
showLoadingIndicator: true
isLoading: image.isLoading || !model.imageUrl
image.fillMode: Image.PreserveAspectCrop
image.source: model.imageUrl ?? ""
@ -379,18 +341,11 @@ Control {
Layout.fillWidth: true
Layout.fillHeight: true
id: assetsView
model: assetsProxyModel
rightMargin: Style.current.halfPadding
cellWidth: (width-rightMargin)/3
cellHeight: cellWidth/2.5
visible: count
model: SortFilterProxyModel {
sourceModel: d.assetsModel
filters: ValueFilter {
roleName: "showcaseVisibility"
value: Constants.ShowcaseVisibility.NoOne
inverted: true
}
}
ScrollBar.vertical: StatusScrollBar { }
delegate: StatusListItem {
readonly property double changePct24hour: model.changePct24hour ?? 0

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit caf3de119055a4169c1efa83d0a42c11221aa014
Subproject commit 30e143ca40b68423edff1a54091c339ebc3694dc