feat: contact verification request and trust status
feat: contact verification fix: add remove identity verified btn fix: add toast message feat: received verification request model feat: finish identity verification flow Fixes #4784
This commit is contained in:
parent
5d4aba62e3
commit
1e7c648300
|
@ -28,6 +28,7 @@ type MessageSignal* = ref object of Signal
|
|||
currentStatus*: seq[StatusUpdateDto]
|
||||
settings*: seq[SettingsFieldDto]
|
||||
clearedHistories*: seq[ClearedHistoryDto]
|
||||
verificationRequests*: seq[VerificationRequest]
|
||||
|
||||
proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
|
||||
var signal:MessageSignal = MessageSignal()
|
||||
|
@ -103,5 +104,9 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
|
|||
for jsonSettingsField in event["event"]["settings"]:
|
||||
signal.settings.add(jsonSettingsField.toSettingsFieldDto())
|
||||
|
||||
if event["event"]{"verificationRequests"} != nil:
|
||||
for jsonVerificationRequest in event["event"]["verificationRequests"]:
|
||||
signal.verificationRequests.add(jsonVerificationRequest.toVerificationRequest())
|
||||
|
||||
result = signal
|
||||
|
||||
|
|
|
@ -92,7 +92,8 @@ proc createMessageItemFromDto(self: Module, message: MessageDto, chatDetails: Ch
|
|||
message.sticker.pack,
|
||||
message.links,
|
||||
newTransactionParametersItem("","","","","","",-1,""),
|
||||
message.mentionedUsersPks
|
||||
message.mentionedUsersPks,
|
||||
contactDetails.details.trustStatus
|
||||
))
|
||||
|
||||
method convertToItems*(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import sequtils, sugar
|
||||
import ../../../../app_service/service/contacts/dto/contacts
|
||||
|
||||
import ../../shared_models/[color_hash_item, color_hash_model]
|
||||
|
||||
|
@ -22,10 +23,13 @@ type
|
|||
position: int
|
||||
categoryId: string
|
||||
highlight: bool
|
||||
trustStatus: TrustStatus
|
||||
|
||||
proc setup*(self: BaseItem, id, name, icon: string, color, emoji, description: string,
|
||||
`type`: int, amIChatAdmin: bool, hasUnreadMessages: bool, notificationsCount: int, muted, blocked, active: bool,
|
||||
position: int, categoryId: string = "", colorId: int = 0, colorHash: seq[ColorHashSegment] = @[], highlight: bool = false) =
|
||||
`type`: int, amIChatAdmin: bool, hasUnreadMessages: bool, notificationsCount: int, muted,
|
||||
blocked, active: bool, position: int, categoryId: string = "", colorId: int = 0,
|
||||
colorHash: seq[ColorHashSegment] = @[], highlight: bool = false,
|
||||
trustStatus: TrustStatus = TrustStatus.Unknown) =
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.amIChatAdmin = amIChatAdmin
|
||||
|
@ -45,13 +49,16 @@ proc setup*(self: BaseItem, id, name, icon: string, color, emoji, description: s
|
|||
self.position = position
|
||||
self.categoryId = categoryId
|
||||
self.highlight = highlight
|
||||
self.trustStatus = trustStatus
|
||||
|
||||
proc initBaseItem*(id, name, icon: string, color, emoji, description: string, `type`: int,
|
||||
amIChatAdmin: bool, hasUnreadMessages: bool, notificationsCount: int, muted, blocked, active: bool,
|
||||
position: int, categoryId: string = "", colorId: int = 0, colorHash: seq[ColorHashSegment] = @[], highlight: bool = false): BaseItem =
|
||||
position: int, categoryId: string = "", colorId: int = 0, colorHash: seq[ColorHashSegment] = @[],
|
||||
highlight: bool = false, trustStatus: TrustStatus = TrustStatus.Unknown): BaseItem =
|
||||
result = BaseItem()
|
||||
result.setup(id, name, icon, color, emoji, description, `type`, amIChatAdmin,
|
||||
hasUnreadMessages, notificationsCount, muted, blocked, active, position, categoryId, colorId, colorHash, highlight)
|
||||
hasUnreadMessages, notificationsCount, muted, blocked, active, position, categoryId, colorId,
|
||||
colorHash, highlight, trustStatus)
|
||||
|
||||
proc delete*(self: BaseItem) =
|
||||
discard
|
||||
|
@ -148,3 +155,9 @@ method highlight*(self: BaseItem): bool {.inline base.} =
|
|||
|
||||
method `highlight=`*(self: var BaseItem, value: bool) {.inline base.} =
|
||||
self.highlight = value
|
||||
|
||||
method trustStatus*(self: BaseItem): TrustStatus {.inline base.} =
|
||||
self.trustStatus
|
||||
|
||||
method `trustStatus=`*(self: var BaseItem, value: TrustStatus) {.inline base.} =
|
||||
self.trustStatus = value
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import NimQml
|
||||
|
||||
|
||||
QtObject:
|
||||
type ChatDetails* = ref object of QObject
|
||||
# fixed props
|
||||
|
@ -17,6 +18,7 @@ QtObject:
|
|||
notificationsCount: int
|
||||
muted: bool
|
||||
position: int
|
||||
isUntrustworthy: bool
|
||||
isMutualContact: bool
|
||||
|
||||
proc delete*(self: ChatDetails) =
|
||||
|
@ -29,7 +31,7 @@ QtObject:
|
|||
proc setChatDetails*(self: ChatDetails, id: string, `type`: int, belongsToCommunity,
|
||||
isUsersListAvailable: bool, name, icon: string, color, description,
|
||||
emoji: string, hasUnreadMessages: bool, notificationsCount: int, muted: bool, position: int,
|
||||
isMutualContact: bool = false) =
|
||||
isUntrustworthy: bool, isMutualContact: bool = false) =
|
||||
self.id = id
|
||||
self.`type` = `type`
|
||||
self.belongsToCommunity = belongsToCommunity
|
||||
|
@ -43,6 +45,7 @@ QtObject:
|
|||
self.notificationsCount = notificationsCount
|
||||
self.muted = muted
|
||||
self.position = position
|
||||
self.isUntrustworthy = isUntrustworthy
|
||||
self.isMutualContact = isMutualContact
|
||||
|
||||
proc getId(self: ChatDetails): string {.slot.} =
|
||||
|
@ -174,3 +177,14 @@ QtObject:
|
|||
proc setIsMutualContact*(self: ChatDetails, value: bool) = # this is not a slot
|
||||
self.isMutualContact = value
|
||||
self.isMutualContactChanged()
|
||||
|
||||
proc isUntrustworthyChanged(self: ChatDetails) {.signal.}
|
||||
proc getIsUntrustworthy(self: ChatDetails): bool {.slot.} =
|
||||
return self.isUntrustworthy
|
||||
QtProperty[bool] isUntrustworthy:
|
||||
read = getIsUntrustworthy
|
||||
notify = isUntrustworthyChanged
|
||||
|
||||
proc setIsUntrustworthy*(self: ChatDetails, value: bool) = # this is not a slot
|
||||
self.isUntrustworthy = value
|
||||
self.isUntrustworthyChanged()
|
|
@ -106,6 +106,18 @@ proc init*(self: Controller) =
|
|||
var args = ContactArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.contactId)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_TRUSTED) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_REMOVED_TRUST_STATUS) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UPDATED) do(e: Args):
|
||||
var args = ContactArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.contactId)
|
||||
|
|
|
@ -111,6 +111,18 @@ proc init*(self: Controller) =
|
|||
var args = ContactArgs(e)
|
||||
self.delegate.updateContactDetails(args.contactId)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.updateContactDetails(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_TRUSTED) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.updateContactDetails(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_REMOVED_TRUST_STATUS) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.updateContactDetails(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UPDATED) do(e: Args):
|
||||
var args = ContactArgs(e)
|
||||
self.delegate.updateContactDetails(args.contactId)
|
||||
|
|
|
@ -8,6 +8,7 @@ import ../../../../shared_models/message_reaction_item
|
|||
import ../../../../shared_models/message_transaction_parameters_item
|
||||
import ../../../../../global/global_singleton
|
||||
import ../../../../../core/eventemitter
|
||||
import ../../../../../../app_service/service/contacts/dto/contacts
|
||||
import ../../../../../../app_service/service/contacts/service as contact_service
|
||||
import ../../../../../../app_service/service/community/service as community_service
|
||||
import ../../../../../../app_service/service/chat/service as chat_service
|
||||
|
@ -92,7 +93,8 @@ proc createFetchMoreMessagesItem(self: Module): Item =
|
|||
stickerPack = -1,
|
||||
@[],
|
||||
newTransactionParametersItem("","","","","","",-1,""),
|
||||
@[]
|
||||
@[],
|
||||
TrustStatus.Unknown
|
||||
)
|
||||
|
||||
proc createChatIdentifierItem(self: Module): Item =
|
||||
|
@ -128,7 +130,8 @@ proc createChatIdentifierItem(self: Module): Item =
|
|||
stickerPack = -1,
|
||||
@[],
|
||||
newTransactionParametersItem("","","","","","",-1,""),
|
||||
@[]
|
||||
@[],
|
||||
TrustStatus.Unknown
|
||||
)
|
||||
|
||||
proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module): bool =
|
||||
|
@ -198,8 +201,9 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
|
|||
m.transactionParameters.transactionHash,
|
||||
m.transactionParameters.commandState,
|
||||
m.transactionParameters.signature),
|
||||
m.mentionedUsersPks()
|
||||
)
|
||||
m.mentionedUsersPks(),
|
||||
sender.details.trustStatus,
|
||||
)
|
||||
|
||||
for r in reactions:
|
||||
if(r.messageId == m.id):
|
||||
|
@ -285,7 +289,8 @@ method messageAdded*(self: Module, message: MessageDto) =
|
|||
message.transactionParameters.transactionHash,
|
||||
message.transactionParameters.commandState,
|
||||
message.transactionParameters.signature),
|
||||
message.mentionedUsersPks
|
||||
message.mentionedUsersPks,
|
||||
sender.details.trustStatus,
|
||||
)
|
||||
|
||||
self.view.model().insertItemBasedOnTimestamp(item)
|
||||
|
@ -398,6 +403,7 @@ method updateContactDetails*(self: Module, contactId: string) =
|
|||
item.senderLocalName = updatedContact.details.localNickname
|
||||
item.senderIcon = updatedContact.icon
|
||||
item.senderIsAdded = updatedContact.details.added
|
||||
item.senderTrustStatus = updatedContact.details.trustStatus
|
||||
if(item.messageContainsMentions):
|
||||
let (m, _, err) = self.controller.getMessageDetails(item.id)
|
||||
if(err.len == 0):
|
||||
|
|
|
@ -76,17 +76,20 @@ method load*(self: Module) =
|
|||
var chatName = chatDto.name
|
||||
var chatImage = chatDto.icon
|
||||
var isMutualContact = false
|
||||
var trustStatus = TrustStatus.Unknown
|
||||
if(chatDto.chatType == ChatType.OneToOne):
|
||||
let contactDto = self.controller.getContactById(self.controller.getMyChatId())
|
||||
chatName = contactDto.userNameOrAlias()
|
||||
isMutualContact = contactDto.isMutualContact
|
||||
trustStatus = contactDto.trustStatus
|
||||
if(contactDto.image.thumbnail.len > 0):
|
||||
chatImage = contactDto.image.thumbnail
|
||||
|
||||
self.view.load(chatDto.id, chatDto.chatType.int, self.controller.belongsToCommunity(),
|
||||
self.controller.isUsersListAvailable(), chatName, chatImage,
|
||||
chatDto.color, chatDto.description, chatDto.emoji, hasNotification, notificationsCount,
|
||||
chatDto.muted, chatDto.position, isMutualContact)
|
||||
chatDto.muted, chatDto.position, isUntrustworthy = trustStatus == TrustStatus.Untrustworthy,
|
||||
isMutualContact)
|
||||
|
||||
self.inputAreaModule.load()
|
||||
self.messagesModule.load()
|
||||
|
@ -188,7 +191,8 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy:
|
|||
m.transactionParameters.transactionHash,
|
||||
m.transactionParameters.commandState,
|
||||
m.transactionParameters.signature),
|
||||
m.mentionedUsersPks
|
||||
m.mentionedUsersPks,
|
||||
contactDetails.details.trustStatus,
|
||||
)
|
||||
item.pinned = true
|
||||
item.pinnedBy = actionInitiatedBy
|
||||
|
@ -317,6 +321,7 @@ method onContactDetailsUpdated*(self: Module, contactId: string) =
|
|||
item.senderDisplayName = updatedContact.displayName
|
||||
item.senderLocalName = updatedContact.details.localNickname
|
||||
item.senderIcon = updatedContact.icon
|
||||
item.senderTrustStatus = updatedContact.details.trustStatus
|
||||
if(item.messageContainsMentions):
|
||||
let (m, _, err) = self.controller.getMessageDetails(item.id)
|
||||
if(err.len == 0):
|
||||
|
@ -325,6 +330,7 @@ method onContactDetailsUpdated*(self: Module, contactId: string) =
|
|||
|
||||
if(self.controller.getMyChatId() == contactId):
|
||||
self.view.updateChatDetailsNameAndIcon(updatedContact.displayName, updatedContact.icon)
|
||||
self.view.updateTrustStatus(updatedContact.details.trustStatus == TrustStatus.Untrustworthy)
|
||||
|
||||
method onNotificationsUpdated*(self: Module, hasUnreadMessages: bool, notificationCount: int) =
|
||||
self.view.updateChatDetailsNotifications(hasUnreadMessages, notificationCount)
|
||||
|
@ -345,3 +351,6 @@ method onMutualContactChanged*(self: Module) =
|
|||
let contactDto = self.controller.getContactById(self.controller.getMyChatId())
|
||||
let isMutualContact = contactDto.isMutualContact
|
||||
self.view.onMutualContactChanged(isMutualContact)
|
||||
|
||||
method contactTrustStatusChanged*(self: Module, publicKey: string, isUntrustworthy: bool) =
|
||||
self.view.updateTrustStatus(isUntrustworthy)
|
||||
|
|
|
@ -91,6 +91,18 @@ proc init*(self: Controller) =
|
|||
|
||||
# Events only for the user list, so not needed in public and one to one chats
|
||||
if(self.isUsersListAvailable):
|
||||
self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_TRUSTED) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_REMOVED_TRUST_STATUS) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACTS_STATUS_UPDATED) do(e: Args):
|
||||
let args = ContactsStatusUpdatedArgs(e)
|
||||
self.delegate.contactsStatusUpdated(args.statusUpdates)
|
||||
|
|
|
@ -7,6 +7,7 @@ import ../../../../../global/global_singleton
|
|||
import ../../../../../core/eventemitter
|
||||
import ../../../../../../app_service/common/conversion
|
||||
import ../../../../../../app_service/common/types
|
||||
import ../../../../../../app_service/service/contacts/dto/contacts
|
||||
import ../../../../../../app_service/service/contacts/service as contact_service
|
||||
import ../../../../../../app_service/service/chat/service as chat_service
|
||||
import ../../../../../../app_service/service/community/service as community_service
|
||||
|
@ -81,6 +82,7 @@ method onNewMessagesLoaded*(self: Module, messages: seq[MessageDto]) =
|
|||
icon = contactDetails.icon,
|
||||
onlineStatus = status,
|
||||
isContact = contactDetails.details.added,
|
||||
isUntrustworthy = contactDetails.details.trustStatus == TrustStatus.Untrustworthy,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -108,6 +110,7 @@ method contactUpdated*(self: Module, publicKey: string) =
|
|||
alias = contactDetails.details.alias,
|
||||
icon = contactDetails.icon,
|
||||
isContact = contactDetails.details.added, #FIXME
|
||||
isUntrustworthy = contactDetails.details.trustStatus == TrustStatus.Untrustworthy,
|
||||
)
|
||||
|
||||
method loggedInUserImageChanged*(self: Module) =
|
||||
|
@ -148,8 +151,9 @@ method addChatMember*(self: Module, member: ChatMember) =
|
|||
onlineStatus = status,
|
||||
isContact = contactDetails.details.added, #FIXME
|
||||
isAdmin = member.admin,
|
||||
joined = member.joined)
|
||||
)
|
||||
joined = member.joined,
|
||||
isUntrustworthy = contactDetails.details.trustStatus == TrustStatus.Untrustworthy
|
||||
))
|
||||
|
||||
method onChatMembersAdded*(self: Module, ids: seq[string]) =
|
||||
for id in ids:
|
||||
|
@ -184,7 +188,9 @@ method onChatMemberUpdated*(self: Module, publicKey: string, admin: bool, joined
|
|||
icon = contactDetails.icon,
|
||||
isContact = contactDetails.details.added,
|
||||
isAdmin = admin,
|
||||
joined = joined)
|
||||
joined = joined,
|
||||
isUntrustworthy = contactDetails.details.trustStatus == TrustStatus.Untrustworthy,
|
||||
)
|
||||
|
||||
method getMembersPublicKeys*(self: Module): string =
|
||||
let publicKeys = self.controller.getMembersPublicKeys()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import NimQml
|
||||
import ../../../shared_models/message_model as pinned_msg_model
|
||||
import ../../../../../app_service/service/contacts/dto/contacts as contacts_dto
|
||||
|
||||
import io_interface
|
||||
import chat_details
|
||||
|
||||
|
@ -32,9 +34,11 @@ QtObject:
|
|||
|
||||
proc load*(self: View, id: string, `type`: int, belongsToCommunity, isUsersListAvailable: bool,
|
||||
name, icon: string, color, description, emoji: string, hasUnreadMessages: bool,
|
||||
notificationsCount: int, muted: bool, position: int, isMutualContact: bool) =
|
||||
self.chatDetails.setChatDetails(id, `type`, belongsToCommunity, isUsersListAvailable, name, icon,
|
||||
color, description, emoji, hasUnreadMessages, notificationsCount, muted, position, isMutualContact)
|
||||
notificationsCount: int, muted: bool, position: int, isUntrustworthy: bool,
|
||||
isMutualContact: bool) =
|
||||
self.chatDetails.setChatDetails(id, `type`, belongsToCommunity, isUsersListAvailable, name,
|
||||
icon, color, description, emoji, hasUnreadMessages, notificationsCount, muted, position,
|
||||
isUntrustworthy, isMutualContact)
|
||||
self.delegate.viewDidLoad()
|
||||
self.chatDetailsChanged()
|
||||
|
||||
|
@ -95,6 +99,9 @@ QtObject:
|
|||
self.chatDetails.setName(name)
|
||||
self.chatDetails.setIcon(icon)
|
||||
|
||||
proc updateTrustStatus*(self: View, isUntrustworthy: bool) =
|
||||
self.chatDetails.setIsUntrustworthy(isUntrustworthy)
|
||||
|
||||
proc updateChatDetailsNotifications*(self: View, hasUnreadMessages: bool, notificationCount: int) =
|
||||
self.chatDetails.setHasUnreadMessages(hasUnreadMessages)
|
||||
self.chatDetails.setNotificationCount(notificationCount)
|
||||
|
|
|
@ -180,6 +180,18 @@ proc init*(self: Controller) =
|
|||
var args = ContactArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.contactId)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_TRUSTED) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_REMOVED_TRUST_STATUS) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.onContactDetailsUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CHAT_RENAMED) do(e: Args):
|
||||
var args = ChatRenameArgs(e)
|
||||
self.delegate.onChatRenamed(args.id, args.newName)
|
||||
|
|
|
@ -39,6 +39,7 @@ proc `$`*(self: Item): string =
|
|||
position: {self.position},
|
||||
categoryId: {self.categoryId},
|
||||
highlight: {self.highlight},
|
||||
trustStatus: {self.trustStatus},
|
||||
subItems:[
|
||||
{$self.subItems}
|
||||
]"""
|
||||
|
@ -60,7 +61,8 @@ proc toJsonNode*(self: Item): JsonNode =
|
|||
"active": self.active,
|
||||
"position": self.position,
|
||||
"categoryId": self.categoryId,
|
||||
"highlight": self.highlight
|
||||
"highlight": self.highlight,
|
||||
"trustStatus": self.trustStatus,
|
||||
}
|
||||
|
||||
proc appendSubItems*(self: Item, items: seq[SubItem]) =
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import NimQml, Tables, strutils, strformat, json, algorithm
|
||||
from ../../../../app_service/service/chat/dto/chat import ChatType
|
||||
from ../../../../app_service/service/contacts/dto/contacts import TrustStatus
|
||||
import item, sub_item, base_item, sub_model
|
||||
|
||||
type
|
||||
|
@ -24,6 +25,7 @@ type
|
|||
IsCategory
|
||||
CategoryId
|
||||
Highlight
|
||||
TrustStatus
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -91,7 +93,8 @@ QtObject:
|
|||
ModelRole.SubItems.int:"subItems",
|
||||
ModelRole.IsCategory.int:"isCategory",
|
||||
ModelRole.CategoryId.int:"categoryId",
|
||||
ModelRole.Highlight.int:"highlight"
|
||||
ModelRole.Highlight.int:"highlight",
|
||||
ModelRole.TrustStatus.int:"trustStatus",
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -145,6 +148,8 @@ QtObject:
|
|||
result = newQVariant(item.categoryId)
|
||||
of ModelRole.Highlight:
|
||||
result = newQVariant(item.highlight)
|
||||
of ModelRole.TrustStatus:
|
||||
result = newQVariant(item.trustStatus.int)
|
||||
|
||||
proc appendItem*(self: Model, item: Item) =
|
||||
let parentModelIndex = newQModelIndex()
|
||||
|
@ -257,14 +262,16 @@ QtObject:
|
|||
if self.items[i].subItems.blockUnblockItemById(id, blocked):
|
||||
return
|
||||
|
||||
proc updateItemDetails*(self: Model, id, name, icon: string) =
|
||||
proc updateItemDetails*(self: Model, id, name, icon: string, trustStatus: TrustStatus) =
|
||||
## This updates only first level items, it doesn't update subitems, since subitems cannot have custom icon.
|
||||
for i in 0 ..< self.items.len:
|
||||
if(self.items[i].id == id):
|
||||
self.items[i].BaseItem.name = name
|
||||
self.items[i].BaseItem.icon = icon
|
||||
self.items[i].BaseItem.trustStatus = trustStatus
|
||||
let index = self.createIndex(i, 0, nil)
|
||||
self.dataChanged(index, index, @[ModelRole.Name.int, ModelRole.Icon.int])
|
||||
self.dataChanged(index, index, @[ModelRole.Name.int, ModelRole.Icon.int,
|
||||
ModelRole.TrustStatus.int])
|
||||
return
|
||||
|
||||
proc renameItem*(self: Model, id: string, name: string) =
|
||||
|
|
|
@ -21,6 +21,7 @@ import ../../../../app_service/service/message/service as message_service
|
|||
import ../../../../app_service/service/mailservers/service as mailservers_service
|
||||
import ../../../../app_service/service/gif/service as gif_service
|
||||
import ../../../../app_service/service/visual_identity/service as visual_identity
|
||||
import ../../../../app_service/service/contacts/dto/contacts as contacts_dto
|
||||
|
||||
export io_interface
|
||||
|
||||
|
@ -210,7 +211,7 @@ proc createItemFromPublicKey(self: Module, publicKey: string): UserItem =
|
|||
isContact = contactDetails.details.isMutualContact(),
|
||||
isVerified = contactDetails.details.isContactVerified(),
|
||||
isUntrustworthy = contactDetails.details.isContactUntrustworthy(),
|
||||
isBlocked = contactDetails.details.isBlocked()
|
||||
isBlocked = contactDetails.details.isBlocked(),
|
||||
)
|
||||
|
||||
proc initContactRequestsModel(self: Module) =
|
||||
|
@ -650,7 +651,8 @@ method onContactDetailsUpdated*(self: Module, publicKey: string) =
|
|||
|
||||
let chatName = contactDetails.displayName
|
||||
let chatImage = contactDetails.icon
|
||||
self.view.chatsModel().updateItemDetails(publicKey, chatName, chatImage)
|
||||
let trustStatus = contactDetails.details.trustStatus
|
||||
self.view.chatsModel().updateItemDetails(publicKey, chatName, chatImage, trustStatus)
|
||||
|
||||
method onNewMessagesReceived*(self: Module, sectionIdMsgBelongsTo: string, chatIdMsgBelongsTo: string,
|
||||
chatTypeMsgBelongsTo: ChatType, unviewedMessagesCount: int, unviewedMentionsCount: int, message: MessageDto) =
|
||||
|
|
|
@ -174,6 +174,18 @@ proc init*(self: Controller) =
|
|||
var args = ContactArgs(e)
|
||||
self.delegate.contactUpdated(args.contactId)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_TRUSTED) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_REMOVED_TRUST_STATUS) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactUpdated(args.publicKey)
|
||||
|
||||
self.events.on(SIGNAL_MNEMONIC_REMOVAL) do(e: Args):
|
||||
self.delegate.mnemonicBackedUp()
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import activity_center/module as activity_center_module
|
|||
import communities/module as communities_module
|
||||
import node_section/module as node_section_module
|
||||
import networks/module as networks_module
|
||||
import ../../../app_service/service/contacts/dto/contacts
|
||||
|
||||
import ../../../app_service/service/keychain/service as keychain_service
|
||||
import ../../../app_service/service/chat/service as chat_service
|
||||
|
@ -692,7 +693,10 @@ method getContactDetailsAsJson*[T](self: Module[T], publicKey: string): string =
|
|||
"isBlocked":contact.blocked,
|
||||
"requestReceived":contact.hasAddedUs,
|
||||
"isSyncing":contact.isSyncing,
|
||||
"removed":contact.removed
|
||||
"removed":contact.removed,
|
||||
"trustStatus": contact.trustStatus.int,
|
||||
"verificationStatus": contact.verificationStatus.int,
|
||||
"hasAddedUs": contact.hasAddedUs
|
||||
}
|
||||
return $jsonObj
|
||||
|
||||
|
@ -736,6 +740,7 @@ method contactUpdated*[T](self: Module[T], publicKey: string) =
|
|||
contactDetails.details.localNickname,
|
||||
contactDetails.details.alias,
|
||||
contactDetails.icon,
|
||||
isUntrustworthy = contactDetails.details.isContactUntrustworthy(),
|
||||
)
|
||||
|
||||
method calculateProfileSectionHasNotification*[T](self: Module[T]): bool =
|
||||
|
|
|
@ -49,10 +49,38 @@ proc init*(self: Controller) =
|
|||
var args = ContactArgs(e)
|
||||
self.delegate.contactNicknameChanged(args.contactId)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UNTRUSTWORTHY) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactTrustStatusChanged(args.publicKey, args.isUntrustworthy)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_TRUSTED) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactTrustStatusChanged(args.publicKey, args.isUntrustworthy)
|
||||
|
||||
self.events.on(SIGNAL_REMOVED_TRUST_STATUS) do(e: Args):
|
||||
var args = TrustArgs(e)
|
||||
self.delegate.contactTrustStatusChanged(args.publicKey, args.isUntrustworthy)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_UPDATED) do(e: Args):
|
||||
var args = ContactArgs(e)
|
||||
self.delegate.contactUpdated(args.contactId)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_VERIFICATION_DECLINED) do(e: Args):
|
||||
var args = ContactArgs(e)
|
||||
self.delegate.onVerificationRequestDeclined(args.contactId)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_VERIFICATION_ADDED) do(e: Args):
|
||||
var args = VerificationRequestArgs(e)
|
||||
self.delegate.onVerificationRequestUpdatedOrAdded(args.verificationRequest)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_VERIFICATION_UPDATED) do(e: Args):
|
||||
var args = VerificationRequestArgs(e)
|
||||
self.delegate.onVerificationRequestUpdatedOrAdded(args.verificationRequest)
|
||||
|
||||
self.events.on(SIGNAL_CONTACT_VERIFICATION_ACCEPTED) do(e: Args):
|
||||
var args = VerificationRequestArgs(e)
|
||||
self.delegate.onVerificationRequestUpdatedOrAdded(args.verificationRequest)
|
||||
|
||||
proc getContacts*(self: Controller, group: ContactsGroup): seq[ContactsDto] =
|
||||
return self.contactsService.getContactsByGroup(group)
|
||||
|
||||
|
@ -88,4 +116,40 @@ proc removeContactRequestRejection*(self: Controller, publicKey: string) =
|
|||
self.contactsService.removeContactRequestRejection(publicKey)
|
||||
|
||||
proc switchToOrCreateOneToOneChat*(self: Controller, chatId: string) =
|
||||
self.chatService.switchToOrCreateOneToOneChat(chatId, "")
|
||||
self.chatService.switchToOrCreateOneToOneChat(chatId, "")
|
||||
|
||||
proc markUntrustworthy*(self: Controller, publicKey: string) =
|
||||
self.contactsService.markUntrustworthy(publicKey)
|
||||
|
||||
proc removeTrustStatus*(self: Controller, publicKey: string) =
|
||||
self.contactsService.removeTrustStatus(publicKey)
|
||||
|
||||
proc getVerificationRequestSentTo*(self: Controller, publicKey: string): VerificationRequest =
|
||||
self.contactsService.getVerificationRequestSentTo(publicKey)
|
||||
|
||||
proc getVerificationRequestFrom*(self: Controller, publicKey: string): VerificationRequest =
|
||||
self.contactsService.getVerificationRequestFrom(publicKey)
|
||||
|
||||
proc sendVerificationRequest*(self: Controller, publicKey: string, challenge: string) =
|
||||
self.contactsService.sendVerificationRequest(publicKey, challenge)
|
||||
|
||||
proc cancelVerificationRequest*(self: Controller, publicKey: string) =
|
||||
self.contactsService.cancelVerificationRequest(publicKey)
|
||||
|
||||
proc verifiedTrusted*(self: Controller, publicKey: string) =
|
||||
self.contactsService.verifiedTrusted(publicKey)
|
||||
|
||||
proc verifiedUntrustworthy*(self: Controller, publicKey: string) =
|
||||
self.contactsService.verifiedUntrustworthy(publicKey)
|
||||
|
||||
proc acceptVerificationRequest*(self: Controller, publicKey: string, response: string) =
|
||||
self.contactsService.acceptVerificationRequest(publicKey, response)
|
||||
|
||||
proc declineVerificationRequest*(self: Controller, publicKey: string) =
|
||||
self.contactsService.declineVerificationRequest(publicKey)
|
||||
|
||||
proc getReceivedVerificationRequests*(self: Controller): seq[VerificationRequest] =
|
||||
self.contactsService.getReceivedVerificationRequests()
|
||||
|
||||
proc hasReceivedVerificationRequestFrom*(self: Controller, fromId: string): bool =
|
||||
self.contactsService.hasReceivedVerificationRequestFrom(fromId)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import NimQml
|
||||
import ../../../../../app_service/service/contacts/dto/contacts as contacts
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
@ -69,8 +70,53 @@ method contactRemoved*(self: AccessInterface, publicKey: string) {.base.} =
|
|||
method contactNicknameChanged*(self: AccessInterface, publicKey: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method contactTrustStatusChanged*(self: AccessInterface, publicKey: string, isUntrustworthy: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method contactUpdated*(self: AccessInterface, publicKey: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method markUntrustworthy*(self: AccessInterface, publicKey: string): void {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method removeTrustStatus*(self: AccessInterface, publicKey: string): void {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getSentVerificationDetailsAsJson*(self: AccessInterface, publicKey: string): string =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getVerificationDetailsFromAsJson*(self: AccessInterface, publicKey: string): string =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method sendVerificationRequest*(self: AccessInterface, publicKey: string, challenge: string) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method cancelVerificationRequest*(self: AccessInterface, publicKey: string) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method verifiedTrusted*(self: AccessInterface, publicKey: string): void {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method verifiedUntrustworthy*(self: AccessInterface, publicKey: string): void {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method declineVerificationRequest*(self: AccessInterface, publicKey: string): void {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method acceptVerificationRequest*(self: AccessInterface, publicKey: string, response: string): void {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method contactRequestRejectionRemoved*(self: AccessInterface, publicKey: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getReceivedVerificationRequests*(self: AccessInterface): seq[VerificationRequest] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method hasReceivedVerificationRequestFrom*(self: AccessInterface, fromId: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onVerificationRequestDeclined*(self: AccessInterface, publicKey: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onVerificationRequestUpdatedOrAdded*(self: AccessInterface, VerificationRequest: VerificationRequest) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
|
@ -1,12 +1,13 @@
|
|||
import NimQml, chronicles
|
||||
|
||||
import io_interface, view, controller
|
||||
import io_interface, view, controller, json
|
||||
import ../../../shared_models/user_item
|
||||
import ../../../shared_models/user_model
|
||||
import ../io_interface as delegate_interface
|
||||
import ../../../../global/global_singleton
|
||||
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/service/contacts/dto/contacts as contacts_dto
|
||||
import ../../../../../app_service/service/contacts/service as contacts_service
|
||||
import ../../../../../app_service/service/chat/service as chat_service
|
||||
|
||||
|
@ -76,6 +77,16 @@ method viewDidLoad*(self: Module) =
|
|||
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
|
||||
# self.buildModel(self.view.receivedButRejectedContactRequestsModel(), ContactsGroup.IncomingRejectedContactRequests)
|
||||
# self.buildModel(self.view.sentButRejectedContactRequestsModel(), ContactsGroup.IncomingRejectedContactRequests)
|
||||
|
||||
let receivedVerificationRequests = self.controller.getReceivedVerificationRequests()
|
||||
var receivedVerificationRequestItems: seq[UserItem] = @[]
|
||||
for receivedVerificationRequest in receivedVerificationRequests:
|
||||
if receivedVerificationRequest.status == VerificationStatus.Verifying or
|
||||
receivedVerificationRequest.status == VerificationStatus.Verified:
|
||||
let contactItem = self.createItemFromPublicKey(receivedVerificationRequest.fromID)
|
||||
contactItem.incomingVerificationStatus = VerificationRequestStatus(receivedVerificationRequest.status)
|
||||
receivedVerificationRequestItems.add(contactItem)
|
||||
self.view.receivedContactRequestsModel().addItems(receivedVerificationRequestItems)
|
||||
|
||||
self.moduleLoaded = true
|
||||
self.delegate.contactsModuleDidLoad()
|
||||
|
@ -172,3 +183,86 @@ method contactNicknameChanged*(self: Module, publicKey: string) =
|
|||
# self.view.receivedButRejectedContactRequestsModel().updateName(publicKey, name)
|
||||
# self.view.sentButRejectedContactRequestsModel().updateName(publicKey, name)
|
||||
self.view.blockedContactsModel().updateName(publicKey, name)
|
||||
|
||||
method contactTrustStatusChanged*(self: Module, publicKey: string, isUntrustworthy: bool) =
|
||||
self.view.myMutualContactsModel().updateTrustStatus(publicKey, isUntrustworthy)
|
||||
self.view.blockedContactsModel().updateTrustStatus(publicKey, isUntrustworthy)
|
||||
|
||||
method markUntrustworthy*(self: Module, publicKey: string): void =
|
||||
self.controller.markUntrustworthy(publicKey)
|
||||
|
||||
method removeTrustStatus*(self: Module, publicKey: string): void =
|
||||
self.controller.removeTrustStatus(publicKey)
|
||||
|
||||
method getSentVerificationDetailsAsJson*(self: Module, publicKey: string): string =
|
||||
let verificationRequest = self.controller.getVerificationRequestSentTo(publicKey)
|
||||
let (name, image, largeImage) = self.controller.getContactNameAndImage(publicKey)
|
||||
let jsonObj = %* {
|
||||
"challenge": verificationRequest.challenge,
|
||||
"response": verificationRequest.response,
|
||||
"requestedAt": verificationRequest.requestedAt,
|
||||
"requestStatus": verificationRequest.status.int,
|
||||
"repliedAt": verificationRequest.repliedAt,
|
||||
"icon": image,
|
||||
"largeImage": largeImage,
|
||||
"displayName": name
|
||||
}
|
||||
return $jsonObj
|
||||
|
||||
method getVerificationDetailsFromAsJson*(self: Module, publicKey: string): string =
|
||||
let verificationRequest = self.controller.getVerificationRequestFrom(publicKey)
|
||||
let (name, image, largeImage) = self.controller.getContactNameAndImage(publicKey)
|
||||
let jsonObj = %* {
|
||||
"from": verificationRequest.fromId,
|
||||
"challenge": verificationRequest.challenge,
|
||||
"response": verificationRequest.response,
|
||||
"requestedAt": verificationRequest.requestedAt,
|
||||
"requestStatus": verificationRequest.status.int,
|
||||
"repliedAt": verificationRequest.repliedAt,
|
||||
"icon": image,
|
||||
"largeImage": largeImage,
|
||||
"displayName": name
|
||||
}
|
||||
return $jsonObj
|
||||
|
||||
method sendVerificationRequest*(self: Module, publicKey: string, challenge: string) =
|
||||
self.controller.sendVerificationRequest(publicKey, challenge)
|
||||
|
||||
method cancelVerificationRequest*(self: Module, publicKey: string) =
|
||||
self.controller.cancelVerificationRequest(publicKey)
|
||||
|
||||
method verifiedTrusted*(self: Module, publicKey: string) =
|
||||
self.controller.verifiedTrusted(publicKey)
|
||||
|
||||
method verifiedUntrustworthy*(self: Module, publicKey: string) =
|
||||
self.controller.verifiedUntrustworthy(publicKey)
|
||||
|
||||
method declineVerificationRequest*(self: Module, publicKey: string) =
|
||||
self.controller.declineVerificationRequest(publicKey)
|
||||
|
||||
method acceptVerificationRequest*(self: Module, publicKey: string, response: string) =
|
||||
self.controller.acceptVerificationRequest(publicKey, response)
|
||||
|
||||
method getReceivedVerificationRequests*(self: Module): seq[VerificationRequest] =
|
||||
self.controller.getReceivedVerificationRequests()
|
||||
|
||||
method hasReceivedVerificationRequestFrom*(self: Module, fromId: string): bool =
|
||||
result = self.controller.hasReceivedVerificationRequestFrom(fromId)
|
||||
|
||||
method onVerificationRequestDeclined*(self: Module, publicKey: string) =
|
||||
self.view.receivedContactRequestsModel.removeItemById(publicKey)
|
||||
|
||||
method onVerificationRequestUpdatedOrAdded*(self: Module, request: VerificationRequest) =
|
||||
let item = self.createItemFromPublicKey(request.fromID)
|
||||
item.incomingVerificationStatus = VerificationRequestStatus(request.status)
|
||||
if (self.view.receivedContactRequestsModel.containsItemWithPubKey(request.fromID)):
|
||||
if request.status != VerificationStatus.Verifying and
|
||||
request.status != VerificationStatus.Verified:
|
||||
self.view.receivedContactRequestsModel.removeItemById(request.fromID)
|
||||
return
|
||||
self.view.receivedContactRequestsModel.updateIncomingRequestStatus(
|
||||
item.pubKey,
|
||||
item.incomingVerificationStatus
|
||||
)
|
||||
return
|
||||
self.view.receivedContactRequestsModel.addItem(item)
|
|
@ -33,8 +33,8 @@ QtObject:
|
|||
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
|
||||
# self.receivedButRejectedContactRequestsModel.delete
|
||||
# self.receivedButRejectedContactRequestsModelVariant.delete
|
||||
# self.sentButRejectedContactRequestsModel.delete
|
||||
# self.sentButRejectedContactRequestsModelVariant.delete
|
||||
# self.sentButRejectedContactRequestsModel.delete
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
|
@ -150,5 +150,37 @@ QtObject:
|
|||
proc removeContact*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.removeContact(publicKey)
|
||||
|
||||
proc markUntrustworthy*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.markUntrustworthy(publicKey)
|
||||
|
||||
proc removeTrustStatus*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.removeTrustStatus(publicKey)
|
||||
|
||||
proc removeContactRequestRejection*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.removeContactRequestRejection(publicKey)
|
||||
self.delegate.removeContactRequestRejection(publicKey)
|
||||
proc getSentVerificationDetailsAsJson(self: View, publicKey: string): string {.slot.} =
|
||||
return self.delegate.getSentVerificationDetailsAsJson(publicKey)
|
||||
|
||||
proc getVerificationDetailsFromAsJson(self: View, publicKey: string): string {.slot.} =
|
||||
return self.delegate.getVerificationDetailsFromAsJson(publicKey)
|
||||
|
||||
proc sendVerificationRequest*(self: View, publicKey: string, challenge: string) {.slot.} =
|
||||
self.delegate.sendVerificationRequest(publicKey, challenge)
|
||||
|
||||
proc cancelVerificationRequest*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.cancelVerificationRequest(publicKey)
|
||||
|
||||
proc verifiedTrusted*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.verifiedTrusted(publicKey)
|
||||
|
||||
proc verifiedUntrustworthy*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.verifiedUntrustworthy(publicKey)
|
||||
|
||||
proc declineVerificationRequest*(self: View, publicKey: string) {.slot.} =
|
||||
self.delegate.declineVerificationRequest(publicKey)
|
||||
|
||||
proc acceptVerificationRequest*(self: View, publicKey: string, response: string) {.slot.} =
|
||||
self.delegate.acceptVerificationRequest(publicKey, response)
|
||||
|
||||
proc hasReceivedVerificationRequestFrom*(self: View, fromId: string): bool {.slot.} =
|
||||
result = self.delegate.hasReceivedVerificationRequestFrom(fromId)
|
|
@ -1,5 +1,6 @@
|
|||
import NimQml
|
||||
import section_item
|
||||
import ../../../app_service/service/contacts/dto/contacts
|
||||
|
||||
QtObject:
|
||||
type ActiveSection* = ref object of QObject
|
||||
|
@ -182,8 +183,8 @@ QtObject:
|
|||
localNickname: string,
|
||||
alias: string,
|
||||
image: string,
|
||||
) =
|
||||
self.item.updateMember(pubkey, name, ensName, localNickname, alias, image)
|
||||
isUntrustworthy: bool) =
|
||||
self.item.updateMember(pubkey, name, ensName, localNickname, alias, image, isUntrustworthy)
|
||||
|
||||
proc pendingRequestsToJoin(self: ActiveSection): QVariant {.slot.} =
|
||||
if (self.item.id == ""):
|
||||
|
|
|
@ -24,8 +24,8 @@ proc initMemberItem*(
|
|||
isUntrustworthy: bool = false,
|
||||
isBlocked: bool = false,
|
||||
contactRequest: ContactRequest = ContactRequest.None,
|
||||
incomingVerification: VerificationRequest = VerificationRequest.None,
|
||||
outcomingVerification: VerificationRequest = VerificationRequest.None,
|
||||
incomingVerificationStatus: VerificationRequestStatus = VerificationRequestStatus.None,
|
||||
outgoingVerificationStatus: VerificationRequestStatus = VerificationRequestStatus.None,
|
||||
isAdmin: bool = false,
|
||||
joined: bool = false,
|
||||
): MemberItem =
|
||||
|
@ -47,8 +47,8 @@ proc initMemberItem*(
|
|||
isUntrustworthy = isUntrustworthy,
|
||||
isBlocked = isBlocked,
|
||||
contactRequest = contactRequest,
|
||||
incomingVerification = incomingVerification,
|
||||
outcomingVerification = outcomingVerification
|
||||
incomingVerificationStatus = incomingVerificationStatus,
|
||||
outgoingVerificationStatus = outgoingVerificationStatus
|
||||
)
|
||||
|
||||
proc `$`*(self: MemberItem): string =
|
||||
|
@ -67,8 +67,8 @@ proc `$`*(self: MemberItem): string =
|
|||
isUntrustworthy: {self.isUntrustworthy},
|
||||
isBlocked: {self.isBlocked},
|
||||
contactRequest: {$self.contactRequest.int},
|
||||
incomingVerification: {$self.incomingVerification.int},
|
||||
outcomingVerification: {$self.outcomingVerification.int},
|
||||
incomingVerificationStatus: {$self.incomingVerificationStatus.int},
|
||||
outgoingVerificationStatus: {$self.outgoingVerificationStatus.int},
|
||||
isAdmin: {self.isAdmin},
|
||||
joined: {self.joined}
|
||||
]"""
|
||||
|
|
|
@ -2,6 +2,7 @@ import NimQml, Tables, strformat, sequtils, sugar
|
|||
|
||||
# TODO: use generics to remove duplication between user_model and member_model
|
||||
|
||||
import ../../../app_service/service/contacts/dto/contacts
|
||||
import member_item
|
||||
|
||||
type
|
||||
|
@ -20,8 +21,8 @@ type
|
|||
IsUntrustworthy
|
||||
IsBlocked
|
||||
ContactRequest
|
||||
IncomingVerification
|
||||
OutcomingVerification
|
||||
IncomingVerificationStatus
|
||||
OutgoingVerificationStatus
|
||||
IsAdmin
|
||||
Joined
|
||||
|
||||
|
@ -81,8 +82,8 @@ QtObject:
|
|||
ModelRole.IsUntrustworthy.int: "isUntrustworthy",
|
||||
ModelRole.IsBlocked.int: "isBlocked",
|
||||
ModelRole.ContactRequest.int: "contactRequest",
|
||||
ModelRole.IncomingVerification.int: "incomingVerification",
|
||||
ModelRole.OutcomingVerification.int: "outcomingVerification",
|
||||
ModelRole.IncomingVerificationStatus.int: "incomingVerificationStatus",
|
||||
ModelRole.OutgoingVerificationStatus.int: "outgoingVerificationStatus",
|
||||
ModelRole.IsAdmin.int: "isAdmin",
|
||||
ModelRole.Joined.int: "joined",
|
||||
}.toTable
|
||||
|
@ -126,10 +127,10 @@ QtObject:
|
|||
result = newQVariant(item.isBlocked)
|
||||
of ModelRole.ContactRequest:
|
||||
result = newQVariant(item.contactRequest.int)
|
||||
of ModelRole.IncomingVerification:
|
||||
result = newQVariant(item.incomingVerification.int)
|
||||
of ModelRole.OutcomingVerification:
|
||||
result = newQVariant(item.outcomingVerification.int)
|
||||
of ModelRole.IncomingVerificationStatus:
|
||||
result = newQVariant(item.incomingVerificationStatus.int)
|
||||
of ModelRole.OutgoingVerificationStatus:
|
||||
result = newQVariant(item.outgoingVerificationStatus.int)
|
||||
of ModelRole.IsAdmin:
|
||||
result = newQVariant(item.isAdmin)
|
||||
of ModelRole.Joined:
|
||||
|
@ -213,7 +214,8 @@ QtObject:
|
|||
icon: string,
|
||||
isContact: bool = false,
|
||||
isAdmin: bool = false,
|
||||
joined: bool = false
|
||||
joined: bool = false,
|
||||
isUntrustworthy: bool = false,
|
||||
) =
|
||||
let ind = self.findIndexForMessageId(pubKey)
|
||||
if(ind == -1):
|
||||
|
@ -227,6 +229,7 @@ QtObject:
|
|||
self.items[ind].isContact = isContact
|
||||
self.items[ind].isAdmin = isAdmin
|
||||
self.items[ind].joined = joined
|
||||
self.items[ind].isUntrustworthy = isUntrustworthy
|
||||
|
||||
let index = self.createIndex(ind, 0, nil)
|
||||
self.dataChanged(index, index, @[
|
||||
|
@ -238,6 +241,7 @@ QtObject:
|
|||
ModelRole.IsContact.int,
|
||||
ModelRole.IsAdmin.int,
|
||||
ModelRole.Joined.int,
|
||||
ModelRole.IsUntrustworthy.int,
|
||||
])
|
||||
|
||||
proc setOnlineStatus*(self: Model, pubKey: string,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import json, strformat
|
||||
import ../../../app_service/common/types
|
||||
import ../../../app_service/service/contacts/dto/contacts
|
||||
|
||||
export types.ContentType
|
||||
import message_reaction_model, message_reaction_item, message_transaction_parameters_item
|
||||
|
@ -35,6 +36,7 @@ type
|
|||
links: seq[string]
|
||||
transactionParameters: TransactionParametersItem
|
||||
mentionedUsersPks: seq[string]
|
||||
senderTrustStatus: TrustStatus
|
||||
|
||||
proc initItem*(
|
||||
id,
|
||||
|
@ -59,6 +61,7 @@ proc initItem*(
|
|||
links: seq[string],
|
||||
transactionParameters: TransactionParametersItem,
|
||||
mentionedUsersPks: seq[string],
|
||||
senderTrustStatus: TrustStatus
|
||||
): Item =
|
||||
result = Item()
|
||||
result.id = id
|
||||
|
@ -89,6 +92,7 @@ proc initItem*(
|
|||
result.mentionedUsersPks = mentionedUsersPks
|
||||
result.gapFrom = 0
|
||||
result.gapTo = 0
|
||||
result.senderTrustStatus = senderTrustStatus
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""Item(
|
||||
|
@ -115,6 +119,7 @@ proc `$`*(self: Item): string =
|
|||
links:{$self.links},
|
||||
transactionParameters:{$self.transactionParameters},
|
||||
mentionedUsersPks:{$self.mentionedUsersPks},
|
||||
senderTrustStatus:{$self.senderTrustStatus},
|
||||
)"""
|
||||
|
||||
proc id*(self: Item): string {.inline.} =
|
||||
|
@ -156,6 +161,12 @@ proc senderIsAdded*(self: Item): bool {.inline.} =
|
|||
proc `senderIsAdded=`*(self: Item, value: bool) {.inline.} =
|
||||
self.senderIsAdded = value
|
||||
|
||||
proc senderTrustStatus*(self: Item): TrustStatus {.inline.} =
|
||||
self.senderTrustStatus
|
||||
|
||||
proc `senderTrustStatus=`*(self: Item, value: TrustStatus) {.inline.} =
|
||||
self.senderTrustStatus = value
|
||||
|
||||
proc outgoingStatus*(self: Item): string {.inline.} =
|
||||
self.outgoingStatus
|
||||
|
||||
|
|
|
@ -34,6 +34,13 @@ QtObject:
|
|||
QtProperty[string] pinnedBy:
|
||||
read = pinnedBy
|
||||
|
||||
proc senderTrustStatus*(self: MessageItem): int {.slot.} =
|
||||
let trustStatus = ?.self.messageItem.senderTrustStatus
|
||||
return trustStatus.int
|
||||
|
||||
QtProperty[int] senderTrustStatus:
|
||||
read = senderTrustStatus
|
||||
|
||||
proc senderDisplayName*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.senderDisplayName
|
||||
QtProperty[string] senderDisplayName:
|
||||
read = senderDisplayName
|
||||
|
|
|
@ -36,6 +36,7 @@ type
|
|||
Links
|
||||
TransactionParameters
|
||||
MentionedUsersPks
|
||||
SenderTrustStatus
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -108,7 +109,8 @@ QtObject:
|
|||
ModelRole.IsEdited.int: "isEdited",
|
||||
ModelRole.Links.int: "links",
|
||||
ModelRole.TransactionParameters.int: "transactionParameters",
|
||||
ModelRole.MentionedUsersPks.int: "mentionedUsersPks"
|
||||
ModelRole.MentionedUsersPks.int: "mentionedUsersPks",
|
||||
ModelRole.SenderTrustStatus.int: "senderTrustStatus"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -136,6 +138,8 @@ QtObject:
|
|||
result = newQVariant(item.senderId)
|
||||
of ModelRole.SenderDisplayName:
|
||||
result = newQVariant(item.senderDisplayName)
|
||||
of ModelRole.SenderTrustStatus:
|
||||
result = newQVariant(item.senderTrustStatus.int)
|
||||
of ModelRole.SenderLocalName:
|
||||
result = newQVariant(item.senderLocalName)
|
||||
of ModelRole.SenderIcon:
|
||||
|
@ -365,7 +369,8 @@ QtObject:
|
|||
|
||||
var roles: seq[int]
|
||||
if(self.items[i].senderId == contactId):
|
||||
roles = @[ModelRole.SenderDisplayName.int, ModelRole.SenderLocalName.int, ModelRole.SenderIcon.int, ModelRole.SenderIsAdded.int]
|
||||
roles = @[ModelRole.SenderDisplayName.int, ModelRole.SenderLocalName.int,
|
||||
ModelRole.SenderIcon.int, ModelRole.SenderIsAdded.int, ModelRole.SenderTrustStatus.int]
|
||||
if(self.items[i].pinnedBy == contactId):
|
||||
roles.add(ModelRole.PinnedBy.int)
|
||||
if(self.items[i].messageContainsMentions):
|
||||
|
|
|
@ -238,8 +238,9 @@ proc updateMember*(
|
|||
ensName: string,
|
||||
nickname: string,
|
||||
alias: string,
|
||||
image: string) =
|
||||
self.membersModel.updateItem(pubkey, name, ensName, nickname, alias, image)
|
||||
image: string,
|
||||
isUntrustworthy: bool) =
|
||||
self.membersModel.updateItem(pubkey, name, ensName, nickname, alias, image, isUntrustworthy)
|
||||
|
||||
proc pendingRequestsToJoin*(self: SectionItem): PendingRequestModel {.inline.} =
|
||||
self.pendingRequestsToJoinModel
|
||||
|
|
|
@ -10,13 +10,16 @@ type
|
|||
None = 0
|
||||
IncomingPending
|
||||
IncomingRejected
|
||||
OutcomingPending
|
||||
OutcomingRejected
|
||||
OutgoingPending
|
||||
OutgoingRejected
|
||||
|
||||
VerificationRequest* {.pure.} = enum
|
||||
VerificationRequestStatus* {.pure.} = enum
|
||||
None = 0
|
||||
Pending
|
||||
Answered
|
||||
Declined
|
||||
Canceled
|
||||
Trusted
|
||||
|
||||
type
|
||||
UserItem* = ref object of RootObj
|
||||
|
@ -34,8 +37,8 @@ type
|
|||
isUntrustworthy: bool
|
||||
isBlocked: bool
|
||||
contactRequest: ContactRequest
|
||||
incomingVerification: VerificationRequest
|
||||
outcomingVerification: VerificationRequest
|
||||
incomingVerificationStatus: VerificationRequestStatus
|
||||
outgoingVerificationStatus: VerificationRequestStatus
|
||||
|
||||
proc setup*(self: UserItem,
|
||||
pubKey: string,
|
||||
|
@ -52,8 +55,9 @@ proc setup*(self: UserItem,
|
|||
isUntrustworthy: bool,
|
||||
isBlocked: bool,
|
||||
contactRequest: ContactRequest,
|
||||
incomingVerification: VerificationRequest,
|
||||
outcomingVerification: VerificationRequest) =
|
||||
incomingVerificationStatus: VerificationRequestStatus,
|
||||
outgoingVerificationStatus: VerificationRequestStatus,
|
||||
) =
|
||||
self.pubKey = pubKey
|
||||
self.displayName = displayName
|
||||
self.ensName = ensName
|
||||
|
@ -68,28 +72,28 @@ proc setup*(self: UserItem,
|
|||
self.isUntrustworthy = isUntrustworthy
|
||||
self.isBlocked = isBlocked
|
||||
self.contactRequest = contactRequest
|
||||
self.incomingVerification = incomingVerification
|
||||
self.outcomingVerification = outcomingVerification
|
||||
self.incomingVerificationStatus = incomingVerificationStatus
|
||||
self.outgoingVerificationStatus = outgoingVerificationStatus
|
||||
|
||||
# FIXME: remove defaults
|
||||
proc initUserItem*(
|
||||
pubKey: string,
|
||||
displayName: string,
|
||||
ensName: string = "",
|
||||
localNickname: string = "",
|
||||
alias: string = "",
|
||||
icon: string,
|
||||
colorId: int = 0,
|
||||
colorHash: string = "",
|
||||
onlineStatus: OnlineStatus = OnlineStatus.Inactive,
|
||||
isContact: bool,
|
||||
isVerified: bool,
|
||||
isUntrustworthy: bool,
|
||||
isBlocked: bool,
|
||||
contactRequest: ContactRequest = ContactRequest.None,
|
||||
incomingVerification: VerificationRequest = VerificationRequest.None,
|
||||
outcomingVerification: VerificationRequest = VerificationRequest.None
|
||||
): UserItem =
|
||||
pubKey: string,
|
||||
displayName: string,
|
||||
ensName: string = "",
|
||||
localNickname: string = "",
|
||||
alias: string = "",
|
||||
icon: string,
|
||||
colorId: int = 0,
|
||||
colorHash: string = "",
|
||||
onlineStatus: OnlineStatus = OnlineStatus.Inactive,
|
||||
isContact: bool,
|
||||
isVerified: bool,
|
||||
isUntrustworthy: bool,
|
||||
isBlocked: bool,
|
||||
contactRequest: ContactRequest = ContactRequest.None,
|
||||
incomingVerificationStatus: VerificationRequestStatus = VerificationRequestStatus.None,
|
||||
outgoingVerificationStatus: VerificationRequestStatus = VerificationRequestStatus.None,
|
||||
): UserItem =
|
||||
result = UserItem()
|
||||
result.setup(
|
||||
pubKey = pubKey,
|
||||
|
@ -106,8 +110,8 @@ proc initUserItem*(
|
|||
isUntrustworthy = isUntrustworthy,
|
||||
isBlocked = isBlocked,
|
||||
contactRequest = contactRequest,
|
||||
incomingVerification = incomingVerification,
|
||||
outcomingVerification = outcomingVerification)
|
||||
incomingVerificationStatus = incomingVerificationStatus,
|
||||
outgoingVerificationStatus = outgoingVerificationStatus)
|
||||
|
||||
proc toOnlineStatus*(statusType: StatusType): OnlineStatus =
|
||||
if(statusType == StatusType.AlwaysOnline or statusType == StatusType.Automatic):
|
||||
|
@ -131,8 +135,8 @@ proc `$`*(self: UserItem): string =
|
|||
isUntrustworthy: {self.isUntrustworthy},
|
||||
isBlocked: {self.isBlocked},
|
||||
contactRequest: {$self.contactRequest.int},
|
||||
incomingVerification: {$self.incomingVerification.int},
|
||||
outcomingVerification: {$self.outcomingVerification.int},
|
||||
incomingVerificationStatus: {$self.incomingVerificationStatus.int},
|
||||
outgoingVerificationStatus: {$self.outgoingVerificationStatus.int},
|
||||
]"""
|
||||
|
||||
proc pubKey*(self: UserItem): string {.inline.} =
|
||||
|
@ -216,14 +220,14 @@ proc contactRequest*(self: UserItem): ContactRequest {.inline.} =
|
|||
proc `contactRequest=`*(self: UserItem, value: ContactRequest) {.inline.} =
|
||||
self.contactRequest = value
|
||||
|
||||
proc incomingVerification*(self: UserItem): VerificationRequest {.inline.} =
|
||||
self.incomingVerification
|
||||
proc incomingVerificationStatus*(self: UserItem): VerificationRequestStatus {.inline.} =
|
||||
self.incomingVerificationStatus
|
||||
|
||||
proc `incomingVerification=`*(self: UserItem, value: VerificationRequest) {.inline.} =
|
||||
self.incomingVerification = value
|
||||
proc `incomingVerificationStatus=`*(self: UserItem, value: VerificationRequestStatus) {.inline.} =
|
||||
self.incomingVerificationStatus = value
|
||||
|
||||
proc outcomingVerification*(self: UserItem): VerificationRequest {.inline.} =
|
||||
self.outcomingVerification
|
||||
proc outgoingVerificationStatus*(self: UserItem): VerificationRequestStatus {.inline.} =
|
||||
self.outgoingVerificationStatus
|
||||
|
||||
proc `outcomingVerification=`*(self: UserItem, value: VerificationRequest) {.inline.} =
|
||||
self.outcomingVerification = value
|
||||
proc `outgoingVerificationStatus=`*(self: UserItem, value: VerificationRequestStatus) {.inline.} =
|
||||
self.outgoingVerificationStatus = value
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import NimQml, Tables, strformat, sequtils, sugar
|
||||
|
||||
import user_item
|
||||
|
||||
type
|
||||
|
@ -18,8 +17,8 @@ type
|
|||
IsUntrustworthy
|
||||
IsBlocked
|
||||
ContactRequest
|
||||
IncomingVerification
|
||||
OutcomingVerification
|
||||
IncomingVerificationStatus
|
||||
OutgoingVerificationStatus
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -75,8 +74,8 @@ QtObject:
|
|||
ModelRole.IsUntrustworthy.int: "isUntrustworthy",
|
||||
ModelRole.IsBlocked.int: "isBlocked",
|
||||
ModelRole.ContactRequest.int: "contactRequest",
|
||||
ModelRole.IncomingVerification.int: "incomingVerification",
|
||||
ModelRole.OutcomingVerification.int: "outcomingVerification",
|
||||
ModelRole.IncomingVerificationStatus.int: "incomingVerificationStatus",
|
||||
ModelRole.OutgoingVerificationStatus.int: "outgoingVerificationStatus",
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -118,10 +117,10 @@ QtObject:
|
|||
result = newQVariant(item.isBlocked)
|
||||
of ModelRole.ContactRequest:
|
||||
result = newQVariant(item.contactRequest.int)
|
||||
of ModelRole.IncomingVerification:
|
||||
result = newQVariant(item.incomingVerification.int)
|
||||
of ModelRole.OutcomingVerification:
|
||||
result = newQVariant(item.outcomingVerification.int)
|
||||
of ModelRole.IncomingVerificationStatus:
|
||||
result = newQVariant(item.incomingVerificationStatus.int)
|
||||
of ModelRole.OutgoingVerificationStatus:
|
||||
result = newQVariant(item.outgoingVerificationStatus.int)
|
||||
|
||||
proc addItems*(self: Model, items: seq[UserItem]) =
|
||||
if(items.len == 0):
|
||||
|
@ -163,8 +162,7 @@ QtObject:
|
|||
self.items = @[]
|
||||
self.endResetModel()
|
||||
|
||||
# TODO: rename to `findIndexForMessagePubkey`
|
||||
proc findIndexForMessageId(self: Model, pubKey: string): int =
|
||||
proc findIndexByPubKey(self: Model, pubKey: string): int =
|
||||
for i in 0 ..< self.items.len:
|
||||
if(self.items[i].pubKey == pubKey):
|
||||
return i
|
||||
|
@ -182,11 +180,11 @@ QtObject:
|
|||
|
||||
# TODO: rename to `containsItem`
|
||||
proc isContactWithIdAdded*(self: Model, id: string): bool =
|
||||
return self.findIndexForMessageId(id) != -1
|
||||
return self.findIndexByPubKey(id) != -1
|
||||
|
||||
proc setName*(self: Model, pubKey: string, displayName: string,
|
||||
ensName: string, localNickname: string) =
|
||||
let ind = self.findIndexForMessageId(pubKey)
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
|
@ -202,7 +200,7 @@ QtObject:
|
|||
])
|
||||
|
||||
proc setIcon*(self: Model, pubKey: string, icon: string) =
|
||||
let ind = self.findIndexForMessageId(pubKey)
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
|
@ -218,9 +216,10 @@ QtObject:
|
|||
ensName: string,
|
||||
localNickname: string,
|
||||
alias: string,
|
||||
icon: string
|
||||
icon: string,
|
||||
isUntrustworthy: bool = false,
|
||||
) =
|
||||
let ind = self.findIndexForMessageId(pubKey)
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
|
@ -228,7 +227,7 @@ QtObject:
|
|||
self.items[ind].ensName = ensName
|
||||
self.items[ind].localNickname = localNickname
|
||||
self.items[ind].alias = alias
|
||||
self.items[ind].icon = icon
|
||||
self.items[ind].isUntrustworthy = isUntrustworthy
|
||||
|
||||
let index = self.createIndex(ind, 0, nil)
|
||||
self.dataChanged(index, index, @[
|
||||
|
@ -237,6 +236,7 @@ QtObject:
|
|||
ModelRole.LocalNickname.int,
|
||||
ModelRole.Alias.int,
|
||||
ModelRole.Icon.int,
|
||||
ModelRole.IsUntrustworthy.int,
|
||||
])
|
||||
|
||||
proc updateName*(
|
||||
|
@ -244,7 +244,7 @@ QtObject:
|
|||
pubKey: string,
|
||||
displayName: string
|
||||
) =
|
||||
let ind = self.findIndexForMessageId(pubKey)
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
|
@ -254,10 +254,36 @@ QtObject:
|
|||
self.dataChanged(index, index, @[
|
||||
ModelRole.DisplayName.int
|
||||
])
|
||||
|
||||
proc updateIncomingRequestStatus*(
|
||||
self: Model,
|
||||
pubKey: string,
|
||||
requestStatus: VerificationRequestStatus
|
||||
) =
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
self.items[ind].incomingVerificationStatus = requestStatus
|
||||
|
||||
let index = self.createIndex(ind, 0, nil)
|
||||
self.dataChanged(index, index, @[
|
||||
ModelRole.IncomingVerificationStatus.int
|
||||
])
|
||||
|
||||
proc updateTrustStatus*(self: Model, pubKey: string, isUntrustworthy: bool) =
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
let first = self.createIndex(ind, 0, nil)
|
||||
let last = self.createIndex(ind, 0, nil)
|
||||
self.items[ind].isUntrustworthy = isUntrustworthy
|
||||
self.dataChanged(first, last, @[ModelRole.IsUntrustworthy.int])
|
||||
|
||||
proc setOnlineStatus*(self: Model, pubKey: string,
|
||||
onlineStatus: OnlineStatus) =
|
||||
let ind = self.findIndexForMessageId(pubKey)
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
|
@ -271,7 +297,7 @@ QtObject:
|
|||
|
||||
# TODO: rename me to removeItemByPubkey
|
||||
proc removeItemById*(self: Model, pubKey: string) =
|
||||
let ind = self.findIndexForMessageId(pubKey)
|
||||
let ind = self.findIndexByPubKey(pubKey)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
|
@ -280,3 +306,6 @@ QtObject:
|
|||
# TODO: rename me to getItemsAsPubkeys
|
||||
proc getItemIds*(self: Model): seq[string] =
|
||||
return self.items.map(i => i.pubKey)
|
||||
|
||||
proc containsItemWithPubKey*(self: Model, pubKey: string): bool =
|
||||
return self.findIndexByPubKey(pubKey) != -1
|
|
@ -10,6 +10,28 @@ type
|
|||
thumbnail*: string
|
||||
large*: string
|
||||
|
||||
type TrustStatus* {.pure.}= enum
|
||||
Unknown = 0,
|
||||
Trusted = 1,
|
||||
Untrustworthy = 2
|
||||
|
||||
type VerificationStatus* {.pure.}= enum
|
||||
Unverified = 0
|
||||
Verifying = 1
|
||||
Verified = 2
|
||||
Declined = 3
|
||||
Canceled = 4
|
||||
Trusted = 5
|
||||
|
||||
type VerificationRequest* = object
|
||||
fromID*: string
|
||||
toID*: string
|
||||
challenge*: string
|
||||
requestedAt*: int64
|
||||
response*: string
|
||||
repliedAt*: int64
|
||||
status*: VerificationStatus
|
||||
|
||||
type ContactsDto* = object
|
||||
id*: string
|
||||
name*: string
|
||||
|
@ -25,6 +47,8 @@ type ContactsDto* = object
|
|||
hasAddedUs*: bool
|
||||
isSyncing*: bool
|
||||
removed*: bool
|
||||
trustStatus*: TrustStatus
|
||||
verificationStatus*: VerificationStatus
|
||||
|
||||
proc `$`(self: Images): string =
|
||||
result = fmt"""Images(
|
||||
|
@ -45,11 +69,13 @@ proc `$`*(self: ContactsDto): string =
|
|||
image:[
|
||||
{$self.image}
|
||||
],
|
||||
added:{self.added}
|
||||
blocked:{self.blocked}
|
||||
hasAddedUs:{self.hasAddedUs}
|
||||
isSyncing:{self.isSyncing}
|
||||
removed:{self.removed}
|
||||
added:{self.added},
|
||||
blocked:{self.blocked},
|
||||
hasAddedUs:{self.hasAddedUs},
|
||||
isSyncing:{self.isSyncing},
|
||||
removed:{self.removed},
|
||||
trustStatus:{self.trustStatus},
|
||||
verificationStatus:{self.verificationStatus},
|
||||
)"""
|
||||
|
||||
proc toImages(jsonObj: JsonNode): Images =
|
||||
|
@ -63,6 +89,28 @@ proc toImages(jsonObj: JsonNode): Images =
|
|||
if(jsonObj.getProp("thumbnail", thumbnailObj)):
|
||||
discard thumbnailObj.getProp("uri", result.thumbnail)
|
||||
|
||||
proc toTrustStatus*(value: int): TrustStatus =
|
||||
result = TrustStatus.Unknown
|
||||
if value >= ord(low(TrustStatus)) or value <= ord(high(TrustStatus)):
|
||||
result = TrustStatus(value)
|
||||
|
||||
proc toVerificationStatus*(value: int): VerificationStatus =
|
||||
result = VerificationStatus.Unverified
|
||||
if value >= ord(low(VerificationStatus)) or value <= ord(high(VerificationStatus)):
|
||||
result = VerificationStatus(value)
|
||||
|
||||
proc toVerificationRequest*(jsonObj: JsonNode): VerificationRequest =
|
||||
result = VerificationRequest()
|
||||
discard jsonObj.getProp("from", result.fromID)
|
||||
discard jsonObj.getProp("to", result.toID)
|
||||
discard jsonObj.getProp("challenge", result.challenge)
|
||||
discard jsonObj.getProp("response", result.response)
|
||||
discard jsonObj.getProp("requested_at", result.requestedAt)
|
||||
discard jsonObj.getProp("replied_at", result.repliedAt)
|
||||
var verificationStatusInt: int
|
||||
discard jsonObj.getProp("verification_status", verificationStatusInt)
|
||||
result.status = verificationStatusInt.toVerificationStatus()
|
||||
|
||||
proc toContactsDto*(jsonObj: JsonNode): ContactsDto =
|
||||
result = ContactsDto()
|
||||
discard jsonObj.getProp("id", result.id)
|
||||
|
@ -73,6 +121,15 @@ proc toContactsDto*(jsonObj: JsonNode): ContactsDto =
|
|||
discard jsonObj.getProp("lastUpdated", result.lastUpdated)
|
||||
discard jsonObj.getProp("lastUpdatedLocally", result.lastUpdatedLocally)
|
||||
discard jsonObj.getProp("localNickname", result.localNickname)
|
||||
|
||||
result.trustStatus = TrustStatus.Unknown
|
||||
var trustStatusInt: int
|
||||
discard jsonObj.getProp("trustStatus", trustStatusInt)
|
||||
result.trustStatus = trustStatusInt.toTrustStatus()
|
||||
|
||||
var verificationStatusInt: int
|
||||
discard jsonObj.getProp("verificationStatus", verificationStatusInt)
|
||||
result.verificationStatus = verificationStatusInt.toVerificationStatus()
|
||||
|
||||
var imageObj: JsonNode
|
||||
if(jsonObj.getProp("images", imageObj)):
|
||||
|
@ -122,13 +179,14 @@ proc isMutualContact*(self: ContactsDto): bool =
|
|||
# But for now we consider that contact is mutual contact if I added him and he added me.
|
||||
return self.hasAddedUs and self.added and not self.removed and not self.blocked
|
||||
|
||||
proc trustStatus*(self: ContactsDto): TrustStatus =
|
||||
result = self.trustStatus
|
||||
|
||||
proc isContactVerified*(self: ContactsDto): bool =
|
||||
# TODO not implemented in `status-go` yet
|
||||
return false
|
||||
return self.verificationStatus == VerificationStatus.Verified
|
||||
|
||||
proc isContactUntrustworthy*(self: ContactsDto): bool =
|
||||
# TODO not implemented in `status-go` yet
|
||||
return false
|
||||
return self.trustStatus == TrustStatus.Untrustworthy
|
||||
|
||||
proc isContactMarked*(self: ContactsDto): bool =
|
||||
return self.isContactVerified() or self.isContactUntrustworthy()
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, Tables, json, sequtils, strformat, chronicles, strutils, times, sugar
|
||||
import NimQml, Tables, json, sequtils, strformat, chronicles, strutils, times, sugar, std/times
|
||||
|
||||
import ../../../app/global/global_singleton
|
||||
import ../../../app/core/signals/types
|
||||
|
@ -27,6 +27,10 @@ type
|
|||
ContactArgs* = ref object of Args
|
||||
contactId*: string
|
||||
|
||||
TrustArgs* = ref object of Args
|
||||
publicKey*: string
|
||||
isUntrustworthy*: bool
|
||||
|
||||
ResolvedContactArgs* = ref object of Args
|
||||
pubkey*: string
|
||||
address*: string
|
||||
|
@ -36,6 +40,9 @@ type
|
|||
ContactsStatusUpdatedArgs* = ref object of Args
|
||||
statusUpdates*: seq[StatusUpdateDto]
|
||||
|
||||
VerificationRequestArgs* = ref object of Args
|
||||
verificationRequest*: VerificationRequest
|
||||
|
||||
# Local Constants:
|
||||
const CheckStatusIntervalInMilliseconds = 5000 # 5 seconds, this is timeout how often do we check for user status.
|
||||
const FiveMinsOnlineLimitInSeconds = int(5 * 60) # 5 minutes
|
||||
|
@ -52,6 +59,16 @@ const SIGNAL_CONTACT_NICKNAME_CHANGED* = "contactNicknameChanged"
|
|||
const SIGNAL_CONTACTS_STATUS_UPDATED* = "contactsStatusUpdated"
|
||||
const SIGNAL_CONTACT_UPDATED* = "contactUpdated"
|
||||
const SIGNAL_LOGGEDIN_USER_IMAGE_CHANGED* = "loggedInUserImageChanged"
|
||||
const SIGNAL_REMOVED_TRUST_STATUS* = "removedTrustStatus"
|
||||
const SIGNAL_CONTACT_UNTRUSTWORTHY* = "contactUntrustworthy"
|
||||
const SIGNAL_CONTACT_TRUSTED* = "contactTrusted"
|
||||
const SIGNAL_CONTACT_VERIFIED* = "contactVerified"
|
||||
const SIGNAL_CONTACT_VERIFICATION_SENT* = "contactVerificationRequestSent"
|
||||
const SIGNAL_CONTACT_VERIFICATION_CANCELLED* = "contactVerificationRequestCancelled"
|
||||
const SIGNAL_CONTACT_VERIFICATION_DECLINED* = "contactVerificationRequestDeclined"
|
||||
const SIGNAL_CONTACT_VERIFICATION_ACCEPTED* = "contactVerificationRequestAccepted"
|
||||
const SIGNAL_CONTACT_VERIFICATION_ADDED* = "contactVerificationRequestAdded"
|
||||
const SIGNAL_CONTACT_VERIFICATION_UPDATED* = "contactVerificationRequestUpdated"
|
||||
|
||||
type
|
||||
ContactsGroup* {.pure.} = enum
|
||||
|
@ -69,6 +86,7 @@ QtObject:
|
|||
networkService: network_service.Service
|
||||
contacts: Table[string, ContactsDto] # [contact_id, ContactsDto]
|
||||
contactsStatus: Table[string, StatusUpdateDto] # [contact_id, StatusUpdateDto]
|
||||
receivedIdentityRequests: Table[string, VerificationRequest] # [from_id, VerificationRequest]
|
||||
events: EventEmitter
|
||||
closingApp: bool
|
||||
imageServerUrl: string
|
||||
|
@ -77,11 +95,13 @@ QtObject:
|
|||
proc getContactById*(self: Service, id: string): ContactsDto
|
||||
proc saveContact(self: Service, contact: ContactsDto)
|
||||
proc startCheckingContactStatuses(self: Service)
|
||||
proc fetchReceivedVerificationRequests*(self: Service) : seq[VerificationRequest]
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.closingApp = true
|
||||
self.contacts.clear
|
||||
self.contactsStatus.clear
|
||||
self.receivedIdentityRequests.clear
|
||||
self.QObject.delete
|
||||
|
||||
proc newService*(
|
||||
|
@ -96,6 +116,8 @@ QtObject:
|
|||
result.networkService = networkService
|
||||
result.threadpool = threadpool
|
||||
result.contacts = initTable[string, ContactsDto]()
|
||||
result.contactsStatus = initTable[string, StatusUpdateDto]()
|
||||
result.receivedIdentityRequests = initTable[string, VerificationRequest]()
|
||||
|
||||
proc addContact(self: Service, contact: ContactsDto) =
|
||||
# Private proc, used for adding contacts only.
|
||||
|
@ -111,9 +133,13 @@ QtObject:
|
|||
for contact in contacts:
|
||||
self.addContact(contact)
|
||||
|
||||
# Identity verifications
|
||||
for request in self.fetchReceivedVerificationRequests():
|
||||
self.receivedIdentityRequests[request.fromId] = request
|
||||
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error: ", errDesription
|
||||
error "error fetching contacts: ", errDesription
|
||||
return
|
||||
|
||||
proc doConnect(self: Service) =
|
||||
|
@ -140,6 +166,31 @@ QtObject:
|
|||
let data = ContactArgs(contactId: c.id)
|
||||
self.events.emit(SIGNAL_CONTACT_UPDATED, data)
|
||||
|
||||
let myPubKey = singletonInstance.userProfile.getPubKey()
|
||||
if(receivedData.verificationRequests.len > 0):
|
||||
for request in receivedData.verificationRequests:
|
||||
if request.fromId == myPubKey:
|
||||
# TODO handle reacting to my own request later
|
||||
continue
|
||||
|
||||
let data = VerificationRequestArgs(verificationRequest: request)
|
||||
let alreadyContains = self.receivedIdentityRequests.contains(request.fromId)
|
||||
self.receivedIdentityRequests[request.fromId] = request
|
||||
|
||||
if alreadyContains:
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFICATION_UPDATED, data)
|
||||
|
||||
if request.status == VerificationStatus.Trusted:
|
||||
if self.contacts.hasKey(request.fromId):
|
||||
self.contacts[request.fromId].trustStatus = TrustStatus.Trusted
|
||||
self.contacts[request.fromId].verificationStatus = VerificationStatus.Trusted
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_TRUSTED,
|
||||
TrustArgs(publicKey: request.fromId, isUntrustworthy: false))
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFIED, ContactArgs(contactId: request.fromId))
|
||||
else:
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFICATION_ADDED, data)
|
||||
|
||||
proc setImageServerUrl(self: Service) =
|
||||
try:
|
||||
let response = status_contacts.getImageServerURL()
|
||||
|
@ -222,6 +273,15 @@ QtObject:
|
|||
return
|
||||
return status_accounts.generateAlias(publicKey).result.getStr
|
||||
|
||||
proc getTrustStatus*(self: Service, publicKey: string): TrustStatus =
|
||||
try:
|
||||
let t = status_contacts.getTrustStatus(publicKey).result.getInt
|
||||
return t.toTrustStatus()
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error: ", errDesription
|
||||
return TrustStatus.Unknown
|
||||
|
||||
proc getContactById*(self: Service, id: string): ContactsDto =
|
||||
if(id == singletonInstance.userProfile.getPubKey()):
|
||||
# If we try to get the contact details of ourselves, just return our own info
|
||||
|
@ -235,7 +295,8 @@ QtObject:
|
|||
image: Images(
|
||||
thumbnail: singletonInstance.userProfile.getThumbnailImage(),
|
||||
large: singletonInstance.userProfile.getLargeImage()
|
||||
)
|
||||
),
|
||||
trustStatus: TrustStatus.Trusted
|
||||
)
|
||||
|
||||
## Returns contact details based on passed id (public key)
|
||||
|
@ -256,13 +317,15 @@ QtObject:
|
|||
return
|
||||
|
||||
let alias = self.generateAlias(id)
|
||||
let trustStatus = self.getTrustStatus(id)
|
||||
result = ContactsDto(
|
||||
id: id,
|
||||
alias: alias,
|
||||
ensVerified: false,
|
||||
added: false,
|
||||
blocked: false,
|
||||
hasAddedUs: false
|
||||
hasAddedUs: false,
|
||||
trustStatus: trustStatus
|
||||
)
|
||||
self.addContact(result)
|
||||
|
||||
|
@ -390,6 +453,7 @@ QtObject:
|
|||
proc removeContact*(self: Service, publicKey: string) =
|
||||
var contact = self.getContactById(publicKey)
|
||||
contact.removed = true
|
||||
contact.added = false
|
||||
|
||||
let response = status_contacts.removeContact(contact.id)
|
||||
if(not response.error.isNil):
|
||||
|
@ -465,3 +529,164 @@ QtObject:
|
|||
result.icon = icon
|
||||
result.isCurrentUser = pubKey == singletonInstance.userProfile.getPubKey()
|
||||
result.details = self.getContactById(pubKey)
|
||||
|
||||
proc markUntrustworthy*(self: Service, publicKey: string) =
|
||||
let response = status_contacts.markUntrustworthy(publicKey)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
error "error marking as untrustworthy ", msg
|
||||
return
|
||||
|
||||
if self.contacts.hasKey(publicKey):
|
||||
self.contacts[publicKey].trustStatus = TrustStatus.Untrustworthy
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_UNTRUSTWORTHY,
|
||||
TrustArgs(publicKey: publicKey, isUntrustworthy: true))
|
||||
|
||||
proc verifiedTrusted*(self: Service, publicKey: string) =
|
||||
let response = status_contacts.verifiedTrusted(publicKey)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
error "error confirming identity ", msg
|
||||
return
|
||||
|
||||
if self.contacts.hasKey(publicKey):
|
||||
self.contacts[publicKey].trustStatus = TrustStatus.Trusted
|
||||
self.contacts[publicKey].verificationStatus = VerificationStatus.Trusted
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_TRUSTED,
|
||||
TrustArgs(publicKey: publicKey, isUntrustworthy: false))
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFIED, ContactArgs(contactId: publicKey))
|
||||
|
||||
proc verifiedUntrustworthy*(self: Service, publicKey: string) =
|
||||
let response = status_contacts.verifiedUntrustworthy(publicKey)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
error "error confirming identity ", msg
|
||||
return
|
||||
|
||||
if self.contacts.hasKey(publicKey):
|
||||
self.contacts[publicKey].trustStatus = TrustStatus.Untrustworthy
|
||||
self.contacts[publicKey].verificationStatus = VerificationStatus.Verified
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_UNTRUSTWORTHY,
|
||||
TrustArgs(publicKey: publicKey, isUntrustworthy: true))
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFIED, ContactArgs(contactId: publicKey))
|
||||
|
||||
proc removeTrustStatus*(self: Service, publicKey: string) =
|
||||
let response = status_contacts.removeTrustStatus(publicKey)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
error "error removing trust status", msg
|
||||
return
|
||||
|
||||
if self.contacts.hasKey(publicKey):
|
||||
self.contacts[publicKey].trustStatus = TrustStatus.Unknown
|
||||
if self.contacts[publicKey].verificationStatus == VerificationStatus.Verified:
|
||||
self.contacts[publicKey].verificationStatus = VerificationStatus.Unverified
|
||||
|
||||
self.events.emit(SIGNAL_REMOVED_TRUST_STATUS,
|
||||
TrustArgs(publicKey: publicKey, isUntrustworthy: false))
|
||||
|
||||
proc getVerificationRequestSentTo*(self: Service, publicKey: string): VerificationRequest =
|
||||
try:
|
||||
let response = status_contacts.getVerificationRequestSentTo(publicKey)
|
||||
return response.result.toVerificationRequest()
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error obtaining verification request", errDesription
|
||||
return
|
||||
|
||||
proc getVerificationRequestFrom*(self: Service, publicKey: string): VerificationRequest =
|
||||
try:
|
||||
if (self.receivedIdentityRequests.contains(publicKey)):
|
||||
return self.receivedIdentityRequests[publicKey]
|
||||
|
||||
let response = status_contacts.getVerificationRequestFrom(publicKey)
|
||||
result = response.result.toVerificationRequest()
|
||||
self.receivedIdentityRequests[publicKey] = result
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error obtaining verification request", errDesription
|
||||
|
||||
proc fetchReceivedVerificationRequests*(self: Service): seq[VerificationRequest] =
|
||||
try:
|
||||
let response = status_contacts.getReceivedVerificationRequests()
|
||||
|
||||
for request in response.result:
|
||||
result.add(request.toVerificationRequest())
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error obtaining verification requests", errDesription
|
||||
|
||||
proc getReceivedVerificationRequests*(self: Service): seq[VerificationRequest] =
|
||||
result = toSeq(self.receivedIdentityRequests.values)
|
||||
|
||||
proc hasReceivedVerificationRequestFrom*(self: Service, fromId: string): bool =
|
||||
result = self.receivedIdentityRequests.contains(fromId)
|
||||
|
||||
proc sendVerificationRequest*(self: Service, publicKey: string, challenge: string) =
|
||||
try:
|
||||
let response = status_contacts.sendVerificationRequest(publicKey, challenge)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
error "error sending contact verification request", msg
|
||||
return
|
||||
|
||||
var contact = self.getContactById(publicKey)
|
||||
contact.verificationStatus = VerificationStatus.Verifying
|
||||
self.saveContact(contact)
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFICATION_SENT, ContactArgs(contactId: publicKey))
|
||||
except Exception as e:
|
||||
error "Error sending verification request", msg = e.msg
|
||||
|
||||
proc cancelVerificationRequest*(self: Service, publicKey: string) =
|
||||
try:
|
||||
let response = status_contacts.cancelVerificationRequest(publicKey)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
error "error sending contact verification request", msg
|
||||
return
|
||||
|
||||
var contact = self.getContactById(publicKey)
|
||||
contact.verificationStatus = VerificationStatus.Unverified
|
||||
self.saveContact(contact)
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFICATION_CANCELLED, ContactArgs(contactId: publicKey))
|
||||
except Exception as e:
|
||||
error "Error canceling verification request", msg = e.msg
|
||||
|
||||
proc acceptVerificationRequest*(self: Service, publicKey: string, responseText: string) =
|
||||
try:
|
||||
let response = status_contacts.acceptVerificationRequest(publicKey, responseText)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
raise newException(RpcException, msg)
|
||||
|
||||
var request = self.receivedIdentityRequests[publicKey]
|
||||
request.status = VerificationStatus.Verified
|
||||
request.response = responseText
|
||||
request.repliedAt = getTime().toUnix * 1000
|
||||
self.receivedIdentityRequests[publicKey] = request
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFICATION_ACCEPTED,
|
||||
VerificationRequestArgs(verificationRequest: request))
|
||||
except Exception as e:
|
||||
error "error accepting contact verification request", msg=e.msg
|
||||
|
||||
proc declineVerificationRequest*(self: Service, publicKey: string) =
|
||||
try:
|
||||
let response = status_contacts.declineVerificationRequest(publicKey)
|
||||
if(not response.error.isNil):
|
||||
let msg = response.error.message
|
||||
raise newException(RpcException, msg)
|
||||
|
||||
var request = self.receivedIdentityRequests[publicKey]
|
||||
request.status = VerificationStatus.Declined
|
||||
self.receivedIdentityRequests[publicKey] = request
|
||||
|
||||
self.events.emit(SIGNAL_CONTACT_VERIFICATION_DECLINED, ContactArgs(contactId: publicKey))
|
||||
except Exception as e:
|
||||
error "error declining contact verification request", msg=e.msg
|
||||
|
|
@ -54,3 +54,51 @@ proc sendContactUpdate*(publicKey, ensName, thumbnail: string): RpcResponse[Json
|
|||
proc getImageServerURL*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* []
|
||||
result = callPrivateRPC("imageServerURL".prefix, payload)
|
||||
|
||||
proc markUntrustworthy*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("markAsUntrustworthy".prefix, payload)
|
||||
|
||||
proc verifiedTrusted*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("verifiedTrusted".prefix, payload)
|
||||
|
||||
proc verifiedUntrustworthy*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("verifiedUntrustworthy".prefix, payload)
|
||||
|
||||
proc removeTrustStatus*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("removeTrustStatus".prefix, payload)
|
||||
|
||||
proc getTrustStatus*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("getTrustStatus".prefix, payload)
|
||||
|
||||
proc sendVerificationRequest*(pubkey: string, challenge: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey, challenge]
|
||||
result = callPrivateRPC("sendContactVerificationRequest".prefix, payload)
|
||||
|
||||
proc acceptVerificationRequest*(pubkey: string, response: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey, response]
|
||||
result = callPrivateRPC("acceptContactVerificationRequest".prefix, payload)
|
||||
|
||||
proc declineVerificationRequest*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("declineContactVerificationRequest".prefix, payload)
|
||||
|
||||
proc getVerificationRequestSentTo*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("getVerificationRequestSentTo".prefix, payload)
|
||||
|
||||
proc getVerificationRequestFrom*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("getVerificationRequestFrom".prefix, payload)
|
||||
|
||||
proc getReceivedVerificationRequests*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* []
|
||||
result = callPrivateRPC("getReceivedVerificationRequests".prefix, payload)
|
||||
|
||||
proc cancelVerificationRequest*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [pubkey]
|
||||
result = callPrivateRPC("cancelVerificationRequest".prefix, payload)
|
||||
|
|
|
@ -129,6 +129,7 @@ ModalPopup {
|
|||
pinnedMessage: model.pinned
|
||||
messagePinnedBy: model.pinnedBy
|
||||
reactionsModel: model.reactions
|
||||
senderTrustStatus: model.senderTrustStatus
|
||||
linkUrls: model.links
|
||||
isInPinnedPopup: true
|
||||
transactionParams: model.transactionParameters
|
||||
|
|
|
@ -135,6 +135,7 @@ Item {
|
|||
messageTimestamp: model.timestamp
|
||||
messageOutgoingStatus: model.message.outgoingStatus
|
||||
messageContentType: model.message.contentType
|
||||
senderTrustStatus: model.message.senderTrustStatus
|
||||
activityCenterMessage: true
|
||||
read: model.read
|
||||
onImageClicked: Global.openImagePopup(image, root.messageContextMenu)
|
||||
|
|
|
@ -303,6 +303,7 @@ Item {
|
|||
messageTimestamp: model.timestamp
|
||||
messageOutgoingStatus: model.outgoingStatus
|
||||
messageContentType: model.contentType
|
||||
senderTrustStatus: model.senderTrustStatus
|
||||
pinnedMessage: model.pinned
|
||||
messagePinnedBy: model.pinnedBy
|
||||
reactionsModel: model.reactions
|
||||
|
|
|
@ -135,6 +135,7 @@ StatusAppTwoPanelLayout {
|
|||
|
||||
messagingStore: profileView.store.messagingStore
|
||||
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.messaging)
|
||||
contactsStore: profileView.store.contactsStore
|
||||
contentWidth: d.contentWidth
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ StatusListItem {
|
|||
property bool isBlocked: false
|
||||
property bool isVerified: false
|
||||
property bool isUntrustworthy: false
|
||||
property int verificationRequestStatus: 0
|
||||
|
||||
property string searchStr: ""
|
||||
|
||||
|
@ -44,12 +45,24 @@ StatusListItem {
|
|||
signal openProfilePopup(string publicKey)
|
||||
signal openChangeNicknamePopup(string publicKey)
|
||||
signal sendMessageActionTriggered(string publicKey)
|
||||
signal showVerificationRequest(string publicKey)
|
||||
signal contactRequestAccepted(string publicKey)
|
||||
signal contactRequestRejected(string publicKey)
|
||||
signal rejectionRemoved(string publicKey)
|
||||
signal textClicked(string publicKey)
|
||||
|
||||
components: [
|
||||
StatusFlatButton {
|
||||
visible: verificationRequestStatus === Constants.verificationStatus.verifying ||
|
||||
verificationRequestStatus === Constants.verificationStatus.verified
|
||||
width: visible ? implicitWidth : 0
|
||||
height: visible ? implicitHeight : 0
|
||||
text: verificationRequestStatus === Constants.verificationStatus.verifying ?
|
||||
qsTr("Respond to ID Request") :
|
||||
qsTr("See ID Request")
|
||||
size: StatusBaseButton.Size.Small
|
||||
onClicked: container.showVerificationRequest(container.publicKey)
|
||||
},
|
||||
StatusFlatRoundButton {
|
||||
visible: showSendMessageButton
|
||||
width: visible ? 32 : 0
|
||||
|
|
|
@ -27,6 +27,7 @@ Item {
|
|||
signal contactClicked(string publicKey)
|
||||
signal openProfilePopup(string publicKey)
|
||||
signal sendMessageActionTriggered(string publicKey)
|
||||
signal showVerificationRequest(string publicKey)
|
||||
signal openChangeNicknamePopup(string publicKey)
|
||||
signal contactRequestAccepted(string publicKey)
|
||||
signal contactRequestRejected(string publicKey)
|
||||
|
@ -115,19 +116,20 @@ Item {
|
|||
isBlocked: model.isBlocked
|
||||
isVerified: model.isVerified
|
||||
isUntrustworthy: model.isUntrustworthy
|
||||
verificationRequestStatus: model.incomingVerificationStatus
|
||||
|
||||
searchStr: contactListRoot.searchString
|
||||
|
||||
showSendMessageButton: model.isContact
|
||||
showRejectContactRequestButton: {
|
||||
if (contactListRoot.panelUsage === Constants.contactsPanelUsage.receivedContactRequest) {
|
||||
if (contactListRoot.panelUsage === Constants.contactsPanelUsage.receivedContactRequest && !model.verificationRequestStatus) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
showAcceptContactRequestButton: {
|
||||
if (contactListRoot.panelUsage === Constants.contactsPanelUsage.receivedContactRequest) {
|
||||
if (contactListRoot.panelUsage === Constants.contactsPanelUsage.receivedContactRequest && !model.verificationRequestStatus) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -162,6 +164,7 @@ Item {
|
|||
onContactRequestRejected: contactListRoot.contactRequestRejected(publicKey)
|
||||
onRejectionRemoved: contactListRoot.rejectionRemoved(publicKey)
|
||||
onTextClicked: contactListRoot.textClicked(publicKey)
|
||||
onShowVerificationRequest: contactListRoot.showVerificationRequest(publicKey)
|
||||
|
||||
visible: searchString === "" ||
|
||||
panelDelegate.name.toLowerCase().includes(lowerCaseSearchString) ||
|
||||
|
|
|
@ -11,7 +11,7 @@ Column {
|
|||
spacing: 4
|
||||
|
||||
property var privacyStore
|
||||
property var messagingStore
|
||||
property var contactsStore
|
||||
property alias mainMenuItems: mainMenuItems.model
|
||||
property alias settingsMenuItems: settingsMenuItems.model
|
||||
property alias extraMenuItems: extraMenuItems.model
|
||||
|
@ -71,7 +71,7 @@ Column {
|
|||
badge.value: {
|
||||
switch (model.subsection) {
|
||||
case Constants.settingsSubsection.messaging:
|
||||
return root.messagingStore.contactRequestsModel.count
|
||||
return root.contactsStore.receivedContactRequestsModel.count
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,4 +80,50 @@ QtObject {
|
|||
function removeContactRequestRejection(pubKey) {
|
||||
root.contactsModule.removeContactRequestRejection(pubKey)
|
||||
}
|
||||
|
||||
function markUntrustworthy(pubKey) {
|
||||
root.contactsModule.markUntrustworthy(pubKey)
|
||||
}
|
||||
|
||||
function removeTrustStatus(pubKey) {
|
||||
root.contactsModule.removeTrustStatus(pubKey)
|
||||
}
|
||||
|
||||
function sendVerificationRequest(pubKey, challenge) {
|
||||
root.contactsModule.sendVerificationRequest(pubKey, challenge);
|
||||
}
|
||||
|
||||
function cancelVerificationRequest(pubKey) {
|
||||
root.contactsModule.cancelVerificationRequest(pubKey);
|
||||
}
|
||||
|
||||
function declineVerificationRequest(pubKey) {
|
||||
root.contactsModule.declineVerificationRequest(pubKey);
|
||||
}
|
||||
|
||||
function acceptVerificationRequest(pubKey, response) {
|
||||
root.contactsModule.acceptVerificationRequest(pubKey, response);
|
||||
}
|
||||
|
||||
function getVerificationDetailsFromAsJson(pubKey) {
|
||||
let resp = root.contactsModule.getVerificationDetailsFromAsJson(pubKey);
|
||||
return JSON.parse(resp);
|
||||
}
|
||||
|
||||
function getSentVerificationDetailsAsJson(pubKey) {
|
||||
let resp = root.contactsModule.getSentVerificationDetailsAsJson(pubKey);
|
||||
return JSON.parse(resp);
|
||||
}
|
||||
|
||||
function hasReceivedVerificationRequestFrom(pubKey) {
|
||||
return root.contactsModule.hasReceivedVerificationRequestFrom(pubKey);
|
||||
}
|
||||
|
||||
function verifiedTrusted(pubKey) {
|
||||
root.contactsModule.verifiedTrusted(pubKey);
|
||||
}
|
||||
|
||||
function verifiedUntrustworthy(pubKey) {
|
||||
root.contactsModule.verifiedUntrustworthy(pubKey);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,6 @@ QtObject {
|
|||
property int profilePicturesVisibility: privacyModule.profilePicturesVisibility
|
||||
property int profilePicturesShowTo: privacyModule.profilePicturesShowTo
|
||||
|
||||
// TODO move contact requests back to the contacts module since we need them in the Profile
|
||||
// also, having them in the chat section creates some waste, since no community has it
|
||||
property var chatSectionModule: mainModule.getChatSectionModule()
|
||||
property var contactRequestsModel: chatSectionModule.contactRequestsModel
|
||||
|
||||
property var mailservers: syncModule.model
|
||||
|
||||
property bool useMailservers: syncModule.useMailservers
|
||||
|
|
|
@ -17,8 +17,6 @@ import shared.controls 1.0
|
|||
import "../stores"
|
||||
import "../panels"
|
||||
import "../popups"
|
||||
// TODO remove this import when the ContactRequestPanel is moved to the the Profile completely
|
||||
import "../../Chat/panels"
|
||||
|
||||
SettingsContentBase {
|
||||
id: root
|
||||
|
@ -181,6 +179,23 @@ SettingsContentBase {
|
|||
onContactRequestRejected: {
|
||||
root.contactsStore.rejectContactRequest(publicKey)
|
||||
}
|
||||
|
||||
onShowVerificationRequest: {
|
||||
try {
|
||||
let request = root.contactsStore.getVerificationDetailsFromAsJson(publicKey)
|
||||
Global.openPopup(contactVerificationRequestPopupComponent, {
|
||||
senderPublicKey: request.from,
|
||||
senderDisplayName: request.displayName,
|
||||
senderIcon: request.icon,
|
||||
challengeText: request.challenge,
|
||||
responseText: request.response,
|
||||
messageTimestamp: request.requestedAt,
|
||||
responseTimestamp: request.repliedAt
|
||||
})
|
||||
} catch (e) {
|
||||
console.error("Error getting or parsing verification data", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContactsListPanel {
|
||||
|
@ -304,6 +319,18 @@ SettingsContentBase {
|
|||
root.contactsStore.removeContact(removeContactConfirmationDialog.value);
|
||||
}
|
||||
removeContactConfirmationDialog.close()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: contactVerificationRequestPopupComponent
|
||||
ContactVerificationRequestPopup {
|
||||
onResponseSent: {
|
||||
root.contactsStore.acceptVerificationRequest(senderPublicKey, response)
|
||||
}
|
||||
onVerificationRefused: {
|
||||
root.contactsStore.declineVerificationRequest(senderPublicKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ Item {
|
|||
MenuPanel {
|
||||
id: profileMenu
|
||||
privacyStore: store.privacyStore
|
||||
messagingStore: store.messagingStore
|
||||
contactsStore: store.contactsStore
|
||||
mainMenuItems: store.mainMenuItems
|
||||
settingsMenuItems: store.settingsMenuItems
|
||||
extraMenuItems: store.extraMenuItems
|
||||
|
|
|
@ -24,6 +24,7 @@ SettingsContentBase {
|
|||
id: root
|
||||
|
||||
property MessagingStore messagingStore
|
||||
property ContactsStore contactsStore
|
||||
|
||||
ColumnLayout {
|
||||
id: generalColumn
|
||||
|
@ -214,7 +215,7 @@ SettingsContentBase {
|
|||
StatusContactRequestsIndicatorListItem {
|
||||
Layout.fillWidth: true
|
||||
title: qsTr("Contacts, Requests, and Blocked Users")
|
||||
requestsCount: root.messagingStore.contactRequestsModel.count
|
||||
requestsCount: root.contactsStore.receivedContactRequestsModel.count
|
||||
sensor.onClicked: Global.changeAppSectionBySectionType(Constants.appSection.profile,
|
||||
Constants.settingsSubsection.contacts)
|
||||
}
|
||||
|
|
|
@ -107,6 +107,10 @@ Item {
|
|||
onDisplayToastMessage: {
|
||||
appMain.rootStore.mainModuleInst.displayEphemeralNotification(title, subTitle, icon, loading, ephNotifType, url);
|
||||
}
|
||||
onOpenEditDisplayNamePopup: {
|
||||
var popup = displayNamePopupComponent.createObject(appMain)
|
||||
popup.open()
|
||||
}
|
||||
}
|
||||
|
||||
function changeAppSectionBySectionId(sectionId) {
|
||||
|
@ -151,6 +155,13 @@ Item {
|
|||
privacyStore: appMain.rootStore.profileSectionStore.privacyStore
|
||||
}
|
||||
|
||||
property Component displayNamePopupComponent: DisplayNamePopup {
|
||||
profileStore: appMain.rootStore.profileSectionStore.profileStore
|
||||
onClosed: {
|
||||
destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: downloadPageComponent
|
||||
DownloadPage {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.5 8C0.5 3.58172 4.08172 0 8.5 0C12.9183 0 16.5 3.58172 16.5 8C16.5 12.4183 12.9183 16 8.5 16C4.08172 16 0.5 12.4183 0.5 8Z" fill="#4360DF"/>
|
||||
<path d="M8.49984 7.5C9.74248 7.5 10.7498 6.49264 10.7498 5.25C10.7498 4.00736 9.74248 3 8.49984 3C7.2572 3 6.24984 4.00736 6.24984 5.25C6.24984 6.49264 7.2572 7.5 8.49984 7.5Z" fill="white"/>
|
||||
<path d="M4.62326 12.0101C5.06378 10.2798 6.63236 9 8.49984 9C10.3673 9 11.9359 10.2798 12.3764 12.0101C12.5127 12.5453 12.0521 13 11.4998 13H5.49984C4.94755 13 4.48701 12.5453 4.62326 12.0101Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 659 B |
|
@ -0,0 +1,4 @@
|
|||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="5" cy="5" r="5" fill="#FF2D55"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.78125 7.65625C5.78125 8.08772 5.43147 8.4375 5 8.4375C4.56853 8.4375 4.21875 8.08772 4.21875 7.65625C4.21875 7.22478 4.56853 6.875 5 6.875C5.43147 6.875 5.78125 7.22478 5.78125 7.65625ZM5 1.875C4.65482 1.875 4.375 2.15482 4.375 2.5V5.3125C4.375 5.65768 4.65482 5.9375 5 5.9375C5.34518 5.9375 5.625 5.65768 5.625 5.3125V2.5C5.625 2.15482 5.34518 1.875 5 1.875Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 576 B |
|
@ -0,0 +1,4 @@
|
|||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="5" cy="5" r="5" fill="#4360DF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.21097 5.79222L6.73854 3.25573C6.91216 3.08149 7.19307 3.0809 7.36869 3.25713C7.54308 3.43214 7.54399 3.71498 7.37008 3.8895L4.52534 6.74428C4.43901 6.83091 4.32615 6.87462 4.2129 6.875C4.09629 6.87412 3.98311 6.8311 3.89811 6.7458L2.6292 5.47241C2.45641 5.29901 2.4565 5.01779 2.63211 4.84156C2.8065 4.66655 3.09029 4.66758 3.26074 4.83864L4.21097 5.79222Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 573 B |
|
@ -125,12 +125,7 @@ Item {
|
|||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton | Qt.LeftButton
|
||||
onClicked: {
|
||||
if((mouse.button === Qt.RightButton) && inputValue.canPaste) {
|
||||
rightClickContextMenu.popup()
|
||||
}
|
||||
else {
|
||||
inputValue.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
inputValue.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,9 +178,7 @@ Item {
|
|||
if (inputBox.copyToClipboard) {
|
||||
RootStore.copyToClipboard(inputBox.textToCopy ? inputBox.textToCopy : inputValue.text)
|
||||
} else {
|
||||
if (inputValue.canPaste) {
|
||||
inputValue.paste()
|
||||
}
|
||||
inputValue.paste()
|
||||
}
|
||||
|
||||
copyBtn.copied = true
|
||||
|
@ -211,22 +204,6 @@ Item {
|
|||
color: validationErrorColor
|
||||
wrapMode: TextEdit.Wrap
|
||||
}
|
||||
|
||||
StatusPopupMenu {
|
||||
id: rightClickContextMenu
|
||||
|
||||
StatusMenuItem {
|
||||
enabled: inputValue.canPaste
|
||||
text: qsTrId("Paste")
|
||||
onTriggered: {
|
||||
inputValue.paste()
|
||||
}
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
inputValue.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*##^##
|
||||
|
|
|
@ -18,18 +18,24 @@ Item {
|
|||
Big
|
||||
}
|
||||
|
||||
property var store
|
||||
property string displayName
|
||||
property string pubkey
|
||||
property string icon
|
||||
property int trustStatus
|
||||
property bool isContact: false
|
||||
|
||||
property int imageSize: ProfileHeader.ImageSize.Compact
|
||||
property bool displayNameVisible: true
|
||||
property bool displayNamePlusIconsVisible: false
|
||||
property bool pubkeyVisible: true
|
||||
property bool pubkeyVisibleWithCopy: false
|
||||
property bool emojiHashVisible: true
|
||||
property bool editImageButtonVisible: false
|
||||
readonly property bool compact: root.imageSize == ProfileHeader.ImageSize.Compact
|
||||
|
||||
signal clicked()
|
||||
signal editClicked()
|
||||
|
||||
height: visible ? contentContainer.height : 0
|
||||
implicitHeight: contentContainer.implicitHeight
|
||||
|
@ -108,9 +114,56 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: 380
|
||||
spacing: Style.current.halfPadding
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: root.displayNamePlusIconsVisible
|
||||
StyledText {
|
||||
text: root.displayName
|
||||
font {
|
||||
weight: Font.Medium
|
||||
pixelSize: Style.current.primaryTextFontSize
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
sourceComponent: SVGImage {
|
||||
height: 16
|
||||
width: 16
|
||||
source: Style.svg("contact")
|
||||
}
|
||||
active: isContact
|
||||
}
|
||||
|
||||
Loader {
|
||||
sourceComponent: VerificationLabel {
|
||||
id: trustStatus
|
||||
trustStatus: root.trustStatus
|
||||
height: 16
|
||||
width: 16
|
||||
}
|
||||
active: root.trustStatus !== Constants.trustStatus.unknown
|
||||
}
|
||||
|
||||
SVGImage {
|
||||
height: 16
|
||||
width: 16
|
||||
source: Style.svg("edit-message")
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
root.editClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
visible: root.pubkeyVisible
|
||||
|
||||
text: Utils.getElidedCompressedPk(pubkey)
|
||||
|
@ -120,6 +173,31 @@ Item {
|
|||
color: Style.current.secondaryText
|
||||
}
|
||||
|
||||
Row {
|
||||
width: 380
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: root.pubkeyVisibleWithCopy
|
||||
StyledText {
|
||||
id: txtChatKey
|
||||
text: qsTr("Chatkey:%1...").arg(pubkey.substring(0, 32))
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
color: Style.current.secondaryText
|
||||
width: 360
|
||||
}
|
||||
|
||||
|
||||
CopyToClipBoardButton {
|
||||
id: copyBtn
|
||||
width: 20
|
||||
height: 20
|
||||
color: Style.current.transparent
|
||||
textToCopy: pubkey
|
||||
store: root.store
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EmojiHash {
|
||||
id: emojiHash
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import QtQuick 2.3
|
||||
import shared.controls 1.0
|
||||
import shared 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
SVGImage {
|
||||
id: root
|
||||
width: 10
|
||||
height: 10
|
||||
|
||||
property int trustStatus: Constants.trustStatus.unknown
|
||||
|
||||
source: {
|
||||
switch(trustStatus) {
|
||||
case Constants.trustStatus.trusted:
|
||||
return Style.svg("verified");
|
||||
case Constants.trustStatus.untrustworthy:
|
||||
return Style.svg("untrustworthy");
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,3 +13,4 @@ GasSelectorButton 1.0 GasSelectorButton.qml
|
|||
MessageBorder 1.0 MessageBorder.qml
|
||||
EmojiReaction 1.0 EmojiReaction.qml
|
||||
ProfileHeader 1.0 ProfileHeader.qml
|
||||
VerificationLabel 1.0 VerificationLabel.qml
|
||||
|
|
|
@ -6,7 +6,8 @@ Item {
|
|||
id: root
|
||||
property color color: Style.current.separator
|
||||
width: parent.width
|
||||
height: root.visible ? 1 : 0
|
||||
implicitHeight: 1
|
||||
height: root.visible ? implicitHeight : 0
|
||||
anchors.topMargin: Style.current.padding
|
||||
Rectangle {
|
||||
id: separator
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import shared.controls 1.0
|
||||
import shared.views.chat 1.0
|
||||
|
||||
StatusModal {
|
||||
id: root
|
||||
|
||||
property string senderPublicKey: ""
|
||||
property string senderDisplayName: ""
|
||||
property string senderIcon: ""
|
||||
property string challengeText: ""
|
||||
property string responseText: ""
|
||||
property string messageTimestamp: ""
|
||||
property string responseTimestamp: ""
|
||||
|
||||
signal verificationRefused(string senderPublicKey)
|
||||
signal responseSent(string senderPublicKey, string response)
|
||||
|
||||
header.title: qsTr("%1 is asking you to verify your identity").arg(root.senderDisplayName)
|
||||
|
||||
x: Math.round(((parent ? parent.width : 0) - width) / 2)
|
||||
y: Math.round(((parent ? parent.height : 0) - height) / 2)
|
||||
|
||||
width: 480
|
||||
height: 230 + verificationMessage.height + verificationResponse.height
|
||||
|
||||
onOpened: {
|
||||
verificationResponse.input.edit.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
onClosed: {
|
||||
root.destroy();
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
|
||||
StatusBaseText {
|
||||
id: description
|
||||
width: parent.width
|
||||
color: Theme.palette.directColor1
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.padding
|
||||
text: qsTr("%1 would like to verify your identity. Answer the question to prove your identity to %2")
|
||||
.arg(root.senderDisplayName).arg(root.senderDisplayName)
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
MessageView {
|
||||
id: verificationMessage
|
||||
anchors.top: description.bottom
|
||||
anchors.topMargin: Style.current.padding
|
||||
isMessage: true
|
||||
shouldRepeatHeader: true
|
||||
messageTimestamp: root.messageTimestamp
|
||||
senderDisplayName: root.senderDisplayName
|
||||
senderIcon: root.senderIcon
|
||||
message: root.challengeText
|
||||
messageContentType: Constants.messageContentType.messageType
|
||||
placeholderMessage: true
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: verificationResponse
|
||||
visible: !responseText
|
||||
anchors.top: verificationMessage.bottom
|
||||
anchors.topMargin: 5
|
||||
input.multiline: true
|
||||
input.placeholderText: qsTr("Provide answer to verification request from this contact.")
|
||||
input.implicitHeight: 152
|
||||
width: parent.width
|
||||
input.verticalAlignment: TextEdit.AlignTop
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
charLimit: 280
|
||||
}
|
||||
|
||||
MessageView {
|
||||
id: responseMessage
|
||||
visible: !!root.responseText
|
||||
anchors.top: verificationMessage.bottom
|
||||
isMessage: true
|
||||
shouldRepeatHeader: true
|
||||
messageTimestamp: root.responseTimestamp
|
||||
senderDisplayName: userProfile.name
|
||||
senderIcon: userProfile.icon
|
||||
message: root.responseText
|
||||
messageContentType: Constants.messageContentType.messageType
|
||||
placeholderMessage: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: responseSent
|
||||
visible: !!root.responseText
|
||||
width: parent.width
|
||||
color: Theme.palette.baseColor1
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.top: responseMessage.bottom
|
||||
anchors.topMargin: 58
|
||||
text: qsTr("You're answer has been sent to %1.").arg(root.senderDisplayName)
|
||||
font.pixelSize: 13
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
visible: !root.responseText
|
||||
text: qsTr("Refuse Verification")
|
||||
onClicked: {
|
||||
root.verificationRefused(root.senderPublicKey)
|
||||
root.close();
|
||||
}
|
||||
},
|
||||
StatusButton {
|
||||
text: qsTr("Send Answer")
|
||||
visible: !root.responseText
|
||||
enabled: verificationResponse.text !== ""
|
||||
onClicked: {
|
||||
root.responseSent(root.senderPublicKey, Utils.escapeHtml(verificationResponse.text))
|
||||
root.responseText = verificationResponse.text
|
||||
root.responseTimestamp = Date.now()
|
||||
}
|
||||
},
|
||||
StatusFlatButton {
|
||||
visible: root.responseText
|
||||
text: qsTr("Change answer")
|
||||
onClicked: {
|
||||
root.responseText = ""
|
||||
}
|
||||
},
|
||||
StatusButton {
|
||||
visible: root.responseText
|
||||
text: qsTr("Close")
|
||||
onClicked: root.close()
|
||||
}
|
||||
]
|
||||
}
|
|
@ -9,6 +9,7 @@ import shared.popups 1.0
|
|||
import shared.stores 1.0
|
||||
import shared.views 1.0 as SharedViews
|
||||
import shared.controls.chat 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
@ -30,11 +31,40 @@ StatusModal {
|
|||
property string userNickname: ""
|
||||
property string userEnsName: ""
|
||||
property string userIcon: ""
|
||||
property int userTrustStatus: Constants.trustStatus.unknown
|
||||
property int verificationStatus: Constants.verificationStatus.unverified
|
||||
property string text: ""
|
||||
property string challenge: ""
|
||||
property string response: ""
|
||||
|
||||
property bool userIsEnsVerified: false
|
||||
property bool userIsBlocked: false
|
||||
property bool userIsUntrustworthy: false
|
||||
property bool userTrustIsUnknown: false
|
||||
property bool isCurrentUser: false
|
||||
property bool isAddedContact: false
|
||||
property bool isMutualContact: false
|
||||
property bool isVerificationSent: false
|
||||
property bool isVerified: false
|
||||
property bool isTrusted: false
|
||||
property bool hasReceivedVerificationRequest: false
|
||||
|
||||
property bool showRemoveVerified: false
|
||||
property bool showVerifyIdentitySection: false
|
||||
property bool showVerificationPendingSection: false
|
||||
property bool showIdentityVerified: false
|
||||
property bool showIdentityVerifiedUntrustworthy: false
|
||||
|
||||
property string verificationChallenge: ""
|
||||
property string verificationResponse: ""
|
||||
property string verificationResponseDisplayName: ""
|
||||
property string verificationResponseIcon: ""
|
||||
property string verificationRequestedAt: ""
|
||||
property string verificationRepliedAt: ""
|
||||
|
||||
signal blockButtonClicked(name: string, address: string)
|
||||
signal unblockButtonClicked(name: string, address: string)
|
||||
signal removeButtonClicked(address: string)
|
||||
|
||||
signal contactUnblocked(publicKey: string)
|
||||
signal contactBlocked(publicKey: string)
|
||||
|
@ -51,6 +81,32 @@ StatusModal {
|
|||
userIsEnsVerified = contactDetails.ensVerified;
|
||||
userIsBlocked = contactDetails.isBlocked;
|
||||
isAddedContact = contactDetails.isContact;
|
||||
isMutualContact = contactDetails.isContact && contactDetails.hasAddedUs
|
||||
userTrustStatus = contactDetails.trustStatus
|
||||
userTrustIsUnknown = contactDetails.trustStatus === Constants.trustStatus.unknown
|
||||
userIsUntrustworthy = contactDetails.trustStatus === Constants.trustStatus.untrustworthy
|
||||
verificationStatus = contactDetails.verificationStatus
|
||||
isVerificationSent = verificationStatus !== Constants.verificationStatus.unverified
|
||||
|
||||
if (isMutualContact && popup.contactsStore.hasReceivedVerificationRequestFrom(publicKey)) {
|
||||
popup.hasReceivedVerificationRequest = true
|
||||
}
|
||||
|
||||
if(isMutualContact && isVerificationSent) {
|
||||
let verificationDetails = popup.contactsStore.getSentVerificationDetailsAsJson(publicKey);
|
||||
|
||||
verificationStatus = verificationDetails.requestStatus;
|
||||
verificationChallenge = verificationDetails.challenge;
|
||||
verificationResponse = verificationDetails.response;
|
||||
verificationResponseDisplayName = verificationDetails.displayName;
|
||||
verificationResponseIcon = verificationDetails.icon;
|
||||
verificationRequestedAt = verificationDetails.requestedAt;
|
||||
verificationRepliedAt = verificationDetails.repliedAt;
|
||||
}
|
||||
isTrusted = verificationStatus === Constants.verificationStatus.trusted
|
||||
isVerified = verificationStatus === Constants.verificationStatus.verified
|
||||
|
||||
text = ""; // this is most likely unneeded
|
||||
isCurrentUser = popup.profileStore.pubkey === publicKey;
|
||||
|
||||
showFooter = !isCurrentUser;
|
||||
|
@ -79,19 +135,19 @@ StatusModal {
|
|||
profileView.unblockContactConfirmationDialog.open();
|
||||
}
|
||||
|
||||
header.title: userDisplayName + qsTr("'s Profile")
|
||||
width: 700
|
||||
|
||||
header.title: {
|
||||
if(showVerifyIdentitySection || showVerificationPendingSection){
|
||||
return qsTr("Verify %1's Identity").arg(userIsEnsVerified ? userName : userDisplayName)
|
||||
}
|
||||
return qsTr("%1's Profile").arg(userIsEnsVerified ? userName : userDisplayName)
|
||||
}
|
||||
header.subTitle: userIsEnsVerified ? userName : Utils.getElidedCompressedPk(userPublicKey)
|
||||
header.subTitleElide: Text.ElideMiddle
|
||||
padding: 8
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int contentSpacing: 5
|
||||
readonly property int contentMargins: 16
|
||||
}
|
||||
|
||||
headerActionButton: StatusFlatRoundButton {
|
||||
headerActionButton: StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
width: 32
|
||||
height: 32
|
||||
|
@ -120,6 +176,33 @@ StatusModal {
|
|||
isAddedContact: popup.isAddedContact
|
||||
isCurrentUser: popup.isCurrentUser
|
||||
|
||||
isMutualContact: popup.isMutualContact
|
||||
isVerificationSent: popup.isVerificationSent
|
||||
isVerified: popup.isVerified
|
||||
isTrusted: popup.isTrusted
|
||||
hasReceivedVerificationRequest: popup.hasReceivedVerificationRequest
|
||||
|
||||
userTrustStatus: popup.userTrustStatus
|
||||
verificationStatus: popup.verificationStatus
|
||||
|
||||
showVerifyIdentitySection: popup.showVerifyIdentitySection
|
||||
showVerificationPendingSection: popup.showVerificationPendingSection
|
||||
showIdentityVerified: popup.showIdentityVerified
|
||||
showIdentityVerifiedUntrustworthy: popup.showIdentityVerifiedUntrustworthy
|
||||
|
||||
challenge: popup.challenge
|
||||
response: popup.response
|
||||
|
||||
userIsUntrustworthy: popup.userIsUntrustworthy
|
||||
userTrustIsUnknown: popup.userTrustIsUnknown
|
||||
|
||||
verificationChallenge: popup.verificationChallenge
|
||||
verificationResponse: popup.verificationResponse
|
||||
verificationResponseDisplayName: popup.verificationResponseDisplayName
|
||||
verificationResponseIcon: popup.verificationResponseIcon
|
||||
verificationRequestedAt: popup.verificationRequestedAt
|
||||
verificationRepliedAt: popup.verificationRepliedAt
|
||||
|
||||
onContactUnblocked: {
|
||||
popup.close()
|
||||
popup.contactUnblocked(publicKey)
|
||||
|
@ -149,7 +232,6 @@ StatusModal {
|
|||
id: sendContactRequestModal
|
||||
anchors.centerIn: parent
|
||||
width: popup.width
|
||||
height: popup.height
|
||||
visible: false
|
||||
header.title: qsTr("Send Contact Request to") + " " + userDisplayName
|
||||
userPublicKey: popup.userPublicKey
|
||||
|
@ -158,6 +240,17 @@ StatusModal {
|
|||
onAccepted: popup.contactsStore.sendContactRequest(userPublicKey, message)
|
||||
onClosed: popup.close()
|
||||
}
|
||||
|
||||
leftButtons:[
|
||||
StatusButton {
|
||||
text: qsTr("Cancel verification")
|
||||
visible: !isVerified && isMutualContact && isVerificationSent && showVerificationPendingSection
|
||||
onClicked: {
|
||||
popup.contactsStore.cancelVerificationRequest(userPublicKey);
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
rightButtons: [
|
||||
StatusFlatButton {
|
||||
|
@ -165,11 +258,12 @@ StatusModal {
|
|||
qsTr("Unblock User") :
|
||||
qsTr("Block User")
|
||||
type: StatusBaseButton.Type.Danger
|
||||
visible: !isAddedContact
|
||||
onClicked: userIsBlocked ? unblockUser() : blockUser()
|
||||
},
|
||||
|
||||
StatusFlatButton {
|
||||
visible: !userIsBlocked && isAddedContact
|
||||
visible: !showRemoveVerified && !showIdentityVerified && !showVerifyIdentitySection && !showVerificationPendingSection && !userIsBlocked && isAddedContact
|
||||
type: StatusBaseButton.Type.Danger
|
||||
text: qsTr('Remove Contact')
|
||||
onClicked: {
|
||||
|
@ -182,6 +276,160 @@ StatusModal {
|
|||
text: qsTr("Send Contact Request")
|
||||
visible: !userIsBlocked && !isAddedContact
|
||||
onClicked: sendContactRequestModal.open()
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Mark Untrustworthy")
|
||||
visible: !showIdentityVerifiedUntrustworthy && !showIdentityVerified && !showVerifyIdentitySection && userTrustIsUnknown
|
||||
enabled: !showVerificationPendingSection || verificationResponse !== ""
|
||||
type: StatusBaseButton.Type.Danger
|
||||
onClicked: {
|
||||
if (showVerificationPendingSection) {
|
||||
popup.showIdentityVerified = false;
|
||||
popup.showIdentityVerifiedUntrustworthy = true;
|
||||
popup.showVerificationPendingSection = false;
|
||||
popup.showVerifyIdentitySection = false;
|
||||
profileView.stepsListModel.setProperty(2, "stepCompleted", true);
|
||||
popup.contactsStore.verifiedUntrustworthy(userPublicKey);
|
||||
} else {
|
||||
popup.contactsStore.markUntrustworthy(userPublicKey);
|
||||
popup.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Remove 'Identity Verified' status")
|
||||
visible: isTrusted && !showIdentityVerified && !showRemoveVerified
|
||||
type: StatusBaseButton.Type.Danger
|
||||
onClicked: {
|
||||
showRemoveVerified = true
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("No")
|
||||
visible: showRemoveVerified
|
||||
type: StatusBaseButton.Type.Danger
|
||||
onClicked: {
|
||||
showRemoveVerified = false
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Yes")
|
||||
visible: showRemoveVerified
|
||||
onClicked: {
|
||||
popup.contactsStore.removeTrustStatus(userPublicKey);
|
||||
popup.close();
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Remove Untrustworthy Mark")
|
||||
visible: userIsUntrustworthy
|
||||
onClicked: {
|
||||
popup.contactsStore.removeTrustStatus(userPublicKey);
|
||||
popup.close();
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Verify Identity")
|
||||
visible: !showIdentityVerifiedUntrustworthy && !showIdentityVerified &&
|
||||
!showVerifyIdentitySection && isMutualContact && !isVerificationSent
|
||||
&& !hasReceivedVerificationRequest
|
||||
onClicked: {
|
||||
popup.showVerifyIdentitySection = true
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Verify Identity pending...")
|
||||
visible: (!showIdentityVerifiedUntrustworthy && !showIdentityVerified && !isTrusted
|
||||
&& isMutualContact && isVerificationSent && !showVerificationPendingSection) ||
|
||||
(hasReceivedVerificationRequest && !isTrusted)
|
||||
onClicked: {
|
||||
if (hasReceivedVerificationRequest) {
|
||||
try {
|
||||
let request = popup.contactsStore.getVerificationDetailsFromAsJson(popup.userPublicKey)
|
||||
Global.openPopup(contactVerificationRequestPopupComponent, {
|
||||
senderPublicKey: request.from,
|
||||
senderDisplayName: request.displayName,
|
||||
senderIcon: request.icon,
|
||||
challengeText: request.challenge,
|
||||
responseText: request.response,
|
||||
messageTimestamp: request.requestedAt,
|
||||
responseTimestamp: request.repliedAt
|
||||
})
|
||||
} catch (e) {
|
||||
console.error("Error getting or parsing verification data", e)
|
||||
}
|
||||
} else {
|
||||
popup.showVerificationPendingSection = true
|
||||
profileView.wizardAnimation.running = true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Send verification request")
|
||||
visible: showVerifyIdentitySection && isMutualContact && !isVerificationSent
|
||||
onClicked: {
|
||||
popup.contactsStore.sendVerificationRequest(userPublicKey, Utils.escapeHtml(profileView.challengeTxt.input.text));
|
||||
profileView.stepsListModel.setProperty(1, "stepCompleted", true);
|
||||
Global.displayToastMessage(qsTr("Verification request sent"),
|
||||
"",
|
||||
"checkmark-circle",
|
||||
false,
|
||||
Constants.ephemeralNotificationType.normal,
|
||||
"");
|
||||
popup.close();
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
text: qsTr("Confirm Identity")
|
||||
visible: isMutualContact && isVerificationSent && !isTrusted && showVerificationPendingSection
|
||||
enabled: verificationChallenge !== "" && verificationResponse !== ""
|
||||
onClicked: {
|
||||
popup.showIdentityVerified = true;
|
||||
popup.showIdentityVerifiedUntrustworthy = false;
|
||||
popup.showVerificationPendingSection = false;
|
||||
popup.showVerifyIdentitySection = false;
|
||||
profileView.stepsListModel.setProperty(2, "stepCompleted", true);
|
||||
popup.contactsStore.verifiedTrusted(userPublicKey);
|
||||
popup.isTrusted = true
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
visible: showIdentityVerified || showIdentityVerifiedUntrustworthy
|
||||
text: qsTr("Rename")
|
||||
onClicked: {
|
||||
nicknamePopup.open()
|
||||
}
|
||||
},
|
||||
|
||||
StatusButton {
|
||||
visible: showIdentityVerified || showIdentityVerifiedUntrustworthy
|
||||
text: qsTr("Close")
|
||||
onClicked: {
|
||||
popup.close();
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Component {
|
||||
id: contactVerificationRequestPopupComponent
|
||||
ContactVerificationRequestPopup {
|
||||
onResponseSent: {
|
||||
popup.contactsStore.acceptVerificationRequest(senderPublicKey, response)
|
||||
}
|
||||
onVerificationRefused: {
|
||||
popup.contactsStore.declineVerificationRequest(senderPublicKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ StatusModal {
|
|||
enabled: messageInput.valid
|
||||
text: qsTr("Send Contact Request")
|
||||
onClicked: {
|
||||
root.accepted(messageInput.text);
|
||||
root.accepted(Utils.escapeHtml(messageInput.text));
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ BlockContactConfirmationDialog 1.0 BlockContactConfirmationDialog.qml
|
|||
SettingsDirtyToastMessage 1.0 SettingsDirtyToastMessage.qml
|
||||
ConfirmationDialog 1.0 ConfirmationDialog.qml
|
||||
CommunityIntroDialog 1.0 CommunityIntroDialog.qml
|
||||
ContactVerificationRequestPopup 1.0 ContactVerificationRequestPopup.qml
|
||||
DownloadModal 1.0 DownloadModal.qml
|
||||
DownloadPage 1.0 DownloadPage.qml
|
||||
ImageCropperModal 1.0 ImageCropperModal.qml
|
||||
|
@ -20,3 +21,4 @@ SelectAccountModal 1.0 SelectAccountModal.qml
|
|||
ProfilePopup 1.0 ProfilePopup.qml
|
||||
ImageCropWorkflow 1.0 ImageCropWorkflow.qml
|
||||
ImportCommunityPopup 1.0 ImportCommunityPopup.qml
|
||||
DisplayNamePopup 1.0 DisplayNamePopup.qml
|
||||
|
|
|
@ -7,7 +7,9 @@ import utils 1.0
|
|||
import shared 1.0
|
||||
import shared.popups 1.0
|
||||
import shared.stores 1.0
|
||||
import shared.views.chat 1.0
|
||||
import shared.controls.chat 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
@ -36,10 +38,42 @@ Rectangle {
|
|||
property bool isCurrentUser: profileStore.pubkey === userPublicKey
|
||||
property bool isAddedContact: false
|
||||
|
||||
property int userTrustStatus: Constants.trustStatus.unknown
|
||||
property int verificationStatus: Constants.verificationStatus.unverified
|
||||
|
||||
property string challenge: ""
|
||||
property string response: ""
|
||||
|
||||
property bool userIsUntrustworthy: false
|
||||
property bool userTrustIsUnknown: false
|
||||
property bool isMutualContact: false
|
||||
property bool isVerificationSent: false
|
||||
property bool isVerified: false
|
||||
property bool isTrusted: false
|
||||
property bool hasReceivedVerificationRequest: false
|
||||
|
||||
property bool showRemoveVerified: false
|
||||
property bool showVerifyIdentitySection: false
|
||||
property bool showVerificationPendingSection: false
|
||||
property bool showIdentityVerified: false
|
||||
property bool showIdentityVerifiedUntrustworthy: false
|
||||
|
||||
property string verificationChallenge: ""
|
||||
property string verificationResponse: ""
|
||||
property string verificationResponseDisplayName: ""
|
||||
property string verificationResponseIcon: ""
|
||||
property string verificationRequestedAt: ""
|
||||
property string verificationRepliedAt: ""
|
||||
|
||||
readonly property alias qrCodePopup: qrCodePopup
|
||||
readonly property alias unblockContactConfirmationDialog: unblockContactConfirmationDialog
|
||||
readonly property alias blockContactConfirmationDialog: blockContactConfirmationDialog
|
||||
readonly property alias removeContactConfirmationDialog: removeContactConfirmationDialog
|
||||
readonly property alias wizardAnimation: wizardAnimation
|
||||
readonly property alias challengeTxt: challengeTxt
|
||||
readonly property alias stepsListModel: stepsListModel
|
||||
|
||||
readonly property int animationDuration: 500
|
||||
|
||||
signal contactUnblocked(publicKey: string)
|
||||
signal contactBlocked(publicKey: string)
|
||||
|
@ -59,13 +93,66 @@ Rectangle {
|
|||
readonly property int subTitleElide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: wizardAnimation
|
||||
ScriptAction {
|
||||
id: step1
|
||||
property int loadingTime: 0
|
||||
Behavior on loadingTime { NumberAnimation { duration: animationDuration }}
|
||||
onLoadingTimeChanged: {
|
||||
if (isVerificationSent) {
|
||||
stepsListModel.setProperty(1, "loadingTime", step1.loadingTime);
|
||||
}
|
||||
}
|
||||
script: {
|
||||
step1.loadingTime = animationDuration;
|
||||
stepsListModel.setProperty(0, "loadingTime", step1.loadingTime);
|
||||
|
||||
if (isVerificationSent) {
|
||||
stepsListModel.setProperty(0, "stepCompleted", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
PauseAnimation {
|
||||
duration: animationDuration + 100
|
||||
}
|
||||
ScriptAction {
|
||||
id: step2
|
||||
property int loadingTime: 0
|
||||
Behavior on loadingTime { NumberAnimation { duration: animationDuration } }
|
||||
onLoadingTimeChanged: {
|
||||
if (isVerificationSent && !!verificationResponse) {
|
||||
stepsListModel.setProperty(2, "loadingTime", step2.loadingTime);
|
||||
}
|
||||
}
|
||||
script: {
|
||||
if (isVerificationSent && !!verificationChallenge) {
|
||||
step2.loadingTime = animationDuration;
|
||||
if (isVerificationSent && !!verificationResponse) {
|
||||
stepsListModel.setProperty(1, "stepCompleted", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PauseAnimation {
|
||||
duration: animationDuration + 100
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
if (verificationStatus === Constants.verificationStatus.trusted) {
|
||||
stepsListModel.setProperty(2, "stepCompleted", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: modalContent
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 16
|
||||
implicitHeight: 32
|
||||
}
|
||||
|
||||
ProfileHeader {
|
||||
|
@ -74,11 +161,23 @@ Rectangle {
|
|||
displayName: root.userDisplayName
|
||||
pubkey: root.userPublicKey
|
||||
icon: root.isCurrentUser ? root.profileStore.icon : root.userIcon
|
||||
trustStatus: root.userTrustStatus
|
||||
isContact: root.isAddedContact
|
||||
store: root.profileStore
|
||||
|
||||
displayNameVisible: false
|
||||
displayNamePlusIconsVisible: true
|
||||
pubkeyVisibleWithCopy: true
|
||||
pubkeyVisible: false
|
||||
imageSize: ProfileHeader.ImageSize.Middle
|
||||
editImageButtonVisible: root.isCurrentUser
|
||||
onEditClicked: {
|
||||
if(!isCurrentUser){
|
||||
nicknamePopup.open()
|
||||
} else {
|
||||
Global.openEditDisplayNamePopup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBanner {
|
||||
|
@ -88,26 +187,9 @@ Rectangle {
|
|||
statusText: qsTr("Blocked")
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 16
|
||||
}
|
||||
|
||||
StatusDescriptionListItem {
|
||||
Layout.fillWidth: true
|
||||
title: root.userIsEnsVerified ? qsTr("ENS username") : qsTr("Username")
|
||||
subTitle: root.userIsEnsVerified ? root.userEnsName : root.userName
|
||||
tooltip.text: qsTr("Copied to clipboard")
|
||||
tooltip.timeout: 1000
|
||||
icon.name: "copy"
|
||||
iconButton.onClicked: {
|
||||
globalUtils.copyToClipboard(subTitle)
|
||||
tooltip.open();
|
||||
}
|
||||
}
|
||||
|
||||
StatusDescriptionListItem {
|
||||
Layout.fillWidth: true
|
||||
visible: !showVerifyIdentitySection && !showVerificationPendingSection && !showIdentityVerified
|
||||
title: qsTr("Chat key")
|
||||
subTitle: Utils.getCompressedPk(root.userPublicKey)
|
||||
subTitleComponent.elide: Text.ElideMiddle
|
||||
|
@ -124,6 +206,7 @@ Rectangle {
|
|||
|
||||
StatusDescriptionListItem {
|
||||
Layout.fillWidth: true
|
||||
visible: !showVerifyIdentitySection && !showVerificationPendingSection && !showIdentityVerified
|
||||
title: qsTr("Share Profile URL")
|
||||
subTitle: {
|
||||
let user = ""
|
||||
|
@ -154,22 +237,164 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
StatusDescriptionListItem {
|
||||
Layout.fillWidth: true
|
||||
visible: !isCurrentUser
|
||||
title: qsTr("Chat settings")
|
||||
subTitle: qsTr("Nickname")
|
||||
value: userNickname ? userNickname : qsTr("None")
|
||||
sensor.enabled: true
|
||||
sensor.onClicked: {
|
||||
nicknamePopup.open()
|
||||
}
|
||||
ListModel {
|
||||
id: stepsListModel
|
||||
ListElement {description:"Send Request"; loadingTime: 0; stepCompleted: false}
|
||||
ListElement {description:"Receive Response"; loadingTime: 0; stepCompleted: false}
|
||||
ListElement {description:"Confirm Identity"; loadingTime: 0; stepCompleted: false}
|
||||
}
|
||||
|
||||
StatusWizardStepper {
|
||||
id: wizardStepper
|
||||
maxDuration: animationDuration
|
||||
visible: showVerifyIdentitySection || showVerificationPendingSection || showIdentityVerified || showIdentityVerifiedUntrustworthy
|
||||
width: parent.width
|
||||
stepsModel: stepsListModel
|
||||
}
|
||||
|
||||
Separator {
|
||||
visible: wizardStepper.visible
|
||||
implicitHeight: 32
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: confirmLbl
|
||||
visible: showIdentityVerified
|
||||
text: qsTr("You have confirmed %1's identity. From now on this verification emblem will always be displayed alongside %1's nickname.").arg(userIsEnsVerified ? userEnsName : userDisplayName)
|
||||
font.pixelSize: Style.current.additionalTextSize
|
||||
horizontalAlignment : Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 363
|
||||
wrapMode: Text.WordWrap
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: confirmUntrustworthyLbl
|
||||
visible: showIdentityVerifiedUntrustworthy
|
||||
text: qsTr("You have marked %1 as Untrustworthy. From now on this Untrustworthy emblem will always be displayed alongside %1's nickname.").arg(userIsEnsVerified ? userEnsName : userDisplayName)
|
||||
font.pixelSize: Style.current.additionalTextSize
|
||||
horizontalAlignment : Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 363
|
||||
wrapMode: Text.WordWrap
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: checkboxIcon.visible || dangerIcon.visible
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: visible ? 16 : 0
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
id: checkboxIcon
|
||||
visible: confirmLbl.visible
|
||||
icon.name: "checkbox"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
icon.color: Theme.palette.white
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
color: Theme.palette.primaryColor1
|
||||
width: 32
|
||||
height: 32
|
||||
}
|
||||
|
||||
StatusDescriptionListItem {
|
||||
Layout.fillWidth: true
|
||||
visible: !showVerifyIdentitySection && !showVerificationPendingSection && !showIdentityVerified
|
||||
title: root.userIsEnsVerified ? qsTr("ENS username") : qsTr("Username")
|
||||
subTitle: root.userIsEnsVerified ? root.userEnsName : root.userName
|
||||
tooltip.text: qsTr("Copied to clipboard")
|
||||
tooltip.timeout: 1000
|
||||
icon.name: "copy"
|
||||
iconButton.onClicked: {
|
||||
globalUtils.copyToClipboard(subTitle)
|
||||
tooltip.open();
|
||||
}
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
id: dangerIcon
|
||||
visible: confirmUntrustworthyLbl.visible
|
||||
icon.name: "tiny/subtract"
|
||||
icon.width: 5
|
||||
icon.height: 21
|
||||
icon.color: Theme.palette.white
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
color: Theme.palette.dangerColor1
|
||||
width: 32
|
||||
height: 32
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: checkboxIcon.visible || dangerIcon.visible
|
||||
height: visible ? 16 : 0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: challengeTxt
|
||||
visible: showVerifyIdentitySection
|
||||
charLimit: 280
|
||||
input.text: root.challenge
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: d.contentMargins
|
||||
Layout.leftMargin: d.contentMargins
|
||||
input.multiline: true
|
||||
input.implicitHeight: 152
|
||||
input.placeholderText: qsTr("Ask a question that only the real %1 will be able to answer e.g. a question about a shared experience, or ask Mark to enter a code or phrase you have sent to them via a different communication channel (phone, post, etc...).").arg(userIsEnsVerified ? userEnsName : userDisplayName)
|
||||
}
|
||||
|
||||
MessageView {
|
||||
id: challengeMessage
|
||||
visible: root.showVerificationPendingSection
|
||||
Layout.fillWidth: true
|
||||
isMessage: true
|
||||
shouldRepeatHeader: true
|
||||
messageTimestamp: root.verificationRequestedAt
|
||||
senderDisplayName: userProfile.name
|
||||
senderIcon: userProfile.icon
|
||||
message: root.verificationChallenge
|
||||
messageContentType: Constants.messageContentType.messageType
|
||||
placeholderMessage: true
|
||||
}
|
||||
|
||||
MessageView {
|
||||
id: responseMessage
|
||||
visible: root.showVerificationPendingSection && !!root.verificationResponse
|
||||
width: parent.width
|
||||
isMessage: true
|
||||
shouldRepeatHeader: true
|
||||
messageTimestamp: root.verificationRepliedAt
|
||||
senderDisplayName: root.verificationResponseDisplayName
|
||||
senderIcon: root.verificationResponseIcon
|
||||
message: root.verificationResponse
|
||||
messageContentType: Constants.messageContentType.messageType
|
||||
placeholderMessage: true
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: waitingForText.visible
|
||||
height: 32
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: waitingForText
|
||||
visible: showVerificationPendingSection && !verificationResponse
|
||||
text: qsTr("Waiting for %1's response...").arg(userIsEnsVerified ? userEnsName : userDisplayName)
|
||||
font.pixelSize: Style.current.additionalTextSize
|
||||
horizontalAlignment : Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 363
|
||||
wrapMode: Text.WordWrap
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
Item {
|
||||
height: 32
|
||||
Layout.fillWidth: true
|
||||
visible: !isCurrentUser
|
||||
implicitHeight: 16
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ Item {
|
|||
property int contentType
|
||||
property bool isChatBlocked: false
|
||||
property bool isActiveChannel: false
|
||||
property int senderTrustStatus
|
||||
|
||||
property int chatHorizontalPadding: Style.current.halfPadding
|
||||
property int chatVerticalPadding: 7
|
||||
|
@ -72,8 +73,9 @@ Item {
|
|||
+ (dateGroupLbl.visible ? dateGroupLbl.height + dateGroupLbl.anchors.topMargin : 0)
|
||||
|
||||
Connections {
|
||||
target: !!root.messageStore && root.messageStore.messageModule? root.messageStore.messageModule : null
|
||||
enabled: responseTo !== ""
|
||||
target: !!root.messageStore && root.messageStore.messageModule ?
|
||||
root.messageStore.messageModule : null
|
||||
enabled: !!root.messageStore && !!root.messageStore.messageModule && responseTo !== ""
|
||||
onRefreshAMessageUserRespondedTo: {
|
||||
if(msgId === messageId)
|
||||
chatReply.resetOriginalMessage()
|
||||
|
@ -383,11 +385,21 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
VerificationLabel {
|
||||
id: trustStatus
|
||||
anchors.left: chatName.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.bottom: chatName.bottom
|
||||
anchors.bottomMargin: 4
|
||||
visible: !root.amISender && chatName.visible
|
||||
trustStatus: senderTrustStatus
|
||||
}
|
||||
|
||||
ChatTimePanel {
|
||||
id: chatTime
|
||||
visible: !editModeOn && headerRepeatCondition
|
||||
anchors.verticalCenter: chatName.verticalCenter
|
||||
anchors.left: chatName.right
|
||||
anchors.left: trustStatus.right
|
||||
anchors.leftMargin: 4
|
||||
color: Style.current.secondaryText
|
||||
timestamp: messageTimestamp
|
||||
|
|
|
@ -41,6 +41,7 @@ Column {
|
|||
property string senderIcon: ""
|
||||
property bool amISender: false
|
||||
property bool senderIsAdded: false
|
||||
property int senderTrustStatus: Constants.trustStatus.unknown
|
||||
readonly property string senderIconToShow: {
|
||||
if ((!senderIsAdded &&
|
||||
Global.privacyModuleInst.profilePicturesVisibility !==
|
||||
|
@ -340,6 +341,7 @@ Column {
|
|||
isChatBlocked: root.isChatBlocked
|
||||
isActiveChannel: root.isActiveChannel
|
||||
emojiPopup: root.emojiPopup
|
||||
senderTrustStatus: root.senderTrustStatus
|
||||
|
||||
communityId: root.communityId
|
||||
stickersLoaded: root.stickersLoaded
|
||||
|
@ -353,7 +355,7 @@ Column {
|
|||
linkUrls: root.linkUrls
|
||||
isInPinnedPopup: root.isInPinnedPopup
|
||||
pinnedMessage: root.pinnedMessage
|
||||
canPin: messageStore.getNumberOfPinnedMessages() < Constants.maxNumberOfPins
|
||||
canPin: !!messageStore && messageStore.getNumberOfPinnedMessages() < Constants.maxNumberOfPins
|
||||
|
||||
transactionParams: root.transactionParams
|
||||
|
||||
|
|
|
@ -100,12 +100,21 @@ QtObject {
|
|||
readonly property int noOne: 3
|
||||
}
|
||||
|
||||
readonly property QtObject contactVerificationState: QtObject {
|
||||
readonly property int notMarked: 0
|
||||
readonly property int verified: 1
|
||||
readonly property QtObject trustStatus: QtObject {
|
||||
readonly property int unknown: 0
|
||||
readonly property int trusted: 1
|
||||
readonly property int untrustworthy: 2
|
||||
}
|
||||
|
||||
readonly property QtObject verificationStatus: QtObject {
|
||||
readonly property int unverified: 0
|
||||
readonly property int verifying: 1
|
||||
readonly property int verified: 2
|
||||
readonly property int declined: 3
|
||||
readonly property int canceled: 4
|
||||
readonly property int trusted: 5
|
||||
}
|
||||
|
||||
readonly property QtObject contactsPanelUsage: QtObject {
|
||||
readonly property int unknownPosition: -1
|
||||
readonly property int mutualContacts: 0
|
||||
|
|
|
@ -28,6 +28,7 @@ QtObject {
|
|||
signal openProfilePopupRequested(string publicKey, var parentPopup, string state)
|
||||
signal openChangeProfilePicPopup()
|
||||
signal displayToastMessage(string title, string subTitle, string icon, bool loading, int ephNotifType, string url)
|
||||
signal openEditDisplayNamePopup()
|
||||
|
||||
function openProfilePopup(publicKey, parentPopup, state = "") {
|
||||
openProfilePopupRequested(publicKey, parentPopup, state);
|
||||
|
|
|
@ -640,7 +640,9 @@ QtObject {
|
|||
isBlocked: false,
|
||||
requestReceived: false,
|
||||
isSyncing: false,
|
||||
removed: false
|
||||
removed: false,
|
||||
trustStatus: Constants.trustStatus.unknown,
|
||||
verificationStatus: Constants.verificationStatus.unverified
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7ad0057003d968423b7ee482502cbf0e0b6716d4
|
||||
Subproject commit 0322ac497bf9e4852b99780f4ff08377a8c3f267
|
Loading…
Reference in New Issue