1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-09-10 12:03:18 +02:00

MaterialTextField: fix rendering

+ set the maximum number of characters in the input
+ elide the text when it's too long
+ save on focus change in the settings view

GitLab: #1064
Change-Id: I973ff09cb3ce56cda98a0b40cedde88ac3829c1d
This commit is contained in:
Franck LAURENT 2023-04-07 13:23:10 -04:00 committed by Sébastien Blin
parent 150d198469
commit 334f794490
14 changed files with 165 additions and 450 deletions

View file

@ -117,6 +117,7 @@ Item {
onClicked: {
if (!usernameTextEdit.editMode) {
usernameTextEdit.startEditing()
usernameTextEdit.readOnly = false
} else {
usernameTextEdit.accepted()
}
@ -143,11 +144,14 @@ Item {
id: btnId
source: JamiResources.key_black_24dp_svg
visible: CurrentAccount.registeredName !== ""
toolTipText: JamiStrings.identifierURI
onClicked: {
if (clicked) {
usernameTextEdit.staticText = CurrentAccount.uri
btnId.toolTipText = JamiStrings.identifierRegisterName
} else {
usernameTextEdit.staticText = CurrentAccount.registeredName
btnId.toolTipText = JamiStrings.identifierURI
}
clicked = !clicked
@ -166,8 +170,10 @@ Item {
fontPixelSize: JamiTheme.jamiIdFontSize
editMode: false
isPersistent: false
readOnly: true
onAccepted: {
usernameTextEdit.readOnly = true
if (dynamicText === '') {
return
}

View file

@ -31,16 +31,9 @@ TextField {
property bool isSwarmDetail: false
onActiveFocusChanged: {
root.cursorPosition = 0
if (!activeFocus && !contextMenu.active) {
root.focus = false
}
if (root.focus)
root.cursorPosition = root.text.length
}
Component.onCompleted: {
root.cursorPosition = 0
}
signal keyPressed
@ -68,6 +61,10 @@ TextField {
property alias infoTipText: infoTip.text
property alias infoTipLineText: infoTipLine.text
//https://doc.qt.io/qt-6/qml-qtquick-textinput.html#maximumLength-prop
property var maxCharacters: undefined
maximumLength: maxCharacters ? maxCharacters : 32767
wrapMode: "NoWrap"
font.pixelSize: JamiTheme.materialLineEditPixelSize

View file

@ -40,6 +40,9 @@ Loader {
property string infoTipLineText
property bool isPersistent: true
property string elidedText: ""
property int maxCharacters
property real fontPixelSize: JamiTheme.materialLineEditPixelSize
property bool fontBold: false
@ -85,9 +88,15 @@ Loader {
MaterialTextField {
id: displayCompField
font.pixelSize: root.fontPixelSize
readOnly: true
text: staticText
horizontalAlignment: TextEdit.AlignHCenter
readOnly: root.readOnly
text: elidedText != "" ? elidedText : staticText
horizontalAlignment: elidedText != "" ? TextEdit.AlignLeft : TextEdit.AlignHCenter
isSwarmDetail: root.isSwarmDetail
isSettings: root.isSettings
textColor: root.textColor
placeholderText: root.placeholderText
prefixIconSrc: isSwarmDetail ? "" : root.prefixIconSrc
prefixIconColor: root.prefixIconColor
}
}
@ -129,6 +138,7 @@ Loader {
isSettings: root.isSettings
isSwarmDetail: root.isSwarmDetail
readOnly: root.readOnly
maxCharacters: root.maxCharacters
}
}

View file

@ -882,6 +882,8 @@ Item {
property string identifierDescription: qsTr("Share this Jami identifier to be contacted on this account!")
property string hereIsIdentifier: qsTr("Here is your Jami identifier, don't hesitate to share it in order to be contacted more easily!")
property string jamiIdentity: qsTr("Jami identity")
property string identifierURI: qsTr("Show fingerprint")
property string identifierRegisterName: qsTr("Show registered name")
//New settings
//ManageAccount

View file

@ -560,6 +560,7 @@ Item {
property real materialLineEditSelectedPixelSize: calcSize(12)
property real materialLineEditPadding: 16
property real textEditError: calcSize(15)
property real maximumCharacters: 50
//MaterialButton
property real buttontextPadding: 10

View file

@ -83,13 +83,24 @@ Rectangle {
ModalTextEdit {
id: titleLine
TextMetrics {
id: titleLineTextSize
text: CurrentConversation.title
elide: Text.ElideRight
elideWidth: titleLine.width
font.pixelSize: JamiTheme.materialLineEditPixelSize
}
maxCharacters: JamiTheme.maximumCharacters
isSwarmDetail: true
readOnly: !isAdmin
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.minimumHeight: JamiTheme.preferredFieldHeight
Layout.preferredWidth: Math.min(217,swarmProfileDetails.width - currentAccountAvatar.width - 30 - JamiTheme.settingsMarginSize)
staticText: CurrentConversation.title
elidedText: titleLineTextSize.elidedText
textColor: root.textColor
prefixIconColor: root.textColor
@ -99,10 +110,14 @@ Rectangle {
LRCInstance.selectedConvUid, dynamicText)
}
editMode: false
isPersistent: false
onActiveFocusChanged: {
if(!activeFocus){
if (!activeFocus) {
ConversationsAdapter.updateConversationTitle(LRCInstance.selectedConvUid, dynamicText)
}
titleLine.editMode = activeFocus
}
infoTipLineText: JamiStrings.swarmName
@ -111,15 +126,26 @@ Rectangle {
ModalTextEdit {
id: descriptionLineButton
TextMetrics {
id: descriptionLineButtonTextSize
text: CurrentConversation.description
elide: Text.ElideRight
elideWidth: descriptionLineButton.width
font.pixelSize: JamiTheme.materialLineEditPixelSize
}
maxCharacters: JamiTheme.maximumCharacters
isSwarmDetail: true
readOnly: !isAdmin || CurrentConversation.isCoreDialog
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.minimumHeight: JamiTheme.preferredFieldHeight
Layout.preferredWidth: Math.min(217,swarmProfileDetails.width - currentAccountAvatar.width - 30 - JamiTheme.settingsMarginSize)
staticText: CurrentConversation.description
placeholderText: JamiStrings.addADescription
elidedText: descriptionLineButtonTextSize.elidedText
textColor: root.textColor
prefixIconColor: root.textColor
@ -127,11 +153,15 @@ Rectangle {
onAccepted: ConversationsAdapter.updateConversationDescription(
LRCInstance.selectedConvUid, dynamicText)
editMode: false
isPersistent: false
onActiveFocusChanged: {
if(!activeFocus){
if (!activeFocus) {
ConversationsAdapter.updateConversationDescription(
LRCInstance.selectedConvUid, dynamicText)
}
descriptionLineButton.editMode = activeFocus
}
infoTipLineText: JamiStrings.addADescription

View file

@ -146,6 +146,7 @@ ColumnLayout {
titleField: JamiStrings.turnPassword
onEditFinished: CurrentAccount.password_TURN = dynamicText
isPassword: true
}
SettingsMaterialTextEdit {

View file

@ -133,6 +133,7 @@ ColumnLayout {
staticText: CurrentAccount.password_TLS
onEditFinished: CurrentAccount.password_TLS = dynamicText
isPassword: true
}
}
}

View file

@ -1,225 +0,0 @@
/*
* Copyright (C) 2019-2023 Savoir-faire Linux Inc.
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt.labs.platform
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../../commoncomponents"
Rectangle {
id: root
property bool isSIP
property int contentWidth: currentAccountSettingsColumnLayout.width
property int preferredHeight: currentAccountSettingsColumnLayout.implicitHeight
property int preferredColumnWidth : Math.min(root.width / 2 - 50, 350)
signal navigateToMainView
signal advancedSettingsToggled(bool settingsVisible)
function updateAccountInfoDisplayed() {
bannedContacts.updateAndShowBannedContactsSlot()
}
function getAdvancedSettingsScrollPosition() {
return advancedSettings.y
}
color: JamiTheme.secondaryBackgroundColor
ColumnLayout {
id: currentAccountSettingsColumnLayout
anchors.horizontalCenter: root.horizontalCenter
width: Math.min(JamiTheme.maximumWidthSettingsView, root.width)
UserIdentity {
id: userIdentity
isSIP: root.isSIP
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
itemWidth: preferredColumnWidth
}
MaterialButton {
id: passwdPushButton
visible: !isSIP && CurrentAccount.managerUri === ""
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: JamiTheme.preferredMarginSize
preferredWidth: JamiTheme.preferredFieldWidth
buttontextHeightMargin: JamiTheme.buttontextHeightMargin
color: JamiTheme.buttonTintedBlack
hoveredColor: JamiTheme.buttonTintedBlackHovered
pressedColor: JamiTheme.buttonTintedBlackPressed
secondary: true
toolTipText: CurrentAccount.hasArchivePassword ?
JamiStrings.changeCurrentPassword :
JamiStrings.setAPassword
text: CurrentAccount.hasArchivePassword ?
JamiStrings.changePassword :
JamiStrings.setPassword
iconSource: JamiResources.round_edit_24dp_svg
onClicked: viewCoordinator.presentDialog(
appWindow,
"commoncomponents/PasswordDialog.qml",
{ purpose: CurrentAccount.hasArchivePassword ?
PasswordDialog.ChangePassword :
PasswordDialog.SetPassword })
}
MaterialButton {
id: btnExportAccount
visible: !isSIP && CurrentAccount.managerUri === ""
Layout.alignment: Qt.AlignHCenter
preferredWidth: JamiTheme.preferredFieldWidth
buttontextHeightMargin: JamiTheme.buttontextHeightMargin
color: JamiTheme.buttonTintedBlack
hoveredColor: JamiTheme.buttonTintedBlackHovered
pressedColor: JamiTheme.buttonTintedBlackPressed
secondary: true
toolTipText: JamiStrings.tipBackupAccount
text: JamiStrings.backupAccountBtn
iconSource: JamiResources.round_save_alt_24dp_svg
onClicked: {
var dlg = viewCoordinator.presentDialog(
appWindow,
"commoncomponents/JamiFileDialog.qml",
{
title: JamiStrings.backupAccountHere,
fileMode: FileDialog.SaveFile,
folder: StandardPaths.writableLocation(StandardPaths.DesktopLocation),
nameFilters: [JamiStrings.jamiArchiveFiles, JamiStrings.allFiles]
})
dlg.fileAccepted.connect(function (file) {
// is there password? If so, go to password dialog, else, go to following directly
var exportPath = UtilsAdapter.getAbsPath(file.toString())
if (CurrentAccount.hasArchivePassword) {
viewCoordinator.presentDialog(
appWindow,
"commoncomponents/PasswordDialog.qml",
{
purpose: PasswordDialog.ExportAccount,
path: exportPath
})
return
} else if (exportPath.length > 0) {
var success = AccountAdapter.model.exportToFile(LRCInstance.currentAccountId, exportPath)
viewCoordinator.presentDialog(
appWindow,
"commoncomponents/SimpleMessageDialog.qml",
{
title: success ? JamiStrings.success : JamiStrings.error,
infoText: success ? JamiStrings.backupSuccessful : JamiStrings.backupFailed,
buttonTitles: [JamiStrings.optionOk],
buttonStyles: [SimpleMessageDialog.ButtonStyle.TintedBlue]
})
}
})
}
}
MaterialButton {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: CurrentAccount.type === Profile.Type.SIP ? JamiTheme.preferredMarginSize : 0
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
preferredWidth: JamiTheme.preferredFieldWidth
buttontextHeightMargin: JamiTheme.buttontextHeightMargin
color: JamiTheme.buttonTintedRed
hoveredColor: JamiTheme.buttonTintedRedHovered
pressedColor: JamiTheme.buttonTintedRedPressed
text: JamiStrings.deleteAccount
iconSource: JamiResources.delete_forever_24dp_svg
onClicked: {
var dlg = viewCoordinator.presentDialog(
appWindow,
"commoncomponents/DeleteAccountDialog.qml",
{
isSIP: CurrentAccount.type === Profile.Type.SIP,
bestName: CurrentAccount.bestName,
accountId: CurrentAccount.uri
})
dlg.accepted.connect(navigateToMainView)
}
}
LinkedDevices {
id: linkedDevices
visible: !isSIP
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
}
BannedContacts {
id: bannedContacts
isSIP: root.isSIP
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
}
AdvancedSettings {
id: advancedSettings
Layout.fillWidth: true
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
Layout.bottomMargin: 8
itemWidth: preferredColumnWidth
isSIP: root.isSIP
onShowAdvancedSettingsRequest: {
advancedSettingsToggled(settingsVisible)
}
}
}
}

View file

@ -72,14 +72,35 @@ SettingsPageBase {
ModalTextEdit {
id: displayNameLineEdit
TextMetrics {
id: displayNameLineEditTextSize
text: CurrentAccount.alias
elide: Text.ElideRight
elideWidth: displayNameLineEdit.width
font.pixelSize: JamiTheme.materialLineEditPixelSize
}
maxCharacters: JamiTheme.maximumCharacters
editMode: false
isPersistent: false
Layout.alignment: Qt.AlignCenter
Layout.preferredHeight: JamiTheme.preferredFieldHeight + 8
Layout.fillWidth: true
staticText: CurrentAccount.alias
placeholderText: JamiStrings.enterNickname
elidedText: displayNameLineEditTextSize.elidedText
onAccepted: AccountAdapter.setCurrAccDisplayName(dynamicText)
onActiveFocusChanged: {
if (!activeFocus) {
AccountAdapter.setCurrAccDisplayName(dynamicText)
}
displayNameLineEdit.editMode = activeFocus
}
}
}

View file

@ -1,141 +0,0 @@
/*
* Copyright (C) 2020-2023 Savoir-faire Linux Inc.
* Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../../commoncomponents"
ColumnLayout {
id: root
property int itemWidth
// Identity
Row {
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.preferredFieldHeight
spacing: width - idLabel.width - currentRingID.width
Label {
id: idLabel
anchors.verticalCenter: parent.verticalCenter
text: JamiStrings.identifier
color: JamiTheme.textColor
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
MaterialLineEdit {
id: currentRingID
anchors.verticalCenter: parent.verticalCenter
width: parent.width - idLabel.width
- JamiTheme.preferredMarginSize
height: JamiTheme.preferredFieldHeight
font.pointSize: JamiTheme.textFontSize
font.kerning: true
font.bold: true
padding: 0
readOnly: true
selectByMouse: true
wrapMode: Text.NoWrap
text: currentRingIDText.elidedText
color: JamiTheme.textColor
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
TextMetrics {
id: currentRingIDText
font: currentRingID.font
elide: Text.ElideRight
elideWidth: root.width - idLabel.width -
JamiTheme.preferredMarginSize * 4
text: CurrentAccount.uri
}
}
}
Row {
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.preferredFieldHeight
spacing: width - lblRegisteredName.width - currentRegisteredID.width
Label {
id: lblRegisteredName
anchors.verticalCenter: parent.verticalCenter
text: JamiStrings.username
color: JamiTheme.textColor
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
UsernameTextEdit {
id: currentRegisteredID
width: JamiTheme.preferredFieldWidth
height: JamiTheme.preferredFieldHeight + 16
anchors.margins: 8
fontPixelSize: JamiTheme.jamiIdFontSize
staticText: CurrentAccount.registeredName
placeholderText: JamiStrings.chooseUsername
editMode: !CurrentAccount.registeredName
isPersistent: !CurrentAccount.registeredName
onAccepted: {
if (dynamicText === '') {
return
}
var dlg = viewCoordinator.presentDialog(
appWindow,
"settingsview/components/NameRegistrationDialog.qml",
{ registeredName: dynamicText })
dlg.accepted.connect(function() {
currentRegisteredID.nameRegistrationState =
UsernameTextEdit.NameRegistrationState.BLANK
})
}
}
}
}

View file

@ -57,6 +57,14 @@ RowLayout {
ModalTextEdit {
id: modalTextEdit
TextMetrics {
id: modalTextEditTextSize
text: root.staticText
elide: Text.ElideRight
elideWidth: itemWidth - 40
font.pixelSize: JamiTheme.materialLineEditPixelSize
}
visible: !root.isPassword
isSettings: true
@ -64,23 +72,24 @@ RowLayout {
Layout.preferredWidth: itemWidth
staticText: root.staticText
placeholderText: root.placeholderText ? root.placeholderText : root.titleField
elidedText: modalTextEditTextSize.elidedText
onAccepted: {
root.dynamicText = dynamicText
editFinished()
}
Timer {
id: debounceTimer
interval: 500
onTriggered: {
root.dynamicText = modalTextEdit.dynamicText
editFinished()
}
}
editMode: false
isPersistent: false
onKeyPressed: {
debounceTimer.restart()
onActiveFocusChanged: {
if(!activeFocus){
root.dynamicText = dynamicText
editFinished()
modalTextEdit.editMode = false
} else {
modalTextEdit.editMode = true
}
}
}

View file

@ -1,60 +0,0 @@
/*
* Copyright (C) 2020-2023 Savoir-faire Linux Inc.
* Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Layouts
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../../commoncomponents"
ColumnLayout {
id: root
property int itemWidth
property bool isSIP
ElidedTextLabel {
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.preferredFieldHeight
eText: JamiStrings.identity
maxWidth: root.width - 72
fontSize: JamiTheme.headerFontSize
}
JamiUserIdentity {
id: jamiUserIdentity
visible: !root.isSIP
itemWidth: root.itemWidth
Layout.fillWidth: true
Layout.leftMargin: JamiTheme.preferredMarginSize
}
SIPUserIdentity {
id: sipUserIdentity
visible: root.isSIP
itemWidth: root.itemWidth
Layout.fillWidth: true
Layout.leftMargin: JamiTheme.preferredMarginSize
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
* Author: Franck Laurent <franck.laurent@savoirfairelinux.com>
*
* 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 QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import QtTest
import net.jami.Models 1.1
import net.jami.Constants 1.1
import "../../../src/app/"
import "../../../src/app/commoncomponents"
ColumnLayout {
id: root
spacing: 0
width: 300
height: 300
MaterialTextField {
id: textField
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: root.width
Layout.maximumWidth: JamiTheme.chatViewMaximumWidth
Layout.preferredHeight: root.height
maxCharacters: 20
TestCase {
name: "Check maxCharacters for MaterialTextField"
when: windowShown
function test_maxCharacters_material_text_field() {
compare(textField.maximumLength, 20)
textField.text = "Small title"
compare(textField.text, "Small title")
textField.text = "Long title more than 20 characted"
compare(textField.text, "Long title more than")
}
}
}
}