Refactor HInterfaceBox and SignIn page

- Cleaned up code
- Sizes are standardized
- New HCheckBox component
- Replace RememberAccount page by a checkbox on the SignIn page
- The page can now be flicked if it's not tall enough to display
  everything

- HNumberAnimation now has an overshoot property that will set the right
  easing type, overshoot and adapt the animation factor/duration.
- HImage can now be colorized
This commit is contained in:
miruka
2019-08-17 13:01:43 -04:00
parent 3e48d63cf3
commit 1ab79347e9
9 changed files with 205 additions and 90 deletions

View File

@@ -0,0 +1,48 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import "../utils.js" as Utils
CheckBox {
id: box
spacing: theme.spacing
property bool highlight: enabled && (hovered || visualFocus)
indicator: Rectangle {
implicitWidth: implicitHeight
implicitHeight: box.contentItem.font.pixelSize * 1.5
x: box.leftPadding
y: box.topPadding + box.availableHeight / 2 - height / 2
radius: theme.radius / 1.5
color: theme.controls.button.background
border.color: Utils.hsluv(
180, highlight ? 80 : 0, highlight ? 80 : 40, highlight ? 1 : 0.7
)
Behavior on border.color { HColorAnimation { factor: 0.5 } }
HIcon {
anchors.centerIn: parent
dimension: parent.width - 2
svgName: "check-mark"
colorize: theme.colors.accentText
visible: scale > 0
scale: box.checked ? 1 : 0
Behavior on scale { HNumberAnimation { overshoot: 4 } }
}
}
contentItem: HLabel {
text: box.text
color: box.enabled ?
theme.controls.button.text :
theme.controls.button.disabledText
// Set a width on CheckBox for wrapping to work, e.g. Layout.fillWidth
wrapMode: Text.Wrap
leftPadding: box.indicator.width + box.spacing
verticalAlignment: Text.AlignVCenter
}
}

View File

@@ -1,8 +1,20 @@
import QtQuick 2.12
import QtGraphicalEffects 1.12
Image {
id: image
asynchronous: true
cache: true
mipmap: true
fillMode: Image.PreserveAspectFit
property color colorize: "transparent"
layer {
enabled: ! Qt.colorEqual(colorize, "transparent")
effect: ColorOverlay {
color: image.colorize
cached: image.cache
}
}
}

View File

@@ -1,8 +1,23 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
HScalingBox {
HRectangle {
id: interfaceBox
color: theme.controls.box.background
implicitWidth: Math.min(
parent.width, theme.minimumSupportedWidthPlusSpacing * multiplyWidth
)
implicitHeight: childrenRect.height
property real multiplyWidth: 1.0
property real multiplyHorizontalSpacing: 1.5
property real multiplyVerticalSpacing: 1.5
property int horizontalSpacing:
Math.min(theme.spacing * width / 400, theme.spacing) *
multiplyHorizontalSpacing
property int verticalSpacing: theme.spacing * multiplyVerticalSpacing
property alias title: interfaceTitle.text
property alias buttonModel: interfaceButtonsRepeater.model
@@ -18,25 +33,35 @@ HScalingBox {
}
}
Keys.onReturnPressed: clickEnterButtonTarget()
Keys.onEnterPressed: clickEnterButtonTarget()
HColumnLayout {
anchors.fill: parent
id: mainColumn
width: parent.width
spacing: interfaceBox.verticalSpacing
HRowLayout {
Layout.alignment: Qt.AlignHCenter
Layout.margins: interfaceBox.margins
HLabel {
id: interfaceTitle
visible: Boolean(text)
font.pixelSize: theme.fontSize.bigger
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
HLabel {
id: interfaceTitle
font.pixelSize: theme.fontSize.bigger
}
Layout.fillWidth: true
Layout.topMargin: interfaceBox.verticalSpacing
Layout.leftMargin: interfaceBox.horizontalSpacing
Layout.rightMargin: interfaceBox.horizontalSpacing
}
HSpacer {}
HColumnLayout {
id: interfaceBody
spacing: interfaceBox.verticalSpacing
HColumnLayout { id: interfaceBody }
HSpacer {}
Layout.fillWidth: true
Layout.leftMargin: interfaceBox.horizontalSpacing
Layout.rightMargin: interfaceBox.horizontalSpacing
}
HRowLayout {
Repeater {
@@ -53,7 +78,7 @@ HScalingBox {
onClicked: buttonCallbacks[modelData.name](button)
Layout.fillWidth: true
Layout.preferredHeight: theme.controls.avatar.size
Layout.preferredHeight: theme.baseElementsHeight
}
}
}

View File

@@ -1,6 +1,10 @@
import QtQuick 2.12
NumberAnimation {
property real factor: 1.0
property real factor: Math.max(overshoot / 1.75, 1.0)
property real overshoot: 1.0
duration: theme.animationDuration * factor
easing.type: overshoot > 1 ? Easing.InOutBack : Easing.Linear
easing.overshoot: overshoot
}

View File

@@ -38,12 +38,13 @@ SwipeView {
implicitWidth: parent ? parent.width : 0
color: theme.controls.header.background
height: ! hideHeaderUnderHeight ||
window.height >=
hideHeaderUnderHeight +
theme.baseElementsHeight +
currentSpacing * 2 ?
theme.baseElementsHeight : 0
height: innerHeaderLabel.text && (
! hideHeaderUnderHeight ||
window.height >=
hideHeaderUnderHeight +
theme.baseElementsHeight +
currentSpacing * 2
) ? theme.baseElementsHeight : 0
Behavior on height { HNumberAnimation {} }
visible: height > 0

View File

@@ -1,46 +0,0 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import "../Base"
Item {
property string loginWith: "username"
property string userId: ""
HInterfaceBox {
id: rememberBox
title: "Sign in"
anchors.centerIn: parent
enterButtonTarget: "yes"
buttonModel: [
{ name: "yes", text: qsTr("Yes") },
{ name: "no", text: qsTr("No") },
]
buttonCallbacks: ({
yes: button => {
py.callCoro("saved_accounts.add", [userId])
pageStack.showPage("EditAccount/EditAccount", {userId})
},
no: button => {
py.callCoro("saved_accounts.delete", [userId])
pageStack.showPage("EditAccount/EditAccount", {userId})
},
})
HLabel {
text: qsTr(
"Do you want to remember this account?\n\n" +
"If yes, the " + loginWith + " and an access token will be " +
"stored to automatically sign in on this device."
)
wrapMode: Text.Wrap
Layout.margins: rememberBox.margins
Layout.fillWidth: true
}
HSpacer {}
}
}

View File

@@ -2,7 +2,7 @@ import QtQuick 2.12
import QtQuick.Layouts 1.12
import "../Base"
Item {
HPage {
property string loginWith: "username"
readonly property bool canLogin: idField.text && passwordField.text
@@ -10,15 +10,16 @@ Item {
HInterfaceBox {
id: signInBox
title: "Sign in"
anchors.centerIn: parent
Layout.alignment: Qt.AlignCenter
multiplyWidth: 0.85
title: qsTr("Sign in")
enterButtonTarget: "login"
buttonModel: [
{ name: "register", text: qsTr("Register"), enabled: false },
{ name: "login", text: qsTr("Login"), enabled: canLogin },
{ name: "forgot", text: qsTr("Forgot?"), enabled: false }
{ name: "forgot", text: qsTr("Forgot?"), enabled: false },
]
buttonCallbacks: ({
@@ -29,14 +30,23 @@ Item {
let args = [idField.text, passwordField.text]
py.callCoro("login_client", args, ([success, data]) => {
if (success) {
// data = userId
errorMessage.text = ""
pageStack.showPage("RememberAccount", {loginWith,data})
} else {
if (! success) {
errorMessage.text = qsTr(data)
button.loading = false
return
}
button.loading = false
py.callCoro(
"saved_accounts." +
(rememberAccount.checked ? "add": "delete"),
[data]
)
pageStack.showPage(
"EditAccount/EditAccount", {userId: data}
)
errorMessage.text = ""
button.loading = false
})
},
@@ -44,9 +54,10 @@ Item {
})
HRowLayout {
spacing: signInBox.margins * 1.25
Layout.margins: signInBox.margins
spacing: signInBox.horizontalSpacing * 1.25
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: signInBox.verticalSpacing / 2
Layout.bottomMargin: Layout.topMargin
Repeater {
model: ["username", "email", "phone"]
@@ -70,20 +81,26 @@ Item {
loginWith === "phone" ? "Phone" :
"Username"
)
onAccepted: signInBox.clickEnterButtonTarget()
Layout.fillWidth: true
Layout.margins: signInBox.margins
}
HTextField {
id: passwordField
placeholderText: qsTr("Password")
echoMode: HTextField.Password
onAccepted: signInBox.clickEnterButtonTarget()
Layout.fillWidth: true
Layout.margins: signInBox.margins
}
HCheckBox {
id: rememberAccount
text: qsTr("Automatically sign in")
checked: true
spacing: signInBox.horizontalSpacing
Layout.maximumWidth: parent.width
Layout.alignment: Qt.AlignHCenter
}
HLabel {
@@ -97,7 +114,6 @@ Item {
Behavior on Layout.maximumHeight { HNumberAnimation {} }
Layout.fillWidth: true
Layout.margins: signInBox.margins
}
}
}