Give identity its due: native enrollment, honest deletion, and sign-in that stays home
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
// A row whose trailing control is a free-text field that reports every
|
||||
// keystroke.
|
||||
//
|
||||
// LiveFieldRow {
|
||||
// label: "Username"
|
||||
// detail: root.userNameProblem !== "" ? root.userNameProblem : "Lowercase…"
|
||||
// invalid: root.userNameProblem !== ""
|
||||
// onEdited: value => root.newUserName = value
|
||||
// }
|
||||
//
|
||||
// TextFieldRow commits on Enter or blur, which is right when every commit is a
|
||||
// privileged write that prompts. It is wrong for a form that has to say whether
|
||||
// what is being typed is acceptable *while* it is being typed: the add-user
|
||||
// form used TextFieldRow and its Create button stayed dark until the field lost
|
||||
// focus, which reads as a broken button rather than as a field awaiting blur.
|
||||
//
|
||||
// So this reports twice. `edited` fires per keystroke, for validation and for
|
||||
// state a page holds until a submit button is pressed. `accepted` fires on
|
||||
// Enter or when focus leaves, for the values that go straight to a privileged
|
||||
// write and must not prompt once per character.
|
||||
|
||||
import QtQuick
|
||||
import qs.config
|
||||
|
||||
SettingRow {
|
||||
id: root
|
||||
|
||||
property string text: ""
|
||||
property string placeholder: ""
|
||||
property bool enabled: true
|
||||
// Draws the field as rejected. The page decides what invalid means; this
|
||||
// only shows it, next to the detail line that says why.
|
||||
property bool invalid: false
|
||||
property int maximumLength: 0
|
||||
|
||||
signal edited(value: string)
|
||||
signal accepted(value: string)
|
||||
|
||||
controlWidth: 220
|
||||
|
||||
function clear(): void {
|
||||
input.text = "";
|
||||
}
|
||||
|
||||
// An external change replaces what is shown, unless it would yank the field
|
||||
// out from under someone mid-edit.
|
||||
onTextChanged: if (!input.activeFocus && input.text !== root.text) input.text = root.text
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: root.controlWidth
|
||||
height: 32
|
||||
radius: 9
|
||||
color: Theme.alpha(Theme.fg, root.enabled ? 0.06 : 0.03)
|
||||
border.width: input.activeFocus ? 2 : 1
|
||||
border.color: root.invalid
|
||||
? Theme.alpha(Theme.danger, 0.6)
|
||||
: (input.activeFocus ? Theme.alpha(Theme.accent, 0.55) : Theme.alpha(Theme.fg, 0.1))
|
||||
opacity: root.enabled ? 1 : 0.5
|
||||
|
||||
TextInput {
|
||||
id: input
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 11
|
||||
anchors.rightMargin: 11
|
||||
enabled: root.enabled
|
||||
activeFocusOnTab: true
|
||||
text: root.text
|
||||
color: root.invalid ? Theme.danger : Theme.fg
|
||||
selectByMouse: true
|
||||
selectionColor: Theme.alpha(Theme.accent, 0.5)
|
||||
selectedTextColor: Theme.fg
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSize
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
maximumLength: root.maximumLength > 0 ? root.maximumLength : 32767
|
||||
clip: true
|
||||
|
||||
onTextEdited: root.edited(input.text)
|
||||
onAccepted: if (input.text !== root.text) root.accepted(input.text)
|
||||
|
||||
// Unchanged text is not re-committed: a page whose `accepted`
|
||||
// handler writes through polkit would otherwise prompt every time
|
||||
// the field was tabbed past.
|
||||
onActiveFocusChanged: {
|
||||
if (input.activeFocus)
|
||||
return;
|
||||
if (input.text !== root.text)
|
||||
root.accepted(input.text);
|
||||
else
|
||||
input.text = root.text;
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
visible: input.text === ""
|
||||
text: root.placeholder
|
||||
color: Theme.fgMuted
|
||||
font: input.font
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user