diff --git a/src/app/commoncomponents/MaterialTextField.qml b/src/app/commoncomponents/MaterialTextField.qml index c193061620017eab10da88ab59d4fe0fbda1dbc5..155347eb3363de50bbd0d43beeab08f938aae202 100644 --- a/src/app/commoncomponents/MaterialTextField.qml +++ b/src/app/commoncomponents/MaterialTextField.qml @@ -26,7 +26,7 @@ TextField { // We need to remove focus when another widget takes activeFocus, // except the context menu. - property bool isActive: activeFocus || contextMenu.active + property bool isActive: activeFocus || contextMenu.active || root.text.toString() !== '' onActiveFocusChanged: { if (!activeFocus && !contextMenu.active) { root.focus = false @@ -39,7 +39,10 @@ TextField { property alias prefixIconColor: prefixIcon.color property string suffixIconSrc property alias suffixIconColor: suffixIcon.color - property color accent: isActive + property string suffixBisIconSrc + property alias suffixBisIconColor: suffixBisIcon.color + + property color accent: isActive || hovered ? prefixIconColor : JamiTheme.buttonTintedBlue property color baseColor: JamiTheme.primaryForegroundColor @@ -50,15 +53,26 @@ TextField { property alias infoTipText: infoTip.text - wrapMode: Text.Wrap + wrapMode: "NoWrap" + font.pointSize: JamiTheme.materialLineEditPointSize font.kerning: true selectByMouse: true mouseSelectionMode: TextInput.SelectCharacters - height: implicitHeight leftPadding: readOnly || prefixIconSrc === '' ? 0 : 32 - rightPadding: readOnly || suffixIconSrc === '' ? 0 : 32 + rightPadding: { + var total = 2 + if (!readOnly) { + + if (suffixIconSrc !== "") + total =+ 30 + if (suffixBisIconSrc !== "") + total =+ 30 + } + return total + } + bottomPadding: 20 topPadding: 2 @@ -116,7 +130,7 @@ TextField { visible: opacity HoverHandler { cursorShape: Qt.ArrowCursor } Behavior on opacity { - NumberAnimation { duration: JamiTheme.longFadeDuration } + NumberAnimation { duration: JamiTheme.longFadeDuration/2 } } } @@ -142,7 +156,8 @@ TextField { TextFieldIcon { id: suffixIcon size: 20 - anchors.right: parent.right + anchors.right: suffixBisIcon.left + anchors.rightMargin: suffixBisIconSrc !== '' ? 5 : 0 color: suffixIconColor source: suffixIconSrc @@ -155,5 +170,20 @@ TextField { } } + TextFieldIcon { + id: suffixBisIcon + size: 20 + anchors.right: parent.right + color: suffixBisIconColor + source: suffixBisIconSrc + + TapHandler { + cursorShape: Qt.ArrowCursor + onTapped: { + modalTextEditRoot.icoClicked() + } + } + } + background: null } diff --git a/src/app/commoncomponents/ModalTextEdit.qml b/src/app/commoncomponents/ModalTextEdit.qml index 62a0accda83a473be9509e88f2a96c5e94150634..cd39b2c85d41d46620ef76a5912e419d2b5bf5bd 100644 --- a/src/app/commoncomponents/ModalTextEdit.qml +++ b/src/app/commoncomponents/ModalTextEdit.qml @@ -22,24 +22,27 @@ import net.jami.Constants 1.1 // This component is used to display and edit a value. Loader { id: root - - property string prefixIconSrc - property color prefixIconColor - property string suffixIconSrc - property color suffixIconColor + property string prefixIconSrc: JamiResources.round_edit_24dp_svg + property color prefixIconColor: JamiTheme.editLineColor + property string suffixIconSrc : "" + property color suffixIconColor: JamiTheme.buttonTintedBlue + property string suffixBisIconSrc : "" + property color suffixBisIconColor: JamiTheme.buttonTintedBlue required property string placeholderText - required property string staticText + property string staticText: "" property string dynamicText property bool inputIsValid: true property string infoTipText - - property variant validator + property bool isPersistent: true property real fontPointSize: JamiTheme.materialLineEditPointSize + property bool fontBold: false + + property int echoMode: TextInput.Normal // Always start with the static text component displayed first. - property bool editMode: false + property bool editMode: true // Emitted when the editor has been accepted. signal accepted @@ -47,10 +50,19 @@ Loader { // Always give up focus when accepted. onAccepted: focus = false + // Needed to give proper focus to loaded item + onFocusChanged: { + if (root.focus && root.isPersistent) { + item.forceActiveFocus() + } + } + // This is used when the user is not editing the text. Component { - id: usernameDisplayComp + + id: displayComp MaterialTextField { + font.pointSize: root.fontPointSize readOnly: true text: staticText @@ -60,19 +72,27 @@ Loader { // This is used when the user is editing the text. Component { - id: usernameEditComp + id: editComp + MaterialTextField { + + id: editCompField + focus: true infoTipText: root.infoTipText prefixIconSrc: root.prefixIconSrc prefixIconColor: root.prefixIconColor suffixIconSrc: root.suffixIconSrc suffixIconColor: root.suffixIconColor + suffixBisIconSrc: root.suffixBisIconSrc + suffixBisIconColor: root.suffixBisIconColor font.pointSize: root.fontPointSize + font.bold: root.fontBold + echoMode: root.echoMode placeholderText: root.placeholderText - validator: root.validator onAccepted: root.accepted() onTextChanged: dynamicText = text + onVisibleChanged: text = dynamicText inputIsValid: root.inputIsValid onFocusChanged: if (!focus) root.editMode = false } @@ -81,8 +101,10 @@ Loader { // We use a loader to switch between the two components depending on the // editMode property. sourceComponent: { - editMode - ? usernameEditComp - : usernameDisplayComp + + editMode || isPersistent + ? editComp + : displayComp } + } diff --git a/src/app/commoncomponents/PasswordTextEdit.qml b/src/app/commoncomponents/PasswordTextEdit.qml new file mode 100644 index 0000000000000000000000000000000000000000..841ee2444f4e6449c287c943263412a5041a5365 --- /dev/null +++ b/src/app/commoncomponents/PasswordTextEdit.qml @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 Savoir-faire Linux Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +import QtQuick + +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 +import net.jami.Models 1.1 + +ModalTextEdit { + id: modalTextEditRoot + + property bool firstEntry: false + + signal icoClicked + + prefixIconSrc: firstEntry ? JamiResources.lock_svg : JamiResources.round_edit_24dp_svg + + suffixBisIconSrc: JamiResources.eye_cross_svg + suffixBisIconColor: JamiTheme.buttonTintedBlue + + placeholderText: JamiStrings.password + infoTipText: firstEntry ? JamiStrings.password : "" + staticText: "" + echoMode: TextInput.Password + + onIcoClicked: { + if (echoMode == TextInput.Normal) { + echoMode = TextInput.Password + suffixBisIconSrc = JamiResources.eye_cross_svg + } else { + echoMode = TextInput.Normal + suffixBisIconSrc = JamiResources.noun_eye_svg + } + } + + function startEditing() { + root.editMode = true + forceActiveFocus() + } +} + diff --git a/src/app/commoncomponents/UsernameTextEdit.qml b/src/app/commoncomponents/UsernameTextEdit.qml index 71090d24b4ef8e52f8585675b819ddf6ba7e6150..774e53ff26514a6c0c2c23872dbe97e11cc4e95a 100644 --- a/src/app/commoncomponents/UsernameTextEdit.qml +++ b/src/app/commoncomponents/UsernameTextEdit.qml @@ -57,12 +57,10 @@ ModalTextEdit { infoTipText: JamiStrings.usernameToolTip placeholderText: JamiStrings.chooseAUsername - staticText: hasRegisteredName ? registeredName : infohash enum NameRegistrationState { BLANK, INVALID, TAKEN, FREE, SEARCHING } property int nameRegistrationState: UsernameLineEdit.NameRegistrationState.BLANK - validator: RegularExpressionValidator { regularExpression: /[A-z0-9_]{0,32}/ } inputIsValid: dynamicText.length === 0 || nameRegistrationState === UsernameLineEdit.NameRegistrationState.FREE