fix(apk): le formulaire garde la vue 'detail', sinon chaque champ perdait le focus

Un gardien defocalise tout ce qui prend le focus hors de l'ecran courant, en
comparant 'view' a l'identifiant de l'ecran. Le formulaire vit dans l'ecran
'detail' ; poser view='edit' le faisait donc blurer a chaque focusin - clavier
ouvert, pas de curseur, rien ne rentrait. Un drapeau 'editing' dit desormais
qu'on modifie, et 'view' continue de nommer l'ecran.

Mesure au protocole DevTools sur le telephone : le champ etait bien atteignable
et focalise, ce qui a elimine le DOM et le CSS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-09-25 17:03:27 +01:00
parent 2a461cad26
commit 9ae7b58767
+25 -8
View File
@@ -1076,6 +1076,7 @@ function renderDetail(d) {
document.getElementById('kebab').hidden = false;
document.getElementById('pencil').hidden = false;
document.getElementById('dav').hidden = true;
editing = false;
var html = '', i;
if (d.totp)
html += '<div class="field totp" id="totp"><div class="cap">2FA code</div>'
@@ -1398,6 +1399,7 @@ function openNewEntry() {
// reutilise pour la creation, et son menu proposait Duplicate et Delete -
// qui, cote Delphi, visent la derniere entree ouverte.
closeMenu();
editing = false;
document.getElementById('kebab').hidden = true;
document.getElementById('pencil').hidden = true;
document.getElementById('dav').hidden = true;
@@ -1525,6 +1527,10 @@ function openMenu() {
/// Ce que le formulaire porte a cet instant, par nom de champ. Sert a le
/// rouvrir tel quel apres une action d'icone, qui passe par un enregistrement.
var editAgain = null;
/// Le formulaire occupe l'ecran du detail : 'view' reste donc 'detail', et
/// c'est ce drapeau qui dit qu'on y modifie - la fleche et la touche retour
/// s'en servent pour refermer le formulaire avant de quitter l'entree.
var editing = false;
function collectEditValues() {
var ins = document.querySelectorAll('#fields [data-ef]'), m = {}, i;
@@ -1558,13 +1564,12 @@ function openEditEntry() {
+ (r.m ? ' wrap' : '') + '">'
+ (r.e === 'folder' ? folderSelect(r.v) : r.m
? '<textarea class="field-in" data-ef="' + esc(r.e) + '" rows="5"'
+ ' autocorrect="off" spellcheck="false" style="' + FIELD_STYLE
+ ';height:auto;resize:vertical">' + esc(r.v) + '</textarea>'
+ ' enterkeyhint="enter" autocorrect="off" spellcheck="false"'
+ ' style="' + FIELD_STYLE + ';height:auto;resize:vertical"></textarea>'
: '<input class="field-in"' + (r.e === 'password' ? ' id="editpwd"' : '')
+ ' data-ef="' + esc(r.e) + '" type="text"'
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"'
+ ' spellcheck="false" style="' + FIELD_STYLE + '" value="'
+ esc(r.v) + '">')
+ ' spellcheck="false" style="' + FIELD_STYLE + '">')
+ (r.e === 'password' ? genButton('editpwd') : '')
+ '</div></div>';
}
@@ -1577,11 +1582,20 @@ function openEditEntry() {
+ '<button class="btn main wide" id="eSave" style="flex:1">Save</button>'
+ '</div>';
document.getElementById('fields').innerHTML = html;
// Les valeurs APRES le rendu, jamais en attribut : c'est ainsi que
// procedait l'editeur d'une ligne, qui acceptait la frappe.
var fill = document.querySelectorAll('#fields [data-ef]'), fi, fe;
for (fi = 0; fi < fill.length; fi++) {
fe = fill[fi].getAttribute('data-ef');
for (var fk = 0; fk < detailRows.length; fk++)
if (detailRows[fk].e === fe && fill[fi].tagName !== 'SELECT')
fill[fi].value = detailRows[fk].v;
}
document.getElementById('eCancel').addEventListener('click', function () {
renderDetail(lastDetail);
});
document.getElementById('eSave').addEventListener('click', saveEditEntry);
view = 'edit';
editing = true;
if (editAgain) {
var ins = document.querySelectorAll('#fields [data-ef]'), i, f;
for (i = 0; i < ins.length; i++) {
@@ -1590,7 +1604,9 @@ function openEditEntry() {
}
editAgain = null;
}
send('touch');
// MEME SORTIE QUE LA CREATION, qui elle accepte la frappe : c'est le seul
// appel qui differait a l'ouverture du formulaire.
send('state?view=detail');
}
/// UN SEUL ENVOI, ET SEULEMENT CE QUI A CHANGE : le reste du coffre n'a pas a
@@ -1969,6 +1985,7 @@ function goList() {
document.body.classList.remove('on-detail');
document.body.classList.add('on-list');
view = 'list';
editing = false;
// Les valeurs en clair partent avec la vue, pas seulement de l'ecran.
detailRows = [];
document.getElementById('fields').innerHTML = '';
@@ -1977,7 +1994,7 @@ function goList() {
// LA FLECHE REFERME D'ABORD LE FORMULAIRE. Elle ramenait a la liste, donc une
// modification en cours disparaissait sans qu'on ait vu l'entree.
document.getElementById('back').addEventListener('click', function () {
if (view === 'edit') { renderDetail(lastDetail); return; }
if (editing) { renderDetail(lastDetail); return; }
goList();
});
@@ -2227,7 +2244,7 @@ var PM = {
// Touche retour du telephone : le formulaire d'abord, la liste ensuite.
// Delphi ne connait que 'detail' - la page seule sait qu'elle edite.
back: function () {
if (view === 'edit') { renderDetail(lastDetail); return; }
if (editing) { renderDetail(lastDetail); return; }
if (view === 'detail') goList();
},
cancelEdit: function () { renderDetail(lastDetail); },