d38490fb09
Closes #102. Doesn't use Shader/HighlightImage for background/placeholder, since that neither matched the previous look nor meet my visual expectations at all. I created both previously available color variations as svg accordingly. Implementation of the background images has been outsourced to a dedicated qml file to reduce duplication and ensure the same layout. Padding is now "medium" everywhere (stickers had none, audio had "small"). For the Icons, some (Highlight-)Image+MouseArea combinations have been changed to IconButton. Regarding videos, I'm not actually sure if the missing "highlight" on the fullscreen icon was intentional. An issue with videos possibly having the same color as the icon remains basically the same. Nonetheless, if this isn't desired, I'll revert to just using the white image. The sticker icon actually does look a bit differently now – it's a bit smaller. I've redrawn it from scratch but mostly kept the dimensions of icon-m-other (which doesn't look good when zoomed in, btw). Perhaps I actually did made a mistake drawing the previous one. Either way, I think it fits well enough. The notification icon remains png, but I managed to reduce its file size by ~60% without visibly impacting it much imho. This may be the longest commit message I've ever written.
441 lines
17 KiB
QML
441 lines
17 KiB
QML
/*
|
|
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
|
|
|
This file is part of Fernschreiber.
|
|
|
|
Fernschreiber 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.
|
|
|
|
Fernschreiber 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 Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
import QtQuick 2.0
|
|
import Sailfish.Silica 1.0
|
|
import WerkWolf.Fernschreiber 1.0
|
|
|
|
Page {
|
|
id: initializationPage
|
|
allowedOrientations: Orientation.All
|
|
backNavigation: false
|
|
|
|
property bool loading: true
|
|
property int authorizationState: TelegramAPI.Closed
|
|
property var authorizationStateData: null
|
|
|
|
Component.onCompleted: {
|
|
initializationPage.authorizationState = tdLibWrapper.getAuthorizationState();
|
|
initializationPage.authorizationStateData = tdLibWrapper.getAuthorizationStateData();
|
|
initializationPage.loading = false;
|
|
|
|
switch (authorizationState) {
|
|
case TelegramAPI.WaitCode:
|
|
initializationPage.loading = false;
|
|
welcomeColumn.visible = false;
|
|
enterPinColumn.visible = true;
|
|
enterPinField.focus = true
|
|
enterPasswordColumn.visible = false;
|
|
waitRegistrationColumn.visible = false;
|
|
break;
|
|
case TelegramAPI.WaitPassword:
|
|
initializationPage.loading = false;
|
|
welcomeColumn.visible = false;
|
|
enterPinColumn.visible = false;
|
|
enterPasswordColumn.visible = true;
|
|
waitRegistrationColumn.visible = false;
|
|
break;
|
|
case TelegramAPI.WaitRegistration:
|
|
initializationPage.loading = false;
|
|
welcomeColumn.visible = false;
|
|
enterPinColumn.visible = false;
|
|
enterPasswordColumn.visible = false;
|
|
waitRegistrationColumn.visible = true;
|
|
pageHeader.title = qsTr("User Registration")
|
|
break;
|
|
default:
|
|
// Nothing ;)
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: tdLibWrapper
|
|
onAuthorizationStateChanged: {
|
|
switch (authorizationState) {
|
|
case TelegramAPI.WaitCode:
|
|
initializationPage.loading = false;
|
|
enterPinColumn.visible = true;
|
|
enterPinField.focus = true
|
|
enterPasswordColumn.visible = false;
|
|
waitRegistrationColumn.visible = false;
|
|
break;
|
|
case TelegramAPI.WaitPassword:
|
|
initializationPage.loading = false;
|
|
enterPinColumn.visible = false;
|
|
enterPasswordColumn.visible = true;
|
|
waitRegistrationColumn.visible = false;
|
|
break;
|
|
case TelegramAPI.WaitRegistration:
|
|
initializationPage.loading = false;
|
|
enterPinColumn.visible = false;
|
|
enterPasswordColumn.visible = false;
|
|
waitRegistrationColumn.visible = true;
|
|
break;
|
|
case TelegramAPI.AuthorizationReady:
|
|
initializationPage.loading = false;
|
|
pageStack.completeAnimation();
|
|
pageStack.pop();
|
|
break;
|
|
default:
|
|
// Nothing ;)
|
|
}
|
|
initializationPage.authorizationStateData = authorizationStateData;
|
|
}
|
|
}
|
|
|
|
|
|
SilicaFlickable {
|
|
id: welcomeFlickable
|
|
contentHeight: content.height
|
|
Behavior on contentHeight { NumberAnimation {} }
|
|
anchors.fill: parent
|
|
|
|
Column {
|
|
id: content
|
|
width: parent.width
|
|
spacing: Theme.paddingLarge
|
|
|
|
PageHeader {
|
|
id: pageHeader
|
|
title: qsTr("Welcome to Fernschreiber!")
|
|
}
|
|
|
|
Image {
|
|
source: "../../images/fernschreiber.svg"
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
sourceSize {
|
|
width: width
|
|
height: height
|
|
}
|
|
fillMode: Image.PreserveAspectFit
|
|
asynchronous: true
|
|
width: Math.min(2 * Theme.itemSizeHuge, Math.min(Screen.width, Screen.height) / 2)
|
|
height: width
|
|
}
|
|
|
|
BusyLabel {
|
|
text: qsTr("Loading...")
|
|
running: initializationPage.loading
|
|
Behavior on opacity { FadeAnimation {} }
|
|
visible: opacity > 0
|
|
}
|
|
|
|
Column {
|
|
id: welcomeColumn
|
|
width: parent.width
|
|
spacing: Theme.paddingLarge
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
opacity: visible ? 1 : 0
|
|
|
|
InfoLabel {
|
|
text: qsTr("Please enter your phone number to continue.")
|
|
}
|
|
|
|
TextField {
|
|
id: phoneNumberTextField
|
|
placeholderText: qsTr("Use the international format, e.g. %1").arg("+4912342424242")
|
|
inputMethodHints: Qt.ImhDialableCharactersOnly
|
|
labelVisible: false
|
|
width: parent.width
|
|
readonly property bool validInput: text.match(/\+[1-9][0-9]{4,}/g)
|
|
EnterKey.iconSource: "image://theme/icon-m-enter-next"
|
|
EnterKey.enabled: validInput
|
|
EnterKey.onClicked: {
|
|
validator = filledValidator
|
|
if(acceptableInput) {
|
|
continueWithPhoneNumberButton.focus = true
|
|
continueWithPhoneNumberButton.enter()
|
|
}
|
|
}
|
|
}
|
|
|
|
Button {
|
|
id: continueWithPhoneNumberButton
|
|
text: qsTr("Continue")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
enabled: phoneNumberTextField.validInput
|
|
onClicked: enter()
|
|
function enter() {
|
|
initializationPage.loading = true;
|
|
welcomeColumn.visible = false;
|
|
tdLibWrapper.setAuthenticationPhoneNumber(phoneNumberTextField.text);
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: pinErrorColumn
|
|
width: parent.width
|
|
spacing: Theme.paddingLarge
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
opacity: visible ? 1 : 0
|
|
visible: false
|
|
|
|
InfoLabel {
|
|
id: errorInfoLabel
|
|
font.pixelSize: Theme.fontSizeLarge
|
|
text: ""
|
|
}
|
|
|
|
Button {
|
|
text: qsTr("OK")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
onClicked: {
|
|
pinErrorColumn.visible = false;
|
|
welcomeColumn.visible = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: enterPasswordColumn
|
|
width: parent.width
|
|
spacing: Theme.paddingLarge
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
opacity: visible ? 1.0 : 0.0
|
|
visible: false
|
|
|
|
InfoLabel {
|
|
font.pixelSize: Theme.fontSizeLarge
|
|
text: qsTr("Please enter your password:")
|
|
}
|
|
|
|
PasswordField {
|
|
id: enterPasswordField
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
font.pixelSize: Theme.fontSizeLarge
|
|
width: parent.width - 2 * Theme.horizontalPageMargin
|
|
horizontalAlignment: TextInput.AlignHCenter
|
|
}
|
|
|
|
Button {
|
|
text: qsTr("OK")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
onClicked: {
|
|
initializationPage.loading = true;
|
|
enterPasswordColumn.visible = false;
|
|
tdLibWrapper.setAuthenticationPassword(enterPasswordField.text);
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: enterPinColumn
|
|
width: parent.width
|
|
spacing: Theme.paddingLarge
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
opacity: visible ? 1.0 : 0.0
|
|
visible: false
|
|
|
|
InfoLabel {
|
|
font.pixelSize: Theme.fontSizeLarge
|
|
text: qsTr("Please enter the code that you received:")
|
|
}
|
|
|
|
TextField {
|
|
id: enterPinField
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
inputMethodHints: Qt.ImhDigitsOnly
|
|
font.pixelSize: Theme.fontSizeExtraLarge
|
|
width: parent.width - 4 * Theme.paddingLarge
|
|
horizontalAlignment: TextInput.AlignHCenter
|
|
EnterKey.iconSource: "image://theme/icon-m-enter-next"
|
|
EnterKey.enabled: text.length > 0
|
|
EnterKey.onClicked: enterPinButton.enter()
|
|
}
|
|
|
|
Button {
|
|
id: enterPinButton
|
|
text: qsTr("OK")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
onClicked: enter()
|
|
function enter() {
|
|
initializationPage.loading = true;
|
|
enterPinColumn.visible = false;
|
|
tdLibWrapper.setAuthenticationCode(enterPinField.text);
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: linkingErrorColumn
|
|
width: parent.width
|
|
spacing: Theme.paddingLarge
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
opacity: visible ? 1.0 : 0.0
|
|
visible: false
|
|
|
|
InfoLabel {
|
|
font.pixelSize: Theme.fontSizeLarge
|
|
text: qsTr("Unable to authenticate you with the entered code.")
|
|
}
|
|
|
|
Button {
|
|
text: qsTr("Enter code again")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
onClicked: {
|
|
linkingErrorColumn.visible = false;
|
|
enterPinColumn.visible = true;
|
|
}
|
|
}
|
|
|
|
Button {
|
|
text: qsTr("Restart authentication")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
onClicked: {
|
|
linkingErrorColumn.visible = false;
|
|
welcomeColumn.visible = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: waitRegistrationColumn
|
|
width: parent.width
|
|
spacing: Theme.paddingLarge
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
opacity: visible ? 1.0 : 0.0
|
|
visible: false
|
|
|
|
InfoLabel {
|
|
id: waitRegistrationInfoLabel
|
|
property bool acknowledged
|
|
font.pixelSize: Theme.fontSizeExtraSmall
|
|
textFormat: Text.StyledText
|
|
horizontalAlignment: Text.AlignLeft
|
|
linkColor: Theme.primaryColor
|
|
property var stateText: initializationPage.authorizationStateData.authorization_state && initializationPage.authorizationStateData.authorization_state.terms_of_service ?
|
|
initializationPage.authorizationStateData.authorization_state.terms_of_service.text :
|
|
null
|
|
visible: !!stateText && !acknowledged
|
|
text: {
|
|
if(!stateText) {
|
|
return '';
|
|
}
|
|
var entities = stateText.entities;
|
|
if(entities && entities.length > 0 && entities[0]["type"]["@type"] === "textEntityTypeTextUrl") { //we just use the first entity for now.
|
|
var offset = entities[0].offset;
|
|
var length = entities[0].length;
|
|
return (stateText.text.slice(0,entities[0].offset)
|
|
+ "<a href=\""+entities[0]["type"]["url"]+"\">"
|
|
+ stateText.text.slice(entities[0].offset, entities[0].offset + entities[0].length)
|
|
+ '</a>'
|
|
+ stateText.text.slice(entities[0].offset + entities[0].length)).replace(/\n/gm, "<br>");
|
|
}
|
|
return stateText.text.replace(/\n/gm, "<br>");
|
|
}
|
|
}
|
|
|
|
Button {
|
|
visible: waitRegistrationInfoLabel.visible
|
|
text: qsTr("OK")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
onClicked: {
|
|
waitRegistrationInfoLabel.acknowledged = true;
|
|
userFirstNameTextField.focus = true
|
|
}
|
|
}
|
|
RegExpValidator {
|
|
id: filledValidator
|
|
regExp: /.+/
|
|
}
|
|
TextField {
|
|
id: userFirstNameTextField
|
|
visible: !waitRegistrationInfoLabel.visible
|
|
opacity: visible ? 1.0 : 0.0
|
|
Behavior on opacity { FadeAnimation {} }
|
|
placeholderText: qsTr("Enter your First Name")
|
|
labelVisible: false
|
|
width: parent.width
|
|
EnterKey.iconSource: !!text ? "image://theme/icon-m-enter-next" : "image://theme/icon-m-text-input"
|
|
EnterKey.onClicked: {
|
|
validator = filledValidator
|
|
if(acceptableInput) userLastNameTextField.focus = true;
|
|
}
|
|
}
|
|
TextField {
|
|
id: userLastNameTextField
|
|
visible: !waitRegistrationInfoLabel.visible
|
|
opacity: visible ? 1.0 : 0.0
|
|
Behavior on opacity { FadeAnimation {} }
|
|
placeholderText: qsTr("Enter your Last Name")
|
|
labelVisible: false
|
|
width: parent.width
|
|
EnterKey.iconSource: !!text ? "image://theme/icon-m-enter-accept" : "image://theme/icon-m-text-input"
|
|
EnterKey.onClicked: {
|
|
validator = filledValidator
|
|
if(acceptableInput) registerUserButton.onClicked(null);
|
|
}
|
|
}
|
|
Button {
|
|
id: registerUserButton
|
|
visible: !waitRegistrationInfoLabel.visible
|
|
opacity: visible ? 1.0 : 0.0
|
|
Behavior on opacity { FadeAnimation {} }
|
|
text: qsTr("Register User")
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
}
|
|
onClicked: {
|
|
userFirstNameTextField.validator = filledValidator
|
|
userLastNameTextField.validator = filledValidator
|
|
if(userFirstNameTextField.acceptableInput && userLastNameTextField.acceptableInput) {
|
|
tdLibWrapper.registerUser(userFirstNameTextField.text, userLastNameTextField.text);
|
|
} else if(!userFirstNameTextField.acceptableInput) {
|
|
userFirstNameTextField.focus = true;
|
|
} else {
|
|
userLastNameTextField.focus = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
Item {
|
|
width: 1
|
|
height: Theme.paddingLarge
|
|
}
|
|
}
|
|
}
|
|
}
|