From 463496153ac7e6a0730fd66f20bbcd2095db4a47 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Mon, 2 May 2022 19:08:35 +0200 Subject: [PATCH] Fixed several issues with activity items relating to icon colouration and activity item sizing + layout Signed-off-by: Claudio Cambra --- src/gui/tray/ActivityItem.qml | 29 +++++++++++++++++++----- src/gui/tray/ActivityItemActions.qml | 9 ++++---- src/gui/tray/ActivityItemContent.qml | 18 ++------------- src/gui/tray/TalkReplyTextField.qml | 21 ++++++++++-------- src/gui/tray/activitydata.cpp | 33 ++++++---------------------- src/gui/tray/activitydata.h | 3 +-- src/gui/tray/activitylistmodel.cpp | 15 ++++++------- src/gui/tray/asyncimageresponse.cpp | 24 ++++++++++++++++++-- src/gui/tray/asyncimageresponse.h | 1 + 9 files changed, 80 insertions(+), 73 deletions(-) diff --git a/src/gui/tray/ActivityItem.qml b/src/gui/tray/ActivityItem.qml index 4415057824150..196ce2086a3e9 100644 --- a/src/gui/tray/ActivityItem.qml +++ b/src/gui/tray/ActivityItem.qml @@ -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() } } } diff --git a/src/gui/tray/ActivityItemActions.qml b/src/gui/tray/ActivityItemActions.qml index faaedb8c0a427..f86ad70d796bc 100644 --- a/src/gui/tray/ActivityItemActions.qml +++ b/src/gui/tray/ActivityItemActions.qml @@ -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() } } diff --git a/src/gui/tray/ActivityItemContent.qml b/src/gui/tray/ActivityItemContent.qml index 079953dea781b..c5408c0fc98af 100644 --- a/src/gui/tray/ActivityItemContent.qml +++ b/src/gui/tray/ActivityItemContent.qml @@ -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 { diff --git a/src/gui/tray/TalkReplyTextField.qml b/src/gui/tray/TalkReplyTextField.qml index 9c9d501c85a4b..550c43a42bac4 100644 --- a/src/gui/tray/TalkReplyTextField.qml +++ b/src/gui/tray/TalkReplyTextField.qml @@ -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 diff --git a/src/gui/tray/activitydata.cpp b/src/gui/tray/activitydata.cpp index bd8c566eb1dbe..1b8bfc34f2900 100644 --- a/src/gui/tray/activitydata.cpp +++ b/src/gui/tray/activitydata.cpp @@ -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"; } } diff --git a/src/gui/tray/activitydata.h b/src/gui/tray/activitydata.h index 501b7fc68948b..944e1f6175562 100644 --- a/src/gui/tray/activitydata.h +++ b/src/gui/tray/activitydata.h @@ -137,8 +137,7 @@ class Activity QDateTime _dateTime; qint64 _expireAtMsecs = -1; QString _accName; - QString _darkIcon; - QString _lightIcon; + QString _icon; bool _isCurrentUserFileActivity = false; QVector _previews; diff --git a/src/gui/tray/activitylistmodel.cpp b/src/gui/tray/activitylistmodel.cpp index 8ffd65077b375..87fb8dcc9b7f9 100644 --- a/src/gui/tray/activitylistmodel.cpp +++ b/src/gui/tray/activitylistmodel.cpp @@ -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); diff --git a/src/gui/tray/asyncimageresponse.cpp b/src/gui/tray/asyncimageresponse.cpp index e484ab0de5571..f393c837a70a2 100644 --- a/src/gui/tray/asyncimageresponse.cpp +++ b/src/gui/tray/asyncimageresponse.cpp @@ -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(); diff --git a/src/gui/tray/asyncimageresponse.h b/src/gui/tray/asyncimageresponse.h index b7394acdf306f..c3327c4c0c857 100644 --- a/src/gui/tray/asyncimageresponse.h +++ b/src/gui/tray/asyncimageresponse.h @@ -33,5 +33,6 @@ private slots: QImage _image; QStringList _imagePaths; QSize _requestedImageSize; + QColor _svgRecolor; int _index = 0; };