Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 222 additions & 0 deletions storybook/pages/KeycardChannelDrawerPage.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

import Storybook

import StatusQ.Core
import StatusQ.Core.Theme
import StatusQ.Controls
import StatusQ.Components

import shared.popups

SplitView {
id: root

orientation: Qt.Horizontal

Logs { id: logs }

// Helper timers for test scenarios
Timer {
id: timer1
interval: 1500
onTriggered: {
if (root.currentScenario === "success") {
logs.logEvent("Changing to reading state")
stateCombo.currentIndex = 2 // reading
timer2.start()
} else if (root.currentScenario === "error") {
logs.logEvent("Changing to reading state")
stateCombo.currentIndex = 2 // reading
timer2.start()
} else if (root.currentScenario === "quick") {
logs.logEvent("Quick change to reading")
stateCombo.currentIndex = 2 // reading
timer2.start()
}
}
}

Timer {
id: timer2
interval: root.currentScenario === "quick" ? 300 : 1500
onTriggered: {
if (root.currentScenario === "success") {
logs.logEvent("Changing to idle state (success)")
stateCombo.currentIndex = 0 // idle (will trigger success)
} else if (root.currentScenario === "error") {
logs.logEvent("Changing to error state")
stateCombo.currentIndex = 3 // error
} else if (root.currentScenario === "quick") {
logs.logEvent("Quick change to idle (success)")
stateCombo.currentIndex = 0 // idle
}
root.currentScenario = ""
}
}

property string currentScenario: ""

Item {
SplitView.fillWidth: true
SplitView.fillHeight: true

KeycardChannelDrawer {
id: drawer

currentState: stateCombo.currentValue
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside

onDismissed: {
logs.logEvent("KeycardChannelDrawer::dismissed()")
}
}
}

LogsAndControlsPanel {
id: logsAndControlsPanel

SplitView.preferredWidth: 350
SplitView.fillHeight: true

logsView.logText: logs.logText

ColumnLayout {
Layout.fillWidth: true
spacing: Theme.padding

// State control section
RowLayout {
Layout.fillWidth: true
spacing: Theme.halfPadding

Label {
Layout.preferredWidth: 120
text: "Current state:"
}

ComboBox {
id: stateCombo
Layout.fillWidth: true

textRole: "text"
valueRole: "value"

model: ListModel {
ListElement { text: "Idle"; value: "idle" }
ListElement { text: "Waiting for Keycard"; value: "waiting-for-keycard" }
ListElement { text: "Reading"; value: "reading" }
ListElement { text: "Error"; value: "error" }
}

currentIndex: 0
}
}

// State info display
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: infoColumn.implicitHeight + Theme.padding * 2
color: Theme.palette.baseColor5
radius: Theme.radius
border.width: 1
border.color: Theme.palette.baseColor2

ColumnLayout {
id: infoColumn
anchors.fill: parent
anchors.margins: Theme.padding
spacing: Theme.halfPadding

StatusBaseText {
Layout.fillWidth: true
text: "State Information"
font.bold: true
font.pixelSize: Theme.primaryTextFontSize
}

StatusBaseText {
Layout.fillWidth: true
text: "Current: %1".arg(stateCombo.currentText)
font.pixelSize: Theme.tertiaryTextFontSize
color: Theme.palette.baseColor1
}

StatusBaseText {
Layout.fillWidth: true
text: "Opened: %1".arg(drawer.opened ? "Yes" : "No")
font.pixelSize: Theme.tertiaryTextFontSize
color: Theme.palette.baseColor1
}
}
}

// Scenario buttons section
Label {
Layout.fillWidth: true
Layout.topMargin: Theme.padding
text: "Test Scenarios:"
font.bold: true
}

Button {
Layout.fillWidth: true
text: "Simulate Success Flow"
onClicked: {
logs.logEvent("Starting success flow simulation")
root.currentScenario = "success"
stateCombo.currentIndex = 1 // waiting-for-keycard
timer1.start()
}
}

Button {
Layout.fillWidth: true
text: "Simulate Error Flow"
onClicked: {
logs.logEvent("Starting error flow simulation")
root.currentScenario = "error"
stateCombo.currentIndex = 1 // waiting-for-keycard
timer1.start()
}
}

Button {
Layout.fillWidth: true
text: "Simulate Quick State Changes"
onClicked: {
logs.logEvent("Testing state queue with rapid changes")
root.currentScenario = "quick"
stateCombo.currentIndex = 1 // waiting-for-keycard
timer1.interval = 300
timer1.start()
}
}

Button {
Layout.fillWidth: true
text: "Open Drawer Manually"
onClicked: {
logs.logEvent("Manually opening drawer")
drawer.open()
}
}

Button {
Layout.fillWidth: true
text: "Clear Logs"
onClicked: logs.clear()
}

Item {
Layout.fillHeight: true
}
}
}
}

// category: Popups
// status: good

22 changes: 17 additions & 5 deletions ui/StatusQ/src/StatusQ/Controls/StatusPinInput.qml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ Item {
*/
property int additionalSpacing: 0

/*!
\qmlproperty flags StatusPinInput::inputMethodHints
This property allows you to customize the input method hints for the virtual keyboard.
The default value is Qt.ImhNone which allows any input based on the validator.
*/
property int inputMethodHints: Qt.ImhNone

signal pinEditedManually()

QtObject {
Expand Down Expand Up @@ -158,9 +165,10 @@ Item {
Convenient method to force active focus in case it gets stolen by any other component.
*/
function forceFocus() {
if (Utils.isMobile)
return
inputText.forceActiveFocus()
if (Qt.inputMethod.visible == false) {
Qt.inputMethod.show()
}
d.activateBlink()
}

Expand Down Expand Up @@ -208,10 +216,14 @@ Item {
TextInput {
id: inputText
objectName: "pinInputTextInput"
visible: false
focus: !Utils.isMobile
visible: true
// Set explicit dimensions for Android keyboard input to work
width: 1
height: 1
opacity: 0
maximumLength: root.pinLen
validator: d.statusValidator.validatorObj
inputMethodHints: root.inputMethodHints
// validator: d.statusValidator.validatorObj
onTextChanged: {
// Modify state of current introduced character position:
if(text.length >= (d.currentPinIndex + 1)) {
Expand Down
7 changes: 7 additions & 0 deletions ui/app/AppLayouts/Onboarding/components/LoginKeycardBox.qml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Control {
objectName: "pinInput"
validator: StatusIntValidator { bottom: 0; top: 999999 }
visible: false
inputMethodHints: Qt.ImhDigitsOnly

onPinInputChanged: {
if (pinInput.length === 6) {
Expand Down Expand Up @@ -235,6 +236,7 @@ Control {
PropertyChanges {
target: pinInputField
visible: true
focus: true
}
PropertyChanges {
target: background
Expand All @@ -251,4 +253,9 @@ Control {
}
}
]

TapHandler {
enabled: pinInputField.visible
onTapped: pinInputField.forceFocus()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ KeycardBasePage {
anchors.horizontalCenter: parent.horizontalCenter
pinLen: Constants.keycard.general.keycardPinLength
validator: StatusIntValidator { bottom: 0; top: 999999 }
inputMethodHints: Qt.ImhDigitsOnly
onPinInputChanged: {
if (pinInput.pinInput.length === pinInput.pinLen) {
root.authorizationRequested(pinInput.pinInput)
Expand Down
70 changes: 59 additions & 11 deletions ui/i18n/qml_base_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2693,6 +2693,26 @@ Do you wish to override the security check and continue?</source>
<source>Zoom</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear site data</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use it to reset the current site if it doesn&apos;t load or work properly.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clearing cache...</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear cache</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clears cached files, cookies, and history for the entire browser. Browsing is paused until it is done.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>BrowserTabView</name>
Expand Down Expand Up @@ -7622,13 +7642,6 @@ Please add it and try again.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FeeRow</name>
<message>
<source>Max.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FeesBox</name>
<message>
Expand Down Expand Up @@ -8891,6 +8904,45 @@ L2 fee: %2</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>KeycardChannelDrawer</name>
<message>
<source>Please tap your Keycard to the back of your device</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reading Keycard</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please keep your Keycard in place</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Keycard Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>An error occurred. Please try again.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Success</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Keycard operation completed successfully</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dismiss</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Ready to scan</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>KeycardConfirmation</name>
<message>
Expand Down Expand Up @@ -8986,10 +9038,6 @@ Are you sure you want to do this?</source>
<source>PIN correct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Keycard blocked</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n attempt(s) remaining</source>
<translation type="unfinished">
Expand Down
Loading