fix(android): drop the labels, put a clear cross in each field

The labels went in this afternoon to tell the token and the sync password
apart, both being masked and stacked. They are removed on request; the
placeholders carry that job again, which they do while the fields are empty -
and that is when it matters, since a filled field is one you just typed.

Each field gets a cross instead. Clearing a forty-character token with the
backspace key takes forty presses and leaves a character behind easily, which
shows up as a 401 whose cause is invisible.

The cross is a SIBLING of the input, laid over it - never a child. A child of
an input does not receive the tap; that cost a build earlier today when the
search field was given its own cross.

It also pushes the configuration immediately: the field keeps the focus, so the
blur that normally carries the value to Delphi never happens.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-08-17 19:18:39 +01:00
parent 382e38913b
commit 060611f101
+39 -11
View File
@@ -186,8 +186,15 @@
font: inherit; outline: none;
}
.field-in::placeholder { color: var(--muted); }
.in-label { color: var(--muted); font-size: 12px; margin: 10px 0 -2px 4px; }
.in-label span { opacity: .7; }
.in-wrap { position: relative; }
/* Le champ laisse la place a la croix, sinon le texte passe dessous. */
.in-wrap .field-in { padding-right: 44px; }
.in-x {
position: absolute; right: 0; top: 8px; width: 44px; height: 46px;
display: flex; align-items: center; justify-content: center;
color: var(--muted); font-size: 22px;
}
.in-x:active { opacity: .5; }
#log {
margin: 10px 0 0; padding: 10px 12px; max-height: 34vh; overflow: auto;
background: rgba(0,0,0,.20); border-radius: var(--radius-s);
@@ -221,26 +228,35 @@
depot, jamais dans le coffre. -->
<button class="btn wide" id="btnWriteTest" hidden>Write test (debug)</button>
</div>
<!-- DES LIBELLES, PAS SEULEMENT DES INDICATIONS D'AIDE. Celles-ci
disparaissent des que le champ est rempli, et depuis que le jeton est
masque comme le mot de passe, deux champs en points noirs se
succedent sans rien qui les distingue - on colle alors dans le mauvais
sans que rien ne le signale. -->
<!-- UNE CROIX PAR CHAMP. Vider par la touche retour demande une quarantaine
d'appuis sur un jeton, et laisse facilement un caractere - ce qui donne
un 401 dont la cause est invisible. La croix est UN FRERE du champ,
posee par-dessus, jamais un enfant : un enfant d'input ne recoit pas
l'appui.
L'indication d'aide sert de libelle, et le jeton comme le mot de passe
sont masques - le placeholder reste donc le seul moyen de les
distinguer quand ils sont vides. -->
<div id="cfg" hidden>
<div class="in-label">Endpoint URL</div>
<div class="in-wrap">
<input class="field-in" id="url" placeholder="endpoint URL"
autocomplete="off" autocorrect="off" autocapitalize="none"
spellcheck="false" inputmode="url">
<div class="in-x" data-clear="url">&#215;</div>
</div>
<!-- MASQUE, comme le mot de passe juste en dessous. Il s'affichait en
clair alors qu'il ouvre le depot : le moins grave des trois secrets
de cet ecran, mais le seul qu'un regard par-dessus l'epaule
attrapait. On le saisit une fois ; le relire n'a aucun usage. -->
<div class="in-label">Gitea token <span>&#183; needs read AND write</span></div>
<input class="field-in" id="tok" placeholder="bearer token"
<div class="in-wrap">
<input class="field-in" id="tok" placeholder="gitea token (read + write)"
type="password" autocomplete="off">
<div class="in-label">Sync password <span>&#183; decrypts the vault</span></div>
<div class="in-x" data-clear="tok">&#215;</div>
</div>
<div class="in-wrap">
<input class="field-in" id="pwd" placeholder="sync password"
type="password" autocomplete="off">
<div class="in-x" data-clear="pwd">&#215;</div>
</div>
</div>
<pre id="log" hidden></pre>
</div>
@@ -347,6 +363,18 @@ document.getElementById('btnSync').addEventListener('click', function () {
pushConfig(); // ce qui est tape mais pas encore quitte compte aussi
send('sync');
});
// Un seul ecouteur pour les trois croix : elles ne different que par leur cible.
document.getElementById('cfg').addEventListener('click', function (ev) {
var id = ev.target.getAttribute('data-clear');
if (!id) return;
var el = document.getElementById(id);
el.value = '';
el.focus();
// Delphi doit l'apprendre tout de suite : le champ ne perdra pas le focus,
// donc l'evenement qui remonte d'habitude la configuration n'aura pas lieu.
pushConfig();
});
document.getElementById('btnCfg').addEventListener('click', function () {
var c = document.getElementById('cfg');
c.hidden = !c.hidden;