import QtGraphicalEffects 1.0 import QtQuick 2.7 import QtQuick.Controls 2.13 import QtQuick.Controls.Material 2.0 import QtQuick.Layouts 1.3 import QtQuick.Window 2.11 import "../opaque" as Opaque import "../opaque/theme" import "../opaque/fonts" // import "../styles" Opaque.Flickable { id: flickRoot Layout.fillHeight: true Layout.fillWidth: true contentWidth: rc.width contentHeight: rc.height readonly property string mode_add: "add" readonly property string mode_edit: "edit" property string mode // edit or add property string onion property string tag property bool deleting property bool changingPassword function reset() { flickRoot.contentY = 0 mode = mode_add reset_errors() txtProfileName.text = "" changingPassword = false txtPassword1.text = "" txtPassword2.text = "" deleting = false deleteConfirmLabel.color = Theme.mainTextColor txtCurrentPassword.text = "" nameLabel.text = "" portrait.performTransform = true portrait.source = "core/account_circle-24px_negative_space.webp" tag = "" confirmDeleteTxt.text = "" radioUsePassword.checked = true } function reset_errors() { txtPassword1.error = false txtPassword2.error = false txtCurrentPassword.error = false passwordErrorLabel.visible = false passwordChangeErrorLabel.visible = false confirmDeleteTxt.error = false } function load(userOnion, name, userTag, image) { reset() mode = mode_edit tag = userTag onion = userOnion txtPassword1.text = "" txtPassword2.text = "" onionLabel.text = onion txtProfileName.text = name nameLabel.text = name portrait.performTransform = false portrait.source = image if (tag == "v1-defaultPassword" || tag == "v1-default-password") { radioNoPassword.checked = true } else { radioUsePassword.checked = true } } Opaque.ResponsiveContainer { id: rc width: flickRoot.width Rectangle { id: leftCol color: Theme.backgroundPaneColor //height: implicitHeight: leftContents.height height: implicitHeight Layout.fillWidth: true Layout.alignment: Qt.AlignTop Column { id: leftContents anchors.horizontalCenter: parent.horizontalCenter Layout.alignment : Qt.AlignHCenter + Qt.AlignTop width: 400 * gcd.themeScale spacing: 10 * gcd.themeScale Opaque.ScalingLabel { anchors.horizontalCenter: parent.horizontalCenter size: Theme.primaryTextSize //: New Profile || Edit Profile text: mode == mode_add ? qsTr("new-profile") : qsTr("edit-profile") bold: true } // spacing Rectangle { height: 30 * gcd.themeScale width: 100 color: Theme.backgroundPaneColor } Opaque.Portrait { id: portrait size: 250 Layout.preferredHeight: size anchors.horizontalCenter: parent.horizontalCenter portraitBorderColor: Theme.portraitOnlineBorderColor portraitColor: Theme.portraitOnlineBackgroundColor badgeColor: Theme.portraitProfileBadgeColor performTransform: true overlayColor: Theme.portraitProfileBadgeTextColor badgeContent: Image {// Profle Type id: profiletype source: radioUsePassword.checked ? gcd.assetPath + "core/lock-24px.webp" : gcd.assetPath + "core/lock-open-24px.webp" height: 40 * gcd.themeScale width: height } } Opaque.ScalingLabel { id: nameLabel visible: mode == mode_edit anchors.horizontalCenter: parent.horizontalCenter size: Theme.primaryTextSize bold: true } // spacing Rectangle { visible: mode == mode_edit height: 10 * gcd.themeScale width: 100 color: Theme.backgroundPaneColor } Opaque.ScalingLabel { visible: mode == mode_edit anchors.horizontalCenter: parent.horizontalCenter size: Theme.secondaryTextSize //: Send this address to peers you want to connect with text: qsTr("profile-oniblon-label") } Opaque.ButtonTextField { id: onionLabel anchors.horizontalCenter: parent.horizontalCenter visible: mode == mode_edit readOnly: true width: leftCol.width - (40*gcd.themeScale) button_text: qsTr("copy-btn") dropShadowColor: Theme.dropShadowPaneColor onClicked: { //: notification: copied to clipboard gcd.popup(qsTr("copied-to-clipboard-notification")) onionLabel.selectAll() onionLabel.copy() } } // spacing Rectangle { visible: radioNoPassword.checked height: 30 * gcd.themeScale width: 100 color: Theme.backgroundPaneColor } Rectangle { width: parent.width height: noPasswordLabel.visible ? noPasswordLabel.height : 0 color: leftCol.color anchors.horizontalCenter: parent.horizontalCenter Opaque.ScalingLabel { id: noPasswordLabel width: parent.width size: Theme.secondaryTextSize anchors.horizontalCenter: parent.horizontalCenter //: Not using a password on this account means that all data stored locally will not be encrypted text: qsTr("no-password-warning") visible: radioNoPassword.checked } } // spacing Rectangle { height: 30 * gcd.themeScale width: 100 color: Theme.backgroundPaneColor } } } Rectangle { id: rightCol color: Theme.backgroundPaneColor anchors.topMargin: 80 * gcd.themeScale height: rightContents.height implicitHeight: height Layout.fillWidth: true Layout.alignment: Qt.AlignTop Column { id: rightContents anchors.horizontalCenter: parent.horizontalCenter Layout.alignment : Qt.AlignHCenter + Qt.AlignTop width: 400 * gcd.themeScale spacing: 40 * gcd.themeScale Opaque.UnderlineTextField { id: txtProfileName backgroundColor: Theme.backgroundPaneColor width: parent.width - (40*gcd.themeScale) anchors.horizontalCenter: parent.horizontalCenter //: Your Display Name placeholderText: qsTr("your-display-name") } RowLayout { visible: (mode == mode_add) || (tag == "v1-defaultPassword") width: parent.width - (40*gcd.themeScale) anchors.horizontalCenter: parent.horizontalCenter //id: radioButtons Opaque.RadioButton { id: radioUsePassword checked: true //: Password text: qsTr("radio-use-password") onClicked: { changingPassword = true } } Opaque.RadioButton { id: radioNoPassword //: Unencrypted (No password) text: qsTr("radio-no-password") onClicked: { changingPassword = true } } } Opaque.UnderlineTextField { id: txtCurrentPassword visible: radioUsePassword.checked && (mode == mode_edit) && tag != "v1-defaultPassword" backgroundColor: Theme.backgroundPaneColor width: parent.width - (40*gcd.themeScale) anchors.horizontalCenter: parent.horizontalCenter //: Current Password placeholderText: qsTr("current-password-label") + ":" echoMode: TextInput.Password } Opaque.UnderlineTextField { id: txtPassword1 visible: radioUsePassword.checked backgroundColor: Theme.backgroundPaneColor width: parent.width - (40*gcd.themeScale) anchors.horizontalCenter: parent.horizontalCenter echoMode: TextInput.Password //: Password placeholderText: qsTr("password1-label") onTextEdited: { changingPassword = true } } Opaque.UnderlineTextField { id: txtPassword2 visible: radioUsePassword.checked backgroundColor: Theme.backgroundPaneColor width: parent.width - (40*gcd.themeScale) anchors.horizontalCenter: parent.horizontalCenter //: Reenter password placeholderText: qsTr("password2-label") echoMode: TextInput.Password } Opaque.ScalingLabel { id: passwordErrorLabel anchors.horizontalCenter: parent.horizontalCenter size: Theme.secondaryTextSize //: Passwords do not match text: qsTr("password-error-match") visible: false color: Theme.textfieldErrorColor } Opaque.ScalingLabel { id: passwordChangeErrorLabel anchors.horizontalCenter: parent.horizontalCenter size: Theme.secondaryTextSize //: Error changing password: Supplied password rejected text: qsTr("password-change-error") visible: false color: Theme.textfieldErrorColor } Opaque.Button { // ADD or SAVE button height: Theme.primaryTextSize * 1.5 anchors.horizontalCenter: parent.horizontalCenter //: Create || Save text: mode == mode_add ? qsTr("create-profile-btn") : qsTr("save-profile-btn") onClicked: { reset_errors() if (mode == mode_add) { if (txtPassword1.text != txtPassword2.text) { passwordErrorLabel.visible = true txtPassword1.error = true txtPassword2.error = true } else { gcd.createProfile(txtProfileName.text, radioNoPassword.checked, txtPassword1.text) gcd.reloadProfileList() parentStack.pane = parentStack.managementPane } } else { console.log("Save clicked") gcd.updateNick(onion, txtProfileName.text) if (changingPassword) { console.log("changingPassword") if (txtPassword1.text != txtPassword2.text) { passwordErrorLabel.visible = true txtPassword1.error = true txtPassword2.error = true } else { console.log("gcd.changePassword") gcd.changePassword(onion, txtCurrentPassword.text, txtPassword1.text, radioNoPassword.checked) } } else { gcd.reloadProfileList() parentStack.pane = parentStack.managementPane } } } } // ***** Delete button and confirm flow ***** Opaque.Button { anchors.right: parent.right anchors.rightMargin: 20 * gcd.themeScale //: Delete Profile text: qsTr("delete-profile-btn") //icon: "regular/trash-alt" visible: mode == mode_edit height: Theme.primaryTextSize * 1.5 onClicked: { deleting = true } } Opaque.ScalingLabel { id: deleteConfirmLabel size: Theme.secondaryTextSize anchors.right: parent.right anchors.rightMargin: 20 * gcd.themeScale //: Type DELETE to confirm text: qsTr("delete-confirm-label")+ ":" visible: deleting } Opaque.UnderlineTextField { id: confirmDeleteTxt visible: deleting backgroundColor: Theme.backgroundPaneColor width: 300 * gcd.themeScale anchors.right: parent.right anchors.rightMargin: 20 * gcd.themeScale placeholderText: qsTr("delete-confirm-label") } Opaque.Button { id: confirmDeleteBtn height: Theme.primaryTextSize * 1.5 anchors.right: parent.right anchors.rightMargin: 20 * gcd.themeScale //: Really Delete Profile text: qsTr("delete-profile-confirm-btn") visible: deleting onClicked: { //: DELETE if (confirmDeleteTxt.text == qsTr("delete-confirm-text")) { deleteConfirmLabel.color = Theme.mainTextColor gcd.deleteProfile(onion) gcd.reloadProfileList() parentStack.pane = parentStack.managementPane } else { confirmDeleteTxt.error = true deleteConfirmLabel.color = Theme.textfieldErrorColor } } } // spacing Rectangle { height: 30 * gcd.themeScale width: 100 color: Theme.backgroundPaneColor } } } Connections { target: gcd onChangePasswordResponse: function(error) { if (!error) { gcd.reloadProfileList() parentStack.pane = parentStack.managementPane } else { passwordChangeErrorLabel.visible = true txtCurrentPassword.error = true } } } } }