feat(@Desktop/chat): extend chat section model with onlineStatus

closes: #7279
This commit is contained in:
Patryk Osmaczko 2022-09-09 13:30:22 +02:00 committed by osmaczko
parent c411f83413
commit ad996d4884
16 changed files with 88 additions and 25 deletions

View File

@ -1,4 +1,6 @@
import sequtils, sugar import sequtils, sugar
import ../../../../app_service/common/types
import ../../../../app_service/service/contacts/dto/contacts import ../../../../app_service/service/contacts/dto/contacts
import ../../shared_models/[color_hash_item, color_hash_model] import ../../shared_models/[color_hash_item, color_hash_model]
@ -25,12 +27,13 @@ type
categoryId: string categoryId: string
highlight: bool highlight: bool
trustStatus: TrustStatus trustStatus: TrustStatus
onlineStatus: OnlineStatus
proc setup*(self: BaseItem, id, name, icon: string, color, emoji, description: string, proc setup*(self: BaseItem, id, name, icon: string, color, emoji, description: string,
`type`: int, amIChatAdmin: bool, lastMessageTimestamp: int, hasUnreadMessages: bool, notificationsCount: int, muted, `type`: int, amIChatAdmin: bool, lastMessageTimestamp: int, hasUnreadMessages: bool, notificationsCount: int, muted,
blocked, active: bool, position: int, categoryId: string = "", colorId: int = 0, blocked, active: bool, position: int, categoryId: string = "", colorId: int = 0,
colorHash: seq[ColorHashSegment] = @[], highlight: bool = false, colorHash: seq[ColorHashSegment] = @[], highlight: bool = false,
trustStatus: TrustStatus = TrustStatus.Unknown) = trustStatus: TrustStatus = TrustStatus.Unknown, onlineStatus = OnlineStatus.Inactive) =
self.id = id self.id = id
self.name = name self.name = name
self.amIChatAdmin = amIChatAdmin self.amIChatAdmin = amIChatAdmin
@ -52,15 +55,16 @@ proc setup*(self: BaseItem, id, name, icon: string, color, emoji, description: s
self.categoryId = categoryId self.categoryId = categoryId
self.highlight = highlight self.highlight = highlight
self.trustStatus = trustStatus self.trustStatus = trustStatus
self.onlineStatus = onlineStatus
proc initBaseItem*(id, name, icon: string, color, emoji, description: string, `type`: int, proc initBaseItem*(id, name, icon: string, color, emoji, description: string, `type`: int,
amIChatAdmin: bool, lastMessageTimestamp: int, hasUnreadMessages: bool, notificationsCount: int, muted, blocked, active: bool, amIChatAdmin: bool, lastMessageTimestamp: int, hasUnreadMessages: bool, notificationsCount: int, muted, blocked, active: bool,
position: int, categoryId: string = "", colorId: int = 0, colorHash: seq[ColorHashSegment] = @[], position: int, categoryId: string = "", colorId: int = 0, colorHash: seq[ColorHashSegment] = @[],
highlight: bool = false, trustStatus: TrustStatus = TrustStatus.Unknown): BaseItem = highlight: bool = false, trustStatus: TrustStatus = TrustStatus.Unknown, onlineStatus = OnlineStatus.Inactive): BaseItem =
result = BaseItem() result = BaseItem()
result.setup(id, name, icon, color, emoji, description, `type`, amIChatAdmin, lastMessageTimestamp, result.setup(id, name, icon, color, emoji, description, `type`, amIChatAdmin, lastMessageTimestamp,
hasUnreadMessages, notificationsCount, muted, blocked, active, position, categoryId, colorId, hasUnreadMessages, notificationsCount, muted, blocked, active, position, categoryId, colorId,
colorHash, highlight, trustStatus) colorHash, highlight, trustStatus, onlineStatus)
proc delete*(self: BaseItem) = proc delete*(self: BaseItem) =
discard discard
@ -169,3 +173,9 @@ method trustStatus*(self: BaseItem): TrustStatus {.inline base.} =
method `trustStatus=`*(self: var BaseItem, value: TrustStatus) {.inline base.} = method `trustStatus=`*(self: var BaseItem, value: TrustStatus) {.inline base.} =
self.trustStatus = value self.trustStatus = value
method onlineStatus*(self: BaseItem): OnlineStatus {.inline base.} =
self.onlineStatus
method `onlineStatus=`*(self: var BaseItem, value: OnlineStatus) {.inline base.} =
self.onlineStatus = value

View File

@ -226,6 +226,10 @@ proc init*(self: Controller) =
return return
self.delegate.createOneToOneChat(args.communityId, args.chatId, args.ensName) self.delegate.createOneToOneChat(args.communityId, args.chatId, args.ensName)
self.events.on(SIGNAL_CONTACTS_STATUS_UPDATED) do(e: Args):
let args = ContactsStatusUpdatedArgs(e)
self.delegate.contactsStatusUpdated(args.statusUpdates)
self.events.on(SignalType.HistoryRequestStarted.event) do(e: Args): self.events.on(SignalType.HistoryRequestStarted.event) do(e: Args):
self.delegate.setLoadingHistoryMessagesInProgress(true) self.delegate.setLoadingHistoryMessagesInProgress(true)

View File

@ -313,3 +313,6 @@ method downloadMessages*(self: AccessInterface, chatId: string, filePath: string
method updateLastMessageTimestamp*(self: AccessInterface, chatId: string, lastMessageTimestamp: int) = method updateLastMessageTimestamp*(self: AccessInterface, chatId: string, lastMessageTimestamp: int) =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method contactsStatusUpdated*(self: AccessInterface, statusUpdates: seq[StatusUpdateDto]) =
raise newException(ValueError, "No implementation available")

View File

@ -2,16 +2,20 @@ import strformat, json
import base_item, sub_model, sub_item import base_item, sub_model, sub_item
import ../../shared_models/color_hash_model import ../../shared_models/color_hash_model
import ../../../../app_service/common/types
import ../../../../app_service/service/contacts/dto/contacts
type type
Item* = ref object of BaseItem Item* = ref object of BaseItem
subItems: SubModel subItems: SubModel
proc initItem*(id, name, icon: string, color, emoji, description: string, proc initItem*(id, name, icon: string, color, emoji, description: string,
`type`: int, amIChatAdmin: bool, lastMessageTimestamp: int, hasUnreadMessages: bool, notificationsCount: int, muted, `type`: int, amIChatAdmin: bool, lastMessageTimestamp: int, hasUnreadMessages: bool, notificationsCount: int, muted,
blocked, active: bool, position: int, categoryId: string, colorId: int = 0, colorHash: seq[ColorHashSegment] = @[], highlight: bool = false): Item = blocked, active: bool, position: int, categoryId: string, colorId: int = 0, colorHash: seq[ColorHashSegment] = @[], highlight: bool = false,
trustStatus: TrustStatus = TrustStatus.Unknown, onlineStatus = OnlineStatus.Inactive): Item =
result = Item() result = Item()
result.setup(id, name, icon, color, emoji, description, `type`, amIChatAdmin, lastMessageTimestamp, hasUnreadMessages, result.setup(id, name, icon, color, emoji, description, `type`, amIChatAdmin, lastMessageTimestamp, hasUnreadMessages,
notificationsCount, muted, blocked, active, position, categoryId, colorId, colorHash, highlight) notificationsCount, muted, blocked, active, position, categoryId, colorId, colorHash, highlight, trustStatus, onlineStatus)
result.subItems = newSubModel() result.subItems = newSubModel()
proc delete*(self: Item) = proc delete*(self: Item) =
@ -41,6 +45,7 @@ proc `$`*(self: Item): string =
categoryId: {self.categoryId}, categoryId: {self.categoryId},
highlight: {self.highlight}, highlight: {self.highlight},
trustStatus: {self.trustStatus}, trustStatus: {self.trustStatus},
onlineStatus: {self.onlineStatus},
subItems:[ subItems:[
{$self.subItems} {$self.subItems}
]""" ]"""
@ -65,6 +70,7 @@ proc toJsonNode*(self: Item): JsonNode =
"categoryId": self.categoryId, "categoryId": self.categoryId,
"highlight": self.highlight, "highlight": self.highlight,
"trustStatus": self.trustStatus, "trustStatus": self.trustStatus,
"onlineStatus": self.onlineStatus
} }
proc appendSubItems*(self: Item, items: seq[SubItem]) = proc appendSubItems*(self: Item, items: seq[SubItem]) =

View File

@ -1,4 +1,5 @@
import NimQml, Tables, strutils, strformat, json import NimQml, Tables, strutils, strformat, json
import ../../../../app_service/common/types
from ../../../../app_service/service/chat/dto/chat import ChatType from ../../../../app_service/service/chat/dto/chat import ChatType
from ../../../../app_service/service/contacts/dto/contacts import TrustStatus from ../../../../app_service/service/contacts/dto/contacts import TrustStatus
import item, sub_item, base_item, sub_model import item, sub_item, base_item, sub_model
@ -27,6 +28,7 @@ type
CategoryId CategoryId
Highlight Highlight
TrustStatus TrustStatus
OnlineStatus
QtObject: QtObject:
type type
@ -92,6 +94,7 @@ QtObject:
ModelRole.CategoryId.int:"categoryId", ModelRole.CategoryId.int:"categoryId",
ModelRole.Highlight.int:"highlight", ModelRole.Highlight.int:"highlight",
ModelRole.TrustStatus.int:"trustStatus", ModelRole.TrustStatus.int:"trustStatus",
ModelRole.OnlineStatus.int:"onlineStatus",
}.toTable }.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant = method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -149,6 +152,8 @@ QtObject:
result = newQVariant(item.highlight) result = newQVariant(item.highlight)
of ModelRole.TrustStatus: of ModelRole.TrustStatus:
result = newQVariant(item.trustStatus.int) result = newQVariant(item.trustStatus.int)
of ModelRole.OnlineStatus:
result = newQVariant(item.onlineStatus.int)
proc appendItem*(self: Model, item: Item) = proc appendItem*(self: Model, item: Item) =
let parentModelIndex = newQModelIndex() let parentModelIndex = newQModelIndex()
@ -304,6 +309,16 @@ QtObject:
self.dataChanged(index, index, self.dataChanged(index, index,
@[ModelRole.Name.int, ModelRole.Description.int, ModelRole.Emoji.int, ModelRole.Color.int]) @[ModelRole.Name.int, ModelRole.Description.int, ModelRole.Emoji.int, ModelRole.Color.int])
return return
proc updateItemOnlineStatus*(self: Model, id: string, onlineStatus: OnlineStatus) =
## This updates only first level items, it doesn't update subitems, since subitems cannot have onlineStatus.
for i in 0 ..< self.items.len:
if(self.items[i].id == id):
if(self.items[i].onlineStatus != onlineStatus):
self.items[i].BaseItem.onlineStatus = onlineStatus
let index = self.createIndex(i, 0, nil)
self.dataChanged(index, index, @[ModelRole.OnlineStatus.int])
return
proc updateNotificationsForItemOrSubItemById*(self: Model, id: string, hasUnreadMessages: bool, proc updateNotificationsForItemOrSubItemById*(self: Model, id: string, hasUnreadMessages: bool,
notificationsCount: int) = notificationsCount: int) =

View File

@ -13,6 +13,7 @@ import ../../../global/app_sections_config as conf
import ../../../global/global_singleton import ../../../global/global_singleton
import ../../../core/eventemitter import ../../../core/eventemitter
import ../../../core/notifications/details as notification_details import ../../../core/notifications/details as notification_details
import ../../../../app_service/common/types
import ../../../../app_service/service/settings/service as settings_service import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/contacts/service as contact_service import ../../../../app_service/service/contacts/service as contact_service
import ../../../../app_service/service/chat/service as chat_service import ../../../../app_service/service/chat/service as chat_service
@ -135,6 +136,7 @@ proc buildChatSectionUI(
var chatImage = "" var chatImage = ""
var colorHash: ColorHashDto = @[] var colorHash: ColorHashDto = @[]
var colorId: int = 0 var colorId: int = 0
var onlineStatus = OnlineStatus.Inactive
let isUsersListAvailable = (chatDto.chatType != ChatType.OneToOne and let isUsersListAvailable = (chatDto.chatType != ChatType.OneToOne and
chatDto.chatType != ChatType.Public) chatDto.chatType != ChatType.Public)
var blocked = false var blocked = false
@ -146,6 +148,8 @@ proc buildChatSectionUI(
blocked = contactDetails.details.isBlocked() blocked = contactDetails.details.isBlocked()
colorHash = self.controller.getColorHash(chatDto.id) colorHash = self.controller.getColorHash(chatDto.id)
colorId = self.controller.getColorId(chatDto.id) colorId = self.controller.getColorId(chatDto.id)
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(chatDto.id).statusType)
elif(chatDto.chatType == ChatType.PrivateGroupChat): elif(chatDto.chatType == ChatType.PrivateGroupChat):
chatImage = chatDto.icon chatImage = chatDto.icon
@ -158,7 +162,7 @@ proc buildChatSectionUI(
let channelItem = initItem(chatDto.id, chatName, chatImage, chatDto.color, let channelItem = initItem(chatDto.id, chatName, chatImage, chatDto.color,
chatDto.emoji, chatDto.description, chatDto.chatType.int, amIChatAdmin, chatDto.timestamp.int, hasNotification, chatDto.emoji, chatDto.description, chatDto.chatType.int, amIChatAdmin, chatDto.timestamp.int, hasNotification,
notificationsCount, chatDto.muted, blocked, chatDto.active, chatDto.position, notificationsCount, chatDto.muted, blocked, chatDto.active, chatDto.position,
chatDto.categoryId, colorId, colorHash) chatDto.categoryId, colorId, colorHash, onlineStatus = onlineStatus)
self.view.chatsModel().appendItem(channelItem) self.view.chatsModel().appendItem(channelItem)
self.addSubmodule(chatDto.id, belongToCommunity, isUsersListAvailable, events, settingsService, self.addSubmodule(chatDto.id, belongToCommunity, isUsersListAvailable, events, settingsService,
contactService, chatService, communityService, messageService, gifService, mailserversService) contactService, chatService, communityService, messageService, gifService, mailserversService)
@ -410,12 +414,15 @@ method addNewChat*(
var chatImage = chatDto.icon var chatImage = chatDto.icon
var colorHash: ColorHashDto = @[] var colorHash: ColorHashDto = @[]
var colorId: int = 0 var colorId: int = 0
var onlineStatus = OnlineStatus.Inactive
var isUsersListAvailable = true var isUsersListAvailable = true
if(chatDto.chatType == ChatType.OneToOne): if(chatDto.chatType == ChatType.OneToOne):
isUsersListAvailable = false isUsersListAvailable = false
(chatName, chatImage) = self.controller.getOneToOneChatNameAndImage(chatDto.id) (chatName, chatImage) = self.controller.getOneToOneChatNameAndImage(chatDto.id)
colorHash = self.controller.getColorHash(chatDto.id) colorHash = self.controller.getColorHash(chatDto.id)
colorId = self.controller.getColorId(chatDto.id) colorId = self.controller.getColorId(chatDto.id)
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(chatDto.id).statusType)
var amIChatAdmin = false var amIChatAdmin = false
if(belongsToCommunity): if(belongsToCommunity):
@ -426,7 +433,8 @@ method addNewChat*(
if chatDto.categoryId.len == 0: if chatDto.categoryId.len == 0:
let item = initItem(chatDto.id, chatName, chatImage, chatDto.color, chatDto.emoji, let item = initItem(chatDto.id, chatName, chatImage, chatDto.color, chatDto.emoji,
chatDto.description, chatDto.chatType.int, amIChatAdmin, chatDto.timestamp.int, hasNotification, notificationsCount, chatDto.description, chatDto.chatType.int, amIChatAdmin, chatDto.timestamp.int, hasNotification, notificationsCount,
chatDto.muted, blocked=false, active=false, position = 0, chatDto.categoryId, colorId, colorHash, chatDto.highlight) chatDto.muted, blocked=false, active=false, position = 0, chatDto.categoryId, colorId, colorHash, chatDto.highlight,
onlineStatus = onlineStatus)
self.addSubmodule(chatDto.id, belongsToCommunity, isUsersListAvailable, events, settingsService, contactService, chatService, self.addSubmodule(chatDto.id, belongsToCommunity, isUsersListAvailable, events, settingsService, contactService, chatService,
communityService, messageService, gifService, mailserversService) communityService, messageService, gifService, mailserversService)
self.chatContentModules[chatDto.id].load() self.chatContentModules[chatDto.id].load()
@ -863,3 +871,8 @@ method downloadMessages*(self: Module, chatId: string, filePath: string) =
return return
self.chatContentModules[chatId].downloadMessages(filePath) self.chatContentModules[chatId].downloadMessages(filePath)
method contactsStatusUpdated*(self: Module, statusUpdates: seq[StatusUpdateDto]) =
for s in statusUpdates:
let status = toOnlineStatus(s.statusType)
self.view.chatsModel().updateItemOnlineStatus(s.publicKey, status)

View File

@ -14,6 +14,7 @@ import ../../shared_models/section_item
import ../../shared_models/[member_item, member_model, section_model] import ../../shared_models/[member_item, member_model, section_model]
import ../../../global/global_singleton import ../../../global/global_singleton
import ../../../core/eventemitter import ../../../core/eventemitter
import ../../../../app_service/common/types
import ../../../../app_service/service/community/service as community_service import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/contacts/service as contacts_service import ../../../../app_service/service/contacts/service as contacts_service
import ../../../../app_service/service/chat/dto/chat import ../../../../app_service/service/chat/dto/chat

View File

@ -53,7 +53,7 @@ import ../../../app_service/service/ens/service as ens_service
import ../../../app_service/service/network/service as network_service import ../../../app_service/service/network/service as network_service
import ../../../app_service/service/general/service as general_service import ../../../app_service/service/general/service as general_service
import ../../../app_service/service/keycard/service as keycard_service import ../../../app_service/service/keycard/service as keycard_service
from ../../../app_service/common/types import StatusType import ../../../app_service/common/types
import ../../../app_service/common/social_links import ../../../app_service/common/social_links
import ../../core/notifications/details import ../../core/notifications/details

View File

@ -7,6 +7,7 @@ import ../io_interface as delegate_interface
import ../../../../global/global_singleton import ../../../../global/global_singleton
import ../../../../core/eventemitter import ../../../../core/eventemitter
import ../../../../../app_service/common/types
import ../../../../../app_service/service/contacts/dto/contacts as contacts_dto import ../../../../../app_service/service/contacts/dto/contacts as contacts_dto
import ../../../../../app_service/service/contacts/service as contacts_service import ../../../../../app_service/service/contacts/service as contacts_service
import ../../../../../app_service/service/chat/service as chat_service import ../../../../../app_service/service/chat/service as chat_service

View File

@ -1,7 +1,9 @@
import NimQml import NimQml
import section_item, user_item import section_item
import ../../../app_service/service/contacts/dto/contacts import ../../../app_service/service/contacts/dto/contacts
import ../../../app_service/common/types
QtObject: QtObject:
type ActiveSection* = ref object of QObject type ActiveSection* = ref object of QObject
item: SectionItem item: SectionItem

View File

@ -1,6 +1,8 @@
import strformat import strformat
import user_item import user_item
import ../../../app_service/common/types
export user_item export user_item
type type

View File

@ -2,6 +2,7 @@ import NimQml, Tables, strformat, sequtils, sugar
# TODO: use generics to remove duplication between user_model and member_model # TODO: use generics to remove duplication between user_model and member_model
import ../../../app_service/common/types
import ../../../app_service/service/contacts/dto/contacts import ../../../app_service/service/contacts/dto/contacts
import member_item import member_item

View File

@ -2,6 +2,8 @@ import strformat
import ./member_model, ./member_item import ./member_model, ./member_item
import ../main/communities/models/[pending_request_item, pending_request_model] import ../main/communities/models/[pending_request_item, pending_request_model]
import ../../../app_service/common/types
type type
SectionType* {.pure.} = enum SectionType* {.pure.} = enum
Chat = 0 Chat = 0

View File

@ -2,10 +2,6 @@ import strformat
import ../../../app_service/common/types import ../../../app_service/common/types
type type
OnlineStatus* {.pure.} = enum
Inactive = 0
Online
ContactRequest* {.pure.} = enum ContactRequest* {.pure.} = enum
None = 0 None = 0
IncomingPending IncomingPending
@ -113,12 +109,6 @@ proc initUserItem*(
incomingVerificationStatus = incomingVerificationStatus, incomingVerificationStatus = incomingVerificationStatus,
outgoingVerificationStatus = outgoingVerificationStatus) outgoingVerificationStatus = outgoingVerificationStatus)
proc toOnlineStatus*(statusType: StatusType): OnlineStatus =
if(statusType == StatusType.AlwaysOnline or statusType == StatusType.Automatic):
return OnlineStatus.Online
else:
return OnlineStatus.Inactive
proc `$`*(self: UserItem): string = proc `$`*(self: UserItem): string =
result = fmt"""User Item( result = fmt"""User Item(
pubKey: {self.pubkey}, pubKey: {self.pubkey},

View File

@ -1,6 +1,8 @@
import NimQml, Tables, strformat, sequtils, sugar import NimQml, Tables, strformat, sequtils, sugar
import user_item import user_item
import ../../../app_service/common/types
type type
ModelRole {.pure.} = enum ModelRole {.pure.} = enum
PubKey = UserRole + 1 PubKey = UserRole + 1

View File

@ -15,9 +15,20 @@ type
Gap = 10 Gap = 10
Edit = 11 Edit = 11
type StatusType* {.pure.} = enum type
Unknown = 0 StatusType* {.pure.} = enum
Automatic Unknown = 0
DoNotDisturb Automatic
AlwaysOnline DoNotDisturb
Inactive AlwaysOnline
Inactive
OnlineStatus* {.pure.} = enum
Inactive = 0
Online
proc toOnlineStatus*(statusType: StatusType): OnlineStatus =
if(statusType == StatusType.AlwaysOnline or statusType == StatusType.Automatic):
return OnlineStatus.Online
else:
return OnlineStatus.Inactive