diff --git a/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml b/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml index b07e33a245..10447fb5ba 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/ChatMessages.qml @@ -1,4 +1,5 @@ import QtQuick 2.13 +import Qt.labs.platform 1.1 import QtQuick.Controls 2.13 import QtQuick.Window 2.13 import QtQuick.Layouts 1.13 @@ -29,6 +30,8 @@ ScrollView { ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ListView { + property string currentNotificationChatId + id: chatLogView anchors.fill: parent anchors.bottomMargin: Style.current.bigPadding @@ -118,6 +121,12 @@ ScrollView { return true } + function clickOnNotification(chatId) { + applicationWindow.raise() + chatsModel.setActiveChannel(chatId) + appMain.changeAppSection(Constants.chat) + applicationWindow.requestActivate() + } Connections { @@ -151,14 +160,50 @@ ScrollView { onMessageNotificationPushed: function(chatId, msg, messageType, chatType, timestamp, identicon, username, hasMention, isAddedContact, channelName) { if (appSettings.notificationSetting == Constants.notifyAllMessages || (appSettings.notificationSetting == Constants.notifyJustMentions && hasMention)) { - if (chatType === Constants.chatTypeOneToOne && !appSettings.allowNotificationsFromNonContacts && !isAddedContact) { - return + if (chatType === Constants.chatTypeOneToOne && !appSettings.allowNotificationsFromNonContacts && !isAddedContact) { + return + } + chatLogView.currentNotificationChatId = chatId + + let name; + if (appSettings.notificationMessagePreviewSetting === Constants.notificationPreviewAnonymous) { + name = "Status" + } else if (chatType === Constants.chatTypePublic) { + name = chatId + } else { + name = chatType === Constants.chatTypePrivateGroupChat ? Utils.filterXSS(channelName) : Utils.removeStatusEns(username) + } + + let message; + if (appSettings.notificationMessagePreviewSetting > Constants.notificationPreviewNameOnly) { + switch(messageType){ + case Constants.imageType: message = qsTr("Image"); break + case Constants.stickerType: message = qsTr("Sticker"); break + default: message = Emoji.parse(msg, "26x26").replace(/\n|\r/g, ' ') } - notificationWindow.notifyUser(chatId, msg, messageType, chatType, timestamp, identicon, username, channelName) + } else { + message = qsTr("You have a new message") + } + + if (appSettings.useOSNotifications && systemTray.supportsMessages) { + systemTray.showMessage(name, + message, + SystemTrayIcon.NoIcon, + Constants.notificationPopupTTL) + } else { + notificationWindow.notifyUser(chatId, name, message, chatType, identicon, chatLogView.clickOnNotification) + } } } } + Connections { + target: systemTray + onMessageClicked: { + chatLogView.clickOnNotification(chatLogView.currentNotificationChatId) + } + } + property var loadMsgs : Backpressure.oneInTime(chatLogView, 500, function() { if(loadingMessages) return; loadingMessages = true; diff --git a/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml b/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml index 926b44aea6..991bef87ac 100644 --- a/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml +++ b/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml @@ -160,6 +160,34 @@ ScrollView { } } + RowLayout { + width: parent.width + StyledText { + text: qsTr("Use your operating system's notifications") + font.pixelSize: 15 + wrapMode: Text.WordWrap + Layout.fillWidth: true + + StyledText { + id: detailText + text: qsTr("Setting this to false will instead use Status' notification style as seen below") + color: Style.current.secondaryText + width: parent.width + font.pixelSize: 12 + wrapMode: Text.WordWrap + anchors.top: parent.bottom + } + } + + StatusSwitch { + Layout.alignment: Qt.AlignRight + checked: appSettings.useOSNotifications + onCheckedChanged: { + appSettings.useOSNotifications = checked + } + } + } + /* GridLayout { */ /* columns: 4 */ /* width: parent.width */ diff --git a/ui/imports/Constants.qml b/ui/imports/Constants.qml index 28d0f5501a..f2d7c2fc76 100644 --- a/ui/imports/Constants.qml +++ b/ui/imports/Constants.qml @@ -15,6 +15,8 @@ QtObject { readonly property int limitLongChatText: 500 readonly property int limitLongChatTextCompactMode: 1000 + readonly property int notificationPopupTTL: 5000 + readonly property string chat: "chat" readonly property string wallet: "wallet" readonly property string browser: "browser" diff --git a/ui/main.qml b/ui/main.qml index 8789029822..e07544c941 100644 --- a/ui/main.qml +++ b/ui/main.qml @@ -102,6 +102,7 @@ ApplicationWindow { property real volume: 0.2 property int notificationSetting: Constants.notifyAllMessages property bool notificationSoundsEnabled: true + property bool useOSNotifications: true property int notificationMessagePreviewSetting: Constants.notificationPreviewNameAndMessage property bool allowNotificationsFromNonContacts: false property var whitelistedUnfurlingSites: ({}) @@ -139,6 +140,7 @@ ApplicationWindow { property real volume: defaultAppSettings.volume property int notificationSetting: defaultAppSettings.notificationSetting property bool notificationSoundsEnabled: defaultAppSettings.notificationSoundsEnabled + property bool useOSNotifications: defaultAppSettings.useOSNotifications property int notificationMessagePreviewSetting: defaultAppSettings.notificationMessagePreviewSetting property bool allowNotificationsFromNonContacts: defaultAppSettings.allowNotificationsFromNonContacts property var whitelistedUnfurlingSites: defaultAppSettings.whitelistedUnfurlingSites @@ -178,6 +180,7 @@ ApplicationWindow { } SystemTrayIcon { + id: systemTray visible: true icon.source: "shared/img/status-logo.png" menu: Menu { diff --git a/ui/shared/NotificationWindow.qml b/ui/shared/NotificationWindow.qml index 527abd508c..7586bd0c73 100644 --- a/ui/shared/NotificationWindow.qml +++ b/ui/shared/NotificationWindow.qml @@ -11,13 +11,11 @@ import "../app/AppLayouts/Chat/ContactsColumn" Item { id: root property string chatId: "" + property string name: "channel name" property string message: "Everything is connected" - property int messageType: 1 property int chatType: 1 - property string timestamp: "20/2/2020" + property var onClick property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQAQMAAAC6caSPAAAABlBMVEXMzMz////TjRV2AAAAAWJLR0QB/wIt3gAAACpJREFUGBntwYEAAAAAw6D7Uw/gCtUAAAAAAAAAAAAAAAAAAAAAAAAAgBNPsAABAjKCqQAAAABJRU5ErkJggg==" - property string username: "@jonas" - property string channelName: "sic-mundus" property var processClick: Backpressure.oneInTime(root, 1000, function () { notificationSound.play() @@ -55,25 +53,8 @@ Item { StatusNotification { id: channelNotif chatId: root.chatId - name: { - if (appSettings.notificationMessagePreviewSetting === Constants.notificationPreviewAnonymous) { - return "Status" - } - if (root.chatType === Constants.chatTypePublic) { - return root.chatId - } - return root.chatType === Constants.chatTypePrivateGroupChat ? Utils.filterXSS(root.channelName) : Utils.removeStatusEns(root.username) - } - message: { - if (appSettings.notificationMessagePreviewSetting > Constants.notificationPreviewNameOnly) { - switch(root.messageType){ - case Constants.imageType: return qsTr("Image"); - case Constants.stickerType: return qsTr("Sticker"); - default: return Emoji.parse(root.message, "26x26").replace(/\n|\r/g, ' ') - } - } - return qsTr("You have a new message") - } + name: root.name + message: root.message chatType: root.chatType identicon: root.identicon @@ -83,19 +64,19 @@ Item { onClicked: { timer.stop() notificationWindowSub.close() - applicationWindow.raise() - chatsModel.setActiveChannel(chatId) - applicationWindow.requestActivate() + root.onClick(root.chatId) + notificationWindowSub.destroy() } } Timer { id: timer - interval: 4000 - running: false + interval: Constants.notificationPopupTTL + running: true repeat: false onTriggered: { notificationWindowSub.close() + notificationWindowSub.destroy() } } onVisibleChanged: { @@ -113,15 +94,13 @@ Item { } } - function notifyUser(chatId, msg, messageType, chatType, timestamp, identicon, username, channelName) { + function notifyUser(chatId, name, msg, chatType, identicon, onClick) { this.chatId = chatId + this.name = name this.message = msg - this.messageType = parseInt(messageType, 10) this.chatType = chatType - this.timestamp = timestamp this.identicon = identicon - this.username = username - this.channelName = channelName + this.onClick = onClick processClick() } }