fix(android): saving now answers, and the editor hides what you type
Two defects, both reported from the device. Nothing came back after Save. AdoptVault rebuilds the LIST, not the detail, so the row stayed in edit mode: the input remained on screen and nothing said whether the write had gone through. The detail is now redrawn from the vault in both cases - after a success it carries the new value, after a failure the old one, which reads without needing a sentence. It is found by UUID rather than by index: the vault has just been replaced by the server's, and nothing guarantees the same entry sits at the same rank. The button also stayed inert-looking for the several seconds a save takes, so it now says "Saving..." and disables itself while the work runs. And the typed password showed in clear. My reasoning was that you cannot verify it anywhere else - but that argues for a reveal button, not for leaving it exposed the whole time. It is masked, with Show next to it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -533,10 +533,28 @@ document.getElementById('fields').addEventListener('click', function (ev) {
|
|||||||
|
|
||||||
var edit = t.getAttribute('data-edit');
|
var edit = t.getAttribute('data-edit');
|
||||||
if (edit !== null) { openEditor(edit); return; }
|
if (edit !== null) { openEditor(edit); return; }
|
||||||
|
if (t.getAttribute('data-editshow') !== null) {
|
||||||
|
// Masque par defaut, revelable a la demande : on tape un mot de passe
|
||||||
|
// qu'on ne peut relire nulle part ailleurs, mais il n'a pas a rester
|
||||||
|
// expose a l'ecran pendant qu'on cherche le bouton.
|
||||||
|
var iv = document.getElementById('editval');
|
||||||
|
var hid = iv.type === 'password';
|
||||||
|
iv.type = hid ? 'text' : 'password';
|
||||||
|
t.textContent = hid ? 'Hide' : 'Show';
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (t.getAttribute('data-editcancel') !== null) { renderDetail(lastDetail); return; }
|
if (t.getAttribute('data-editcancel') !== null) { renderDetail(lastDetail); return; }
|
||||||
if (t.getAttribute('data-editsave') !== null) {
|
if (t.getAttribute('data-editsave') !== null) {
|
||||||
var input = document.getElementById('editval');
|
var input = document.getElementById('editval');
|
||||||
if (!input || !input.value) return; // vide : on n'ecrase pas par megarde
|
if (!input || !input.value) return; // vide : on n'ecrase pas par megarde
|
||||||
|
// DIRE QUE CA TRAVAILLE. L'enregistrement tire, dechiffre, rechiffre et
|
||||||
|
// publie : plusieurs secondes pendant lesquelles rien ne bougeait, et le
|
||||||
|
// bouton semblait n'avoir pas pris l'appui.
|
||||||
|
t.textContent = 'Saving...';
|
||||||
|
t.disabled = true;
|
||||||
|
var cancel = document.querySelector('[data-editcancel]');
|
||||||
|
if (cancel) cancel.disabled = true;
|
||||||
|
input.disabled = true;
|
||||||
send('setpwd?v=' + encodeURIComponent(input.value));
|
send('setpwd?v=' + encodeURIComponent(input.value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -554,9 +572,10 @@ function openEditor(k) {
|
|||||||
if (!row) return;
|
if (!row) return;
|
||||||
var line = row.parentNode;
|
var line = row.parentNode;
|
||||||
line.innerHTML =
|
line.innerHTML =
|
||||||
'<input class="field-in" id="editval" type="text" autocomplete="off"'
|
'<input class="field-in" id="editval" type="password" autocomplete="off"'
|
||||||
+ ' autocorrect="off" autocapitalize="none" spellcheck="false"'
|
+ ' autocorrect="off" autocapitalize="none" spellcheck="false"'
|
||||||
+ ' style="margin:0">'
|
+ ' style="margin:0">'
|
||||||
|
+ '<button class="btn" data-editshow>Show</button>'
|
||||||
+ '<button class="btn" data-editcancel>Cancel</button>'
|
+ '<button class="btn" data-editcancel>Cancel</button>'
|
||||||
+ '<button class="btn main" data-editsave>Save</button>';
|
+ '<button class="btn main" data-editsave>Save</button>';
|
||||||
var input = document.getElementById('editval');
|
var input = document.getElementById('editval');
|
||||||
|
|||||||
+27
@@ -192,6 +192,7 @@ type
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
procedure OpenEntry(AVaultIndex: Integer);
|
procedure OpenEntry(AVaultIndex: Integer);
|
||||||
procedure SaveEntryPassword(const ANewValue: string);
|
procedure SaveEntryPassword(const ANewValue: string);
|
||||||
|
procedure ReopenEntryByUuid(const AUuid: string);
|
||||||
procedure OnClipTimer(Sender: TObject);
|
procedure OnClipTimer(Sender: TObject);
|
||||||
procedure OnDeadline(Sender: TObject);
|
procedure OnDeadline(Sender: TObject);
|
||||||
procedure OnHardwareBack(Sender: TObject; var Key: Word;
|
procedure OnHardwareBack(Sender: TObject; var Key: Word;
|
||||||
@@ -522,6 +523,25 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Redessine le detail d'une entree retrouvee par son uuid.
|
||||||
|
///
|
||||||
|
/// PAR UUID ET NON PAR INDICE : le coffre vient d'etre remplace par celui du
|
||||||
|
/// serveur, et rien ne garantit que la meme entree occupe le meme rang - un
|
||||||
|
/// tri se fait sur le nom affiche, qu'une autre machine a pu changer.
|
||||||
|
procedure TForm8.ReopenEntryByUuid(const AUuid: string);
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
begin
|
||||||
|
for I := 0 to FVault.Count - 1 do
|
||||||
|
if FVault.Entry(I).Uuid = AUuid then
|
||||||
|
begin
|
||||||
|
OpenEntry(I);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
// Disparue du distant entre-temps : la liste est deja a jour, on y reste.
|
||||||
|
WebCall('PM.back()');
|
||||||
|
end;
|
||||||
|
|
||||||
/// Change le mot de passe de l'entree ouverte, et publie.
|
/// Change le mot de passe de l'entree ouverte, et publie.
|
||||||
///
|
///
|
||||||
/// TIRER, MODIFIER, RECHIFFRER, PUBLIER - dans cet ordre, et sur l'instantane
|
/// TIRER, MODIFIER, RECHIFFRER, PUBLIER - dans cet ordre, et sur l'instantane
|
||||||
@@ -632,6 +652,13 @@ begin
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
WebCall('PM.toast(' + JsArg('Not saved - ' + LErr) + ')');
|
WebCall('PM.toast(' + JsArg('Not saved - ' + LErr) + ')');
|
||||||
|
// LE DETAIL DOIT REVENIR, dans les deux cas. AdoptVault reconstruit
|
||||||
|
// la LISTE ; la ligne en cours d'edition restait telle quelle, donc
|
||||||
|
// le champ de saisie demeurait a l'ecran et rien ne disait si
|
||||||
|
// l'enregistrement avait abouti. On la redessine depuis le coffre :
|
||||||
|
// apres un succes elle porte la nouvelle valeur, apres un echec
|
||||||
|
// l'ancienne - ce qui se lit sans commentaire.
|
||||||
|
ReopenEntryByUuid(LUuid);
|
||||||
end);
|
end);
|
||||||
finally
|
finally
|
||||||
LClient.Free;
|
LClient.Free;
|
||||||
|
|||||||
Reference in New Issue
Block a user