1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-09-04 22:23:32 +02:00

settings: fix username registration

Make username registration line edit a common component

Gitlab: #56
Change-Id: Icb5dc1c8acc6d56f699f9a1cc4ebee6976f5eae1
This commit is contained in:
Ming Rui Zhang 2020-09-08 15:50:58 -04:00
parent 2e0e250a2c
commit c2411af6c9
9 changed files with 211 additions and 280 deletions

View file

@ -111,5 +111,6 @@
<file>src/constant/JamiQmlUtils.qml</file>
<file>src/wizardview/components/AccountCreationStepIndicator.qml</file>
<file>src/commoncomponents/SpinnerButton.qml</file>
<file>src/commoncomponents/UsernameLineEdit.qml</file>
</qresource>
</RCC>

View file

@ -19,7 +19,6 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtGraphicalEffects 1.15
import QtQuick.Layouts 1.15
import "../constant"
@ -27,7 +26,7 @@ Button {
id: root
property alias fontCapitalization: buttonText.font.capitalization
property alias source: root.icon.source
property alias source: buttonImage.source
property string toolTipText: ""
property var color: "transparent"
property var hoveredColor: undefined
@ -37,80 +36,92 @@ Button {
property var preferredWidth: 400
property var preferredHeight: 36
property var minimumIconTextSpacing: 10
property var iconPreferredHeight: 18
property var iconPreferredWidth: 18
property int elide: Text.ElideRight
font.kerning: true
icon.source: ""
icon.height: 18
icon.width: 18
hoverEnabled: hoveredColor !== undefined
contentItem: Item {
Rectangle {
anchors.fill: parent
color: "transparent"
RowLayout {
anchors.fill: parent
anchors.centerIn: parent
AnimatedImage {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: 8
Layout.preferredHeight: root.icon.height
Layout.preferredWidth: root.icon.width
AnimatedImage {
id: buttonAnimatedImage
source: animatedImageSource
playing: true
paused: false
fillMode: Image.PreserveAspectFit
mipmap: true
visible: animatedImageSource !== ""
}
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: JamiTheme.preferredMarginSize / 2
Image {
source: root.icon.source
Layout.preferredWidth: root.icon.width
Layout.preferredHeight: root.icon.height
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: JamiTheme.preferredMarginSize / 2
layer {
enabled: true
effect: ColorOverlay {
id: overlay
color:{
if (!outlined)
return "white"
if (hovered && root.hoveredColor)
return root.hoveredColor
if (checked && root.pressedColor)
return root.pressedColor
return root.color
}
height: iconPreferredHeight
width: iconPreferredWidth
source: animatedImageSource
playing: true
paused: false
fillMode: Image.PreserveAspectFit
mipmap: true
visible: animatedImageSource.length !== 0
}
Image {
id: buttonImage
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: JamiTheme.preferredMarginSize / 2
height: iconPreferredHeight
width: iconPreferredWidth
visible: source.toString().length !== 0
layer {
enabled: true
effect: ColorOverlay {
id: overlay
color:{
if (!outlined)
return "white"
if (hovered && root.hoveredColor)
return root.hoveredColor
if (checked && root.pressedColor)
return root.pressedColor
return root.color
}
}
}
Text {
id: buttonText
}
Layout.rightMargin: root.icon.width + JamiTheme.preferredMarginSize / 2
text: root.text
elide: root.elide
color: {
if (!outlined)
return "white"
if (hovered && root.hoveredColor)
return root.hoveredColor
if (checked && root.pressedColor)
return root.pressedColor
return root.color
}
font: root.font
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
Text {
id: buttonText
anchors.centerIn: parent
width: {
var iconWidth = (buttonAnimatedImage.visible || buttonImage.visible) ?
iconPreferredWidth : 0
return (parent.width / 2 - iconWidth -
JamiTheme.preferredMarginSize / 2 - minimumIconTextSpacing) * 2
}
text: root.text
elide: root.elide
color: {
if (!outlined)
return "white"
if (hovered && root.hoveredColor)
return root.hoveredColor
if (checked && root.pressedColor)
return root.pressedColor
return root.color
}
font: root.font
horizontalAlignment: Text.AlignHCenter
}
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@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 2.14
import QtQuick.Controls 2.14
import net.jami.Models 1.0
MaterialLineEdit {
id: root
enum NameRegistrationState {
BLANK,
INVALID,
TAKEN,
FREE,
SEARCHING
}
property int nameRegistrationState: UsernameLineEdit.NameRegistrationState.BLANK
Connections {
id: registeredNameFoundConnection
target: ClientWrapper.nameDirectory
function onRegisteredNameFound(status, address, name) {
if (text === name) {
switch(status) {
case NameDirectory.LookupStatus.NOT_FOUND:
nameRegistrationState = UsernameLineEdit.NameRegistrationState.FREE
break
case NameDirectory.LookupStatus.ERROR:
case NameDirectory.LookupStatus.INVALID_NAME:
case NameDirectory.LookupStatus.INVALID:
nameRegistrationState = UsernameLineEdit.NameRegistrationState.INVALID
break
case NameDirectory.LookupStatus.SUCCESS:
nameRegistrationState = UsernameLineEdit.NameRegistrationState.TAKEN
break
}
}
}
}
Timer {
id: lookupTimer
repeat: false
interval: 200
onTriggered: {
if (text.length !== 0 && readOnly === false) {
nameRegistrationState = UsernameLineEdit.NameRegistrationState.SEARCHING
ClientWrapper.nameDirectory.lookupName("", text)
} else {
nameRegistrationState = UsernameLineEdit.NameRegistrationState.BLANK
}
}
}
selectByMouse: true
font.pointSize: 9
font.kerning: true
borderColorMode: {
switch (nameRegistrationState){
case UsernameLineEdit.NameRegistrationState.BLANK:
return MaterialLineEdit.NORMAL
case UsernameLineEdit.NameRegistrationState.INVALID:
case UsernameLineEdit.NameRegistrationState.TAKEN:
return MaterialLineEdit.ERROR
case UsernameLineEdit.NameRegistrationState.FREE:
return MaterialLineEdit.RIGHT
case UsernameLineEdit.NameRegistrationState.SEARCHING:
return MaterialLineEdit.SEARCHING
}
}
onTextChanged: lookupTimer.restart()
}

View file

@ -83,7 +83,7 @@ Item {
property int splitViewHandlePreferredWidth: 4
property int textFontSize: 9
property int settingsFontSize: 10
property int settingsFontSize: 9
property int buttonFontSize: 9
property int headerFontSize: 13
property int titleFontSize: 16

View file

@ -33,30 +33,15 @@ import "../../commoncomponents"
Rectangle {
id: root
enum RegName {
BLANK,
INVALIDFORM,
TAKEN,
FREE,
SEARCHING
}
property int regNameUi: CurrentAccountSettingsScrollPage.BLANK
property string registeredName: ""
property bool registeredIdNeedsSet: false
property int refreshVariable : 0
property int preferredColumnWidth : root.width / 2 - 50
signal navigateToMainView
signal navigateToNewWizardView
signal backArrowClicked
function refreshRelevantUI(){
refreshVariable++
refreshVariable--
}
function updateAccountInfoDisplayed() {
setAvatar()
@ -86,7 +71,6 @@ Rectangle {
if (advanceSettingsView.visible) {
advanceSettingsView.updateAccountInfoDisplayedAdvance()
}
refreshRelevantUI()
}
function connectCurrentAccount() {
@ -161,63 +145,6 @@ Rectangle {
}
}
// slots
function verifyRegisteredNameSlot() {
if (ClientWrapper.SettingsAdapter.get_CurrentAccountInfo_RegisteredName() !== "") {
regNameUi = CurrentAccountSettingsScrollPage.BLANK
} else {
registeredName = ClientWrapper.utilsAdaptor.stringSimplifier(
currentRegisteredID.text)
if (registeredName !== "") {
if (ClientWrapper.utilsAdaptor.validateRegNameForm(registeredName)) {
regNameUi = CurrentAccountSettingsScrollPage.SEARCHING
lookUpLabelTimer.restart()
} else {
regNameUi = CurrentAccountSettingsScrollPage.INVALIDFORM
}
} else {
regNameUi = CurrentAccountSettingsScrollPage.BLANK
}
}
}
Timer {
id: lookUpLabelTimer
interval: 300
onTriggered: {
beforeNameLookup()
}
}
function beforeNameLookup() {
ClientWrapper.nameDirectory.lookupName("", registeredName)
}
Connections {
target: ClientWrapper.nameDirectory
enabled: true
function onRegisteredNameFound(status, address, name) {
afterNameLookup(status, name)
}
}
function afterNameLookup(status, regName) {
if (registeredName === regName && regName.length > 2) {
switch (status) {
case NameDirectory.LookupStatus.NOT_FOUND:
regNameUi = CurrentAccountSettingsScrollPage.FREE
break
default:
regNameUi = CurrentAccountSettingsScrollPage.TAKEN
break
}
} else {
regNameUi = CurrentAccountSettingsScrollPage.BLANK
}
}
function setAccEnableSlot(state) {
ClientWrapper.accountModel.setAccountEnabled(ClientWrapper.utilsAdaptor.getCurrAccId(), state)
}
@ -317,14 +244,11 @@ Rectangle {
onAccepted: {
registeredIdNeedsSet = false
currentRegisteredID.nameRegistrationState =
UsernameLineEdit.NameRegistrationState.BLANK
}
}
function slotRegisterName() {
refreshRelevantUI()
nameRegistrationDialog.openNameRegistrationDialog(registeredName)
}
LinkDeviceDialog{
id: linkDeviceDialog
@ -582,7 +506,7 @@ Rectangle {
readOnly: true
selectByMouse: true
text: { currentRingIDText.elidedText }
text: currentRingIDText.elidedText
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
@ -601,9 +525,7 @@ Rectangle {
elide: Text.ElideRight
elideWidth: root.width - idLabel.width -JamiTheme.preferredMarginSize*4
text: { refreshVariable
return ClientWrapper.SettingsAdapter.getCurrentAccount_Profile_Info_Uri()
}
text: ClientWrapper.SettingsAdapter.getCurrentAccount_Profile_Info_Uri()
}
}
}
@ -623,68 +545,53 @@ Rectangle {
maxWidth: width
}
MaterialLineEdit {
UsernameLineEdit {
id: currentRegisteredID
Layout.alignment: Qt.AlignRight
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.fillWidth: true
placeholderText: { refreshVariable
var result = true ?
qsTr("Type here to register a username") : ""
return result}
placeholderText: registeredIdNeedsSet ?
qsTr("Type here to register a username") : ""
text: {
refreshVariable
if (!registeredIdNeedsSet){
if (!registeredIdNeedsSet)
return ClientWrapper.SettingsAdapter.get_CurrentAccountInfo_RegisteredName()
} else {
else
return ""
}
}
selectByMouse: true
readOnly: { refreshVariable
return !registeredIdNeedsSet}
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
font.bold: { refreshVariable
return !registeredIdNeedsSet}
readOnly: !registeredIdNeedsSet
font.bold: !registeredIdNeedsSet
horizontalAlignment: registeredIdNeedsSet ?
Text.AlignLeft :
Text.AlignRight
verticalAlignment: Text.AlignVCenter
padding: 8
borderColorMode: {
switch (regNameUi) {
case CurrentAccountSettingsScrollPage.INVALIDFORM:
case CurrentAccountSettingsScrollPage.TAKEN:
return InfoLineEdit.ERROR
case CurrentAccountSettingsScrollPage.FREE:
return InfoLineEdit.RIGHT
case CurrentAccountSettingsScrollPage.BLANK:
case CurrentAccountSettingsScrollPage.SEARCHING:
default:
return InfoLineEdit.NORMAL
}
}
onImageClicked: {
slotRegisterName()
}
onTextEdited: {
verifyRegisteredNameSlot()
}
onEditingFinished: {
verifyRegisteredNameSlot()
}
}
}
MaterialButton {
id: btnRegisterName
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.rightMargin: currentRegisteredID.width / 2 - width / 2
Layout.preferredWidth: 120
Layout.preferredHeight: 30
visible: registeredIdNeedsSet &&
currentRegisteredID.nameRegistrationState ===
UsernameLineEdit.NameRegistrationState.FREE
text: qsTr("Register")
toolTipText: qsTr("Register the username")
color: JamiTheme.buttonTintedGrey
hoveredColor: JamiTheme.buttonTintedGreyHovered
pressedColor: JamiTheme.buttonTintedGreyPressed
onClicked: nameRegistrationDialog.openNameRegistrationDialog(
currentRegisteredID.text)
}
}
// Buttons Pwd, Export, Delete

View file

@ -1075,20 +1075,6 @@ UtilsAdapter::getCallStatusStr(int statusInt)
return lrc::api::call::to_string(status);
}
// returns true if name is valid registered name
bool
UtilsAdapter::validateRegNameForm(const QString& regName)
{
QRegularExpression regExp(" ");
if (regName.size() > 2 && !regName.contains(regExp)) {
return true;
} else {
return false;
}
}
QString
UtilsAdapter::getStringUTF8(QString string)
{

View file

@ -424,10 +424,8 @@ public:
Q_INVOKABLE const QString getCallId(const QString& accountId, const QString& convUid);
Q_INVOKABLE const QString getCallStatusStr(int statusInt);
Q_INVOKABLE QString getStringUTF8(QString string);
Q_INVOKABLE bool validateRegNameForm(const QString& regName);
Q_INVOKABLE QString getRecordQualityString(int value);
Q_INVOKABLE QString getCurrentPath();
Q_INVOKABLE QString stringSimplifier(QString input) { return input.simplified(); }
Q_INVOKABLE QString toNativeSeparators(QString inputDir)
{

View file

@ -40,14 +40,6 @@ Rectangle {
CONNECTMANAGER
}
enum NameRegistrationState {
BLANK,
INVALID,
TAKEN,
FREE,
SEARCHING
}
enum WizardViewPageIndex {
WELCOMEPAGE = 0,
CREATEACCOUNTPAGE,
@ -120,35 +112,11 @@ Rectangle {
}
}
Connections {
id: registeredNameFoundConnection
target: ClientWrapper.nameDirectory
function onRegisteredNameFound(status, address, name) {
if (registeredName === name) {
switch(status) {
case NameDirectory.LookupStatus.NOT_FOUND:
createAccountPage.nameRegistrationUIState = WizardView.FREE
break
case NameDirectory.LookupStatus.ERROR:
case NameDirectory.LookupStatus.INVALID_NAME:
case NameDirectory.LookupStatus.INVALID:
createAccountPage.nameRegistrationUIState = WizardView.INVALID
break
case NameDirectory.LookupStatus.SUCCESS:
createAccountPage.nameRegistrationUIState = WizardView.TAKEN
break
}
}
}
}
function changePageQML(pageIndex) {
controlPanelStackView.currentIndex = pageIndex
if (pageIndex === WizardView.WizardViewPageIndex.WELCOMEPAGE) {
fileToImport = ""
createAccountPage.nameRegistrationUIState = WizardView.BLANK
createAccountPage.nameRegistrationUIState = UsernameLineEdit.NameRegistrationState.BLANK
} else if (pageIndex === WizardView.WizardViewPageIndex.CREATEACCOUNTPAGE) {
createAccountPage.initializeOnShowUp()
} else if (pageIndex === WizardView.WizardViewPageIndex.CREATESIPACCOUNTPAGE) {
@ -232,28 +200,9 @@ Rectangle {
changePageQML(WizardView.WizardViewPageIndex.PROFILEPAGE)
}
onText_usernameEditAliasChanged: lookupTimer.restart()
onLeavePage: {
changePageQML(WizardView.WizardViewPageIndex.WELCOMEPAGE)
}
Timer {
id: lookupTimer
repeat: false
interval: 200
onTriggered: {
registeredName = createAccountPage.text_usernameEditAlias
if (registeredName.length !== 0) {
createAccountPage.nameRegistrationUIState = WizardView.SEARCHING
ClientWrapper.nameDirectory.lookupName("", registeredName)
} else {
createAccountPage.nameRegistrationUIState = WizardView.BLANK
}
}
}
}
CreateSIPAccountPage {

View file

@ -30,7 +30,7 @@ Rectangle {
id: root
property alias text_usernameEditAlias: usernameEdit.text
property int nameRegistrationUIState: WizardView.BLANK
property alias nameRegistrationUIState: usernameEdit.nameRegistrationState
property alias text_passwordEditAlias: passwordEdit.text
signal createAccount
@ -127,7 +127,7 @@ Rectangle {
}
}
MaterialLineEdit {
UsernameLineEdit {
id: usernameEdit
Layout.topMargin: 15
@ -135,24 +135,7 @@ Rectangle {
Layout.preferredWidth: chooseUsernameButton.width
Layout.alignment: Qt.AlignHCenter
selectByMouse: true
placeholderText: qsTr("Choose your username")
font.pointSize: 9
font.kerning: true
borderColorMode: {
switch (nameRegistrationUIState){
case WizardView.BLANK:
return MaterialLineEdit.NORMAL
case WizardView.INVALID:
case WizardView.TAKEN:
return MaterialLineEdit.ERROR
case WizardView.FREE:
return MaterialLineEdit.RIGHT
case WizardView.SEARCHING:
return MaterialLineEdit.SEARCHING
}
}
}
Label {
@ -162,13 +145,13 @@ Rectangle {
text: {
switch(nameRegistrationUIState){
case WizardView.BLANK:
case WizardView.SEARCHING:
case WizardView.FREE:
case UsernameLineEdit.NameRegistrationState.BLANK:
case UsernameLineEdit.NameRegistrationState.SEARCHING:
case UsernameLineEdit.NameRegistrationState.FREE:
return ""
case WizardView.INVALID:
case UsernameLineEdit.NameRegistrationState.INVALID:
return qsTr("Invalid username")
case WizardView.TAKEN:
case UsernameLineEdit.NameRegistrationState.TAKEN:
return qsTr("Username already taken")
}
}
@ -184,14 +167,15 @@ Rectangle {
Layout.preferredHeight: preferredHeight
text: qsTr("CHOOSE USERNAME")
enabled: nameRegistrationUIState === WizardView.FREE
color: nameRegistrationUIState === WizardView.FREE ? JamiTheme.wizardBlueButtons :
JamiTheme.buttonTintedGreyInactive
enabled: nameRegistrationUIState === UsernameLineEdit.NameRegistrationState.FREE
color: nameRegistrationUIState === UsernameLineEdit.NameRegistrationState.FREE ?
JamiTheme.wizardBlueButtons :
JamiTheme.buttonTintedGreyInactive
hoveredColor: JamiTheme.buttonTintedBlueHovered
pressedColor: JamiTheme.buttonTintedBluePressed
onClicked: {
if (nameRegistrationUIState === WizardView.FREE)
if (nameRegistrationUIState === UsernameLineEdit.NameRegistrationState.FREE)
createAccountStack.currentIndex = createAccountStack.currentIndex + 1
}
}