fix(RenameGroupPopup): fix name validation and scrolling
- increase the length limit to 30 and allow `&`, as per the spec - wrap the popup in a scroll view - pls some minor cleanups Fixes #16523
This commit is contained in:
parent
d317df032d
commit
158154bcca
|
@ -61,22 +61,21 @@ Control {
|
|||
function getTagColor(isReadonly) {
|
||||
if(isReadonly)
|
||||
return Theme.palette.baseColor1
|
||||
return mouseArea.containsMouse ? Theme.palette.miscColor1 : Theme.palette.primaryColor1
|
||||
return root.hovered ? Theme.palette.miscColor1 : Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: 30
|
||||
horizontalPadding: d.tagMargins
|
||||
font.pixelSize: 15
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
font.family: Theme.baseFont.name
|
||||
|
||||
background: Rectangle {
|
||||
color: d.getTagColor(root.isReadonly)
|
||||
radius: 8
|
||||
radius: Theme.radius
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
id: tagRow
|
||||
spacing: 2
|
||||
|
||||
StatusIcon {
|
||||
|
@ -99,7 +98,6 @@ Control {
|
|||
height: d.tagIconsSize
|
||||
icon: "close"
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
enabled: !root.isReadonly
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
|
|
@ -73,7 +73,6 @@ Item {
|
|||
Layout.leftMargin: Theme.padding
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: text !== ""
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
Item {
|
||||
|
@ -115,7 +114,7 @@ Item {
|
|||
Layout.minimumWidth: 4
|
||||
Layout.fillHeight: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: 15
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
color: Theme.palette.directColor1
|
||||
|
||||
selectByMouse: true
|
||||
|
@ -193,7 +192,7 @@ Item {
|
|||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
Layout.rightMargin: Theme.padding
|
||||
visible: text !== ""
|
||||
font.pixelSize: 10
|
||||
font.pixelSize: Theme.asideTextFontSize
|
||||
color: Theme.palette.dangerColor1
|
||||
}
|
||||
}
|
||||
|
@ -210,14 +209,12 @@ Item {
|
|||
|
||||
StatusButton {
|
||||
objectName: "inlineSelectorConfirmButton"
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
enabled: (listView.count > 0)
|
||||
text: qsTr("Confirm")
|
||||
onClicked: root.confirmed()
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: qsTr("Cancel")
|
||||
type: StatusBaseButton.Type.Danger
|
||||
onClicked: root.rejected()
|
||||
|
|
|
@ -216,7 +216,6 @@ Rectangle {
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: accountImage.right
|
||||
anchors.leftMargin: Theme.smallPadding
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
SuggestionBoxPanel 1.0 SuggestionBoxPanel.qml
|
||||
UserListPanel 1.0 UserListPanel.qml
|
||||
ChatAnchorButtonsPanel 1.0 ChatAnchorButtonsPanel.qml
|
||||
InlineSelectorPanel 1.0 InlineSelectorPanel.qml
|
||||
|
|
|
@ -290,7 +290,6 @@ Item {
|
|||
&& !d.sendingInProgress
|
||||
}
|
||||
|
||||
store: root.rootStore
|
||||
usersModel: d.activeUsersStore.usersModel
|
||||
sharedStore: root.sharedRootStore
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import QtQuick 2.15
|
|||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQml.Models 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
@ -46,7 +45,6 @@ Page {
|
|||
Behavior on anchors.bottomMargin { NumberAnimation { duration: 30 }}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
|
||||
}
|
||||
|
||||
|
@ -73,14 +71,14 @@ Page {
|
|||
const ensName = member.displayName.includes(".eth") ? member.displayName : ""
|
||||
root.rootStore.chatCommunitySectionModule.createOneToOneChat("", member.pubKey, ensName)
|
||||
} else {
|
||||
var groupName = "";
|
||||
var pubKeys = [];
|
||||
var groupName = []
|
||||
var pubKeys = []
|
||||
for (var i = 0; i < model.count; i++) {
|
||||
const member = model.get(i)
|
||||
groupName += (member.displayName + (i === model.count - 1 ? "" : "&"))
|
||||
groupName.push(member.displayName)
|
||||
pubKeys.push(member.pubKey)
|
||||
}
|
||||
root.rootStore.chatCommunitySectionModule.createGroupChat("", groupName, JSON.stringify(pubKeys))
|
||||
root.rootStore.chatCommunitySectionModule.createGroupChat("", groupName.join("&"), JSON.stringify(pubKeys))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +129,6 @@ Page {
|
|||
Layout.alignment: Qt.AlignTop
|
||||
Layout.leftMargin: Theme.halfPadding
|
||||
visible: contactsList.visible
|
||||
font.pixelSize: 15
|
||||
text: qsTr("Contacts")
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
@ -182,7 +179,6 @@ Page {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("You can only send direct messages to your Contacts.\n
|
||||
Send a contact request to the person you would like to chat with, you will be able to chat with them once they have accepted your contact request.")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
@ -8,14 +8,14 @@ import StatusQ.Core.Utils 0.1
|
|||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import "../panels"
|
||||
import "../stores"
|
||||
import "private"
|
||||
import AppLayouts.Chat.stores 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import "private"
|
||||
|
||||
MembersSelectorBase {
|
||||
id: root
|
||||
|
||||
|
@ -55,7 +55,7 @@ MembersSelectorBase {
|
|||
readonly property string _pubKey: model.pubKey
|
||||
|
||||
height: ListView.view.height
|
||||
text: root.tagText(model.localNickname, model.displayName, model.alias)
|
||||
text: model.preferredDisplayName
|
||||
|
||||
isReadonly: {
|
||||
if (model.memberRole === Constants.memberRole.owner) return true
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQml.Models 2.2
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQml.Models 2.15
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
@ -9,8 +9,6 @@ import "private"
|
|||
|
||||
import utils 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
MembersSelectorBase {
|
||||
id: root
|
||||
|
||||
|
@ -39,20 +37,18 @@ MembersSelectorBase {
|
|||
}
|
||||
|
||||
onTextPasted: (text) => {
|
||||
// When pated, process text immediately
|
||||
contactLookupDelayTimer.stop() // when pasting, textChanged is still emited first
|
||||
// When pasted, process text immediately
|
||||
contactLookupDelayTimer.stop() // when pasting, textChanged is still emitted first
|
||||
d.lookupContact(text)
|
||||
}
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: d.selectedMembers
|
||||
}
|
||||
model: d.selectedMembers
|
||||
|
||||
delegate: StatusTagItem {
|
||||
readonly property string _pubKey: model.pubKey
|
||||
|
||||
height: ListView.view.height
|
||||
text: root.tagText(model.localNickname, model.displayName, model.alias)
|
||||
text: model.localNickname || model.displayName
|
||||
|
||||
onClosed: root.entryRemoved(this)
|
||||
}
|
||||
|
@ -129,11 +125,7 @@ MembersSelectorBase {
|
|||
return false
|
||||
}
|
||||
|
||||
d.selectedMembers.append({
|
||||
"pubKey": pubKey,
|
||||
"displayName": displayName,
|
||||
"localNickname": localNickname
|
||||
})
|
||||
d.selectedMembers.append({pubKey, displayName, localNickname})
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import "../../panels"
|
||||
|
||||
import AppLayouts.Chat.stores 1.0 as ChatStores
|
||||
import AppLayouts.Chat.panels 1.0
|
||||
|
||||
import utils 1.0
|
||||
import shared.controls.delegates 1.0
|
||||
|
@ -25,10 +22,6 @@ InlineSelectorPanel {
|
|||
readonly property int membersLimit: 20 // see: https://github.com/status-im/status-mobile/issues/13066
|
||||
property bool limitReached: model.count >= membersLimit
|
||||
|
||||
function tagText(localNickname, displayName, aliasName) {
|
||||
return localNickname || displayName || aliasName
|
||||
}
|
||||
|
||||
property string pastedChatKey: ""
|
||||
|
||||
label.text: qsTr("To:")
|
||||
|
@ -54,41 +47,32 @@ InlineSelectorPanel {
|
|||
return true
|
||||
}
|
||||
|
||||
function isPastedProfileLinkToContact(pubkey) {
|
||||
return root.pastedChatKey === pubkey
|
||||
}
|
||||
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
FastExpressionFilter {
|
||||
enabled: root.edit.text !== "" && root.pastedChatKey == ""
|
||||
expression: {
|
||||
root.edit.text // ensure expression is reevaluated when edit.text changes
|
||||
return _suggestionsModel.searchPredicate(model.displayName, model.localNickname, model.alias)
|
||||
}
|
||||
expectedRoles: ["displayName", "localNickname", "alias"]
|
||||
},
|
||||
ExpressionFilter {
|
||||
FastExpressionFilter {
|
||||
expression: {
|
||||
root.model.count // ensure expression is reevaluated when members model changes
|
||||
return _suggestionsModel.notAMemberPredicate(model.pubKey)
|
||||
}
|
||||
expectedRoles: ["pubKey"]
|
||||
},
|
||||
ExpressionFilter {
|
||||
enabled: root.pastedChatKey != ""
|
||||
expression: {
|
||||
root.pastedChatKey // ensure expression is reevaluated when members model changes
|
||||
return _suggestionsModel.isPastedProfileLinkToContact(model.pubKey)
|
||||
}
|
||||
ValueFilter {
|
||||
roleName: "pubKey"
|
||||
value: root.pastedChatKey
|
||||
enabled: root.pastedChatKey !== ""
|
||||
}
|
||||
]
|
||||
|
||||
proxyRoles: ExpressionRole {
|
||||
name: "title"
|
||||
expression: model.localNickname || model.displayName || model.alias
|
||||
}
|
||||
|
||||
sorters: StringSorter {
|
||||
roleName: "title"
|
||||
numericMode: true
|
||||
roleName: "preferredDisplayName"
|
||||
caseSensitivity: Qt.CaseInsensitive
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQml.Models 2.14
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQml.Models 2.15
|
||||
|
||||
import shared.controls 1.0
|
||||
import shared.panels 1.0
|
||||
|
@ -26,11 +26,11 @@ StatusDialog {
|
|||
|
||||
title: qsTr("Edit group name and image")
|
||||
width: 480
|
||||
height: 610
|
||||
padding: 0
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int nameCharLimit: 24
|
||||
readonly property int nameCharLimit: 30 // cf spec: https://github.com/status-im/feature-specs/blob/d66c586f13cb1fa0486544030148df68e06928f0/content/raw/chat/group_chat.md
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
|
@ -47,66 +47,71 @@ StatusDialog {
|
|||
imageEditor.dataImage = activeGroupImageData
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
anchors.fill: parent
|
||||
spacing: 20
|
||||
contentWidth: availableWidth
|
||||
|
||||
StatusInput {
|
||||
id: groupName
|
||||
input.edit.objectName: "groupChatEdit_name"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
label: qsTr("Name the group")
|
||||
charLimit: d.nameCharLimit
|
||||
ColumnLayout {
|
||||
width: scrollView.availableWidth
|
||||
spacing: 20
|
||||
|
||||
validators: [
|
||||
StatusMinLengthValidator {
|
||||
minLength: 1
|
||||
errorMessage: Utils.getErrorMessage(groupName.errors, qsTr("group name"))
|
||||
},
|
||||
StatusRegularExpressionValidator {
|
||||
regularExpression: Constants.regularExpressions.alphanumericalExpanded
|
||||
errorMessage: Constants.errorMessages.alphanumericalExpandedRegExp
|
||||
}
|
||||
]
|
||||
}
|
||||
StatusInput {
|
||||
id: groupName
|
||||
input.edit.objectName: "groupChatEdit_name"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
label: qsTr("Name the group")
|
||||
charLimit: d.nameCharLimit
|
||||
|
||||
StatusBaseText {
|
||||
id: imgText
|
||||
text: qsTr("Group image")
|
||||
leftPadding: groupName.leftPadding - root.padding
|
||||
}
|
||||
validators: [
|
||||
StatusMinLengthValidator {
|
||||
minLength: 1
|
||||
errorMessage: Utils.getErrorMessage(groupName.errors, qsTr("group name"))
|
||||
},
|
||||
StatusRegularExpressionValidator {
|
||||
regularExpression: Constants.regularExpressions.alphanumericalExpanded2
|
||||
errorMessage: Constants.errorMessages.alphanumericalExpandedRegExp
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
EditCroppedImagePanel {
|
||||
id: imageEditor
|
||||
objectName: "groupChatEdit_image"
|
||||
Layout.preferredWidth: 128
|
||||
Layout.preferredHeight: Layout.preferredWidth / aspectRatio
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
StatusBaseText {
|
||||
id: imgText
|
||||
text: qsTr("Group image")
|
||||
}
|
||||
|
||||
imageFileDialogTitle: qsTr("Choose an image as logo")
|
||||
title: qsTr("Edit group name and image")
|
||||
acceptButtonText: qsTr("Use as an icon for this group chat")
|
||||
}
|
||||
EditCroppedImagePanel {
|
||||
id: imageEditor
|
||||
objectName: "groupChatEdit_image"
|
||||
Layout.preferredWidth: 128
|
||||
Layout.preferredHeight: Layout.preferredWidth / aspectRatio
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
StatusBaseText {
|
||||
id: colorText
|
||||
text: qsTr("Standard colours")
|
||||
leftPadding: groupName.leftPadding - root.padding
|
||||
}
|
||||
imageFileDialogTitle: qsTr("Choose an image as logo")
|
||||
title: qsTr("Edit group name and image")
|
||||
acceptButtonText: qsTr("Use as an icon for this group chat")
|
||||
}
|
||||
|
||||
StatusColorSelectorGrid {
|
||||
id: colorSelectionGrid
|
||||
objectName: "groupChatEdit_color"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
diameter: 40
|
||||
selectorDiameter: 16
|
||||
columns: 6
|
||||
selectedColorIndex: -1
|
||||
}
|
||||
StatusBaseText {
|
||||
id: colorText
|
||||
text: qsTr("Standard colours")
|
||||
}
|
||||
|
||||
Item {
|
||||
id: spacerItem
|
||||
height: 10
|
||||
StatusColorSelectorGrid {
|
||||
id: colorSelectionGrid
|
||||
objectName: "groupChatEdit_color"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: -(parent.spacing / 3)
|
||||
diameter: 40
|
||||
selectorDiameter: 16
|
||||
columns: 6
|
||||
selectedColorIndex: -1
|
||||
}
|
||||
|
||||
Item {
|
||||
id: spacerItem
|
||||
height: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ Rectangle {
|
|||
signal dismissLinkPreview(int index)
|
||||
|
||||
property var usersModel
|
||||
property ChatStores.RootStore store
|
||||
property SharedStores.RootStore sharedStore
|
||||
|
||||
property var emojiPopup: null
|
||||
|
|
|
@ -54,16 +54,6 @@ StatusMenu {
|
|||
onTriggered: root.displayProfilePopup(root.chatId)
|
||||
}
|
||||
|
||||
StatusAction {
|
||||
objectName: "viewMembersStatusAction"
|
||||
text: qsTr("View Members")
|
||||
icon.name: "group-chat"
|
||||
enabled: root.chatType === Constants.chatType.privateGroupChat
|
||||
onTriggered: {
|
||||
localAccountSensitiveSettings.expandUsersList = !localAccountSensitiveSettings.expandUsersList;
|
||||
}
|
||||
}
|
||||
|
||||
StatusAction {
|
||||
objectName: "addRemoveFromGroupStatusAction"
|
||||
text: root.amIChatAdmin ? qsTr("Add / remove from group") : qsTr("Add to group")
|
||||
|
|
|
@ -933,7 +933,6 @@ Loader {
|
|||
suggestionsOpened = false
|
||||
}
|
||||
|
||||
store: root.rootStore
|
||||
usersModel: root.usersStore.usersModel
|
||||
sharedStore: root.sharedRootStore
|
||||
emojiPopup: root.emojiPopup
|
||||
|
@ -957,7 +956,7 @@ Loader {
|
|||
|
||||
linkPreviewModel: root.linkPreviewModel
|
||||
gifLinks: root.gifLinks
|
||||
playAnimations: root.Window.window.active && root.messageStore.isChatActive
|
||||
playAnimations: root.Window.active && root.messageStore.isChatActive
|
||||
isOnline: root.rootStore.mainModuleInst.isOnline
|
||||
highlightLink: delegate.hoveredLink
|
||||
onImageClicked: (image, mouse, imageSource, url) => {
|
||||
|
|
|
@ -659,6 +659,7 @@ QtObject {
|
|||
readonly property var alphanumerical: /^$|^[a-zA-Z0-9]+$/
|
||||
readonly property var alphanumericalExpanded: /^$|^[a-zA-Z0-9\-_\.\u0020]+$/
|
||||
readonly property var alphanumericalExpanded1: /^[a-zA-Z0-9\-_]+(?: [a-zA-Z0-9\-_]+)*$/
|
||||
readonly property var alphanumericalExpanded2: /^$|^[a-zA-Z0-9\-_\.\u0020\&]+$/
|
||||
readonly property var alphanumericalWithSpace: /^$|^[a-zA-Z0-9\s]+$/
|
||||
readonly property var asciiPrintable: /^$|^[!-~]+$/
|
||||
readonly property var ascii: /^$|^[\x00-\x7F]+$/
|
||||
|
|
Loading…
Reference in New Issue