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/settings/dto/[settings]
import ../../../../app_service/service/saved_address/dto as saved_address_dto import ../../../../app_service/service/saved_address/dto as saved_address_dto
import ../../../../app_service/service/wallet_account/dto/[keypair_dto] import ../../../../app_service/service/wallet_account/dto/[keypair_dto]
import ../../../../app_service/service/profile/dto/[profile_showcase]
type MessageSignal* = ref object of Signal type MessageSignal* = ref object of Signal
bookmarks*: seq[BookmarkDto] bookmarks*: seq[BookmarkDto]
@ -40,7 +39,7 @@ type MessageSignal* = ref object of Signal
keypairs*: seq[KeypairDto] keypairs*: seq[KeypairDto]
watchOnlyAccounts*: seq[WalletAccountDto] watchOnlyAccounts*: seq[WalletAccountDto]
accountsPositions*: seq[WalletAccountDto] accountsPositions*: seq[WalletAccountDto]
updatedProfileShowcases*: seq[ProfileShowcaseDto] updatedProfileShowcaseContactIDs*: seq[string]
type MessageDeliveredSignal* = ref object of Signal type MessageDeliveredSignal* = ref object of Signal
chatId*: string chatId*: string
@ -167,8 +166,8 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
for jsonAcc in e["accountsPositions"]: for jsonAcc in e["accountsPositions"]:
signal.accountsPositions.add(jsonAcc.toWalletAccountDto()) signal.accountsPositions.add(jsonAcc.toWalletAccountDto())
if e.contains("updatedProfileShowcases"): if e.contains("updatedProfileShowcaseContactIDs"):
for jsonProfileShowcase in e["updatedProfileShowcases"]: for contactId in e["updatedProfileShowcaseContactIDs"]:
signal.updatedProfileShowcases.add(jsonProfileShowcase.toProfileShowcaseDto()) signal.updatedProfileShowcaseContactIDs.add(contactId.getStr())
result = signal result = signal

View File

@ -1,9 +1,11 @@
import sugar, sequtils
import io_interface import io_interface
import ../../../../core/eventemitter import ../../../../core/eventemitter
import ../../../../../app_service/service/contacts/service as contacts_service import app_service/service/contacts/service as contacts_service
import ../../../../../app_service/service/chat/service as chat_service import app_service/service/chat/service as chat_service
import ../../../../../app_service/service/message/dto/message as message_dto import app_service/service/network/service as network_service
import app_service/service/message/dto/message as message_dto
type type
Controller* = ref object of RootObj Controller* = ref object of RootObj
@ -11,16 +13,19 @@ type
events: EventEmitter events: EventEmitter
contactsService: contacts_service.Service contactsService: contacts_service.Service
chatService: chat_service.Service chatService: chat_service.Service
networkService: network_service.Service
proc newController*(delegate: io_interface.AccessInterface, proc newController*(delegate: io_interface.AccessInterface,
events: EventEmitter, events: EventEmitter,
contactsService: contacts_service.Service, contactsService: contacts_service.Service,
chatService: chat_service.Service): Controller = chatService: chat_service.Service,
networkService: network_service.Service): Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate
result.events = events result.events = events
result.contactsService = contactsService result.contactsService = contactsService
result.chatService = chatService result.chatService = chatService
result.networkService = networkService
proc delete*(self: Controller) = proc delete*(self: Controller) =
discard discard
@ -90,6 +95,18 @@ proc init*(self: Controller) =
let args = ContactInfoRequestArgs(e) let args = ContactInfoRequestArgs(e)
self.delegate.onContactInfoRequestFinished(args.publicKey, args.ok) 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] = proc getContacts*(self: Controller, group: ContactsGroup): seq[ContactsDto] =
return self.contactsService.getContactsByGroup(group) return self.contactsService.getContactsByGroup(group)
@ -180,3 +197,12 @@ proc shareUserUrlWithChatKey*(self: Controller, pubkey: string): string =
proc shareUserUrlWithENS*(self: Controller, pubkey: string): string = proc shareUserUrlWithENS*(self: Controller, pubkey: string): string =
self.contactsService.shareUserUrlWithENS(pubkey) 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/contacts as contacts
import ../../../../../app_service/service/contacts/dto/status_update import ../../../../../app_service/service/contacts/dto/status_update
import app_service/service/contacts/dto/profile_showcase
type type
AccessInterface* {.pure inheritable.} = ref object of RootObj AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module. ## Abstract class for any input/interaction with this module.
@ -138,4 +140,25 @@ method shareUserUrlWithChatKey*(self: AccessInterface, pubkey: string): string {
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method shareUserUrlWithENS*(self: AccessInterface, pubkey: string): string {.base.} = 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") 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 ../../../../global/global_singleton
import ../../../../core/eventemitter import ../../../../core/eventemitter
import ../../../../../app_service/common/types import app_service/common/types
import ../../../../../app_service/service/contacts/dto/contacts as contacts_dto import app_service/service/contacts/dto/contacts as contacts_dto
import ../../../../../app_service/service/contacts/service as contacts_service import app_service/service/contacts/service as contacts_service
import ../../../../../app_service/service/chat/service as chat_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 export io_interface
const COLLECTIBLES_CACHE_AGE_SECONDS = 60
logScope: logScope:
topics = "profile-section-contacts-module" topics = "profile-section-contacts-module"
type type
Module* = ref object of io_interface.AccessInterface Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface delegate: delegate_interface.AccessInterface
controller: Controller controller: controller.Controller
collectiblesController: collectiblesc.Controller
view: View view: View
viewVariant: QVariant viewVariant: QVariant
moduleLoaded: bool moduleLoaded: bool
showcasePublicKey: string
showcaseForAContactLoading: bool
proc newModule*(delegate: delegate_interface.AccessInterface, proc newModule*(delegate: delegate_interface.AccessInterface,
events: EventEmitter, events: EventEmitter,
contactsService: contacts_service.Service, contactsService: contacts_service.Service,
chatService: chat_service.Service): chatService: chat_service.Service,
networkService: network_service.Service):
Module = Module =
result = Module() result = Module()
result.delegate = delegate result.delegate = delegate
result.view = newView(result) result.view = newView(result)
result.viewVariant = newQVariant(result.view) 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.moduleLoaded = false
result.showcaseForAContactLoading = false
method delete*(self: Module) = method delete*(self: Module) =
self.view.delete self.view.delete
self.viewVariant.delete
self.collectiblesController.delete
proc createItemFromPublicKey(self: Module, publicKey: string): UserItem = proc createItemFromPublicKey(self: Module, publicKey: string): UserItem =
let contactDetails = self.controller.getContactDetails(publicKey) let contactDetails = self.controller.getContactDetails(publicKey)
@ -303,3 +331,98 @@ method shareUserUrlWithChatKey*(self: Module, pubkey: string): string =
method shareUserUrlWithENS*(self: Module, pubkey: string): string = method shareUserUrlWithENS*(self: Module, pubkey: string): string =
return self.controller.shareUserUrlWithENS(pubkey) 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 ../../../shared_models/user_model
import ./io_interface import ./io_interface
import models/showcase_contact_generic_model
import models/showcase_contact_accounts_model
import models/showcase_contact_social_links_model
QtObject: QtObject:
type type
View* = ref object of QObject View* = ref object of QObject
@ -20,6 +24,17 @@ QtObject:
# receivedButRejectedContactRequestsModelVariant: QVariant # receivedButRejectedContactRequestsModelVariant: QVariant
# sentButRejectedContactRequestsModel: Model # sentButRejectedContactRequestsModel: Model
# sentButRejectedContactRequestsModelVariant: QVariant # 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) = proc delete*(self: View) =
self.myMutualContactsModel.delete self.myMutualContactsModel.delete
@ -35,6 +50,16 @@ QtObject:
# self.receivedButRejectedContactRequestsModelVariant.delete # self.receivedButRejectedContactRequestsModelVariant.delete
# self.sentButRejectedContactRequestsModelVariant.delete # self.sentButRejectedContactRequestsModelVariant.delete
# self.sentButRejectedContactRequestsModel.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 self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View = proc newView*(delegate: io_interface.AccessInterface): View =
@ -54,6 +79,16 @@ QtObject:
# result.receivedButRejectedContactRequestsModelVariant = newQVariant(result.receivedButRejectedContactRequestsModel) # result.receivedButRejectedContactRequestsModelVariant = newQVariant(result.receivedButRejectedContactRequestsModel)
# result.sentButRejectedContactRequestsModel = newModel() # result.sentButRejectedContactRequestsModel = newModel()
# result.sentButRejectedContactRequestsModelVariant = newQVariant(result.sentButRejectedContactRequestsModel) # 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) = proc load*(self: View) =
self.delegate.viewDidLoad() self.delegate.viewDidLoad()
@ -204,4 +239,79 @@ QtObject:
self.delegate.requestContactInfo(publicKey) self.delegate.requestContactInfo(publicKey)
proc onContactInfoRequestFinished*(self: View, publicKey: string, ok: bool) {.slot.} = proc onContactInfoRequestFinished*(self: View, publicKey: string, ok: bool) {.slot.} =
self.contactInfoRequestFinished(publicKey, ok) 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.controller = controller.newController(result)
result.moduleLoaded = false result.moduleLoaded = false
result.profileModule = profile_module.newModule(result, events, profileService, settingsService, communityService, walletAccountService, networkService, tokenService) result.profileModule = profile_module.newModule(result, events, profileService, settingsService, communityService, walletAccountService, tokenService)
result.contactsModule = contacts_module.newModule(result, events, contactsService, chatService) result.contactsModule = contacts_module.newModule(result, events, contactsService, chatService, networkService)
result.languageModule = language_module.newModule(result, events, languageService) result.languageModule = language_module.newModule(result, events, languageService)
result.privacyModule = privacy_module.newModule(result, events, settingsService, keychainService, privacyService, generalService) result.privacyModule = privacy_module.newModule(result, events, settingsService, keychainService, privacyService, generalService)
result.aboutModule = about_module.newModule(result, events, aboutService) result.aboutModule = about_module.newModule(result, events, aboutService)

View File

@ -1,4 +1,3 @@
import sugar, sequtils
import io_interface import io_interface
import app/global/app_signals 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/settings/service as settings_service
import app_service/service/community/service as community_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/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/service/token/service as token_service
import app_service/common/social_links import app_service/common/social_links
import app_service/common/types import app_service/common/types
@ -22,7 +20,6 @@ type
settingsService: settings_service.Service settingsService: settings_service.Service
communityService: community_service.Service communityService: community_service.Service
walletAccountService: wallet_account_service.Service walletAccountService: wallet_account_service.Service
networkService: network_service.Service
tokenService: token_service.Service tokenService: token_service.Service
proc newController*( proc newController*(
@ -32,7 +29,6 @@ proc newController*(
settingsService: settings_service.Service, settingsService: settings_service.Service,
communityService: community_service.Service, communityService: community_service.Service,
walletAccountService: wallet_account_service.Service, walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service): Controller = tokenService: token_service.Service): Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate
@ -41,7 +37,6 @@ proc newController*(
result.settingsService = settingsService result.settingsService = settingsService
result.communityService = communityService result.communityService = communityService
result.walletAccountService = walletAccountService result.walletAccountService = walletAccountService
result.networkService = networkService
result.tokenService = tokenService result.tokenService = tokenService
proc delete*(self: Controller) = 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.events.on(SIGNAL_PROFILE_SHOWCASE_PREFERENCES_SAVE_FAILED) do(e: Args):
self.delegate.onProfileShowcasePreferencesSaveFailed() 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) let args = ProfileShowcasePreferencesArgs(e)
self.delegate.updateProfileShowcasePreferences(args.preferences) self.delegate.loadProfileShowcasePreferences(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)
proc storeIdentityImage*(self: Controller, address: string, image: string, aX: int, aY: int, bX: int, bY: int): bool = 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 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] = proc getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAccountDto] =
self.walletAccountService.getWalletAccounts(true) self.walletAccountService.getWalletAccounts(true)
proc getChainIds*(self: Controller): seq[int] =
self.networkService.getCurrentNetworks().map(n => n.chainId)
proc setSocialLinks*(self: Controller, links: SocialLinks) = proc setSocialLinks*(self: Controller, links: SocialLinks) =
self.settingsService.setSocialLinks(links) self.settingsService.setSocialLinks(links)
@ -113,19 +93,13 @@ proc getBio*(self: Controller): string =
proc setBio*(self: Controller, bio: string): bool = proc setBio*(self: Controller, bio: string): bool =
self.settingsService.saveBio(bio) 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.profileService.saveProfileShowcasePreferences(preferences)
self.events.emit(MARK_WALLET_ADDRESSES_AS_SHOWN, WalletAddressesArgs(addresses: revealedAddresses)) self.events.emit(MARK_WALLET_ADDRESSES_AS_SHOWN, WalletAddressesArgs(addresses: revealedAddresses))
proc requestProfileShowcasePreferences*(self: Controller) = proc requestProfileShowcasePreferences*(self: Controller) =
self.profileService.requestProfileShowcasePreferences() 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 = proc getProfileShowcaseSocialLinksLimit*(self: Controller): int =
self.profileService.getProfileShowcaseSocialLinksLimit() self.profileService.getProfileShowcaseSocialLinksLimit()

View File

@ -1,14 +1,7 @@
import NimQml import NimQml
import app_service/common/social_links 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/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 import models/profile_save_data
@ -28,9 +21,6 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} = method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getCollectiblesModel*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")
method getBio*(self: AccessInterface): string {.base.} = method getBio*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
@ -67,38 +57,13 @@ method getProfileShowcaseSocialLinksLimit*(self: AccessInterface): int {.base.}
method getProfileShowcaseEntriesLimit*(self: AccessInterface): int {.base.} = method getProfileShowcaseEntriesLimit*(self: AccessInterface): int {.base.} =
raise newException(ValueError, "No implementation available") 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.} = method requestProfileShowcasePreferences*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method setIsFirstShowcaseInteraction*(self: AccessInterface) {.base.} = method setIsFirstShowcaseInteraction*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method requestProfileShowcase*(self: AccessInterface, publicKey: string) {.base.} = method loadProfileShowcasePreferences*(self: AccessInterface, preferences: ProfileShowcasePreferencesDto) {.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.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
# View Delegate Interface # 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, ./view, ./controller
import ../io_interface as delegate_interface 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/settings/service as settings_service
import app_service/service/community/service as community_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/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/profile/dto/profile_showcase_preferences
import app_service/service/token/service as token_service import app_service/service/token/service as token_service
import app_service/common/social_links import app_service/common/social_links
import app/modules/shared_models/social_links_model import app/modules/shared_models/social_links_model
import app/modules/shared_models/social_link_item 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_generic_model
import models/showcase_preferences_social_links_model import models/showcase_preferences_social_links_model
import models/profile_save_data import models/profile_save_data
import backend/collectibles as backend_collectibles
export io_interface export io_interface
logScope: logScope:
@ -40,11 +29,9 @@ type
Module* = ref object of io_interface.AccessInterface Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface delegate: delegate_interface.AccessInterface
controller: controller.Controller controller: controller.Controller
collectiblesController: collectiblesc.Controller
view: View view: View
viewVariant: QVariant viewVariant: QVariant
moduleLoaded: bool moduleLoaded: bool
presentedPublicKey: string
proc newModule*( proc newModule*(
delegate: delegate_interface.AccessInterface, delegate: delegate_interface.AccessInterface,
@ -53,26 +40,18 @@ proc newModule*(
settingsService: settings_service.Service, settingsService: settings_service.Service,
communityService: community_service.Service, communityService: community_service.Service,
walletAccountService: wallet_account_service.Service, walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service): Module = tokenService: token_service.Service): Module =
result = Module() result = Module()
result.delegate = delegate result.delegate = delegate
result.view = view.newView(result) result.view = view.newView(result)
result.viewVariant = newQVariant(result.view) result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, profileService, settingsService, communityService, walletAccountService, networkService, tokenService) result.controller = controller.newController(result, events, profileService, settingsService, communityService, walletAccountService, tokenService)
result.collectiblesController = collectiblesc.newController(
requestId = int32(backend_collectibles.CollectiblesRequestID.ProfileShowcase),
loadType = collectiblesc.LoadType.AutoLoadSingleUpdate,
networkService = networkService,
events = events
)
result.moduleLoaded = false result.moduleLoaded = false
method delete*(self: Module) = method delete*(self: Module) =
self.view.delete self.view.delete
self.viewVariant.delete self.viewVariant.delete
self.controller.delete self.controller.delete
self.collectiblesController.delete
method load*(self: Module) = method load*(self: Module) =
self.controller.init() self.controller.init()
@ -84,9 +63,6 @@ method isLoaded*(self: Module): bool =
method getModuleAsVariant*(self: Module): QVariant = method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant return self.viewVariant
method getCollectiblesModel*(self: Module): QVariant =
return self.collectiblesController.getModelAsVariant()
proc updateSocialLinks(self: Module, socialLinks: SocialLinks) = proc updateSocialLinks(self: Module, socialLinks: SocialLinks) =
var socialLinkItems = toSocialLinkItems(socialLinks) var socialLinkItems = toSocialLinkItems(socialLinks)
self.view.socialLinksSaved(socialLinkItems) self.view.socialLinksSaved(socialLinkItems)
@ -153,11 +129,6 @@ method saveProfileIdentity*(self: Module, identity: IdentitySaveData) =
self.view.emitProfileIdentitySaveFailedSignal() self.view.emitProfileIdentitySaveFailedSignal()
method saveProfileShowcasePreferences*(self: Module, showcase: ShowcaseSaveData) = 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() var showcasePreferences = ProfileShowcasePreferencesDto()
for _, showcaseCommunity in showcase.communities: for _, showcaseCommunity in showcase.communities:
@ -219,89 +190,12 @@ method saveProfileShowcasePreferences*(self: Module, showcase: ShowcaseSaveData)
order: showcaseSocialLink.showcasePosition order: showcaseSocialLink.showcasePosition
)) ))
self.controller.storeProfileShowcasePreferences(showcasePreferences, revealedAddresses) self.controller.saveProfileShowcasePreferences(showcasePreferences, revealedAddresses)
method requestProfileShowcasePreferences(self: Module) = method requestProfileShowcasePreferences(self: Module) =
let myPublicKey = singletonInstance.userProfile.getPubKey()
if self.presentedPublicKey != myPublicKey:
self.view.clearModels()
self.presentedPublicKey = myPublicKey
self.controller.requestProfileShowcasePreferences() self.controller.requestProfileShowcasePreferences()
method requestProfileShowcase*(self: Module, publicKey: string) = method loadProfileShowcasePreferences(self: Module, preferences: ProfileShowcasePreferencesDto) =
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
var communityItems: seq[ShowcasePreferencesGenericItem] = @[] var communityItems: seq[ShowcasePreferencesGenericItem] = @[]
for community in preferences.communities: for community in preferences.communities:
communityItems.add(ShowcasePreferencesGenericItem( communityItems.add(ShowcasePreferencesGenericItem(
@ -309,7 +203,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: community.showcaseVisibility, showcaseVisibility: community.showcaseVisibility,
showcasePosition: community.order showcasePosition: community.order
)) ))
self.view.updateProfileShowcasePreferencesCommunities(communityItems) self.view.loadProfileShowcasePreferencesCommunities(communityItems)
var accountItems: seq[ShowcasePreferencesGenericItem] = @[] var accountItems: seq[ShowcasePreferencesGenericItem] = @[]
for account in preferences.accounts: for account in preferences.accounts:
@ -318,7 +212,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: account.showcaseVisibility, showcaseVisibility: account.showcaseVisibility,
showcasePosition: account.order showcasePosition: account.order
)) ))
self.view.updateProfileShowcasePreferencesAccounts(accountItems) self.view.loadProfileShowcasePreferencesAccounts(accountItems)
var collectibleItems: seq[ShowcasePreferencesGenericItem] = @[] var collectibleItems: seq[ShowcasePreferencesGenericItem] = @[]
for collectible in preferences.collectibles: for collectible in preferences.collectibles:
@ -327,7 +221,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: collectible.showcaseVisibility, showcaseVisibility: collectible.showcaseVisibility,
showcasePosition: collectible.order showcasePosition: collectible.order
)) ))
self.view.updateProfileShowcasePreferencesCollectibles(collectibleItems) self.view.loadProfileShowcasePreferencesCollectibles(collectibleItems)
var assetItems: seq[ShowcasePreferencesGenericItem] = @[] var assetItems: seq[ShowcasePreferencesGenericItem] = @[]
for token in preferences.verifiedTokens: for token in preferences.verifiedTokens:
@ -342,7 +236,7 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
showcaseVisibility: token.showcaseVisibility, showcaseVisibility: token.showcaseVisibility,
showcasePosition: token.order showcasePosition: token.order
)) ))
self.view.updateProfileShowcasePreferencesAssets(assetItems) self.view.loadProfileShowcasePreferencesAssets(assetItems)
var socialLinkItems: seq[ShowcasePreferencesSocialLinkItem] = @[] var socialLinkItems: seq[ShowcasePreferencesSocialLinkItem] = @[]
for socialLink in preferences.socialLinks: for socialLink in preferences.socialLinks:
@ -351,61 +245,4 @@ method updateProfileShowcasePreferences(self: Module, preferences: ProfileShowca
text: socialLink.text, text: socialLink.text,
showcasePosition: socialLink.order showcasePosition: socialLink.order
)) ))
self.view.updateProfileShowcasePreferencesSocialLinks(socialLinkItems) self.view.loadProfileShowcasePreferencesSocialLinks(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)

View File

@ -1,19 +1,9 @@
import NimQml, json, sequtils, sugar, std/algorithm import NimQml, json, sequtils
import io_interface import io_interface
import app/modules/shared_models/social_links_model import app/modules/shared_models/social_links_model
import app/modules/shared_models/social_link_item 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/profile_save_data
import models/showcase_preferences_generic_model import models/showcase_preferences_generic_model
import models/showcase_preferences_social_links_model import models/showcase_preferences_social_links_model
@ -27,14 +17,6 @@ QtObject:
socialLinksModelVariant: QVariant socialLinksModelVariant: QVariant
temporarySocialLinksModel: SocialLinksModel # used for editing purposes temporarySocialLinksModel: SocialLinksModel # used for editing purposes
temporarySocialLinksModelVariant: QVariant temporarySocialLinksModelVariant: QVariant
profileShowcaseCommunitiesModel: ProfileShowcaseCommunitiesModel
profileShowcaseCommunitiesModelVariant: QVariant
profileShowcaseAccountsModel: ProfileShowcaseAccountsModel
profileShowcaseAccountsModelVariant: QVariant
profileShowcaseCollectiblesModel: ProfileShowcaseCollectiblesModel
profileShowcaseCollectiblesModelVariant: QVariant
profileShowcaseAssetsModel: ProfileShowcaseAssetsModel
profileShowcaseAssetsModelVariant: QVariant
showcasePreferencesCommunitiesModel: ShowcasePreferencesGenericModel showcasePreferencesCommunitiesModel: ShowcasePreferencesGenericModel
showcasePreferencesCommunitiesModelVariant: QVariant showcasePreferencesCommunitiesModelVariant: QVariant
@ -48,20 +30,11 @@ QtObject:
showcasePreferencesSocialLinksModelVariant: QVariant showcasePreferencesSocialLinksModelVariant: QVariant
proc delete*(self: View) = proc delete*(self: View) =
self.QObject.delete
# TODO: remove old models # TODO: remove old models
self.socialLinksModel.delete self.socialLinksModel.delete
self.socialLinksModelVariant.delete self.socialLinksModelVariant.delete
self.temporarySocialLinksModel.delete self.temporarySocialLinksModel.delete
self.temporarySocialLinksModelVariant.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.showcasePreferencesCommunitiesModel.delete
self.showcasePreferencesCommunitiesModelVariant.delete self.showcasePreferencesCommunitiesModelVariant.delete
@ -73,6 +46,7 @@ QtObject:
self.showcasePreferencesAssetsModelVariant.delete self.showcasePreferencesAssetsModelVariant.delete
self.showcasePreferencesSocialLinksModel.delete self.showcasePreferencesSocialLinksModel.delete
self.showcasePreferencesSocialLinksModelVariant.delete self.showcasePreferencesSocialLinksModelVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View = proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete) new(result, delete)
@ -83,14 +57,6 @@ QtObject:
result.socialLinksModelVariant = newQVariant(result.socialLinksModel) result.socialLinksModelVariant = newQVariant(result.socialLinksModel)
result.temporarySocialLinksModel = newSocialLinksModel() result.temporarySocialLinksModel = newSocialLinksModel()
result.temporarySocialLinksModelVariant = newQVariant(result.temporarySocialLinksModel) 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.showcasePreferencesCommunitiesModel = newShowcasePreferencesGenericModel()
result.showcasePreferencesCommunitiesModelVariant = newQVariant(result.showcasePreferencesCommunitiesModel) result.showcasePreferencesCommunitiesModelVariant = newQVariant(result.showcasePreferencesCommunitiesModel)
@ -213,72 +179,30 @@ QtObject:
proc emitProfileShowcasePreferencesSaveFailedSignal*(self: View) = proc emitProfileShowcasePreferencesSaveFailedSignal*(self: View) =
self.profileShowcasePreferencesSaveFailed() self.profileShowcasePreferencesSaveFailed()
# TODO: remove old models proc getShowcasePreferencesCommunitiesModel(self: View): QVariant {.slot.} =
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.} =
return self.showcasePreferencesCommunitiesModelVariant return self.showcasePreferencesCommunitiesModelVariant
QtProperty[QVariant] showcasePreferencesCommunitiesModel: QtProperty[QVariant] showcasePreferencesCommunitiesModel:
read = getProfileShowcasePreferencesCommunitiesModel read = getShowcasePreferencesCommunitiesModel
proc getProfileShowcasePreferencesAccountsModel(self: View): QVariant {.slot.} = proc getShowcasePreferencesAccountsModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesAccountsModelVariant return self.showcasePreferencesAccountsModelVariant
QtProperty[QVariant] showcasePreferencesAccountsModel: QtProperty[QVariant] showcasePreferencesAccountsModel:
read = getProfileShowcasePreferencesAccountsModel read = getShowcasePreferencesAccountsModel
proc getProfileShowcasePreferencesCollectiblesModel(self: View): QVariant {.slot.} = proc getShowcasePreferencesCollectiblesModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesCollectiblesModelVariant return self.showcasePreferencesCollectiblesModelVariant
QtProperty[QVariant] showcasePreferencesCollectiblesModel: QtProperty[QVariant] showcasePreferencesCollectiblesModel:
read = getProfileShowcasePreferencesCollectiblesModel read = getShowcasePreferencesCollectiblesModel
proc getProfileShowcasePreferencesAssetsModel(self: View): QVariant {.slot.} = proc getShowcasePreferencesAssetsModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesAssetsModelVariant return self.showcasePreferencesAssetsModelVariant
QtProperty[QVariant] showcasePreferencesAssetsModel: QtProperty[QVariant] showcasePreferencesAssetsModel:
read = getProfileShowcasePreferencesAssetsModel read = getShowcasePreferencesAssetsModel
proc getProfileShowcasePreferencesSocialLinksModel(self: View): QVariant {.slot.} = proc getShowcasePreferencesSocialLinksModel(self: View): QVariant {.slot.} =
return self.showcasePreferencesSocialLinksModelVariant return self.showcasePreferencesSocialLinksModelVariant
QtProperty[QVariant] showcasePreferencesSocialLinksModel: QtProperty[QVariant] showcasePreferencesSocialLinksModel:
read = getProfileShowcasePreferencesSocialLinksModel read = getShowcasePreferencesSocialLinksModel
proc clearModels*(self: View) {.slot.} =
self.profileShowcaseCommunitiesModel.clear()
self.profileShowcaseAccountsModel.clear()
self.profileShowcaseCollectiblesModel.clear()
self.profileShowcaseAssetsModel.clear()
proc saveProfileIdentity(self: View, profileData: string) {.slot.} = proc saveProfileIdentity(self: View, profileData: string) {.slot.} =
let profileDataObj = profileData.parseJson let profileDataObj = profileData.parseJson
@ -296,49 +220,23 @@ QtObject:
proc getProfileShowcaseEntriesLimit*(self: View): int {.slot.} = proc getProfileShowcaseEntriesLimit*(self: View): int {.slot.} =
self.delegate.getProfileShowcaseEntriesLimit() self.delegate.getProfileShowcaseEntriesLimit()
proc requestProfileShowcase(self: View, publicKey: string) {.slot.} =
self.delegate.requestProfileShowcase(publicKey)
proc requestProfileShowcasePreferences(self: View) {.slot.} = proc requestProfileShowcasePreferences(self: View) {.slot.} =
self.delegate.requestProfileShowcasePreferences() self.delegate.requestProfileShowcasePreferences()
proc setIsFirstShowcaseInteraction(self: View) {.slot.} = proc setIsFirstShowcaseInteraction(self: View) {.slot.} =
self.delegate.setIsFirstShowcaseInteraction() self.delegate.setIsFirstShowcaseInteraction()
proc getProfileShowcaseCommunities*(self: View): seq[ProfileShowcaseCommunityItem] = proc loadProfileShowcasePreferencesCommunities*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
return self.profileShowcaseCommunitiesModel.items()
proc updateProfileShowcasePreferencesCommunities*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesCommunitiesModel.setItems(items) self.showcasePreferencesCommunitiesModel.setItems(items)
proc updateProfileShowcasePreferencesAccounts*(self: View, items: seq[ShowcasePreferencesGenericItem]) = proc loadProfileShowcasePreferencesAccounts*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesAccountsModel.setItems(items) self.showcasePreferencesAccountsModel.setItems(items)
proc updateProfileShowcasePreferencesCollectibles*(self: View, items: seq[ShowcasePreferencesGenericItem]) = proc loadProfileShowcasePreferencesCollectibles*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesCollectiblesModel.setItems(items) self.showcasePreferencesCollectiblesModel.setItems(items)
proc updateProfileShowcasePreferencesAssets*(self: View, items: seq[ShowcasePreferencesGenericItem]) = proc loadProfileShowcasePreferencesAssets*(self: View, items: seq[ShowcasePreferencesGenericItem]) =
self.showcasePreferencesAssetsModel.setItems(items) self.showcasePreferencesAssetsModel.setItems(items)
proc updateProfileShowcasePreferencesSocialLinks*(self: View, items: seq[ShowcasePreferencesSocialLinkItem]) = proc loadProfileShowcasePreferencesSocialLinks*(self: View, items: seq[ShowcasePreferencesSocialLinkItem]) =
self.showcasePreferencesSocialLinksModel.setItems(items) 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(%* { arg.finish(%* {
"publicKey": arg.pubkey, "publicKey": arg.pubkey,
"response": response, "response": response,
"error": nil, "error": "",
}) })
except Exception as e: except Exception as e:
arg.finish(%* { arg.finish(%* {
"publicKey": arg.pubkey, "publicKey": arg.pubkey,
"error": e.msg, "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 include ../../../common/json_utils
type ProfileShowcaseMembershipStatus* {.pure.}= enum
Unproven = 0,
ProvenMember = 1,
NotAMember = 2,
type ProfileShowcaseCommunity* = ref object of RootObj type ProfileShowcaseCommunity* = ref object of RootObj
communityId*: string communityId*: string
order*: int order*: int
membershipStatus*: ProfileShowcaseMembershipStatus
type ProfileShowcaseAccount* = ref object of RootObj type ProfileShowcaseAccount* = ref object of RootObj
contactId*: string contactId*: string
@ -43,10 +49,19 @@ type ProfileShowcaseDto* = ref object of RootObj
unverifiedTokens*: seq[ProfileShowcaseUnverifiedToken] unverifiedTokens*: seq[ProfileShowcaseUnverifiedToken]
socialLinks*: seq[ProfileShowcaseSocialLink] 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 = proc toProfileShowcaseCommunity*(jsonObj: JsonNode): ProfileShowcaseCommunity =
result = ProfileShowcaseCommunity() result = ProfileShowcaseCommunity()
discard jsonObj.getProp("communityId", result.communityId) discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("order", result.order) discard jsonObj.getProp("order", result.order)
result.membershipStatus = jsonObj.toProfileShowcaseMembershipStatus()
proc toProfileShowcaseAccount*(jsonObj: JsonNode): ProfileShowcaseAccount = proc toProfileShowcaseAccount*(jsonObj: JsonNode): ProfileShowcaseAccount =
result = ProfileShowcaseAccount() result = ProfileShowcaseAccount()
@ -113,3 +128,10 @@ proc `%`*(x: ProfileShowcaseAccount): JsonNode =
result["colorId"] = % x.colorId result["colorId"] = % x.colorId
result["emoji"] = % x.emoji result["emoji"] = % x.emoji
result["order"] = % x.order 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/contacts as contacts_dto
import ./dto/status_update as status_update_dto import ./dto/status_update as status_update_dto
import ./dto/contact_details import ./dto/contact_details
import ./dto/profile_showcase
import ../../../backend/contacts as status_contacts import ../../../backend/contacts as status_contacts
import ../../../backend/accounts as status_accounts import ../../../backend/accounts as status_accounts
@ -60,6 +62,13 @@ type
chatId*: string chatId*: string
messages*: JsonNode 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: # Signals which may be emitted by this service:
const SIGNAL_ENS_RESOLVED* = "ensResolved" const SIGNAL_ENS_RESOLVED* = "ensResolved"
const SIGNAL_CONTACT_ADDED* = "contactAdded" const SIGNAL_CONTACT_ADDED* = "contactAdded"
@ -84,6 +93,10 @@ const SIGNAL_CONTACT_VERIFICATION_UPDATED* = "contactVerificationRequestUpdated"
const SIGNAL_CONTACT_INFO_REQUEST_FINISHED* = "contactInfoRequestFinished" const SIGNAL_CONTACT_INFO_REQUEST_FINISHED* = "contactInfoRequestFinished"
const SIGNAL_APPEND_CHAT_MESSAGES* = "appendChatMessages" 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 type
ContactsGroup* {.pure.} = enum ContactsGroup* {.pure.} = enum
AllKnownContacts AllKnownContacts
@ -223,7 +236,12 @@ QtObject:
else: else:
self.events.emit(SIGNAL_CONTACT_VERIFICATION_ADDED, data) 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): self.events.on(SignalType.StatusUpdatesTimedout.event) do(e:Args):
var receivedData = StatusUpdatesTimedoutSignal(e) var receivedData = StatusUpdatesTimedoutSignal(e)
if(receivedData.statusUpdates.len > 0): if(receivedData.statusUpdates.len > 0):
@ -881,3 +899,58 @@ QtObject:
return response.result.getStr return response.result.getStr
except Exception as e: except Exception as e:
error "Error getting user url with ens name", msg = e.msg, pubkey 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,51 +11,13 @@ const asyncGetProfileShowcasePreferencesTask: Task = proc(argEncoded: string) {.
let response = status_accounts.getProfileShowcasePreferences() let response = status_accounts.getProfileShowcasePreferences()
arg.finish(%* { arg.finish(%* {
"response": response, "response": response,
"error": nil, "error": "",
}) })
except Exception as e: except Exception as e:
arg.finish(%* { arg.finish(%* {
"error": e.msg, "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)
type type
SaveProfileShowcasePreferencesTaskArg = ref object of QObjectTaskArg SaveProfileShowcasePreferencesTaskArg = ref object of QObjectTaskArg
preferences: ProfileShowcasePreferencesDto preferences: ProfileShowcasePreferencesDto
@ -66,7 +28,7 @@ const saveProfileShowcasePreferencesTask: Task = proc(argEncoded: string) {.gcsa
let response = status_accounts.setProfileShowcasePreferences(arg.preferences.toJsonNode()) let response = status_accounts.setProfileShowcasePreferences(arg.preferences.toJsonNode())
arg.finish(%* { arg.finish(%* {
"response": response, "response": response,
"error": nil, "error": "",
}) })
except Exception as e: except Exception as e:
arg.finish(%* { arg.finish(%* {

View File

@ -10,7 +10,6 @@ import ../../../app/core/tasks/[qt, threadpool]
import ../../../backend/accounts as status_accounts import ../../../backend/accounts as status_accounts
import ../accounts/dto/accounts import ../accounts/dto/accounts
import dto/profile_showcase
import dto/profile_showcase_preferences import dto/profile_showcase_preferences
include async_tasks include async_tasks
@ -22,17 +21,10 @@ type
ProfileShowcasePreferencesArgs* = ref object of Args ProfileShowcasePreferencesArgs* = ref object of Args
preferences*: ProfileShowcasePreferencesDto preferences*: ProfileShowcasePreferencesDto
ProfileShowcaseForContactArgs* = ref object of Args
profileShowcase*: ProfileShowcaseDto
# Signals which may be emitted by this service: # 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_SUCCEEDED* = "profileShowcasePreferencesSaveSucceeded"
const SIGNAL_PROFILE_SHOWCASE_PREFERENCES_SAVE_FAILED* = "profileShowcasePreferencesSaveFailed" 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: QtObject:
type Service* = ref object of QObject type Service* = ref object of QObject
@ -55,13 +47,6 @@ QtObject:
let args = SettingsTextValueArgs(e) let args = SettingsTextValueArgs(e)
singletonInstance.userProfile.setDisplayName(args.value) 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] = proc storeIdentityImage*(self: Service, address: string, image: string, aX: int, aY: int, bX: int, bY: int): seq[Image] =
try: try:
let response = status_accounts.storeIdentityImage(address, image, aX, aY, bX, bY) 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 error "error: ", procName="setDisplayName", errName = e.name, errDesription = e.msg
return false 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) = proc requestProfileShowcasePreferences*(self: Service) =
let arg = QObjectTaskArg( let arg = QObjectTaskArg(
tptr: cast[ByteAddress](asyncGetProfileShowcasePreferencesTask), tptr: cast[ByteAddress](asyncGetProfileShowcasePreferencesTask),
@ -181,7 +116,7 @@ QtObject:
let preferences = rpcResponseObj["response"]["result"].toProfileShowcasePreferencesDto() 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)) ProfileShowcasePreferencesArgs(preferences: preferences))
except Exception as e: except Exception as e:
error "Error requesting profile showcase preferences", msg = e.msg 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] let payload = %* [address, password]
return core.callPrivateRPC("accounts_verifyKeystoreFileForAccount", payload) 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] = proc getProfileShowcaseAccountsByAddress*(address: string): RpcResponse[JsonNode] =
let payload = %* [address] let payload = %* [address]
result = callPrivateRPC("getProfileShowcaseAccountsByAddress".prefix, payload) result = callPrivateRPC("getProfileShowcaseAccountsByAddress".prefix, payload)

View File

@ -143,4 +143,8 @@ proc shareUserUrlWithChatKey*(pubkey: string): RpcResponse[JsonNode] =
result = callPrivateRPC("shareUserURLWithChatKey".prefix, %*[pubkey]) result = callPrivateRPC("shareUserURLWithChatKey".prefix, %*[pubkey])
proc shareUserUrlWithENS*(pubkey: string): RpcResponse[JsonNode] = proc shareUserUrlWithENS*(pubkey: string): RpcResponse[JsonNode] =
result = callPrivateRPC("shareUserURLWithENS".prefix, %*[pubkey]) 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()") onCloseRequested: logs.logEvent("closeRequested()")
sendToAccountEnabled: true
showcaseCommunitiesModel: CommunitiesModel {}
showcaseAccountsModel: WalletAccountsModel {}
showcaseCollectiblesModel: ManageCollectiblesModel {}
showcaseSocialLinksModel: assetsStore.groupedAccountAssetsModel
// TODO: showcaseAssetsModel
profileStore: QtObject { profileStore: QtObject {
readonly property string pubkey: "0xdeadbeef" readonly property string pubkey: "0xdeadbeef"
readonly property string ensName: name.text readonly property string ensName: name.text
@ -298,14 +306,6 @@ SplitView {
function copyToClipboard(text) { function copyToClipboard(text) {
logs.logEvent("profileStore::copyToClipboard", ["text"], arguments) 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 { contactsStore: QtObject {
@ -364,32 +364,10 @@ SplitView {
logs.logEvent("contactsStore::changeContactNickname", ["publicKey", "newNickname", "displayName", "isEdit"], arguments) logs.logEvent("contactsStore::changeContactNickname", ["publicKey", "newNickname", "displayName", "isEdit"], arguments)
localNickname.text = newNickname localNickname.text = newNickname
} }
}
walletStore: QtObject { function requestProfileShowcase(publicKey) {
function setFilterAddress(address) { logs.logEvent("contactsStore::requestProfileShowcase", ["publicKey"], arguments)
logs.logEvent("walletStore::setFilterAddress", ["address"], 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 { ListModel {
id: communitiesModel 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: "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" } 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 { ListModel {
id: comboBoxModel id: comboBoxModel
@ -59,7 +44,6 @@ Item {
id: dirtyState id: dirtyState
sourceModel: communitiesModel sourceModel: communitiesModel
showcaseModel: communitiesShowcaseModel
} }
MovableModel { MovableModel {
@ -77,72 +61,36 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
Layout.margins: 10 Layout.margins: 10
rows: 3 rows: 2
columns: 3 columns: 2
spacing: 10 spacing: 10
flow: Grid.TopToBottom flow: Grid.TopToBottom
Label {
text: "Backend models"
font.pixelSize: 22
padding: 10
}
GenericListView { GenericListView {
width: grid.width / 3 - grid.spacing width: grid.width / 2 - grid.spacing
height: 300 height: 300
model: communitiesModel model: communitiesModel
label: "COMMUNITIES MODEL" label: "COMMUNITIES MODEL - Backend model"
} }
GenericListView { GenericListView {
width: grid.width / 3 - grid.spacing width: grid.width / 2 - 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
height: 300 height: 300
model: dirtyState.writable_ model: dirtyState.writable_
label: "WRITABLE MODEL" label: "WRITABLE MODEL - Internal Model"
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition", "name"] roles: ["showcaseKey", "showcaseVisibility", "showcasePosition", "name"]
} }
Label {
text: "Display models"
font.pixelSize: 22
padding: 10
}
GenericListView { GenericListView {
width: grid.width / 3 - grid.spacing width: grid.width / 2 - grid.spacing
height: 300 height: 300
model: movableModel model: movableModel
label: "IN SHOWCASE" label: "IN SHOWCASE - output"
movable: true movable: true
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"] roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"]
@ -185,11 +133,11 @@ Item {
} }
GenericListView { GenericListView {
width: grid.width / 3 - grid.spacing width: grid.width / 2 - grid.spacing
height: 300 height: 300
model: dirtyState.hiddenModel model: dirtyState.hiddenModel
label: "HIDDEN" label: "HIDDEN - output"
roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"] roles: ["showcaseKey", "showcaseVisibility", "showcasePosition"]
@ -208,8 +156,13 @@ Item {
onClicked: { onClicked: {
const toBeSaved = dirtyState.currentState() const toBeSaved = dirtyState.currentState()
communitiesShowcaseModel.clear() for (let i = 0; i < communitiesModel.count; i++) {
communitiesShowcaseModel.append(toBeSaved) 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 Layout.alignment: Qt.AlignHCenter

View File

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

View File

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

View File

@ -18,16 +18,7 @@ import utils 1.0
QObject { QObject {
id: root id: root
property alias sourceModel: joined.leftModel property alias sourceModel: writable.sourceModel
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
/** /**
* Model holding elements from 'sourceModel' intended to be visible in the * Model holding elements from 'sourceModel' intended to be visible in the
* showcase, sorted by 'position' role. Includes roles from both input models. * showcase, sorted by 'position' role. Includes roles from both input models.
@ -95,7 +86,6 @@ QObject {
// internals, debug purpose only // internals, debug purpose only
readonly property alias writable_: writable readonly property alias writable_: writable
readonly property alias joined_: joined
component HiddenFilter: AnyOf { component HiddenFilter: AnyOf {
UndefinedFilter { UndefinedFilter {
@ -108,16 +98,9 @@ QObject {
} }
} }
LeftJoinModel {
id: joined
joinRole: "showcaseKey"
}
VisibilityAndPositionDirtyStateModel { VisibilityAndPositionDirtyStateModel {
id: writable id: writable
sourceModel: root.singleModelMode ? root.sourceModel : joined
visibilityHidden: Constants.ShowcaseVisibility.NoOne visibilityHidden: Constants.ShowcaseVisibility.NoOne
} }

View File

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

View File

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

View File

@ -16,6 +16,23 @@ QtObject {
property var receivedContactRequestsModel: contactsModule.receivedContactRequestsModel property var receivedContactRequestsModel: contactsModule.receivedContactRequestsModel
property var sentContactRequestsModel: contactsModule.sentContactRequestsModel 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. // Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
// property var receivedButRejectedContactRequestsModel: contactsModule.receivedButRejectedContactRequestsModel // property var receivedButRejectedContactRequestsModel: contactsModule.receivedButRejectedContactRequestsModel
// property var sentButRejectedContactRequestsModel: contactsModule.sentButRejectedContactRequestsModel // property var sentButRejectedContactRequestsModel: contactsModule.sentButRejectedContactRequestsModel
@ -25,23 +42,23 @@ QtObject {
} }
function generateAlias(pubKey) { function generateAlias(pubKey) {
return root.globalUtilsInst.generateAlias(pubKey) return root.globalUtilsInst.generateAlias(pubKey)
} }
function getFromClipboard() { function getFromClipboard() {
return root.globalUtilsInst.getFromClipboard() return root.globalUtilsInst.getFromClipboard()
} }
function isMyMutualContact(pubKey) { function isMyMutualContact(pubKey) {
return root.contactsModule.isMyMutualContact(pubKey) return root.contactsModule.isMyMutualContact(pubKey)
} }
function isBlockedContact(pubKey) { function isBlockedContact(pubKey) {
return root.contactsModule.isBlockedContact(pubKey) return root.contactsModule.isBlockedContact(pubKey)
} }
function hasPendingContactRequest(pubKey) { function hasPendingContactRequest(pubKey) {
return root.contactsModule.hasPendingContactRequest(pubKey) return root.contactsModule.hasPendingContactRequest(pubKey)
} }
function joinPrivateChat(pubKey) { function joinPrivateChat(pubKey) {

View File

@ -2,6 +2,10 @@ import QtQuick 2.13
import utils 1.0 import utils 1.0
import AppLayouts.Chat.stores 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 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) { function importCommunity(communityKey) {
root.communitiesModuleInst.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 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 showcasePreferencesCommunitiesModel: profileModule.showcasePreferencesCommunitiesModel
readonly property var showcasePreferencesAccountsModel: profileModule.showcasePreferencesAccountsModel readonly property var showcasePreferencesAccountsModel: profileModule.showcasePreferencesAccountsModel
readonly property var showcasePreferencesCollectiblesModel: profileModule.showcasePreferencesCollectiblesModel readonly property var showcasePreferencesCollectiblesModel: profileModule.showcasePreferencesCollectiblesModel
readonly property var showcasePreferencesAssetsModel: profileModule.showcasePreferencesAssetsModel readonly property var showcasePreferencesAssetsModel: profileModule.showcasePreferencesAssetsModel
readonly property var showcasePreferencesSocialLinksModel: profileModule.showcasePreferencesSocialLinksModel 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 readonly property bool isFirstShowcaseInteraction: localAccountSettings.isFirstShowcaseInteraction
property var details: Utils.getContactDetailsAsJson(pubkey) property var details: Utils.getContactDetailsAsJson(pubkey)
@ -118,10 +110,6 @@ QtObject {
root.profileModule.requestProfileShowcasePreferences() root.profileModule.requestProfileShowcasePreferences()
} }
function requestProfileShowcase(publicKey) {
root.profileModule.requestProfileShowcase(publicKey)
}
function setIsFirstShowcaseInteraction() { function setIsFirstShowcaseInteraction() {
root.profileModule.setIsFirstShowcaseInteraction() root.profileModule.setIsFirstShowcaseInteraction()
} }

View File

@ -28,27 +28,24 @@ import AppLayouts.Wallet.stores 1.0
SettingsContentBase { SettingsContentBase {
id: root id: root
property WalletStore walletStore
property ProfileStore profileStore property ProfileStore profileStore
property PrivacyStore privacyStore
property ContactsStore contactsStore 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 sideBySidePreview
property bool toastClashesWithDirtyBubble property bool toastClashesWithDirtyBubble
readonly property alias sideBySidePreviewComponent: myProfilePreviewComponent
property QtObject dirtyValues: QtObject { readonly property QtObject liveValues: QtObject {
property string displayName: descriptionPanel.displayName.text readonly property string displayName: descriptionPanel.displayName.text
property string bio: descriptionPanel.bio.text readonly property string bio: descriptionPanel.bio.text
property url profileLargeImage: profileHeader.previewIcon readonly 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
} }
enum TabIndex { enum TabIndex {
@ -126,7 +123,7 @@ SettingsContentBase {
onVisibleChanged: if (visible) profileStore.requestProfileShowcasePreferences() onVisibleChanged: if (visible) profileStore.requestProfileShowcasePreferences()
Component.onCompleted: profileStore.requestProfileShowcasePreferences() Component.onCompleted: profileStore.requestProfileShowcasePreferences()
readonly property var priv: QtObject { property QObject priv: QObject {
id: priv id: priv
readonly property bool hasAnyProfileShowcaseChanges: showcaseModels.dirty readonly property bool hasAnyProfileShowcaseChanges: showcaseModels.dirty
@ -137,19 +134,11 @@ SettingsContentBase {
profileHeader.icon !== profileStore.profileLargeImage profileHeader.icon !== profileStore.profileLargeImage
property ProfileShowcaseModels showcaseModels: ProfileShowcaseModels { property ProfileShowcaseModels showcaseModels: ProfileShowcaseModels {
communitiesSourceModel: root.communitiesModel id: showcaseModels
communitiesShowcaseModel: root.profileStore.showcasePreferencesCommunitiesModel
communitiesSearcherText: profileShowcaseCommunitiesPanel.searcherText communitiesSearcherText: profileShowcaseCommunitiesPanel.searcherText
accountsSourceModel: root.walletStore.ownAccounts
accountsShowcaseModel: root.profileStore.showcasePreferencesAccountsModel
accountsSearcherText: profileShowcaseAccountsPanel.searcherText accountsSearcherText: profileShowcaseAccountsPanel.searcherText
collectiblesSourceModel: root.profileStore.collectiblesModel
collectiblesShowcaseModel: root.profileStore.showcasePreferencesCollectiblesModel
collectiblesSearcherText: profileShowcaseCollectiblesPanel.searcherText 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 // 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 // id: profileShowcaseAssetsPanel
// baseModel: root.walletAssetsStore.groupedAccountAssetsModel // TODO: instantiate an assets model in profile module // baseModel: root.walletAssetsStore.groupedAccountAssetsModel // TODO: instantiate an assets model in profile module
// showcaseModel: root.profileStore.profileShowcaseAssetsModel // showcaseModel: root.contactsStore.showcaseContactAssetsModel
// addAccountsButtonVisible: root.profileStore.profileShowcaseAccountsModel.hiddenCount > 0 // addAccountsButtonVisible: root.contactsStore.showcaseContactAccountsModel.hiddenCount > 0
// formatCurrencyAmount: function(amount, symbol) { // formatCurrencyAmount: function(amount, symbol) {
// return root.currencyStore.formatCurrencyAmount(amount, symbol) // return root.currencyStore.formatCurrencyAmount(amount, symbol)
// } // }
@ -401,10 +390,33 @@ SettingsContentBase {
publicKey: root.contactsStore.myPublicKey publicKey: root.contactsStore.myPublicKey
profileStore: root.profileStore profileStore: root.profileStore
contactsStore: root.contactsStore contactsStore: root.contactsStore
networkConnectionStore: root.networkConnectionStore sendToAccountEnabled: root.sendToAccountEnabled
onClosed: destroy() onClosed: destroy()
dirtyValues: root.dirtyValues dirtyValues: root.liveValues
dirty: root.dirty 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 { Item {
property alias profileStore: profilePreview.profileStore property alias profileStore: profilePreview.profileStore
property alias contactsStore: profilePreview.contactsStore property alias contactsStore: profilePreview.contactsStore
property alias networkConnectionStore: profilePreview.networkConnectionStore property alias sendToAccountEnabled: profilePreview.sendToAccountEnabled
property alias dirtyValues: profilePreview.dirtyValues property alias dirtyValues: profilePreview.dirtyValues
property alias dirty: profilePreview.dirty 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 implicitHeight: profilePreview.implicitHeight
+ profilePreview.anchors.topMargin + profilePreview.anchors.topMargin
+ profilePreview.anchors.bottomMargin + profilePreview.anchors.bottomMargin

View File

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

View File

@ -535,10 +535,22 @@ QtObject {
id: profilePopupComponent id: profilePopupComponent
ProfileDialog { ProfileDialog {
id: profilePopup id: profilePopup
property bool isCurrentUser: publicKey === rootStore.profileSectionStore.profileStore.pubkey
profileStore: rootStore.profileSectionStore.profileStore profileStore: rootStore.profileSectionStore.profileStore
contactsStore: rootStore.profileSectionStore.contactsStore 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: { onClosed: {
if (profilePopup.parentPopup) { if (profilePopup.parentPopup) {
profilePopup.parentPopup.close() profilePopup.parentPopup.close()

View File

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

View File

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

View File

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

2
vendor/status-go vendored

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