diff --git a/resources.qrc b/resources.qrc
index 437c9567a..f2f122987 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -5,5 +5,6 @@
         <file>src/gui/tray/HeaderButton.qml</file>
         <file>theme/Style/Style.qml</file>
         <file>theme/Style/qmldir</file>
+        <file>src/gui/tray/ActivityActionButton.qml</file>
     </qresource>
 </RCC>
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 5a49920e0..b6a666924 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -43,6 +43,7 @@ set(client_UI_SRCS
     addcertificatedialog.ui
     proxyauthdialog.ui
     mnemonicdialog.ui
+    tray/ActivityActionButton.qml
     tray/Window.qml
     tray/UserLine.qml
     wizard/flow2authwidget.ui
diff --git a/src/gui/tray/ActivityActionButton.qml b/src/gui/tray/ActivityActionButton.qml
new file mode 100644
index 000000000..6bb127e71
--- /dev/null
+++ b/src/gui/tray/ActivityActionButton.qml
@@ -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
+    }
+}
diff --git a/src/gui/tray/ActivityData.h b/src/gui/tray/ActivityData.h
index be30f77a2..f8bbef101 100644
--- a/src/gui/tray/ActivityData.h
+++ b/src/gui/tray/ActivityData.h
@@ -27,11 +27,18 @@ namespace OCC {
 
 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:
     QString _label;
     QString _link;
     QByteArray _verb;
-    bool _isPrimary;
+    bool _primary;
 };
 
 /* ==================================================================== */
diff --git a/src/gui/tray/ActivityListModel.cpp b/src/gui/tray/ActivityListModel.cpp
index 15d7a22bd..a2d39252d 100644
--- a/src/gui/tray/ActivityListModel.cpp
+++ b/src/gui/tray/ActivityListModel.cpp
@@ -53,6 +53,7 @@ QHash<int, QByteArray> ActivityListModel::roleNames() const
     roles[ActionRole] = "type";
     roles[ActionIconRole] = "icon";
     roles[ActionTextRole] = "subject";
+    roles[ActionsLinksRole] = "links";
     roles[ActionTextColorRole] = "activityTextTitleColor";
     roles[ObjectTypeRole] = "objectType";
     roles[PointInTimeRole] = "dateTime";
@@ -139,10 +140,8 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
     }
     case ActionsLinksRole: {
         QList<QVariant> customList;
-        foreach (ActivityLink customItem, a._links) {
-            QVariant customVariant;
-            customVariant.setValue(customItem);
-            customList << customVariant;
+        foreach (ActivityLink activityLink, a._links) {
+            customList << QVariant::fromValue(activityLink);
         }
         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()) {
-        qCWarning(lcActivity) << "Couldn't trigger action at index" << id << "/ final list size:" << _finalList.size();
+    if (activityIndex < 0 || activityIndex >= _finalList.size()) {
+        qCWarning(lcActivity) << "Couldn't trigger default action at index" << activityIndex << "/ final list size:" << _finalList.size();
         return;
     }
 
-    const auto modelIndex = index(id);
+    const auto modelIndex = index(activityIndex);
     const auto path = data(modelIndex, PathRole).toUrl();
 
-    const auto activity = _finalList.at(id);
+    const auto activity = _finalList.at(activityIndex);
     if (activity._status == SyncFileItem::Conflict) {
         Q_ASSERT(!activity._file.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()
 {
     ActivityList resultList;
diff --git a/src/gui/tray/ActivityListModel.h b/src/gui/tray/ActivityListModel.h
index f09d39d66..29b14e921 100644
--- a/src/gui/tray/ActivityListModel.h
+++ b/src/gui/tray/ActivityListModel.h
@@ -74,7 +74,8 @@ public:
     void removeActivityFromActivityList(int row);
     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:
     void slotRefreshActivity();
@@ -86,6 +87,7 @@ private slots:
 
 signals:
     void activityJobStatusCode(int statusCode);
+    void sendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);
 
 protected:
     QHash<int, QByteArray> roleNames() const override;
diff --git a/src/gui/tray/NotificationHandler.cpp b/src/gui/tray/NotificationHandler.cpp
index 445d0a88a..98e5c1aa7 100644
--- a/src/gui/tray/NotificationHandler.cpp
+++ b/src/gui/tray/NotificationHandler.cpp
@@ -128,7 +128,7 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
             al._label = QUrl::fromPercentEncoding(actionJson.value("label").toString().toUtf8());
             al._link = actionJson.value("link").toString();
             al._verb = actionJson.value("type").toString().toUtf8();
-            al._isPrimary = actionJson.value("primary").toBool();
+            al._primary = actionJson.value("primary").toBool();
 
             a._links.append(al);
         }
@@ -139,7 +139,7 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
         al._label = tr("Dismiss");
         al._link = Utility::concatUrlPath(ai->account()->url(), notificationsPath + "/" + QString::number(a._id)).toString();
         al._verb = "DELETE";
-        al._isPrimary = false;
+        al._primary = false;
         a._links.append(al);
 
         list.append(a);
diff --git a/src/gui/tray/UserModel.cpp b/src/gui/tray/UserModel.cpp
index 9df3dd111..8e83bc936 100644
--- a/src/gui/tray/UserModel.cpp
+++ b/src/gui/tray/UserModel.cpp
@@ -51,6 +51,8 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
     connect(this, &User::guiLog, Logger::instance(), &Logger::guiLog);
 
     connect(_account->account().data(), &Account::accountChangedAvatar, this, &User::avatarChanged);
+
+    connect(_activityModel, &ActivityListModel::sendNotificationRequest, this, &User::slotSendNotificationRequest);
 }
 
 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._link = folderInstance->path();
             link._verb = "";
-            link._isPrimary = true;
+            link._primary = true;
             activity._links.append(link);
         }
 
diff --git a/src/gui/tray/Window.qml b/src/gui/tray/Window.qml
index a007a9cb3..ac9de333f 100644
--- a/src/gui/tray/Window.qml
+++ b/src/gui/tray/Window.qml
@@ -108,23 +108,11 @@ Window {
             id: trayWindowHeaderBackground
 
             anchors.left:   trayWindowBackground.left
+            anchors.right:  trayWindowBackground.right
             anchors.top:    trayWindowBackground.top
             height:         Style.trayWindowHeaderHeight
-            width:          Style.trayWindowWidth
             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 {
                 id: trayWindowHeaderLayout
 
@@ -511,16 +499,17 @@ Window {
 
         ListView {
             id: activityListView
-
             anchors.top: trayWindowHeaderBackground.bottom
-            anchors.horizontalCenter: trayWindowBackground.horizontalCenter
-            width:  Style.trayWindowWidth - Style.trayWindowBorderWidth
-            height: Style.trayWindowHeight - Style.trayWindowHeaderHeight
+            anchors.left: trayWindowBackground.left
+            anchors.right: trayWindowBackground.right
+            anchors.bottom: trayWindowBackground.bottom
             clip: true
             ScrollBar.vertical: ScrollBar {
                 id: listViewScrollbar
             }
 
+            readonly property int maxActionButtons: 2
+
             keyNavigationEnabled: true
 
             Accessible.role: Accessible.List
@@ -531,26 +520,28 @@ Window {
             delegate: RowLayout {
                 id: activityItem
 
+                readonly property variant links: model.links
+
+                readonly property int itemIndex: model.index
+
                 width: parent.width
                 height: Style.trayWindowHeaderHeight
                 spacing: 0
 
                 Accessible.role: Accessible.ListItem
                 Accessible.name: path !== "" ? qsTr("Open %1 locally").arg(displayPath)
-                                                    : message
+                                             : message
                 Accessible.onPressAction: activityMouseArea.clicked()
 
                 MouseArea {
                     id: activityMouseArea
                     enabled: (path !== "" || link !== "")
                     anchors.left: activityItem.left
-                    anchors.right: (shareButton.visible) ? shareButton.left
-                                 : (replyButton.visible) ? replyButton.left
-                                 : activityItem.right
+                    anchors.right: activityActionsLayout.right
                     height: parent.height
                     anchors.margins: 2
                     hoverEnabled: true
-                    onClicked: activityModel.triggerActionAtIndex(model.index)
+                    onClicked: activityModel.triggerDefaultAction(model.index)
 
                     Rectangle {
                         anchors.fill: parent
@@ -575,13 +566,14 @@ Window {
                 Column {
                     id: activityTextColumn
                     anchors.left: activityIcon.right
+                    anchors.right: activityActionsLayout.left
                     anchors.leftMargin: 8
                     spacing: 4
                     Layout.alignment: Qt.AlignLeft
                     Text {
                         id: activityTextTitle
                         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
                         font.pixelSize: Style.topLinePixelSize
                         color: activityTextTitleColor
@@ -594,7 +586,7 @@ Window {
                             : (type === "Notification") ? message
                             : ""
                         height: (text === "") ? 0 : activityTextTitle.height
-                        width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8
+                        width: parent.width
                         elide: Text.ElideRight
                         font.pixelSize: Style.subLinePixelSize
                     }
@@ -603,7 +595,7 @@ Window {
                         id: activityTextDateTime
                         text: dateTime
                         height: (text === "") ? 0 : activityTextTitle.height
-                        width: Style.activityLabelBaseWidth + ((path === "") ? activityItem.height : 0) + ((link === "") ? activityItem.height : 0) - 8
+                        width: parent.width
                         elide: Text.ElideRight
                         font.pixelSize: Style.subLinePixelSize
                         color: "#808080"
@@ -624,56 +616,175 @@ Window {
                         }
                     }
                 }
-                Button {
-                    id: shareButton
+                RowLayout {
+                    id: activityActionsLayout
                     anchors.right: activityItem.right
-
-                    Layout.preferredWidth: (path === "") ? 0 : parent.height
-                    Layout.preferredHeight: parent.height
+                    spacing: 0
                     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"
+
+                    function actionButtonIcon(actionIndex) {
+                        const verb = String(model.links[actionIndex].verb);
+                        if (verb === "WEB" && (model.objectType === "chat" || model.objectType === "call")) {
+                            return "qrc:///client/theme/reply.svg";
+                        } else if (verb === "DELETE") {
+                            return "qrc:///client/theme/close.svg";
+                        }
+
+                        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
-                    Accessible.name: qsTr("Share %1").arg(displayPath)
-                    Accessible.onPressAction: shareButton.clicked()
-                }
+                    Repeater {
+                        model: activityItem.links.length > activityListView.maxActionButtons ? 1 : activityItem.links.length
 
-                Button {
-                    id: replyButton
-                    anchors.right: activityItem.right
+                        ActivityActionButton {
+                            id: activityActionButton
+
+                            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
-                    Accessible.name: qsTr("Open Talk %1").arg(link)
-                    Accessible.onPressAction: replyButton.clicked()
+                    Button {
+                        id: moreActionsButton
+
+                        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()
+                    }
                 }
             }