From 29f737b831bacc2c772deaa171553ae4109fd9dc Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:18:41 +0100 Subject: [PATCH] ui(apk): icone et nom en tete du formulaire, arrondis unifies, retour au formulaire apres une action d'icone L'icone se commet comme un champ : Delphi rouvrait l'entree et la vue de lecture reprenait la place au milieu d'une modification. Le formulaire est maintenant rouvert avec ce qui y etait deja tape. Co-Authored-By: Claude Opus 5 --- android-client/PMA.WebUI.pas | 3 ++ android-client/web/app.html | 63 ++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/android-client/PMA.WebUI.pas b/android-client/PMA.WebUI.pas index 2bee99a..d059699 100644 --- a/android-client/PMA.WebUI.pas +++ b/android-client/PMA.WebUI.pas @@ -257,6 +257,9 @@ begin LRoot := TJSONObject.Create; try LRoot.AddPair('title', AEntry.Display); + // L'icone du moment, pour que le formulaire montre ce qu'il va changer. + LRoot.AddPair('icon', AEntry.IconB64); + LRoot.AddPair('initial', Initial(AEntry.Display)); LRoot.AddPair('totp', TJSONBool.Create(AEntry.Totp <> '')); LArr := TJSONArray.Create; LRoot.AddPair('rows', LArr); diff --git a/android-client/web/app.html b/android-client/web/app.html index bfd8405..25e2db6 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -98,7 +98,10 @@ .search { flex: 1; position: relative; } .search input { width: 100%; height: 46px; padding: 0 38px 0 40px; - border: 0; border-radius: var(--radius-s); + /* MEME ARRONDI QUE LES PASTILLES DE DOSSIER. Trois rayons differents se + voyaient d'un coup d'oeil sur le meme ecran : la recherche, les + pastilles, les boutons. Les deux premiers se touchent presque. */ + border: 0; border-radius: 999px; background: rgba(255,255,255,.10); color: var(--text); font-size: 15px; outline: none; } @@ -153,8 +156,9 @@ text-overflow: ellipsis; white-space: nowrap; } .txt span { display: block; color: var(--muted); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + /* Les boutons prennent le meme arrondi que la recherche et les pastilles. */ .btn { - flex: 0 0 auto; border: 0; border-radius: var(--radius-s); + flex: 0 0 auto; border: 0; border-radius: 999px; background: var(--raised); color: var(--text); padding: 11px 13px; font-size: 13px; font-family: inherit; } @@ -1100,6 +1104,9 @@ function renderDetail(d) { document.body.classList.add('on-detail'); view = 'detail'; send('state?view=detail'); + // Retour au formulaire apres une action d'icone : elle passe par un + // enregistrement, donc par ce rendu-ci. + if (editAgain) openEditEntry(); } document.getElementById('fields').addEventListener('click', function (ev) { @@ -1127,7 +1134,15 @@ document.getElementById('fields').addEventListener('click', function (ev) { return; } var ia = t.getAttribute('data-iconact'); - if (ia !== null) { send('icon?a=' + ia); return; } + if (ia !== null) { + // L'ICONE SE COMMET COMME LE RESTE, donc Delphi rouvre l'entree et la vue + // de lecture reprenait la place - on se retrouvait dehors sans avoir fini. + // Ce drapeau dit a renderDetail de rendre la main au formulaire, avec ce + // qui y etait deja tape. + editAgain = collectEditValues(); + send('icon?a=' + ia); + return; + } var save = t.getAttribute('data-save'); if (save !== null) { send('savefile?k=' + save); return; } var copy = t.getAttribute('data-copy'); @@ -1491,10 +1506,35 @@ function openMenu() { // La page ne connait toujours pas le schema : elle rend une ligne par champ // que Delphi a marque modifiable ('e' porte son nom), dans l'ordre qu'il a // choisi. Ajouter un champ modifiable cote Delphi suffit a le voir ici. +/// 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; + +function collectEditValues() { + var ins = document.querySelectorAll('#fields [data-ef]'), m = {}, i; + for (i = 0; i < ins.length; i++) + m[ins[i].getAttribute('data-ef')] = ins[i].value; + return m; +} + function openEditEntry() { if (!lastDetail) return; closeMenu(); - var html = '
', i, r; + // L'ICONE ET LE NOM EN TETE : on voit ce qu'on modifie, et surtout ce que + // les trois boutons d'en dessous vont remplacer. + var d = lastDetail; + var html = '
' + + '
' + + '
' + + (d.icon ? '' : esc(d.initial || '')) + + '
' + + '
' + + esc(d.title || '') + '
' + + '
' + + '' + + '' + + '' + + '
', i, r; for (i = 0; i < detailRows.length; i++) { r = detailRows[i]; if (!r.e) continue; @@ -1515,12 +1555,7 @@ function openEditEntry() { // L'ICONE SE CHANGE OU SE CHANGENT LES CHAMPS. Elle vivait dans le menu de // l'entree, a cote de Supprimer : deux actions de nature opposee au meme // endroit, et rien qui montre l'icone du moment. - html += '
Icon
' - + '' - + '' - + '' - + '
' - + '
' + html += '
' + '
' + '' + '' @@ -1530,6 +1565,14 @@ function openEditEntry() { renderDetail(lastDetail); }); document.getElementById('eSave').addEventListener('click', saveEditEntry); + if (editAgain) { + var ins = document.querySelectorAll('#fields [data-ef]'), i, f; + for (i = 0; i < ins.length; i++) { + f = ins[i].getAttribute('data-ef'); + if (editAgain[f] !== undefined) ins[i].value = editAgain[f]; + } + editAgain = null; + } send('touch'); }