fix(ActivityCenter): Getting any of AC notifications visible

Close #7016
This commit is contained in:
MishkaRogachev 2022-09-15 19:34:41 +03:00 committed by Mikhail Rogachev
parent 6668803fb3
commit edbd9adbb6
9 changed files with 337 additions and 149 deletions

View File

@ -26,11 +26,11 @@ QtObject:
proc activityNotificationsChanged*(self: View) {.signal.}
proc getModel(self: View): QVariant {.slot.} =
proc getActivityNotificationModel(self: View): QVariant {.slot.} =
return newQVariant(self.modelVariant)
QtProperty[QVariant] model:
read = getModel
QtProperty[QVariant] activityNotificationsModel:
read = getActivityNotificationModel
notify = activityNotificationsChanged
proc hasMoreToShowChanged*(self: View) {.signal.}

View File

@ -121,9 +121,13 @@ QtObject {
property var mainModuleInst: mainModule
property var activityCenterModuleInst: activityCenterModule
property var activityCenterList: activityCenterModuleInst.model
property var activityCenterList: activityCenterModuleInst.activityNotificationsModel
property int unreadNotificationsCount: activityCenterList.unreadCount
function loadMoreNotifications() {
activityCenterModuleInst.loadMoreNotifications()
}
property var communitiesModuleInst: communitiesModule
property var communitiesList: communitiesModuleInst.model
property bool communityPermissionsEnabled: localAccountSensitiveSettings.isCommunityPermissionsEnabled

View File

@ -1,11 +1,13 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQml.Models 2.13
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtGraphicalEffects 1.13
import Qt.labs.qmlmodels 1.0
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import SortFilterProxyModel 0.2
import shared 1.0
import shared.popups 1.0
import shared.views.chat 1.0
@ -42,7 +44,30 @@ Popup {
reactionModel: root.store.emojiReactionsModel
}
readonly property int unreadNotificationsCount : root.store.activityCenterList.unreadCount
readonly property int unreadNotificationsCount : root.store.unreadNotificationsCount
function filterActivityCategories(notificationType) {
switch (root.currentActivityCategory) {
case ActivityCenterPopup.ActivityCategory.All:
return true
case ActivityCenterPopup.ActivityCategory.Mentions:
return notificationType === Constants.activityCenterNotificationTypeMention
case ActivityCenterPopup.ActivityCategory.Replies:
return notificationType === Constants.activityCenterNotificationTypeReply
case ActivityCenterPopup.ActivityCategory.ContactRequests:
return notificationType === Constants.activityCenterNotificationTypeContactRequest
default:
return false
}
}
onOpened: {
root.store.loadMoreNotifications()
Global.popupOpened = true
}
onClosed: {
Global.popupOpened = false
}
modal: false
@ -69,12 +94,6 @@ Popup {
}
}
x: Global.applicationWindow.width - root.width - Style.current.halfPadding
onOpened: {
Global.popupOpened = true
}
onClosed: {
Global.popupOpened = false
}
padding: 0
ActivityCenterPopupTopBarPanel {
@ -92,149 +111,182 @@ Popup {
}
}
// TODO: replace with StatusListView
StatusScrollView {
id: scrollView
StatusListView {
id: listView
anchors.left: parent.left
anchors.right: parent.right
anchors.top: activityCenterTopBar.bottom
anchors.topMargin: 13
anchors.bottom: parent.bottom
anchors.bottomMargin: Style.current.smallPadding
width: parent.width
anchors.margins: Style.current.smallPadding
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
model: SortFilterProxyModel {
sourceModel: root.store.activityCenterList
Column {
id: notificationsContainer
width: scrollView.availableWidth
spacing: 0
filters: ExpressionFilter { expression: filterActivityCategories(model.notificationType) }
}
Repeater {
model: notifDelegateList
delegate: DelegateChooser {
role: "notificationType"
DelegateChoice {
roleValue: Constants.activityCenterNotificationTypeMention
ActivityNotificationMention { store: root.store; notification: model }
}
DelegateModelGeneralized {
id: notifDelegateList
lessThan: [
function(left, right) { return left.timestamp > right.timestamp }
]
model: root.store.activityCenterList
delegate: Item {
id: notificationDelegate
width: parent.availableWidth
height: notifLoader.active ? childrenRect.height : 0
property int idx: DelegateModel.itemsIndex
Component.onCompleted: {
switch (model.notificationType) {
case Constants.activityCenterNotificationTypeMention:
if (!hasMentions) {
hasMentions = true
}
break
case Constants.activityCenterNotificationTypeReply:
if (!hasReplies) {
hasReplies = true
}
break
}
}
Loader {
property int previousNotificationIndex: {
if (notificationDelegate.idx === 0) {
return 0
}
// This is used in order to have access to the previous message and determine the timestamp
// we can't rely on the index because the sequence of messages is not ordered on the nim side
if (notificationDelegate.idx < notifDelegateList.items.count - 1) {
return notifDelegateList.items.get(notificationDelegate.idx - 1).model.index
}
return -1;
}
readonly property string previousNotificationTimestamp: notificationDelegate.idx === 0 ? "" :
root.store.activityCenterList.getNotificationData(previousNotificationIndex, "timestamp")
onPreviousNotificationTimestampChanged: {
root.store.messageStore.prevMsgTimestamp = previousNotificationTimestamp;
}
id: notifLoader
anchors.top: parent.top
active: !!sourceComponent
width: parent.width
sourceComponent: {
switch (model.notificationType) {
case Constants.activityCenterNotificationTypeOneToOne:
case Constants.activityCenterNotificationTypeMention:
case Constants.activityCenterNotificationTypeReply: return messageNotificationComponent
case Constants.activityCenterNotificationTypeGroupRequest: return groupRequestNotificationComponent
default: return null
}
}
onLoaded: {
if (model.notificationType === Constants.activityCenterNotificationTypeReply ||
model.notificationType === Constants.activityCenterNotificationTypeGroupRequest) {
item.previousNotificationIndex = Qt.binding(() => notifLoader.previousNotificationIndex);
item.previousNotificationTimestamp = Qt.binding(() => notifLoader.previousNotificationTimestamp);
}
}
}
Component {
id: messageNotificationComponent
ActivityCenterMessageComponentView {
id: activityCenterMessageView
store: root.store
acCurrentActivityCategory: root.currentActivityCategory
chatSectionModule: root.chatSectionModule
messageContextMenu: root.messageContextMenu
hideReadNotifications: root.hideReadNotifications
Connections {
target: root
onOpened: activityCenterMessageView.reevaluateItemBadge()
}
onActivityCenterClose: {
root.close();
}
Component.onCompleted: {
activityCenterMessageView.reevaluateItemBadge()
}
}
}
Component {
id: groupRequestNotificationComponent
ActivityCenterGroupRequest {
store: root.store
hideReadNotifications: root.hideReadNotifications
acCurrentActivityCategoryAll: root.currentActivityCategory === ActivityCenter.ActivityCategory.All
}
}
}
DelegateChoice {
roleValue: Constants.activityCenterNotificationTypeReply
ActivityNotificationReply { store: root.store; notification: model }
}
Item {
visible: root.store.activityCenterModuleInst.hasMoreToShow
width: parent.width
height: visible ? showMoreBtn.height + showMoreBtn.anchors.topMargin : 0
StatusButton {
id: showMoreBtn
text: qsTr("Show more")
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
onClicked: root.store.activityCenterModuleInst.loadMoreNotifications()
}
DelegateChoice {
roleValue: Constants.activityCenterNotificationTypeContactRequest
ActivityNotificationContactRequest { store: root.store; notification: model }
}
}
}
}
// // TODO: replace with StatusListView
// StatusScrollView {
// id: scrollView
// anchors.left: parent.left
// anchors.right: parent.right
// anchors.top: activityCenterTopBar.bottom
// anchors.topMargin: 13
// anchors.bottom: parent.bottom
// anchors.bottomMargin: Style.current.smallPadding
// width: parent.width
// ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
// Column {
// id: notificationsContainer
// width: scrollView.availableWidth
// spacing: 0
// Repeater {
// model: notifDelegateList
// }
// DelegateModelGeneralized {
// id: notifDelegateList
// lessThan: [
// function(left, right) { return left.timestamp > right.timestamp }
// ]
// model: root.store.activityCenterList
// delegate: Item {
// id: notificationDelegate
// width: parent.availableWidth
// height: notifLoader.active ? childrenRect.height : 0
// property int idx: DelegateModel.itemsIndex
// Component.onCompleted: {
// switch (model.notificationType) {
// case Constants.activityCenterNotificationTypeMention:
// if (!hasMentions) {
// hasMentions = true
// }
// break
// case Constants.activityCenterNotificationTypeReply:
// if (!hasReplies) {
// hasReplies = true
// }
// break
// }
// }
// Loader {
// property int previousNotificationIndex: {
// if (notificationDelegate.idx === 0) {
// return 0
// }
// // This is used in order to have access to the previous message and determine the timestamp
// // we can't rely on the index because the sequence of messages is not ordered on the nim side
// if (notificationDelegate.idx < notifDelegateList.items.count - 1) {
// return notifDelegateList.items.get(notificationDelegate.idx - 1).model.index
// }
// return -1;
// }
// readonly property string previousNotificationTimestamp: notificationDelegate.idx === 0 ? "" :
// root.store.activityCenterList.getNotificationData(previousNotificationIndex, "timestamp")
// onPreviousNotificationTimestampChanged: {
// root.store.messageStore.prevMsgTimestamp = previousNotificationTimestamp;
// }
// id: notifLoader
// anchors.top: parent.top
// active: !!sourceComponent
// width: parent.width
// sourceComponent: {
// switch (model.notificationType) {
// case Constants.activityCenterNotificationTypeOneToOne:
// case Constants.activityCenterNotificationTypeMention:
// case Constants.activityCenterNotificationTypeReply: return messageNotificationComponent
// case Constants.activityCenterNotificationTypeGroupRequest: return groupRequestNotificationComponent
// default: return null
// }
// }
// onLoaded: {
// if (model.notificationType === Constants.activityCenterNotificationTypeReply ||
// model.notificationType === Constants.activityCenterNotificationTypeGroupRequest) {
// item.previousNotificationIndex = Qt.binding(() => notifLoader.previousNotificationIndex);
// item.previousNotificationTimestamp = Qt.binding(() => notifLoader.previousNotificationTimestamp);
// }
// }
// }
// Component {
// id: messageNotificationComponent
// ActivityCenterMessageComponentView {
// id: activityCenterMessageView
// store: root.store
// acCurrentActivityCategory: root.currentActivityCategory
// chatSectionModule: root.chatSectionModule
// messageContextMenu: root.messageContextMenu
// hideReadNotifications: root.hideReadNotifications
// Connections {
// target: root
// onOpened: activityCenterMessageView.reevaluateItemBadge()
// }
// onActivityCenterClose: {
// root.close();
// }
// Component.onCompleted: {
// activityCenterMessageView.reevaluateItemBadge()
// }
// }
// }
// Component {
// id: groupRequestNotificationComponent
// ActivityCenterGroupRequest {
// store: root.store
// hideReadNotifications: root.hideReadNotifications
// acCurrentActivityCategoryAll: root.currentActivityCategory === ActivityCenter.ActivityCategory.All
// }
// }
// }
// }
// Item {
// visible: root.store.activityCenterModuleInst.hasMoreToShow
// width: parent.width
// height: visible ? showMoreBtn.height + showMoreBtn.anchors.topMargin : 0
// StatusButton {
// id: showMoreBtn
// text: qsTr("Show more")
// anchors.horizontalCenter: parent.horizontalCenter
// anchors.top: parent.top
// anchors.topMargin: Style.current.smallPadding
// onClicked: root.store.activityCenterModuleInst.loadMoreNotifications()
// }
// }
// }
// }
// }

View File

@ -0,0 +1,46 @@
import QtQuick 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import shared 1.0
import utils 1.0
Item {
id: root
property var notification
property var store
property alias markReadBtnVisible: markReadBtn.visible
width: listView.availableWidth
height: 50
StatusFlatRoundButton {
id: markReadBtn
width: 32
height: 32
icon.width: 24
icon.height: 24
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
icon.source: Style.svg("check-activity")
icon.color: notification.read ? icon.disabledColor : "transparent"
color: "transparent"
tooltip.text: !notification.read ? qsTr("Mark as Read") : qsTr("Mark as Unread")
tooltip.orientation: StatusToolTip.Orientation.Left
tooltip.x: -tooltip.width - Style.current.padding
tooltip.y: 4
onClicked: {
notification.read ?
root.store.activityCenterModuleInst.markActivityCenterNotificationUnread(
notification.id, notification.message.communityId, notification.message.chatId, notification.notificationType) :
root.store.activityCenterModuleInst.markActivityCenterNotificationRead(
notification.id, notification.message.communityId, notification.chatId, notification.notificationType)
}
}
}

View File

@ -0,0 +1,49 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import shared 1.0
import utils 1.0
import shared.panels.chat 1.0
ActivityNotificationBase {
id: root
markReadBtnVisible: false
height: 60
StatusSmartIdenticon {
id: identicon
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter
name: notification.author
asset.color: Theme.palette.miscColor5
}
RowLayout {
anchors.top: parent.top
anchors.left: identicon.right
StatusBaseText {
text: notification.name
font.pixelSize: 15
color: Style.current.primary
}
StatusBaseText {
text: Utils.getElidedPk(notification.author) + " \u2022"
font.pixelSize: 12
color: Style.current.secondaryText
}
ChatTimePanel {
font.pixelSize: 12
color: Style.current.secondaryText
timestamp: notification.timestamp
}
}
}

View File

@ -0,0 +1,15 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import shared 1.0
import utils 1.0
import shared.panels.chat 1.0
ActivityNotificationBase {
id: root
}

View File

@ -0,0 +1,15 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import shared 1.0
import utils 1.0
import shared.panels.chat 1.0
ActivityNotificationBase {
id: root
}

View File

@ -424,11 +424,11 @@ QtObject {
readonly property int communityChatInvitationOnlyAccess: 2
readonly property int communityChatOnRequestAccess: 3
readonly property int activityCenterNotificationTypeOneToOne: 1
readonly property int activityCenterNotificationTypeGroupRequest: 2
readonly property int activityCenterNotificationTypeMention: 3
readonly property int activityCenterNotificationTypeReply: 4
readonly property int activityCenterNotificationTypeContactRequest: 5
readonly property int maxNbDaysToFetch: 30
readonly property int fetchRangeLast24Hours: 86400

View File

@ -605,12 +605,19 @@ QtObject {
return globalUtils.getCompressedPk(publicKey)
}
function getElidedPk(publicKey) {
if (publicKey === "") {
return ""
}
return StatusQUtils.Utils.elideText(publicKey, 5, 3)
}
function getElidedCompressedPk(publicKey) {
if (publicKey === "") {
return ""
}
let compressedPk = getCompressedPk(publicKey)
return StatusQUtils.Utils.elideText(compressedPk, 6, 3)
return getElidedPk(compressedPk, 6, 3)
}
function getTimeDifference(d1, d2) {