feat(android): an entry can be deleted from the phone
Both, or nothing: the row leaves the snapshot AND a tombstone takes its place. Removing the row alone does not delete - the desktop still holds its own copy, and the next pull would bring it back as an entry we never had. The time matters too: the desktop's arbitration keeps an entry edited AFTER the deletion rather than killing it a second time. No trash on the phone, deliberately. The desktop's is a `deleted` flag that does not travel in sync, so a deletion stopping there would propagate nowhere. Hence a button at the very bottom, in two taps, that disarms itself after four seconds - a button left armed gets touched by accident much later, and this is the one action with no way back. The confirmation is in the page because the engine cannot offer one: a JavaScript prompt needs a WebChromeClient FMX does not provide. Not exercised on the device: it would have destroyed a real entry.
This commit is contained in:
@@ -154,6 +154,9 @@
|
||||
.btn:active { opacity: .62; }
|
||||
.btn.wide { padding: 13px 18px; font-size: 15px; }
|
||||
.btn.main { background: var(--accent); }
|
||||
/* Rouge sourd : assez pour qu'on ne le confonde pas avec Copy, pas assez
|
||||
pour attirer l'oeil sur la seule action irreversible de l'ecran. */
|
||||
.btn.danger { background: rgba(220, 80, 80, .30); }
|
||||
|
||||
.empty { text-align: center; color: var(--muted); padding: 48px 16px; }
|
||||
|
||||
@@ -593,6 +596,14 @@ function renderDetail(d) {
|
||||
+ (r.e ? '<button class="btn" data-edit="' + i + '">Edit</button>' : '')
|
||||
+ '</div></div>';
|
||||
}
|
||||
// SUPPRIMER, tout en bas et en deux temps. Sans retour possible depuis le
|
||||
// telephone - il n'y a pas de corbeille ici - donc ni en tete d'ecran ni a
|
||||
// portee d'un appui distrait. Le premier appui ne fait qu'armer ; c'est la
|
||||
// confirmation, faute de pouvoir en demander une au moteur (une invite
|
||||
// JavaScript exige un WebChromeClient que FMX ne fournit pas).
|
||||
html += '<div class="field"><div class="line">'
|
||||
+ '<button class="btn danger" id="del" style="flex:1">Delete entry'
|
||||
+ '</button></div></div>';
|
||||
document.getElementById('fields').innerHTML = html;
|
||||
document.body.classList.add('on-detail');
|
||||
view = 'detail';
|
||||
@@ -601,6 +612,24 @@ function renderDetail(d) {
|
||||
|
||||
document.getElementById('fields').addEventListener('click', function (ev) {
|
||||
var t = ev.target, k = t.getAttribute('data-show');
|
||||
if (t.id === 'del') {
|
||||
if (t.getAttribute('data-armed') === null) {
|
||||
t.setAttribute('data-armed', '1');
|
||||
t.textContent = 'Really delete - tap again';
|
||||
// Desarme tout seul : un bouton reste arme indefiniment se fait toucher
|
||||
// par megarde bien plus tard, et la suppression est sans retour.
|
||||
setTimeout(function () {
|
||||
if (!t.parentNode) return;
|
||||
t.removeAttribute('data-armed');
|
||||
t.textContent = 'Delete entry';
|
||||
}, 4000);
|
||||
return;
|
||||
}
|
||||
t.disabled = true;
|
||||
t.textContent = 'Deleting...';
|
||||
send('delentry');
|
||||
return;
|
||||
}
|
||||
if (k !== null) {
|
||||
var cell = document.querySelector('[data-v="' + k + '"]');
|
||||
var hidden = cell.classList.contains('mask');
|
||||
|
||||
Reference in New Issue
Block a user