What changed, and why it matters
This commit is a simple user-interface reorganization in Electrum's mobile/QML preferences screen. It groups existing security-related toggles (biometric authentication, payment authentication, screenshot protection) under a new 'Security' heading and renames one toggle from 'Always allow screenshots' to 'Protect secrets from screenshots' while keeping the same underlying setting. No security vulnerability is introduced or fixed.
No security action needed; this is a UI/UX refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies electrum/gui/qml/components/Preferences.qml only. It moves existing RowLayout preference items around visually: the ‘Security’ section now contains payment authentication, biometric authentication, and the screenshot toggle. The screenshot switch logic is inverted at the UI layer (disableScreenshots.checked = !Config.alwaysAllowScreenshots) so the label reads ‘Protect secrets from screenshots’ instead of ‘Always allow screenshots’. The actual Config.alwaysAllowScreenshots backend value and behavior are unchanged. No new functionality, no permission changes, no cryptographic changes, and no bug fixes are present.
Changed components
electrum/gui/qml/components/Preferences.qmlInspect captured patch +82 / −77
diff --git a/electrum/gui/qml/components/Preferences.qml b/electrum/gui/qml/components/Preferences.qml
index fe560d3..3bbcff0 100644
--- a/electrum/gui/qml/components/Preferences.qml
+++ b/electrum/gui/qml/components/Preferences.qml
@@ -161,55 +161,61 @@ Pane {
Layout.columnSpan: 2
Layout.fillWidth: true
spacing: 0
- // isAvailable checks phone support and if a fingerprint is enrolled on the system
- enabled: Biometrics.isAvailable && Daemon.currentWallet
+ Switch {
+ id: syncLabels
+ onCheckedChanged: {
+ if (activeFocus)
+ AppController.setPluginEnabled('labels', checked)
+ }
+ }
+ Label {
+ Layout.fillWidth: true
+ text: qsTr('Synchronize labels')
+ wrapMode: Text.Wrap
+ }
+ }
- Connections {
- target: Biometrics
- function onEnablingFailed(error) {
- if (error === 'CANCELLED') {
- return // don't show error popup
- }
- var err = app.messageDialog.createObject(app, {
- text: qsTr('Failed to enable biometric authentication: ') + error
- })
- err.open()
+ RowLayout {
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ spacing: 0
+ Switch {
+ id: psbtNostr
+ onCheckedChanged: {
+ if (activeFocus)
+ AppController.setPluginEnabled('psbt_nostr', checked)
}
}
+ Label {
+ Layout.fillWidth: true
+ text: qsTr('Nostr Cosigner')
+ wrapMode: Text.Wrap
+ }
+ }
+ RowLayout {
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ spacing: 0
Switch {
- id: useBiometrics
- checked: Biometrics.isEnabled
+ id: setMaxBrightnessOnQrDisplay
onCheckedChanged: {
- if (activeFocus) {
- useBiometrics.focus = false
- if (checked) {
- if (Daemon.singlePasswordEnabled) {
- Biometrics.enable(Daemon.singlePassword)
- } else {
- useBiometrics.checked = false
- var err = app.messageDialog.createObject(app, {
- title: qsTr('Unavailable'),
- text: [
- qsTr("Cannot activate biometric authentication because you have wallets with different passwords."),
- qsTr("To use biometric authentication you first need to change all wallet passwords to the same password.")
- ].join("\n")
- })
- err.open()
- }
- } else {
- Biometrics.disableProtected()
- }
- }
+ if (activeFocus)
+ Config.setMaxBrightnessOnQrDisplay = checked
}
}
Label {
Layout.fillWidth: true
- text: qsTr('Biometric authentication')
+ text: qsTr('Set display to max brightness when displaying QR codes')
wrapMode: Text.Wrap
}
}
+ PrefsHeading {
+ Layout.columnSpan: 2
+ text: qsTr('Security')
+ }
+
RowLayout {
Layout.columnSpan: 2
Layout.fillWidth: true
@@ -232,7 +238,7 @@ Pane {
}
Label {
Layout.fillWidth: true
- text: qsTr('Payment authentication')
+ text: qsTr('Request authentication for payments')
wrapMode: Text.Wrap
}
}
@@ -241,34 +247,51 @@ Pane {
Layout.columnSpan: 2
Layout.fillWidth: true
spacing: 0
- Switch {
- id: syncLabels
- onCheckedChanged: {
- if (activeFocus)
- AppController.setPluginEnabled('labels', checked)
+ // isAvailable checks phone support and if a fingerprint is enrolled on the system
+ enabled: Biometrics.isAvailable && Daemon.currentWallet
+
+ Connections {
+ target: Biometrics
+ function onEnablingFailed(error) {
+ if (error === 'CANCELLED') {
+ return // don't show error popup
+ }
+ var err = app.messageDialog.createObject(app, {
+ text: qsTr('Failed to enable biometric authentication: ') + error
+ })
+ err.open()
}
}
- Label {
- Layout.fillWidth: true
- text: qsTr('Synchronize labels')
- wrapMode: Text.Wrap
- }
- }
- RowLayout {
- Layout.columnSpan: 2
- Layout.fillWidth: true
- spacing: 0
Switch {
- id: psbtNostr
+ id: useBiometrics
+ checked: Biometrics.isEnabled
onCheckedChanged: {
- if (activeFocus)
- AppController.setPluginEnabled('psbt_nostr', checked)
+ if (activeFocus) {
+ useBiometrics.focus = false
+ if (checked) {
+ if (Daemon.singlePasswordEnabled) {
+ Biometrics.enable(Daemon.singlePassword)
+ } else {
+ useBiometrics.checked = false
+ var err = app.messageDialog.createObject(app, {
+ title: qsTr('Unavailable'),
+ text: [
+ qsTr("Cannot activate biometric authentication because you have wallets with different passwords."),
+ qsTr("To use biometric authentication you first need to change all wallet passwords to the same password.")
+ ].join("\n")
+ })
+ err.open()
+ }
+ } else {
+ Biometrics.disableProtected()
+ }
+ }
}
}
Label {
Layout.fillWidth: true
- text: qsTr('Nostr Cosigner')
+ text: qsTr('Biometric authentication')
wrapMode: Text.Wrap
}
}
@@ -278,15 +301,15 @@ Pane {
Layout.fillWidth: true
spacing: 0
Switch {
- id: setMaxBrightnessOnQrDisplay
+ id: disableScreenshots
onCheckedChanged: {
if (activeFocus)
- Config.setMaxBrightnessOnQrDisplay = checked
+ Config.alwaysAllowScreenshots = !checked
}
}
Label {
Layout.fillWidth: true
- text: qsTr('Set display to max brightness when displaying QR codes')
+ text: qsTr('Protect secrets from screenshots')
wrapMode: Text.Wrap
}
}
@@ -463,24 +486,6 @@ Pane {
wrapMode: Text.Wrap
}
}
-
- RowLayout {
- Layout.columnSpan: 2
- Layout.fillWidth: true
- spacing: 0
- Switch {
- id: alwaysAllowScreenshots
- onCheckedChanged: {
- if (activeFocus)
- Config.alwaysAllowScreenshots = checked
- }
- }
- Label {
- Layout.fillWidth: true
- text: qsTr('Always allow screenshots')
- wrapMode: Text.Wrap
- }
- }
}
}
}
@@ -498,7 +503,7 @@ Pane {
freezeReusedAddressUtxos.checked = Config.freezeReusedAddressUtxos
useTrampolineRouting.checked = !Config.useGossip
enableDebugLogs.checked = Config.enableDebugLogs
- alwaysAllowScreenshots.checked = Config.alwaysAllowScreenshots
+ disableScreenshots.checked = !Config.alwaysAllowScreenshots
setMaxBrightnessOnQrDisplay.checked = Config.setMaxBrightnessOnQrDisplay
useRecoverableChannels.checked = Config.useRecoverableChannels
syncLabels.checked = AppController.isPluginEnabled('labels')
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.