feat(community ownership) Move community control node flow UI
Implement the UI part of the new flow for moving community control nodes w/o involving private keys Closes #12088
This commit is contained in:
parent
a072286675
commit
848d3b14f5
|
@ -98,11 +98,6 @@ proc init*(self: Controller) =
|
||||||
let args = CommunityArgs(e)
|
let args = CommunityArgs(e)
|
||||||
self.delegate.communityAdded(args.community)
|
self.delegate.communityAdded(args.community)
|
||||||
|
|
||||||
self.events.on(SIGNAL_COMMUNITY_PRIVATE_KEY_REMOVED) do(e:Args):
|
|
||||||
let args = CommunityArgs(e)
|
|
||||||
self.delegate.communityEdited(args.community)
|
|
||||||
self.delegate.communityPrivateKeyRemoved(args.community.id)
|
|
||||||
|
|
||||||
self.events.on(SIGNAL_COMMUNITY_IMPORTED) do(e:Args):
|
self.events.on(SIGNAL_COMMUNITY_IMPORTED) do(e:Args):
|
||||||
let args = CommunityArgs(e)
|
let args = CommunityArgs(e)
|
||||||
if(args.error.len > 0):
|
if(args.error.len > 0):
|
||||||
|
@ -312,9 +307,6 @@ proc getChatDetailsByIds*(self: Controller, chatIds: seq[string]): seq[ChatDto]
|
||||||
proc requestCommunityInfo*(self: Controller, communityId: string, importing: bool) =
|
proc requestCommunityInfo*(self: Controller, communityId: string, importing: bool) =
|
||||||
self.communityService.requestCommunityInfo(communityId, importing)
|
self.communityService.requestCommunityInfo(communityId, importing)
|
||||||
|
|
||||||
proc removePrivateKey*(self: Controller, communityId: string) =
|
|
||||||
self.communityService.removePrivateKey(communityId)
|
|
||||||
|
|
||||||
proc importCommunity*(self: Controller, communityKey: string) =
|
proc importCommunity*(self: Controller, communityKey: string) =
|
||||||
self.communityService.asyncImportCommunity(communityKey)
|
self.communityService.asyncImportCommunity(communityKey)
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,6 @@ method cancelRequestToJoinCommunity*(self: AccessInterface, communityId: string)
|
||||||
method requestCommunityInfo*(self: AccessInterface, communityId: string, importing: bool) {.base.} =
|
method requestCommunityInfo*(self: AccessInterface, communityId: string, importing: bool) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method removePrivateKey*(self: AccessInterface, communityId: string) {.base.} =
|
|
||||||
raise newException(ValueError, "No implementation available")
|
|
||||||
|
|
||||||
method importCommunity*(self: AccessInterface, communityKey: string) {.base.} =
|
method importCommunity*(self: AccessInterface, communityKey: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
@ -92,9 +89,6 @@ method communityCategoryEdited*(self: AccessInterface) {.base.} =
|
||||||
method communityCategoryDeleted*(self: AccessInterface) {.base.} =
|
method communityCategoryDeleted*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method communityPrivateKeyRemoved*(self: AccessInterface, communityId: string) {.base.} =
|
|
||||||
raise newException(ValueError, "No implementation available")
|
|
||||||
|
|
||||||
method communityEdited*(self: AccessInterface, community: CommunityDto) {.base.} =
|
method communityEdited*(self: AccessInterface, community: CommunityDto) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
|
|
@ -243,9 +243,6 @@ method navigateToCommunity*(self: Module, communityId: string) =
|
||||||
else:
|
else:
|
||||||
self.delegate.setActiveSectionById(communityId)
|
self.delegate.setActiveSectionById(communityId)
|
||||||
|
|
||||||
method communityPrivateKeyRemoved*(self: Module, communityId: string) =
|
|
||||||
self.view.communityPrivateKeyRemoved(communityId)
|
|
||||||
|
|
||||||
method communityEdited*(self: Module, community: CommunityDto) =
|
method communityEdited*(self: Module, community: CommunityDto) =
|
||||||
self.view.model().editItem(self.getCommunityItem(community))
|
self.view.model().editItem(self.getCommunityItem(community))
|
||||||
self.view.communityChanged(community.id)
|
self.view.communityChanged(community.id)
|
||||||
|
@ -341,9 +338,6 @@ method communityImported*(self: Module, community: CommunityDto) =
|
||||||
method communityDataImported*(self: Module, community: CommunityDto) =
|
method communityDataImported*(self: Module, community: CommunityDto) =
|
||||||
self.view.addItem(self.getCommunityItem(community))
|
self.view.addItem(self.getCommunityItem(community))
|
||||||
|
|
||||||
method removePrivateKey*(self: Module, communityId: string) =
|
|
||||||
self.controller.removePrivateKey(communityId)
|
|
||||||
|
|
||||||
method importCommunity*(self: Module, communityId: string) =
|
method importCommunity*(self: Module, communityId: string) =
|
||||||
self.view.emitImportingCommunityStateChangedSignal(communityId, ImportCommunityState.ImportingInProgress.int, errorMsg = "")
|
self.view.emitImportingCommunityStateChangedSignal(communityId, ImportCommunityState.ImportingInProgress.int, errorMsg = "")
|
||||||
self.controller.importCommunity(communityId)
|
self.controller.importCommunity(communityId)
|
||||||
|
|
|
@ -118,7 +118,6 @@ QtObject:
|
||||||
|
|
||||||
proc communityAdded*(self: View, communityId: string) {.signal.}
|
proc communityAdded*(self: View, communityId: string) {.signal.}
|
||||||
proc communityChanged*(self: View, communityId: string) {.signal.}
|
proc communityChanged*(self: View, communityId: string) {.signal.}
|
||||||
proc communityPrivateKeyRemoved*(self: View, communityId: string) {.signal.}
|
|
||||||
proc discordOldestMessageTimestampChanged*(self: View) {.signal.}
|
proc discordOldestMessageTimestampChanged*(self: View) {.signal.}
|
||||||
proc discordImportErrorsCountChanged*(self: View) {.signal.}
|
proc discordImportErrorsCountChanged*(self: View) {.signal.}
|
||||||
proc communityAccessRequested*(self: View, communityId: string) {.signal.}
|
proc communityAccessRequested*(self: View, communityId: string) {.signal.}
|
||||||
|
@ -540,9 +539,6 @@ QtObject:
|
||||||
proc isCommunityRequestPending*(self: View, communityId: string): bool {.slot.} =
|
proc isCommunityRequestPending*(self: View, communityId: string): bool {.slot.} =
|
||||||
self.delegate.isCommunityRequestPending(communityId)
|
self.delegate.isCommunityRequestPending(communityId)
|
||||||
|
|
||||||
proc removePrivateKey*(self: View, communityId: string) {.slot.} =
|
|
||||||
self.delegate.removePrivateKey(communityId)
|
|
||||||
|
|
||||||
proc importCommunity*(self: View, communityKey: string) {.slot.} =
|
proc importCommunity*(self: View, communityKey: string) {.slot.} =
|
||||||
self.delegate.importCommunity(communityKey)
|
self.delegate.importCommunity(communityKey)
|
||||||
|
|
||||||
|
|
|
@ -253,10 +253,6 @@ proc init*(self: Controller) =
|
||||||
let args = CommunityMembersRevealedAccountsArgs(e)
|
let args = CommunityMembersRevealedAccountsArgs(e)
|
||||||
self.delegate.communityMembersRevealedAccountsLoaded(args.communityId, args.membersRevealedAccounts)
|
self.delegate.communityMembersRevealedAccountsLoaded(args.communityId, args.membersRevealedAccounts)
|
||||||
|
|
||||||
self.events.on(SIGNAL_COMMUNITY_PRIVATE_KEY_REMOVED) do(e:Args):
|
|
||||||
let args = CommunityArgs(e)
|
|
||||||
self.delegate.communityEdited(args.community)
|
|
||||||
|
|
||||||
self.events.on(SIGNAL_COMMUNITIES_UPDATE) do(e:Args):
|
self.events.on(SIGNAL_COMMUNITIES_UPDATE) do(e:Args):
|
||||||
let args = CommunitiesArgs(e)
|
let args = CommunitiesArgs(e)
|
||||||
for community in args.communities:
|
for community in args.communities:
|
||||||
|
|
|
@ -60,10 +60,6 @@ proc init*(self: Controller) =
|
||||||
let args = CommunityArgs(e)
|
let args = CommunityArgs(e)
|
||||||
self.delegate.editCommunity(args.community)
|
self.delegate.editCommunity(args.community)
|
||||||
|
|
||||||
self.events.on(SIGNAL_COMMUNITY_PRIVATE_KEY_REMOVED) do(e:Args):
|
|
||||||
let args = CommunityArgs(e)
|
|
||||||
self.delegate.editCommunity(args.community)
|
|
||||||
|
|
||||||
self.events.on(SIGNAL_COMMUNITIES_UPDATE) do(e:Args):
|
self.events.on(SIGNAL_COMMUNITIES_UPDATE) do(e:Args):
|
||||||
let args = CommunitiesArgs(e)
|
let args = CommunitiesArgs(e)
|
||||||
for community in args.communities:
|
for community in args.communities:
|
||||||
|
@ -106,4 +102,4 @@ proc getChatDetails*(self: Controller, chatId: string): ChatDto =
|
||||||
return self.chatService.getChatById(chatId)
|
return self.chatService.getChatById(chatId)
|
||||||
|
|
||||||
proc getContactDetails*(self: Controller, id: string): ContactDetails =
|
proc getContactDetails*(self: Controller, id: string): ContactDetails =
|
||||||
return self.contactService.getContactDetails(id)
|
return self.contactService.getContactDetails(id)
|
||||||
|
|
|
@ -207,8 +207,6 @@ const TOKEN_PERMISSIONS_MODIFIED = "tokenPermissionsModified"
|
||||||
const SIGNAL_CHECK_PERMISSIONS_TO_JOIN_RESPONSE* = "checkPermissionsToJoinResponse"
|
const SIGNAL_CHECK_PERMISSIONS_TO_JOIN_RESPONSE* = "checkPermissionsToJoinResponse"
|
||||||
const SIGNAL_CHECK_PERMISSIONS_TO_JOIN_FAILED* = "checkPermissionsToJoinFailed"
|
const SIGNAL_CHECK_PERMISSIONS_TO_JOIN_FAILED* = "checkPermissionsToJoinFailed"
|
||||||
|
|
||||||
const SIGNAL_COMMUNITY_PRIVATE_KEY_REMOVED* = "communityPrivateKeyRemoved"
|
|
||||||
|
|
||||||
const SIGNAL_COMMUNITY_METRICS_UPDATED* = "communityMetricsUpdated"
|
const SIGNAL_COMMUNITY_METRICS_UPDATED* = "communityMetricsUpdated"
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
|
@ -1669,20 +1667,6 @@ QtObject:
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
proc removePrivateKey*(self: Service, communityId: string) =
|
|
||||||
try:
|
|
||||||
let response = status_go.removePrivateKey(communityId)
|
|
||||||
if (response.error != nil):
|
|
||||||
let error = Json.decode($response.error, RpcError)
|
|
||||||
raise newException(RpcException, fmt"err: {error.message}")
|
|
||||||
|
|
||||||
var community = self.communities[communityId]
|
|
||||||
community.isControlNode = false
|
|
||||||
self.communities[communityId] = community
|
|
||||||
self.events.emit(SIGNAL_COMMUNITY_PRIVATE_KEY_REMOVED, CommunityArgs(community: community))
|
|
||||||
except Exception as e:
|
|
||||||
error "Error removing community private key: ", msg = e.msg
|
|
||||||
|
|
||||||
proc asyncImportCommunity*(self: Service, communityKey: string) =
|
proc asyncImportCommunity*(self: Service, communityKey: string) =
|
||||||
let arg = AsyncImportCommunityTaskArg(
|
let arg = AsyncImportCommunityTaskArg(
|
||||||
tptr: cast[ByteAddress](asyncImportCommunityTask),
|
tptr: cast[ByteAddress](asyncImportCommunityTask),
|
||||||
|
|
|
@ -387,9 +387,6 @@ proc collectCommunityMetrics*(communityId: string, metricsType: int, intervals:
|
||||||
proc requestCommunityInfo*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc requestCommunityInfo*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
result = callPrivateRPC("requestCommunityInfoFromMailserver".prefix, %*[communityId])
|
result = callPrivateRPC("requestCommunityInfoFromMailserver".prefix, %*[communityId])
|
||||||
|
|
||||||
proc removePrivateKey*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
|
||||||
result = callPrivateRPC("removePrivateKey".prefix, %*[communityId])
|
|
||||||
|
|
||||||
proc importCommunity*(communityKey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc importCommunity*(communityKey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
result = callPrivateRPC("importCommunity".prefix, %*[communityKey])
|
result = callPrivateRPC("importCommunity".prefix, %*[communityKey])
|
||||||
|
|
||||||
|
@ -471,4 +468,4 @@ proc getCommunityPublicKeyFromPrivateKey*(communityPrivateKey: string,): RpcResp
|
||||||
return callPrivateRPC("getCommunityPublicKeyFromPrivateKey".prefix, %*[communityPrivateKey])
|
return callPrivateRPC("getCommunityPublicKeyFromPrivateKey".prefix, %*[communityPrivateKey])
|
||||||
|
|
||||||
proc getCommunityMembersForWalletAddresses*(communityId: string, chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc getCommunityMembersForWalletAddresses*(communityId: string, chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
return callPrivateRPC("getCommunityMembersForWalletAddresses".prefix, %* [communityId, chainId])
|
return callPrivateRPC("getCommunityMembersForWalletAddresses".prefix, %* [communityId, chainId])
|
||||||
|
|
|
@ -92,7 +92,9 @@
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?node-id=3132%3A383870&mode=dev"
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?node-id=3132%3A383870&mode=dev"
|
||||||
],
|
],
|
||||||
"ExportControlNodePopup": [
|
"ExportControlNodePopup": [
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31171-627949&mode=design&t=WxK2N6sL8idHBKMZ-0"
|
"https://www.figma.com/file/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?type=design&node-id=36894-685070&mode=design&t=6k1ago8SSQ5Ip9J8-0",
|
||||||
|
"https://www.figma.com/file/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?type=design&node-id=37275-289960&mode=design&t=6k1ago8SSQ5Ip9J8-0",
|
||||||
|
"https://www.figma.com/file/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?type=design&node-id=37275-290036&mode=design&t=6k1ago8SSQ5Ip9J8-0"
|
||||||
],
|
],
|
||||||
"HoldingsDropdown": [
|
"HoldingsDropdown": [
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=22721%3A499660&t=F5yiYQV2YGPBdrJ8-0",
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=22721%3A499660&t=F5yiYQV2YGPBdrJ8-0",
|
||||||
|
@ -103,7 +105,7 @@
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=22734%3A502737&t=7gqqAFbdG5KrPOmn-0"
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=22734%3A502737&t=7gqqAFbdG5KrPOmn-0"
|
||||||
],
|
],
|
||||||
"ImportControlNodePopup": [
|
"ImportControlNodePopup": [
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31171-628434&mode=design&t=IFFCNUpRS3oQbzAR-0"
|
"https://www.figma.com/file/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?type=design&node-id=36894-685104&mode=design&t=6k1ago8SSQ5Ip9J8-0"
|
||||||
],
|
],
|
||||||
"InDropdown": [
|
"InDropdown": [
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2934%3A482182",
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2934%3A482182",
|
||||||
|
@ -163,7 +165,8 @@
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31281-635619&mode=design&t=RYpVRgwqCjp8fUEX-0"
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31281-635619&mode=design&t=RYpVRgwqCjp8fUEX-0"
|
||||||
],
|
],
|
||||||
"OverviewSettingsFooter": [
|
"OverviewSettingsFooter": [
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31171-629792&mode=design&t=IAlt2Frp5gx0yPAn-0"
|
"https://www.figma.com/file/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?type=design&node-id=36894-684461&mode=design&t=6k1ago8SSQ5Ip9J8-0",
|
||||||
|
"https://www.figma.com/file/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?type=design&node-id=36894-684611&mode=design&t=6k1ago8SSQ5Ip9J8-0"
|
||||||
],
|
],
|
||||||
"OverviewSettingsPanel": [
|
"OverviewSettingsPanel": [
|
||||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31229-627216&mode=design&t=KoQOW7vmoNc7f41m-0"
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31229-627216&mode=design&t=KoQOW7vmoNc7f41m-0"
|
||||||
|
|
|
@ -45,6 +45,7 @@ SplitView {
|
||||||
|
|
||||||
Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.".arg(dialog.name)
|
Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.".arg(dialog.name)
|
||||||
loginType: ctrlLoginType.currentIndex
|
loginType: ctrlLoginType.currentIndex
|
||||||
|
requirementsCheckPending: false
|
||||||
|
|
||||||
walletAccountsModel: WalletAccountsModel {}
|
walletAccountsModel: WalletAccountsModel {}
|
||||||
permissionsModel: dialog.accessType === Constants.communityChatOnRequestAccess ? PermissionsModel.complexPermissionsModel
|
permissionsModel: dialog.accessType === Constants.communityChatOnRequestAccess ? PermissionsModel.complexPermissionsModel
|
||||||
|
|
|
@ -3,6 +3,8 @@ import QtQuick.Controls 2.15
|
||||||
|
|
||||||
import AppLayouts.Communities.popups 1.0
|
import AppLayouts.Communities.popups 1.0
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
|
||||||
import Storybook 1.0
|
import Storybook 1.0
|
||||||
|
|
||||||
SplitView {
|
SplitView {
|
||||||
|
@ -11,22 +13,66 @@ SplitView {
|
||||||
|
|
||||||
Logs { id: logs }
|
Logs { id: logs }
|
||||||
|
|
||||||
Item {
|
function openDialog() {
|
||||||
|
popupComponent.createObject(popupBg)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: openDialog()
|
||||||
|
|
||||||
|
Item {
|
||||||
SplitView.fillWidth: true
|
SplitView.fillWidth: true
|
||||||
SplitView.fillHeight: true
|
SplitView.fillHeight: true
|
||||||
|
|
||||||
PopupBackground {
|
PopupBackground {
|
||||||
|
id: popupBg
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Reopen"
|
text: "Reopen"
|
||||||
|
|
||||||
onClicked: popupComponent.createObject(parent)
|
onClicked: openDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: fakeDevicesModel
|
||||||
|
ListElement {
|
||||||
|
name: "Device 1 (osx)"
|
||||||
|
deviceType: "osx"
|
||||||
|
timestamp: 123456789
|
||||||
|
isCurrentDevice: true
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
name: "Device 2 (windows)"
|
||||||
|
deviceType: "windows"
|
||||||
|
timestamp: 123456789123
|
||||||
|
isCurrentDevice: false
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
name: "Device 3 (android)"
|
||||||
|
deviceType: "android"
|
||||||
|
timestamp: 0
|
||||||
|
isCurrentDevice: false
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
name: "Device 4 (ios)"
|
||||||
|
deviceType: "ios"
|
||||||
|
timestamp: 0
|
||||||
|
isCurrentDevice: false
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
name: "Device 5 (desktop)"
|
||||||
|
deviceType: "desktop"
|
||||||
|
timestamp: 0
|
||||||
|
isCurrentDevice: false
|
||||||
|
enabled: true
|
||||||
}
|
}
|
||||||
Component.onCompleted: popupComponent.createObject(parent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
@ -36,9 +82,27 @@ SplitView {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
modal: false
|
modal: false
|
||||||
visible: true
|
visible: true
|
||||||
communityName: "Socks"
|
closePolicy: Popup.NoAutoClose
|
||||||
privateKey: "0x0454f2231543ba02583e4c55e513a75092a4f2c86c04d0796b195e964656d6cd94b8237c64ef668eb0fe268387adc3fe699bce97190a631563c82b718c19cf1fb8"
|
destroyOnClose: true
|
||||||
onDeletePrivateKey: logs.logEvent("ExportControlNodePopup::onDeletePrivateKey")
|
community: QtObject {
|
||||||
|
property string id: "1"
|
||||||
|
property string name: "Socks"
|
||||||
|
property var members: { "count": 5 }
|
||||||
|
property string image: Style.png("tokens/UNI")
|
||||||
|
property string color: "orchid"
|
||||||
|
}
|
||||||
|
devicesStore: QtObject {
|
||||||
|
function loadDevices() {}
|
||||||
|
|
||||||
|
property bool isDeviceSetup: true
|
||||||
|
|
||||||
|
property var devicesModule: QtObject {
|
||||||
|
property bool devicesLoading
|
||||||
|
property bool devicesLoadingError
|
||||||
|
}
|
||||||
|
|
||||||
|
property var devicesModel: ctrlHasSyncedDevices.checked ? fakeDevicesModel : null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +113,11 @@ SplitView {
|
||||||
SplitView.preferredHeight: 160
|
SplitView.preferredHeight: 160
|
||||||
|
|
||||||
logsView.logText: logs.logText
|
logsView.logText: logs.logText
|
||||||
|
|
||||||
|
Switch {
|
||||||
|
id: ctrlHasSyncedDevices
|
||||||
|
text: "Has synced devices"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,149 +15,25 @@ SplitView {
|
||||||
|
|
||||||
Logs { id: logs }
|
Logs { id: logs }
|
||||||
|
|
||||||
SplitView {
|
function openDialog() {
|
||||||
|
popupComponent.createObject(popupBg)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: openDialog()
|
||||||
|
|
||||||
|
Item {
|
||||||
SplitView.fillWidth: true
|
SplitView.fillWidth: true
|
||||||
SplitView.fillHeight: true
|
SplitView.fillHeight: true
|
||||||
Pane {
|
|
||||||
id: mainPane
|
|
||||||
SplitView.fillWidth: true
|
|
||||||
SplitView.fillHeight: true
|
|
||||||
|
|
||||||
PopupBackground {
|
PopupBackground {
|
||||||
anchors.fill: parent
|
id: popupBg
|
||||||
}
|
anchors.fill: parent
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Reopen"
|
text: "Reopen"
|
||||||
|
|
||||||
onClicked: popupComponent.createObject(mainPane)
|
onClicked: openDialog()
|
||||||
}
|
|
||||||
Component.onCompleted: popupComponent.createObject(mainPane)
|
|
||||||
}
|
|
||||||
Pane {
|
|
||||||
SplitView.preferredWidth: 300
|
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: "Matching private key"
|
|
||||||
}
|
|
||||||
TextEdit {
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "transparent"
|
|
||||||
border.color: "red"
|
|
||||||
border.width: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
id: matchingPrivateKey
|
|
||||||
Layout.fillWidth: true
|
|
||||||
wrapMode: TextEdit.Wrap
|
|
||||||
readOnly: true
|
|
||||||
text: "0x0454f2231543ba02583e4c55e513a75092a4f2c86c04d0796b195e964656d6cd"
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
text: "Copy"
|
|
||||||
onClicked: {
|
|
||||||
matchingPrivateKey.selectAll()
|
|
||||||
matchingPrivateKey.copy()
|
|
||||||
matchingPrivateKey.deselect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: "Mismatching private key"
|
|
||||||
}
|
|
||||||
TextEdit {
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "transparent"
|
|
||||||
border.color: "red"
|
|
||||||
border.width: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
id: mismatchingPrivateKey
|
|
||||||
Layout.fillWidth: true
|
|
||||||
wrapMode: TextEdit.Wrap
|
|
||||||
readOnly: true
|
|
||||||
text: "0x0454f2231543ba02583e4c55e513a75092a4f2c86c04d0796b195e964656d6ce"
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
text: "Copy"
|
|
||||||
onClicked: {
|
|
||||||
mismatchingPrivateKey.selectAll()
|
|
||||||
mismatchingPrivateKey.copy()
|
|
||||||
mismatchingPrivateKey.deselect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: "Load in progress private key"
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEdit {
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "transparent"
|
|
||||||
border.color: "red"
|
|
||||||
border.width: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
id: loadInProgressPrivateKey
|
|
||||||
Layout.fillWidth: true
|
|
||||||
wrapMode: TextEdit.Wrap
|
|
||||||
readOnly: true
|
|
||||||
text: "0x0454f2231543ba02583e4c55e513a75092a4f2c86c04d0796b195e964656d6ca"
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
text: "Copy"
|
|
||||||
onClicked: {
|
|
||||||
loadInProgressPrivateKey.selectAll()
|
|
||||||
loadInProgressPrivateKey.copy()
|
|
||||||
loadInProgressPrivateKey.deselect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: d
|
|
||||||
readonly property var community: QtObject {
|
|
||||||
property string id: "1"
|
|
||||||
property string name: "Socks"
|
|
||||||
property var members: { "count": 5 }
|
|
||||||
property string image: Style.png("tokens/UNI")
|
|
||||||
property string color: "orchid"
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property var otherCommunity: QtObject {
|
|
||||||
property string id: "2"
|
|
||||||
property string name: "Socks"
|
|
||||||
property var members: { "count": 5 }
|
|
||||||
property string image: Style.png("tokens/UNI")
|
|
||||||
property string color: "orchid"
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property Timer timer: Timer {
|
|
||||||
//id: _timer
|
|
||||||
interval: 1000
|
|
||||||
repeat: false
|
|
||||||
function callWithDelay(cb) {
|
|
||||||
d.timer.triggered.connect(cb);
|
|
||||||
d.timer.triggered.connect(function release () {
|
|
||||||
d.timer.triggered.disconnect(cb);
|
|
||||||
d.timer.triggered.disconnect(release);
|
|
||||||
});
|
|
||||||
d.timer.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,16 +45,13 @@ SplitView {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
modal: false
|
modal: false
|
||||||
visible: true
|
visible: true
|
||||||
|
community: QtObject {
|
||||||
onRequestCommunityInfo: {
|
property string id: "1"
|
||||||
logs.logEvent("ImportControlNodePopup::onRequestCommunityInfo", ["private key"], [privateKey])
|
property string name: "Socks"
|
||||||
if(privateKey === matchingPrivateKey.text)
|
property var members: { "count": 5 }
|
||||||
d.timer.callWithDelay(() => popup.setCommunityInfo(d.community))
|
property string image: Style.png("tokens/UNI")
|
||||||
else if (privateKey === mismatchingPrivateKey.text)
|
property string color: "orchid"
|
||||||
d.timer.callWithDelay(() => popup.setCommunityInfo(d.otherCommunity))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
community: d.community
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,27 +32,6 @@ SplitView {
|
||||||
text: "Control node on/off"
|
text: "Control node on/off"
|
||||||
checked: true
|
checked: true
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: "Login type::"
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton {
|
|
||||||
checked: true
|
|
||||||
text: qsTr("Password")
|
|
||||||
onCheckedChanged: if(checked) footer.loginType = Constants.LoginType.Password
|
|
||||||
}
|
|
||||||
RadioButton {
|
|
||||||
text: qsTr("Biometrics")
|
|
||||||
onCheckedChanged: if(checked) footer.loginType = Constants.LoginType.Biometrics
|
|
||||||
}
|
|
||||||
RadioButton {
|
|
||||||
text: qsTr("Keycard")
|
|
||||||
onCheckedChanged: if(checked) footer.loginType = Constants.LoginType.Keycard
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,5 @@ import QtQuick 2.15
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
property var chatCommunitySectionModule
|
property var chatCommunitySectionModule
|
||||||
|
property var contactsStore
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ StatusBaseText {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: root.leftPadding
|
anchors.leftMargin: root.leftPadding
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
active: root.loading
|
active: root.loading && root.text
|
||||||
sourceComponent: LoadingComponent {
|
sourceComponent: LoadingComponent {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
radius: textMetrics.font.pixelSize === 15 ? 4 : 8
|
radius: textMetrics.font.pixelSize === 15 ? 4 : 8
|
||||||
|
|
|
@ -21,7 +21,7 @@ import StatusQ.Controls 0.1
|
||||||
|
|
||||||
model: someModel
|
model: someModel
|
||||||
|
|
||||||
// For a vertical list bind the imlicitHeight to contentHeight
|
// For a vertical list bind the implicitHeight to contentHeight
|
||||||
implicitHeight: contentHeight
|
implicitHeight: contentHeight
|
||||||
|
|
||||||
delegate: DelegateItem {
|
delegate: DelegateItem {
|
||||||
|
|
|
@ -627,10 +627,6 @@ QtObject {
|
||||||
communitiesModuleInst.authenticateWithCallback()
|
communitiesModuleInst.authenticateWithCallback()
|
||||||
}
|
}
|
||||||
|
|
||||||
function removePrivateKey(communityId) {
|
|
||||||
root.communitiesModuleInst.removePrivateKey(communityId)
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property Connections communitiesModuleConnections: Connections {
|
readonly property Connections communitiesModuleConnections: Connections {
|
||||||
target: communitiesModuleInst
|
target: communitiesModuleInst
|
||||||
function onImportingCommunityStateChanged(communityId, state, errorMsg) {
|
function onImportingCommunityStateChanged(communityId, state, errorMsg) {
|
||||||
|
|
|
@ -13,7 +13,6 @@ import utils 1.0
|
||||||
Control {
|
Control {
|
||||||
id: root
|
id: root
|
||||||
property bool isControlNode: true
|
property bool isControlNode: true
|
||||||
property int loginType: Constants.LoginType.Password
|
|
||||||
property string communityName: ""
|
property string communityName: ""
|
||||||
|
|
||||||
signal exportControlNodeClicked
|
signal exportControlNodeClicked
|
||||||
|
@ -29,9 +28,7 @@ Control {
|
||||||
property string paragraphTitle
|
property string paragraphTitle
|
||||||
property string paragraphSubtitle
|
property string paragraphSubtitle
|
||||||
property string primaryButtonText
|
property string primaryButtonText
|
||||||
property string primaryButtonIcon
|
|
||||||
property string secondaryButtonText
|
property string secondaryButtonText
|
||||||
property string secondaryButtonIcon
|
|
||||||
property string indicatorBgColor
|
property string indicatorBgColor
|
||||||
property string indicatorColor
|
property string indicatorColor
|
||||||
property var primaryButtonAction: root.exportControlNodeClicked
|
property var primaryButtonAction: root.exportControlNodeClicked
|
||||||
|
@ -91,15 +88,14 @@ Control {
|
||||||
|
|
||||||
StatusFlatButton {
|
StatusFlatButton {
|
||||||
size: StatusBaseButton.Size.Small
|
size: StatusBaseButton.Size.Small
|
||||||
text: d.secondaryButtonText
|
text: qsTr("Learn more")
|
||||||
icon.name: d.secondaryButtonIcon
|
icon.name: "external-link"
|
||||||
onClicked: root.learnMoreClicked()
|
onClicked: root.learnMoreClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusButton {
|
StatusButton {
|
||||||
size: StatusBaseButton.Size.Small
|
size: StatusBaseButton.Size.Small
|
||||||
text: d.primaryButtonText
|
text: d.primaryButtonText
|
||||||
icon.name: d.primaryButtonIcon
|
|
||||||
onClicked: d.primaryButtonAction()
|
onClicked: d.primaryButtonAction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,10 +110,7 @@ Control {
|
||||||
PropertyChanges { target: d; indicatorColor: Theme.palette.successColor1 }
|
PropertyChanges { target: d; indicatorColor: Theme.palette.successColor1 }
|
||||||
PropertyChanges { target: d; paragraphTitle: qsTr("This device is currently the control node for the %1 Community").arg(root.communityName) }
|
PropertyChanges { target: d; paragraphTitle: qsTr("This device is currently the control node for the %1 Community").arg(root.communityName) }
|
||||||
PropertyChanges { target: d; paragraphSubtitle: qsTr("For your Community to function correctly keep this device online with Status running as much as possible.") }
|
PropertyChanges { target: d; paragraphSubtitle: qsTr("For your Community to function correctly keep this device online with Status running as much as possible.") }
|
||||||
PropertyChanges { target: d; primaryButtonText: qsTr("Move control node") }
|
PropertyChanges { target: d; primaryButtonText: qsTr("How to move control node") }
|
||||||
PropertyChanges { target: d; primaryButtonIcon: Constants.authenticationIconByType[root.loginType] }
|
|
||||||
PropertyChanges { target: d; secondaryButtonText: qsTr("Learn more") }
|
|
||||||
PropertyChanges { target: d; secondaryButtonIcon: "external-link" }
|
|
||||||
PropertyChanges { target: d; primaryButtonAction: root.exportControlNodeClicked }
|
PropertyChanges { target: d; primaryButtonAction: root.exportControlNodeClicked }
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
|
@ -126,11 +119,8 @@ Control {
|
||||||
PropertyChanges { target: d; indicatorBgColor: Theme.palette.primaryColor3 }
|
PropertyChanges { target: d; indicatorBgColor: Theme.palette.primaryColor3 }
|
||||||
PropertyChanges { target: d; indicatorColor: Theme.palette.primaryColor1 }
|
PropertyChanges { target: d; indicatorColor: Theme.palette.primaryColor1 }
|
||||||
PropertyChanges { target: d; paragraphTitle: qsTr("Make this device the control node for the %1 Community").arg(root.communityName) }
|
PropertyChanges { target: d; paragraphTitle: qsTr("Make this device the control node for the %1 Community").arg(root.communityName) }
|
||||||
PropertyChanges { target: d; paragraphSubtitle: qsTr("You will need to input the Community private key. Ensure this is a device you can keep online with Status running.") }
|
PropertyChanges { target: d; paragraphSubtitle: qsTr("Ensure this is a device you can keep online with Status running.") }
|
||||||
PropertyChanges { target: d; primaryButtonText: qsTr("Make this device the control node") }
|
PropertyChanges { target: d; primaryButtonText: qsTr("Make this device the control node") }
|
||||||
PropertyChanges { target: d; primaryButtonIcon: "" }
|
|
||||||
PropertyChanges { target: d; secondaryButtonText: qsTr("Learn more") }
|
|
||||||
PropertyChanges { target: d; secondaryButtonIcon: "external-link" }
|
|
||||||
PropertyChanges { target: d; primaryButtonAction: root.importControlNodeClicked }
|
PropertyChanges { target: d; primaryButtonAction: root.importControlNodeClicked }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -148,7 +148,6 @@ StackLayout {
|
||||||
leftPadding: 64
|
leftPadding: 64
|
||||||
bottomPadding: 64
|
bottomPadding: 64
|
||||||
topPadding: 0
|
topPadding: 0
|
||||||
loginType: root.loginType
|
|
||||||
communityName: root.name
|
communityName: root.name
|
||||||
isControlNode: root.isControlNode
|
isControlNode: root.isControlNode
|
||||||
onExportControlNodeClicked: root.exportControlNodeClicked()
|
onExportControlNodeClicked: root.exportControlNodeClicked()
|
||||||
|
|
|
@ -4,24 +4,276 @@ import QtQuick.Layouts 1.15
|
||||||
import QtQml.Models 2.14
|
import QtQml.Models 2.14
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Components 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Popups.Dialog 0.1
|
import StatusQ.Popups.Dialog 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
|
import SortFilterProxyModel 0.2
|
||||||
|
|
||||||
StatusDialog {
|
StatusDialog {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string communityName: ""
|
required property var community
|
||||||
property string privateKey: ""
|
property var devicesStore
|
||||||
|
|
||||||
signal deletePrivateKey
|
|
||||||
|
|
||||||
width: 640
|
width: 640
|
||||||
title: qsTr("Move %1 community control node").arg(root.communityName)
|
|
||||||
|
|
||||||
closePolicy: Popup.NoAutoClose
|
onAboutToShow: {
|
||||||
|
devicesStore.loadDevices()
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
readonly property var devices: SortFilterProxyModel {
|
||||||
|
sourceModel: root.devicesStore.devicesModel
|
||||||
|
sorters: [
|
||||||
|
RoleSorter {
|
||||||
|
roleName: "isCurrentDevice"
|
||||||
|
sortOrder: Qt.DescendingOrder
|
||||||
|
priority: 2
|
||||||
|
},
|
||||||
|
RoleSorter {
|
||||||
|
roleName: "isMobile"
|
||||||
|
priority: 1 // Higher number === higher priority
|
||||||
|
}
|
||||||
|
]
|
||||||
|
proxyRoles: ExpressionRole {
|
||||||
|
name: "isMobile"
|
||||||
|
expression: model.deviceType === "ios" || model.deviceType === "android"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readonly property var syncedDesktopDevices: SortFilterProxyModel {
|
||||||
|
sourceModel: root.devicesStore.devicesModel
|
||||||
|
filters: ExpressionFilter {
|
||||||
|
expression: !model.isCurrentDevice && model.enabled && (model.deviceType !== "ios" && model.deviceType !== "android")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property bool hasSyncedDesktopDevices: syncedDesktopDevices.count
|
||||||
|
}
|
||||||
|
|
||||||
|
header: StatusDialogHeader {
|
||||||
|
headline.title: qsTr("How to move the %1 control node to another device").arg(root.community.name)
|
||||||
|
actions.closeButton.onClicked: root.close()
|
||||||
|
leftComponent: StatusSmartIdenticon {
|
||||||
|
asset.name: root.community.image
|
||||||
|
asset.isImage: !!asset.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 20
|
||||||
|
|
||||||
|
Paragraph {
|
||||||
|
text: d.hasSyncedDesktopDevices ? qsTr("Any of your synced <b>desktop</b> devices can be the control node for this Community:")
|
||||||
|
: qsTr("You don’t currently have any <b>synced desktop devices</b>. You will need to sync another desktop device before you can move the %1 control node to it. Does the device you want to use as the control node currently have Status installed?").arg(root.community.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.leftMargin: Style.current.bigPadding
|
||||||
|
Layout.rightMargin: Style.current.bigPadding
|
||||||
|
sourceComponent: d.hasSyncedDesktopDevices ? devicesInstructions : noDevicesInstructions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: StatusDialogFooter {
|
||||||
|
rightButtons: ObjectModel {
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Close")
|
||||||
|
onClicked: root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: devicesInstructions
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.current.padding
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: -40
|
||||||
|
Layout.rightMargin: -40
|
||||||
|
Layout.preferredHeight: devicesView.implicitHeight
|
||||||
|
Layout.fillHeight: true
|
||||||
|
color: Theme.palette.baseColor2
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: -parent.Layout.leftMargin
|
||||||
|
anchors.rightMargin: -parent.Layout.rightMargin
|
||||||
|
anchors.topMargin: 28
|
||||||
|
anchors.bottomMargin: 28
|
||||||
|
color: Theme.palette.indirectColor4
|
||||||
|
radius: Style.current.radius
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
StatusListView {
|
||||||
|
id: devicesView
|
||||||
|
width: parent.width
|
||||||
|
implicitHeight: contentHeight
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
visible: !root.devicesStore.devicesModule.devicesLoading &&
|
||||||
|
!root.devicesStore.devicesModule.devicesLoadingError &&
|
||||||
|
root.devicesStore.isDeviceSetup
|
||||||
|
|
||||||
|
model: d.devices
|
||||||
|
|
||||||
|
delegate: ItemDelegate {
|
||||||
|
id: deviceDelegate
|
||||||
|
width: ListView.view.width
|
||||||
|
implicitHeight: 64
|
||||||
|
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
|
||||||
|
horizontalPadding: Style.current.padding
|
||||||
|
verticalPadding: 12
|
||||||
|
text: model.name
|
||||||
|
enabled: model.enabled && !model.isMobile
|
||||||
|
background: null
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: Style.current.padding
|
||||||
|
StatusRoundIcon {
|
||||||
|
Layout.alignment: Qt.AlignLeading
|
||||||
|
asset.name: SQUtils.Utils.deviceIcon(model.deviceType)
|
||||||
|
asset.color: model.isCurrentDevice ? Theme.palette.successColor1 : enabled ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
|
||||||
|
asset.bgColor: model.isCurrentDevice ? Theme.palette.successColor3 : enabled ? Theme.palette.primaryColor3 : Theme.palette.baseColor2
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
color: enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||||
|
text: deviceDelegate.text
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignTrailing
|
||||||
|
visible: model.isCurrentDevice
|
||||||
|
color: Theme.palette.successColor1
|
||||||
|
text: qsTr("Control node (this device)")
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignTrailing
|
||||||
|
visible: model.isMobile
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
text: qsTr("Not eligible (desktop only)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("1. On the device you want to make the control node <font color='%1'>login using this profile</font>").arg(Theme.palette.directColor1)
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 4
|
||||||
|
Instruction {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: qsTr("2. Go to")
|
||||||
|
}
|
||||||
|
StatusRoundIcon {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
asset.name: "show"
|
||||||
|
}
|
||||||
|
Paragraph {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: qsTr("%1 Admin Overview").arg(root.community.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("3. Click <font color='%1'>Make this device the control node</font>").arg(Theme.palette.directColor1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: noDevicesInstructions
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.current.padding
|
||||||
|
|
||||||
|
StatusSwitchTabBar {
|
||||||
|
id: switchBar
|
||||||
|
Layout.fillWidth: true
|
||||||
|
StatusSwitchTabButton {
|
||||||
|
text: qsTr("Status installed on other device")
|
||||||
|
}
|
||||||
|
StatusSwitchTabButton {
|
||||||
|
text: qsTr("Status not installed on other device")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StackLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
currentIndex: switchBar.currentIndex
|
||||||
|
ColumnLayout {
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("On this device...")
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 4
|
||||||
|
Instruction {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: qsTr("1. Go to")
|
||||||
|
}
|
||||||
|
StatusRoundIcon {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
asset.name: "settings"
|
||||||
|
}
|
||||||
|
Paragraph {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: qsTr("Settings")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 4
|
||||||
|
Instruction {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: qsTr("2. Go to")
|
||||||
|
}
|
||||||
|
StatusRoundIcon {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
asset.name: "rotate"
|
||||||
|
}
|
||||||
|
Paragraph {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: qsTr("Syncing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("3. Click <font color='%1'>Setup Syncing</font> and sync your other devices").arg(Theme.palette.directColor1)
|
||||||
|
}
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("4. Click <font color='%1'>How to move control node</font> again for next instructions").arg(Theme.palette.directColor1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("1. Install and launch Status on the device you want to use as the control node")
|
||||||
|
}
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("2. On that device, click <font color='%1'>I already use Status</font>").arg(Theme.palette.directColor1)
|
||||||
|
}
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("3. Click <font color='%1'>Scan or enter sync code</font> and sync your new device").arg(Theme.palette.directColor1)
|
||||||
|
}
|
||||||
|
Instruction {
|
||||||
|
text: qsTr("4. Click <font color='%1'>How to move control node</font> again for next instructions").arg(Theme.palette.directColor1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
component Paragraph: StatusBaseText {
|
component Paragraph: StatusBaseText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -33,118 +285,7 @@ StatusDialog {
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
component CopyButton: StatusButton {
|
component Instruction: Paragraph {
|
||||||
id: copyButton
|
color: Theme.palette.baseColor1
|
||||||
borderColor: textColor
|
|
||||||
disabledTextColor: textColor
|
|
||||||
disabledColor: normalColor
|
|
||||||
text: qsTr("Copy")
|
|
||||||
size: StatusButton.Size.Tiny
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "success"
|
|
||||||
PropertyChanges {
|
|
||||||
target: copyButton
|
|
||||||
text: ""
|
|
||||||
icon.name: "checkmark"
|
|
||||||
normalColor: Theme.palette.successColor2
|
|
||||||
textColor: Theme.palette.successColor1
|
|
||||||
enabled: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
width = width // break the biding to prevent the button from shrinking
|
|
||||||
copyButton.state = "success"
|
|
||||||
Backpressure.debounce(root, 2000, function () {
|
|
||||||
copyButton.state = ""
|
|
||||||
})()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusScrollView {
|
|
||||||
id: scroll
|
|
||||||
anchors.fill: parent
|
|
||||||
contentWidth: availableWidth
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: layout
|
|
||||||
width: scroll.availableWidth
|
|
||||||
spacing: 20
|
|
||||||
Paragraph {
|
|
||||||
text: qsTr("For a Status Community to function, it needs to have a single control node running. This installation of Status Desktop is currently the %1 community control node. To move the %1 control node to another device: ").arg(root.communityName)
|
|
||||||
}
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 4
|
|
||||||
Paragraph {
|
|
||||||
text: qsTr("1. Copy your Community’s private key:")
|
|
||||||
}
|
|
||||||
StatusBaseInput {
|
|
||||||
id: privateKeyTextArea
|
|
||||||
Layout.fillWidth: true
|
|
||||||
multiline: true
|
|
||||||
edit.readOnly: true
|
|
||||||
text: root.privateKey
|
|
||||||
rightComponent: CopyButton {
|
|
||||||
onClicked: {
|
|
||||||
privateKeyTextArea.edit.selectAll()
|
|
||||||
privateKeyTextArea.edit.copy()
|
|
||||||
privateKeyTextArea.edit.deselect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Paragraph {
|
|
||||||
text: qsTr("2. Stop using this computer as a control node")
|
|
||||||
}
|
|
||||||
Paragraph {
|
|
||||||
text: qsTr("3. Import this Community via private key on another installation of Status desktop")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
StatusDialogDivider { Layout.fillWidth: true }
|
|
||||||
Item { Layout.fillHeight: true }
|
|
||||||
Paragraph {
|
|
||||||
text: qsTr("I acknowledge that...")
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusCheckBox {
|
|
||||||
id: agreeToStopControl
|
|
||||||
Layout.fillWidth: true
|
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
|
||||||
text: qsTr("%1 will stop working without a control node").arg(root.communityName)
|
|
||||||
}
|
|
||||||
StatusCheckBox {
|
|
||||||
id: agreeToSavePrivateKey
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.minimumHeight: 40
|
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
|
||||||
text: qsTr("I have saved the %1 private key").arg(root.communityName)
|
|
||||||
}
|
|
||||||
StatusCheckBox {
|
|
||||||
id: agreeToDeletePrivateKey
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.minimumHeight: 40
|
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
|
||||||
text: qsTr("If I lose the private key, %1 will be unrecoverable").arg(root.communityName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
footer: StatusDialogFooter {
|
|
||||||
rightButtons: ObjectModel {
|
|
||||||
StatusButton {
|
|
||||||
text: qsTr("Delete private key and stop control node")
|
|
||||||
enabled: agreeToStopControl.checked && agreeToSavePrivateKey.checked && agreeToDeletePrivateKey.checked
|
|
||||||
type: StatusBaseButton.Type.Danger
|
|
||||||
onClicked: {
|
|
||||||
root.deletePrivateKey()
|
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import QtQml 2.15
|
||||||
import QtQml.Models 2.14
|
import QtQml.Models 2.14
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Components 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Popups.Dialog 0.1
|
import StatusQ.Popups.Dialog 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
@ -16,25 +17,23 @@ StatusDialog {
|
||||||
|
|
||||||
required property var community
|
required property var community
|
||||||
|
|
||||||
signal importControlNode(string privateKey)
|
signal importControlNode(var community)
|
||||||
signal requestCommunityInfo(string privateKey)
|
|
||||||
|
|
||||||
function setCommunityInfo(communityInfo) {
|
|
||||||
d.requestedCommunityInfo = communityInfo
|
|
||||||
d.privateKeyCheckInProgress = false
|
|
||||||
}
|
|
||||||
|
|
||||||
onRequestCommunityInfo: d.privateKeyCheckInProgress = true
|
|
||||||
|
|
||||||
width: 640
|
width: 640
|
||||||
height: Math.max(552, implicitHeight)
|
|
||||||
title: qsTr("Make this device the control node for %1").arg(root.community.name)
|
header: StatusDialogHeader {
|
||||||
|
headline.title: qsTr("Make this device the control node for %1").arg(root.community.name)
|
||||||
|
actions.closeButton.onClicked: root.close()
|
||||||
|
leftComponent: StatusSmartIdenticon {
|
||||||
|
asset.name: root.community.image
|
||||||
|
asset.isImage: !!asset.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
closePolicy: Popup.NoAutoClose
|
closePolicy: Popup.NoAutoClose
|
||||||
|
|
||||||
component Paragraph: StatusBaseText {
|
component Paragraph: StatusBaseText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 40
|
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
font.pixelSize: Style.current.primaryTextFontSize
|
||||||
lineHeightMode: Text.FixedHeight
|
lineHeightMode: Text.FixedHeight
|
||||||
lineHeight: 22
|
lineHeight: 22
|
||||||
|
@ -42,163 +41,42 @@ StatusDialog {
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
component PasteButton: StatusButton {
|
contentItem: ColumnLayout {
|
||||||
id: pasteButton
|
spacing: Style.current.padding
|
||||||
borderColor: textColor
|
|
||||||
text: qsTr("Paste")
|
|
||||||
size: StatusButton.Size.Tiny
|
|
||||||
}
|
|
||||||
|
|
||||||
component ChatDetails: Control {
|
|
||||||
verticalPadding: 6
|
|
||||||
horizontalPadding: 4
|
|
||||||
|
|
||||||
contentItem: RowLayout {
|
|
||||||
StatusChatInfoButton {
|
|
||||||
id: communityInfoButton
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
title: community.name
|
|
||||||
subTitle: qsTr("%n member(s)", "", community.members.count || 0)
|
|
||||||
asset.name: community.image
|
|
||||||
asset.color: community.color
|
|
||||||
asset.isImage: true
|
|
||||||
type: StatusChatInfoButton.Type.OneToOneChat
|
|
||||||
hoverEnabled: false
|
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
StatusBaseText {
|
|
||||||
id: detectionLabel
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
font.pixelSize: Style.current.additionalTextSize
|
|
||||||
visible: !!text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "matchingPrivateKey"
|
|
||||||
when: d.isPrivateKeyMatching
|
|
||||||
PropertyChanges { target: detectionLabel; text: qsTr("Private key is valid") }
|
|
||||||
PropertyChanges { target: detectionLabel; color: Theme.palette.successColor1 }
|
|
||||||
PropertyChanges { target: communityInfoButton; visible: true }
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "mismatchingPrivateKey"
|
|
||||||
when: !d.isPrivateKeyMatching && d.isPrivateKey && !d.privateKeyCheckInProgress
|
|
||||||
PropertyChanges { target: detectionLabel; text: qsTr("This is not the correct private key for %1").arg(root.community.name) }
|
|
||||||
PropertyChanges { target: detectionLabel; color: Theme.palette.dangerColor1 }
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "checking"
|
|
||||||
when: d.privateKeyCheckInProgress
|
|
||||||
PropertyChanges { target: detectionLabel; text: qsTr("Checking private key...") }
|
|
||||||
PropertyChanges { target: detectionLabel; color: Theme.palette.baseColor1 }
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "invalidPrivateKey"
|
|
||||||
when: !d.isPrivateKey && d.isPrivateKeyInserted
|
|
||||||
PropertyChanges { target: detectionLabel; text: qsTr("This is not a private key") }
|
|
||||||
PropertyChanges { target: detectionLabel; color: Theme.palette.dangerColor1 }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: d
|
|
||||||
readonly property bool isPrivateKey: Utils.isPrivateKey(privateKeyTextArea.text)
|
|
||||||
readonly property bool isPrivateKeyMatching: d.requestedCommunityInfo ? d.requestedCommunityInfo.id === community.id : false
|
|
||||||
readonly property bool isPrivateKeyInserted: privateKeyTextArea.text.length > 0
|
|
||||||
|
|
||||||
property bool privateKeyCheckInProgress: false
|
|
||||||
property var requestedCommunityInfo: undefined
|
|
||||||
|
|
||||||
onIsPrivateKeyChanged: {
|
|
||||||
if(!isPrivateKey) {
|
|
||||||
requestedCommunityInfo = undefined
|
|
||||||
privateKeyCheckInProgress = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
privateKeyCheckInProgress = true
|
|
||||||
requestedCommunityInfo = undefined
|
|
||||||
requestCommunityInfo(privateKeyTextArea.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: mainLayout
|
|
||||||
anchors.fill: parent
|
|
||||||
spacing: 0
|
|
||||||
Paragraph {
|
Paragraph {
|
||||||
Layout.preferredHeight: 22
|
text: qsTr("Are you sure you want to make this device the control node for %1? This device should be one that you are able to keep online and running Status at all times to enable the Community to function correctly.").arg(root.community.name)
|
||||||
Layout.bottomMargin: Style.current.halfPadding
|
}
|
||||||
text: qsTr("To move the %1 control node to this device: ").arg(root.community.name)
|
StatusDialogDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
Paragraph {
|
Paragraph {
|
||||||
text: qsTr("1. Stop using any other devices as the control node for this Community")
|
text: qsTr("I acknowledge that...")
|
||||||
}
|
}
|
||||||
Paragraph {
|
StatusCheckBox {
|
||||||
text: qsTr("2. Paste the Community’s private key below:")
|
id: agreementCheckBox
|
||||||
}
|
|
||||||
StatusBaseInput {
|
|
||||||
id: privateKeyTextArea
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 86
|
font.pixelSize: Style.current.primaryTextFontSize
|
||||||
rightPadding: Style.current.padding
|
text: qsTr("I must keep this device online and running Status")
|
||||||
multiline: true
|
|
||||||
valid: d.isPrivateKey || !d.isPrivateKeyInserted
|
|
||||||
placeholderText: qsTr("e.g. %1").arg("0x0454f2231543ba02583e4c55e513a75092a4f2c86c04d0796b195e964656d6cd94b8237c64ef668eb0fe268387adc3fe699bce97190a631563c82b718c19cf1fb8")
|
|
||||||
rightComponent: PasteButton {
|
|
||||||
onClicked: {
|
|
||||||
privateKeyTextArea.edit.clear()
|
|
||||||
privateKeyTextArea.edit.paste()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ChatDetails {
|
StatusCheckBox {
|
||||||
Layout.topMargin: Style.current.halfPadding
|
id: agreementCheckBox2
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.minimumHeight: 46
|
font.pixelSize: Style.current.primaryTextFontSize
|
||||||
}
|
text: qsTr("My other synced device will cease to be the control node for this Community")
|
||||||
Item {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.minimumHeight: Style.current.xlPadding
|
|
||||||
}
|
|
||||||
ColumnLayout {
|
|
||||||
id: agreementLayout
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
spacing: mainLayout.spacing
|
|
||||||
|
|
||||||
visible: d.isPrivateKeyMatching
|
|
||||||
|
|
||||||
StatusDialogDivider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
Paragraph {
|
|
||||||
Layout.topMargin: Style.current.padding
|
|
||||||
text: qsTr("I acknowledge that...")
|
|
||||||
}
|
|
||||||
StatusCheckBox {
|
|
||||||
id: agreementCheckBox
|
|
||||||
Layout.fillWidth: true
|
|
||||||
font.pixelSize: Style.current.primaryTextFontSize
|
|
||||||
text: qsTr("I must keep this device online and running Status for the Community to function")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
footer: StatusDialogFooter {
|
footer: StatusDialogFooter {
|
||||||
rightButtons: ObjectModel {
|
rightButtons: ObjectModel {
|
||||||
|
StatusFlatButton {
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
onClicked: root.close()
|
||||||
|
}
|
||||||
StatusButton {
|
StatusButton {
|
||||||
text: qsTr("Make this device the control node for %1").arg(root.community.name)
|
text: qsTr("Make this device the control node for %1").arg(root.community.name)
|
||||||
enabled: d.isPrivateKeyMatching && agreementCheckBox.checked
|
enabled: agreementCheckBox.checked && agreementCheckBox2.checked
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.importControlNode(privateKeyTextArea.text)
|
root.importControlNode(root.community)
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,8 +60,6 @@ QtObject {
|
||||||
|
|
||||||
signal importingCommunityStateChanged(string communityId, int state, string errorMsg)
|
signal importingCommunityStateChanged(string communityId, int state, string errorMsg)
|
||||||
|
|
||||||
signal communityPrivateKeyRemoved(string communityId)
|
|
||||||
|
|
||||||
signal communityInfoAlreadyRequested()
|
signal communityInfoAlreadyRequested()
|
||||||
|
|
||||||
function createCommunity(args = {
|
function createCommunity(args = {
|
||||||
|
@ -253,9 +251,5 @@ QtObject {
|
||||||
function onCommunityInfoAlreadyRequested() {
|
function onCommunityInfoAlreadyRequested() {
|
||||||
root.communityInfoAlreadyRequested()
|
root.communityInfoAlreadyRequested()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCommunityPrivateKeyRemoved(communityId) {
|
|
||||||
root.communityPrivateKeyRemoved(communityId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,23 +218,14 @@ StatusSectionLayout {
|
||||||
if(!root.isControlNode)
|
if(!root.isControlNode)
|
||||||
return
|
return
|
||||||
|
|
||||||
root.rootStore.authenticateWithCallback((authenticated) => {
|
Global.openExportControlNodePopup(root.community)
|
||||||
if(!authenticated)
|
|
||||||
return
|
|
||||||
|
|
||||||
Global.openExportControlNodePopup(root.community.name, root.chatCommunitySectionModule.exportCommunity(root.community.id), (popup) => {
|
|
||||||
popup.onDeletePrivateKey.connect(() => {
|
|
||||||
root.rootStore.removePrivateKey(root.community.id)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onImportControlNodeClicked: {
|
onImportControlNodeClicked: {
|
||||||
if(root.isControlNode)
|
if(root.isControlNode)
|
||||||
return
|
return
|
||||||
|
|
||||||
Global.openImportControlNodePopup(root.community, d.importControlNodePopupOpened)
|
Global.openImportControlNodePopup(root.community)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,44 +523,6 @@ StatusSectionLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestCommunityInfoWithCallback(privateKey, callback) {
|
|
||||||
if(!callback) return
|
|
||||||
|
|
||||||
//success
|
|
||||||
root.rootStore.communityAdded.connect(function communityAddedHandler(communityId) {
|
|
||||||
root.rootStore.communityAdded.disconnect(communityAddedHandler)
|
|
||||||
let community = null
|
|
||||||
try {
|
|
||||||
const communityJson = root.rootStore.getSectionByIdJson(communityId)
|
|
||||||
community = JSON.parse(communityJson)
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("Error parsing community json: ", communityJson, " error: ", e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(community)
|
|
||||||
})
|
|
||||||
|
|
||||||
//error
|
|
||||||
root.rootStore.importingCommunityStateChanged.connect(function communityImportingStateChangedHandler(communityId, status) {
|
|
||||||
root.rootStore.importingCommunityStateChanged.disconnect(communityImportingStateChangedHandler)
|
|
||||||
if(status === Constants.communityImportingError) {
|
|
||||||
callback(null)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
root.rootStore.requestCommunityInfo(privateKey, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
function importControlNodePopupOpened(popup) {
|
|
||||||
popup.requestCommunityInfo.connect((privateKey) => {
|
|
||||||
requestCommunityInfoWithCallback(privateKey, popup.setCommunityInfo)
|
|
||||||
})
|
|
||||||
|
|
||||||
popup.importControlNode.connect((privateKey) => {
|
|
||||||
root.rootStore.importCommunity(privateKey)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusQUtils.ModelChangeTracker {
|
StatusQUtils.ModelChangeTracker {
|
||||||
|
|
|
@ -205,6 +205,7 @@ Item {
|
||||||
popupParent: appMain
|
popupParent: appMain
|
||||||
rootStore: appMain.rootStore
|
rootStore: appMain.rootStore
|
||||||
communitiesStore: appMain.communitiesStore
|
communitiesStore: appMain.communitiesStore
|
||||||
|
devicesStore: appMain.rootStore.profileSectionStore.devicesStore
|
||||||
isDevBuild: !production
|
isDevBuild: !production
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,16 +343,6 @@ Item {
|
||||||
Constants.ephemeralNotificationType.normal,
|
Constants.ephemeralNotificationType.normal,
|
||||||
"")
|
"")
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCommunityPrivateKeyRemoved(communityId) {
|
|
||||||
const community = appMain.communitiesStore.getCommunityDetailsAsJson(communityId)
|
|
||||||
Global.displayToastMessage(qsTr("This device is no longer the control node for the %1 Community").arg(community.name),
|
|
||||||
"",
|
|
||||||
"info",
|
|
||||||
false,
|
|
||||||
Constants.ephemeralNotificationType.normal,
|
|
||||||
"")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|
|
@ -28,6 +28,7 @@ QtObject {
|
||||||
required property var popupParent
|
required property var popupParent
|
||||||
required property var rootStore
|
required property var rootStore
|
||||||
property var communitiesStore
|
property var communitiesStore
|
||||||
|
property var devicesStore
|
||||||
property bool isDevBuild
|
property bool isDevBuild
|
||||||
|
|
||||||
property var activePopupComponents: []
|
property var activePopupComponents: []
|
||||||
|
@ -276,15 +277,12 @@ QtObject {
|
||||||
openPopup(testnetModal)
|
openPopup(testnetModal)
|
||||||
}
|
}
|
||||||
|
|
||||||
function openExportControlNodePopup(communityName, privateKey, cb) {
|
function openExportControlNodePopup(community) {
|
||||||
openPopup(exportControlNodePopup, {
|
openPopup(exportControlNodePopup, { community })
|
||||||
communityName: communityName,
|
|
||||||
privateKey: privateKey
|
|
||||||
}, cb)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openImportControlNodePopup(community, cb) {
|
function openImportControlNodePopup(community) {
|
||||||
openPopup(importControlNodePopup, {community: community}, cb)
|
openPopup(importControlNodePopup, { community })
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property list<Component> _components: [
|
readonly property list<Component> _components: [
|
||||||
|
@ -680,6 +678,7 @@ QtObject {
|
||||||
Component {
|
Component {
|
||||||
id: exportControlNodePopup
|
id: exportControlNodePopup
|
||||||
ExportControlNodePopup {
|
ExportControlNodePopup {
|
||||||
|
devicesStore: root.devicesStore
|
||||||
onClosed: destroy()
|
onClosed: destroy()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -688,6 +687,7 @@ QtObject {
|
||||||
id: importControlNodePopup
|
id: importControlNodePopup
|
||||||
ImportControlNodePopup {
|
ImportControlNodePopup {
|
||||||
onClosed: destroy()
|
onClosed: destroy()
|
||||||
|
onImportControlNode: console.warn("!!! TODO importControlNode for community:", community.name) // FIXME implement moving (importing) the control node
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,8 @@ QtObject {
|
||||||
signal openOutgoingIDRequestPopup(string publicKey, var cb)
|
signal openOutgoingIDRequestPopup(string publicKey, var cb)
|
||||||
signal openDeleteMessagePopup(string messageId, var messageStore)
|
signal openDeleteMessagePopup(string messageId, var messageStore)
|
||||||
signal openDownloadImageDialog(string imageSource)
|
signal openDownloadImageDialog(string imageSource)
|
||||||
signal openExportControlNodePopup(string communityName, string privateKey, var cb)
|
signal openExportControlNodePopup(var community)
|
||||||
signal openImportControlNodePopup(var community, var cb)
|
signal openImportControlNodePopup(var community)
|
||||||
signal contactRenamed(string publicKey)
|
signal contactRenamed(string publicKey)
|
||||||
|
|
||||||
signal openLink(string link)
|
signal openLink(string link)
|
||||||
|
|
Loading…
Reference in New Issue