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)
|
||||
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):
|
||||
let args = CommunityArgs(e)
|
||||
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) =
|
||||
self.communityService.requestCommunityInfo(communityId, importing)
|
||||
|
||||
proc removePrivateKey*(self: Controller, communityId: string) =
|
||||
self.communityService.removePrivateKey(communityId)
|
||||
|
||||
proc importCommunity*(self: Controller, communityKey: string) =
|
||||
self.communityService.asyncImportCommunity(communityKey)
|
||||
|
||||
|
|
|
@ -65,9 +65,6 @@ method cancelRequestToJoinCommunity*(self: AccessInterface, communityId: string)
|
|||
method requestCommunityInfo*(self: AccessInterface, communityId: string, importing: bool) {.base.} =
|
||||
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.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -92,9 +89,6 @@ method communityCategoryEdited*(self: AccessInterface) {.base.} =
|
|||
method communityCategoryDeleted*(self: AccessInterface) {.base.} =
|
||||
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.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -243,9 +243,6 @@ method navigateToCommunity*(self: Module, communityId: string) =
|
|||
else:
|
||||
self.delegate.setActiveSectionById(communityId)
|
||||
|
||||
method communityPrivateKeyRemoved*(self: Module, communityId: string) =
|
||||
self.view.communityPrivateKeyRemoved(communityId)
|
||||
|
||||
method communityEdited*(self: Module, community: CommunityDto) =
|
||||
self.view.model().editItem(self.getCommunityItem(community))
|
||||
self.view.communityChanged(community.id)
|
||||
|
@ -341,9 +338,6 @@ method communityImported*(self: Module, community: CommunityDto) =
|
|||
method communityDataImported*(self: Module, community: CommunityDto) =
|
||||
self.view.addItem(self.getCommunityItem(community))
|
||||
|
||||
method removePrivateKey*(self: Module, communityId: string) =
|
||||
self.controller.removePrivateKey(communityId)
|
||||
|
||||
method importCommunity*(self: Module, communityId: string) =
|
||||
self.view.emitImportingCommunityStateChangedSignal(communityId, ImportCommunityState.ImportingInProgress.int, errorMsg = "")
|
||||
self.controller.importCommunity(communityId)
|
||||
|
|
|
@ -118,7 +118,6 @@ QtObject:
|
|||
|
||||
proc communityAdded*(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 discordImportErrorsCountChanged*(self: View) {.signal.}
|
||||
proc communityAccessRequested*(self: View, communityId: string) {.signal.}
|
||||
|
@ -540,9 +539,6 @@ QtObject:
|
|||
proc isCommunityRequestPending*(self: View, communityId: string): bool {.slot.} =
|
||||
self.delegate.isCommunityRequestPending(communityId)
|
||||
|
||||
proc removePrivateKey*(self: View, communityId: string) {.slot.} =
|
||||
self.delegate.removePrivateKey(communityId)
|
||||
|
||||
proc importCommunity*(self: View, communityKey: string) {.slot.} =
|
||||
self.delegate.importCommunity(communityKey)
|
||||
|
||||
|
|
|
@ -253,10 +253,6 @@ proc init*(self: Controller) =
|
|||
let args = CommunityMembersRevealedAccountsArgs(e)
|
||||
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):
|
||||
let args = CommunitiesArgs(e)
|
||||
for community in args.communities:
|
||||
|
|
|
@ -60,10 +60,6 @@ proc init*(self: Controller) =
|
|||
let args = CommunityArgs(e)
|
||||
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):
|
||||
let args = CommunitiesArgs(e)
|
||||
for community in args.communities:
|
||||
|
@ -106,4 +102,4 @@ proc getChatDetails*(self: Controller, chatId: string): ChatDto =
|
|||
return self.chatService.getChatById(chatId)
|
||||
|
||||
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_FAILED* = "checkPermissionsToJoinFailed"
|
||||
|
||||
const SIGNAL_COMMUNITY_PRIVATE_KEY_REMOVED* = "communityPrivateKeyRemoved"
|
||||
|
||||
const SIGNAL_COMMUNITY_METRICS_UPDATED* = "communityMetricsUpdated"
|
||||
|
||||
QtObject:
|
||||
|
@ -1669,20 +1667,6 @@ QtObject:
|
|||
)
|
||||
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) =
|
||||
let arg = AsyncImportCommunityTaskArg(
|
||||
tptr: cast[ByteAddress](asyncImportCommunityTask),
|
||||
|
|
|
@ -387,9 +387,6 @@ proc collectCommunityMetrics*(communityId: string, metricsType: int, intervals:
|
|||
proc requestCommunityInfo*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
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].} =
|
||||
result = callPrivateRPC("importCommunity".prefix, %*[communityKey])
|
||||
|
||||
|
@ -471,4 +468,4 @@ proc getCommunityPublicKeyFromPrivateKey*(communityPrivateKey: string,): RpcResp
|
|||
return callPrivateRPC("getCommunityPublicKeyFromPrivateKey".prefix, %*[communityPrivateKey])
|
||||
|
||||
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"
|
||||
],
|
||||
"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": [
|
||||
"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"
|
||||
],
|
||||
"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": [
|
||||
"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"
|
||||
],
|
||||
"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": [
|
||||
"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)
|
||||
loginType: ctrlLoginType.currentIndex
|
||||
requirementsCheckPending: false
|
||||
|
||||
walletAccountsModel: WalletAccountsModel {}
|
||||
permissionsModel: dialog.accessType === Constants.communityChatOnRequestAccess ? PermissionsModel.complexPermissionsModel
|
||||
|
|
|
@ -3,6 +3,8 @@ import QtQuick.Controls 2.15
|
|||
|
||||
import AppLayouts.Communities.popups 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import Storybook 1.0
|
||||
|
||||
SplitView {
|
||||
|
@ -11,22 +13,66 @@ SplitView {
|
|||
|
||||
Logs { id: logs }
|
||||
|
||||
Item {
|
||||
function openDialog() {
|
||||
popupComponent.createObject(popupBg)
|
||||
}
|
||||
|
||||
Component.onCompleted: openDialog()
|
||||
|
||||
Item {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
PopupBackground {
|
||||
id: popupBg
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.centerIn: parent
|
||||
text: "Reopen"
|
||||
Button {
|
||||
anchors.centerIn: parent
|
||||
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 {
|
||||
|
@ -36,9 +82,27 @@ SplitView {
|
|||
anchors.centerIn: parent
|
||||
modal: false
|
||||
visible: true
|
||||
communityName: "Socks"
|
||||
privateKey: "0x0454f2231543ba02583e4c55e513a75092a4f2c86c04d0796b195e964656d6cd94b8237c64ef668eb0fe268387adc3fe699bce97190a631563c82b718c19cf1fb8"
|
||||
onDeletePrivateKey: logs.logEvent("ExportControlNodePopup::onDeletePrivateKey")
|
||||
closePolicy: Popup.NoAutoClose
|
||||
destroyOnClose: true
|
||||
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
|
||||
|
||||
logsView.logText: logs.logText
|
||||
|
||||
Switch {
|
||||
id: ctrlHasSyncedDevices
|
||||
text: "Has synced devices"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,149 +15,25 @@ SplitView {
|
|||
|
||||
Logs { id: logs }
|
||||
|
||||
SplitView {
|
||||
function openDialog() {
|
||||
popupComponent.createObject(popupBg)
|
||||
}
|
||||
|
||||
Component.onCompleted: openDialog()
|
||||
|
||||
Item {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
Pane {
|
||||
id: mainPane
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
PopupBackground {
|
||||
anchors.fill: parent
|
||||
}
|
||||
PopupBackground {
|
||||
id: popupBg
|
||||
anchors.fill: parent
|
||||
|
||||
Button {
|
||||
anchors.centerIn: parent
|
||||
text: "Reopen"
|
||||
|
||||
onClicked: popupComponent.createObject(mainPane)
|
||||
}
|
||||
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();
|
||||
onClicked: openDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,16 +45,13 @@ SplitView {
|
|||
anchors.centerIn: parent
|
||||
modal: false
|
||||
visible: true
|
||||
|
||||
onRequestCommunityInfo: {
|
||||
logs.logEvent("ImportControlNodePopup::onRequestCommunityInfo", ["private key"], [privateKey])
|
||||
if(privateKey === matchingPrivateKey.text)
|
||||
d.timer.callWithDelay(() => popup.setCommunityInfo(d.community))
|
||||
else if (privateKey === mismatchingPrivateKey.text)
|
||||
d.timer.callWithDelay(() => popup.setCommunityInfo(d.otherCommunity))
|
||||
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"
|
||||
}
|
||||
|
||||
community: d.community
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,27 +32,6 @@ SplitView {
|
|||
text: "Control node on/off"
|
||||
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 {
|
||||
property var chatCommunitySectionModule
|
||||
property var contactsStore
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ StatusBaseText {
|
|||
anchors.left: parent.left
|
||||
anchors.leftMargin: root.leftPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
active: root.loading
|
||||
active: root.loading && root.text
|
||||
sourceComponent: LoadingComponent {
|
||||
anchors.centerIn: parent
|
||||
radius: textMetrics.font.pixelSize === 15 ? 4 : 8
|
||||
|
|
|
@ -21,7 +21,7 @@ import StatusQ.Controls 0.1
|
|||
|
||||
model: someModel
|
||||
|
||||
// For a vertical list bind the imlicitHeight to contentHeight
|
||||
// For a vertical list bind the implicitHeight to contentHeight
|
||||
implicitHeight: contentHeight
|
||||
|
||||
delegate: DelegateItem {
|
||||
|
|
|
@ -627,10 +627,6 @@ QtObject {
|
|||
communitiesModuleInst.authenticateWithCallback()
|
||||
}
|
||||
|
||||
function removePrivateKey(communityId) {
|
||||
root.communitiesModuleInst.removePrivateKey(communityId)
|
||||
}
|
||||
|
||||
readonly property Connections communitiesModuleConnections: Connections {
|
||||
target: communitiesModuleInst
|
||||
function onImportingCommunityStateChanged(communityId, state, errorMsg) {
|
||||
|
|
|
@ -13,7 +13,6 @@ import utils 1.0
|
|||
Control {
|
||||
id: root
|
||||
property bool isControlNode: true
|
||||
property int loginType: Constants.LoginType.Password
|
||||
property string communityName: ""
|
||||
|
||||
signal exportControlNodeClicked
|
||||
|
@ -29,9 +28,7 @@ Control {
|
|||
property string paragraphTitle
|
||||
property string paragraphSubtitle
|
||||
property string primaryButtonText
|
||||
property string primaryButtonIcon
|
||||
property string secondaryButtonText
|
||||
property string secondaryButtonIcon
|
||||
property string indicatorBgColor
|
||||
property string indicatorColor
|
||||
property var primaryButtonAction: root.exportControlNodeClicked
|
||||
|
@ -91,15 +88,14 @@ Control {
|
|||
|
||||
StatusFlatButton {
|
||||
size: StatusBaseButton.Size.Small
|
||||
text: d.secondaryButtonText
|
||||
icon.name: d.secondaryButtonIcon
|
||||
text: qsTr("Learn more")
|
||||
icon.name: "external-link"
|
||||
onClicked: root.learnMoreClicked()
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
size: StatusBaseButton.Size.Small
|
||||
text: d.primaryButtonText
|
||||
icon.name: d.primaryButtonIcon
|
||||
onClicked: d.primaryButtonAction()
|
||||
}
|
||||
}
|
||||
|
@ -114,10 +110,7 @@ Control {
|
|||
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; 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; primaryButtonIcon: Constants.authenticationIconByType[root.loginType] }
|
||||
PropertyChanges { target: d; secondaryButtonText: qsTr("Learn more") }
|
||||
PropertyChanges { target: d; secondaryButtonIcon: "external-link" }
|
||||
PropertyChanges { target: d; primaryButtonText: qsTr("How to move control node") }
|
||||
PropertyChanges { target: d; primaryButtonAction: root.exportControlNodeClicked }
|
||||
},
|
||||
State {
|
||||
|
@ -126,11 +119,8 @@ Control {
|
|||
PropertyChanges { target: d; indicatorBgColor: Theme.palette.primaryColor3 }
|
||||
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; 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; primaryButtonIcon: "" }
|
||||
PropertyChanges { target: d; secondaryButtonText: qsTr("Learn more") }
|
||||
PropertyChanges { target: d; secondaryButtonIcon: "external-link" }
|
||||
PropertyChanges { target: d; primaryButtonAction: root.importControlNodeClicked }
|
||||
}
|
||||
]
|
||||
|
|
|
@ -148,7 +148,6 @@ StackLayout {
|
|||
leftPadding: 64
|
||||
bottomPadding: 64
|
||||
topPadding: 0
|
||||
loginType: root.loginType
|
||||
communityName: root.name
|
||||
isControlNode: root.isControlNode
|
||||
onExportControlNodeClicked: root.exportControlNodeClicked()
|
||||
|
|
|
@ -4,24 +4,276 @@ import QtQuick.Layouts 1.15
|
|||
import QtQml.Models 2.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
StatusDialog {
|
||||
id: root
|
||||
|
||||
property string communityName: ""
|
||||
property string privateKey: ""
|
||||
|
||||
signal deletePrivateKey
|
||||
required property var community
|
||||
property var devicesStore
|
||||
|
||||
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 {
|
||||
Layout.fillWidth: true
|
||||
|
@ -33,118 +285,7 @@ StatusDialog {
|
|||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
component CopyButton: StatusButton {
|
||||
id: copyButton
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
component Instruction: Paragraph {
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import QtQml 2.15
|
|||
import QtQml.Models 2.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
@ -16,25 +17,23 @@ StatusDialog {
|
|||
|
||||
required property var community
|
||||
|
||||
signal importControlNode(string privateKey)
|
||||
signal requestCommunityInfo(string privateKey)
|
||||
|
||||
function setCommunityInfo(communityInfo) {
|
||||
d.requestedCommunityInfo = communityInfo
|
||||
d.privateKeyCheckInProgress = false
|
||||
}
|
||||
|
||||
onRequestCommunityInfo: d.privateKeyCheckInProgress = true
|
||||
signal importControlNode(var community)
|
||||
|
||||
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
|
||||
|
||||
component Paragraph: StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
lineHeightMode: Text.FixedHeight
|
||||
lineHeight: 22
|
||||
|
@ -42,163 +41,42 @@ StatusDialog {
|
|||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
component PasteButton: StatusButton {
|
||||
id: pasteButton
|
||||
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
|
||||
contentItem: ColumnLayout {
|
||||
spacing: Style.current.padding
|
||||
Paragraph {
|
||||
Layout.preferredHeight: 22
|
||||
Layout.bottomMargin: Style.current.halfPadding
|
||||
text: qsTr("To move the %1 control node to this device: ").arg(root.community.name)
|
||||
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)
|
||||
}
|
||||
StatusDialogDivider {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Paragraph {
|
||||
text: qsTr("1. Stop using any other devices as the control node for this Community")
|
||||
text: qsTr("I acknowledge that...")
|
||||
}
|
||||
Paragraph {
|
||||
text: qsTr("2. Paste the Community’s private key below:")
|
||||
}
|
||||
StatusBaseInput {
|
||||
id: privateKeyTextArea
|
||||
StatusCheckBox {
|
||||
id: agreementCheckBox
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 86
|
||||
rightPadding: Style.current.padding
|
||||
multiline: true
|
||||
valid: d.isPrivateKey || !d.isPrivateKeyInserted
|
||||
placeholderText: qsTr("e.g. %1").arg("0x0454f2231543ba02583e4c55e513a75092a4f2c86c04d0796b195e964656d6cd94b8237c64ef668eb0fe268387adc3fe699bce97190a631563c82b718c19cf1fb8")
|
||||
rightComponent: PasteButton {
|
||||
onClicked: {
|
||||
privateKeyTextArea.edit.clear()
|
||||
privateKeyTextArea.edit.paste()
|
||||
}
|
||||
}
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
text: qsTr("I must keep this device online and running Status")
|
||||
}
|
||||
ChatDetails {
|
||||
Layout.topMargin: Style.current.halfPadding
|
||||
StatusCheckBox {
|
||||
id: agreementCheckBox2
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 46
|
||||
}
|
||||
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")
|
||||
}
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
text: qsTr("My other synced device will cease to be the control node for this Community")
|
||||
}
|
||||
}
|
||||
|
||||
footer: StatusDialogFooter {
|
||||
rightButtons: ObjectModel {
|
||||
rightButtons: ObjectModel {
|
||||
StatusFlatButton {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: root.close()
|
||||
}
|
||||
StatusButton {
|
||||
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: {
|
||||
root.importControlNode(privateKeyTextArea.text)
|
||||
root.importControlNode(root.community)
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,8 +60,6 @@ QtObject {
|
|||
|
||||
signal importingCommunityStateChanged(string communityId, int state, string errorMsg)
|
||||
|
||||
signal communityPrivateKeyRemoved(string communityId)
|
||||
|
||||
signal communityInfoAlreadyRequested()
|
||||
|
||||
function createCommunity(args = {
|
||||
|
@ -253,9 +251,5 @@ QtObject {
|
|||
function onCommunityInfoAlreadyRequested() {
|
||||
root.communityInfoAlreadyRequested()
|
||||
}
|
||||
|
||||
function onCommunityPrivateKeyRemoved(communityId) {
|
||||
root.communityPrivateKeyRemoved(communityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,23 +218,14 @@ StatusSectionLayout {
|
|||
if(!root.isControlNode)
|
||||
return
|
||||
|
||||
root.rootStore.authenticateWithCallback((authenticated) => {
|
||||
if(!authenticated)
|
||||
return
|
||||
|
||||
Global.openExportControlNodePopup(root.community.name, root.chatCommunitySectionModule.exportCommunity(root.community.id), (popup) => {
|
||||
popup.onDeletePrivateKey.connect(() => {
|
||||
root.rootStore.removePrivateKey(root.community.id)
|
||||
})
|
||||
})
|
||||
})
|
||||
Global.openExportControlNodePopup(root.community)
|
||||
}
|
||||
|
||||
onImportControlNodeClicked: {
|
||||
if(root.isControlNode)
|
||||
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 {
|
||||
|
|
|
@ -205,6 +205,7 @@ Item {
|
|||
popupParent: appMain
|
||||
rootStore: appMain.rootStore
|
||||
communitiesStore: appMain.communitiesStore
|
||||
devicesStore: appMain.rootStore.profileSectionStore.devicesStore
|
||||
isDevBuild: !production
|
||||
}
|
||||
|
||||
|
@ -342,16 +343,6 @@ Item {
|
|||
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 {
|
||||
|
|
|
@ -28,6 +28,7 @@ QtObject {
|
|||
required property var popupParent
|
||||
required property var rootStore
|
||||
property var communitiesStore
|
||||
property var devicesStore
|
||||
property bool isDevBuild
|
||||
|
||||
property var activePopupComponents: []
|
||||
|
@ -276,15 +277,12 @@ QtObject {
|
|||
openPopup(testnetModal)
|
||||
}
|
||||
|
||||
function openExportControlNodePopup(communityName, privateKey, cb) {
|
||||
openPopup(exportControlNodePopup, {
|
||||
communityName: communityName,
|
||||
privateKey: privateKey
|
||||
}, cb)
|
||||
function openExportControlNodePopup(community) {
|
||||
openPopup(exportControlNodePopup, { community })
|
||||
}
|
||||
|
||||
function openImportControlNodePopup(community, cb) {
|
||||
openPopup(importControlNodePopup, {community: community}, cb)
|
||||
function openImportControlNodePopup(community) {
|
||||
openPopup(importControlNodePopup, { community })
|
||||
}
|
||||
|
||||
readonly property list<Component> _components: [
|
||||
|
@ -680,6 +678,7 @@ QtObject {
|
|||
Component {
|
||||
id: exportControlNodePopup
|
||||
ExportControlNodePopup {
|
||||
devicesStore: root.devicesStore
|
||||
onClosed: destroy()
|
||||
}
|
||||
},
|
||||
|
@ -688,6 +687,7 @@ QtObject {
|
|||
id: importControlNodePopup
|
||||
ImportControlNodePopup {
|
||||
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 openDeleteMessagePopup(string messageId, var messageStore)
|
||||
signal openDownloadImageDialog(string imageSource)
|
||||
signal openExportControlNodePopup(string communityName, string privateKey, var cb)
|
||||
signal openImportControlNodePopup(var community, var cb)
|
||||
signal openExportControlNodePopup(var community)
|
||||
signal openImportControlNodePopup(var community)
|
||||
signal contactRenamed(string publicKey)
|
||||
|
||||
signal openLink(string link)
|
||||
|
|
Loading…
Reference in New Issue