fix: Fix and rework "start chat" text field input (#10450)

This commit is contained in:
Igor Sirotin 2023-04-27 17:03:49 +03:00 committed by GitHub
parent 20102ebe3b
commit 6fe82ef133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 102 additions and 48 deletions

View File

@ -8,7 +8,10 @@ const SystemMentionChars* = {'0'..'9', 'x'}
const SystemTagMapping* = [("@everyone", "@0x00001")] const SystemTagMapping* = [("@everyone", "@0x00001")]
proc isCompressedPubKey*(strPubKey: string): bool = proc isCompressedPubKey*(strPubKey: string): bool =
return strPubKey.startsWith("zQ3") and allCharsInSet(strPubKey, CompressedKeyChars) let length = len(strPubKey)
return length >= 48 and length <= 50 and
strPubKey.startsWith("zQ3sh") and
allCharsInSet(strPubKey, CompressedKeyChars)
proc isSystemMention*(mention: string) : bool = proc isSystemMention*(mention: string) : bool =
mention.startsWith("0x") and allCharsInSet(mention, SystemMentionChars) mention.startsWith("0x") and allCharsInSet(mention, SystemMentionChars)

View File

@ -68,8 +68,10 @@ const asyncRequestContactInfoTask: Task = proc(argEncoded: string) {.gcsafe, nim
arg.finish(%* { arg.finish(%* {
"publicKey": arg.pubkey, "publicKey": arg.pubkey,
"response": response, "response": response,
"error": nil,
}) })
except Exception as e: except Exception as e:
arg.finish(%* { arg.finish(%* {
"publicKey": arg.pubkey,
"error": e.msg, "error": e.msg,
}) })

View File

@ -319,12 +319,12 @@ QtObject:
proc getContactById*(self: Service, id: string): ContactsDto = proc getContactById*(self: Service, id: string): ContactsDto =
var pubkey = id var pubkey = id
if len(pubkey) == 0:
return
if service_conversion.isCompressedPubKey(id): if service_conversion.isCompressedPubKey(id):
pubkey = status_accounts.decompressPk(id).result pubkey = status_accounts.decompressPk(id).result
if len(pubkey) == 0:
return
if(pubkey == singletonInstance.userProfile.getPubKey()): if(pubkey == singletonInstance.userProfile.getPubKey()):
# If we try to get the contact details of ourselves, just return our own info # If we try to get the contact details of ourselves, just return our own info
return ContactsDto( return ContactsDto(
@ -779,10 +779,18 @@ QtObject:
proc asyncContactInfoLoaded*(self: Service, pubkeyAndRpcResponse: string) {.slot.} = proc asyncContactInfoLoaded*(self: Service, pubkeyAndRpcResponse: string) {.slot.} =
let rpcResponseObj = pubkeyAndRpcResponse.parseJson let rpcResponseObj = pubkeyAndRpcResponse.parseJson
let publicKey = $rpcResponseObj{"publicKey"} let publicKey = $rpcResponseObj{"publicKey"}
let requestError = rpcResponseObj{"error"}
var error : string
if (rpcResponseObj{"response"}{"error"}.kind != JNull): if requestError.kind != JNull:
let error = Json.decode($rpcResponseObj["response"]["error"], RpcError) error = $requestError
error "Error requesting contact info", msg = error.message, publicKey else:
let responseError = rpcResponseObj{"response"}{"error"}
if responseError.kind != JNull:
error = Json.decode($responseError, RpcError).message
if len(error) != 0:
error "error requesting contact info", msg = error, publicKey
self.events.emit(SIGNAL_CONTACT_INFO_REQUEST_FINISHED, ContactInfoRequestArgs(publicKey: publicKey, ok: false)) self.events.emit(SIGNAL_CONTACT_INFO_REQUEST_FINISHED, ContactInfoRequestArgs(publicKey: publicKey, ok: false))
return return

View File

@ -41,6 +41,18 @@ Item {
implicitWidth: mainLayout.implicitWidth implicitWidth: mainLayout.implicitWidth
implicitHeight: mainLayout.implicitHeight implicitHeight: mainLayout.implicitHeight
QtObject {
id: d
function paste() {
root.suggestionsDialog.forceHide = true
edit.pasteOperation = true
edit.paste()
root.textPasted(edit.text)
edit.pasteOperation = false
}
}
RowLayout { RowLayout {
id: mainLayout id: mainLayout
anchors.fill: parent anchors.fill: parent
@ -118,13 +130,17 @@ Item {
cursorVisible: edit.cursorVisible cursorVisible: edit.cursorVisible
} }
onTextEdited: if (suggestionsDialog.forceHide && !pasteOperation) onTextEdited: {
if (suggestionsDialog.forceHide && !pasteOperation)
suggestionsDialog.forceHide = false suggestionsDialog.forceHide = false
}
Keys.onPressed: (event) => {
Keys.onPressed: {
if (event.matches(StandardKey.Paste)) { if (event.matches(StandardKey.Paste)) {
pasteOperation = true event.accepted = true
root.suggestionsDialog.forceHide = true d.paste()
return
} }
if (suggestionsDialog.visible) { if (suggestionsDialog.visible) {
@ -149,17 +165,6 @@ Item {
} }
} }
} }
Keys.onReleased: {
if (event.matches(StandardKey.Paste)) {
event.accepted = true
pasteOperation = false
if (text) {
root.textPasted(text)
}
}
}
} }
// ensure edit cursor is visible // ensure edit cursor is visible

View File

@ -33,7 +33,14 @@ MembersSelectorBase {
} }
edit.onTextChanged: { edit.onTextChanged: {
d.lookupContact(edit.text) // When edited, give a small delay in case next character is printed soon
contactLookupDelayTimer.start()
}
onTextPasted: (text) => {
// When pated, process text immediately
contactLookupDelayTimer.stop() // when pasting, textChanged is still emited first
d.lookupContact(text)
} }
model: SortFilterProxyModel { model: SortFilterProxyModel {
@ -55,11 +62,52 @@ MembersSelectorBase {
property ListModel selectedMembers: ListModel {} property ListModel selectedMembers: ListModel {}
function lookupContact(value) { function lookupContact(value) {
value = value.trim()
if (value.startsWith(Constants.userLinkPrefix)) if (value.startsWith(Constants.userLinkPrefix))
value = value.slice(Constants.userLinkPrefix.length) value = value.slice(Constants.userLinkPrefix.length)
if (Utils.isCompressedPubKey(value)) if (Utils.isChatKey(value)) {
processContact(value)
return
}
if (Utils.isValidEns(value)) {
root.rootStore.contactsStore.resolveENS(value) root.rootStore.contactsStore.resolveENS(value)
return
}
root.suggestionsDialog.forceHide = false
}
function processContact(publicKey) {
const contactDetails = Utils.getContactDetailsAsJson(publicKey, false)
if (contactDetails.publicKey === "") {
// not a valid key given
root.suggestionsDialog.forceHide = false
return
}
if (contactDetails.publicKey === root.rootStore.contactsStore.myPublicKey ||
contactDetails.isBlocked) {
root.suggestionsDialog.forceHide = false
return
};
if (contactDetails.isContact) {
root.rootStore.mainModuleInst.switchTo(root.rootStore.getMySectionId(), contactDetails.publicKey)
return
}
if (root.model.count === 0 && !root.rootStore.contactsStore.hasPendingContactRequest(contactDetails.publicKey)) {
Global.openContactRequestPopup(contactDetails.publicKey,
popup => popup.closed.connect(root.rejected))
return
}
root.suggestionsDialog.forceHide = false
} }
function addMember(pubKey, displayName, localNickname) { function addMember(pubKey, displayName, localNickname) {
@ -87,6 +135,15 @@ MembersSelectorBase {
} }
} }
Timer {
id: contactLookupDelayTimer
repeat: false
interval: 500
onTriggered: {
d.lookupContact(edit.text)
}
}
Connections { Connections {
enabled: root.visible enabled: root.visible
target: root.rootStore.contactsStore.mainModuleInst target: root.rootStore.contactsStore.mainModuleInst
@ -95,28 +152,7 @@ MembersSelectorBase {
root.suggestionsDialog.forceHide = false root.suggestionsDialog.forceHide = false
return return
} }
d.processContact(resolvedPubKey)
const contactDetails = Utils.getContactDetailsAsJson(resolvedPubKey, false)
if (contactDetails.publicKey === root.rootStore.contactsStore.myPublicKey ||
contactDetails.isBlocked) {
root.suggestionsDialog.forceHide = false
return
};
if (contactDetails.isContact) {
root.rootStore.mainModuleInst.switchTo(root.rootStore.getMySectionId(), contactDetails.publicKey)
return
}
if (root.model.count === 0 && !root.rootStore.contactsStore.hasPendingContactRequest(contactDetails.publicKey)) {
Global.openContactRequestPopup(contactDetails.publicKey,
popup => popup.closed.connect(root.rejected))
return
}
root.suggestionsDialog.forceHide = false
} }
} }
} }