refactor(act-center): refactor activity center to the new arch
This commit is contained in:
parent
27f8c33dbd
commit
45fddc55ba
|
@ -27,6 +27,7 @@ import ../../app_service/service/stickers/service as stickers_service
|
|||
import ../../app_service/service/about/service as about_service
|
||||
import ../../app_service/service/node_configuration/service as node_configuration_service
|
||||
import ../../app_service/service/network/service as network_service
|
||||
import ../../app_service/service/activity_center/service as activity_center_service
|
||||
|
||||
import ../modules/startup/module as startup_module
|
||||
import ../modules/main/module as main_module
|
||||
|
@ -89,6 +90,7 @@ type
|
|||
stickersService: stickers_service.Service
|
||||
aboutService: about_service.Service
|
||||
networkService: network_service.Service
|
||||
activityCenterService: activity_center_service.Service
|
||||
languageService: language_service.Service
|
||||
mnemonicService: mnemonic_service.Service
|
||||
privacyService: privacy_service.Service
|
||||
|
@ -140,6 +142,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||
result.chatService = chat_service.newService(statusFoundation.status.events, result.contactsService)
|
||||
result.communityService = community_service.newService(result.chatService)
|
||||
result.messageService = message_service.newService(statusFoundation.status.events, statusFoundation.threadpool)
|
||||
result.activityCenterService = activity_center_service.newService(statusFoundation.status.events, statusFoundation.threadpool, result.chatService)
|
||||
result.tokenService = token_service.newService(statusFoundation.status.events, statusFoundation.threadpool,
|
||||
result.settingsService)
|
||||
result.collectibleService = collectible_service.newService(result.settingsService)
|
||||
|
@ -196,7 +199,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||
result.mnemonicService,
|
||||
result.privacyService,
|
||||
result.providerService,
|
||||
result.stickersService
|
||||
result.stickersService,
|
||||
result.activityCenterService
|
||||
)
|
||||
|
||||
# Do connections
|
||||
|
@ -226,6 +230,7 @@ proc delete*(self: AppController) =
|
|||
self.walletAccountService.delete
|
||||
self.aboutService.delete
|
||||
self.networkService.delete
|
||||
self.activityCenterService.delete
|
||||
self.dappPermissionsService.delete
|
||||
self.providerService.delete
|
||||
self.ensService.delete
|
||||
|
@ -270,6 +275,7 @@ proc load(self: AppController) =
|
|||
self.languageService.init()
|
||||
self.stickersService.init()
|
||||
self.networkService.init()
|
||||
self.activityCenterService.init()
|
||||
|
||||
let pubKey = self.settingsService.getPublicKey()
|
||||
singletonInstance.localAccountSensitiveSettings.setFileName(pubKey)
|
||||
|
|
|
@ -9,6 +9,7 @@ import status/types/community as old_community
|
|||
import ../../../../app_service/service/message/dto/[message, pinned_message, reaction]
|
||||
import ../../../../app_service/service/chat/dto/[chat]
|
||||
import ../../../../app_service/service/community/dto/[community]
|
||||
import ../../../../app_service/service/activity_center/dto/[notification]
|
||||
import ../../../../app_service/service/contacts/dto/[contacts, status_update]
|
||||
|
||||
type MessageSignal* = ref object of Signal
|
||||
|
@ -20,7 +21,7 @@ type MessageSignal* = ref object of Signal
|
|||
emojiReactions*: seq[ReactionDto]
|
||||
communities*: seq[CommunityDto]
|
||||
membershipRequests*: seq[old_community.CommunityMembershipRequest]
|
||||
activityCenterNotification*: seq[ActivityCenterNotification]
|
||||
activityCenterNotifications*: seq[ActivityCenterNotificationDto]
|
||||
statusUpdates*: seq[StatusUpdateDto]
|
||||
deletedMessages*: seq[RemovedMessage]
|
||||
|
||||
|
@ -70,7 +71,7 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
|
|||
|
||||
if event["event"]{"activityCenterNotifications"} != nil:
|
||||
for jsonNotification in event["event"]["activityCenterNotifications"]:
|
||||
signal.activityCenterNotification.add(jsonNotification.toActivityCenterNotification())
|
||||
signal.activityCenterNotifications.add(jsonNotification.toActivityCenterNotificationDto())
|
||||
|
||||
if event["event"]{"pinMessages"} != nil:
|
||||
discard
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
import Tables, stint
|
||||
import eventemitter
|
||||
import ./controller_interface
|
||||
import ./io_interface
|
||||
|
||||
import ../../../../app/core/signals/types
|
||||
import ../../../../app_service/service/activity_center/service as activity_center_service
|
||||
import ../../../../app_service/service/contacts/service as contacts_service
|
||||
import ../../../../app_service/service/chat/service as chat_service
|
||||
|
||||
export controller_interface
|
||||
|
||||
type
|
||||
Controller*[T: controller_interface.DelegateInterface] = ref object of controller_interface.AccessInterface
|
||||
delegate: io_interface.AccessInterface
|
||||
events: EventEmitter
|
||||
activityCenterService: activity_center_service.Service
|
||||
contactsService: contacts_service.Service
|
||||
|
||||
proc newController*[T](
|
||||
delegate: io_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
activityCenterService: activity_center_service.Service,
|
||||
contactsService: contacts_service.Service
|
||||
): Controller[T] =
|
||||
result = Controller[T]()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.activityCenterService = activityCenterService
|
||||
result.contactsService = contactsService
|
||||
|
||||
method delete*[T](self: Controller[T]) =
|
||||
discard
|
||||
|
||||
method init*[T](self: Controller[T]) =
|
||||
self.events.on(SIGNAL_ACTIVITY_CENTER_NOTIFICATIONS_LOADED) do(e: Args):
|
||||
let args = ActivityCenterNotificationsArgs(e)
|
||||
self.delegate.pushActivityCenterNotifications(args.activityCenterNotifications)
|
||||
|
||||
self.events.on(chat_service.SIGNAL_CHAT_UPDATE) do(e: Args):
|
||||
var evArgs = ChatUpdateArgsNew(e)
|
||||
if (evArgs.activityCenterNotifications.len > 0):
|
||||
self.delegate.addActivityCenterNotification(evArgs.activityCenterNotifications)
|
||||
|
||||
self.events.on(activity_center_service.SIGNAL_MARK_NOTIFICATIONS_AS_ACCEPTED) do(e: Args):
|
||||
var evArgs = MarkAsAcceptedNotificationProperties(e)
|
||||
self.delegate.acceptActivityCenterNotificationsDone(evArgs.notificationIds)
|
||||
|
||||
self.events.on(activity_center_service.SIGNAL_MARK_NOTIFICATIONS_AS_DISMISSED) do(e: Args):
|
||||
var evArgs = MarkAsDismissedNotificationProperties(e)
|
||||
self.delegate.dismissActivityCenterNotificationsDone(evArgs.notificationIds)
|
||||
|
||||
self.events.on(activity_center_service.SIGNAL_MARK_NOTIFICATIONS_AS_READ) do(e: Args):
|
||||
var evArgs = MarkAsReadNotificationProperties(e)
|
||||
if (evArgs.isAll):
|
||||
self.delegate.markAllActivityCenterNotificationsReadDone()
|
||||
return
|
||||
if (evArgs.notificationIds.len > 0):
|
||||
self.delegate.markActivityCenterNotificationReadDone(evArgs.notificationIds)
|
||||
|
||||
self.events.on(activity_center_service.SIGNAL_MARK_NOTIFICATIONS_AS_UNREAD) do(e: Args):
|
||||
var evArgs = MarkAsUnreadNotificationProperties(e)
|
||||
if (evArgs.notificationIds.len > 0):
|
||||
self.delegate.markActivityCenterNotificationUnreadDone(evArgs.notificationIds)
|
||||
|
||||
self.events.on(SignalType.Message.event) do(e: Args):
|
||||
var evArgs = MessageSignal(e)
|
||||
if (evArgs.activityCenterNotifications.len > 0):
|
||||
self.delegate.addActivityCenterNotification(evArgs.activityCenterNotifications)
|
||||
|
||||
|
||||
method hasMoreToShow*[T](self: Controller[T]): bool =
|
||||
return self.activityCenterService.hasMoreToShow()
|
||||
|
||||
method unreadActivityCenterNotificationsCount*[T](self: Controller[T]): int =
|
||||
return self.activityCenterService.unreadActivityCenterNotificationsCount()
|
||||
|
||||
method getContactDetails*[T](self: Controller[T], contactId: string): ContactDetails =
|
||||
return self.contactsService.getContactDetails(contactId)
|
||||
|
||||
method getActivityCenterNotifications*[T](self: Controller[T]): seq[ActivityCenterNotificationDto] =
|
||||
return self.activityCenterService.getActivityCenterNotifications()
|
||||
|
||||
method markAllActivityCenterNotificationsRead*[T](self: Controller[T]): string =
|
||||
return self.activityCenterService.markAllActivityCenterNotificationsRead()
|
||||
|
||||
method markActivityCenterNotificationRead*[T](
|
||||
self: Controller[T],
|
||||
notificationId: string,
|
||||
markAsReadProps: MarkAsReadNotificationProperties
|
||||
): string =
|
||||
return self.activityCenterService.markActivityCenterNotificationRead(notificationId, markAsReadProps)
|
||||
|
||||
method markActivityCenterNotificationUnread*[T](
|
||||
self: Controller[T],
|
||||
notificationId: string,
|
||||
markAsUnreadProps: MarkAsUnreadNotificationProperties
|
||||
): string =
|
||||
return self.activityCenterService.markActivityCenterNotificationUnread(notificationId, markAsUnreadProps)
|
||||
|
||||
method acceptActivityCenterNotifications*[T](self: Controller[T], notificationIds: seq[string]): string =
|
||||
return self.activityCenterService.acceptActivityCenterNotifications(notificationIds)
|
||||
|
||||
method dismissActivityCenterNotifications*[T](self: Controller[T], notificationIds: seq[string]): string =
|
||||
return self.activityCenterService.dismissActivityCenterNotifications(notificationIds)
|
|
@ -0,0 +1,44 @@
|
|||
import ../../../../app_service/service/contacts/service as contacts_service
|
||||
import ../../../../app_service/service/activity_center/service as activity_center_service
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
## Abstract class for any input/interaction with this module.
|
||||
|
||||
method delete*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method init*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method hasMoreToShow*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method unreadActivityCenterNotificationsCount*(self: AccessInterface): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getContactDetails*(self: AccessInterface, contactId: string): ContactDetails {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getActivityCenterNotifications*(self: AccessInterface): seq[ActivityCenterNotificationDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markAllActivityCenterNotificationsRead*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markActivityCenterNotificationRead*(self: AccessInterface, notificationId: string, markAsReadProps: MarkAsReadNotificationProperties): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markActivityCenterNotificationUnread*(self: AccessInterface, notificationId: string, markAsUnreadProps: MarkAsUnreadNotificationProperties): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method acceptActivityCenterNotifications*(self: AccessInterface, notificationIds: seq[string]): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method dismissActivityCenterNotifications*(self: AccessInterface, notificationIds: seq[string]): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
type
|
||||
## Abstract class (concept) which must be implemented by object/s used in this
|
||||
## module.
|
||||
DelegateInterface* = concept c
|
|
@ -0,0 +1,73 @@
|
|||
import Tables, stint
|
||||
import ./item
|
||||
import ../../../../app_service/service/activity_center/service as activity_center_service
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
## Abstract class for any input/interaction with this module.
|
||||
|
||||
method delete*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method load*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method hasMoreToShow*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method unreadActivityCenterNotificationsCount*(self: AccessInterface): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method convertToItems*(self: AccessInterface, activityCenterNotifications: seq[ActivityCenterNotificationDto]): seq[Item] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getActivityCenterNotifications*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markAllActivityCenterNotificationsRead*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markAllActivityCenterNotificationsReadDone*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method dismissActivityCenterNotificationsDone*(self: AccessInterface, notificationIds: seq[string]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markActivityCenterNotificationReadDone*(self: AccessInterface, notificationIds: seq[string]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markActivityCenterNotificationUnreadDone*(self: AccessInterface, notificationIds: seq[string]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method acceptActivityCenterNotificationsDone*(self: AccessInterface, notificationIds: seq[string]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markActivityCenterNotificationRead*(self: AccessInterface, notificationId: string, communityId: string, channelId: string, nType: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markActivityCenterNotificationUnread*(self: AccessInterface, notificationId: string, communityId: string, channelId: string, nType: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method pushActivityCenterNotifications*(self: AccessInterface, activityCenterNotifications: seq[ActivityCenterNotificationDto]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method addActivityCenterNotification*(self: AccessInterface, activityCenterNotifications: seq[ActivityCenterNotificationDto]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method acceptActivityCenterNotifications*(self: AccessInterface, notificationIds: seq[string]): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method dismissActivityCenterNotifications*(self: AccessInterface, notificationIds: seq[string]): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
type
|
||||
## Abstract class (concept) which must be implemented by object/s used in this
|
||||
## module.
|
||||
DelegateInterface* = concept c
|
||||
c.activityCenterDidLoad()
|
|
@ -0,0 +1,85 @@
|
|||
import strformat, stint
|
||||
import ../../shared_models/message_item_qobject
|
||||
|
||||
type Item* = ref object
|
||||
id: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat
|
||||
chatId: string
|
||||
name: string
|
||||
author: string
|
||||
notificationType: int
|
||||
timestamp: int64
|
||||
read: bool
|
||||
dismissed: bool
|
||||
accepted: bool
|
||||
messageItem: MessageItem
|
||||
|
||||
proc initItem*(
|
||||
id: string,
|
||||
chatId: string,
|
||||
name: string,
|
||||
author: string,
|
||||
notificationType: int,
|
||||
timestamp: int64,
|
||||
read: bool,
|
||||
dismissed: bool,
|
||||
accepted: bool,
|
||||
messageItem: MessageItem
|
||||
): Item =
|
||||
result = Item()
|
||||
result.id = id
|
||||
result.chatId = chatId
|
||||
result.name = name
|
||||
result.author = author
|
||||
result.notificationType = notificationType
|
||||
result.timestamp = timestamp
|
||||
result.read = read
|
||||
result.dismissed = dismissed
|
||||
result.accepted = accepted
|
||||
result.messageItem = messageItem
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""StickerItem(
|
||||
id: {self.id},
|
||||
name: {$self.name},
|
||||
chatId: {$self.chatId},
|
||||
author: {$self.author},
|
||||
notificationType: {$self.notificationType},
|
||||
timestamp: {$self.timestamp},
|
||||
read: {$self.read},
|
||||
dismissed: {$self.dismissed},
|
||||
accepted: {$self.accepted},
|
||||
# messageItem: {$self.messageItem},
|
||||
]"""
|
||||
|
||||
proc id*(self: Item): string =
|
||||
return self.id
|
||||
|
||||
proc name*(self: Item): string =
|
||||
return self.name
|
||||
|
||||
proc author*(self: Item): string =
|
||||
return self.author
|
||||
|
||||
proc chatId*(self: Item): string =
|
||||
return self.chatId
|
||||
|
||||
proc notificationType*(self: Item): int =
|
||||
return self.notificationType
|
||||
|
||||
proc timestamp*(self: Item): int64 =
|
||||
return self.timestamp
|
||||
|
||||
proc read*(self: Item): bool =
|
||||
return self.read
|
||||
|
||||
proc `read=`*(self: Item, value: bool) =
|
||||
self.read = value
|
||||
|
||||
proc dismissed*(self: Item): bool =
|
||||
return self.dismissed
|
||||
|
||||
proc accepted*(self: Item): bool =
|
||||
return self.accepted
|
||||
|
||||
proc messageItem*(self: Item): MessageItem =
|
||||
return self.messageItem
|
|
@ -0,0 +1,196 @@
|
|||
import NimQml, Tables, chronicles, json, sequtils, strformat, strutils
|
||||
import ./item
|
||||
|
||||
type
|
||||
NotifRoles {.pure.} = enum
|
||||
Id = UserRole + 1
|
||||
ChatId = UserRole + 2
|
||||
Name = UserRole + 3
|
||||
NotificationType = UserRole + 4
|
||||
Message = UserRole + 5
|
||||
Timestamp = UserRole + 6
|
||||
Read = UserRole + 7
|
||||
Dismissed = UserRole + 8
|
||||
Accepted = UserRole + 9
|
||||
Author = UserRole + 10
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Model* = ref object of QAbstractListModel
|
||||
activityCenterNotifications*: seq[Item]
|
||||
nbUnreadNotifications*: int
|
||||
|
||||
proc setup(self: Model) = self.QAbstractListModel.setup
|
||||
|
||||
proc delete(self: Model) =
|
||||
self.activityCenterNotifications = @[]
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc newModel*(): Model =
|
||||
new(result, delete)
|
||||
result.activityCenterNotifications = @[]
|
||||
result.setup()
|
||||
|
||||
proc getUnreadNotificationsForChat*(self: Model, chatId: string): seq[string] =
|
||||
result = @[]
|
||||
for notification in self.activityCenterNotifications:
|
||||
if (notification.chatId == chatId and not notification.read):
|
||||
result.add(notification.id)
|
||||
|
||||
proc unreadCountChanged*(self: Model) {.signal.}
|
||||
|
||||
proc unreadCount*(self: Model): int {.slot.} =
|
||||
self.nbUnreadNotifications
|
||||
|
||||
QtProperty[int] unreadCount:
|
||||
read = unreadCount
|
||||
notify = unreadCountChanged
|
||||
|
||||
proc markAllAsRead*(self: Model) =
|
||||
self.nbUnreadNotifications = 0
|
||||
self.unreadCountChanged()
|
||||
|
||||
for activityCenterNotification in self.activityCenterNotifications:
|
||||
activityCenterNotification.read = true
|
||||
|
||||
let topLeft = self.createIndex(0, 0, nil)
|
||||
let bottomRight = self.createIndex(self.activityCenterNotifications.len - 1, 0, nil)
|
||||
self.dataChanged(topLeft, bottomRight, @[NotifRoles.Read.int])
|
||||
|
||||
method rowCount*(self: Model, index: QModelIndex = nil): int = self.activityCenterNotifications.len
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.activityCenterNotifications.len:
|
||||
return
|
||||
|
||||
let acitivityNotificationItem = self.activityCenterNotifications[index.row]
|
||||
let communityItemRole = role.NotifRoles
|
||||
case communityItemRole:
|
||||
of NotifRoles.Id: result = newQVariant(acitivityNotificationItem.id)
|
||||
of NotifRoles.ChatId: result = newQVariant(acitivityNotificationItem.chatId)
|
||||
of NotifRoles.Name: result = newQVariant(acitivityNotificationItem.name)
|
||||
of NotifRoles.Author: result = newQVariant(acitivityNotificationItem.author)
|
||||
of NotifRoles.NotificationType: result = newQVariant(acitivityNotificationItem.notificationType.int)
|
||||
of NotifRoles.Message: result = newQVariant(acitivityNotificationItem.messageItem)
|
||||
of NotifRoles.Timestamp: result = newQVariant(acitivityNotificationItem.timestamp)
|
||||
of NotifRoles.Read: result = newQVariant(acitivityNotificationItem.read.bool)
|
||||
of NotifRoles.Dismissed: result = newQVariant(acitivityNotificationItem.dismissed.bool)
|
||||
of NotifRoles.Accepted: result = newQVariant(acitivityNotificationItem.accepted.bool)
|
||||
|
||||
proc getNotificationData(self: Model, index: int, data: string): string {.slot.} =
|
||||
if index < 0 or index >= self.activityCenterNotifications.len: return ("")
|
||||
|
||||
let notif = self.activityCenterNotifications[index]
|
||||
case data:
|
||||
of "id": result = notif.id
|
||||
of "chatId": result = notif.chatId
|
||||
of "name": result = notif.name
|
||||
of "author": result = notif.author
|
||||
of "notificationType": result = $(notif.notificationType.int)
|
||||
of "timestamp": result = $(notif.timestamp)
|
||||
of "read": result = $(notif.read)
|
||||
of "dismissed": result = $(notif.dismissed)
|
||||
of "accepted": result = $(notif.accepted)
|
||||
else: result = ("")
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
NotifRoles.Id.int:"id",
|
||||
NotifRoles.ChatId.int:"chatId",
|
||||
NotifRoles.Name.int: "name",
|
||||
NotifRoles.Author.int: "author",
|
||||
NotifRoles.NotificationType.int: "notificationType",
|
||||
NotifRoles.Message.int: "message",
|
||||
NotifRoles.Timestamp.int: "timestamp",
|
||||
NotifRoles.Read.int: "read",
|
||||
NotifRoles.Dismissed.int: "dismissed",
|
||||
NotifRoles.Accepted.int: "accepted"
|
||||
}.toTable
|
||||
|
||||
proc reduceUnreadCount(self: Model, numberNotifs: int) =
|
||||
self.nbUnreadNotifications = self.nbUnreadNotifications - numberNotifs
|
||||
if (self.nbUnreadNotifications < 0):
|
||||
self.nbUnreadNotifications = 0
|
||||
self.unreadCountChanged()
|
||||
|
||||
proc markActivityCenterNotificationUnread*(self: Model, notificationId: string) =
|
||||
self.nbUnreadNotifications = self.nbUnreadNotifications + 1
|
||||
self.unreadCountChanged()
|
||||
|
||||
var i = 0
|
||||
for acnViewItem in self.activityCenterNotifications:
|
||||
if (acnViewItem.id == notificationId):
|
||||
acnViewItem.read = false
|
||||
let index = self.createIndex(i, 0, nil)
|
||||
self.dataChanged(index, index, @[NotifRoles.Read.int])
|
||||
break
|
||||
i.inc
|
||||
|
||||
proc markActivityCenterNotificationRead*(self: Model, notificationId: string) =
|
||||
self.nbUnreadNotifications = self.nbUnreadNotifications - 1
|
||||
if (self.nbUnreadNotifications < 0):
|
||||
self.nbUnreadNotifications = 0
|
||||
self.unreadCountChanged()
|
||||
|
||||
var i = 0
|
||||
for acnViewItem in self.activityCenterNotifications:
|
||||
if (acnViewItem.id == notificationId):
|
||||
acnViewItem.read = true
|
||||
let index = self.createIndex(i, 0, nil)
|
||||
self.dataChanged(index, index, @[NotifRoles.Read.int])
|
||||
break
|
||||
i.inc
|
||||
|
||||
proc removeNotifications*(self: Model, ids: seq[string]) =
|
||||
var i = 0
|
||||
var indexesToDelete: seq[int] = @[]
|
||||
for activityCenterNotification in self.activityCenterNotifications:
|
||||
for id in ids:
|
||||
if (activityCenterNotification.id == id):
|
||||
indexesToDelete.add(i)
|
||||
break
|
||||
i = i + 1
|
||||
|
||||
i = 0
|
||||
for index in indexesToDelete:
|
||||
let indexUpdated = index - i
|
||||
self.beginRemoveRows(newQModelIndex(), indexUpdated, indexUpdated)
|
||||
self.activityCenterNotifications.delete(indexUpdated)
|
||||
self.endRemoveRows()
|
||||
i = i + 1
|
||||
|
||||
self.reduceUnreadCount(ids.len)
|
||||
|
||||
proc setNewData*(self: Model, activityCenterNotifications: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
self.activityCenterNotifications = activityCenterNotifications
|
||||
self.endResetModel()
|
||||
|
||||
proc addActivityNotificationItemToList*(self: Model, activityCenterNotification: Item, addToCount: bool = true) =
|
||||
self.beginInsertRows(newQModelIndex(), self.activityCenterNotifications.len, self.activityCenterNotifications.len)
|
||||
|
||||
self.activityCenterNotifications.add(activityCenterNotification)
|
||||
|
||||
self.endInsertRows()
|
||||
|
||||
if (addToCount and not activityCenterNotification.read):
|
||||
self.nbUnreadNotifications = self.nbUnreadNotifications + 1
|
||||
|
||||
proc updateUnreadCount*(self: Model, count: int) =
|
||||
self.nbUnreadNotifications = count
|
||||
self.unreadCountChanged()
|
||||
|
||||
proc addActivityNotificationItemsToList*(self: Model, activityCenterNotifications: seq[Item]) =
|
||||
if (self.activityCenterNotifications.len == 0):
|
||||
self.setNewData(activityCenterNotifications)
|
||||
else:
|
||||
for activityCenterNotification in activityCenterNotifications:
|
||||
var found = false
|
||||
for notif in self.activityCenterNotifications:
|
||||
if activityCenterNotification.id == notif.id:
|
||||
found = true
|
||||
break
|
||||
if found: continue
|
||||
self.addActivityNotificationItemToList(activityCenterNotification, false)
|
|
@ -0,0 +1,176 @@
|
|||
import NimQml, Tables, stint, sugar, sequtils
|
||||
|
||||
import eventemitter
|
||||
import ./io_interface, ./view, ./controller
|
||||
import ./item as notification_item
|
||||
import ../../shared_models/message_item as message_item
|
||||
import ../../shared_models/message_item_qobject as message_item_qobject
|
||||
import ../../../global/global_singleton
|
||||
import ../../../../app_service/service/activity_center/service as activity_center_service
|
||||
import ../../../../app_service/service/contacts/service as contacts_service
|
||||
|
||||
export io_interface
|
||||
|
||||
type
|
||||
Module* [T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface
|
||||
delegate: T
|
||||
controller: controller.AccessInterface
|
||||
view: View
|
||||
viewVariant: QVariant
|
||||
moduleLoaded: bool
|
||||
|
||||
proc newModule*[T](
|
||||
delegate: T,
|
||||
events: EventEmitter,
|
||||
activityCenterService: activity_center_service.Service,
|
||||
contactsService: contacts_service.Service
|
||||
): Module[T] =
|
||||
result = Module[T]()
|
||||
result.delegate = delegate
|
||||
result.view = newView(result)
|
||||
result.viewVariant = newQVariant(result.view)
|
||||
result.controller = controller.newController[Module[T]](
|
||||
result,
|
||||
events,
|
||||
activityCenterService,
|
||||
contactsService
|
||||
)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*[T](self: Module[T]) =
|
||||
self.view.delete
|
||||
|
||||
method load*[T](self: Module[T]) =
|
||||
singletonInstance.engine.setRootContextProperty("activityCenterModule", self.viewVariant)
|
||||
self.controller.init()
|
||||
self.view.load()
|
||||
|
||||
method isLoaded*[T](self: Module[T]): bool =
|
||||
return self.moduleLoaded
|
||||
|
||||
method viewDidLoad*[T](self: Module[T]) =
|
||||
self.moduleLoaded = true
|
||||
self.delegate.activityCenterDidLoad()
|
||||
|
||||
method hasMoreToShow*[T](self: Module[T]): bool =
|
||||
self.controller.hasMoreToShow()
|
||||
|
||||
method unreadActivityCenterNotificationsCount*[T](self: Module[T]): int =
|
||||
self.controller.unreadActivityCenterNotificationsCount()
|
||||
|
||||
method convertToItems*[T](
|
||||
self: Module[T],
|
||||
activityCenterNotifications: seq[ActivityCenterNotificationDto]
|
||||
): seq[notification_item.Item] =
|
||||
result = activityCenterNotifications.map(
|
||||
proc(n: ActivityCenterNotificationDto): Item =
|
||||
var messageItem = MessageItem()
|
||||
if (n.message.id == ""):
|
||||
# If there is a message in the Notification, transfer it to a MessageItem (QObject)
|
||||
let contactDetails = self.controller.getContactDetails(n.message.`from`)
|
||||
messageItem = message_item_qobject.newMessageItem(initItem(
|
||||
n.message.id,
|
||||
n.message.responseTo,
|
||||
n.message.`from`,
|
||||
contactDetails.displayName,
|
||||
contactDetails.localNickname,
|
||||
contactDetails.icon,
|
||||
contactDetails.isIconIdenticon,
|
||||
contactDetails.isCurrentUser,
|
||||
n.message.outgoingStatus,
|
||||
n.message.text,
|
||||
n.message.image,
|
||||
n.message.seen,
|
||||
n.message.timestamp,
|
||||
ContentType(n.message.contentType),
|
||||
n.message.messageType
|
||||
))
|
||||
|
||||
return notification_item.initItem(
|
||||
n.id,
|
||||
n.chatId,
|
||||
n.name,
|
||||
n.author,
|
||||
n.notificationType.int,
|
||||
n.timestamp,
|
||||
n.read,
|
||||
n.dismissed,
|
||||
n.accepted,
|
||||
messageItem
|
||||
)
|
||||
)
|
||||
|
||||
method getActivityCenterNotifications*[T](self: Module[T]): seq[notification_item.Item] =
|
||||
let activityCenterNotifications = self.controller.getActivityCenterNotifications()
|
||||
self.view.pushActivityCenterNotifications(self.convertToItems(activityCenterNotifications))
|
||||
|
||||
method markAllActivityCenterNotificationsRead*[T](self: Module[T]): string =
|
||||
self.controller.markAllActivityCenterNotificationsRead()
|
||||
|
||||
method markAllActivityCenterNotificationsReadDone*[T](self: Module[T]): string =
|
||||
self.view.markAllActivityCenterNotificationsReadDone()
|
||||
|
||||
method markActivityCenterNotificationRead*[T](
|
||||
self: Module[T],
|
||||
notificationId: string,
|
||||
communityId: string,
|
||||
channelId: string,
|
||||
nType: int
|
||||
): string =
|
||||
let notificationType = ActivityCenterNotificationType(nType)
|
||||
let markAsReadProps = MarkAsReadNotificationProperties(
|
||||
notificationIds: @[notificationId],
|
||||
communityId: communityId,
|
||||
channelId: channelId,
|
||||
notificationTypes: @[notificationType]
|
||||
)
|
||||
result = self.controller.markActivityCenterNotificationRead(notificationId, markAsReadProps)
|
||||
|
||||
method markActivityCenterNotificationReadDone*[T](self: Module[T], notificationIds: seq[string]) =
|
||||
for notificationId in notificationIds:
|
||||
self.view.markActivityCenterNotificationReadDone(notificationId)
|
||||
|
||||
method pushActivityCenterNotifications*[T](
|
||||
self: Module[T],
|
||||
activityCenterNotifications: seq[ActivityCenterNotificationDto]
|
||||
) =
|
||||
self.view.pushActivityCenterNotifications(self.convertToItems(activityCenterNotifications))
|
||||
|
||||
method addActivityCenterNotification*[T](
|
||||
self: Module[T],
|
||||
activityCenterNotifications: seq[ActivityCenterNotificationDto]
|
||||
) =
|
||||
self.view.addActivityCenterNotification(self.convertToItems(activityCenterNotifications))
|
||||
|
||||
method markActivityCenterNotificationUnread*[T](
|
||||
self: Module[T],
|
||||
notificationId: string,
|
||||
communityId: string,
|
||||
channelId: string,
|
||||
nType: int
|
||||
): string =
|
||||
let notificationType = ActivityCenterNotificationType(nType)
|
||||
let markAsUnreadProps = MarkAsUnreadNotificationProperties(
|
||||
notificationIds: @[notificationId],
|
||||
communityId: communityId,
|
||||
channelId: channelId,
|
||||
notificationTypes: @[notificationType]
|
||||
)
|
||||
|
||||
result = self.controller.markActivityCenterNotificationUnread(notificationId, markAsUnreadProps)
|
||||
|
||||
method markActivityCenterNotificationUnreadDone*[T](self: Module[T], notificationIds: seq[string]) =
|
||||
for notificationId in notificationIds:
|
||||
self.view.markActivityCenterNotificationUnreadDone(notificationId)
|
||||
|
||||
method acceptActivityCenterNotificationsDone*[T](self: Module[T], notificationIds: seq[string]) =
|
||||
self.view.acceptActivityCenterNotificationsDone(notificationIds)
|
||||
|
||||
method acceptActivityCenterNotifications*[T](self: Module[T], notificationIds: seq[string]): string =
|
||||
self.controller.acceptActivityCenterNotifications(notificationIds)
|
||||
|
||||
method dismissActivityCenterNotificationsDone*[T](self: Module[T], notificationIds: seq[string]) =
|
||||
self.view.dismissActivityCenterNotificationsDone(notificationIds)
|
||||
|
||||
method dismissActivityCenterNotifications*[T](self: Module[T], notificationIds: seq[string]): string =
|
||||
self.controller.dismissActivityCenterNotifications(notificationIds)
|
|
@ -0,0 +1,128 @@
|
|||
import NimQml, json, strutils, json_serialization, sequtils, strformat
|
||||
import ../../../../app_service/service/activity_center/service as activity_center_service
|
||||
|
||||
import ./model
|
||||
import ./io_interface, ./item
|
||||
|
||||
QtObject:
|
||||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
model: Model
|
||||
modelVariant: QVariant
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
result.delegate = delegate
|
||||
result.model = newModel()
|
||||
result.modelVariant = newQVariant(result.model)
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc activityNotificationsChanged*(self: View) {.signal.}
|
||||
|
||||
proc getModel(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.modelVariant)
|
||||
|
||||
QtProperty[QVariant] model:
|
||||
read = getModel
|
||||
notify = activityNotificationsChanged
|
||||
|
||||
proc hasMoreToShowChanged*(self: View) {.signal.}
|
||||
|
||||
proc hasMoreToShow*(self: View): bool {.slot.} =
|
||||
self.delegate.hasMoreToShow()
|
||||
|
||||
QtProperty[bool] hasMoreToShow:
|
||||
read = hasMoreToShow
|
||||
notify = hasMoreToShowChanged
|
||||
|
||||
proc pushActivityCenterNotifications*(self:View, activityCenterNotifications: seq[Item]) =
|
||||
self.model.addActivityNotificationItemsToList(activityCenterNotifications)
|
||||
self.activityNotificationsChanged()
|
||||
self.hasMoreToShowChanged()
|
||||
|
||||
let count = self.delegate.unreadActivityCenterNotificationsCount()
|
||||
self.model.updateUnreadCount(count)
|
||||
|
||||
proc loadMoreNotifications(self: View) {.slot.} =
|
||||
self.delegate.getActivityCenterNotifications()
|
||||
|
||||
proc markAllActivityCenterNotificationsRead(self: View): string {.slot.} =
|
||||
result = self.delegate.markAllActivityCenterNotificationsRead()
|
||||
|
||||
proc markAllActivityCenterNotificationsReadDone*(self: View) {.slot.} =
|
||||
self.model.markAllAsRead()
|
||||
|
||||
proc markActivityCenterNotificationRead(
|
||||
self: View,
|
||||
notificationId: string,
|
||||
communityId: string,
|
||||
channelId: string,
|
||||
nType: int
|
||||
): void {.slot.} =
|
||||
discard self.delegate.markActivityCenterNotificationRead(notificationId, communityId, channelId, nType)
|
||||
|
||||
proc markActivityCenterNotificationReadDone*(self: View, notificationId: string) =
|
||||
self.model.markActivityCenterNotificationRead(notificationId)
|
||||
|
||||
proc markActivityCenterNotificationUnreadDone*(self: View, notificationId: string) =
|
||||
self.model.markActivityCenterNotificationUnread(notificationId)
|
||||
|
||||
proc markAllChatMentionsAsRead*(self: View, communityId: string, chatId: string) =
|
||||
let notifsIds = self.model.getUnreadNotificationsForChat(chatId)
|
||||
for notifId in notifsIds:
|
||||
# TODO change the 3 to the real type
|
||||
self.markActivityCenterNotificationRead(notifId, communityId, chatId, ActivityCenterNotificationType.Mention.int)
|
||||
|
||||
proc markActivityCenterNotificationUnread(
|
||||
self: View,
|
||||
notificationId: string,
|
||||
communityId: string,
|
||||
channelId: string,
|
||||
nType: int
|
||||
): void {.slot.} =
|
||||
discard self.delegate.markActivityCenterNotificationUnread(
|
||||
notificationId,
|
||||
communityId,
|
||||
channelId,
|
||||
nType
|
||||
)
|
||||
|
||||
proc acceptActivityCenterNotifications(self: View, idsJson: string): string {.slot.} =
|
||||
let ids = map(parseJson(idsJson).getElems(), proc(x:JsonNode):string = x.getStr())
|
||||
|
||||
result = self.delegate.acceptActivityCenterNotifications(ids)
|
||||
|
||||
proc acceptActivityCenterNotificationsDone*(self: View, notificationIds: seq[string]) =
|
||||
self.model.removeNotifications(notificationIds)
|
||||
|
||||
proc acceptActivityCenterNotification(self: View, id: string): string {.slot.} =
|
||||
self.acceptActivityCenterNotifications(fmt"[""{id}""]")
|
||||
|
||||
proc dismissActivityCenterNotifications(self: View, idsJson: string): string {.slot.} =
|
||||
let ids = map(parseJson(idsJson).getElems(), proc(x:JsonNode):string = x.getStr())
|
||||
|
||||
result = self.delegate.dismissActivityCenterNotifications(ids)
|
||||
|
||||
proc dismissActivityCenterNotification(self: View, id: string): string {.slot.} =
|
||||
self.dismissActivityCenterNotifications(fmt"[""{id}""]")
|
||||
|
||||
proc dismissActivityCenterNotificationsDone*(self: View, notificationIds: seq[string]) =
|
||||
self.model.removeNotifications(notificationIds)
|
||||
|
||||
proc addActivityCenterNotification*(self: View, activityCenterNotifications: seq[Item]) =
|
||||
for activityCenterNotification in activityCenterNotifications:
|
||||
# TODO this should be handled by the chat or community module
|
||||
# if self.channelView.activeChannel.id == activityCenterNotification.chatId:
|
||||
# activityCenterNotification.read = true
|
||||
# let communityId = self.status.chat.getCommunityIdForChat(activityCenterNotification.chatId)
|
||||
# if communityId != "":
|
||||
# self.communities.joinedCommunityList.decrementMentions(communityId, activityCenterNotification.chatId)
|
||||
self.model.addActivityNotificationItemToList(activityCenterNotification)
|
||||
self.activityNotificationsChanged()
|
|
@ -104,3 +104,6 @@ method unmuteChat*(self: Controller) =
|
|||
|
||||
method getContactById*(self: Controller, contactId: string): ContactsDto =
|
||||
return self.contactService.getContactById(contactId)
|
||||
|
||||
method getContactDetails*(self: Controller, contactId: string): ContactDetails =
|
||||
return self.contactService.getContactDetails(contactId)
|
|
@ -1,6 +1,7 @@
|
|||
import ../../../../../app_service/service/contacts/dto/[contacts]
|
||||
import ../../../../../app_service/service/message/dto/[message, reaction]
|
||||
import ../../../../../app_service/service/chat/dto/[chat]
|
||||
import ../../../../../app_service/service/contacts/service
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
@ -43,3 +44,6 @@ method unmuteChat*(self: AccessInterface) {.base.} =
|
|||
|
||||
method getContactById*(self: AccessInterface, contactId: string): ContactsDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getContactDetails*(self: AccessInterface, contactId: string): ContactDetails {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
|
@ -128,18 +128,25 @@ proc buildPinnedMessageItem(self: Module, messageId: string, item: var pinned_ms
|
|||
if(err.len > 0):
|
||||
return false
|
||||
|
||||
let sender = self.controller.getContactById(m.`from`)
|
||||
let senderDisplayName = sender.userNameOrAlias()
|
||||
let amISender = m.`from` == singletonInstance.userProfile.getPubKey()
|
||||
var senderIcon = sender.identicon
|
||||
var isSenderIconIdenticon = sender.identicon.len > 0
|
||||
if(sender.image.thumbnail.len > 0):
|
||||
senderIcon = sender.image.thumbnail
|
||||
isSenderIconIdenticon = false
|
||||
let contactDetails = self.controller.getContactDetails(m.`from`)
|
||||
|
||||
var item = initItem(m.id, m.responseTo, m.`from`, senderDisplayName, sender.localNickname, senderIcon,
|
||||
isSenderIconIdenticon, amISender, m.outgoingStatus, m.text, m.image, m.seen, m.timestamp, m.contentType.ContentType,
|
||||
m.messageType)
|
||||
var item = initItem(
|
||||
m.id,
|
||||
m.responseTo,
|
||||
m.`from`,
|
||||
contactDetails.displayName,
|
||||
contactDetails.localNickname,
|
||||
contactDetails.icon,
|
||||
contactDetails.isIconIdenticon,
|
||||
contactDetails.isCurrentUser,
|
||||
m.outgoingStatus,
|
||||
m.text,
|
||||
m.image,
|
||||
m.seen,
|
||||
m.timestamp,
|
||||
m.contentType.ContentType,
|
||||
m.messageType
|
||||
)
|
||||
item.pinned = true
|
||||
|
||||
for r in reactions:
|
||||
|
|
|
@ -10,6 +10,7 @@ import browser_section/module as browser_section_module
|
|||
import profile_section/module as profile_section_module
|
||||
import app_search/module as app_search_module
|
||||
import stickers/module as stickers_module
|
||||
import activity_center/module as activity_center_module
|
||||
|
||||
import ../../../app_service/service/keychain/service as keychain_service
|
||||
import ../../../app_service/service/chat/service as chat_service
|
||||
|
@ -31,6 +32,7 @@ import ../../../app_service/service/language/service as language_service
|
|||
import ../../../app_service/service/mnemonic/service as mnemonic_service
|
||||
import ../../../app_service/service/privacy/service as privacy_service
|
||||
import ../../../app_service/service/stickers/service as stickers_service
|
||||
import ../../../app_service/service/activity_center/service as activity_center_service
|
||||
|
||||
import eventemitter
|
||||
|
||||
|
@ -48,6 +50,7 @@ type
|
|||
browserSectionModule: browser_section_module.AccessInterface
|
||||
profileSectionModule: profile_section_module.AccessInterface
|
||||
stickersModule: stickers_module.AccessInterface
|
||||
activityCenterModule: activity_center_module.AccessInterface
|
||||
appSearchModule: app_search_module.AccessInterface
|
||||
moduleLoaded: bool
|
||||
|
||||
|
@ -73,7 +76,8 @@ proc newModule*[T](
|
|||
mnemonicService: mnemonic_service.ServiceInterface,
|
||||
privacyService: privacy_service.ServiceInterface,
|
||||
providerService: provider_service.ServiceInterface,
|
||||
stickersService: stickers_service.Service
|
||||
stickersService: stickers_service.Service,
|
||||
activityCenterService: activity_center_service.Service
|
||||
): Module[T] =
|
||||
result = Module[T]()
|
||||
result.delegate = delegate
|
||||
|
@ -94,6 +98,7 @@ proc newModule*[T](
|
|||
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService,
|
||||
profileService, contactsService, aboutService, languageService, mnemonicService, privacyService)
|
||||
result.stickersModule = stickers_module.newModule(result, events, stickersService)
|
||||
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService)
|
||||
result.appSearchModule = app_search_module.newModule(result, events, contactsService, chatService, communityService,
|
||||
messageService)
|
||||
|
||||
|
@ -101,6 +106,7 @@ method delete*[T](self: Module[T]) =
|
|||
self.chatSectionModule.delete
|
||||
self.profileSectionModule.delete
|
||||
self.stickersModule.delete
|
||||
self.activityCenterModule.delete
|
||||
for cModule in self.communitySectionsModule.values:
|
||||
cModule.delete
|
||||
self.communitySectionsModule.clear
|
||||
|
@ -213,6 +219,7 @@ method load*[T](
|
|||
# self.nodeManagementSectionModule.load()
|
||||
self.profileSectionModule.load()
|
||||
self.stickersModule.load()
|
||||
self.activityCenterModule.load()
|
||||
self.appSearchModule.load()
|
||||
|
||||
# Set active section on app start
|
||||
|
@ -241,6 +248,9 @@ proc checkIfModuleDidLoad [T](self: Module[T]) =
|
|||
if(not self.stickersModule.isLoaded()):
|
||||
return
|
||||
|
||||
if(not self.activityCenterModule.isLoaded()):
|
||||
return
|
||||
|
||||
if(not self.appSearchModule.isLoaded()):
|
||||
return
|
||||
|
||||
|
@ -259,6 +269,9 @@ method appSearchDidLoad*[T](self: Module[T]) =
|
|||
proc stickersDidLoad*[T](self: Module[T]) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
proc activityCenterDidLoad*[T](self: Module[T]) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
proc walletSectionDidLoad*[T](self: Module[T]) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
import Tables, json
|
||||
|
||||
type
|
||||
ImageItem* = object
|
||||
thumbnail*: string
|
||||
large*: string
|
||||
|
||||
proc initImageItem*(
|
||||
thumbnail: string,
|
||||
large: string
|
||||
): ImageItem =
|
||||
result = ImageItem()
|
||||
result.thumbnail = thumbnail
|
||||
result.large = large
|
||||
|
||||
proc thumbnail*(self: ImageItem): string {.inline.} =
|
||||
self.thumbnail
|
||||
|
||||
proc large*(self: ImageItem): string {.inline.} =
|
||||
self.large
|
||||
|
||||
type
|
||||
Item* = ref object
|
||||
id: string
|
||||
name: string
|
||||
ensVerified: bool
|
||||
alias: string
|
||||
identicon: string
|
||||
lastUpdated: int64
|
||||
lastUpdatedLocally: int64
|
||||
localNickname: string
|
||||
image: ImageItem
|
||||
added: bool
|
||||
blocked: bool
|
||||
isSyncing: bool
|
||||
hasAddedUs: bool
|
||||
removed: bool
|
||||
|
||||
proc initItem*(
|
||||
id: string,
|
||||
name: string,
|
||||
ensVerified: bool,
|
||||
alias: string,
|
||||
identicon: string,
|
||||
lastUpdated: int64,
|
||||
lastUpdatedLocally: int64,
|
||||
image: ImageItem,
|
||||
added: bool,
|
||||
blocked: bool,
|
||||
isSyncing: bool,
|
||||
hasAddedUs: bool,
|
||||
removed: bool
|
||||
): Item =
|
||||
result = Item()
|
||||
result.id = id
|
||||
result.name = name
|
||||
result.ensVerified = ensVerified
|
||||
result.alias = alias
|
||||
result.lastUpdated = lastUpdated
|
||||
result.lastUpdatedLocally = lastUpdatedLocally
|
||||
result.image = image
|
||||
result.added = added
|
||||
result.blocked = blocked
|
||||
result.isSyncing = isSyncing
|
||||
result.hasAddedUs = hasAddedUs
|
||||
result.removed = removed
|
||||
|
||||
proc id*(self: Item): string {.inline.} =
|
||||
self.id
|
||||
|
||||
proc name*(self: Item): string {.inline.} =
|
||||
self.name
|
||||
|
||||
proc ensVerified*(self: Item): bool {.inline.} =
|
||||
self.ensVerified
|
||||
|
||||
proc alias*(self: Item): string {.inline.} =
|
||||
self.alias
|
||||
|
||||
proc lastUpdated*(self: Item): int64 {.inline.} =
|
||||
self.lastUpdated
|
||||
|
||||
proc lastUpdatedLocally*(self: Item): int64 {.inline.} =
|
||||
self.lastUpdatedLocally
|
||||
|
||||
proc image*(self: Item): ImageItem {.inline.} =
|
||||
self.image
|
||||
|
||||
proc added*(self: Item): bool {.inline.} =
|
||||
self.added
|
||||
|
||||
proc blocked*(self: Item): bool {.inline.} =
|
||||
self.blocked
|
||||
|
||||
proc isSyncing*(self: Item): bool {.inline.} =
|
||||
self.isSyncing
|
||||
|
||||
proc hasAddedUs*(self: Item): bool {.inline.} =
|
||||
self.hasAddedUs
|
||||
|
||||
proc removed*(self: Item): bool {.inline.} =
|
||||
self.removed
|
|
@ -66,6 +66,27 @@ proc initItem*(id, responseToMessageWithId, senderId, senderDisplayName, senderL
|
|||
result.messageType = messageType
|
||||
result.pinned = false
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""Item(
|
||||
id: {$self.id},
|
||||
responseToMessageWithId: {self.responseToMessageWithId},
|
||||
senderId: {self.senderId},
|
||||
senderDisplayName: {$self.senderDisplayName},
|
||||
senderLocalName: {self.senderLocalName},
|
||||
amISender: {$self.amISender},
|
||||
isSenderIconIdenticon: {$self.isSenderIconIdenticon},
|
||||
seen: {$self.seen},
|
||||
outgoingStatus:{$self.outgoingStatus},
|
||||
messageText:{self.messageText},
|
||||
messageImage:{self.messageImage},
|
||||
timestamp:{$self.timestamp},
|
||||
contentType:{$self.contentType.int},
|
||||
messageType:{$self.messageType},
|
||||
chatTypeThisMessageBelongsTo:{self.chatTypeThisMessageBelongsTo},
|
||||
chatColorThisMessageBelongsTo:{self.chatColorThisMessageBelongsTo},
|
||||
pinned:{$self.pinned}
|
||||
)"""
|
||||
|
||||
proc id*(self: Item): string {.inline.} =
|
||||
self.id
|
||||
|
||||
|
@ -99,6 +120,12 @@ proc messageText*(self: Item): string {.inline.} =
|
|||
proc messageImage*(self: Item): string {.inline.} =
|
||||
self.messageImage
|
||||
|
||||
proc stickerPack*(self: Item): int {.inline.} =
|
||||
self.stickerPack
|
||||
|
||||
proc stickerHash*(self: Item): string {.inline.} =
|
||||
self.stickerHash
|
||||
|
||||
proc seen*(self: Item): bool {.inline.} =
|
||||
self.seen
|
||||
|
||||
|
@ -192,21 +219,6 @@ proc getCountsForReactions*(self: Item): seq[JsonNode] =
|
|||
|
||||
result.add(%* {"emojiId": k, "counts": v.len})
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""MessageItem(
|
||||
id: {self.id},
|
||||
responseToMessageWithId: {self.responseToMessageWithId},
|
||||
senderId: {self.senderId},
|
||||
senderDisplayName: {self.senderDisplayName},
|
||||
senderLocalName: {self.senderLocalName},
|
||||
timestamp: {self.timestamp},
|
||||
contentType: {self.contentType.int},
|
||||
messageType:{self.messageType},
|
||||
chatTypeThisMessageBelongsTo:{self.chatTypeThisMessageBelongsTo},
|
||||
chatColorThisMessageBelongsTo:{self.chatColorThisMessageBelongsTo},
|
||||
pinned:{self.pinned}
|
||||
]"""
|
||||
|
||||
proc toJsonNode*(self: Item): JsonNode =
|
||||
result = %* {
|
||||
"id": self.id,
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
import NimQml, std/wrapnils
|
||||
import ./message_item
|
||||
|
||||
QtObject:
|
||||
type MessageItem* = ref object of QObject
|
||||
messageItem*: message_item.Item
|
||||
|
||||
proc setup(self: MessageItem) =
|
||||
self.QObject.setup
|
||||
|
||||
proc delete*(self: MessageItem) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newMessageItem*(message: message_item.Item): MessageItem =
|
||||
new(result, delete)
|
||||
result.messageItem = message
|
||||
result.setup
|
||||
|
||||
proc `$`*(self: MessageItem): string =
|
||||
result = $self.messageItem
|
||||
|
||||
proc setMessageItem*(self: MessageItem, messageItem: message_item.Item) =
|
||||
self.messageItem = messageItem
|
||||
|
||||
proc responseToMessageWithId*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.responseToMessageWithId
|
||||
QtProperty[string] responseToMessageWithId:
|
||||
read = responseToMessageWithId
|
||||
|
||||
proc senderId*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.senderId
|
||||
QtProperty[string] senderId:
|
||||
read = senderId
|
||||
|
||||
proc senderDisplayName*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.senderDisplayName
|
||||
QtProperty[string] senderDisplayName:
|
||||
read = senderDisplayName
|
||||
|
||||
proc senderLocalName*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.senderLocalName
|
||||
QtProperty[string] senderLocalName:
|
||||
read = senderLocalName
|
||||
|
||||
proc amISender*(self: MessageItem): bool {.slot.} = result = ?.self.messageItem.amISender
|
||||
QtProperty[bool] amISender:
|
||||
read = amISender
|
||||
|
||||
proc senderIcon*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.senderIcon
|
||||
QtProperty[string] senderIcon:
|
||||
read = senderIcon
|
||||
|
||||
proc isSenderIconIdenticon*(self: MessageItem): bool {.slot.} = result = ?.self.messageItem.isSenderIconIdenticon
|
||||
QtProperty[bool] isSenderIconIdenticon:
|
||||
read = isSenderIconIdenticon
|
||||
|
||||
proc seen*(self: MessageItem): bool {.slot.} = result = ?.self.messageItem.seen
|
||||
QtProperty[bool] seen:
|
||||
read = seen
|
||||
|
||||
proc outgoingStatus*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.outgoingStatus
|
||||
QtProperty[string] outgoingStatus:
|
||||
read = outgoingStatus
|
||||
|
||||
proc messageText*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.messageText
|
||||
QtProperty[string] messageText:
|
||||
read = messageText
|
||||
|
||||
proc messageImage*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.messageImage
|
||||
QtProperty[string] messageImage:
|
||||
read = messageImage
|
||||
|
||||
proc stickerHash*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.stickerHash
|
||||
QtProperty[string] stickerHash:
|
||||
read = stickerHash
|
||||
|
||||
proc stickerPack*(self: MessageItem): int {.slot.} = result = ?.self.messageItem.stickerPack
|
||||
QtProperty[int] stickerPack:
|
||||
read = stickerPack
|
||||
|
||||
# Convert to int
|
||||
# proc gapFrom*(self: MessageItem): int64 {.slot.} = result = ?.self.messageItem.gapFrom
|
||||
# QtProperty[int64] gapFrom:
|
||||
# read = gapFrom
|
||||
|
||||
# proc gapTo*(self: MessageItem): int64 {.slot.} = result = ?.self.messageItem.gapTo
|
||||
# QtProperty[int64] gapTo:
|
||||
# read = gapTo
|
||||
|
||||
# proc timestamp*(self: MessageItem): int64 {.slot.} = result = ?.self.messageItem.timestamp
|
||||
# QtProperty[int64] timestamp:
|
||||
# read = timestamp
|
||||
|
||||
proc contentType*(self: MessageItem): int {.slot.} =
|
||||
if (self.messageItem.isNil): return 0
|
||||
result = self.messageItem.contentType.int
|
||||
QtProperty[int] contentType:
|
||||
read = contentType
|
||||
|
||||
proc messageType*(self: MessageItem): int {.slot.} = result = ?.self.messageItem.messageType
|
||||
QtProperty[int] messageType:
|
||||
read = messageType
|
||||
|
||||
# TODO find a way to pass reactions since they are not basic types (might need to be a Model)
|
||||
# proc reactions*(self: MessageItem): int {.slot.} = result = ?.self.messageItem.reactions
|
||||
# QtProperty[int] reactions:
|
||||
# read = reactions
|
||||
|
||||
# proc reactionIds*(self: MessageItem): int {.slot.} = result = ?.self.messageItem.reactionIds
|
||||
# QtProperty[int] reactionIds:
|
||||
# read = reactionIds
|
||||
|
||||
proc pinned*(self: MessageItem): bool {.slot.} = result = ?.self.messageItem.pinned
|
||||
QtProperty[int] bool:
|
||||
read = bool
|
|
@ -0,0 +1,16 @@
|
|||
include ../../common/json_utils
|
||||
include ../../../app/core/tasks/common
|
||||
|
||||
type
|
||||
AsyncActivityNotificationLoadTaskArg = ref object of QObjectTaskArg
|
||||
cursor: string
|
||||
limit: int
|
||||
|
||||
const asyncActivityNotificationLoadTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[AsyncActivityNotificationLoadTaskArg](argEncoded)
|
||||
let activityNotificationsCallResult = status_activity_center.rpcActivityCenterNotifications(newJString(arg.cursor), arg.limit)
|
||||
|
||||
let responseJson = %*{
|
||||
"activityNotifications": activityNotificationsCallResult.result
|
||||
}
|
||||
arg.finish(responseJson)
|
|
@ -0,0 +1,72 @@
|
|||
{.used.}
|
||||
|
||||
import json, strformat, strutils, stint, json_serialization
|
||||
import ../../message/dto/message
|
||||
|
||||
include ../../../common/json_utils
|
||||
include ../../../common/utils
|
||||
|
||||
type ActivityCenterNotificationType* {.pure.}= enum
|
||||
Unknown = 0,
|
||||
NewOneToOne = 1,
|
||||
NewPrivateGroupChat = 2,
|
||||
Mention = 3
|
||||
Reply = 4
|
||||
|
||||
type ActivityCenterNotificationDto* = ref object of RootObj
|
||||
id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat
|
||||
chatId*: string
|
||||
name*: string
|
||||
author*: string
|
||||
notificationType*: ActivityCenterNotificationType
|
||||
message*: MessageDto
|
||||
timestamp*: int64
|
||||
read*: bool
|
||||
dismissed*: bool
|
||||
accepted*: bool
|
||||
|
||||
proc `$`*(self: ActivityCenterNotificationDto): string =
|
||||
result = fmt"""ActivityCenterNotificationDto(
|
||||
id: {$self.id},
|
||||
chatId: {self.chatId},
|
||||
author: {self.author},
|
||||
notificationType: {$self.notificationType.int},
|
||||
timestamp: {self.timestamp},
|
||||
read: {$self.read},
|
||||
dismissed: {$self.dismissed},
|
||||
accepted: {$self.accepted},
|
||||
message:{self.message}
|
||||
)"""
|
||||
|
||||
proc toActivityCenterNotificationDto*(jsonObj: JsonNode): ActivityCenterNotificationDto =
|
||||
result = ActivityCenterNotificationDto()
|
||||
discard jsonObj.getProp("id", result.id)
|
||||
discard jsonObj.getProp("chatId", result.chatId)
|
||||
discard jsonObj.getProp("author", result.author)
|
||||
|
||||
result.notificationType = ActivityCenterNotificationType.Unknown
|
||||
var notificationTypeInt: int
|
||||
if (jsonObj.getProp("notificationType", notificationTypeInt) and
|
||||
(notificationTypeInt >= ord(low(ActivityCenterNotificationType)) or
|
||||
notificationTypeInt <= ord(high(ActivityCenterNotificationType)))):
|
||||
result.notificationType = ActivityCenterNotificationType(notificationTypeInt)
|
||||
|
||||
discard jsonObj.getProp("timestamp", result.timestamp)
|
||||
discard jsonObj.getProp("read", result.read)
|
||||
discard jsonObj.getProp("dismissed", result.dismissed)
|
||||
discard jsonObj.getProp("accepted", result.accepted)
|
||||
|
||||
if jsonObj.contains("message") and jsonObj{"message"}.kind != JNull:
|
||||
result.message = jsonObj{"message"}.toMessageDto()
|
||||
elif result.notificationType == ActivityCenterNotificationType.NewOneToOne and
|
||||
jsonObj.contains("lastMessage") and jsonObj{"lastMessage"}.kind != JNull:
|
||||
result.message = jsonObj{"lastMessage"}.toMessageDto()
|
||||
|
||||
|
||||
proc parseActivityCenterNotifications*(rpcResult: JsonNode): (string, seq[ActivityCenterNotificationDto]) =
|
||||
var notifs: seq[ActivityCenterNotificationDto] = @[]
|
||||
if rpcResult{"notifications"}.kind != JNull:
|
||||
for jsonMsg in rpcResult["notifications"]:
|
||||
notifs.add(jsonMsg.toActivityCenterNotificationDto())
|
||||
return (rpcResult{"cursor"}.getStr, notifs)
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
import NimQml, json, sequtils, chronicles, strutils, strutils, stint
|
||||
|
||||
import eventemitter
|
||||
import ../../../app/core/[main]
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
|
||||
import web3/ethtypes, web3/conversions, stew/byteutils, nimcrypto, json_serialization, chronicles
|
||||
import json, tables, json_serialization
|
||||
|
||||
import ../chat/service as chat_service
|
||||
|
||||
import status/statusgo_backend_new/activity_center as status_activity_center
|
||||
import status/statusgo_backend_new/response_type
|
||||
import ./dto/notification
|
||||
|
||||
export notification
|
||||
|
||||
include async_tasks
|
||||
|
||||
logScope:
|
||||
topics = "activity-center-service"
|
||||
|
||||
type
|
||||
ActivityCenterNotificationsArgs* = ref object of Args
|
||||
activityCenterNotifications*: seq[ActivityCenterNotificationDto]
|
||||
|
||||
MarkAsAcceptedNotificationProperties* = ref object of Args
|
||||
notificationIds*: seq[string]
|
||||
|
||||
MarkAsDismissedNotificationProperties* = ref object of Args
|
||||
notificationIds*: seq[string]
|
||||
|
||||
MarkAsReadNotificationProperties* = ref object of Args
|
||||
isAll*: bool
|
||||
notificationIds*: seq[string]
|
||||
communityId*: string
|
||||
channelId*: string
|
||||
notificationTypes*: seq[ActivityCenterNotificationType]
|
||||
|
||||
MarkAsUnreadNotificationProperties* = ref object of Args
|
||||
notificationIds*: seq[string]
|
||||
communityId*: string
|
||||
channelId*: string
|
||||
notificationTypes*: seq[ActivityCenterNotificationType]
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
# TODO remove new when refactor is done
|
||||
const SIGNAL_ACTIVITY_CENTER_NOTIFICATIONS_LOADED* = "activityCenterNotificationsLoaded-new"
|
||||
const SIGNAL_MARK_NOTIFICATIONS_AS_READ* = "markNotificationsAsRead-new"
|
||||
const SIGNAL_MARK_NOTIFICATIONS_AS_UNREAD* = "markNotificationsAsUnread-new"
|
||||
const SIGNAL_MARK_NOTIFICATIONS_AS_ACCEPTED* = "markNotificationsAsAccepted"
|
||||
const SIGNAL_MARK_NOTIFICATIONS_AS_DISMISSED* = "markNotificationsAsDismissed"
|
||||
|
||||
const DEFAULT_LIMIT = 20
|
||||
|
||||
|
||||
QtObject:
|
||||
type Service* = ref object of QObject
|
||||
threadpool: ThreadPool
|
||||
events: EventEmitter
|
||||
chatService: chat_service.Service
|
||||
cursor*: string
|
||||
|
||||
# Forward declaration
|
||||
proc asyncActivityNotificationLoad*(self: Service)
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newService*(
|
||||
events: EventEmitter,
|
||||
threadpool: ThreadPool,
|
||||
chatService: chat_service.Service
|
||||
): Service =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
result.events = events
|
||||
result.threadpool = threadpool
|
||||
result.chatService = chatService
|
||||
|
||||
proc init*(self: Service) =
|
||||
self.asyncActivityNotificationLoad()
|
||||
|
||||
proc hasMoreToShow*(self: Service): bool =
|
||||
return self.cursor != ""
|
||||
|
||||
proc asyncActivityNotificationLoad*(self: Service) =
|
||||
let arg = AsyncActivityNotificationLoadTaskArg(
|
||||
tptr: cast[ByteAddress](asyncActivityNotificationLoadTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "asyncActivityNotificationLoaded",
|
||||
cursor: "",
|
||||
limit: DEFAULT_LIMIT
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc getActivityCenterNotifications*(self: Service): seq[ActivityCenterNotificationDto] =
|
||||
if(self.cursor == ""): return
|
||||
|
||||
var cursorVal: JsonNode
|
||||
|
||||
if self.cursor == "":
|
||||
cursorVal = newJNull()
|
||||
else:
|
||||
cursorVal = newJString(self.cursor)
|
||||
|
||||
let callResult = status_activity_center.rpcActivityCenterNotifications(cursorVal, DEFAULT_LIMIT)
|
||||
let activityCenterNotificationsTuple = parseActivityCenterNotifications(callResult.result)
|
||||
|
||||
self.cursor = activityCenterNotificationsTuple[0];
|
||||
|
||||
result = activityCenterNotificationsTuple[1]
|
||||
|
||||
proc markActivityCenterNotificationRead*(
|
||||
self: Service,
|
||||
notificationId: string,
|
||||
markAsReadProps: MarkAsReadNotificationProperties
|
||||
): string =
|
||||
try:
|
||||
discard status_activity_center.markActivityCenterNotificationsRead(@[notificationId])
|
||||
self.events.emit(SIGNAL_MARK_NOTIFICATIONS_AS_READ, markAsReadProps)
|
||||
except Exception as e:
|
||||
error "Error marking as read", msg = e.msg
|
||||
result = e.msg
|
||||
|
||||
proc unreadActivityCenterNotificationsCount*(self: Service): int =
|
||||
try:
|
||||
let response = status_activity_center.unreadActivityCenterNotificationsCount()
|
||||
|
||||
if response.result.kind != JNull:
|
||||
return response.result.getInt
|
||||
except Exception as e:
|
||||
error "Error getting unread acitvity center unread count", msg = e.msg
|
||||
|
||||
proc markActivityCenterNotificationUnread*(
|
||||
self: Service,
|
||||
notificationId: string,
|
||||
markAsUnreadProps: MarkAsUnreadNotificationProperties
|
||||
): string =
|
||||
try:
|
||||
discard status_activity_center.markActivityCenterNotificationsUnread(@[notificationId])
|
||||
self.events.emit(SIGNAL_MARK_NOTIFICATIONS_AS_UNREAD, markAsUnreadProps)
|
||||
except Exception as e:
|
||||
error "Error marking as unread", msg = e.msg
|
||||
result = e.msg
|
||||
|
||||
proc markAllActivityCenterNotificationsRead*(self: Service, initialLoad: bool = true):string =
|
||||
try:
|
||||
discard status_activity_center.markAllActivityCenterNotificationsRead()
|
||||
# This proc should accept ActivityCenterNotificationType in order to clear all notifications
|
||||
# per type, that's why we have this part here. If we add all types to notificationsType that
|
||||
# means that we need to clear all notifications for all types.
|
||||
var types : seq[ActivityCenterNotificationType]
|
||||
for t in ActivityCenterNotificationType:
|
||||
types.add(t)
|
||||
|
||||
self.events.emit(SIGNAL_MARK_NOTIFICATIONS_AS_READ,
|
||||
MarkAsReadNotificationProperties(notificationTypes: types, isAll: true))
|
||||
except Exception as e:
|
||||
error "Error marking all as read", msg = e.msg
|
||||
result = e.msg
|
||||
|
||||
proc asyncActivityNotificationLoaded*(self: Service, rpcResponse: string) {.slot.} =
|
||||
let rpcResponseObj = rpcResponse.parseJson
|
||||
|
||||
if(rpcResponseObj["activityNotifications"].kind != JNull):
|
||||
let activityCenterNotificationsTuple = parseActivityCenterNotifications(rpcResponseObj["activityNotifications"])
|
||||
|
||||
self.cursor = activityCenterNotificationsTuple[0]
|
||||
|
||||
self.events.emit(SIGNAL_ACTIVITY_CENTER_NOTIFICATIONS_LOADED,
|
||||
ActivityCenterNotificationsArgs(activityCenterNotifications: activityCenterNotificationsTuple[1]))
|
||||
|
||||
proc acceptActivityCenterNotifications*(self: Service, notificationIds: seq[string]): string =
|
||||
try:
|
||||
let response = status_activity_center.acceptActivityCenterNotifications(notificationIds)
|
||||
|
||||
let (chats, messages) = self.chatService.parseChatResponse2(response)
|
||||
self.events.emit(chat_service.SIGNAL_CHAT_UPDATE,
|
||||
ChatUpdateArgsNew(messages: messages, chats: chats))
|
||||
|
||||
except Exception as e:
|
||||
error "Error marking as accepted", msg = e.msg
|
||||
result = e.msg
|
||||
|
||||
proc dismissActivityCenterNotifications*(self: Service, notificationIds: seq[string]): string =
|
||||
try:
|
||||
discard status_activity_center.dismissActivityCenterNotifications(notificationIds)
|
||||
self.events.emit(SIGNAL_MARK_NOTIFICATIONS_AS_DISMISSED,
|
||||
MarkAsDismissedNotificationProperties(notificationIds: notificationIds))
|
||||
except Exception as e:
|
||||
error "Error marking as dismissed", msg = e.msg
|
||||
result = e.msg
|
||||
|
||||
|
|
@ -2,6 +2,7 @@ import NimQml, Tables, json, sequtils, strformat, chronicles, os
|
|||
|
||||
import ./dto/chat as chat_dto
|
||||
import ../message/dto/message as message_dto
|
||||
import ../activity_center/dto/notification as notification_dto
|
||||
import ../contacts/service as contact_service
|
||||
import status/statusgo_backend_new/chat as status_chat
|
||||
import status/statusgo_backend_new/chatCommands as status_chat_commands
|
||||
|
@ -34,7 +35,7 @@ type
|
|||
# emojiReactions*: seq[Reaction]
|
||||
# communities*: seq[Community]
|
||||
# communityMembershipRequests*: seq[CommunityMembershipRequest]
|
||||
# activityCenterNotifications*: seq[ActivityCenterNotification]
|
||||
activityCenterNotifications*: seq[ActivityCenterNotificationDto]
|
||||
# statusUpdates*: seq[StatusUpdate]
|
||||
# deletedMessages*: seq[RemovedMessage]
|
||||
|
||||
|
|
|
@ -36,6 +36,13 @@ type
|
|||
ContactsStatusUpdatedArgs* = ref object of Args
|
||||
statusUpdates*: seq[StatusUpdateDto]
|
||||
|
||||
ContactDetails* = ref object of RootObj
|
||||
displayName*: string
|
||||
localNickname*: string
|
||||
icon*: string
|
||||
isIconIdenticon*: bool
|
||||
isCurrentUser*: bool
|
||||
|
||||
# Local Constants:
|
||||
const CheckStatusIntervalInMilliseconds = 5000 # 5 seconds, this is timeout how often do we check for user status.
|
||||
const OnlineLimitInSeconds = int(5.5 * 60) # 5.5 minutes
|
||||
|
@ -341,3 +348,15 @@ QtObject:
|
|||
timeoutInMilliseconds: CheckStatusIntervalInMilliseconds
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc getContactDetails*(self: Service, pubKey: string): ContactDetails =
|
||||
result = ContactDetails()
|
||||
let contact = self.getContactById(pubKey)
|
||||
result.displayName = contact.userNameOrAlias()
|
||||
result.isCurrentUser = pubKey == singletonInstance.userProfile.getPubKey()
|
||||
result.icon = contact.identicon
|
||||
result.isIconIdenticon = contact.identicon.len > 0
|
||||
if(contact.image.thumbnail.len > 0):
|
||||
result.icon = contact.image.thumbnail
|
||||
result.isIconIdenticon = false
|
||||
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import utils 1.0
|
||||
import "../../../../../shared"
|
||||
import "../../../../../shared/popups"
|
||||
import "../../../../../shared/panels"
|
||||
import "../../../../../shared/status"
|
||||
import ".."
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 64
|
||||
|
||||
Row {
|
||||
id: filterButtons
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.padding
|
||||
height: allBtn.height
|
||||
spacing: Style.current.padding
|
||||
|
||||
StatusButton {
|
||||
id: allBtn
|
||||
//% "All"
|
||||
text: qsTrId("all")
|
||||
type: "secondary"
|
||||
size: "small"
|
||||
highlighted: activityCenter.currentFilter === ActivityCenter.Filter.All
|
||||
onClicked: activityCenter.currentFilter = ActivityCenter.Filter.All
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
id: mentionsBtn
|
||||
//% "Mentions"
|
||||
text: qsTrId("mentions")
|
||||
type: "secondary"
|
||||
enabled: hasMentions
|
||||
size: "small"
|
||||
highlighted: activityCenter.currentFilter === ActivityCenter.Filter.Mentions
|
||||
onClicked: activityCenter.currentFilter = ActivityCenter.Filter.Mentions
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
id: repliesbtn
|
||||
//% "Replies"
|
||||
text: qsTrId("replies")
|
||||
enabled: hasReplies
|
||||
type: "secondary"
|
||||
size: "small"
|
||||
highlighted: activityCenter.currentFilter === ActivityCenter.Filter.Replies
|
||||
onClicked: activityCenter.currentFilter = ActivityCenter.Filter.Replies
|
||||
}
|
||||
|
||||
// StatusButton {
|
||||
// id: contactRequestsBtn
|
||||
// //% "Contact requests"
|
||||
// text: qsTrId("contact-requests")
|
||||
// enabled: hasContactRequests
|
||||
// type: "secondary"
|
||||
// size: "small"
|
||||
// highlighted: activityCenter.currentFilter === ActivityCenter.Filter.ContactRequests
|
||||
// onClicked: activityCenter.currentFilter = ActivityCenter.Filter.ContactRequests
|
||||
// }
|
||||
}
|
||||
|
||||
Row {
|
||||
id: otherButtons
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
height: markAllReadBtn.height
|
||||
spacing: Style.current.padding
|
||||
|
||||
StatusIconButton {
|
||||
id: markAllReadBtn
|
||||
icon.name: "double-check"
|
||||
iconColor: Style.current.primary
|
||||
icon.width: 24
|
||||
icon.height: 24
|
||||
width: 32
|
||||
height: 32
|
||||
onClicked: {
|
||||
// Not Refactored Yet
|
||||
// errorText.text = chatsModel.activityNotificationList.markAllActivityCenterNotificationsRead()
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: markAllReadBtn.hovered
|
||||
//% "Mark all as Read"
|
||||
text: qsTrId("mark-all-as-read")
|
||||
}
|
||||
}
|
||||
|
||||
StatusContextMenuButton {
|
||||
id: moreActionsBtn
|
||||
onClicked: moreActionsMenu.open()
|
||||
|
||||
// TODO: replace with StatusPopupMenu
|
||||
PopupMenu {
|
||||
id: moreActionsMenu
|
||||
x: moreActionsBtn.width - moreActionsMenu.width
|
||||
y: moreActionsBtn.height + 4
|
||||
|
||||
Action {
|
||||
icon.source: hideReadNotifications ? Style.svg("eye") : Style.svg("eye-barred")
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
text: hideReadNotifications ?
|
||||
//% "Show read notifications"
|
||||
qsTrId("show-read-notifications") :
|
||||
//% "Hide read notifications"
|
||||
qsTrId("hide-read-notifications")
|
||||
onTriggered: hideReadNotifications = !hideReadNotifications
|
||||
}
|
||||
Action {
|
||||
icon.source: Style.svg("bell")
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
//% "Notification settings"
|
||||
text: qsTrId("chat-notification-preferences")
|
||||
onTriggered: {
|
||||
activityCenter.close()
|
||||
Global.changeAppSectionBySectionType(Constants.appSection.profile)
|
||||
// TODO: replace with shared store constant
|
||||
// Profile/RootStore.notifications_id
|
||||
profileLayoutContainer.changeProfileSection(7)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: errorText
|
||||
visible: !!text
|
||||
anchors.top: filterButtons.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
color: Style.current.danger
|
||||
}
|
||||
}
|
|
@ -81,8 +81,7 @@ Popup {
|
|||
profileLayoutContainer.changeProfileSection(7)
|
||||
}
|
||||
onMarkAllReadClicked: {
|
||||
// Not Refactored Yet
|
||||
// errorText = activityCenter.store.chatsModelInst.activityNotificationList.markAllActivityCenterNotificationsRead()
|
||||
errorText = activityCenter.store.activityCenterModuleInst.markAllActivityCenterNotificationsRead()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,9 +145,7 @@ Popup {
|
|||
function(left, right) { return left.timestamp > right.timestamp }
|
||||
]
|
||||
|
||||
// Not Refactored Yet
|
||||
model: []
|
||||
// model: activityCenter.store.chatsModelInst.activityNotificationList
|
||||
model: activityCenter.store.activityCenterList
|
||||
|
||||
delegate: Item {
|
||||
id: notificationDelegate
|
||||
|
@ -186,9 +183,7 @@ Popup {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
// Not Refactored Yet
|
||||
property string previousNotificationTimestamp: ""
|
||||
// property string previousNotificationTimestamp: notificationDelegate.idx === 0 ? "" : chatsModel.activityNotificationList.getNotificationData(previousNotificationIndex, "timestamp")
|
||||
property string previousNotificationTimestamp: notificationDelegate.idx === 0 ? "" : activityCenter.store.activityCenterList.getNotificationData(previousNotificationIndex, "timestamp")
|
||||
onPreviousNotificationTimestampChanged: {
|
||||
activityCenter.store.messageStore.prevMsgTimestamp = previousNotificationTimestamp;
|
||||
}
|
||||
|
@ -227,8 +222,7 @@ Popup {
|
|||
}
|
||||
|
||||
Item {
|
||||
// Not Refactored Yet
|
||||
// visible: activityCenter.store.chatsModelInst.activityNotificationList.hasMoreToShow
|
||||
visible: activityCenter.store.activityCenterModuleInst.hasMoreToShow
|
||||
width: parent.width
|
||||
height: visible ? showMoreBtn.height + showMoreBtn.anchors.topMargin : 0
|
||||
StatusButton {
|
||||
|
@ -238,8 +232,7 @@ Popup {
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
// Not Refactored Yet
|
||||
// onClicked: activityCenter.store.chatsModelInst.activityNotificationList.loadMoreNotifications()
|
||||
onClicked: activityCenter.store.activityCenterModuleInst.loadMoreNotifications()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ QtObject {
|
|||
// Not Refactored Yet
|
||||
// property var profileModelInst: profileModel
|
||||
property var profileModuleInst: profileModule
|
||||
property var activityCenterModuleInst: activityCenterModule
|
||||
property var activityCenterList: activityCenterModuleInst.model
|
||||
|
||||
property var userProfileInst: userProfile
|
||||
|
||||
|
|
|
@ -155,10 +155,8 @@ Item {
|
|||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.halfPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
// Not Refactored Yet
|
||||
// onAcceptClicked: root.store.chatsModelInst.activityNotificationList.acceptActivityCenterNotification(model.id)
|
||||
// Not Refactored Yet
|
||||
// onDeclineClicked: root.store.chatsModelInst.activityNotificationList.dismissActivityCenterNotification(model.id)
|
||||
onAcceptClicked: root.store.activityCenterModuleInst.acceptActivityCenterNotification(model.id)
|
||||
onDeclineClicked: root.store.activityCenterModuleInst.dismissActivityCenterNotification(model.id)
|
||||
onProfileClicked: groupRequestContent.openProfile()
|
||||
onBlockClicked: {
|
||||
// Not Refactored Yet
|
||||
|
@ -171,10 +169,9 @@ Item {
|
|||
BlockContactConfirmationDialog {
|
||||
id: blockContactConfirmationDialog
|
||||
onBlockButtonClicked: {
|
||||
// Not Refactored Yet
|
||||
// root.store.profileModuleInst.blockContact(blockContactConfirmationDialog.contactAddress)
|
||||
// root.store.chatsModelInst.activityNotificationList.dismissActivityCenterNotification(model.id)
|
||||
// blockContactConfirmationDialog.close()
|
||||
root.store.profileModuleInst.blockContact(blockContactConfirmationDialog.contactAddress)
|
||||
root.store.activityCenterModuleInst.dismissActivityCenterNotification(model.id)
|
||||
blockContactConfirmationDialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,11 +58,10 @@ Item {
|
|||
tooltip.x: -tooltip.width - Style.current.padding
|
||||
tooltip.y: markReadBtn.height / 2 - height / 2 + 4
|
||||
onClicked: {
|
||||
// Not Refactored Yet
|
||||
// if (!model.read) {
|
||||
// return root.store.chatsModelInst.activityNotificationList.markActivityCenterNotificationRead(model.id, model.message.communityId, model.message.chatId, model.notificationType)
|
||||
// }
|
||||
// return root.store.chatsModelInst.activityNotificationList.markActivityCenterNotificationUnread(model.id, model.message.communityId, model.message.chatId, model.notificationType)
|
||||
if (!model.read) {
|
||||
return root.store.activityCenterModuleInst.markActivityCenterNotificationRead(model.id, model.message.communityId, model.message.chatId, model.notificationType)
|
||||
}
|
||||
return root.store.activityCenterModuleInst.markActivityCenterNotificationUnread(model.id, model.message.communityId, model.message.chatId, model.notificationType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,13 +76,12 @@ Item {
|
|||
// const setActiveChannel = root.store.chatsModelInst.channelView.setActiveChannel
|
||||
// const chatId = model.message.chatId
|
||||
// const messageId = model.message.messageId
|
||||
// root.store.profileModuleInst.addContact(model.author)
|
||||
root.store.activityCenterModuleInst.acceptActivityCenterNotification(model.id)
|
||||
// root.store.chatsModelInst.activityNotificationList.acceptActivityCenterNotification(model.id)
|
||||
// setActiveChannel(chatId)
|
||||
// positionAtMessage(messageId)
|
||||
}
|
||||
// Not Refactored Yet
|
||||
// onDeclineClicked: root.store.chatsModelInst.activityNotificationList.dismissActivityCenterNotification(model.id)
|
||||
onDeclineClicked: root.store.activityCenterModuleInst.dismissActivityCenterNotification(model.id)
|
||||
onProfileClicked: root.openProfile()
|
||||
onBlockClicked: {
|
||||
// Not Refactored Yet
|
||||
|
@ -98,8 +96,8 @@ Item {
|
|||
onBlockButtonClicked: {
|
||||
// Not Refactored Yet
|
||||
// root.store.profileModuleInst.blockContact(blockContactConfirmationDialog.contactAddress)
|
||||
// root.store.chatsModelInst.activityNotificationList.dismissActivityCenterNotification(model.id)
|
||||
// blockContactConfirmationDialog.close()
|
||||
root.store.activityCenterModuleInst.dismissActivityCenterNotification(model.id)
|
||||
blockContactConfirmationDialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue