mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2025-05-03 23:34:12 +02:00
Implemented notification action buttons and context menu for confirm/dismiss and other actions.
Signed-off-by: allexzander <blackslayer4@gmail.com>
This commit is contained in:
parent
7721832ee0
commit
f04281cb69
@ -5,5 +5,6 @@
|
|||||||
<file>src/gui/tray/HeaderButton.qml</file>
|
<file>src/gui/tray/HeaderButton.qml</file>
|
||||||
<file>theme/Style/Style.qml</file>
|
<file>theme/Style/Style.qml</file>
|
||||||
<file>theme/Style/qmldir</file>
|
<file>theme/Style/qmldir</file>
|
||||||
|
<file>src/gui/tray/ActivityActionButton.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -43,6 +43,7 @@ set(client_UI_SRCS
|
|||||||
addcertificatedialog.ui
|
addcertificatedialog.ui
|
||||||
proxyauthdialog.ui
|
proxyauthdialog.ui
|
||||||
mnemonicdialog.ui
|
mnemonicdialog.ui
|
||||||
|
tray/ActivityActionButton.qml
|
||||||
tray/Window.qml
|
tray/Window.qml
|
||||||
tray/UserLine.qml
|
tray/UserLine.qml
|
||||||
wizard/flow2authwidget.ui
|
wizard/flow2authwidget.ui
|
||||||
|
106
src/gui/tray/ActivityActionButton.qml
Normal file
106
src/gui/tray/ActivityActionButton.qml
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import Style 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
readonly property bool labelVisible: label.visible
|
||||||
|
readonly property bool iconVisible: icon.visible
|
||||||
|
|
||||||
|
// label value
|
||||||
|
property string text: ""
|
||||||
|
|
||||||
|
// icon value
|
||||||
|
property string imageSource: ""
|
||||||
|
|
||||||
|
// Tooltip value
|
||||||
|
property string tooltipText: text
|
||||||
|
|
||||||
|
// text color
|
||||||
|
property color textColor: Style.ncTextColor
|
||||||
|
property color textColorHovered: Style.lightHover
|
||||||
|
|
||||||
|
// text background color
|
||||||
|
property color textBgColor: "transparent"
|
||||||
|
property color textBgColorHovered: Style.lightHover
|
||||||
|
|
||||||
|
// icon background color
|
||||||
|
property color iconBgColor: "transparent"
|
||||||
|
property color iconBgColorHovered: Style.lightHover
|
||||||
|
|
||||||
|
// text border color
|
||||||
|
property color textBorderColor: "transparent"
|
||||||
|
|
||||||
|
property alias hovered: mouseArea.containsMouse
|
||||||
|
|
||||||
|
signal clicked()
|
||||||
|
|
||||||
|
Accessible.role: Accessible.Button
|
||||||
|
Accessible.name: text !== "" ? text : (tooltipText !== "" ? tooltipText : qsTr("Activity action button"))
|
||||||
|
Accessible.onPressAction: clicked()
|
||||||
|
|
||||||
|
// background with border around the Text
|
||||||
|
Rectangle {
|
||||||
|
visible: parent.labelVisible
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
// padding
|
||||||
|
anchors.topMargin: 10
|
||||||
|
anchors.bottomMargin: 10
|
||||||
|
|
||||||
|
border.color: parent.textBorderColor
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
color: parent.hovered ? parent.textBgColorHovered : parent.textBgColor
|
||||||
|
|
||||||
|
radius: 25
|
||||||
|
}
|
||||||
|
|
||||||
|
// background with border around the Image
|
||||||
|
Rectangle {
|
||||||
|
visible: parent.iconVisible
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
color: parent.hovered ? parent.iconBgColorHovered : parent.iconBgColor
|
||||||
|
}
|
||||||
|
|
||||||
|
// label
|
||||||
|
Text {
|
||||||
|
id: label
|
||||||
|
visible: parent.text !== ""
|
||||||
|
text: parent.text
|
||||||
|
font: parent.font
|
||||||
|
color: parent.hovered ? parent.textColorHovered : parent.textColor
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.rightMargin: 10
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
// icon
|
||||||
|
Image {
|
||||||
|
id: icon
|
||||||
|
visible: parent.imageSource !== ""
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: parent.imageSource
|
||||||
|
sourceSize.width: visible ? 32 : 0
|
||||||
|
sourceSize.height: visible ? 32 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: parent.clicked()
|
||||||
|
hoverEnabled: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolTip {
|
||||||
|
text: parent.tooltipText
|
||||||
|
delay: 1000
|
||||||
|
visible: text != "" && parent.hovered
|
||||||
|
}
|
||||||
|
}
|
@ -27,11 +27,18 @@ namespace OCC {
|
|||||||
|
|
||||||
class ActivityLink
|
class ActivityLink
|
||||||
{
|
{
|
||||||
|
Q_GADGET
|
||||||
|
|
||||||
|
Q_PROPERTY(QString label MEMBER _label)
|
||||||
|
Q_PROPERTY(QString link MEMBER _link)
|
||||||
|
Q_PROPERTY(QByteArray verb MEMBER _verb)
|
||||||
|
Q_PROPERTY(bool primary MEMBER _primary)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString _label;
|
QString _label;
|
||||||
QString _link;
|
QString _link;
|
||||||
QByteArray _verb;
|
QByteArray _verb;
|
||||||
bool _isPrimary;
|
bool _primary;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
@ -53,6 +53,7 @@ QHash<int, QByteArray> ActivityListModel::roleNames() const
|
|||||||
roles[ActionRole] = "type";
|
roles[ActionRole] = "type";
|
||||||
roles[ActionIconRole] = "icon";
|
roles[ActionIconRole] = "icon";
|
||||||
roles[ActionTextRole] = "subject";
|
roles[ActionTextRole] = "subject";
|
||||||
|
roles[ActionsLinksRole] = "links";
|
||||||
roles[ActionTextColorRole] = "activityTextTitleColor";
|
roles[ActionTextColorRole] = "activityTextTitleColor";
|
||||||
roles[ObjectTypeRole] = "objectType";
|
roles[ObjectTypeRole] = "objectType";
|
||||||
roles[PointInTimeRole] = "dateTime";
|
roles[PointInTimeRole] = "dateTime";
|
||||||
@ -139,10 +140,8 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
case ActionsLinksRole: {
|
case ActionsLinksRole: {
|
||||||
QList<QVariant> customList;
|
QList<QVariant> customList;
|
||||||
foreach (ActivityLink customItem, a._links) {
|
foreach (ActivityLink activityLink, a._links) {
|
||||||
QVariant customVariant;
|
customList << QVariant::fromValue(activityLink);
|
||||||
customVariant.setValue(customItem);
|
|
||||||
customList << customVariant;
|
|
||||||
}
|
}
|
||||||
return customList;
|
return customList;
|
||||||
}
|
}
|
||||||
@ -418,17 +417,17 @@ void ActivityListModel::removeActivityFromActivityList(Activity activity)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActivityListModel::triggerActionAtIndex(int id) const
|
void ActivityListModel::triggerDefaultAction(int activityIndex) const
|
||||||
{
|
{
|
||||||
if (id < 0 || id >= _finalList.size()) {
|
if (activityIndex < 0 || activityIndex >= _finalList.size()) {
|
||||||
qCWarning(lcActivity) << "Couldn't trigger action at index" << id << "/ final list size:" << _finalList.size();
|
qCWarning(lcActivity) << "Couldn't trigger default action at index" << activityIndex << "/ final list size:" << _finalList.size();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto modelIndex = index(id);
|
const auto modelIndex = index(activityIndex);
|
||||||
const auto path = data(modelIndex, PathRole).toUrl();
|
const auto path = data(modelIndex, PathRole).toUrl();
|
||||||
|
|
||||||
const auto activity = _finalList.at(id);
|
const auto activity = _finalList.at(activityIndex);
|
||||||
if (activity._status == SyncFileItem::Conflict) {
|
if (activity._status == SyncFileItem::Conflict) {
|
||||||
Q_ASSERT(!activity._file.isEmpty());
|
Q_ASSERT(!activity._file.isEmpty());
|
||||||
Q_ASSERT(!activity._folder.isEmpty());
|
Q_ASSERT(!activity._folder.isEmpty());
|
||||||
@ -461,6 +460,30 @@ void ActivityListModel::triggerActionAtIndex(int id) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActivityListModel::triggerAction(int activityIndex, int actionIndex)
|
||||||
|
{
|
||||||
|
if (activityIndex < 0 || activityIndex >= _finalList.size()) {
|
||||||
|
qCWarning(lcActivity) << "Couldn't trigger action on activity at index" << activityIndex << "/ final list size:" << _finalList.size();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto activity = _finalList[activityIndex];
|
||||||
|
|
||||||
|
if (actionIndex < 0 || actionIndex >= activity._links.size()) {
|
||||||
|
qCWarning(lcActivity) << "Couldn't trigger action at index" << actionIndex << "/ actions list size:" << activity._links.size();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto action = activity._links[actionIndex];
|
||||||
|
|
||||||
|
if (action._verb == "WEB") {
|
||||||
|
QDesktopServices::openUrl(QUrl(action._link));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit sendNotificationRequest(activity._accName, action._link, action._verb, activityIndex);
|
||||||
|
}
|
||||||
|
|
||||||
void ActivityListModel::combineActivityLists()
|
void ActivityListModel::combineActivityLists()
|
||||||
{
|
{
|
||||||
ActivityList resultList;
|
ActivityList resultList;
|
||||||
|
@ -74,7 +74,8 @@ public:
|
|||||||
void removeActivityFromActivityList(int row);
|
void removeActivityFromActivityList(int row);
|
||||||
void removeActivityFromActivityList(Activity activity);
|
void removeActivityFromActivityList(Activity activity);
|
||||||
|
|
||||||
Q_INVOKABLE void triggerActionAtIndex(int id) const;
|
Q_INVOKABLE void triggerDefaultAction(int activityIndex) const;
|
||||||
|
Q_INVOKABLE void triggerAction(int activityIndex, int actionIndex);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void slotRefreshActivity();
|
void slotRefreshActivity();
|
||||||
@ -86,6 +87,7 @@ private slots:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void activityJobStatusCode(int statusCode);
|
void activityJobStatusCode(int statusCode);
|
||||||
|
void sendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
@ -128,7 +128,7 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
|
|||||||
al._label = QUrl::fromPercentEncoding(actionJson.value("label").toString().toUtf8());
|
al._label = QUrl::fromPercentEncoding(actionJson.value("label").toString().toUtf8());
|
||||||
al._link = actionJson.value("link").toString();
|
al._link = actionJson.value("link").toString();
|
||||||
al._verb = actionJson.value("type").toString().toUtf8();
|
al._verb = actionJson.value("type").toString().toUtf8();
|
||||||
al._isPrimary = actionJson.value("primary").toBool();
|
al._primary = actionJson.value("primary").toBool();
|
||||||
|
|
||||||
a._links.append(al);
|
a._links.append(al);
|
||||||
}
|
}
|
||||||
@ -139,7 +139,7 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
|
|||||||
al._label = tr("Dismiss");
|
al._label = tr("Dismiss");
|
||||||
al._link = Utility::concatUrlPath(ai->account()->url(), notificationsPath + "/" + QString::number(a._id)).toString();
|
al._link = Utility::concatUrlPath(ai->account()->url(), notificationsPath + "/" + QString::number(a._id)).toString();
|
||||||
al._verb = "DELETE";
|
al._verb = "DELETE";
|
||||||
al._isPrimary = false;
|
al._primary = false;
|
||||||
a._links.append(al);
|
a._links.append(al);
|
||||||
|
|
||||||
list.append(a);
|
list.append(a);
|
||||||
|
@ -51,6 +51,8 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
|
|||||||
connect(this, &User::guiLog, Logger::instance(), &Logger::guiLog);
|
connect(this, &User::guiLog, Logger::instance(), &Logger::guiLog);
|
||||||
|
|
||||||
connect(_account->account().data(), &Account::accountChangedAvatar, this, &User::avatarChanged);
|
connect(_account->account().data(), &Account::accountChangedAvatar, this, &User::avatarChanged);
|
||||||
|
|
||||||
|
connect(_activityModel, &ActivityListModel::sendNotificationRequest, this, &User::slotSendNotificationRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void User::slotBuildNotificationDisplay(const ActivityList &list)
|
void User::slotBuildNotificationDisplay(const ActivityList &list)
|
||||||
@ -329,7 +331,7 @@ void User::slotAddError(const QString &folderAlias, const QString &message, Erro
|
|||||||
link._label = tr("Retry all uploads");
|
link._label = tr("Retry all uploads");
|
||||||
link._link = folderInstance->path();
|
link._link = folderInstance->path();
|
||||||
link._verb = "";
|
link._verb = "";
|
||||||
link._isPrimary = true;
|
link._primary = true;
|
||||||
activity._links.append(link);
|
activity._links.append(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,23 +108,11 @@ Window {
|
|||||||
id: trayWindowHeaderBackground
|
id: trayWindowHeaderBackground
|
||||||
|
|
||||||
anchors.left: trayWindowBackground.left
|
anchors.left: trayWindowBackground.left
|
||||||
|
anchors.right: trayWindowBackground.right
|
||||||
anchors.top: trayWindowBackground.top
|
anchors.top: trayWindowBackground.top
|
||||||
height: Style.trayWindowHeaderHeight
|
height: Style.trayWindowHeaderHeight
|
||||||
width: Style.trayWindowWidth
|
|
||||||
color: Style.ncBlue
|
color: Style.ncBlue
|
||||||
|
|
||||||
// The overlay rectangle below eliminates the rounded corners from the bottom of the header
|
|
||||||
// as Qt only allows setting the radius for all corners right now, not specific ones
|
|
||||||
Rectangle {
|
|
||||||
id: trayWindowHeaderButtomHalfBackground
|
|
||||||
|
|
||||||
anchors.left: trayWindowHeaderBackground.left
|
|
||||||
anchors.bottom: trayWindowHeaderBackground.bottom
|
|
||||||
height: Style.trayWindowHeaderHeight / 2
|
|
||||||
width: Style.trayWindowWidth
|
|
||||||
color: Style.ncBlue
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: trayWindowHeaderLayout
|
id: trayWindowHeaderLayout
|
||||||
|
|
||||||
@ -511,16 +499,17 @@ Window {
|
|||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: activityListView
|
id: activityListView
|
||||||
|
|
||||||
anchors.top: trayWindowHeaderBackground.bottom
|
anchors.top: trayWindowHeaderBackground.bottom
|
||||||
anchors.horizontalCenter: trayWindowBackground.horizontalCenter
|
anchors.left: trayWindowBackground.left
|
||||||
width: Style.trayWindowWidth - Style.trayWindowBorderWidth
|
anchors.right: trayWindowBackground.right
|
||||||
height: Style.trayWindowHeight - Style.trayWindowHeaderHeight
|
anchors.bottom: trayWindowBackground.bottom
|
||||||
clip: true
|
clip: true
|
||||||
ScrollBar.vertical: ScrollBar {
|
ScrollBar.vertical: ScrollBar {
|
||||||
id: listViewScrollbar
|
id: listViewScrollbar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property int maxActionButtons: 2
|
||||||
|
|
||||||
keyNavigationEnabled: true
|
keyNavigationEnabled: true
|
||||||
|
|
||||||
Accessible.role: Accessible.List
|
Accessible.role: Accessible.List
|
||||||
@ -531,26 +520,28 @@ Window {
|
|||||||
delegate: RowLayout {
|
delegate: RowLayout {
|
||||||
id: activityItem
|
id: activityItem
|
||||||
|
|
||||||
|
readonly property variant links: model.links
|
||||||
|
|
||||||
|
readonly property int itemIndex: model.index
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: Style.trayWindowHeaderHeight
|
height: Style.trayWindowHeaderHeight
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
Accessible.role: Accessible.ListItem
|
Accessible.role: Accessible.ListItem
|
||||||
Accessible.name: path !== "" ? qsTr("Open %1 locally").arg(displayPath)
|
Accessible.name: path !== "" ? qsTr("Open %1 locally").arg(displayPath)
|
||||||
: message
|
: message
|
||||||
Accessible.onPressAction: activityMouseArea.clicked()
|
Accessible.onPressAction: activityMouseArea.clicked()
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: activityMouseArea
|
id: activityMouseArea
|
||||||
enabled: (path !== "" || link !== "")
|
enabled: (path !== "" || link !== "")
|
||||||
anchors.left: activityItem.left
|
anchors.left: activityItem.left
|
||||||
anchors.right: (shareButton.visible) ? shareButton.left
|
anchors.right: activityActionsLayout.right
|
||||||
: (replyButton.visible) ? replyButton.left
|
|
||||||
: activityItem.right
|
|
||||||
height: parent.height
|
height: parent.height
|
||||||
anchors.margins: 2
|
anchors.margins: 2
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: activityModel.triggerActionAtIndex(model.index)
|
onClicked: activityModel.triggerDefaultAction(model.index)
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -575,13 +566,14 @@ Window {
|
|||||||
Column {
|
Column {
|
||||||
id: activityTextColumn
|
id: activityTextColumn
|
||||||
anchors.left: activityIcon.right
|
anchors.left: activityIcon.right
|
||||||
|
anchors.right: activityActionsLayout.left
|
||||||
anchors.leftMargin: 8
|
anchors.leftMargin: 8
|
||||||
spacing: 4
|
spacing: 4
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
Text {
|
Text {
|
||||||
id: activityTextTitle
|
id: activityTextTitle
|
||||||
text: (type === "Activity" || type === "Notification") ? subject : message
|
text: (type === "Activity" || type === "Notification") ? subject : message
|
||||||
width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.pixelSize: Style.topLinePixelSize
|
font.pixelSize: Style.topLinePixelSize
|
||||||
color: activityTextTitleColor
|
color: activityTextTitleColor
|
||||||
@ -594,7 +586,7 @@ Window {
|
|||||||
: (type === "Notification") ? message
|
: (type === "Notification") ? message
|
||||||
: ""
|
: ""
|
||||||
height: (text === "") ? 0 : activityTextTitle.height
|
height: (text === "") ? 0 : activityTextTitle.height
|
||||||
width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.pixelSize: Style.subLinePixelSize
|
font.pixelSize: Style.subLinePixelSize
|
||||||
}
|
}
|
||||||
@ -603,7 +595,7 @@ Window {
|
|||||||
id: activityTextDateTime
|
id: activityTextDateTime
|
||||||
text: dateTime
|
text: dateTime
|
||||||
height: (text === "") ? 0 : activityTextTitle.height
|
height: (text === "") ? 0 : activityTextTitle.height
|
||||||
width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8
|
width: parent.width
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.pixelSize: Style.subLinePixelSize
|
font.pixelSize: Style.subLinePixelSize
|
||||||
color: "#808080"
|
color: "#808080"
|
||||||
@ -624,56 +616,175 @@ Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button {
|
RowLayout {
|
||||||
id: shareButton
|
id: activityActionsLayout
|
||||||
anchors.right: activityItem.right
|
anchors.right: activityItem.right
|
||||||
|
spacing: 0
|
||||||
Layout.preferredWidth: (path === "") ? 0 : parent.height
|
|
||||||
Layout.preferredHeight: parent.height
|
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
flat: true
|
|
||||||
hoverEnabled: true
|
function actionButtonIcon(actionIndex) {
|
||||||
visible: (path === "") ? false : true
|
const verb = String(model.links[actionIndex].verb);
|
||||||
display: AbstractButton.IconOnly
|
if (verb === "WEB" && (model.objectType === "chat" || model.objectType === "call")) {
|
||||||
icon.source: "qrc:///client/theme/share.svg"
|
return "qrc:///client/theme/reply.svg";
|
||||||
icon.color: "transparent"
|
} else if (verb === "DELETE") {
|
||||||
background: Rectangle {
|
return "qrc:///client/theme/close.svg";
|
||||||
color: parent.hovered ? Style.lightHover : "transparent"
|
}
|
||||||
|
|
||||||
|
return "qrc:///client/theme/confirm.svg";
|
||||||
}
|
}
|
||||||
ToolTip.visible: hovered
|
|
||||||
ToolTip.delay: 1000
|
|
||||||
ToolTip.text: qsTr("Open share dialog")
|
|
||||||
onClicked: Systray.openShareDialog(displayPath,absolutePath)
|
|
||||||
|
|
||||||
Accessible.role: Accessible.Button
|
Repeater {
|
||||||
Accessible.name: qsTr("Share %1").arg(displayPath)
|
model: activityItem.links.length > activityListView.maxActionButtons ? 1 : activityItem.links.length
|
||||||
Accessible.onPressAction: shareButton.clicked()
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
ActivityActionButton {
|
||||||
id: replyButton
|
id: activityActionButton
|
||||||
anchors.right: activityItem.right
|
|
||||||
|
readonly property int actionIndex: model.index
|
||||||
|
readonly property bool primary: model.index === 0 && String(activityItem.links[actionIndex].verb) !== "DELETE"
|
||||||
|
|
||||||
|
height: activityItem.height
|
||||||
|
|
||||||
|
text: !primary ? "" : activityItem.links[actionIndex].label
|
||||||
|
|
||||||
|
imageSource: !primary ? activityActionsLayout.actionButtonIcon(actionIndex) : ""
|
||||||
|
|
||||||
|
textColor: primary ? Style.ncBlue : "black"
|
||||||
|
textColorHovered: Style.lightHover
|
||||||
|
|
||||||
|
textBorderColor: Style.ncBlue
|
||||||
|
|
||||||
|
textBgColor: "transparent"
|
||||||
|
textBgColorHovered: Style.ncBlue
|
||||||
|
|
||||||
|
tooltipText: activityItem.links[actionIndex].label
|
||||||
|
|
||||||
|
Layout.minimumWidth: primary ? 80 : -1
|
||||||
|
Layout.minimumHeight: parent.height
|
||||||
|
|
||||||
|
Layout.preferredWidth: primary ? -1 : parent.height
|
||||||
|
|
||||||
|
onClicked: activityModel.triggerAction(activityItem.itemIndex, actionIndex)
|
||||||
|
}
|
||||||
|
|
||||||
Layout.preferredWidth: (objectType == "chat" || objectType == "call") ? parent.height : 0
|
|
||||||
Layout.preferredHeight: parent.height
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
flat: true
|
|
||||||
hoverEnabled: true
|
|
||||||
visible: (objectType == "chat" || objectType == "call") ? true : false
|
|
||||||
display: AbstractButton.IconOnly
|
|
||||||
icon.source: "qrc:///client/theme/reply.svg"
|
|
||||||
icon.color: "transparent"
|
|
||||||
background: Rectangle {
|
|
||||||
color: parent.hovered ? Style.lightHover : "transparent"
|
|
||||||
}
|
}
|
||||||
ToolTip.visible: hovered
|
|
||||||
ToolTip.delay: 1000
|
|
||||||
ToolTip.text: qsTr("Open Talk")
|
|
||||||
onClicked: Qt.openUrlExternally(link)
|
|
||||||
|
|
||||||
Accessible.role: Accessible.Button
|
Button {
|
||||||
Accessible.name: qsTr("Open Talk %1").arg(link)
|
id: moreActionsButton
|
||||||
Accessible.onPressAction: replyButton.clicked()
|
|
||||||
|
Layout.preferredWidth: parent.height
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
|
flat: true
|
||||||
|
hoverEnabled: true
|
||||||
|
visible: activityItem.links.length > activityListView.maxActionButtons
|
||||||
|
display: AbstractButton.IconOnly
|
||||||
|
icon.source: "qrc:///client/theme/more.svg"
|
||||||
|
icon.color: "transparent"
|
||||||
|
background: Rectangle {
|
||||||
|
color: parent.hovered ? Style.lightHover : "transparent"
|
||||||
|
}
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.delay: 1000
|
||||||
|
ToolTip.text: qsTr("Show more actions")
|
||||||
|
|
||||||
|
Accessible.role: Accessible.Button
|
||||||
|
Accessible.name: qsTr("Show more actions")
|
||||||
|
Accessible.onPressAction: moreActionsButton.clicked()
|
||||||
|
|
||||||
|
onClicked: moreActionsButtonContextMenu.popup();
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: trayWindow
|
||||||
|
onActiveChanged: {
|
||||||
|
if (!trayWindow.active) {
|
||||||
|
moreActionsButtonContextMenu.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: activityListView
|
||||||
|
|
||||||
|
onMovementStarted: {
|
||||||
|
moreActionsButtonContextMenu.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Container {
|
||||||
|
id: moreActionsButtonContextMenuContainer
|
||||||
|
visible: moreActionsButtonContextMenu.opened
|
||||||
|
|
||||||
|
width: moreActionsButtonContextMenu.width
|
||||||
|
height: moreActionsButtonContextMenu.height
|
||||||
|
anchors.right: moreActionsButton.right
|
||||||
|
anchors.top: moreActionsButton.top
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id: moreActionsButtonContextMenu
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
// transform model to contain indexed actions with primary action filtered out
|
||||||
|
function actionListToContextMenuList(actionList) {
|
||||||
|
// early out with non-altered data
|
||||||
|
if (activityItem.links.length <= activityListView.maxActionButtons) {
|
||||||
|
return actionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add index to every action and filter 'primary' action out
|
||||||
|
var reducedActionList = actionList.reduce(function(reduced, action, index) {
|
||||||
|
if (!action.primary) {
|
||||||
|
var actionWithIndex = { actionIndex: index, label: action.label };
|
||||||
|
reduced.push(actionWithIndex);
|
||||||
|
}
|
||||||
|
return reduced;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
return reducedActionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: moreActionsButtonContextMenuRepeater
|
||||||
|
|
||||||
|
model: moreActionsButtonContextMenu.actionListToContextMenuList(activityItem.links)
|
||||||
|
|
||||||
|
delegate: MenuItem {
|
||||||
|
id: moreActionsButtonContextMenuEntry
|
||||||
|
readonly property int actionIndex: model.modelData.actionIndex
|
||||||
|
readonly property string label: model.modelData.label
|
||||||
|
text: label
|
||||||
|
onTriggered: activityModel.triggerAction(activityItem.itemIndex, actionIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: shareButton
|
||||||
|
|
||||||
|
Layout.preferredWidth: (path === "") ? 0 : parent.height
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
flat: true
|
||||||
|
hoverEnabled: true
|
||||||
|
visible: (path === "") ? false : true
|
||||||
|
display: AbstractButton.IconOnly
|
||||||
|
icon.source: "qrc:///client/theme/share.svg"
|
||||||
|
icon.color: "transparent"
|
||||||
|
background: Rectangle {
|
||||||
|
color: parent.hovered ? Style.lightHover : "transparent"
|
||||||
|
}
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.delay: 1000
|
||||||
|
ToolTip.text: qsTr("Open share dialog")
|
||||||
|
onClicked: Systray.openShareDialog(displayPath,absolutePath)
|
||||||
|
|
||||||
|
Accessible.role: Accessible.Button
|
||||||
|
Accessible.name: qsTr("Share %1").arg(displayPath)
|
||||||
|
Accessible.onPressAction: shareButton.clicked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user