Skip to content

Commit

Permalink
feat(Onboarding): Create Profile
Browse files Browse the repository at this point in the history
- implements the basic Onboarding UI skeleton and the Create Profile
flow

Fixes #16719
  • Loading branch information
caybro committed Nov 7, 2024
1 parent d6d5467 commit d53cbc9
Show file tree
Hide file tree
Showing 26 changed files with 1,132 additions and 98 deletions.
94 changes: 94 additions & 0 deletions storybook/pages/OnboardingLayoutPage.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQml 2.15

import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1

import Models 1.0
import Storybook 1.0

import utils 1.0

import AppLayouts.Onboarding2 1.0

import mainui 1.0
import shared.stores 1.0 as SharedStores
import AppLayouts.stores 1.0 as AppLayoutStores

// compat
import AppLayouts.Onboarding.stores 1.0 as OOBS

SplitView {
id: root
orientation: Qt.Vertical

Logs { id: logs }

Popups {
popupParent: root
sharedRootStore: SharedStores.RootStore {}
rootStore: AppLayoutStores.RootStore {}
communityTokensStore: SharedStores.CommunityTokensStore {}
}

OnboardingLayout {
id: onboarding
SplitView.fillWidth: true
SplitView.fillHeight: true
startupStore: OOBS.StartupStore {
function getPasswordStrengthScore(password) {
return Math.min(password.length, 4)
}
}
metricsStore: SharedStores.MetricsStore {
readonly property var d: QtObject {
id: d
property bool isCentralizedMetricsEnabled
}

function toggleCentralizedMetrics(enabled) {
d.isCentralizedMetricsEnabled = enabled
}

function addCentralizedMetricIfEnabled(eventName, eventValue = null) {}

readonly property bool isCentralizedMetricsEnabled : d.isCentralizedMetricsEnabled
}

QtObject {
id: localAppSettings
property bool metricsPopupSeen
}
}

LogsAndControlsPanel {
id: logsAndControlsPanel

SplitView.minimumHeight: 100
SplitView.preferredHeight: 150

logsView.logText: logs.logText

ColumnLayout {
Label {
text: "Current page: %1".arg(onboarding.stack.currentItem ? onboarding.stack.currentItem.title : "")
}
Label {
text: "Current path: %1 -> %2".arg(onboarding.primaryPath).arg(onboarding.secondaryPath)
}
Label {
text: "Stack depth: %1".arg(onboarding.stack.depth)
}
}
}
}

// category: Onboarding
// status: good
// https://www.figma.com/design/Lw4nPYQcZOPOwTgETiiIYo/Desktop-Onboarding-Redesign?node-id=1-25&node-type=canvas&m=dev
3 changes: 3 additions & 0 deletions storybook/stubs/shared/stores/MetricsStore.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import QtQml 2.15

QtObject {}
1 change: 1 addition & 0 deletions storybook/stubs/shared/stores/qmldir
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ PermissionsStore 1.0 PermissionsStore.qml
ProfileStore 1.0 ProfileStore.qml
RootStore 1.0 RootStore.qml
UtilsStore 1.0 UtilsStore.qml
MetricsStore 1.0 MetricsStore.qml
3 changes: 1 addition & 2 deletions ui/StatusQ/src/StatusQ/Components/StatusImage.qml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import QtQuick 2.13
import QtQuick.Window 2.15
import QtQuick 2.15

/*!
\qmltype StatusImage
Expand Down
1 change: 1 addition & 0 deletions ui/StatusQ/src/StatusQ/Components/StatusSmartIdenticon.qml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Loader {
objectName: "statusRoundImage"
width: parent.width
height: parent.height
radius: asset.bgRadius
image.source: root.asset.isImage ? root.asset.name : ""
showLoadingIndicator: true
border.width: root.asset.imgIsIdenticon ? 1 : 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ StatusProgressBar {
Default value: "So-so"
*/
property string labelSoso: qsTr("So-so")
property string labelSoso: qsTr("Okay")
/*!
\qmlproperty string StatusPasswordStrengthIndicator::labelGood
This property holds the text shown when the strength is StatusPasswordStrengthIndicator.Strength.Good.
Expand All @@ -88,7 +88,7 @@ StatusProgressBar {
Default value: "Great"
*/
property string labelGreat: qsTr("Great")
property string labelGreat: qsTr("Very strong")

enum Strength {
None, // 0
Expand Down
5 changes: 5 additions & 0 deletions ui/StatusQ/src/assets.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -8339,6 +8339,11 @@
<file>assets/png/onboarding/profile_fetching_in_progress.png</file>
<file>assets/png/onboarding/seed-phrase.png</file>
<file>assets/png/onboarding/welcome.png</file>
<file>assets/png/onboarding/status_totebag_artwork_1.png</file>
<file>assets/png/onboarding/status_generate_keys.png</file>
<file>assets/png/onboarding/create_profile_seed.png</file>
<file>assets/png/onboarding/create_profile_keycard.png</file>
<file>assets/png/onboarding/enable_biometrics.png</file>
<file>assets/png/onRampProviders/latamex.png</file>
<file>assets/png/onRampProviders/mercuryo.png</file>
<file>assets/png/onRampProviders/moonPay.png</file>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
207 changes: 207 additions & 0 deletions ui/app/AppLayouts/Onboarding2/OnboardingLayout.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import QtQuick 2.15
import QtQuick.Controls 2.15

import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1

import AppLayouts.Onboarding2.pages 1.0

import shared.stores 1.0 as SharedStores
import utils 1.0

// compat
import AppLayouts.Onboarding.stores 1.0 as OOBS

Page {
id: root

property OOBS.StartupStore startupStore: OOBS.StartupStore {}
required property SharedStores.MetricsStore metricsStore

readonly property alias stack: stack
readonly property alias primaryPath: d.primaryPath
readonly property alias secondaryPath: d.secondaryPath

signal finished(bool success, int primaryPath, int secondaryPath)

QtObject {
id: d
// logic
property int primaryPath: OnboardingLayout.PrimaryPath.Unknown
property int secondaryPath: OnboardingLayout.SecondaryPath.Unknown

// UI
readonly property int opacityDuration: 50
readonly property int swipeDuration: 400

// state
property string password
property bool enableBiometrics
}

enum PrimaryPath {
Unknown,
CreateProfile,
Login
}

enum SecondaryPath {
Unknown,
CreateProfileWithPassword,
CreateProfileWithSeedphrase,
CreateProfileWithKeycard
// TODO secondary Login paths
}

// page stack
StackView {
id: stack
anchors.fill: parent
initialItem: welcomePage

pushEnter: Transition {
ParallelAnimation {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 50; easing.type: Easing.InQuint }
NumberAnimation { property: "x"; from: (stack.mirrored ? -0.3 : 0.3) * stack.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
}
}
pushExit: Transition {
NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 50; easing.type: Easing.OutQuint }
}
popEnter: Transition {
ParallelAnimation {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 50; easing.type: Easing.InQuint }
NumberAnimation { property: "x"; from: (stack.mirrored ? -0.3 : 0.3) * -stack.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
}
}
popExit: pushExit
replaceEnter: pushEnter
replaceExit: pushExit
}

// back button
StatusButton {
objectName: "onboardingBackButton"
isRoundIcon: true
width: 44
height: 44
anchors.left: parent.left
anchors.leftMargin: Theme.padding
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.padding
icon.name: "arrow-left"
visible: stack.depth > 1 && !stack.busy
onClicked: stack.pop()
}

// main signal handler
Connections {
target: stack.currentItem
ignoreUnknownSignals: true

// welcome page
function onCreateProfileRequested() {
console.warn("!!! CREATE PROFILE")
d.primaryPath = OnboardingLayout.PrimaryPath.CreateProfile
stack.push(helpUsImproveStatusPage)
}
function onLoginRequested() {
console.warn("!!! LOG IN")
d.primaryPath = OnboardingLayout.PrimaryPath.Login
}

// help us improve page
function onShareUsageDataRequested() {
console.warn("!!! SHARE USAGE DATA")
metricsStore.toggleCentralizedMetrics(true)
Global.addCentralizedMetricIfEnabled("usage_data_shared", {placement: Constants.metricsEnablePlacement.onboarding})
localAppSettings.metricsPopupSeen = true

if (d.primaryPath === OnboardingLayout.PrimaryPath.CreateProfile)
stack.push(createProfilePage)
else if (d.primaryPath === OnboardingLayout.PrimaryPath.Login)
; // TODO Login
}
function onDontShareUsageDataRequested() {
console.warn("!!! DONT SHARE USAGE DATA")
metricsStore.toggleCentralizedMetrics(false)
localAppSettings.metricsPopupSeen = true

if (d.primaryPath === OnboardingLayout.PrimaryPath.CreateProfile)
stack.push(createProfilePage)
else if (d.primaryPath === OnboardingLayout.PrimaryPath.Login)
; // TODO Login
}

// create profile page
function onCreateProfileWithPasswordRequested() {
console.warn("!!! CREATE PROFILE WITH PASSWORD")
d.secondaryPath = OnboardingLayout.SecondaryPath.CreateProfileWithPassword
stack.push(createPasswordPage)
}
function onCreateProfileWithSeedphraseRequested() {
console.warn("!!! CREATE PROFILE WITH SEEDPHRASE")
d.secondaryPath = OnboardingLayout.SecondaryPath.CreateProfileWithSeedphrase
}
function onCreateProfileWithEmptyKeycardRequested() {
console.warn("!!! CREATE PROFILE WITH KEYCARD")
d.secondaryPath = OnboardingLayout.SecondaryPath.CreateProfileWithKeycard
}

// create password page
function onPasswordSetRequested(password: string) {
console.warn("!!! SET PASSWORD REQUESTED")
//root.startupStore.setPassword(password)
d.password = password

stack.push(enableBiometricsPage, {subtitle: qsTr("Use biometrics to fill in your password?")})
}

// enable biometrics page
function onEnableBiometricsRequested(enabled: bool) {
console.warn("!!! ENABLE BIOMETRICS:", enabled)
d.enableBiometrics = enabled
// TODO push final splash screen
}
}

Component {
id: welcomePage
WelcomePage {
StackView.onActivated: {
d.primaryPath = OnboardingLayout.PrimaryPath.Unknown
d.secondaryPath = OnboardingLayout.SecondaryPath.Unknown
d.password = ""
d.enableBiometrics = false
}
}
}

Component {
id: helpUsImproveStatusPage
HelpUsImproveStatusPage {}
}

Component {
id: createProfilePage
CreateProfilePage {}
}

Component {
id: createPasswordPage
CreatePasswordPage {
passwordStrengthScoreFunction: root.startupStore.getPasswordStrengthScore
StackView.onRemoved: {
d.secondaryPath = OnboardingLayout.SecondaryPath.Unknown
d.password = ""
}
}
}

Component {
id: enableBiometricsPage
EnableBiometricsPage {
StackView.onRemoved: d.enableBiometrics = false
}
}
}
Loading

0 comments on commit d53cbc9

Please sign in to comment.