refactor(ProfileView): Adapt the profile view to the new `ContactDetails` component

This commit is contained in:
Alex Jbanca 2024-06-03 11:57:02 +03:00 committed by Alex Jbanca
parent afcb7608e0
commit f943440915
6 changed files with 161 additions and 199 deletions

View File

@ -20,100 +20,102 @@ import QtTest 1.15
SplitView {
id: root
ColumnLayout {
Pane {
SplitView.fillWidth: true
SplitView.fillHeight: true
clip: true
spacing: 5
Label {
Layout.fillWidth: true
text: "publicKey: " + contactDetails.publicKey
font.bold: true
}
Label {
Layout.fillWidth: true
text: "loading: " + contactDetails.loading
font.bold: true
}
Label {
Layout.fillWidth: true
text: "displayName: " + contactDetails.displayName
}
Label {
Layout.fillWidth: true
text: "ensName: " + contactDetails.ensName
}
Label {
Layout.fillWidth: true
text: "ensVerified: " + contactDetails.ensVerified
}
Label {
Layout.fillWidth: true
text: "localNickname: " + contactDetails.localNickname
}
Label {
Layout.fillWidth: true
text: "alias: " + contactDetails.alias
}
Label {
Layout.fillWidth: true
text: "icon: " + contactDetails.icon
}
Label {
Layout.fillWidth: true
text: "colorId: " + contactDetails.colorId
}
Label {
Layout.fillWidth: true
text: "colorHash: " + contactDetails.colorHash
}
Label {
Layout.fillWidth: true
text: "onlineStatus: " + contactDetails.onlineStatus
}
Label {
Layout.fillWidth: true
text: "isContact: " + contactDetails.isContact
}
Label {
Layout.fillWidth: true
text: "isCurrentUser: " + contactDetails.isCurrentUser
}
Label {
Layout.fillWidth: true
text: "isVerified: " + contactDetails.isVerified
}
Label {
Layout.fillWidth: true
text: "isUntrustworthy: " + contactDetails.isUntrustworthy
}
Label {
Layout.fillWidth: true
text: "isBlocked: " + contactDetails.isBlocked
}
Label {
Layout.fillWidth: true
text: "contactRequestState: " + contactDetails.contactRequestState
}
Label {
Layout.fillWidth: true
text: "incomingVerificationStatus: " + contactDetails.incomingVerificationStatus
}
Label {
Layout.fillWidth: true
text: "outgoingVerificationStatus: " + contactDetails.outgoingVerificationStatus
}
contentItem: ColumnLayout {
clip: true
spacing: 5
Label {
Layout.fillWidth: true
text: "publicKey: " + contactDetails.publicKey
font.bold: true
}
Label {
Layout.fillWidth: true
text: "loading: " + contactDetails.loading
font.bold: true
}
Label {
Layout.fillWidth: true
text: "displayName: " + contactDetails.displayName
}
Label {
Layout.fillWidth: true
text: "ensName: " + contactDetails.ensName
}
Label {
Layout.fillWidth: true
text: "ensVerified: " + contactDetails.ensVerified
}
Label {
Layout.fillWidth: true
text: "localNickname: " + contactDetails.localNickname
}
Label {
Layout.fillWidth: true
text: "alias: " + contactDetails.alias
}
Label {
Layout.fillWidth: true
text: "icon: " + contactDetails.icon
}
Label {
Layout.fillWidth: true
text: "colorId: " + contactDetails.colorId
}
Label {
Layout.fillWidth: true
text: "colorHash: " + contactDetails.colorHash
}
Label {
Layout.fillWidth: true
text: "onlineStatus: " + contactDetails.onlineStatus
}
Label {
Layout.fillWidth: true
text: "isContact: " + contactDetails.isContact
}
Label {
Layout.fillWidth: true
text: "isCurrentUser: " + contactDetails.isCurrentUser
}
Label {
Layout.fillWidth: true
text: "isVerified: " + contactDetails.isVerified
}
Label {
Layout.fillWidth: true
text: "isUntrustworthy: " + contactDetails.isUntrustworthy
}
Label {
Layout.fillWidth: true
text: "isBlocked: " + contactDetails.isBlocked
}
Label {
Layout.fillWidth: true
text: "contactRequestState: " + contactDetails.contactRequestState
}
Label {
Layout.fillWidth: true
text: "incomingVerificationStatus: " + contactDetails.incomingVerificationStatus
}
Label {
Layout.fillWidth: true
text: "outgoingVerificationStatus: " + contactDetails.outgoingVerificationStatus
}
Pane {
contentItem: RowLayout {
ComboBox {
id: pubKeySelector
model: [...ModelUtils.modelToFlatArray(myContactsModel, "pubKey"), "myPubKey", "none"]
ModelChangeTracker {
id: modelChangeTracker
model: myContactsModel
onRevisionChanged: {
pubKeySelector.model = [...ModelUtils.modelToFlatArray(myContactsModel, "pubKey"), "myPubKey", "none"]
Pane {
contentItem: RowLayout {
ComboBox {
id: pubKeySelector
model: [...ModelUtils.modelToFlatArray(myContactsModel, "pubKey"), "myPubKey", "none"]
ModelChangeTracker {
id: modelChangeTracker
model: myContactsModel
onRevisionChanged: {
pubKeySelector.model = [...ModelUtils.modelToFlatArray(myContactsModel, "pubKey"), "myPubKey", "none"]
}
}
}
}
@ -121,20 +123,22 @@ SplitView {
}
}
UsersModelEditor {
id: myContactsModelEditor
Pane {
SplitView.fillHeight: true
SplitView.preferredWidth: 500
model: myContactsModel
contentItem: UsersModelEditor {
id: myContactsModelEditor
model: myContactsModel
onRemoveClicked: (index) => {
myContactsModel.remove(index, 1)
}
onRemoveAllClicked: () => {
myContactsModel.clear()
}
onAddClicked: () => {
myContactsModel.append(getNewUser(myContactsModel.count))
onRemoveClicked: (index) => {
myContactsModel.remove(index, 1)
}
onRemoveAllClicked: () => {
myContactsModel.clear()
}
onAddClicked: () => {
myContactsModel.append(getNewUser(myContactsModel.count))
}
}
}

View File

@ -67,7 +67,7 @@ public:
// QAbstractItemModel interface
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QHash<int, QByteArray> roleNames() const override;
// QQmlParserStatus interface

View File

@ -310,27 +310,27 @@ bool ConcatModel::setData(const QModelIndex &index, const QVariant &value, int r
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
return false;
auto row = index.row();
const auto row = index.row();
auto source = sourceForIndex(row);
const auto source = sourceForIndex(row);
if (source.first == nullptr)
return false;
auto model = source.first->model();
const auto model = source.first->model();
if (model == nullptr)
return false;
auto sourcePosition = m_sources.indexOf(source.first);
const auto sourcePosition = m_sources.indexOf(source.first);
if (sourcePosition == -1)
return false;
auto& mapping = m_rolesMappingToSource[sourcePosition];
auto it = mapping.find(role);
const auto& mapping = m_rolesMappingToSource[sourcePosition];
const auto it = mapping.find(role);
if (it == mapping.end())
return false;
auto sourceIndex = model->index(source.second, 0);
const auto sourceIndex = model->index(source.second, 0);
if(!sourceIndex.isValid())
return false;

View File

@ -67,7 +67,7 @@ QObject {
QObject {
id: d
property bool loading: !itemData.available && !isMe
readonly property bool loading: !itemData.available && !isMe
onLoadingChanged: {
if (loading) {
contactsStore.requestContactInfo(root.publicKey)

View File

@ -8,23 +8,23 @@ QtObject {
property var profileModule
property string pubkey: !!Global.userProfile? Global.userProfile.pubKey : ""
property string name: !!Global.userProfile? Global.userProfile.name : ""
property string username: !!Global.userProfile? Global.userProfile.username : ""
property string displayName: !!Global.userProfile? Global.userProfile.displayName : ""
property string preferredName: !!Global.userProfile? Global.userProfile.preferredName : ""
property string profileLargeImage: !!Global.userProfile? Global.userProfile.largeImage : ""
property string icon: !!Global.userProfile? Global.userProfile.icon : ""
property string pubkey: userProfile.pubKey
property string name: userProfile.name
property string username: userProfile.username
property string displayName: userProfile.displayName
property string preferredName: userProfile.preferredName
property string profileLargeImage: userProfile.largeImage
property string icon: userProfile.icon
property bool userDeclinedBackupBanner: Global.appIsReady? localAccountSensitiveSettings.userDeclinedBackupBanner : false
property var privacyStore: profileSectionModule.privacyModule
readonly property string keyUid: !!Global.userProfile ? Global.userProfile.keyUid : ""
readonly property bool isKeycardUser: !!Global.userProfile ? Global.userProfile.isKeycardUser : false
readonly property int currentUserStatus: !!Global.userProfile ? Global.userProfile.currentUserStatus : 0
readonly property var thumbnailImage: !!Global.userProfile ? Global.userProfile.thumbnailImage : ""
readonly property var largeImage: !!Global.userProfile ? Global.userProfile.largeImage : ""
readonly property string keyUid: userProfile.keyUid
readonly property bool isKeycardUser: userProfile.isKeycardUser
readonly property int currentUserStatus: userProfile.currentUserStatus
readonly property var thumbnailImage: userProfile.thumbnailImage
readonly property var largeImage: userProfile.largeImage
readonly property int colorId: Utils.colorIdForPubkey(root.pubkey)
readonly property var colorHash: Utils.getColorHashAsJson(root.pubkey, name != "")
readonly property string defaultDisplayName: Utils.getDefaultDisplayName("", name, displayName, username)
readonly property string defaultDisplayName: ProfileUtils.displayName("", name, displayName, username)
readonly property string bio: profileModule.bio
readonly property string socialLinksJson: profileModule.socialLinksJson

View File

@ -22,6 +22,7 @@ import shared.views.profile 1.0
import SortFilterProxyModel 0.2
import AppLayouts.Wallet.stores 1.0 as WalletNS
import AppLayouts.Profile.helpers 1.0
Pane {
id: root
@ -60,13 +61,15 @@ Pane {
id: background
}
ContactDetails {
id: contactDetails
publicKey: root.publicKey
contactsStore: root.contactsStore
profileStore: root.profileStore
}
QtObject {
id: d
property var contactDetails: Utils.getContactDetailsAsJson(root.publicKey, !isCurrentUser, !isCurrentUser, true)
function reload() {
contactDetails = Utils.getContactDetailsAsJson(root.publicKey, !isCurrentUser, !isCurrentUser, true)
}
readonly property bool isCurrentUser: root.profileStore.pubkey === root.publicKey
readonly property string userDisplayName: contactDetails.displayName
@ -81,7 +84,7 @@ Pane {
readonly property int contactRequestState: contactDetails.contactRequestState
readonly property int outgoingVerificationStatus: contactDetails.verificationStatus
readonly property int outgoingVerificationStatus: contactDetails.outgoingVerificationStatus
readonly property int incomingVerificationStatus: contactDetails.incomingVerificationStatus
readonly property bool isVerificationRequestSent:
@ -93,46 +96,10 @@ Pane {
readonly property bool isTrusted: outgoingVerificationStatus === Constants.verificationStatus.trusted ||
incomingVerificationStatus === Constants.verificationStatus.trusted
readonly property bool isLocallyTrusted: contactDetails.trustStatus === Constants.trustStatus.trusted
readonly property string linkToProfile: root.contactsStore.getLinkToProfile(root.publicKey)
readonly property var conns: Connections {
target: root.contactsStore.myContactsModel ?? null
function onItemChanged(pubKey) {
if (pubKey === root.publicKey)
d.reload()
}
}
// FIXME: use myContactsModel for identity verification
readonly property var conns2: Connections {
target: root.contactsStore.receivedContactRequestsModel ?? null
function onItemChanged(pubKey) {
if (pubKey === root.publicKey)
d.reload()
}
}
readonly property var conns3: Connections {
target: root.contactsStore.sentContactRequestsModel ?? null
function onItemChanged(pubKey) {
if (pubKey === root.publicKey)
d.reload()
}
}
}
function reload() {
d.reload()
}
onDirtyChanged: {
if (!dirty)
d.reload()
}
Component {
@ -168,8 +135,7 @@ Pane {
objectName: "profileDialog_reviewContactRequestButton"
size: StatusButton.Size.Small
text: qsTr("Review contact request")
onClicked: Global.openReviewContactRequestPopup(root.publicKey, d.contactDetails,
popup => popup.closed.connect(d.reload))
onClicked: Global.openReviewContactRequestPopup(root.publicKey, contactDetails, null)
}
}
@ -179,8 +145,7 @@ Pane {
objectName: "profileDialog_sendContactRequestButton"
size: StatusButton.Size.Small
text: qsTr("Send contact request")
onClicked: Global.openContactRequestPopup(root.publicKey, d.contactDetails,
popup => popup.accepted.connect(d.reload))
onClicked: Global.openContactRequestPopup(root.publicKey, contactDetails, null)
}
}
@ -190,7 +155,7 @@ Pane {
size: StatusButton.Size.Small
type: StatusBaseButton.Type.Danger
text: qsTr("Block user")
onClicked: Global.blockContactRequested(root.publicKey, d.contactDetails)
onClicked: Global.blockContactRequested(root.publicKey, contactDetails)
}
}
@ -199,7 +164,7 @@ Pane {
StatusButton {
size: StatusButton.Size.Small
text: qsTr("Unblock user")
onClicked: Global.unblockContactRequested(root.publicKey, d.contactDetails)
onClicked: Global.unblockContactRequested(root.publicKey, contactDetails)
}
}
@ -229,8 +194,7 @@ Pane {
text: qsTr("Reply to ID verification request")
objectName: "respondToIDRequest_StatusItem"
icon.name: "checkmark-circle"
onClicked: Global.openIncomingIDRequestPopup(root.publicKey, d.contactDetails,
popup => popup.closed.connect(d.reload))
onClicked: Global.openIncomingIDRequestPopup(root.publicKey, contactDetails, null)
}
}
@ -241,8 +205,7 @@ Pane {
text: qsTr("Request ID verification")
objectName: "requestIDVerification_StatusItem"
icon.name: "checkmark-circle"
onClicked: Global.openSendIDRequestPopup(root.publicKey, d.contactDetails,
popup => popup.accepted.connect(d.reload))
onClicked: Global.openSendIDRequestPopup(root.publicKey, contactDetails, null)
}
}
@ -253,8 +216,7 @@ Pane {
text: d.incomingVerificationStatus !== Constants.verificationStatus.verified ? qsTr("ID verification pending")
: qsTr("Review ID verification reply")
icon.name: d.incomingVerificationStatus !== Constants.verificationStatus.verified ? "history" : "checkmark-circle"
onClicked: Global.openOutgoingIDRequestPopup(root.publicKey, d.contactDetails,
popup => popup.closed.connect(d.reload))
onClicked: Global.openOutgoingIDRequestPopup(root.publicKey, contactDetails, null)
}
}
@ -302,14 +264,14 @@ Pane {
: d.mainDisplayName
pubkey: root.publicKey
image: root.dirty ? root.dirtyValues.profileLargeImage
: Utils.addTimestampToURL(d.contactDetails.largeImage)
: Utils.addTimestampToURL(contactDetails.largeImage)
interactive: false
imageWidth: 90
imageHeight: imageWidth
ensVerified: d.contactDetails.ensVerified
ensVerified: contactDetails.ensVerified
Binding on onlineStatus {
value: d.contactDetails.onlineStatus
value: contactDetails.onlineStatus
when: !d.isCurrentUser
}
}
@ -400,24 +362,22 @@ Pane {
SendContactRequestMenuItem {
enabled: !d.isContact && !d.isBlocked && d.contactRequestState !== Constants.ContactRequestState.Sent &&
d.contactDetails.trustStatus === Constants.trustStatus.untrustworthy // we have an action button otherwise
contactDetails.trustStatus === Constants.trustStatus.untrustworthy // we have an action button otherwise
onTriggered: {
Global.openContactRequestPopup(root.publicKey, d.contactDetails, null)
Global.openContactRequestPopup(root.publicKey, contactDetails, null)
}
}
StatusAction {
text: qsTr("Mark as ID verified")
icon.name: "checkmark-circle"
enabled: root.idVerificationFlowsEnabled && d.isContact && !d.isBlocked && !(d.isTrusted || d.isLocallyTrusted)
onTriggered: Global.openMarkAsIDVerifiedPopup(root.publicKey, d.contactDetails,
popup => popup.accepted.connect(d.reload))
onTriggered: Global.openMarkAsIDVerifiedPopup(root.publicKey, contactDetails, null)
}
StatusAction {
text: d.userNickName ? qsTr("Edit nickname") : qsTr("Add nickname")
icon.name: "edit_pencil"
onTriggered: {
Global.openNicknamePopupRequested(root.publicKey, d.contactDetails,
popup => popup.closed.connect(d.reload))
Global.openNicknamePopupRequested(root.publicKey, contactDetails, null)
}
}
StatusAction {
@ -441,23 +401,22 @@ Pane {
icon.name: "delete"
type: StatusAction.Type.Danger
enabled: root.idVerificationFlowsEnabled && d.isContact && (d.isTrusted || d.isLocallyTrusted)
onTriggered: Global.openRemoveIDVerificationDialog(root.publicKey, d.contactDetails,
popup => popup.accepted.connect(d.reload))
onTriggered: Global.openRemoveIDVerificationDialog(root.publicKey, contactDetails, null)
}
StatusAction {
text: qsTr("Remove nickname")
icon.name: "delete"
type: StatusAction.Type.Danger
enabled: !d.isCurrentUser && !!d.contactDetails.localNickname
enabled: !d.isCurrentUser && !!contactDetails.localNickname
onTriggered: root.contactsStore.changeContactNickname(root.publicKey, "", d.optionalDisplayName, true)
}
StatusAction {
text: qsTr("Mark as untrusted")
icon.name: "warning"
type: StatusAction.Type.Danger
enabled: d.contactDetails.trustStatus !== Constants.trustStatus.untrustworthy && !d.isBlocked
enabled: contactDetails.trustStatus !== Constants.trustStatus.untrustworthy && !d.isBlocked
onTriggered: {
Global.markAsUntrustedRequested(root.publicKey, d.contactDetails)
Global.markAsUntrustedRequested(root.publicKey, contactDetails)
}
}
StatusAction {
@ -471,10 +430,9 @@ Pane {
text: qsTr("Remove untrusted mark")
icon.name: "warning"
type: StatusAction.Type.Danger
enabled: d.contactDetails.trustStatus === Constants.trustStatus.untrustworthy && !d.isBlocked
enabled: contactDetails.trustStatus === Constants.trustStatus.untrustworthy && !d.isBlocked
onTriggered: {
root.contactsStore.removeTrustStatus(root.publicKey)
d.reload()
}
}
StatusAction {
@ -483,7 +441,7 @@ Pane {
type: StatusAction.Type.Danger
enabled: d.isContact && !d.isBlocked && d.contactRequestState !== Constants.ContactRequestState.Sent
onTriggered: {
Global.removeContactRequested(root.publicKey, d.contactDetails)
Global.removeContactRequested(root.publicKey, contactDetails)
}
}
StatusAction {
@ -492,7 +450,7 @@ Pane {
type: StatusAction.Type.Danger
enabled: !d.isBlocked
onTriggered: {
Global.blockContactRequested(root.publicKey, d.contactDetails)
Global.blockContactRequested(root.publicKey, contactDetails)
}
}
}
@ -524,7 +482,7 @@ Pane {
objectName: "ProfileDialog_userVerificationIcons"
visible: !d.isCurrentUser
isContact: d.isContact
trustIndicator: d.contactDetails.trustStatus
trustIndicator: contactDetails.trustStatus
isBlocked: d.isBlocked
tiny: false
}
@ -580,7 +538,7 @@ Pane {
id: bioText
width: bioScrollView.availableWidth
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: root.dirty ? root.dirtyValues.bio.trim() : d.contactDetails.bio.trim()
text: root.dirty ? root.dirtyValues.bio.trim() : contactDetails.bio.trim()
}
}
EmojiHash {