Fix text syncing

This commit is contained in:
Devin Lin 2021-04-11 11:46:50 -04:00
parent 07142481bf
commit 38f9e4871d
4 changed files with 129 additions and 82 deletions

View file

@ -23,12 +23,6 @@ Rectangle {
color: Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.backgroundColor, {"alpha": 0.9*255}) color: Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.backgroundColor, {"alpha": 0.9*255})
property string pinLabel: qsTr("Enter PIN") property string pinLabel: qsTr("Enter PIN")
// for displaying temporary number in pin dot display
property int previewCharIndex: -2
// if waiting for result of auth
property bool waitingForAuth: false
// colour calculations // colour calculations
property color buttonColor: Qt.lighter(PlasmaCore.Theme.backgroundColor, 1.3) property color buttonColor: Qt.lighter(PlasmaCore.Theme.backgroundColor, 1.3)
property color buttonPressedColor: Qt.darker(PlasmaCore.Theme.backgroundColor, 1.08) property color buttonPressedColor: Qt.darker(PlasmaCore.Theme.backgroundColor, 1.08)
@ -48,70 +42,24 @@ Rectangle {
signal passwordChanged() signal passwordChanged()
// keypad functions
function reset() { function reset() {
waitingForAuth = false; passwordBar.reset();
root.password = "";
passwordChanged();
keypadRoot.pinLabel = qsTr("Enter PIN");
}
function backspace() {
if (!keypadRoot.waitingForAuth) {
keypadRoot.previewCharIndex = -2;
root.password = root.password.substr(0, root.password.length - 1);
passwordChanged();
}
}
function clear() {
if (!keypadRoot.waitingForAuth) {
keypadRoot.previewCharIndex = -2;
root.password = "";
passwordChanged();
}
}
function enter() {
if (root.password !== "") { // prevent typing lock when password is empty
keypadRoot.waitingForAuth = true;
}
// don't try to unlock if there is a timeout (unlock once unlocked)
if (!authenticator.graceLocked) {
authenticator.tryUnlock(root.password);
}
}
function keyPress(data) {
if (!keypadRoot.waitingForAuth) {
if (keypadRoot.pinLabel !== qsTr("Enter PIN")) {
keypadRoot.pinLabel = qsTr("Enter PIN");
}
keypadRoot.previewCharIndex = root.password.length;
root.password += data
passwordChanged();
// trigger turning letter into dot later
letterTimer.restart();
}
} }
Connections { Connections {
target: authenticator target: authenticator
function onSucceeded() { function onSucceeded() {
pinLabel = qsTr("Logging in..."); passwordBar.pinLabel = qsTr("Logging in...");
keypadRoot.waitingForAuth = false; passwordBar.waitingForAuth = false;
} }
function onFailed() { function onFailed() {
root.password = ""; root.password = "";
passwordChanged(); passwordBar.pinLabel = qsTr("Wrong PIN");
pinLabel = qsTr("Wrong PIN"); passwordBar.waitingForAuth = false;
keypadRoot.waitingForAuth = false;
} }
function onGraceLockedChanged() { function onGraceLockedChanged() {
// try authenticating if it was waiting for grace lock to stop and it has stopped // try authenticating if it was waiting for grace lock to stop and it has stopped
if (!authenticator.graceLocked && keypadRoot.waitingForAuth) { if (!authenticator.graceLocked && passwordBar.waitingForAuth) {
authenticator.tryUnlock(root.password); authenticator.tryUnlock(root.password);
} }
} }
@ -121,26 +69,15 @@ Rectangle {
Keys.onPressed: { Keys.onPressed: {
if (event.modifiers === Qt.NoModifier) { if (event.modifiers === Qt.NoModifier) {
if (event.key === Qt.Key_Backspace) { if (event.key === Qt.Key_Backspace) {
keypadRoot.backspace(); passwordBar.backspace();
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
keypadRoot.enter(); passwordBar.enter();
} else if (event.text != "") { } else if (event.text != "") {
keypadRoot.keyPress(event.text); passwordBar.keyPress(event.text);
} }
} }
} }
// trigger turning letter into dot after 500 milliseconds
Timer {
id: letterTimer
interval: 500
running: false
repeat: false
onTriggered: {
keypadRoot.previewCharIndex = -2;
}
}
RectangularGlow { RectangularGlow {
anchors.topMargin: 1 anchors.topMargin: 1
anchors.fill: passwordBar anchors.fill: passwordBar
@ -162,8 +99,15 @@ Rectangle {
keypadOpen: swipeProgress === 1 keypadOpen: swipeProgress === 1
password: root.password password: root.password
previewCharIndex: keypadRoot.previewCharIndex previewCharIndex: -2
pinLabel: keypadRoot.pinLabel pinLabel: qsTr("Enter PIN")
onChangePassword: root.password = password
Binding {
target: passwordBar
property: "password"
value: root.password
}
} }
// actual number keys // actual number keys
@ -238,16 +182,16 @@ Rectangle {
onClicked: { onClicked: {
if (modelData === "R") { if (modelData === "R") {
keypadRoot.backspace(); passwordBar.backspace();
} else if (modelData === "E") { } else if (modelData === "E") {
keypadRoot.enter(); passwordBar.enter();
} else { } else {
keypadRoot.keyPress(modelData); passwordBar.keyPress(modelData);
} }
} }
onPressAndHold: { onPressAndHold: {
if (modelData === "R") { if (modelData === "R") {
clear(); passwordBar.clear();
} }
} }
} }

View file

@ -235,6 +235,7 @@ PlasmaCore.ColorScope {
anchors.fill: parent anchors.fill: parent
property int columnHeight: units.gridUnit * 20 property int columnHeight: units.gridUnit * 20
property int oldContentY: contentY
height: columnHeight + root.height height: columnHeight + root.height
contentHeight: columnHeight + root.height contentHeight: columnHeight + root.height
@ -253,9 +254,10 @@ PlasmaCore.ColorScope {
// wipe password if it is more than half way down the screen // wipe password if it is more than half way down the screen
onContentYChanged: { onContentYChanged: {
if (contentY < columnHeight / 2) { if (contentY < columnHeight / 2 && oldContentY >= columnHeight / 2) {
keypad.reset(); keypad.reset();
} }
oldContentY = contentY;
} }
ColumnLayout { ColumnLayout {

View file

@ -48,6 +48,7 @@ Item {
} }
height: 1 height: 1
color: Qt.rgba(1, 1, 1, 0.5) color: Qt.rgba(1, 1, 1, 0.5)
opacity: 1 - (passwordFlickable.contentY / passwordFlickable.columnHeight)
} }
} }
Rectangle { Rectangle {
@ -77,6 +78,7 @@ Item {
} }
height: 1 height: 1
color: Qt.rgba(1, 1, 1, 0.5) color: Qt.rgba(1, 1, 1, 0.5)
opacity: 1 - (passwordFlickable.contentY / passwordFlickable.columnHeight)
} }
} }

View file

@ -21,13 +21,81 @@ Rectangle {
property bool isPinMode: true property bool isPinMode: true
property string password property string password
// for displaying temporary number in pin dot display
property int previewCharIndex property int previewCharIndex
property string pinLabel property string pinLabel
property bool keypadOpen property bool keypadOpen
// if waiting for result of auth
property bool waitingForAuth: false
property color headerTextColor: Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.textColor, {"alpha": 0.75*255}) property color headerTextColor: Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.textColor, {"alpha": 0.75*255})
property color headerTextInactiveColor: Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.textColor, {"alpha": 0.4*255}) property color headerTextInactiveColor: Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.textColor, {"alpha": 0.4*255})
signal changePassword();
// keypad functions
function reset() {
waitingForAuth = false;
root.password = "";
changePassword();
root.pinLabel = qsTr("Enter PIN");
}
function backspace() {
if (!root.waitingForAuth) {
root.previewCharIndex = -2;
root.password = root.password.substr(0, root.password.length - 1);
changePassword();
}
}
function clear() {
if (!root.waitingForAuth) {
root.previewCharIndex = -2;
root.password = "";
changePassword();
}
}
function enter() {
if (root.password !== "") { // prevent typing lock when password is empty
root.waitingForAuth = true;
}
// don't try to unlock if there is a timeout (unlock once unlocked)
if (!authenticator.graceLocked) {
authenticator.tryUnlock(root.password);
}
}
function keyPress(data) {
if (!root.waitingForAuth) {
if (root.pinLabel !== qsTr("Enter PIN")) {
root.pinLabel = qsTr("Enter PIN");
}
root.previewCharIndex = root.password.length;
root.password += data
changePassword();
// trigger turning letter into dot later
letterTimer.restart();
}
}
// trigger turning letter into dot after 500 milliseconds
Timer {
id: letterTimer
interval: 500
running: false
repeat: false
onTriggered: {
root.previewCharIndex = -2;
}
}
// we need to use a listmodel to avoid all delegates from reloading // we need to use a listmodel to avoid all delegates from reloading
ListModel { ListModel {
id: dotDisplayModel id: dotDisplayModel
@ -43,10 +111,41 @@ Rectangle {
// hidden textfield so that the virtual keyboard shows up // hidden textfield so that the virtual keyboard shows up
TextField { TextField {
visible: false
id: textField id: textField
visible: false
focus: keypadOpen && !isPinMode focus: keypadOpen && !isPinMode
z: 1 z: 1
property bool externalEdit: false
property string prevText: ""
Connections {
target: root
function onChangePassword() {
if (textField.text != root.password) {
textField.externalEdit = true;
textField.text = root.password;
}
}
}
onEditingFinished: {
if (textField.focus) {
root.enter();
}
}
onTextChanged: {
if (!externalEdit) {
if (prevText.length > text.length) { // backspace
for (let i = 0; i < (prevText.length - text.length); i++) {
root.backspace();
}
} else if (text.length > 0) { // key enter
root.keyPress(text.charAt(text.length - 1));
}
prevText = text;
}
externalEdit = false;
}
} }
// toggle between showing keypad and not // toggle between showing keypad and not
@ -123,7 +222,7 @@ Rectangle {
scale: 0 scale: 0
anchors.fill: parent anchors.fill: parent
radius: width radius: width
color: keypadRoot.waitingForAuth ? root.headerTextInactiveColor : root.headerTextColor // dim when waiting for auth color: root.waitingForAuth ? root.headerTextInactiveColor : root.headerTextColor // dim when waiting for auth
PropertyAnimation { PropertyAnimation {
id: dotAnimation id: dotAnimation
@ -137,7 +236,7 @@ Rectangle {
id: charLabel id: charLabel
scale: 0 scale: 0
anchors.centerIn: parent anchors.centerIn: parent
color: keypadRoot.waitingForAuth ? root.headerTextInactiveColor : root.headerTextColor // dim when waiting for auth color: root.waitingForAuth ? root.headerTextInactiveColor : root.headerTextColor // dim when waiting for auth
text: model.char text: model.char
font.pointSize: 12 font.pointSize: 12