diff --git a/ui/app/AppLayouts/Chat/panels/InlineSelectorPanel.qml b/ui/app/AppLayouts/Chat/panels/InlineSelectorPanel.qml index 749b2736b8..d66ad10e81 100644 --- a/ui/app/AppLayouts/Chat/panels/InlineSelectorPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/InlineSelectorPanel.qml @@ -24,9 +24,15 @@ Item { readonly property alias warningLabel: warningLabel readonly property alias edit: edit + property bool confirmBtnEnabled: (listView.count > 0) + signal confirmed() signal rejected() + signal enterKeyPressed() + signal upKeyPressed() + signal downKeyPressed() + signal entryAccepted(var suggestionsDelegate) signal entryRemoved(var delegate) signal textPasted(string text) @@ -60,100 +66,105 @@ Item { Item { Layout.fillWidth: true Layout.fillHeight: true - StatusScrollView { - id: scrollView - anchors.fill: parent - padding: 0 - onContentWidthChanged: { - if (scrollView.contentWidth > scrollView.width) { - scrollView.contentX = scrollView.contentWidth - scrollView.width - } else { - scrollView.contentX = 0 - } - } + onWidthChanged: { + listView.positionViewAtEnd(); + } - RowLayout { - height: scrollView.height + RowLayout { + anchors.fill: parent + Item { + //40 px least space for input + Layout.preferredWidth: (listView.contentWidth < (parent.width - 40)) ? + listView.contentWidth : (parent.width - 40) + Layout.preferredHeight: 44 StatusListView { + clip: true id: listView - Layout.fillWidth: true - Layout.preferredHeight: 30 - implicitWidth: contentWidth + width: parent.width + height: 30 + anchors.verticalCenter: parent.verticalCenter orientation: ListView.Horizontal spacing: Style.current.halfPadding - } - - TextInput { - id: edit - Layout.minimumWidth: 4 - Layout.fillHeight: true - verticalAlignment: Text.AlignVCenter - font.pixelSize: 15 - color: Theme.palette.directColor1 - - selectByMouse: true - selectionColor: Theme.palette.primaryColor2 - selectedTextColor: color - - cursorDelegate: Rectangle { - color: Theme.palette.primaryColor1 - implicitWidth: 2 - radius: 1 - visible: edit.cursorVisible - SequentialAnimation on visible { - loops: Animation.Infinite - running: edit.cursorVisible - PropertyAnimation { to: false; duration: 600; } - PropertyAnimation { to: true; duration: 600; } - } + ScrollBar.horizontal: scrollBar + onCountChanged: { + positionViewAtEnd(); } + } + StatusScrollBar { + id: scrollBar + parent: listView.parent + anchors.top: listView.bottom + anchors.left: listView.left + anchors.right: listView.right + policy: ScrollBar.AsNeeded + visible: resolveVisibility(policy, listView.width, listView.contentWidth) + } + } + TextInput { + id: edit + Layout.fillWidth: true + Layout.fillHeight: true + verticalAlignment: Text.AlignVCenter + font.pixelSize: 15 + color: Theme.palette.directColor1 + clip: true - Keys.onPressed: { - if (event.matches(StandardKey.Paste)) { - event.accepted = true - const previousText = text; - const previousSelectedText = selectedText; - paste() - if (previousText === "" || previousSelectedText.length === previousText.length) - root.textPasted(text) - return; - } + selectByMouse: true + selectionColor: Theme.palette.primaryColor2 + selectedTextColor: color - if (suggestionsDialog.visible) { - if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { - root.entryAccepted(suggestionsListView.itemAtIndex(suggestionsListView.currentIndex)) - } else if (event.key === Qt.Key_Up) { - suggestionsListView.decrementCurrentIndex() - } else if (event.key === Qt.Key_Down) { - suggestionsListView.incrementCurrentIndex() - } - } else { - if (event.key === Qt.Key_Backspace && edit.text === "") { - root.entryRemoved(listView.itemAtIndex(listView.count - 1)) - } else if (event.key === Qt.Key_Return || event.key === Qt.Enter) { - root.confirmed() - } else if (event.key === Qt.Key_Escape) { - root.rejected() - } - } + cursorDelegate: Rectangle { + color: Theme.palette.primaryColor1 + implicitWidth: 2 + radius: 1 + visible: edit.cursorVisible + SequentialAnimation on visible { + loops: Animation.Infinite + running: edit.cursorVisible + PropertyAnimation { to: false; duration: 600; } + PropertyAnimation { to: true; duration: 600; } } } - // ensure edit cursor is visible - Item { - Layout.fillHeight: true - implicitWidth: 1 + Keys.onPressed: { + if (event.matches(StandardKey.Paste)) { + event.accepted = true + const previousText = text; + const previousSelectedText = selectedText; + paste() + if (previousText === "" || previousSelectedText.length === previousText.length) + root.textPasted(text) + return; + } + + if (suggestionsDialog.visible) { + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + root.entryAccepted(suggestionsListView.itemAtIndex(suggestionsListView.currentIndex)) + } else if (event.key === Qt.Key_Up) { + suggestionsListView.decrementCurrentIndex() + } else if (event.key === Qt.Key_Down) { + suggestionsListView.incrementCurrentIndex() + } + } else { + if (event.key === Qt.Key_Backspace && edit.text === "" && listView.count > 0) { + root.entryRemoved(listView.itemAtIndex(listView.count - 1)) + } else if (event.key === Qt.Key_Return || event.key === Qt.Enter) { + root.enterKeyPressed() + } else if (event.key === Qt.Key_Escape) { + root.rejected() + } else if (event.key === Qt.Key_Up) { + root.upKeyPressed(); + } else if (event.key === Qt.Key_Down) { + root.downKeyPressed(); + } + } } } - ScrollBar.horizontal: StatusScrollBar { - id: scrollBar - parent: scrollView.parent - anchors.top: scrollView.bottom - anchors.left: scrollView.left - anchors.right: scrollView.right - policy: ScrollBar.AsNeeded - visible: resolveVisibility(policy, scrollView.width, scrollView.contentWidth) + // ensure edit cursor is visible + Item { + Layout.fillHeight: true + implicitWidth: 1 } } } @@ -181,7 +192,7 @@ Item { StatusButton { objectName: "inlineSelectorConfirmButton" Layout.alignment: Qt.AlignVCenter - enabled: (listView.count > 0) + enabled: root.confirmBtnEnabled text: qsTr("Confirm") onClicked: root.confirmed() } diff --git a/ui/app/AppLayouts/Chat/views/CreateChatView.qml b/ui/app/AppLayouts/Chat/views/CreateChatView.qml index 6de6913128..8e4ad5f57f 100644 --- a/ui/app/AppLayouts/Chat/views/CreateChatView.qml +++ b/ui/app/AppLayouts/Chat/views/CreateChatView.qml @@ -70,6 +70,7 @@ Page { cleanup() chatInput.textInput.clear() + Global.closeCreateChatView(); } onRejected: { @@ -81,6 +82,18 @@ Page { if (visible) edit.forceActiveFocus() } + + onEnterKeyPressed: { + entryAccepted(contactsList.itemAtIndex(contactsList.currentIndex)); + } + + onUpKeyPressed: { + contactsList.decrementCurrentIndex(); + } + + onDownKeyPressed: { + contactsList.incrementCurrentIndex(); + } } StatusActivityCenterButton { @@ -115,13 +128,13 @@ Page { Layout.fillWidth: true Layout.fillHeight: true - visible: membersSelector.suggestionsModel.count && !(membersSelector.edit.text !== "") implicitWidth: contentItem.childrenRect.width model: membersSelector.suggestionsModel delegate: ContactListItemDelegate { width: ListView.view.width + highlighted: ListView.isCurrentItem onClicked: membersSelector.entryAccepted(this) } } @@ -138,22 +151,26 @@ Page { closeGifPopupAfterSelection: true onSendTransactionCommandButtonClicked: { root.rootStore.createChatStartSendTransactionProcess = true; - root.createChat(); + membersSelector.createChat(); } onReceiveTransactionCommandButtonClicked: { root.rootStore.createChatStartReceiveTransactionProcess = true; - root.createChat(); + membersSelector.createChat(); } onStickerSelected: { root.rootStore.createChatStickerHashId = hashId; root.rootStore.createChatStickerPackId = packId; root.rootStore.createChatStickerUrl = url; - root.createChat(); + membersSelector.createChat(); } onSendMessage: { - root.rootStore.createChatFileUrls = chatInput.fileUrls; - root.rootStore.createChatInitMessage = chatInput.textInput.text; - root.createChat(); + root.rootStore.createChatInitMessage = chatInput.textInput.text + root.rootStore.createChatFileUrls = chatInput.fileUrls + membersSelector.createChat() + + membersSelector.cleanup() + chatInput.textInput.clear() + Global.closeCreateChatView(); } } } diff --git a/ui/app/AppLayouts/Chat/views/MembersEditSelectorView.qml b/ui/app/AppLayouts/Chat/views/MembersEditSelectorView.qml index d5940a1675..3bf9707835 100644 --- a/ui/app/AppLayouts/Chat/views/MembersEditSelectorView.qml +++ b/ui/app/AppLayouts/Chat/views/MembersEditSelectorView.qml @@ -23,6 +23,7 @@ MembersSelectorBase { property var sectionModule property var chatContentModule + confirmBtnEnabled: true onConfirmed: { d.updateGroupMembers() d.resetTemporaryModel() @@ -31,7 +32,7 @@ MembersSelectorBase { onRejected: { d.resetTemporaryModel() } - + limitReached: (model.count === membersLimit) onEntryAccepted: { if (!root.limitReached) { d.appendTemporaryModel(suggestionsDelegate._pubKey, suggestionsDelegate.userName) diff --git a/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml b/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml index 08ee56dbcb..f530a1c82c 100644 --- a/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml +++ b/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml @@ -14,17 +14,15 @@ import SortFilterProxyModel 0.2 MembersSelectorBase { id: root - limitReached: model.count >= membersLimit - 1 // -1 because creator is not on the list of members when creating chat - function cleanup() { - root.edit.clear() - d.selectedMembers.clear() + root.edit.clear(); + d.selectedMembers.clear(); } onEntryAccepted: { if (root.limitReached) return - if (d.addMember(suggestionsDelegate._pubKey, suggestionsDelegate.userName)) + if (d.addMember(suggestionsDelegate._pubKey, suggestionsDelegate.userName, suggestionsDelegate.isAdmin)) root.edit.clear() } @@ -44,7 +42,8 @@ MembersSelectorBase { readonly property string _pubKey: model.pubKey height: ListView.view.height text: model.displayName - + isReadonly: model.isAdmin + icon: model.isAdmin ? "crown" : "" onClicked: root.entryRemoved(this) } @@ -59,7 +58,7 @@ MembersSelectorBase { root.rootStore.contactsStore.resolveENS(value) } - function addMember(pubKey, displayName) { + function addMember(pubKey, displayName, isAdmin) { for (let i = 0; i < d.selectedMembers.count; ++i) { if (d.selectedMembers.get(i).pubKey === pubKey) return false @@ -67,7 +66,8 @@ MembersSelectorBase { d.selectedMembers.append({ "pubKey": pubKey, - "displayName": displayName + "displayName": displayName, + "isAdmin": isAdmin }) return true } diff --git a/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml b/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml index 95907d19d4..1f437e07ec 100644 --- a/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml +++ b/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml @@ -21,7 +21,7 @@ InlineSelectorPanel { property var rootStore readonly property int membersLimit: 20 // see: https://github.com/status-im/status-mobile/issues/13066 - property bool limitReached: model.count >= membersLimit + property bool limitReached: (model.count === (membersLimit-1)) label.text: qsTr("To:") warningLabel.text: qsTr("%1 USER LIMIT REACHED").arg(membersLimit)