feat(apk): edition de l'entree entiere en un seul enregistrement, et icone choisie dans la galerie
Un crayon ouvre un formulaire pre-rempli : tous les champs modifiables a la
fois, un seul Save, donc UN commit au lieu d'un par champ ('setfields',
plusieurs PatchEntryField dans le meme CommitChange).
L'icone quitte le menu de l'entree pour ce formulaire : From site (recherche),
Image... (galerie, reduite a 128 px, provenance custom) et Remove.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -585,6 +585,7 @@
|
||||
<div class="head">
|
||||
<button class="btn ico-btn back-btn" id="back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-label="Back" role="img"><path d="M20 12H5M11 5l-7 7 7 7"/></svg></button>
|
||||
<h1 id="dtitle"></h1>
|
||||
<button class="btn ico-btn" id="pencil" aria-label="Edit entry"></button>
|
||||
<button class="btn ico-btn" id="kebab" aria-label="Entry menu"></button>
|
||||
</div>
|
||||
<div class="scroll"><div id="fields"></div></div>
|
||||
@@ -1067,6 +1068,7 @@ function renderDetail(d) {
|
||||
detailRows = d.rows || [];
|
||||
document.getElementById('dtitle').textContent = d.title || '';
|
||||
document.getElementById('kebab').hidden = false;
|
||||
document.getElementById('pencil').hidden = false;
|
||||
var html = '', i;
|
||||
if (d.totp)
|
||||
html += '<div class="field totp" id="totp"><div class="cap">2FA code</div>'
|
||||
@@ -1126,6 +1128,8 @@ document.getElementById('fields').addEventListener('click', function (ev) {
|
||||
send('touch');
|
||||
return;
|
||||
}
|
||||
var ia = t.getAttribute('data-iconact');
|
||||
if (ia !== null) { 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');
|
||||
@@ -1458,6 +1462,7 @@ function openNewEntry() {
|
||||
// qui, cote Delphi, visent la derniere entree ouverte.
|
||||
closeMenu();
|
||||
document.getElementById('kebab').hidden = true;
|
||||
document.getElementById('pencil').hidden = true;
|
||||
document.getElementById('fields').innerHTML =
|
||||
'<div class="form">'
|
||||
+ '<div class="field"><div class="cap">Kind</div><div class="line">'
|
||||
@@ -1565,13 +1570,83 @@ function closeMenu() {
|
||||
function openMenu() {
|
||||
var m = document.getElementById('menu');
|
||||
m.innerHTML = '<button data-hist>Previous passwords</button>'
|
||||
+ '<button data-icon="fetch">Fetch icon</button>'
|
||||
+ '<button data-icon="clear">Remove icon</button>'
|
||||
+ '<button data-dup>Duplicate entry</button>'
|
||||
+ '<button class="danger" data-del>Delete entry</button>';
|
||||
m.hidden = false;
|
||||
}
|
||||
|
||||
// MODIFIER L'ENTREE ENTIERE, PAS UN CHAMP A LA FOIS.
|
||||
//
|
||||
// Chaque ligne avait son crayon : ouvrir, taper, valider, recommencer - et
|
||||
// CHAQUE validation etait un enregistrement complet, donc un commit de plus
|
||||
// dans le depot. Ici un seul formulaire, un seul Save, un seul commit.
|
||||
//
|
||||
// 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.
|
||||
function openEditEntry() {
|
||||
if (!lastDetail) return;
|
||||
closeMenu();
|
||||
var html = '<div class="form">', i, r;
|
||||
for (i = 0; i < detailRows.length; i++) {
|
||||
r = detailRows[i];
|
||||
if (!r.e) continue;
|
||||
html += '<div class="field"><div class="cap">' + esc(r.c) + '</div><div class="line'
|
||||
+ (r.m ? ' wrap' : '') + '">'
|
||||
+ (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>'
|
||||
: '<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) + '">')
|
||||
+ (r.e === 'password' ? genButton('editpwd') : '')
|
||||
+ '</div></div>';
|
||||
}
|
||||
// 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 += '<div class="field"><div class="cap">Icon</div><div class="line">'
|
||||
+ '<button class="btn" data-iconact="fetch">From site</button>'
|
||||
+ '<button class="btn" data-iconact="pick">Image...</button>'
|
||||
+ '<button class="btn" data-iconact="clear">Remove</button>'
|
||||
+ '</div></div>'
|
||||
+ '</div>'
|
||||
+ '<div class="line" style="display:flex;gap:8px;margin-top:12px">'
|
||||
+ '<button class="btn wide" id="eCancel" style="flex:1">Cancel</button>'
|
||||
+ '<button class="btn main wide" id="eSave" style="flex:1">Save</button>'
|
||||
+ '</div>';
|
||||
document.getElementById('fields').innerHTML = html;
|
||||
document.getElementById('eCancel').addEventListener('click', function () {
|
||||
renderDetail(lastDetail);
|
||||
});
|
||||
document.getElementById('eSave').addEventListener('click', saveEditEntry);
|
||||
send('touch');
|
||||
}
|
||||
|
||||
/// UN SEUL ENVOI, ET SEULEMENT CE QUI A CHANGE : le reste du coffre n'a pas a
|
||||
/// etre reecrit parce qu'on a corrige une faute de frappe dans un nom.
|
||||
function saveEditEntry() {
|
||||
var ins = document.querySelectorAll('#fields [data-ef]'), q = [], n = 0, i, el, f, v, k;
|
||||
for (i = 0; i < ins.length; i++) {
|
||||
el = ins[i];
|
||||
f = el.getAttribute('data-ef');
|
||||
v = el.value;
|
||||
for (k = 0; k < detailRows.length; k++)
|
||||
if (detailRows[k].e === f && detailRows[k].v === v) { f = ''; break; }
|
||||
if (!f) continue;
|
||||
q.push('f' + n + '=' + encodeURIComponent(f) + '&v' + n + '=' + encodeURIComponent(v));
|
||||
n++;
|
||||
}
|
||||
if (!n) { renderDetail(lastDetail); return; }
|
||||
document.getElementById('eSave').disabled = true;
|
||||
send('setfields?' + q.join('&'));
|
||||
}
|
||||
|
||||
document.getElementById('pencil').innerHTML = ico('edit', 'Edit entry');
|
||||
document.getElementById('pencil').addEventListener('click', openEditEntry);
|
||||
document.getElementById('kebab').innerHTML = ico('dots', 'Entry menu');
|
||||
document.getElementById('kebab').addEventListener('click', function (ev) {
|
||||
ev.stopPropagation();
|
||||
|
||||
Reference in New Issue
Block a user