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

13
TODO.md
View File

@ -1,10 +1,12 @@
- Refactoring
- `^property type name$`
- Use [Animators](https://doc.qt.io/qt-5/qml-qtquick-animator.html)
- Choose a better default easing type for animations
- Use overshoot for the scale login thing
- Sendbox
- SignIn/RememberAccount screens
- SignIn must be in a flickable
- Unfinished work in button-refactor branch
- Button can get "hoverEnabled: false" to let HoverHandlers work
- HButton
- Control: hovered, visualFocus, enaled
- Border and pressed color in theme / checkbox theming
- Room Sidepane
- Hide when window too small
- Also save/load its size
@ -88,7 +90,7 @@
- Spinner when loading account, past room events, images or clicking buttons
- Show account page as loading until profile initially retrieved
- Theming
- Support SVG hue via image provider for icons
- Make all icons white/black, since we can now use ColorOverlay
- Don't create additional lines in theme conversion (braces)
- Recursively merge default and user theme
- Distribute fonts
@ -121,6 +123,7 @@
- Links preview
- Client improvements
- Logout previous session if adding an account that's already connected
- Image provider: on failed conversion, way to show a "broken image" thumb?
- Config file format
- Initial sync filter and lazy load, see weechat-matrix `_handle_login()`

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="24"
fill-rule="evenodd"
clip-rule="evenodd"
version="1.1"
id="svg4"
sodipodi:docname="check-mark.svg"
inkscape:version="">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview6"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="-7.6779661"
inkscape:cy="12"
inkscape:current-layer="svg4" />
<path
d="M21 6.285l-11.16 12.733-6.84-6.018 1.319-1.49 5.341 4.686 9.865-11.196 1.475 1.285z"
id="path2"
style="fill:#ffffff;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

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
}
}
}