feat(communities): allow community import via public key
Status allows for importing communities via their private keys. There's a requested feature that users should be able to import a community via its public key as well. This will behave differently as private keys won't give users ownership of the communities. When importing via a (compressed) public key, Status will try to fetch information about the community from the network. If it finds such information, it'll load it into the app and create a communitiy view from which users can then request access. If it can't find a community or community information in the network, the user will get a dedicated error message. This commit also refactors the `ImportCommunityPopup` such that it uses `StatusDialog` and updates the copy accordingly since importing via public key is now possible as well. Closes #8339
This commit is contained in:
parent
16be01495a
commit
b510b33730
|
@ -35,7 +35,12 @@ proc init*(self: Controller) =
|
||||||
|
|
||||||
self.events.on(SIGNAL_COMMUNITY_DATA_IMPORTED) do(e:Args):
|
self.events.on(SIGNAL_COMMUNITY_DATA_IMPORTED) do(e:Args):
|
||||||
let args = CommunityArgs(e)
|
let args = CommunityArgs(e)
|
||||||
self.delegate.communityAdded(args.community)
|
self.delegate.communityImported(args.community)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_COMMUNITY_LOAD_DATA_FAILED) do(e: Args):
|
||||||
|
let args = CommunityArgs(e)
|
||||||
|
self.delegate.onImportCommunityErrorOccured(args.community.id, args.error)
|
||||||
|
|
||||||
|
|
||||||
self.events.on(SIGNAL_CURATED_COMMUNITY_FOUND) do(e:Args):
|
self.events.on(SIGNAL_CURATED_COMMUNITY_FOUND) do(e:Args):
|
||||||
let args = CuratedCommunityArgs(e)
|
let args = CuratedCommunityArgs(e)
|
||||||
|
@ -48,7 +53,7 @@ proc init*(self: Controller) =
|
||||||
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):
|
||||||
self.delegate.onImportCommunityErrorOccured(args.error)
|
self.delegate.onImportCommunityErrorOccured(args.community.id, args.error)
|
||||||
else:
|
else:
|
||||||
self.delegate.communityImported(args.community)
|
self.delegate.communityImported(args.community)
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ method curatedCommunityEdited*(self: AccessInterface, community: CuratedCommunit
|
||||||
method communityImported*(self: AccessInterface, community: CommunityDto) {.base.} =
|
method communityImported*(self: AccessInterface, community: CommunityDto) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method onImportCommunityErrorOccured*(self: AccessInterface, error: string) {.base.} =
|
method onImportCommunityErrorOccured*(self: AccessInterface, communityId: string, error: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||||
|
|
|
@ -301,14 +301,14 @@ method deleteCommunityChat*(self: Module, communityId: string, channelId: string
|
||||||
|
|
||||||
method communityImported*(self: Module, community: CommunityDto) =
|
method communityImported*(self: Module, community: CommunityDto) =
|
||||||
self.view.addItem(self.getCommunityItem(community))
|
self.view.addItem(self.getCommunityItem(community))
|
||||||
self.view.emitImportingCommunityStateChangedSignal(ImportCommunityState.Imported.int, "")
|
self.view.emitImportingCommunityStateChangedSignal(community.id, ImportCommunityState.Imported.int, "")
|
||||||
|
|
||||||
method importCommunity*(self: Module, communityKey: string) =
|
method importCommunity*(self: Module, communityKey: string) =
|
||||||
self.view.emitImportingCommunityStateChangedSignal(ImportCommunityState.ImportingInProgress.int, "")
|
self.view.emitImportingCommunityStateChangedSignal(communityKey, ImportCommunityState.ImportingInProgress.int, "")
|
||||||
self.controller.importCommunity(communityKey)
|
self.controller.importCommunity(communityKey)
|
||||||
|
|
||||||
method onImportCommunityErrorOccured*(self: Module, error: string) =
|
method onImportCommunityErrorOccured*(self: Module, communityId: string, error: string) =
|
||||||
self.view.emitImportingCommunityStateChangedSignal(ImportCommunityState.ImportingError.int, error)
|
self.view.emitImportingCommunityStateChangedSignal(communityId, ImportCommunityState.ImportingError.int, error)
|
||||||
|
|
||||||
method requestExtractDiscordChannelsAndCategories*(self: Module, filesToImport: seq[string]) =
|
method requestExtractDiscordChannelsAndCategories*(self: Module, filesToImport: seq[string]) =
|
||||||
self.view.setDiscordDataExtractionInProgress(true)
|
self.view.setDiscordDataExtractionInProgress(true)
|
||||||
|
|
|
@ -471,9 +471,9 @@ QtObject:
|
||||||
proc importCommunity*(self: View, communityKey: string) {.slot.} =
|
proc importCommunity*(self: View, communityKey: string) {.slot.} =
|
||||||
self.delegate.importCommunity(communityKey)
|
self.delegate.importCommunity(communityKey)
|
||||||
|
|
||||||
proc importingCommunityStateChanged*(self:View, state: int, errorMsg: string) {.signal.}
|
proc importingCommunityStateChanged*(self:View, communityId: string, state: int, errorMsg: string) {.signal.}
|
||||||
proc emitImportingCommunityStateChangedSignal*(self: View, state: int, errorMsg: string) =
|
proc emitImportingCommunityStateChangedSignal*(self: View, communityId: string, state: int, errorMsg: string) =
|
||||||
self.importingCommunityStateChanged(state, errorMsg)
|
self.importingCommunityStateChanged(communityId, state, errorMsg)
|
||||||
|
|
||||||
proc isMemberOfCommunity*(self: View, communityId: string, pubKey: string): bool {.slot.} =
|
proc isMemberOfCommunity*(self: View, communityId: string, pubKey: string): bool {.slot.} =
|
||||||
let sectionItem = self.model.getItemById(communityId)
|
let sectionItem = self.model.getItemById(communityId)
|
||||||
|
|
|
@ -235,6 +235,9 @@ method onMyRequestAdded*(self: AccessInterface) {.base.} =
|
||||||
method activateStatusDeepLink*(self: AccessInterface, statusDeepLink: string) {.base.} =
|
method activateStatusDeepLink*(self: AccessInterface, statusDeepLink: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method setCommunityIdToSpectate*(self: AccessInterface, commnityId: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
# This way (using concepts) is used only for the modules managed by AppController
|
# This way (using concepts) is used only for the modules managed by AppController
|
||||||
type
|
type
|
||||||
DelegateInterface* = concept c
|
DelegateInterface* = concept c
|
||||||
|
|
|
@ -575,6 +575,9 @@ method emitStoringPasswordSuccess*[T](self: Module[T]) =
|
||||||
method emitMailserverNotWorking*[T](self: Module[T]) =
|
method emitMailserverNotWorking*[T](self: Module[T]) =
|
||||||
self.view.emitMailserverNotWorking()
|
self.view.emitMailserverNotWorking()
|
||||||
|
|
||||||
|
method setCommunityIdToSpectate*[T](self: Module[T], communityId: string) =
|
||||||
|
self.statusUrlCommunityToSpectate = communityId
|
||||||
|
|
||||||
method getActiveSectionId*[T](self: Module[T]): string =
|
method getActiveSectionId*[T](self: Module[T]): string =
|
||||||
return self.controller.getActiveSectionId()
|
return self.controller.getActiveSectionId()
|
||||||
|
|
||||||
|
|
|
@ -239,3 +239,6 @@ QtObject:
|
||||||
proc destroyKeycardSharedModuleFlow*(self: View) {.signal.}
|
proc destroyKeycardSharedModuleFlow*(self: View) {.signal.}
|
||||||
proc emitDestroyKeycardSharedModuleFlow*(self: View) =
|
proc emitDestroyKeycardSharedModuleFlow*(self: View) =
|
||||||
self.destroyKeycardSharedModuleFlow()
|
self.destroyKeycardSharedModuleFlow()
|
||||||
|
|
||||||
|
proc setCommunityIdToSpectate*(self: View, communityId: string) {.slot.} =
|
||||||
|
self.delegate.setCommunityIdToSpectate(communityId)
|
||||||
|
|
|
@ -8,4 +8,5 @@ type
|
||||||
const asyncRequestCommunityInfoTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
const asyncRequestCommunityInfoTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
let arg = decode[AsyncRequestCommunityInfoTaskArg](argEncoded)
|
let arg = decode[AsyncRequestCommunityInfoTaskArg](argEncoded)
|
||||||
let response = status_go.requestCommunityInfo(arg.communityId)
|
let response = status_go.requestCommunityInfo(arg.communityId)
|
||||||
arg.finish(response)
|
let tpl: tuple[communityId: string, response: RpcResponse[JsonNode]] = (arg.communityId, response)
|
||||||
|
arg.finish(tpl)
|
||||||
|
|
|
@ -100,6 +100,7 @@ const SIGNAL_COMMUNITY_CREATED* = "communityCreated"
|
||||||
const SIGNAL_COMMUNITY_ADDED* = "communityAdded"
|
const SIGNAL_COMMUNITY_ADDED* = "communityAdded"
|
||||||
const SIGNAL_COMMUNITY_IMPORTED* = "communityImported"
|
const SIGNAL_COMMUNITY_IMPORTED* = "communityImported"
|
||||||
const SIGNAL_COMMUNITY_DATA_IMPORTED* = "communityDataImported" # This one is when just loading the data with requestCommunityInfo
|
const SIGNAL_COMMUNITY_DATA_IMPORTED* = "communityDataImported" # This one is when just loading the data with requestCommunityInfo
|
||||||
|
const SIGNAL_COMMUNITY_LOAD_DATA_FAILED* = "communityLoadDataFailed"
|
||||||
const SIGNAL_COMMUNITY_EDITED* = "communityEdited"
|
const SIGNAL_COMMUNITY_EDITED* = "communityEdited"
|
||||||
const SIGNAL_COMMUNITIES_UPDATE* = "communityUpdated"
|
const SIGNAL_COMMUNITIES_UPDATE* = "communityUpdated"
|
||||||
const SIGNAL_COMMUNITY_CHANNEL_CREATED* = "communityChannelCreated"
|
const SIGNAL_COMMUNITY_CHANNEL_CREATED* = "communityChannelCreated"
|
||||||
|
@ -1165,16 +1166,21 @@ QtObject:
|
||||||
error "Error reordering category channel", msg = e.msg, communityId, categoryId, position
|
error "Error reordering category channel", msg = e.msg, communityId, categoryId, position
|
||||||
|
|
||||||
|
|
||||||
proc asyncCommunityInfoLoaded*(self: Service, rpcResponse: string) {.slot.} =
|
proc asyncCommunityInfoLoaded*(self: Service, communityIdAndRpcResponse: string) {.slot.} =
|
||||||
let rpcResponseObj = rpcResponse.parseJson
|
let rpcResponseObj = communityIdAndRpcResponse.parseJson
|
||||||
if (rpcResponseObj{"error"}.kind != JNull):
|
if (rpcResponseObj{"response"}{"error"}.kind != JNull):
|
||||||
let error = Json.decode($rpcResponseObj["error"], RpcError)
|
let error = Json.decode($rpcResponseObj["response"]["error"], RpcError)
|
||||||
error "Error requesting community info", msg = error.message
|
error "Error requesting community info", msg = error.message
|
||||||
return
|
return
|
||||||
|
|
||||||
let community = rpcResponseObj{"result"}.toCommunityDto()
|
var community = rpcResponseObj{"response"}{"result"}.toCommunityDto()
|
||||||
|
if community.id != "":
|
||||||
self.allCommunities[community.id] = community
|
self.allCommunities[community.id] = community
|
||||||
self.events.emit(SIGNAL_COMMUNITY_DATA_IMPORTED, CommunityArgs(community: community))
|
self.events.emit(SIGNAL_COMMUNITY_DATA_IMPORTED, CommunityArgs(community: community))
|
||||||
|
else:
|
||||||
|
community.id = rpcResponseObj{"response"}{"communityId"}.getStr()
|
||||||
|
self.events.emit(SIGNAL_COMMUNITY_LOAD_DATA_FAILED, CommunityArgs(community: community, error: "Couldn't find community info"))
|
||||||
|
|
||||||
|
|
||||||
proc requestCommunityInfo*(self: Service, communityId: string) =
|
proc requestCommunityInfo*(self: Service, communityId: string) =
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -47,6 +47,8 @@ QtObject {
|
||||||
|
|
||||||
property var advancedModule: profileSectionModule.advancedModule
|
property var advancedModule: profileSectionModule.advancedModule
|
||||||
|
|
||||||
|
signal importingCommunityStateChanged(string communityId, int state, string errorMsg)
|
||||||
|
|
||||||
function setActiveCommunity(communityId) {
|
function setActiveCommunity(communityId) {
|
||||||
mainModule.setActiveSectionById(communityId);
|
mainModule.setActiveSectionById(communityId);
|
||||||
}
|
}
|
||||||
|
@ -570,4 +572,11 @@ QtObject {
|
||||||
function hex2Eth(value) {
|
function hex2Eth(value) {
|
||||||
return globalUtils.hex2Eth(value)
|
return globalUtils.hex2Eth(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property Connections communitiesModuleConnections: Connections {
|
||||||
|
target: communitiesModuleInst
|
||||||
|
function onImportingCommunityStateChanged(communityId, state, errorMsg) {
|
||||||
|
root.importingCommunityStateChanged(communityId, state, errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,8 +319,8 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root.store.communitiesModuleInst
|
target: root.store
|
||||||
function onImportingCommunityStateChanged(state, errorMsg) {
|
function onImportingCommunityStateChanged(communityId, state, errorMsg) {
|
||||||
let title = ""
|
let title = ""
|
||||||
let loading = false
|
let loading = false
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
import QtQml.Models 2.2
|
import QtQml.Models 2.2
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var communitiesModuleInst: communitiesModule
|
property var communitiesModuleInst: communitiesModule
|
||||||
|
property var mainModuleInst: mainModule
|
||||||
|
|
||||||
readonly property var curatedCommunitiesModel: root.communitiesModuleInst.curatedCommunities
|
readonly property var curatedCommunitiesModel: root.communitiesModuleInst.curatedCommunities
|
||||||
|
|
||||||
|
@ -51,6 +54,8 @@ QtObject {
|
||||||
|
|
||||||
property string communityTags: communitiesModuleInst.tags
|
property string communityTags: communitiesModuleInst.tags
|
||||||
|
|
||||||
|
signal importingCommunityStateChanged(string communityId, int state, string errorMsg)
|
||||||
|
|
||||||
function createCommunity(args = {
|
function createCommunity(args = {
|
||||||
name: "",
|
name: "",
|
||||||
description: "",
|
description: "",
|
||||||
|
@ -85,6 +90,16 @@ QtObject {
|
||||||
root.communitiesModuleInst.importCommunity(communityKey);
|
root.communitiesModuleInst.importCommunity(communityKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function requestCommunityInfo(communityKey) {
|
||||||
|
let publicKey = communityKey
|
||||||
|
if (Utils.isCompressedPubKey(communityKey)) {
|
||||||
|
publicKey = Utils.changeCommunityKeyCompression(communityKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
root.mainModuleInst.setCommunityIdToSpectate(publicKey)
|
||||||
|
root.communitiesModuleInst.requestCommunityInfo(publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
function setActiveCommunity(communityId) {
|
function setActiveCommunity(communityId) {
|
||||||
mainModule.setActiveSectionById(communityId);
|
mainModule.setActiveSectionById(communityId);
|
||||||
}
|
}
|
||||||
|
@ -155,4 +170,12 @@ QtObject {
|
||||||
args.image.src, args.image.AX, args.image.AY, args.image.BX, args.image.BY,
|
args.image.src, args.image.AX, args.image.AY, args.image.BX, args.image.BY,
|
||||||
args.options.historyArchiveSupportEnabled, args.options.pinMessagesAllowedForMembers, from, args.options.encrypted);
|
args.options.historyArchiveSupportEnabled, args.options.pinMessagesAllowedForMembers, from, args.options.encrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
readonly property Connections connections: Connections {
|
||||||
|
target: communitiesModuleInst
|
||||||
|
function onImportingCommunityStateChanged(communityId, state, errorMsg) {
|
||||||
|
root.importingCommunityStateChanged(communityId, state, errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,82 +1,135 @@
|
||||||
import QtQuick 2.12
|
import QtQuick 2.12
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls 2.3
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
import QtGraphicalEffects 1.13
|
import QtGraphicalEffects 1.13
|
||||||
import QtQuick.Dialogs 1.3
|
import QtQuick.Dialogs 1.3
|
||||||
|
import QtQml.Models 2.14
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import shared.controls 1.0
|
import shared.controls 1.0
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Popups 0.1
|
import StatusQ.Popups.Dialog 0.1
|
||||||
import StatusQ.Controls 0.1 as StatusQControls
|
import StatusQ.Controls 0.1
|
||||||
|
|
||||||
StatusModal {
|
StatusDialog {
|
||||||
id: root
|
id: root
|
||||||
width: 640
|
|
||||||
height: 400
|
|
||||||
|
|
||||||
property var store
|
property var store
|
||||||
|
width: 640
|
||||||
|
title: qsTr("Import Community")
|
||||||
|
|
||||||
function validate(communityKey) {
|
QtObject {
|
||||||
return Utils.isPrivateKey(communityKey) && Utils.startsWith0x(communityKey)
|
id: d
|
||||||
|
property string importErrorMessage
|
||||||
|
readonly property string inputErrorMessage: isInputValid ? "" : qsTr("Invalid key")
|
||||||
|
readonly property string errorMessage: importErrorMessage || inputErrorMessage
|
||||||
|
readonly property bool isPrivateKey: Utils.isPrivateKey(keyInput.text)
|
||||||
|
readonly property bool isPublicKey: Utils.isChatKey(keyInput.text)
|
||||||
|
readonly property bool isInputValid: isPrivateKey || isPublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
header.title: qsTr("Import Community")
|
footer: StatusDialogFooter {
|
||||||
|
rightButtons: ObjectModel {
|
||||||
onClosed: {
|
StatusFlatButton {
|
||||||
root.destroy();
|
text: qsTr("Cancel")
|
||||||
|
onClicked: root.reject()
|
||||||
|
}
|
||||||
|
StatusButton {
|
||||||
|
id: importButton
|
||||||
|
enabled: d.isInputValid
|
||||||
|
text: d.isPrivateKey ? qsTr("Make this an Owner Node") : qsTr("Import")
|
||||||
|
onClicked: {
|
||||||
|
let communityKey = keyInput.text.trim();
|
||||||
|
if (d.isPrivateKey) {
|
||||||
|
if (!communityKey.startsWith("0x")) {
|
||||||
|
communityKey = "0x" + communityKey;
|
||||||
|
}
|
||||||
|
root.store.importCommunity(communityKey);
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
if (d.isPublicKey) {
|
||||||
|
importButton.loading = true
|
||||||
|
root.store.requestCommunityInfo(communityKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Item {
|
ColumnLayout {
|
||||||
width: root.width - 32
|
anchors.fill: parent
|
||||||
anchors.left: parent.left
|
spacing: Style.current.padding
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
height: childrenRect.height
|
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
id: infoText1
|
id: infoText1
|
||||||
anchors.top: parent.top
|
Layout.fillWidth: true
|
||||||
anchors.topMargin: Style.current.padding
|
text: qsTr("Enter the public key of the community you wish to access, or enter the private key of a community you own. Remember to always keep any private key safe and never share a private key with anyone else.")
|
||||||
text: qsTr("Entering a community key will grant you the ownership of that community. Please be responsible with it and don’t share the key with people you don’t trust.")
|
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
width: parent.width
|
|
||||||
font.pixelSize: 13
|
font.pixelSize: 13
|
||||||
color: Theme.palette.baseColor1
|
color: Theme.palette.baseColor1
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledTextArea {
|
StatusBaseText {
|
||||||
|
id: inputLabel
|
||||||
|
text: qsTr("Community key")
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
font.pixelSize: 15
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusTextArea {
|
||||||
id: keyInput
|
id: keyInput
|
||||||
label: qsTr("Community private key")
|
|
||||||
placeholderText: "0x0..."
|
placeholderText: "0x0..."
|
||||||
customHeight: 110
|
height: 110
|
||||||
anchors.top: infoText1.bottom
|
Layout.fillWidth: true
|
||||||
anchors.topMargin: Style.current.bigPadding
|
onTextChanged: d.importErrorMessage = ""
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
importButton.enabled = root.validate(keyInput.text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: detectionLabel
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font.pixelSize: 13
|
||||||
|
visible: keyInput.text.trim() !== ""
|
||||||
|
text: {
|
||||||
|
if (d.errorMessage !== "") {
|
||||||
|
return d.errorMessage
|
||||||
|
}
|
||||||
|
if (d.isPrivateKey) {
|
||||||
|
return qsTr("Private key detected")
|
||||||
|
}
|
||||||
|
if (d.isPublicKey) {
|
||||||
|
return qsTr("Public key detected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color: d.errorMessage === "" ? Theme.palette.successColor1 : Theme.palette.dangerColor1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rightButtons: [
|
|
||||||
StatusQControls.StatusButton {
|
Connections {
|
||||||
id: importButton
|
target: root.store
|
||||||
enabled: false
|
function onImportingCommunityStateChanged(communityId, state, errorMsg) {
|
||||||
text: qsTr("Import")
|
|
||||||
onClicked: {
|
|
||||||
let communityKey = keyInput.text.trim();
|
let communityKey = keyInput.text.trim();
|
||||||
if (!communityKey.startsWith("0x")) {
|
if (d.isPublicKey) {
|
||||||
communityKey = "0x" + communityKey;
|
let currentCommunityKey = Utils.isCompressedPubKey(communityKey) ?
|
||||||
|
Utils.changeCommunityKeyCompression(communityKey) :
|
||||||
|
communityKey
|
||||||
|
|
||||||
|
if (communityId == currentCommunityKey) {
|
||||||
|
importButton.loading = false
|
||||||
|
if (state === Constants.communityImported && root.opened) {
|
||||||
|
root.close()
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
root.store.importCommunity(communityKey);
|
if (state === Constants.communityImportingError) {
|
||||||
root.close();
|
d.importErrorMessage = errorMsg
|
||||||
|
importButton.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,10 @@ QtObject {
|
||||||
return (startsWith0x(value) && isHex(value) && value.length === 132) || globalUtilsInst.isCompressedPubKey(value)
|
return (startsWith0x(value) && isHex(value) && value.length === 132) || globalUtilsInst.isCompressedPubKey(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isCompressedPubKey(pubKey) {
|
||||||
|
return globalUtilsInst.isCompressedPubKey(pubKey)
|
||||||
|
}
|
||||||
|
|
||||||
function isValidETHNamePrefix(value) {
|
function isValidETHNamePrefix(value) {
|
||||||
return !(value.trim() === "" || value.endsWith(".") || value.indexOf("..") > -1)
|
return !(value.trim() === "" || value.endsWith(".") || value.indexOf("..") > -1)
|
||||||
}
|
}
|
||||||
|
@ -620,6 +624,11 @@ QtObject {
|
||||||
return communityKey
|
return communityKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function changeCommunityKeyCompression(communityKey) {
|
||||||
|
return globalUtilsInst.changeCommunityKeyCompression(communityKey)
|
||||||
|
}
|
||||||
|
|
||||||
function getCompressedPk(publicKey) {
|
function getCompressedPk(publicKey) {
|
||||||
if (publicKey === "") {
|
if (publicKey === "") {
|
||||||
return ""
|
return ""
|
||||||
|
|
Loading…
Reference in New Issue