diff --git a/src/Gui/Login/InstanceInput.qml b/src/Gui/Login/InstanceInput.qml
new file mode 100644
index 0000000..4774edc
--- /dev/null
+++ b/src/Gui/Login/InstanceInput.qml
@@ -0,0 +1,69 @@
+import QtQuick
+import QtQuick.Layouts
+
+import "../PStyle"
+
+ColumnLayout {
+ id: root
+
+ signal tryInstance(url: string)
+
+ Timer {
+ id: focusTimer
+ running: true
+ onTriggered: instanceInput.pTf.forceActiveFocus()
+ repeat: false
+ interval: 250
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("QutePleroma")
+ font: PStyle.getFont(36)
+ }
+
+ RowLayout {
+ PText {
+ Layout.alignment: Qt.AlignBottom
+ Layout.bottomMargin: 8
+ text: "https://"
+ }
+
+ PInputField {
+ id: instanceInput
+ Layout.preferredWidth: 200
+ label: qsTr("Instance URL")
+ placeholderText: "ak.gensokyo.shop"
+
+ onTfChanged: (text) => {
+ let url;
+
+ try {
+ url = new URL(`https://${text}`)
+ } catch (_) {
+ btn.enabled = false
+ return
+ }
+
+ btn.enabled = true
+ }
+
+ onTfAccepted: getInstanceInfo()
+ }
+
+ PIconButton {
+ id: btn
+ Layout.alignment: Qt.AlignBottom
+ pIcon.name: "arrow-right"
+ enabled: false
+
+ onPressed: getInstanceInfo()
+ }
+ }
+
+ function getInstanceInfo() {
+ btn.enabled = false
+ const instanceUrl = `https://${instanceInput.tfText}`
+ tryInstance(instanceUrl)
+ }
+}
\ No newline at end of file
diff --git a/src/Gui/Login/LoadingInfo.qml b/src/Gui/Login/LoadingInfo.qml
new file mode 100644
index 0000000..89d3c89
--- /dev/null
+++ b/src/Gui/Login/LoadingInfo.qml
@@ -0,0 +1,20 @@
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+
+import "../PStyle"
+
+ColumnLayout {
+ spacing: 32
+
+ PBusyIndicator {
+ Layout.alignment: Qt.AlignHCenter
+ Layout.preferredHeight: 48
+ running: true
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("Loading instance information...")
+ }
+}
\ No newline at end of file
diff --git a/src/Gui/Login/Login.qml b/src/Gui/Login/Login.qml
new file mode 100644
index 0000000..efb77bf
--- /dev/null
+++ b/src/Gui/Login/Login.qml
@@ -0,0 +1,125 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtQml
+
+import Util
+import "../PStyle"
+
+PStackView {
+ id: login
+ initialItem: instanceInput
+
+ property var instanceInfo
+
+ Component {
+ id: instanceInput
+
+ Rectangle {
+ InstanceInput {
+ anchors.centerIn: parent
+
+ onTryInstance: (instanceUrl) => {
+ login.push(loadInstance)
+
+ Http.getRequest(
+ `${instanceUrl}/api/v1/instance`,
+ (body) => {
+ const json = JSON.parse(body)
+ print(`Instance name: ${json.title}`)
+ print(`Instance description: ${json.description}`)
+ instanceInfo = json
+ login.replace(infoScreen)
+ },
+ (err) => {
+ print(err)
+ login.pop()
+ })
+ }
+ }
+ }
+ }
+
+ Component {
+ id: loadInstance
+
+ Rectangle {
+ LoadingInfo {
+ anchors.centerIn: parent
+ }
+ }
+ }
+
+ Component {
+ id: infoScreen
+
+ Rectangle {
+ ColumnLayout {
+ id: info
+ anchors.centerIn: parent
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: instanceInfo.title
+ font: PStyle.getFont(36)
+ }
+
+ Image {
+ id: instanceLogo
+
+ source: instanceInfo.thumbnail
+
+ Layout.alignment: Qt.AlignHCenter
+ Layout.maximumWidth: 120
+ Layout.maximumHeight: Layout.maximumWidth
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: instanceInfo.description
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: `uri: ${instanceInfo.uri}`
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: `version: ${instanceInfo.version}`
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: `known domains: ${instanceInfo.stats.domain_count}`
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: `known users: ${instanceInfo.stats.remote_user_count}`
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: `status count: ${instanceInfo.stats.status_count}`
+ }
+
+ PText {
+ Layout.alignment: Qt.AlignHCenter
+ text: `user count: ${instanceInfo.stats.user_count}`
+ }
+
+ PTextButton {
+ text: qsTr("Back")
+ enabled: true
+
+ Layout.alignment: Qt.AlignHCenter
+
+ onClicked: {
+ login.pop()
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Gui/Splash.qml b/src/Gui/Splash.qml
index e63ca11..eab8ae0 100644
--- a/src/Gui/Splash.qml
+++ b/src/Gui/Splash.qml
@@ -4,6 +4,7 @@ import QtQuick.Layouts
import QtQuick.Controls
import Util
+import "Login"
import "PStyle"
Window {
@@ -15,28 +16,8 @@ Window {
PBackground {
anchors.fill: parent
- ColumnLayout {
+ Login {
anchors.centerIn: parent
-
- PText {
- Layout.alignment: Qt.AlignHCenter
- text: qsTr("QutePleroma")
- font: PStyle.getFont(36)
- }
-
- RowLayout {
- PInputField {
- Layout.preferredWidth: 200
- label: qsTr("Instance URL")
- placeholderText: "ak.gensokyo.shop"
- }
-
- PIconButton {
- id: btn
- Layout.alignment: Qt.AlignBottom
- pIcon.name: "arrow-right"
- }
- }
}
}
}
\ No newline at end of file
diff --git a/src/Gui/Style/PStyle/PBusyIndicator.qml b/src/Gui/Style/PStyle/PBusyIndicator.qml
new file mode 100644
index 0000000..016218c
--- /dev/null
+++ b/src/Gui/Style/PStyle/PBusyIndicator.qml
@@ -0,0 +1,66 @@
+import QtQuick
+import QtQuick.Controls
+
+import "."
+
+BusyIndicator {
+ id: control
+
+ contentItem: Item {
+ width: height
+ height: control.height
+
+ Item {
+ id: item
+
+ x: 0
+ y: 0
+ width: parent.width
+ height: parent.height
+ opacity: control.running ? 1 : 0
+
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: PStyle.animationDuration
+ }
+ }
+
+ RotationAnimator {
+ target: item
+ running: control.running && control.visible
+ from: 0
+ to: 360
+ loops: Animation.Infinite
+ duration: PStyle.animationDuration * 12
+ }
+
+ Repeater {
+ id: repeater
+ model: 5
+
+ Rectangle {
+ id: delegate
+ x: item.width / 2 - width / 2
+ y: item.height / 2 - height / 2
+ implicitWidth: 8
+ implicitHeight: 8
+ radius: width / 2
+ color: Qt.darker(PStyle.foreColor, 1.2)
+
+ required property int index
+
+ transform: [
+ Translate {
+ y: -Math.min(item.width, item.height) * 0.5 + 5
+ },
+ Rotation {
+ angle: delegate.index / repeater.count * 360
+ origin.x: 5
+ origin.y: 5
+ }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/src/Gui/Style/PStyle/PInputField.qml b/src/Gui/Style/PStyle/PInputField.qml
index 88850f0..f9a3e1e 100644
--- a/src/Gui/Style/PStyle/PInputField.qml
+++ b/src/Gui/Style/PStyle/PInputField.qml
@@ -4,8 +4,13 @@ import "."
ColumnLayout {
property alias label: lbl.text
property alias placeholderText: tf.placeholderText
+ property alias tfText: tf.text
+ property alias pTf: tf
spacing: 2
+ signal tfChanged(text: string)
+ signal tfAccepted()
+
PText {
id: lbl
font.pointSize: 10
@@ -14,5 +19,8 @@ ColumnLayout {
PTextField {
id: tf
Layout.fillWidth: true
+
+ onTextEdited: tfChanged(text)
+ onAccepted: tfAccepted()
}
}
\ No newline at end of file
diff --git a/src/Gui/Style/PStyle/PRawButton.qml b/src/Gui/Style/PStyle/PRawButton.qml
index fd10f2b..02a8e8b 100644
--- a/src/Gui/Style/PStyle/PRawButton.qml
+++ b/src/Gui/Style/PStyle/PRawButton.qml
@@ -9,10 +9,10 @@ Button {
background: PBackground {
id: background
- color: Qt.darker(PStyle.backColor, 1.8)
+ color: btn.enabled ? Qt.darker(PStyle.backColor, 1.8) : Qt.lighter(PStyle.backColor, 2.4)
border.width: 1
- border.color: PStyle.foreColor
+ border.color: btn.enabled ? PStyle.foreColor : Qt.darker(PStyle.foreColor, 1.4) // Qt.hsva(0, 1, 0.5, 1)
}
states: [
@@ -66,6 +66,7 @@ Button {
}
MouseArea {
+ enabled: btn.enabled
hoverEnabled: true
anchors.fill: btn
onEntered: {
diff --git a/src/Gui/Style/PStyle/PStackView.qml b/src/Gui/Style/PStyle/PStackView.qml
new file mode 100644
index 0000000..b3a7416
--- /dev/null
+++ b/src/Gui/Style/PStyle/PStackView.qml
@@ -0,0 +1,41 @@
+import QtQuick
+import QtQuick.Controls
+import "."
+
+StackView {
+ pushEnter: Transition {
+ PropertyAnimation {
+ property: "opacity"
+ from: 0
+ to: 1
+ duration: PStyle.animationDuration
+ }
+ }
+
+ pushExit: Transition {
+ PropertyAnimation {
+ property: "opacity"
+ from: 1
+ to: 0
+ duration: PStyle.animationDuration
+ }
+ }
+
+ popEnter: Transition {
+ PropertyAnimation {
+ property: "opacity"
+ from: 0
+ to: 1
+ duration: PStyle.animationDuration
+ }
+ }
+
+ popExit: Transition {
+ PropertyAnimation {
+ property: "opacity"
+ from: 1
+ to: 0
+ duration: PStyle.animationDuration
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Gui/Style/resources.qrc b/src/Gui/Style/resources.qrc
index 8bf25de..0afd4e2 100644
--- a/src/Gui/Style/resources.qrc
+++ b/src/Gui/Style/resources.qrc
@@ -10,5 +10,7 @@
PStyle/PRawButton.qml
PStyle/PIconButton.qml
PStyle/PIcon.qml
+ PStyle/PBusyIndicator.qml
+ PStyle/PStackView.qml
\ No newline at end of file
diff --git a/src/resources.qrc b/src/resources.qrc
index 17ebe5c..63bd332 100644
--- a/src/resources.qrc
+++ b/src/resources.qrc
@@ -2,9 +2,16 @@
Gui/Splash.qml
+
Gui/Util/Http.qml
Gui/Util/qmldir
+
+ Gui/Login/Login.qml
+ Gui/Login/InstanceInput.qml
+ Gui/Login/LoadingInfo.qml
+
+
Icons/arrow-right.svg
\ No newline at end of file