feat(apk): afficher/masquer les secrets, scanner le QR 2FA, et toast() reparé

- Mot de passe et secret 2FA naissent masques dans la creation et l'edition,
  avec un oeil pour les reveler.
- Un bouton QR dans le champ 2FA ouvre la camera du scan des reglages ; le lien
  otpauth:// lu part a la page, qui n'en garde que le secret. Le journal ne note
  que le fait.
- toast() designait l'element <div id="toast"> (chaque id est une variable
  globale) : sept appels de la page levaient "toast is not a function" et leur
  message ne s'affichait jamais. Une vraie fonction globale les repare tous.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-09-28 11:20:31 +01:00
parent 22c418f933
commit 3acf78b1ca
2 changed files with 85 additions and 9 deletions
+21 -3
View File
@@ -386,6 +386,9 @@ type
// Scanner du QR affiche par le poste (ZXing.Delphi, Apache 2.0).
var
FScanning, FScanBusy: Boolean;
/// Le scan en cours cherche un QR de 2FA (otpauth://) et non le lien des
/// reglages. Pose par 'scanqr?for=totp', lu au decodage.
FScanTotp: Boolean;
/// L'action de la galerie survit a l'appel : le selecteur d'Android rend
/// la main tout de suite et rappelle plus tard.
FPickIcon: TTakePhotoFromLibraryAction;
@@ -2062,7 +2065,10 @@ begin
// SCANNER LE QR DU POSTE depuis l'app : le scanner du systeme envoyait
// le lien a une recherche web ou demandait avec quoi l'ouvrir.
else if LAction = 'scanqr' then
StartScan
begin
FScanTotp := Param('for') = 'totp';
StartScan;
end
else if LAction = 'pinclear' then
ClearUnlockCode(TNetEncoding.URL.Decode(Param('c')))
@@ -3788,7 +3794,10 @@ begin
except
// Pas d'autofocus continu : l'image restera nette a bonne distance.
end;
FScanLbl.Text := 'Point the camera at the QR shown on the PC';
if FScanTotp then
FScanLbl.Text := 'Point the camera at the 2FA QR code'
else
FScanLbl.Text := 'Point the camera at the QR shown on the PC';
FCam.Active := True;
FScanWatch.Enabled := True;
Log('QR scan started');
@@ -3875,7 +3884,16 @@ begin
// CHERCHE, NE COMPARE PAS LE DEBUT : le texte decode est arrive
// avec un caractere invisible en tete (104 lus pour 103 emis),
// et le lien etait ignore alors qu'il etait lu.
if Pos('pmserver://sync?', LText) > 0 then
// 2FA : le lien otpauth:// porte le SECRET. Il part a la page,
// qui le range dans le champ ; le journal n'en dit que le fait.
if FScanTotp and (Pos('otpauth://', LowerCase(LText)) > 0) then
begin
StopScan;
Log('QR scan: 2FA code read');
WebCall('PM.totpFromQr(' + JsArg(Trim(Copy(LText,
Pos('otpauth://', LowerCase(LText)), MaxInt))) + ')');
end
else if (not FScanTotp) and (Pos('pmserver://sync?', LText) > 0) then
begin
StopScan;
ApplySyncLink(Trim(Copy(LText, Pos('pmserver://sync?', LText), MaxInt)));