pin support

This commit is contained in:
2026-04-28 12:01:35 +08:00
parent 2556c2db83
commit 7c884a2185
9 changed files with 324 additions and 2 deletions

View File

@@ -286,9 +286,15 @@ ApplicationWindow {
function onSendError(error) {
sendProgressDialog.close()
pinDialog.close()
errorDialog.text = error
errorDialog.open()
}
function onPinRequired(firstAttempt) {
pinDialog.isFirstAttempt = firstAttempt
pinDialog.open()
}
}
Dialog {
@@ -317,6 +323,112 @@ ApplicationWindow {
}
}
Dialog {
id: pinDialog
anchors.centerIn: parent
modal: true
closePolicy: Popup.NoAutoClose
title: qsTr("PIN Required")
property bool isFirstAttempt: true
ColumnLayout {
spacing: 12
Label {
text: pinDialog.isFirstAttempt
? qsTr("The receiver requires a PIN to accept files.")
: qsTr("Invalid PIN. Please try again.")
wrapMode: Text.WordWrap
Layout.fillWidth: true
color: pinDialog.isFirstAttempt ? palette.text : "red"
}
TextField {
id: pinInput
Layout.fillWidth: true
placeholderText: qsTr("Enter PIN")
echoMode: TextInput.Password
focus: true
onAccepted: pinDialog.submitPin()
}
}
footer: DialogButtonBox {
Button {
text: qsTr("Cancel")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
}
Button {
text: qsTr("Submit")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
enabled: pinInput.text.length > 0
}
}
onAccepted: submitPin()
onRejected: {
appController.cancelSend()
close()
}
function submitPin() {
if (pinInput.text.length > 0) {
appController.retryWithPin(pinInput.text)
pinInput.text = ""
}
}
onOpened: {
pinInput.text = ""
pinInput.forceActiveFocus()
}
}
Dialog {
id: setPinDialog
anchors.centerIn: parent
modal: true
title: qsTr("Set Receive PIN")
ColumnLayout {
spacing: 12
Label {
text: qsTr("Enter a PIN that senders must provide to transfer files to this device. Leave empty to disable.")
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
TextField {
id: setPinInput
Layout.fillWidth: true
placeholderText: qsTr("Enter PIN")
onAccepted: setPinDialog.accepted()
}
}
footer: DialogButtonBox {
Button {
text: qsTr("Cancel")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
}
Button {
text: qsTr("OK")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
}
}
onAccepted: {
appController.receivePin = setPinInput.text
}
onOpened: {
setPinInput.text = appController.receivePin
setPinInput.forceActiveFocus()
}
}
function formatSize(bytes) {
if (bytes < 1024) return bytes + " B"
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB"
@@ -597,6 +709,25 @@ ApplicationWindow {
checked: appController.quickSave
onCheckedChanged: appController.quickSave = checked
}
Label { text: qsTr("Receive PIN:") }
RowLayout {
Layout.fillWidth: true
Label {
text: appController.receivePin.length > 0 ? qsTr("Enabled") : qsTr("Disabled")
color: appController.receivePin.length > 0 ? "green" : palette.mid
}
Item { Layout.fillWidth: true }
Button {
text: appController.receivePin.length > 0 ? qsTr("Change") : qsTr("Set PIN")
onClicked: setPinDialog.open()
}
Button {
text: qsTr("Remove")
visible: appController.receivePin.length > 0
onClicked: appController.receivePin = ""
}
}
}
FolderDialog {