Fixed several issues with activity items relating to icon colouration and activity...
authorClaudio Cambra <claudio.cambra@gmail.com>
Mon, 2 May 2022 17:08:35 +0000 (19:08 +0200)
committerClaudio Cambra <claudio.cambra@gmail.com>
Mon, 16 May 2022 14:42:53 +0000 (16:42 +0200)
Signed-off-by: Claudio Cambra <claudio.cambra@gmail.com>
src/gui/tray/ActivityItem.qml
src/gui/tray/ActivityItemActions.qml
src/gui/tray/ActivityItemContent.qml
src/gui/tray/TalkReplyTextField.qml
src/gui/tray/activitydata.cpp
src/gui/tray/activitydata.h
src/gui/tray/activitylistmodel.cpp
src/gui/tray/asyncimageresponse.cpp
src/gui/tray/asyncimageresponse.h

index 4415057824150cc0956a905264a744faa261a29b..196ce2086a3e928f6828759138bc159fa5e0e885 100644 (file)
@@ -23,13 +23,13 @@ MouseArea {
     hoverEnabled: true
 
     // We center the children vertically in the middle of this MouseArea to create the padding.
-    height: childrenRect.height + (Style.standardSpacing * 2)
+    height: contentLayout.implicitHeight + (Style.standardSpacing * 2)
 
     Accessible.role: Accessible.ListItem
     Accessible.name: (model.path !== "" && model.displayPath !== "") ? qsTr("Open %1 locally").arg(model.displayPath) : model.message
     Accessible.onPressAction: root.clicked()
 
-    function showReplyOptions() {
+    function toggleReplyOptions() {
         isTalkReplyOptionVisible = !isTalkReplyOptionVisible
     }
 
@@ -55,13 +55,14 @@ MouseArea {
     }
 
     ColumnLayout {
+        id: contentLayout
         anchors.left: root.left
         anchors.right: root.right
         anchors.rightMargin: Style.standardSpacing
         anchors.leftMargin: Style.standardSpacing
         anchors.verticalCenter: parent.verticalCenter
 
-        spacing: 0
+        spacing: 10
 
         ActivityItemContent {
             id: activityContent
@@ -77,15 +78,30 @@ MouseArea {
             onDismissButtonClicked: activityModel.slotTriggerDismiss(model.index)
         }
 
+        Loader {
+            id: talkReplyTextFieldLoader
+            active: root.isChatActivity && root.isTalkReplyPossible && root.activityData.messageSent === ""
+            visible: root.isTalkReplyOptionVisible
+
+            Layout.leftMargin: Style.trayListItemIconSize + activityContent.spacing
+            Layout.preferredHeight: root.isTalkReplyOptionVisible ? implicitHeight : 0
+
+            sourceComponent: TalkReplyTextField {
+                onSendReply: {
+                    UserModel.currentUser.sendReplyMessage(model.index, model.conversationToken, reply, model.messageId);
+                    talkReplyTextFieldLoader.visible = false;
+                }
+            }
+        }
+
         ActivityItemActions {
             id: activityActions
 
             visible: !root.isFileActivityList && model.linksForActionButtons.length > 0 && !isTalkReplyOptionVisible
 
             Layout.fillWidth: true
-            Layout.leftMargin: 60
-            Layout.bottomMargin: model.links.length > 1 ? 5 : 0
-            Layout.preferredHeight: Style.minActivityHeight
+            Layout.leftMargin: Style.trayListItemIconSize + activityContent.spacing
+            Layout.minimumHeight: Style.minActivityHeight
 
             displayActions: model.displayActions
             objectType: model.objectType
@@ -98,6 +114,7 @@ MouseArea {
             flickable: root.flickable
 
             onTriggerAction: activityModel.slotTriggerAction(model.index, actionIndex)
+            onShowReplyField: root.toggleReplyOptions()
         }
     }
 }
index faaedb8c0a4275373bc631906fcfa3739b2aaa88..f86ad70d796bc5aed12407ff23ff0b9848d6e2cc 100644 (file)
@@ -22,6 +22,7 @@ RowLayout {
     property Flickable flickable
 
     signal triggerAction(int actionIndex)
+    signal showReplyField()
 
     Repeater {
         id: actionsRepeater
@@ -42,15 +43,15 @@ RowLayout {
             text: model.modelData.label
             toolTipText: model.modelData.label
 
-            imageSource: model.modelData.imageSource
-            imageSourceHover: model.modelData.imageSourceHovered
+            imageSource: model.modelData.imageSource ? model.modelData.imageSource + UserModel.currentUser.headerColor : ""
+            imageSourceHover: model.modelData.imageSourceHovered ? model.modelData.imageSourceHovered + UserModel.currentUser.headerTextColor : ""
 
             textColor: imageSource !== "" ? UserModel.currentUser.headerColor : Style.ncTextColor
-            textColorHovered: imageSource !== "" ? Style.lightHover : Style.ncTextColor
+            textColorHovered: imageSource !== "" ? UserModel.currentUser.headerTextColor : Style.ncTextColor
 
             bold: primary
 
-            onClicked: !isTalkReplyButton? root.triggerAction(model.index) : showReplyOptions(model.index)
+            onClicked: !isTalkReplyButton ? root.triggerAction(model.index) : root.showReplyField()
         }
     }
 
index 079953dea781bdd25f13290f5caf33208735fca6..c5408c0fc98afa7ccd03a3ef2e33ee37d2e636a7 100644 (file)
@@ -26,10 +26,10 @@ RowLayout {
         id: thumbnailItem
         Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
         Layout.preferredWidth: Style.trayListItemIconSize
-        Layout.preferredHeight: model.thumbnail.isMimeTypeIcon ? Style.trayListItemIconSize * 0.9 : Style.trayListItemIconSize
+        Layout.preferredHeight: model.thumbnail && model.thumbnail.isMimeTypeIcon ? Style.trayListItemIconSize * 0.9 : Style.trayListItemIconSize
         readonly property int imageWidth: width * (1 - Style.thumbnailImageSizeReduction)
         readonly property int imageHeight: height * (1 - Style.thumbnailImageSizeReduction)
-        readonly property int thumbnailRadius: model.thumbnail.isUserAvatar ? width / 2 : 3
+        readonly property int thumbnailRadius: model.thumbnail && model.thumbnail.isUserAvatar ? width / 2 : 3
 
         Loader {
             id: thumbnailImageLoader
@@ -166,20 +166,6 @@ RowLayout {
             color: Style.ncSecondaryTextColor
             visible: text !== ""
         }
-
-        Loader {
-            id: talkReplyTextFieldLoader
-            active: isChatActivity && isTalkReplyPossible
-            visible: isTalkReplyOptionVisible
-
-            anchors.top: activityTextDateTime.bottom
-            anchors.topMargin: 10
-
-            sourceComponent: TalkReplyTextField {
-                id: talkReplyMessage
-                anchors.fill: parent
-            }
-        }
     }
 
     Button {
index 9c9d501c85a4befbc2189b70ac6df8d1e075aece..550c43a42bac4e4fe45002b17d3cc1a1e3b1f881 100644 (file)
@@ -7,29 +7,32 @@ import com.nextcloud.desktopclient 1.0
 Item {
     id: root
 
+    signal sendReply(string reply)
+
     function sendReplyMessage() {
         if (replyMessageTextField.text === "") {
             return;
         }
 
-        UserModel.currentUser.sendReplyMessage(model.index, model.conversationToken, replyMessageTextField.text, model.messageId);
-        replyMessageTextField.visible = false
+        root.sendReply(replyMessageTextField.text);
     }
 
+    height: 38
+    width: 250
+
     TextField {
         id: replyMessageTextField
-        visible: model.messageSent === ""
-
-        // TODO use Layout to manage width/height. The Layout.minimunWidth does not apply to the width set.
-        height: 38
-        width: 250
-
-        onAccepted: root.sendReplyMessage()
 
+        anchors.fill: parent
         topPadding: 4
+        rightPadding: sendReplyMessageButton.width
+        visible: model.messageSent === ""
 
+        color: Style.ncSecondaryTextColor
         placeholderText: qsTr("Reply to â€¦")
 
+        onAccepted: root.sendReplyMessage()
+
         background: Rectangle {
             id: replyMessageTextFieldBorder
             radius: 24
index bd8c566eb1dbec85f3d9b1b1918c46848d694172..1b8bfc34f2900b99734b6d9d5b56f00ee9895440 100644 (file)
@@ -63,25 +63,9 @@ OCC::Activity Activity::fromActivityJson(const QJsonObject &json, const AccountP
     activity._file = json.value(QStringLiteral("object_name")).toString();
     activity._link = QUrl(json.value(QStringLiteral("link")).toString());
     activity._dateTime = QDateTime::fromString(json.value(QStringLiteral("datetime")).toString(), Qt::ISODate);
-    activity._darkIcon = json.value(QStringLiteral("icon")).toString();  // We have both dark and light for theming purposes
-    activity._lightIcon = json.value(QStringLiteral("icon")).toString(); // Some icons get changed in the ActivityListModel
+    activity._icon = json.value(QStringLiteral("icon")).toString();
     activity._isCurrentUserFileActivity = activity._objectType == QStringLiteral("files") && activityUser == account->davUser();
 
-    const auto darkIconPath = QStringLiteral("qrc://:/client/theme/white/");
-    const auto lightIconPath = QStringLiteral("qrc://:/client/theme/black/");
-    if(activity._darkIcon.contains("change.svg")) {
-        activity._darkIcon = darkIconPath + QStringLiteral("change.svg");
-        activity._lightIcon = lightIconPath + QStringLiteral("change.svg");
-    } else if(activity._darkIcon.contains("calendar.svg")) {
-        activity._darkIcon = darkIconPath + QStringLiteral("calendar.svg");
-        activity._lightIcon = lightIconPath + QStringLiteral("calendar.svg");
-    } else if(activity._darkIcon.contains("personal.svg")) {
-        activity._darkIcon = darkIconPath + QStringLiteral("user.svg");
-        activity._lightIcon = lightIconPath + QStringLiteral("user.svg");
-    }  else if(activity._darkIcon.contains("core/img/actions")) {
-        activity._darkIcon.insert(activity._darkIcon.indexOf(".svg"), "-white");
-    }
-
     auto richSubjectData = json.value(QStringLiteral("subject_rich")).toArray();
 
     if(richSubjectData.size() > 1) {
@@ -144,15 +128,12 @@ OCC::Activity Activity::fromActivityJson(const QJsonObject &json, const AccountP
     }
 
     if(!previewsData.isEmpty()) {
-        if(activity._darkIcon.contains(QStringLiteral("add-color.svg"))) {
-            activity._darkIcon = "qrc:///client/theme/colored/add-bordered.svg";
-            activity._lightIcon = "qrc:///client/theme/colored/add-bordered.svg";
-        } else if(activity._darkIcon.contains(QStringLiteral("delete-color.svg"))) {
-            activity._darkIcon = "qrc:///client/theme/colored/delete-bordered.svg";
-            activity._lightIcon = "qrc:///client/theme/colored/add-bordered.svg";
-        } else if(activity._darkIcon.contains(QStringLiteral("change.svg"))) {
-            activity._darkIcon = "qrc:///client/theme/colored/change-bordered.svg";
-            activity._lightIcon = "qrc:///client/theme/colored/add-bordered.svg";
+        if(activity._icon.contains(QStringLiteral("add-color.svg"))) {
+            activity._icon = "qrc:///client/theme/colored/add-bordered.svg";
+        } else if(activity._icon.contains(QStringLiteral("delete-color.svg"))) {
+            activity._icon = "qrc:///client/theme/colored/delete-bordered.svg";
+        } else if(activity._icon.contains(QStringLiteral("change.svg"))) {
+            activity._icon = "qrc:///client/theme/colored/change-bordered.svg";
         }
     }
 
index 501b7fc68948bf4551b9236adff9d82c82c24ba5..944e1f6175562a6738c2f4ba93038578c282270c 100644 (file)
@@ -137,8 +137,7 @@ public:
     QDateTime _dateTime;
     qint64 _expireAtMsecs = -1;
     QString _accName;
-    QString _darkIcon;
-    QString _lightIcon;
+    QString _icon;
     bool _isCurrentUserFileActivity = false;
     QVector<PreviewData> _previews;
 
index 8ffd65077b37571ee5b208cfe6d86aacc12d2745..87fb8dcc9b7f95c111c626dd3d596527f67e0c1f 100644 (file)
@@ -248,11 +248,13 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
             }
         } else {
             // We have an activity
-            if (a._darkIcon.isEmpty()) {
+            if (a._icon.isEmpty()) {
                 colorIconPath.append("activity.svg");
                 return colorIconPath;
             }
-            return role == DarkIconRole ? a._darkIcon : a._lightIcon;
+
+            const QString basePath = QStringLiteral("image://tray-image-provider/") % a._icon % QStringLiteral("/");
+            return role == DarkIconRole ? QString(basePath + QStringLiteral("white")) : QString(basePath + QStringLiteral("black"));
         }
     };
 
@@ -485,8 +487,7 @@ void ActivityListModel::insertOrRemoveDummyFetchingActivity()
         a._objectType = dummyFetchingActivityObjectType;
         a._subject = tr("Fetching activities…");
         a._dateTime = QDateTime::currentDateTime();
-        a._darkIcon = QLatin1String("qrc:///client/theme/colored/change-bordered.svg");
-        a._lightIcon = QLatin1String("qrc:///client/theme/colored/change-bordered.svg");
+        a._icon = QLatin1String("qrc:///client/theme/colored/change-bordered.svg");
 
         beginInsertRows({}, 0, 0);
         _finalList.prepend(a);
@@ -792,10 +793,8 @@ QVariant ActivityListModel::convertLinkToActionButton(const OCC::ActivityLink &a
     const QString replyButtonPath = QStringLiteral("image://svgimage-custom-color/reply.svg");
 
     if (isReplyIconApplicable) {
-        activityLinkCopy._imageSource =
-            QString(replyButtonPath + "/" + OCC::Theme::instance()->wizardHeaderBackgroundColor().name());
-        activityLinkCopy._imageSourceHovered =
-            QString(replyButtonPath + "/" + OCC::Theme::instance()->wizardHeaderTitleColor().name());
+        activityLinkCopy._imageSource = QString(replyButtonPath + "/");
+        activityLinkCopy._imageSourceHovered = QString(replyButtonPath + "/");
     }
 
     return QVariant::fromValue(activityLinkCopy);
index e484ab0de55712c93456c9dd8b5bb9326af5b696..f393c837a70a2d13b71e5426d6fa804a630af4bf 100644 (file)
@@ -26,7 +26,16 @@ AsyncImageResponse::AsyncImageResponse(const QString &id, const QSize &requested
         return;
     }
 
-    _imagePaths = id.split(QLatin1Char(';'), Qt::SkipEmptyParts);
+    auto actualId = id;
+    const auto idSplit = id.split(QStringLiteral("/"), Qt::SkipEmptyParts);
+    const auto color = QColor(idSplit.last());
+
+    if(color.isValid()) {
+        _svgRecolor = color;
+        actualId.remove("/" % idSplit.last());
+    }
+
+    _imagePaths = actualId.split(QLatin1Char(';'), Qt::SkipEmptyParts);
     _requestedImageSize = requestedSize;
 
     if (_imagePaths.isEmpty()) {
@@ -96,7 +105,18 @@ void AsyncImageResponse::slotProcessNetworkReply()
                 scaledSvg.fill("transparent");
                 QPainter painterForSvg(&scaledSvg);
                 svgRenderer.render(&painterForSvg);
-                setImageAndEmitFinished(scaledSvg);
+
+                if(!_svgRecolor.isValid()) {
+                    setImageAndEmitFinished(scaledSvg);
+                    return;
+                }
+
+                QImage image(_requestedImageSize, QImage::Format_ARGB32);
+                image.fill(_svgRecolor);
+                QPainter imagePainter(&image);
+                imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+                imagePainter.drawImage(0, 0, scaledSvg);
+                setImageAndEmitFinished(image);
                 return;
             } else {
                 processNextImage();
index b7394acdf306f35009baa5b5563740ab5e1a441a..c3327c4c0c8573bd5fb5e0e0b23cd62cbb184f22 100644 (file)
@@ -33,5 +33,6 @@ private slots:
     QImage _image;
     QStringList _imagePaths;
     QSize _requestedImageSize;
+    QColor _svgRecolor;
     int _index = 0;
 };