feat(sync): add a fallback mechanism when the pairing does't work (#15820)
Fixes #15750 When the pairing fails, the UI now let's the user use the seed phrase instead. When they do, a call is send to the original device and both instances will show an AC notif. When the original device accepts the pairing, the call is made to pair and sync the devices and the AC notifs get deleted
This commit is contained in:
parent
4133afb676
commit
252061d8e8
|
@ -7,6 +7,7 @@ import ../../../../app_service/service/contacts/service as contacts_service
|
||||||
import ../../../../app_service/service/message/service as message_service
|
import ../../../../app_service/service/message/service as message_service
|
||||||
import ../../../../app_service/service/community/service as community_service
|
import ../../../../app_service/service/community/service as community_service
|
||||||
import ../../../../app_service/service/chat/service as chat_service
|
import ../../../../app_service/service/chat/service as chat_service
|
||||||
|
import ../../../../app_service/service/devices/service as devices_service
|
||||||
|
|
||||||
type
|
type
|
||||||
Controller* = ref object of RootObj
|
Controller* = ref object of RootObj
|
||||||
|
@ -17,6 +18,7 @@ type
|
||||||
messageService: message_service.Service
|
messageService: message_service.Service
|
||||||
chatService: chat_service.Service
|
chatService: chat_service.Service
|
||||||
communityService: community_service.Service
|
communityService: community_service.Service
|
||||||
|
devicesService: devices_service.Service
|
||||||
|
|
||||||
proc newController*(
|
proc newController*(
|
||||||
delegate: io_interface.AccessInterface,
|
delegate: io_interface.AccessInterface,
|
||||||
|
@ -26,6 +28,7 @@ proc newController*(
|
||||||
messageService: message_service.Service,
|
messageService: message_service.Service,
|
||||||
chatService: chat_service.Service,
|
chatService: chat_service.Service,
|
||||||
communityService: community_service.Service,
|
communityService: community_service.Service,
|
||||||
|
devicesService: devices_service.Service,
|
||||||
): Controller =
|
): Controller =
|
||||||
result = Controller()
|
result = Controller()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
|
@ -35,6 +38,7 @@ proc newController*(
|
||||||
result.messageService = messageService
|
result.messageService = messageService
|
||||||
result.chatService = chatService
|
result.chatService = chatService
|
||||||
result.communityService = communityService
|
result.communityService = communityService
|
||||||
|
result.devicesService = devicesService
|
||||||
|
|
||||||
proc delete*(self: Controller) =
|
proc delete*(self: Controller) =
|
||||||
discard
|
discard
|
||||||
|
@ -162,3 +166,6 @@ proc setActivityCenterReadType*(self: Controller, readType: ActivityCenterReadTy
|
||||||
|
|
||||||
proc getActivityCenterReadType*(self: Controller): ActivityCenterReadType =
|
proc getActivityCenterReadType*(self: Controller): ActivityCenterReadType =
|
||||||
return self.activityCenterService.getActivityCenterReadType()
|
return self.activityCenterService.getActivityCenterReadType()
|
||||||
|
|
||||||
|
proc enableInstallationAndSync*(self: Controller, installationId: string) =
|
||||||
|
self.devicesService.enableInstallationAndSync(installationId)
|
||||||
|
|
|
@ -110,3 +110,6 @@ method getActivityCenterReadType*(self: AccessInterface): int {.base.} =
|
||||||
|
|
||||||
method setActivityGroupCounters*(self: AccessInterface, counters: Table[ActivityCenterGroup, int]) {.base.} =
|
method setActivityGroupCounters*(self: AccessInterface, counters: Table[ActivityCenterGroup, int]) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method enableInstallationAndSync*(self: AccessInterface, installationId: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
|
@ -25,6 +25,7 @@ type Item* = ref object
|
||||||
repliedMessageItem: MessageItem
|
repliedMessageItem: MessageItem
|
||||||
chatType: ChatType
|
chatType: ChatType
|
||||||
tokenDataItem: TokenDataItem
|
tokenDataItem: TokenDataItem
|
||||||
|
installationId: string
|
||||||
|
|
||||||
proc initItem*(
|
proc initItem*(
|
||||||
id: string,
|
id: string,
|
||||||
|
@ -43,7 +44,8 @@ proc initItem*(
|
||||||
messageItem: MessageItem,
|
messageItem: MessageItem,
|
||||||
repliedMessageItem: MessageItem,
|
repliedMessageItem: MessageItem,
|
||||||
chatType: ChatType,
|
chatType: ChatType,
|
||||||
tokenDataItem: TokenDataItem
|
tokenDataItem: TokenDataItem,
|
||||||
|
installationId: string
|
||||||
): Item =
|
): Item =
|
||||||
result = Item()
|
result = Item()
|
||||||
result.id = id
|
result.id = id
|
||||||
|
@ -63,6 +65,7 @@ proc initItem*(
|
||||||
result.repliedMessageItem = repliedMessageItem
|
result.repliedMessageItem = repliedMessageItem
|
||||||
result.chatType = chatType
|
result.chatType = chatType
|
||||||
result.tokenDataItem = tokenDataItem
|
result.tokenDataItem = tokenDataItem
|
||||||
|
result.installationId = installationId
|
||||||
|
|
||||||
proc `$`*(self: Item): string =
|
proc `$`*(self: Item): string =
|
||||||
result = fmt"""activity_center/Item(
|
result = fmt"""activity_center/Item(
|
||||||
|
@ -74,6 +77,7 @@ proc `$`*(self: Item): string =
|
||||||
verificationStatus: {$self.verificationStatus.int},
|
verificationStatus: {$self.verificationStatus.int},
|
||||||
sectionId: {$self.sectionId},
|
sectionId: {$self.sectionId},
|
||||||
author: {$self.author},
|
author: {$self.author},
|
||||||
|
installationId: {$self.installationId},
|
||||||
notificationType: {$self.notificationType.int},
|
notificationType: {$self.notificationType.int},
|
||||||
timestamp: {$self.timestamp},
|
timestamp: {$self.timestamp},
|
||||||
read: {$self.read},
|
read: {$self.read},
|
||||||
|
@ -93,6 +97,9 @@ proc name*(self: Item): string =
|
||||||
proc author*(self: Item): string =
|
proc author*(self: Item): string =
|
||||||
return self.author
|
return self.author
|
||||||
|
|
||||||
|
proc installationId*(self: Item): string =
|
||||||
|
return self.installationId
|
||||||
|
|
||||||
proc chatId*(self: Item): string =
|
proc chatId*(self: Item): string =
|
||||||
return self.chatId
|
return self.chatId
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ type
|
||||||
RepliedMessage
|
RepliedMessage
|
||||||
ChatType
|
ChatType
|
||||||
TokenData
|
TokenData
|
||||||
|
InstallationId
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
|
@ -89,6 +90,7 @@ QtObject:
|
||||||
of NotifRoles.RepliedMessage: result = newQVariant(activityNotificationItem.repliedMessageItem)
|
of NotifRoles.RepliedMessage: result = newQVariant(activityNotificationItem.repliedMessageItem)
|
||||||
of NotifRoles.ChatType: result = newQVariant(activityNotificationItem.chatType.int)
|
of NotifRoles.ChatType: result = newQVariant(activityNotificationItem.chatType.int)
|
||||||
of NotifRoles.TokenData: result = newQVariant(activityNotificationItem.tokenDataItem)
|
of NotifRoles.TokenData: result = newQVariant(activityNotificationItem.tokenDataItem)
|
||||||
|
of NotifRoles.InstallationId: result = newQVariant(activityNotificationItem.installationId)
|
||||||
|
|
||||||
method roleNames(self: Model): Table[int, string] =
|
method roleNames(self: Model): Table[int, string] =
|
||||||
{
|
{
|
||||||
|
@ -109,7 +111,8 @@ QtObject:
|
||||||
NotifRoles.Accepted.int: "accepted",
|
NotifRoles.Accepted.int: "accepted",
|
||||||
NotifRoles.RepliedMessage.int: "repliedMessage",
|
NotifRoles.RepliedMessage.int: "repliedMessage",
|
||||||
NotifRoles.ChatType.int: "chatType",
|
NotifRoles.ChatType.int: "chatType",
|
||||||
NotifRoles.TokenData.int: "tokenData"
|
NotifRoles.TokenData.int: "tokenData",
|
||||||
|
NotifRoles.InstallationId.int: "installationId",
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
proc findNotificationIndex(self: Model, notificationId: string): int =
|
proc findNotificationIndex(self: Model, notificationId: string): int =
|
||||||
|
|
|
@ -14,6 +14,7 @@ import ../../../../app_service/service/contacts/service as contacts_service
|
||||||
import ../../../../app_service/service/message/service as message_service
|
import ../../../../app_service/service/message/service as message_service
|
||||||
import ../../../../app_service/service/chat/service as chat_service
|
import ../../../../app_service/service/chat/service as chat_service
|
||||||
import ../../../../app_service/service/community/service as community_service
|
import ../../../../app_service/service/community/service as community_service
|
||||||
|
import ../../../../app_service/service/devices/service as devices_service
|
||||||
|
|
||||||
export io_interface
|
export io_interface
|
||||||
|
|
||||||
|
@ -33,7 +34,8 @@ proc newModule*(
|
||||||
contactsService: contacts_service.Service,
|
contactsService: contacts_service.Service,
|
||||||
messageService: message_service.Service,
|
messageService: message_service.Service,
|
||||||
chatService: chat_service.Service,
|
chatService: chat_service.Service,
|
||||||
communityService: community_service.Service
|
communityService: community_service.Service,
|
||||||
|
devicesService: devices_service.Service,
|
||||||
): Module =
|
): Module =
|
||||||
result = Module()
|
result = Module()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
|
@ -46,7 +48,8 @@ proc newModule*(
|
||||||
contactsService,
|
contactsService,
|
||||||
messageService,
|
messageService,
|
||||||
chatService,
|
chatService,
|
||||||
communityService
|
communityService,
|
||||||
|
devicesService,
|
||||||
)
|
)
|
||||||
result.moduleLoaded = false
|
result.moduleLoaded = false
|
||||||
|
|
||||||
|
@ -216,7 +219,8 @@ method convertToItems*(
|
||||||
messageItem,
|
messageItem,
|
||||||
repliedMessageItem,
|
repliedMessageItem,
|
||||||
chatDetails.chatType,
|
chatDetails.chatType,
|
||||||
tokenDataItem
|
tokenDataItem,
|
||||||
|
notification.installationId,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -323,3 +327,6 @@ method getActivityCenterReadType*(self: Module): int =
|
||||||
|
|
||||||
method setActivityGroupCounters*(self: Module, counters: Table[ActivityCenterGroup, int]) =
|
method setActivityGroupCounters*(self: Module, counters: Table[ActivityCenterGroup, int]) =
|
||||||
self.view.setActivityGroupCounters(counters)
|
self.view.setActivityGroupCounters(counters)
|
||||||
|
|
||||||
|
method enableInstallationAndSync*(self: Module, installationId: string) =
|
||||||
|
self.controller.enableInstallationAndSync(installationId)
|
||||||
|
|
|
@ -211,3 +211,6 @@ QtObject:
|
||||||
proc setActivityGroupCounters*(self: View, counters: Table[ActivityCenterGroup, int]) =
|
proc setActivityGroupCounters*(self: View, counters: Table[ActivityCenterGroup, int]) =
|
||||||
self.groupCounters = counters
|
self.groupCounters = counters
|
||||||
self.groupCountersChanged()
|
self.groupCountersChanged()
|
||||||
|
|
||||||
|
proc enableInstallationAndSync*(self: View, installationId: string) {.slot.} =
|
||||||
|
self.delegate.enableInstallationAndSync(installationId)
|
||||||
|
|
|
@ -225,7 +225,7 @@ proc newModule*[T](
|
||||||
networkService, tokenService)
|
networkService, tokenService)
|
||||||
result.gifsModule = gifs_module.newModule(result, events, gifService)
|
result.gifsModule = gifs_module.newModule(result, events, gifService)
|
||||||
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
|
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
|
||||||
messageService, chatService, communityService)
|
messageService, chatService, communityService, devicesService)
|
||||||
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService, communityTokensService,
|
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService, communityTokensService,
|
||||||
networkService, transactionService, tokenService, chatService, walletAccountService, keycardService)
|
networkService, transactionService, tokenService, chatService, walletAccountService, keycardService)
|
||||||
result.appSearchModule = app_search_module.newModule(result, events, contactsService, chatService, communityService,
|
result.appSearchModule = app_search_module.newModule(result, events, contactsService, chatService, communityService,
|
||||||
|
@ -468,6 +468,9 @@ proc connectForNotificationsOnly[T](self: Module[T]) =
|
||||||
self.view.showToastTransactionSendingComplete(args.chainId, args.transactionHash, args.data, args.success,
|
self.view.showToastTransactionSendingComplete(args.chainId, args.transactionHash, args.data, args.success,
|
||||||
ord(args.txType), args.fromAddress, args.toAddress, args.fromTokenKey, args.fromAmount, args.toTokenKey, args.toAmount)
|
ord(args.txType), args.fromAddress, args.toAddress, args.fromTokenKey, args.fromAmount, args.toTokenKey, args.toAmount)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_PAIRING_FALLBACK_COMPLETED) do(e:Args):
|
||||||
|
self.view.showToastPairingFallbackCompleted()
|
||||||
|
|
||||||
method load*[T](
|
method load*[T](
|
||||||
self: Module[T],
|
self: Module[T],
|
||||||
events: EventEmitter,
|
events: EventEmitter,
|
||||||
|
|
|
@ -344,6 +344,7 @@ QtObject:
|
||||||
txType: int, fromAddr: string, toAddr: string, fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string) {.signal.}
|
txType: int, fromAddr: string, toAddr: string, fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string) {.signal.}
|
||||||
proc showToastTransactionSendingComplete*(self: View, chainId: int, txHash: string, data: string, success: bool,
|
proc showToastTransactionSendingComplete*(self: View, chainId: int, txHash: string, data: string, success: bool,
|
||||||
txType: int, fromAddr: string, toAddr: string, fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string) {.signal.}
|
txType: int, fromAddr: string, toAddr: string, fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string) {.signal.}
|
||||||
|
proc showToastPairingFallbackCompleted*(self: View) {.signal.}
|
||||||
|
|
||||||
## Used in test env only, for testing keycard flows
|
## Used in test env only, for testing keycard flows
|
||||||
proc registerMockedKeycard*(self: View, cardIndex: int, readerState: int, keycardState: int,
|
proc registerMockedKeycard*(self: View, cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
|
|
@ -137,10 +137,6 @@ proc init*(self: Controller) =
|
||||||
self.delegate.emitLogOut()
|
self.delegate.emitLogOut()
|
||||||
self.connectionIds.add(handlerId)
|
self.connectionIds.add(handlerId)
|
||||||
|
|
||||||
handlerId = self.events.onWithUUID(SignalType.NodeReady.event) do(e:Args):
|
|
||||||
self.events.emit("nodeReady", Args())
|
|
||||||
self.connectionIds.add(handlerId)
|
|
||||||
|
|
||||||
handlerId = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
|
handlerId = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
|
||||||
let args = KeycardLibArgs(e)
|
let args = KeycardLibArgs(e)
|
||||||
self.delegate.onKeycardResponse(args.flowType, args.flowEvent)
|
self.delegate.onKeycardResponse(args.flowType, args.flowEvent)
|
||||||
|
@ -642,3 +638,6 @@ proc notificationsNeedsEnable*(self: Controller): bool =
|
||||||
|
|
||||||
proc proceedToApp*(self: Controller) =
|
proc proceedToApp*(self: Controller) =
|
||||||
self.delegate.finishAppLoading()
|
self.delegate.finishAppLoading()
|
||||||
|
|
||||||
|
proc finishPairingThroughSeedPhraseProcess*(self: Controller, installationId: string) =
|
||||||
|
self.devicesService.finishPairingThroughSeedPhraseProcess(installationId)
|
||||||
|
|
|
@ -10,3 +10,9 @@ proc delete*(self: SyncDeviceResultState) =
|
||||||
|
|
||||||
method executePrimaryCommand*(self: SyncDeviceResultState, controller: Controller) =
|
method executePrimaryCommand*(self: SyncDeviceResultState, controller: Controller) =
|
||||||
controller.loginLocalPairingAccount()
|
controller.loginLocalPairingAccount()
|
||||||
|
|
||||||
|
method getNextSecondaryState*(self: SyncDeviceResultState, controller: Controller): State =
|
||||||
|
return createState(StateType.UserProfileEnterSeedPhrase, FlowType.FirstRunOldUserImportSeedPhrase, self)
|
||||||
|
|
||||||
|
method getNextTertiaryState*(self: SyncDeviceResultState, controller: Controller): State =
|
||||||
|
return createState(StateType.SyncDeviceWithSyncCode, FlowType.FirstRunOldUserSyncCode, self)
|
||||||
|
|
|
@ -325,6 +325,8 @@ method finishAppLoading*[T](self: Module[T]) =
|
||||||
|
|
||||||
method checkFetchingStatusAndProceed*[T](self: Module[T]) =
|
method checkFetchingStatusAndProceed*[T](self: Module[T]) =
|
||||||
if self.view.fetchingDataModel().isEntityLoaded(FetchingFromWakuProfile):
|
if self.view.fetchingDataModel().isEntityLoaded(FetchingFromWakuProfile):
|
||||||
|
if self.view.getLocalPairingInstallationId() != "":
|
||||||
|
self.controller.finishPairingThroughSeedPhraseProcess(self.view.getLocalPairingInstallationId())
|
||||||
self.finishAppLoading()
|
self.finishAppLoading()
|
||||||
return
|
return
|
||||||
let currStateObj = self.view.currentStartupStateObj()
|
let currStateObj = self.view.currentStartupStateObj()
|
||||||
|
@ -530,6 +532,8 @@ method addToKeycardUidPairsToCheckForAChangeAfterLogin*[T](self: Module[T], oldK
|
||||||
|
|
||||||
method removeAllKeycardUidPairsForCheckingForAChangeAfterLogin*[T](self: Module[T]) =
|
method removeAllKeycardUidPairsForCheckingForAChangeAfterLogin*[T](self: Module[T]) =
|
||||||
self.delegate.removeAllKeycardUidPairsForCheckingForAChangeAfterLogin()
|
self.delegate.removeAllKeycardUidPairsForCheckingForAChangeAfterLogin()
|
||||||
|
if self.view.getLocalPairingInstallationId() != "":
|
||||||
|
self.controller.finishPairingThroughSeedPhraseProcess(self.view.getLocalPairingInstallationId())
|
||||||
|
|
||||||
method getConnectionString*[T](self: Module[T]): string =
|
method getConnectionString*[T](self: Module[T]): string =
|
||||||
return self.controller.getConnectionString()
|
return self.controller.getConnectionString()
|
||||||
|
|
|
@ -32,6 +32,8 @@ type ActivityCenterNotificationType* {.pure.}= enum
|
||||||
FirstCommunityTokenReceived = 20
|
FirstCommunityTokenReceived = 20
|
||||||
CommunityBanned = 21
|
CommunityBanned = 21
|
||||||
CommunityUnbanned = 22
|
CommunityUnbanned = 22
|
||||||
|
NewInstallationReceived = 23
|
||||||
|
NewInstallationCreated = 24
|
||||||
|
|
||||||
type ActivityCenterGroup* {.pure.}= enum
|
type ActivityCenterGroup* {.pure.}= enum
|
||||||
All = 0,
|
All = 0,
|
||||||
|
@ -65,6 +67,7 @@ type ActivityCenterNotificationDto* = ref object of RootObj
|
||||||
verificationStatus*: VerificationStatus
|
verificationStatus*: VerificationStatus
|
||||||
name*: string
|
name*: string
|
||||||
author*: string
|
author*: string
|
||||||
|
installationId*: string
|
||||||
notificationType*: ActivityCenterNotificationType
|
notificationType*: ActivityCenterNotificationType
|
||||||
message*: MessageDto
|
message*: MessageDto
|
||||||
replyMessage*: MessageDto
|
replyMessage*: MessageDto
|
||||||
|
@ -84,6 +87,7 @@ proc `$`*(self: ActivityCenterNotificationDto): string =
|
||||||
membershipStatus: {self.membershipStatus},
|
membershipStatus: {self.membershipStatus},
|
||||||
contactVerificationStatus: {self.verificationStatus},
|
contactVerificationStatus: {self.verificationStatus},
|
||||||
author: {self.author},
|
author: {self.author},
|
||||||
|
installationId: {self.installationId},
|
||||||
notificationType: {$self.notificationType.int},
|
notificationType: {$self.notificationType.int},
|
||||||
timestamp: {self.timestamp},
|
timestamp: {self.timestamp},
|
||||||
read: {$self.read},
|
read: {$self.read},
|
||||||
|
@ -117,6 +121,7 @@ proc toActivityCenterNotificationDto*(jsonObj: JsonNode): ActivityCenterNotifica
|
||||||
result.verificationStatus = VerificationStatus(verificationStatusInt)
|
result.verificationStatus = VerificationStatus(verificationStatusInt)
|
||||||
|
|
||||||
discard jsonObj.getProp("author", result.author)
|
discard jsonObj.getProp("author", result.author)
|
||||||
|
discard jsonObj.getProp("installationId", result.installationId)
|
||||||
|
|
||||||
result.notificationType = ActivityCenterNotificationType.NoType
|
result.notificationType = ActivityCenterNotificationType.NoType
|
||||||
var notificationTypeInt: int
|
var notificationTypeInt: int
|
||||||
|
@ -179,7 +184,9 @@ proc activityCenterNotificationTypesByGroup*(group: ActivityCenterGroup) : seq[i
|
||||||
ActivityCenterNotificationType.CommunityTokenReceived.int,
|
ActivityCenterNotificationType.CommunityTokenReceived.int,
|
||||||
ActivityCenterNotificationType.FirstCommunityTokenReceived.int,
|
ActivityCenterNotificationType.FirstCommunityTokenReceived.int,
|
||||||
ActivityCenterNotificationType.CommunityBanned.int,
|
ActivityCenterNotificationType.CommunityBanned.int,
|
||||||
ActivityCenterNotificationType.CommunityUnbanned.int
|
ActivityCenterNotificationType.CommunityUnbanned.int,
|
||||||
|
ActivityCenterNotificationType.NewInstallationReceived.int,
|
||||||
|
ActivityCenterNotificationType.NewInstallationCreated.int,
|
||||||
]
|
]
|
||||||
of ActivityCenterGroup.Mentions:
|
of ActivityCenterGroup.Mentions:
|
||||||
return @[ActivityCenterNotificationType.Mention.int]
|
return @[ActivityCenterNotificationType.Mention.int]
|
||||||
|
|
|
@ -88,7 +88,7 @@ QtObject:
|
||||||
result.chatService = chatService
|
result.chatService = chatService
|
||||||
|
|
||||||
proc handleNewNotificationsLoaded(self: Service, activityCenterNotifications: seq[ActivityCenterNotificationDto]) =
|
proc handleNewNotificationsLoaded(self: Service, activityCenterNotifications: seq[ActivityCenterNotificationDto]) =
|
||||||
# For now status-go notify about every notification update regardless active group so we need filter manulay on the desktop side
|
# For now status-go notify about every notification update regardless active group so we need filter manually on the desktop side
|
||||||
let groupTypes = activityCenterNotificationTypesByGroup(self.activeGroup)
|
let groupTypes = activityCenterNotificationTypesByGroup(self.activeGroup)
|
||||||
let filteredNotifications = filter(activityCenterNotifications, proc(notification: ActivityCenterNotificationDto): bool =
|
let filteredNotifications = filter(activityCenterNotifications, proc(notification: ActivityCenterNotificationDto): bool =
|
||||||
return (self.readType == ActivityCenterReadType.All or not notification.read) and groupTypes.contains(notification.notificationType.int)
|
return (self.readType == ActivityCenterReadType.All or not notification.read) and groupTypes.contains(notification.notificationType.int)
|
||||||
|
|
|
@ -55,6 +55,8 @@ proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
|
||||||
self.chatKey = data.accountData.chatKey
|
self.chatKey = data.accountData.chatKey
|
||||||
of EventReceivedInstallation:
|
of EventReceivedInstallation:
|
||||||
self.installation = data.installation
|
self.installation = data.installation
|
||||||
|
of EventCompletedAndNodeReady:
|
||||||
|
self.installation = data.installation
|
||||||
of EventReceivedKeystoreFiles:
|
of EventReceivedKeystoreFiles:
|
||||||
self.transferredKeypairs = data.transferredKeypairs
|
self.transferredKeypairs = data.transferredKeypairs
|
||||||
of EventConnectionError:
|
of EventConnectionError:
|
||||||
|
|
|
@ -9,6 +9,7 @@ import ./dto/local_pairing_status
|
||||||
import app_service/service/settings/service as settings_service
|
import app_service/service/settings/service as settings_service
|
||||||
import app_service/service/accounts/service as accounts_service
|
import app_service/service/accounts/service as accounts_service
|
||||||
import app_service/service/wallet_account/service as wallet_account_service
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
|
import ../../common/activity_center
|
||||||
|
|
||||||
import app/global/global_singleton
|
import app/global/global_singleton
|
||||||
import app/core/[main]
|
import app/core/[main]
|
||||||
|
@ -49,6 +50,7 @@ const SIGNAL_DEVICES_LOADED* = "devicesLoaded"
|
||||||
const SIGNAL_ERROR_LOADING_DEVICES* = "devicesErrorLoading"
|
const SIGNAL_ERROR_LOADING_DEVICES* = "devicesErrorLoading"
|
||||||
const SIGNAL_LOCAL_PAIRING_STATUS_UPDATE* = "localPairingStatusUpdate"
|
const SIGNAL_LOCAL_PAIRING_STATUS_UPDATE* = "localPairingStatusUpdate"
|
||||||
const SIGNAL_INSTALLATION_NAME_UPDATED* = "installationNameUpdated"
|
const SIGNAL_INSTALLATION_NAME_UPDATED* = "installationNameUpdated"
|
||||||
|
const SIGNAL_PAIRING_FALLBACK_COMPLETED* = "pairingFallbackCompleted"
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type Service* = ref object of QObject
|
type Service* = ref object of QObject
|
||||||
|
@ -174,14 +176,23 @@ QtObject:
|
||||||
#
|
#
|
||||||
|
|
||||||
proc inputConnectionStringForBootstrappingFinished*(self: Service, responseJson: string) {.slot.} =
|
proc inputConnectionStringForBootstrappingFinished*(self: Service, responseJson: string) {.slot.} =
|
||||||
|
var currentError = ""
|
||||||
|
if self.localPairingStatus.state == LocalPairingState.Error:
|
||||||
|
# The error was already returned by an event, keep it to reuse
|
||||||
|
currentError = self.localPairingStatus.error
|
||||||
|
|
||||||
let response = responseJson.parseJson
|
let response = responseJson.parseJson
|
||||||
let errorDescription = response["error"].getStr
|
let errorDescription = response["error"].getStr
|
||||||
if len(errorDescription) == 0:
|
if len(errorDescription) == 0:
|
||||||
|
var installation = InstallationDto()
|
||||||
|
installation.id = response["installationId"].getStr # Set the installation with the ID (only info we have for now)
|
||||||
let data = LocalPairingEventArgs(
|
let data = LocalPairingEventArgs(
|
||||||
|
installation: installation,
|
||||||
eventType: EventCompletedAndNodeReady,
|
eventType: EventCompletedAndNodeReady,
|
||||||
action: ActionPairingInstallation,
|
action: ActionPairingInstallation,
|
||||||
accountData: LocalPairingAccountData(),
|
accountData: LocalPairingAccountData(),
|
||||||
error: "")
|
error: currentError,
|
||||||
|
)
|
||||||
self.updateLocalPairingStatus(data)
|
self.updateLocalPairingStatus(data)
|
||||||
return
|
return
|
||||||
error "failed to start bootstrapping device", errorDescription
|
error "failed to start bootstrapping device", errorDescription
|
||||||
|
@ -189,7 +200,8 @@ QtObject:
|
||||||
eventType: EventConnectionError,
|
eventType: EventConnectionError,
|
||||||
action: ActionUnknown,
|
action: ActionUnknown,
|
||||||
accountData: LocalPairingAccountData(),
|
accountData: LocalPairingAccountData(),
|
||||||
error: errorDescription)
|
error: errorDescription,
|
||||||
|
)
|
||||||
self.updateLocalPairingStatus(data)
|
self.updateLocalPairingStatus(data)
|
||||||
|
|
||||||
proc validateConnectionString*(self: Service, connectionString: string): string =
|
proc validateConnectionString*(self: Service, connectionString: string): string =
|
||||||
|
@ -360,3 +372,24 @@ QtObject:
|
||||||
configJSON: $configJSON
|
configJSON: $configJSON
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
|
proc finishPairingThroughSeedPhraseProcess*(self: Service, installationId: string) =
|
||||||
|
try:
|
||||||
|
let response = status_installations.finishPairingThroughSeedPhraseProcess(installationId)
|
||||||
|
if response.error != nil:
|
||||||
|
let e = Json.decode($response.error, RpcError)
|
||||||
|
raise newException(CatchableError, e.message)
|
||||||
|
except Exception as e:
|
||||||
|
error "error: ", desription = e.msg
|
||||||
|
|
||||||
|
proc enableInstallationAndSync*(self: Service, installationId: string) =
|
||||||
|
try:
|
||||||
|
let response = status_installations.enableInstallationAndSync(installationId)
|
||||||
|
if response.error != nil:
|
||||||
|
let e = Json.decode($response.error, RpcError)
|
||||||
|
raise newException(CatchableError, e.message)
|
||||||
|
# Parse AC notif
|
||||||
|
checkAndEmitACNotificationsFromResponse(self.events, response.result{"activityCenterNotifications"})
|
||||||
|
self.events.emit(SIGNAL_PAIRING_FALLBACK_COMPLETED, Args())
|
||||||
|
except Exception as e:
|
||||||
|
error "error: ", desription = e.msg
|
||||||
|
|
|
@ -35,3 +35,15 @@ proc enableInstallation*(installationId: string): RpcResponse[JsonNode] =
|
||||||
proc disableInstallation*(installationId: string): RpcResponse[JsonNode] =
|
proc disableInstallation*(installationId: string): RpcResponse[JsonNode] =
|
||||||
let payload = %* [installationId]
|
let payload = %* [installationId]
|
||||||
result = callPrivateRPC("disableInstallation".prefix, payload)
|
result = callPrivateRPC("disableInstallation".prefix, payload)
|
||||||
|
|
||||||
|
proc finishPairingThroughSeedPhraseProcess*(installationId: string): RpcResponse[JsonNode] =
|
||||||
|
let payload = %* [{
|
||||||
|
"installationId": installationId,
|
||||||
|
}]
|
||||||
|
result = callPrivateRPC("enableInstallationAndPair".prefix, payload)
|
||||||
|
|
||||||
|
proc enableInstallationAndSync*(installationId: string): RpcResponse[JsonNode] =
|
||||||
|
let payload = %* [{
|
||||||
|
"installationId": installationId,
|
||||||
|
}]
|
||||||
|
result = callPrivateRPC("enableInstallationAndSync".prefix, payload)
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
|
||||||
|
import mainui.activitycenter.views 1.0
|
||||||
|
import mainui.activitycenter.stores 1.0
|
||||||
|
|
||||||
|
import Storybook 1.0
|
||||||
|
|
||||||
|
SplitView {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
orientation: Qt.Vertical
|
||||||
|
|
||||||
|
Logs { id: logs }
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: notificationMock
|
||||||
|
|
||||||
|
property string id: "1"
|
||||||
|
property string communityId: "1"
|
||||||
|
property string sectionId: "1"
|
||||||
|
property int notificationType: 1
|
||||||
|
property int timestamp: Date.now()
|
||||||
|
property int previousTimestamp: 0
|
||||||
|
property bool read: false
|
||||||
|
property bool dismissed: false
|
||||||
|
property bool accepted: false
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
SplitView.fillHeight: true
|
||||||
|
SplitView.fillWidth: true
|
||||||
|
|
||||||
|
ActivityNotificationNewDevice {
|
||||||
|
id: notification
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - 50
|
||||||
|
height: implicitHeight
|
||||||
|
|
||||||
|
type: ActivityNotificationNewDevice.InstallationType.Received
|
||||||
|
accountName: "bob.eth"
|
||||||
|
store: undefined
|
||||||
|
notification: notificationMock
|
||||||
|
|
||||||
|
onMoreDetailsClicked: logs.logEvent("ActivityNotificationNewDevice::onMoreDetailsClicked")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LogsAndControlsPanel {
|
||||||
|
SplitView.minimumHeight: 100
|
||||||
|
SplitView.preferredHeight: 160
|
||||||
|
|
||||||
|
logsView.logText: logs.logText
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Row {
|
||||||
|
RadioButton {
|
||||||
|
text: "Received"
|
||||||
|
checked: true
|
||||||
|
onCheckedChanged: if(checked) notification.type = ActivityNotificationNewDevice.InstallationType.Received
|
||||||
|
}
|
||||||
|
|
||||||
|
RadioButton {
|
||||||
|
text: "Created"
|
||||||
|
onCheckedChanged: if(checked) notification.type = ActivityNotificationNewDevice.InstallationType.Created
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// category: Activity Center
|
||||||
|
// https://www.figma.com/design/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=40765-355811&m=dev
|
|
@ -304,6 +304,8 @@ QtObject {
|
||||||
|
|
||||||
readonly property int loginType: getLoginType()
|
readonly property int loginType: getLoginType()
|
||||||
|
|
||||||
|
property string name: userProfileInst.name
|
||||||
|
|
||||||
property StickersStore stickersStore: StickersStore {
|
property StickersStore stickersStore: StickersStore {
|
||||||
stickersModule: stickersModuleInst
|
stickersModule: stickersModuleInst
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,14 @@ Item {
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
readonly property bool finished: startupStore.localPairingState === Constants.LocalPairingState.Finished
|
readonly property bool finished: startupStore.localPairingState === Constants.LocalPairingState.Finished
|
||||||
|
readonly property bool pairingFailed: startupStore.localPairingState === Constants.LocalPairingState.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: layout
|
id: layout
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: 48
|
spacing: 24
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -55,6 +56,20 @@ Item {
|
||||||
installationDeviceType: startupStore.localPairingInstallationDeviceType
|
installationDeviceType: startupStore.localPairingInstallationDeviceType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
visible: d.pairingFailed
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("Use recovery phrase")
|
||||||
|
onClicked: root.startupStore.doSecondaryAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusFlatButton {
|
||||||
|
visible: d.pairingFailed
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("Try again")
|
||||||
|
onClicked: root.startupStore.doTertiaryAction()
|
||||||
|
}
|
||||||
|
|
||||||
StatusButton {
|
StatusButton {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
text: qsTr("Sign in")
|
text: qsTr("Sign in")
|
||||||
|
|
|
@ -370,6 +370,17 @@ Item {
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onShowToastPairingFallbackCompleted() {
|
||||||
|
Global.displayToastMessage(
|
||||||
|
qsTr("Device paired"),
|
||||||
|
qsTr("Sync in process. Keep device powered and app open."),
|
||||||
|
"checkmark-circle",
|
||||||
|
false,
|
||||||
|
Constants.ephemeralNotificationType.success,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
import QtGraphicalEffects 1.15
|
import QtGraphicalEffects 1.15
|
||||||
|
import QtQml.Models 2.15
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Backpressure 0.1
|
import StatusQ.Core.Backpressure 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Popups.Dialog 0.1
|
||||||
|
|
||||||
import shared 1.0
|
import shared 1.0
|
||||||
import shared.popups 1.0
|
import shared.popups 1.0
|
||||||
|
@ -149,6 +152,9 @@ Popup {
|
||||||
return communityUnbannedNotificationComponent
|
return communityUnbannedNotificationComponent
|
||||||
case ActivityCenterStore.ActivityCenterNotificationType.NewPrivateGroupChat:
|
case ActivityCenterStore.ActivityCenterNotificationType.NewPrivateGroupChat:
|
||||||
return groupChatInvitationNotificationComponent
|
return groupChatInvitationNotificationComponent
|
||||||
|
case ActivityCenterStore.ActivityCenterNotificationType.NewInstallationReceived:
|
||||||
|
case ActivityCenterStore.ActivityCenterNotificationType.NewInstallationCreated:
|
||||||
|
return newDeviceDetectedComponent
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -316,6 +322,36 @@ Popup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: newDeviceDetectedComponent
|
||||||
|
|
||||||
|
ActivityNotificationNewDevice {
|
||||||
|
type: setType(notification)
|
||||||
|
|
||||||
|
filteredIndex: parent.filteredIndex
|
||||||
|
notification: parent.notification
|
||||||
|
accountName: store.name
|
||||||
|
store: root.store
|
||||||
|
activityCenterStore: root.activityCenterStore
|
||||||
|
onCloseActivityCenter: root.close()
|
||||||
|
onMoreDetailsClicked: {
|
||||||
|
switch (type) {
|
||||||
|
case ActivityNotificationNewDevice.InstallationType.Received:
|
||||||
|
Global.openPopup(pairDeviceDialog, {
|
||||||
|
name: store.name,
|
||||||
|
deviceId: notification.installationId
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ActivityNotificationNewDevice.InstallationType.Created:
|
||||||
|
Global.openPopup(checkOtherDeviceDialog, {
|
||||||
|
deviceId: notification.installationId
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: communityTokenReceivedComponent
|
id: communityTokenReceivedComponent
|
||||||
|
|
||||||
|
@ -369,4 +405,94 @@ Popup {
|
||||||
onCloseActivityCenter: root.close()
|
onCloseActivityCenter: root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function truncateDeviceId(deviceId) {
|
||||||
|
return deviceId.substring(0, 7).toUpperCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: pairDeviceDialog
|
||||||
|
|
||||||
|
StatusDialog {
|
||||||
|
property string name
|
||||||
|
property string deviceId
|
||||||
|
|
||||||
|
width: 480
|
||||||
|
closePolicy: Popup.CloseOnPressOutside
|
||||||
|
destroyOnClose: true
|
||||||
|
|
||||||
|
title: qsTr("Pair new device and sync profile")
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("New device with %1 profile has been detected. You can see the device ID below and on your other device. Only confirm the request if the device ID matches.")
|
||||||
|
.arg(name)
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
font.pixelSize: 27
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.letterSpacing: 5
|
||||||
|
text: truncateDeviceId(deviceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: StatusDialogFooter {
|
||||||
|
leftButtons: ObjectModel {
|
||||||
|
StatusFlatButton {
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
onClicked: {
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rightButtons: ObjectModel {
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Pair and Sync")
|
||||||
|
onClicked: {
|
||||||
|
activityCenterStore.enableInstallationAndSync(deviceId)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: checkOtherDeviceDialog
|
||||||
|
|
||||||
|
StatusDialog {
|
||||||
|
property string deviceId
|
||||||
|
|
||||||
|
width: 480
|
||||||
|
closePolicy: Popup.CloseOnPressOutside
|
||||||
|
destroyOnClose: true
|
||||||
|
|
||||||
|
title: qsTr("Pair this device and sync profile")
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Check your other device for a pairing request. Ensure that the this device ID displayed on your other device. Only proceed with pairing and syncing if the IDs are identical.")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
font.pixelSize: 27
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.letterSpacing: 5
|
||||||
|
text: truncateDeviceId(deviceId)
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
footer: null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,9 @@ QtObject {
|
||||||
CommunityTokenReceived = 19,
|
CommunityTokenReceived = 19,
|
||||||
FirstCommunityTokenReceived = 20,
|
FirstCommunityTokenReceived = 20,
|
||||||
CommunityBanned = 21,
|
CommunityBanned = 21,
|
||||||
CommunityUnbanned = 22
|
CommunityUnbanned = 22,
|
||||||
|
NewInstallationReceived = 23,
|
||||||
|
NewInstallationCreated = 24
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ActivityCenterReadType {
|
enum ActivityCenterReadType {
|
||||||
|
@ -118,4 +120,8 @@ QtObject {
|
||||||
function dismissActivityCenterNotification(notification) {
|
function dismissActivityCenterNotification(notification) {
|
||||||
root.activityCenterModuleInst.dismissActivityCenterNotification(notification.id)
|
root.activityCenterModuleInst.dismissActivityCenterNotification(notification.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enableInstallationAndSync(installationId) {
|
||||||
|
root.activityCenterModuleInst.enableInstallationAndSync(installationId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Components 0.1
|
||||||
|
|
||||||
|
import shared 1.0
|
||||||
|
import shared.panels 1.0
|
||||||
|
import utils 1.0
|
||||||
|
import mainui.activitycenter.stores 1.0
|
||||||
|
|
||||||
|
|
||||||
|
ActivityNotificationBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property string accountName
|
||||||
|
required property int type // Possible values [InstallationType]
|
||||||
|
|
||||||
|
signal moreDetailsClicked
|
||||||
|
|
||||||
|
function setType(notification) {
|
||||||
|
if (notification) {
|
||||||
|
switch (notification.notificationType) {
|
||||||
|
case ActivityCenterStore.ActivityCenterNotificationType.NewInstallationReceived:
|
||||||
|
return ActivityNotificationNewDevice.InstallationType.Received
|
||||||
|
|
||||||
|
case ActivityCenterStore.ActivityCenterNotificationType.NewInstallationCreated:
|
||||||
|
return ActivityNotificationNewDevice.InstallationType.Created
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ActivityNotificationNewDevice.InstallationType.Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InstallationType {
|
||||||
|
Unknown,
|
||||||
|
Received,
|
||||||
|
Created
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
|
||||||
|
property string title: ""
|
||||||
|
property string info: ""
|
||||||
|
property string assetColor: Theme.palette.primaryColor1
|
||||||
|
property string assetName: d.desktopAssetName
|
||||||
|
property string assetBgColor: Theme.palette.primaryColor3
|
||||||
|
property string ctaText: qsTr("More details")
|
||||||
|
|
||||||
|
readonly property string desktopAssetName: "desktop"
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyComponent: RowLayout {
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
StatusSmartIdenticon {
|
||||||
|
Layout.preferredWidth: 40
|
||||||
|
Layout.preferredHeight: 40
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.leftMargin: Style.current.padding
|
||||||
|
Layout.topMargin: 2
|
||||||
|
|
||||||
|
asset {
|
||||||
|
width: 24
|
||||||
|
height: width
|
||||||
|
name: d.assetName
|
||||||
|
color: d.assetColor
|
||||||
|
bgWidth: 40
|
||||||
|
bgHeight: 40
|
||||||
|
bgColor: d.assetBgColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 2
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
StatusMessageHeader {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
displayNameLabel.text: d.title
|
||||||
|
timestamp: root.notification.timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: Style.current.padding
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: d.info
|
||||||
|
font.italic: true
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctaComponent: StatusFlatButton {
|
||||||
|
size: StatusBaseButton.Size.Small
|
||||||
|
text: d.ctaText
|
||||||
|
onClicked: {
|
||||||
|
root.moreDetailsClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
when: root.type === ActivityNotificationNewDevice.InstallationType.Received
|
||||||
|
PropertyChanges {
|
||||||
|
target: d
|
||||||
|
title: qsTr("New device detected")
|
||||||
|
info: qsTr("New device with %1 profile has been detected.").arg(accountName)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
when: root.type === ActivityNotificationNewDevice.InstallationType.Created
|
||||||
|
PropertyChanges {
|
||||||
|
target: d
|
||||||
|
title: qsTr("Sync your profile")
|
||||||
|
info: qsTr("Check your other device for a pairing request.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -2,3 +2,4 @@ ActivityNotificationCommunityMembershipRequest 1.0 ActivityNotificationCommunity
|
||||||
ActivityNotificationTransferOwnership 1.0 ActivityNotificationTransferOwnership.qml
|
ActivityNotificationTransferOwnership 1.0 ActivityNotificationTransferOwnership.qml
|
||||||
ActivityNotificationCommunityShareAddresses 1.0 ActivityNotificationCommunityShareAddresses.qml
|
ActivityNotificationCommunityShareAddresses 1.0 ActivityNotificationCommunityShareAddresses.qml
|
||||||
ActivityNotificationCommunityTokenReceived 1.0 ActivityNotificationCommunityTokenReceived.qml
|
ActivityNotificationCommunityTokenReceived 1.0 ActivityNotificationCommunityTokenReceived.qml
|
||||||
|
ActivityNotificationNewDevice 1.0 ActivityNotificationNewDevice.qml
|
||||||
|
|
|
@ -27,6 +27,18 @@ Rectangle {
|
||||||
property bool detailsVisible: false
|
property bool detailsVisible: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CopyButton {
|
||||||
|
width: 20
|
||||||
|
height: 20
|
||||||
|
visible: d.detailsVisible
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 8
|
||||||
|
anchors.rightMargin: 8
|
||||||
|
textToCopy: root.details
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: layout
|
id: layout
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue