Warning, /network/tokodon/src/content/ui/AccountInfo.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
0002 // SPDX-License-Identifier: GPL-3.0-only
0003 
0004 import QtQuick 2.15
0005 import org.kde.kirigami 2.19 as Kirigami
0006 import QtQuick.Controls 2.15 as QQC2
0007 import QtQml.Models 2.15
0008 import QtQuick.Layouts 1.15
0009 import QtQuick.Dialogs 1.3
0010 import org.kde.kmasto 1.0
0011 
0012 TimelinePage {
0013     id: accountInfo
0014 
0015     required property string accountId
0016 
0017     property var postsBar
0018 
0019     readonly property var currentIndex: postsBar ? postsBar.currentIndex : 0
0020     readonly property bool onPostsTab: accountInfo.currentIndex === 0
0021     readonly property bool onRepliesTab: accountInfo.currentIndex === 1
0022     readonly property bool onMediaTab: accountInfo.currentIndex === 2
0023 
0024     readonly property bool canExcludeBoosts: accountInfo.onPostsTab || accountInfo.onRepliesTab
0025     property bool excludeBoosts: false
0026 
0027     model: AccountModel {
0028         id: model
0029 
0030         accountId: accountInfo.accountId
0031 
0032         excludeReplies: !accountInfo.onRepliesTab
0033         excludeBoosts: accountInfo.excludeBoosts || accountInfo.onMediaTab
0034         excludePinned: !accountInfo.onPostsTab
0035         onlyMedia: accountInfo.onMediaTab
0036     }
0037 
0038     listViewHeader: QQC2.Pane {
0039         width: parent.width
0040         Kirigami.Theme.colorSet: Kirigami.Theme.Window
0041         Kirigami.Theme.inherit: false
0042         leftPadding: 0
0043         rightPadding: 0
0044         bottomPadding: 0
0045         topPadding: 0
0046 
0047         contentItem: Loader {
0048             active: model.identity
0049             sourceComponent: ColumnLayout {
0050                 spacing: 0
0051                 Rectangle {
0052                     Layout.preferredHeight: Kirigami.Units.gridUnit * 7
0053                     Layout.fillWidth: true
0054                     clip: true
0055                     color: Kirigami.Theme.backgroundColor
0056                     Kirigami.Theme.colorSet: Kirigami.Theme.View
0057 
0058                     Image {
0059                         anchors.centerIn: parent
0060                         source: model.identity.backgroundUrl
0061                         fillMode: Image.PreserveAspectFit
0062                         visible: model.identity.backgroundUrl
0063                     }
0064 
0065                     QQC2.Control {
0066                         visible: accountInfo.model.identity.relationship && accountInfo.model.identity.relationship.followedBy
0067                         x: Kirigami.Units.smallSpacing
0068                         y: Kirigami.Units.smallSpacing
0069                         contentItem: QQC2.Label {
0070                             text: i18n("Follows you")
0071                             color: '#fafafa'
0072                         }
0073 
0074                         background: Rectangle {
0075                             radius: 3
0076                             color: '#090b0d'
0077                         }
0078                     }
0079                 }
0080                 RowLayout {
0081                     Layout.leftMargin: Kirigami.Units.largeSpacing
0082                     Layout.rightMargin: Kirigami.Units.largeSpacing
0083                     Layout.topMargin: Kirigami.Units.smallSpacing
0084                     Layout.bottomMargin: Kirigami.Units.smallSpacing
0085                     Item {
0086                         Layout.minimumWidth: Kirigami.Units.gridUnit * 5
0087                         Layout.alignment: Qt.AlignBottom
0088                         Kirigami.Avatar {
0089                             anchors {
0090                                 left: parent.left
0091                                 bottom: parent.bottom
0092                             }
0093                             cache: true
0094                             source: model.identity.avatarUrl
0095                             width: Kirigami.Units.gridUnit * 5
0096                             height: Kirigami.Units.gridUnit * 5
0097                         }
0098                     }
0099                     Kirigami.ActionToolBar {
0100                         Layout.fillWidth: true
0101                         Layout.minimumHeight: Kirigami.Units.gridUnit * 2
0102                         Layout.alignment: Qt.AlignBottom
0103                         alignment: Qt.AlignRight
0104                         flat: false
0105                         actions: [
0106                             Kirigami.Action {
0107                                 displayHint: Kirigami.DisplayHint.KeepVisible
0108                                 text: {
0109                                     if (model.identity.relationship && model.identity.relationship.requested) {
0110                                         return i18n("Requested");
0111                                     }
0112                                     if (model.identity.relationship && model.identity.relationship.following) {
0113                                         return i18n("Following");
0114                                     }
0115                                     return i18n("Follow");
0116                                 }
0117                                 onTriggered: {
0118                                     if (model.identity.relationship.requested
0119                                         || model.identity.relationship.following) {
0120                                         model.account.unfollowAccount(model.identity);
0121                                     } else {
0122                                         model.account.followAccount(model.identity);
0123                                     }
0124                                 }
0125                                 visible: !model.isSelf
0126                             },
0127                             Kirigami.Action {
0128                                 displayHint: Kirigami.DisplayHint.KeepVisible
0129                                 icon.name: {
0130                                     if (model.identity.relationship && model.identity.relationship.notifying) {
0131                                         return "notifications";
0132                                     } else {
0133                                         return "notifications-disabled";
0134                                     }
0135                                 }
0136 
0137                                 visible: model.identity.relationship && model.identity.relationship.following && !model.isSelf
0138                                 tooltip: {
0139                                     if (model.identity.relationship && model.identity.relationship.notifying) {
0140                                         return i18n("Stop notifying me when %1 posts", '@' + model.identity.account);
0141                                     } else {
0142                                         return i18n("Notify me when %1 posts", '@' + model.identity.account);
0143                                     }
0144                                 }
0145                                 onTriggered: {
0146                                     if (model.identity.relationship && model.identity.relationship.notifying) {
0147                                         model.account.followAccount(model.identity, model.identity.relationship.showingReblogs, false);
0148                                     } else {
0149                                         model.account.followAccount(model.identity, model.identity.relationship.showingReblogs, true);
0150                                     }
0151                                 }
0152                             },
0153                             Kirigami.Action {
0154                                 icon.name: "view-hidden"
0155                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0156                                 visible: model.identity.relationship && model.identity.relationship.following && !model.isSelf
0157                                 text: {
0158                                     if (model.identity.relationship && model.identity.relationship.showingReblogs) {
0159                                         return i18n("Hide Boosts from %1", '@' + model.identity.account);
0160                                     } else {
0161                                         return i18n("Stop Hiding Boosts from %1", '@' + model.identity.account);
0162                                     }
0163                                 }
0164                                 onTriggered: {
0165                                     if (model.identity.relationship && model.identity.relationship.showingReblogs) {
0166                                         model.account.followAccount(model.identity, false, model.identity.relationship.notifying);
0167                                     } else {
0168                                         model.account.followAccount(model.identity, true, model.identity.relationship.notifying);
0169                                     }
0170                                 }
0171                             },
0172                             Kirigami.Action {
0173                                 icon.name: "favorite"
0174                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0175                                 visible: model.identity.relationship && !model.isSelf
0176                                 text: {
0177                                     if (model.identity.relationship && model.identity.relationship.endorsed) {
0178                                         return i18n("Stop Featuring on Profile");
0179                                     } else {
0180                                         return i18n("Feature on Profile");
0181                                     }
0182                                 }
0183                                 onTriggered: {
0184                                     if (model.identity.relationship && model.identity.relationship.endorsed) {
0185                                         model.account.unpin(model.identity);
0186                                     } else {
0187                                         model.account.pin(model.identity);
0188                                     }
0189                                 }
0190                             },
0191                             Kirigami.Action {
0192                                 icon.name: "dialog-cancel"
0193                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0194                                 visible: model.identity.relationship && !model.isSelf
0195                                 text: {
0196                                     if (model.identity.relationship && model.identity.relationship.muting) {
0197                                         return i18n("Stop Muting");
0198                                     } else {
0199                                         return i18n("Mute");
0200                                     }
0201                                 }
0202                                 onTriggered: {
0203                                     if (model.identity.relationship && model.identity.relationship.muting) {
0204                                         model.account.unmuteAccount(model.identity);
0205                                     } else {
0206                                         model.account.muteAccount(model.identity);
0207                                     }
0208                                 }
0209                             },
0210                             Kirigami.Action {
0211                                 icon.name: "im-ban-kick-user"
0212                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0213                                 visible: model.identity.relationship && !model.isSelf
0214                                 text: {
0215                                     if (model.identity.relationship && model.identity.relationship.blocking) {
0216                                         return i18n("Stop Blocking");
0217                                     } else {
0218                                         return i18n("Block");
0219                                     }
0220                                 }
0221                                 onTriggered: {
0222                                     if (model.identity.relationship && model.identity.relationship.blocking) {
0223                                         model.account.unblock(model.identity);
0224                                     } else {
0225                                         model.account.block(model.identity);
0226                                     }
0227                                 }
0228                             },
0229                             Kirigami.Action {
0230                                 icon.name: "user-group-properties"
0231                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0232                                 visible: model.isSelf
0233                                 text: i18n("Edit Profile")
0234                                 onTriggered: pageStack.push('qrc:/content/ui/Settings/ProfileEditor.qml', {
0235                                                     account: model.account
0236                                                 }, {
0237                                                     title: i18n("Account editor")
0238                                                 })
0239                             },
0240                             Kirigami.Action {
0241                                 icon.name: "settings-configure"
0242                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0243                                 visible: model.isSelf
0244                                 text: i18n("Settings")
0245                                 onTriggered: pageStack.pushDialogLayer('qrc:/content/ui/Settings/SettingsPage.qml', {}, { title: i18n("Configure") })
0246                             },
0247                             Kirigami.Action {
0248                                 icon.name: "list-add-user"
0249                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0250                                 visible: model.isSelf
0251                                 text: i18n("Follow Requests")
0252                                 onTriggered: pageStack.push(socialGraphComponent, { name: "request" });
0253                             },
0254                             Kirigami.Action {
0255                                 icon.name: "microphone-sensitivity-muted"
0256                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0257                                 visible: model.isSelf
0258                                 text: i18n("Muted Accounts")
0259                                 onTriggered: pageStack.push(socialGraphComponent, { name: "mutes" });
0260                             },
0261                             Kirigami.Action {
0262                                 icon.name: "cards-block"
0263                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0264                                 visible: model.isSelf
0265                                 text: i18n("Blocked Accounts")
0266                                 onTriggered: pageStack.push(socialGraphComponent, { name: "blocks" });
0267                             },
0268                             Kirigami.Action {
0269                                 icon.name: "favorite"
0270                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0271                                 visible: model.isSelf
0272                                 text: i18n("Featured Accounts")
0273                                 onTriggered: pageStack.push(socialGraphComponent, { name: "featured" });
0274                             },
0275                             Kirigami.Action {
0276                                 icon.name: "edit-copy"
0277                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0278                                 text: i18n("Copy Link to This Profile")
0279                                 onTriggered: {
0280                                     Clipboard.saveText(model.identity.url)
0281                                     applicationWindow().showPassiveNotification(i18n("Post link copied."));
0282                                 }
0283                             },
0284                             ShareAction {
0285                                 id: shareAction
0286 
0287                                 displayHint: Kirigami.DisplayHint.AlwaysHide
0288 
0289                                 inputData: {
0290                                     'urls': [model.identity.url.toString()],
0291                                     'title': "Profile",
0292                                 }
0293                             }
0294                         ]
0295                     }
0296                 }
0297 
0298                 Kirigami.Heading {
0299                     Layout.fillWidth: true
0300                     Layout.leftMargin: Kirigami.Units.largeSpacing
0301                     Layout.rightMargin: Kirigami.Units.largeSpacing
0302                     text: model.identity.displayName
0303                 }
0304                 QQC2.TextArea {
0305                     text: "@" + model.identity.account
0306                     color: Kirigami.Theme.disabledTextColor
0307                     textFormat: TextEdit.PlainText
0308                     readOnly: true
0309                     Layout.fillWidth: true
0310                     background: null
0311                     topPadding: 0
0312                 }
0313                 Repeater {
0314                     model: accountInfo.model.identity.fields
0315                     ColumnLayout {
0316                         Layout.fillWidth: true
0317                         spacing: 0
0318                         Kirigami.Separator {
0319                             Layout.fillWidth: true
0320                         }
0321                         RowLayout {
0322                             spacing: 0
0323                             QQC2.Pane {
0324                                 contentItem: QQC2.Label {
0325                                     text: modelData.name
0326                                     wrapMode: Text.WordWrap
0327                                 }
0328                                 Layout.minimumWidth: Kirigami.Units.gridUnit * 7
0329                                 Layout.maximumWidth: Kirigami.Units.gridUnit * 7
0330                                 Kirigami.Theme.colorSet: Kirigami.Theme.View
0331                                 leftPadding: Kirigami.Units.largeSpacing
0332                                 rightPadding: Kirigami.Units.largeSpacing
0333                                 bottomPadding: 0
0334                                 topPadding: 0
0335                             }
0336 
0337                             QQC2.TextArea {
0338                                 Layout.fillWidth: true
0339                                 Layout.fillHeight: true
0340                                 readOnly: true
0341                                 wrapMode: Text.WordWrap
0342                                 background: Rectangle {
0343                                     color: modelData.verified_at !== null ? Kirigami.Theme.positiveBackgroundColor : Kirigami.Theme.backgroundColor
0344                                 }
0345                                 textFormat: TextEdit.RichText
0346                                 text: modelData.value
0347                                 onLinkActivated: Qt.openUrlExternally(link)
0348                                 MouseArea {
0349                                     anchors.fill: parent
0350                                     acceptedButtons: Qt.NoButton // don't eat clicks on the Text
0351                                     cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
0352                                 }
0353                             }
0354                         }
0355                     }
0356                 }
0357                 Kirigami.Separator {
0358                     Layout.fillWidth: true
0359                 }
0360                 RowLayout {
0361                     visible: accountInfo.model.identity.relationship
0362                     Kirigami.Heading {
0363                         Layout.fillWidth: true
0364                         Layout.leftMargin: Kirigami.Units.largeSpacing
0365                         Layout.rightMargin: Kirigami.Units.largeSpacing
0366                         Layout.topMargin: Kirigami.Units.smallSpacing
0367                         Layout.bottomMargin: Kirigami.Units.smallSpacing
0368                         text: i18n("Note")
0369                         level: 4
0370                     }
0371 
0372                     QQC2.Control {
0373                         id: savedNotification
0374                         visible: false
0375                         contentItem: QQC2.Label {
0376                             text: i18n("Saved")
0377                             color: Kirigami.Theme.positiveTextColor
0378                         }
0379 
0380                         background: Rectangle {
0381                             radius: 3
0382                             color: Kirigami.Theme.positiveBackgroundColor
0383                         }
0384                     }
0385                 }
0386                 QQC2.TextArea {
0387                     id: noteField
0388                     visible: accountInfo.model.identity.relationship
0389                     Layout.fillWidth: true
0390                     background: Item {}
0391                     placeholderText: i18n("Click to add a note")
0392                     textFormat: TextEdit.PlainText
0393                     text: accountInfo.model.identity.relationship ? accountInfo.model.identity.relationship.note : ''
0394                     Layout.leftMargin: 0
0395                     Layout.rightMargin: 0
0396                     Layout.topMargin: Kirigami.Units.smallSpacing
0397                     Layout.bottomMargin: Kirigami.Units.smallSpacing
0398                     property string lastSavedText: ''
0399                     onActiveFocusChanged: {
0400                         lastSavedText = text;
0401                         if (activeFocus) {
0402                             autoSaveTimer.start()
0403                         } else {
0404                             accountInfo.model.account.addNote(accountInfo.model.identity, text);
0405                             savedNotification.visible = true;
0406                             savedNotificationTimer.restart();
0407                             lastSavedText = text;
0408                             autoSaveTimer.stop()
0409                         }
0410                     }
0411                     Timer {
0412                         id: autoSaveTimer
0413                         running: false
0414                         repeat: true
0415                         interval: 5000
0416                         onTriggered: if (noteField.lastSavedText !== noteField.text) {
0417                             accountInfo.model.account.addNote(accountInfo.model.identity, noteField.text);
0418                             savedNotification.visible = true;
0419                             noteField.lastSavedText = noteField.text;
0420                             savedNotificationTimer.restart();
0421                         }
0422                     }
0423 
0424                     Timer {
0425                         id: savedNotificationTimer
0426                         running: false
0427                         interval: 5000
0428                         onTriggered: savedNotification.visible = false
0429                     }
0430                 }
0431                 Kirigami.Separator {
0432                     Layout.fillWidth: true
0433                     visible: noteField.visible
0434                 }
0435                 QQC2.TextArea {
0436                     text: accountInfo.model.identity.bio
0437                     textFormat: TextEdit.RichText
0438                     readOnly: true
0439                     Layout.fillWidth: true
0440                     Layout.leftMargin: Kirigami.Units.largeSpacing
0441                     Layout.rightMargin: Kirigami.Units.largeSpacing
0442                     Layout.topMargin: Kirigami.Units.smallSpacing
0443                     Layout.bottomMargin: Kirigami.Units.smallSpacing
0444                     leftPadding: 0
0445                     rightPadding: 0
0446                     bottomPadding: 0
0447                     topPadding: 0
0448                     background: null
0449                     wrapMode: Text.WordWrap
0450                     onLinkActivated: Qt.openUrlExternally(link)
0451                     MouseArea {
0452                         anchors.fill: parent
0453                         acceptedButtons: Qt.NoButton // don't eat clicks on the Text
0454                         cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
0455                     }
0456                 }
0457                 RowLayout {
0458                     Layout.leftMargin: Kirigami.Units.largeSpacing
0459                     Layout.topMargin: Kirigami.Units.largeSpacing
0460                     Layout.bottomMargin: Kirigami.Units.largeSpacing
0461                     Layout.rightMargin: Kirigami.Units.largeSpacing
0462 
0463                     Kirigami.Chip {
0464                         closable: false
0465                         enabled: false
0466 
0467                         text: i18nc("@label User's number of statuses", "<b>%1</b> posts", model.identity.statusesCount)
0468                     }
0469                     Kirigami.Chip {
0470                         closable: false
0471                         checkable: false
0472 
0473                         onClicked: {
0474                             pageStack.push(socialGraphComponent, {
0475                                 name: "followers",
0476                                 accountId: accountId,
0477                             });
0478                         }
0479                         text: i18nc("@label User's number of followers", "<b>%1</b> followers", model.identity.followersCount)
0480                     }
0481                     Kirigami.Chip {
0482                         closable: false
0483                         checkable: false
0484 
0485                         onClicked: {
0486                             pageStack.push(socialGraphComponent, {
0487                                 name: "following",
0488                                 accountId: accountId,
0489                             });
0490                         }
0491                         text: i18nc("@label User's number of followed accounts", "<b>%1</b> following", model.identity.followingCount)
0492                     }
0493                 }
0494                 QQC2.TabBar {
0495                     id: bar
0496 
0497                     Component.onCompleted: accountInfo.postsBar = bar
0498 
0499                     Layout.alignment: Qt.AlignHCenter
0500                     Layout.fillWidth: true
0501 
0502                     QQC2.TabButton {
0503                         text: i18nc("@item:inmenu Profile Post Filter", "Posts")
0504                         implicitWidth: bar.width / 3
0505                     }
0506                     QQC2.TabButton {
0507                         text: i18nc("@item:inmenu Profile Post Filter", "Posts && Replies")
0508                         implicitWidth: bar.width / 3
0509                     }
0510                     QQC2.TabButton {
0511                         text: i18nc("@item:inmenu Profile Post Filter", "Media")
0512                         implicitWidth: bar.width / 3
0513                     }
0514                 }
0515                 Rectangle {
0516                     Layout.fillWidth: true
0517 
0518                     implicitHeight: extraLayout.implicitHeight + Kirigami.Units.largeSpacing * 2
0519 
0520                     Kirigami.Theme.inherit: false
0521                     Kirigami.Theme.colorSet: Kirigami.Theme.Header
0522 
0523                     color: Kirigami.Theme.backgroundColor
0524 
0525                     RowLayout {
0526                         id: extraLayout
0527 
0528                         anchors {
0529                             fill: parent
0530 
0531                             topMargin: Kirigami.Units.largeSpacing
0532                             leftMargin: Kirigami.Units.largeSpacing
0533                             rightMargin: Kirigami.Units.largeSpacing
0534                             bottomMargin: Kirigami.Units.largeSpacing
0535                         }
0536 
0537                         QQC2.Switch {
0538                             text: i18nc("@option:check", "Hide boosts")
0539 
0540                             onToggled: accountInfo.excludeBoosts = checked
0541 
0542                             enabled: accountInfo.canExcludeBoosts
0543                         }
0544                     }
0545                 }
0546                 Kirigami.Separator {
0547                     Layout.fillWidth: true
0548                 }
0549             }
0550         }
0551     }
0552 }