Add 'Reply' as activity link instead of changing the 'View chat' link.

- Align 'Reply' button.
- Do not display 'View chat' as a link: the 'View chat' action is active when
the user clickcs on the notification item in the tray window.
- Convert the QByteArray verb value to String.
- Handle logic to toggle the reply textfield in the QML code.

Signed-off-by: Camila <hello@camila.codes>
This commit is contained in:
Camila 2022-03-29 13:33:06 +02:00
parent 468a33cfa8
commit c254572e80
No known key found for this signature in database
GPG key ID: 7A4A6121E88E2AD4
8 changed files with 50 additions and 60 deletions

View file

@ -12,8 +12,9 @@ MouseArea {
property bool isFileActivityList: false
property bool isChatActivity: model.objectType === "chat" || model.objectType === "room" || model.objectType === "call"
property bool isTalkReplyPossible: model.conversationToken !== ""
readonly property bool isChatActivity: model.objectType === "chat" || model.objectType === "room" || model.objectType === "call"
readonly property bool isTalkReplyPossible: model.conversationToken !== ""
property bool isTalkReplyOptionVisible: model.messageSent !== ""
signal fileActivityButtonClicked(string absolutePath)
@ -26,6 +27,10 @@ MouseArea {
Accessible.name: (model.path !== "" && model.displayPath !== "") ? qsTr("Open %1 locally").arg(model.displayPath) : model.message
Accessible.onPressAction: root.clicked()
function showReplyOptions(activityIndex) {
isTalkReplyOptionVisible = !isTalkReplyOptionVisible
}
Rectangle {
id: activityHover
anchors.fill: parent
@ -73,11 +78,11 @@ MouseArea {
ActivityItemActions {
id: activityActions
visible: !root.isFileActivityList && model.linksForActionButtons.length > 0 && !model.displayReplyOption
visible: !root.isFileActivityList && model.linksForActionButtons.length > 0 && !isTalkReplyOptionVisible
Layout.preferredHeight: Style.trayWindowHeaderHeight * 0.85
Layout.fillWidth: true
Layout.leftMargin: 40
Layout.leftMargin: 60
Layout.bottomMargin: model.links.length > 1 ? 5 : 0
displayActions: model.displayActions

View file

@ -31,7 +31,12 @@ RowLayout {
ActivityActionButton {
id: activityActionButton
readonly property bool primary: model.index === 0 && model.modelData.verb !== "DELETE"
readonly property string verb: model.modelData.verb
readonly property bool primary: model.index === 0 && verb !== "DELETE"
readonly property bool isViewChatlink: verb === "WEB"
readonly property bool isTalkReplyButton: verb === "REPLY"
visible: !isViewChatlink
Layout.minimumWidth: primary ? Style.activityItemActionPrimaryButtonMinWidth : Style.activityItemActionSecondaryButtonMinWidth
Layout.preferredHeight: primary ? parent.height : parent.height * 0.3
@ -48,7 +53,7 @@ RowLayout {
bold: primary
onClicked: root.triggerAction(model.index)
onClicked: !isTalkReplyButton? root.triggerAction(model.index) : showReplyOptions(model.index)
}
}

View file

@ -131,10 +131,22 @@ RowLayout {
color: Style.ncSecondaryTextColor
}
Label {
id: talkReplyMessageSent
text: root.activityData.messageSent
height: (text === "") ? 0 : implicitHeight
width: parent.width
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 2
font.pixelSize: Style.topLinePixelSize
color: Style.ncSecondaryTextColor
}
Loader {
id: talkReplyTextFieldLoader
active: isChatActivity && isTalkReplyPossible && model.displayReplyOption
visible: model.displayReplyOption
active: isChatActivity && isTalkReplyPossible
visible: isTalkReplyOptionVisible
anchors.top: activityTextDateTime.bottom
anchors.topMargin: 10

View file

@ -13,25 +13,18 @@ Item {
}
UserModel.currentUser.sendReplyMessage(model.index, model.conversationToken, replyMessageTextField.text, model.messageId);
}
Text {
id: replyMessageSent
text: model.messageSent
font.pixelSize: Style.topLinePixelSize
color: Style.menuBorder
visible: model.messageSent !== ""
replyMessageTextField.visible = false
}
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()
visible: replyMessageSent.text === ""
topPadding: 4

View file

@ -113,7 +113,6 @@ public:
QString conversationToken;
QString messageId;
QString messageSent;
bool displayReplyOption = false;
};
Type _type;

View file

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program is free software; you can redistribute it and/or modify
@ -80,7 +80,6 @@ QHash<int, QByteArray> ActivityListModel::roleNames() const
roles[TalkNotificationConversationTokenRole] = "conversationToken";
roles[TalkNotificationMessageIdRole] = "messageId";
roles[TalkNotificationMessageSentRole] = "messageSent";
roles[TalkNotificationDisplayReplyOptionRole] = "displayReplyOption";
return roles;
}
@ -333,8 +332,6 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
return a._talkNotificationData.messageId;
case TalkNotificationMessageSentRole:
return replyMessageSent(a);
case TalkNotificationDisplayReplyOptionRole:
return displayReplyOption(a);
default:
return QVariant();
}
@ -614,12 +611,6 @@ void ActivityListModel::slotTriggerAction(const int activityIndex, const int act
const auto action = activity._links[actionIndex];
// TODO this will change with https://github.com/nextcloud/desktop/issues/4159
if (action._verb == "WEB" && action._label == tr("View chat")) {
setDisplayReplyOption(activityIndex);
return;
}
if (action._verb == "WEB") {
Utility::openBrowser(QUrl(action._link));
return;
@ -672,7 +663,7 @@ QVariantList ActivityListModel::convertLinksToActionButtons(const Activity &acti
}
if (static_cast<quint32>(activity._links.size()) > maxActionButtons()) {
customList << ActivityListModel::convertLinkToActionButton(activity, activity._links.first());
customList << ActivityListModel::convertLinkToActionButton(activity._links.first());
return customList;
}
@ -680,20 +671,18 @@ QVariantList ActivityListModel::convertLinksToActionButtons(const Activity &acti
if (activityLink._verb == QStringLiteral("DELETE")
|| (activity._objectType == QStringLiteral("chat") || activity._objectType == QStringLiteral("call")
|| activity._objectType == QStringLiteral("room"))) {
customList << ActivityListModel::convertLinkToActionButton(activity, activityLink);
customList << ActivityListModel::convertLinkToActionButton(activityLink);
}
}
return customList;
}
QVariant ActivityListModel::convertLinkToActionButton(const OCC::Activity &activity, const OCC::ActivityLink &activityLink)
QVariant ActivityListModel::convertLinkToActionButton(const OCC::ActivityLink &activityLink)
{
auto activityLinkCopy = activityLink;
const auto isReplyIconApplicable = activityLink._verb == QStringLiteral("WEB")
&& (activity._objectType == QStringLiteral("chat") || activity._objectType == QStringLiteral("call")
|| activity._objectType == QStringLiteral("room"));
const auto isReplyIconApplicable = activityLink._verb == QStringLiteral("REPLY");
const QString replyButtonPath = QStringLiteral("image://svgimage-custom-color/reply.svg");
@ -704,14 +693,8 @@ QVariant ActivityListModel::convertLinkToActionButton(const OCC::Activity &activ
QString(replyButtonPath + "/" + OCC::Theme::instance()->wizardHeaderTitleColor().name());
}
const auto isReplyLabelApplicable = activityLink._verb == QStringLiteral("WEB")
&& (activity._objectType == QStringLiteral("chat")
|| (activity._objectType != QStringLiteral("room") && activity._objectType != QStringLiteral("call")));
if (activityLink._verb == QStringLiteral("DELETE")) {
activityLinkCopy._label = QObject::tr("Mark as read");
} else if (isReplyLabelApplicable) {
activityLinkCopy._label = QObject::tr("Reply");
}
return QVariant::fromValue(activityLinkCopy);
@ -836,15 +819,4 @@ QString ActivityListModel::replyMessageSent(const Activity &activity) const
{
return activity._talkNotificationData.messageSent;
}
void ActivityListModel::setDisplayReplyOption(const int activityIndex)
{
_finalList[activityIndex]._talkNotificationData.displayReplyOption = true;
emit dataChanged(index(activityIndex, 0), index(activityIndex, 0), {ActivityListModel::TalkNotificationDisplayReplyOptionRole});
}
bool ActivityListModel::displayReplyOption(const Activity &activity) const
{
return activity._talkNotificationData.displayReplyOption;
}
}

View file

@ -71,7 +71,6 @@ public:
TalkNotificationConversationTokenRole,
TalkNotificationMessageIdRole,
TalkNotificationMessageSentRole,
TalkNotificationDisplayReplyOptionRole,
};
Q_ENUM(DataRole)
@ -108,7 +107,6 @@ public:
void setReplyMessageSent(const int activityIndex, const QString &message);
QString replyMessageSent(const Activity &activity) const;
bool displayReplyOption(const Activity &activity) const;
public slots:
void slotRefreshActivity();
@ -143,14 +141,12 @@ protected:
private:
static QVariantList convertLinksToMenuEntries(const Activity &activity);
static QVariantList convertLinksToActionButtons(const Activity &activity);
static QVariant convertLinkToActionButton(const Activity &activity, const ActivityLink &activityLink);
static QVariant convertLinkToActionButton(const ActivityLink &activityLink);
void combineActivityLists();
bool canFetchActivities() const;
void ingestActivities(const QJsonArray &activities);
void setDisplayReplyOption(const int activityIndex);
ActivityList _activityLists;
ActivityList _syncFileItemLists;
ActivityList _notificationLists;
@ -175,7 +171,7 @@ private:
bool _doneFetching = false;
bool _hideOldActivities = true;
static constexpr quint32 MaxActionButtons = 2;
static constexpr quint32 MaxActionButtons = 3;
};
}

View file

@ -98,9 +98,9 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
a._id = json.value("notification_id").toInt();
// 2 cases to consider:
// - server == 24 & has Talk: notification type chat/call contains conversationToken/messageId in object_type
// - server < 24 & has Talk: notification type chat/call contains _only_ the conversationToken in object_type
if (a._objectType == "chat" || a._objectType == "call") {
// 1. server == 24 & has Talk: object_type is chat/call/room & object_id contains conversationToken/messageId
// 2. server < 24 & has Talk: object_type is chat/call/room & object_id contains _only_ conversationToken
if (a._objectType == "chat" || a._objectType == "call" || a._objectType == "room") {
const auto objectId = json.value("object_id").toString();
const auto objectIdData = objectId.split("/");
a._talkNotificationData.conversationToken = objectIdData.first();
@ -109,6 +109,14 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
} else {
qCInfo(lcServerNotification) << "Replying directly to Talk conversation" << a._talkNotificationData.conversationToken << "will not be possible because the notification doesn't contain the message ID.";
}
ActivityLink al;
al._label = tr("Reply");
al._verb = "REPLY";
al._primary = true;
a._links.insert(0, al);
list.append(a);
}
a._status = 0;