i18n(android): the interface speaks English, like the desktop app
It was in French because the conversation is, and I never asked. The desktop app the client mirrors says Add field, Attach file, Show previous versions - someone moving between the two would notice the seam. Every visible string moved: buttons, statuses, detail row captions, log lines and the biometric prompt, plus the messages the modules surface through LastStoreError and LastBiometricError. Code comments stay in French. They address the author, not the user, and that is already the language of CLAUDE.md and much of the repo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+73
-73
@@ -1,4 +1,4 @@
|
||||
unit mainApk;
|
||||
unit mainApk;
|
||||
{
|
||||
Client Android en LECTURE SEULE : deverrouiller, chercher, copier.
|
||||
|
||||
@@ -218,7 +218,7 @@ var
|
||||
LEvents: IFMXApplicationEventService;
|
||||
begin
|
||||
inherited;
|
||||
Caption := 'Coffre';
|
||||
Caption := 'Vault';
|
||||
// Le fond de la forme, et non celui du style : tout le reste est peint
|
||||
// par-dessus, et un gris herite se verrait entre les blocs.
|
||||
Fill.Kind := TBrushKind.Solid;
|
||||
@@ -328,8 +328,8 @@ begin
|
||||
FLaySettings.Align := TAlignLayout.Top;
|
||||
FLaySettings.Height := 116;
|
||||
FLaySettings.Visible := False;
|
||||
FToken := TopEdit(FLaySettings, 'jeton Bearer', FIRSTRUN_TOKEN);
|
||||
FUrl := TopEdit(FLaySettings, 'URL de l''endpoint', FIRSTRUN_URL);
|
||||
FToken := TopEdit(FLaySettings, 'bearer token', FIRSTRUN_TOKEN);
|
||||
FUrl := TopEdit(FLaySettings, 'endpoint URL', FIRSTRUN_URL);
|
||||
FToken.Margins.Rect := RectF(16, 8, 16, 0);
|
||||
FUrl.Margins.Rect := RectF(16, 8, 16, 0);
|
||||
// Ce que l'appareil a retenu l'emporte sur les valeurs de premier lancement.
|
||||
@@ -347,20 +347,20 @@ begin
|
||||
LRow.Height := 48;
|
||||
LRow.Margins.Rect := RectF(16, 8, 16, 0);
|
||||
|
||||
FBtnLog := FlatButton(LRow, 'Journal', OnToggleLog);
|
||||
FBtnLog := FlatButton(LRow, 'Log', OnToggleLog);
|
||||
FBtnLog.Align := TAlignLayout.Right;
|
||||
FBtnLog.Width := 120;
|
||||
FBtnLog.Margins.Left := 8;
|
||||
|
||||
FBtnSettings := FlatButton(LRow, 'Reglages du serveur', OnToggleSettings);
|
||||
FBtnSettings := FlatButton(LRow, 'Server settings', OnToggleSettings);
|
||||
FBtnSettings.Align := TAlignLayout.Client;
|
||||
|
||||
FBtnSync := TopButton(FLayUnlock, 'Synchroniser', DoSync);
|
||||
FBtnSync := TopButton(FLayUnlock, 'Sync', DoSync);
|
||||
// Accentue : c'est l'action attendue quand aucun coffre n'est encore la.
|
||||
FBtnOpen := TopButton(FLayUnlock, 'Ouvrir le coffre', DoOpenLocal, 52, True);
|
||||
FBtnOpen := TopButton(FLayUnlock, 'Open vault', DoOpenLocal, 52, True);
|
||||
|
||||
// Pre-rempli depuis le fichier local, jamais depuis ce fichier-ci.
|
||||
FPwd := TopEdit(FLayUnlock, 'mot de passe de sync', TEST_PWD, True);
|
||||
FPwd := TopEdit(FLayUnlock, 'sync password', TEST_PWD, True);
|
||||
FPwd.Margins.Rect := RectF(16, 16, 16, 0);
|
||||
|
||||
FStatus := TLabel.Create(Self);
|
||||
@@ -386,7 +386,7 @@ begin
|
||||
LBar.Align := TAlignLayout.Bottom;
|
||||
LBar.Height := 52;
|
||||
|
||||
LBtnLock := FlatButton(LBar, 'Verrouiller', OnBackTap);
|
||||
LBtnLock := FlatButton(LBar, 'Lock', OnBackTap);
|
||||
LBtnLock.Align := TAlignLayout.Left;
|
||||
LBtnLock.Margins.Rect := RectF(16, 4, 0, 8);
|
||||
LBtnLock.Width := 140;
|
||||
@@ -422,7 +422,7 @@ begin
|
||||
//
|
||||
// Bouton peint et non TComboBox : le combo etait l'un des deux derniers
|
||||
// controles a porter encore le style, et il jurait avec le reste.
|
||||
FBtnFolder := FlatButton(LTop, 'Tous les dossiers', OnFolderTap);
|
||||
FBtnFolder := FlatButton(LTop, 'All folders', OnFolderTap);
|
||||
FBtnFolder.Align := TAlignLayout.Right;
|
||||
FBtnFolder.Width := 170;
|
||||
FBtnFolder.Margins.Left := 8;
|
||||
@@ -445,7 +445,7 @@ begin
|
||||
FSearchHint.Margins.Left := 10;
|
||||
FSearchHint.HitTest := False;
|
||||
FSearchHint.Opacity := 0.45;
|
||||
FSearchHint.Text := 'Rechercher';
|
||||
FSearchHint.Text := 'Search';
|
||||
end;
|
||||
|
||||
/// Intitule discret au-dessus d'une valeur. Meme forme pour toutes les
|
||||
@@ -504,7 +504,7 @@ begin
|
||||
FLayDetail.Align := TAlignLayout.Client;
|
||||
FLayDetail.Visible := False;
|
||||
|
||||
LBtnBack := FlatButton(FLayDetail, 'Retour', OnBackTap);
|
||||
LBtnBack := FlatButton(FLayDetail, 'Back', OnBackTap);
|
||||
LBtnBack.Align := TAlignLayout.Bottom;
|
||||
LBtnBack.Height := 52;
|
||||
LBtnBack.Margins.Rect := RectF(16, 8, 16, 8);
|
||||
@@ -547,15 +547,15 @@ begin
|
||||
if HasVault then
|
||||
begin
|
||||
if VaultNeedsAuth then
|
||||
Status('Coffre present sur cet appareil - protege')
|
||||
Status('Vault on this device - protected')
|
||||
else
|
||||
Status('Coffre present sur cet appareil');
|
||||
SetButtonText(FBtnSync, 'Synchroniser');
|
||||
Status('Vault on this device');
|
||||
SetButtonText(FBtnSync, 'Sync');
|
||||
end
|
||||
else
|
||||
begin
|
||||
Status('Aucun coffre local - premier telechargement');
|
||||
SetButtonText(FBtnSync, 'Telecharger le coffre');
|
||||
Status('No local vault - first download');
|
||||
SetButtonText(FBtnSync, 'Download vault');
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -635,10 +635,10 @@ begin
|
||||
|
||||
// Le corps d'une note est stocke dans le champ mot de passe : meme donnee,
|
||||
// autre intitule, et pas de raison de la masquer comme un secret.
|
||||
if FCurrent.IsNote then LPwdCaption := 'Contenu' else LPwdCaption := 'Mot de passe';
|
||||
if FCurrent.IsNote then LPwdCaption := 'Content' else LPwdCaption := 'Password';
|
||||
|
||||
Add('Site', FCurrent.Site, False);
|
||||
Add('Identifiant', FCurrent.Username, False);
|
||||
Add('Username', FCurrent.Username, False);
|
||||
Add(LPwdCaption, FCurrent.Password, not FCurrent.IsNote);
|
||||
for I := 0 to High(FCurrent.Fields) do
|
||||
Add(FCurrent.Fields[I].Caption, FCurrent.Fields[I].Value,
|
||||
@@ -658,16 +658,16 @@ begin
|
||||
// rendu bidirectionnel de FMX en fait n'importe quoi. Separes, chacun se
|
||||
// lit dans son sens.
|
||||
for I := 0 to High(FCurrent.Attachments) do
|
||||
Add('Piece jointe - ' + HumanSize(FCurrent.Attachments[I].SizeBytes),
|
||||
Add('Attachment - ' + HumanSize(FCurrent.Attachments[I].SizeBytes),
|
||||
FCurrent.Attachments[I].FileName, False);
|
||||
|
||||
Add('Dossier / etiquettes', LMeta, False);
|
||||
Add('Folder / tags', LMeta, False);
|
||||
// Le sous-type n'existe que pour les modeles (carte, cle SSH, serveur...) ;
|
||||
// Add ignore une valeur vide, donc rien a tester ici.
|
||||
Add('Type', FCurrent.Template, False);
|
||||
// Horodatage tel quel : c'est de l'ISO 8601 UTC, lisible, et le reformater
|
||||
// demanderait de decider d'un fuseau alors qu'il n'y a rien a arbitrer.
|
||||
Add('Modifie le', FCurrent.UpdatedAt, False);
|
||||
Add('Updated', FCurrent.UpdatedAt, False);
|
||||
|
||||
SetLength(FRowValues, Length(FRows));
|
||||
SetLength(FRowShown, Length(FRows));
|
||||
@@ -678,12 +678,12 @@ begin
|
||||
LOrder := 0;
|
||||
if FCurrent.Totp <> '' then
|
||||
begin
|
||||
LRow := MakeRow(FDetBody, 'Code 2FA', LOrder, FTotpValue);
|
||||
LRow := MakeRow(FDetBody, '2FA code', LOrder, FTotpValue);
|
||||
Inc(LOrder);
|
||||
SetLength(FRowCtls, Length(FRowCtls) + 1);
|
||||
FRowCtls[High(FRowCtls)] := LRow;
|
||||
FTotpValue.TextSettings.Font.Size := 26;
|
||||
AddRowButton(LRow, 'Copier', -1, OnCopyTap);
|
||||
AddRowButton(LRow, 'Copy', -1, OnCopyTap);
|
||||
OnTotpTick(nil); // pas d'attente d'une seconde a l'ouverture
|
||||
FTotpTimer.Enabled := True;
|
||||
end;
|
||||
@@ -698,11 +698,11 @@ begin
|
||||
if FRows[I].Secret then
|
||||
begin
|
||||
LValue.Text := MASK;
|
||||
AddRowButton(LRow, 'Afficher', I, OnRevealTap);
|
||||
AddRowButton(LRow, 'Show', I, OnRevealTap);
|
||||
end
|
||||
else
|
||||
LValue.Text := FRows[I].Value;
|
||||
AddRowButton(LRow, 'Copier', I, OnCopyTap);
|
||||
AddRowButton(LRow, 'Copy', I, OnCopyTap);
|
||||
end;
|
||||
// La derniere ligne affichee touche sinon le bord du defilement, ce qui la
|
||||
// fait passer pour tronquee alors qu'elle est juste collee.
|
||||
@@ -728,7 +728,7 @@ begin
|
||||
if FTotpCode = '' then
|
||||
begin
|
||||
// Un secret illisible ne doit pas passer pour un code : le dire.
|
||||
FTotpValue.Text := 'secret illisible';
|
||||
FTotpValue.Text := 'unreadable secret';
|
||||
FTotpTimer.Enabled := False;
|
||||
Exit;
|
||||
end;
|
||||
@@ -810,8 +810,8 @@ end;
|
||||
procedure TForm8.AdoptVault(const APlainJson: string);
|
||||
begin
|
||||
FVault.LoadFromJson(APlainJson);
|
||||
Log(' ' + FVault.LiveCount.ToString + ' entrees, ' +
|
||||
FVault.TrashCount.ToString + ' en corbeille');
|
||||
Log(' ' + FVault.LiveCount.ToString + ' entries, ' +
|
||||
FVault.TrashCount.ToString + ' in trash');
|
||||
RebuildIcons;
|
||||
PopulateFolders;
|
||||
Touch;
|
||||
@@ -845,7 +845,7 @@ begin
|
||||
on E: Exception do
|
||||
begin
|
||||
// Un coffre local illisible se remplace, il ne se repare pas.
|
||||
Log('Coffre local corrompu : ' + E.Message);
|
||||
Log('Local vault corrupt: ' + E.Message);
|
||||
ClearVault;
|
||||
ShowUnlock;
|
||||
end;
|
||||
@@ -856,8 +856,8 @@ begin
|
||||
// ShowUnlock AVANT le message : il repositionne le statut selon ce que
|
||||
// l'appareil detient, et ecraserait donc l'explication.
|
||||
ShowUnlock;
|
||||
Log('Coffre local illisible : ' + LastStoreError);
|
||||
Status('Coffre local illisible - voir le journal');
|
||||
Log('Local vault unreadable: ' + LastStoreError);
|
||||
Status('Local vault unreadable - see log');
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -877,13 +877,13 @@ begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if not AAuto then Status('Authentification...');
|
||||
AuthenticateThen('Acceder au coffre',
|
||||
if not AAuto then Status('Authenticating...');
|
||||
AuthenticateThen('Unlock the vault',
|
||||
procedure(AOutcome: TBioOutcome)
|
||||
begin
|
||||
case AOutcome of
|
||||
boOK: OpenLocalNow;
|
||||
boCancelled: Status('Annule');
|
||||
boCancelled: Status('Cancelled');
|
||||
boUnavailable:
|
||||
// Reponse nette du systeme : plus rien pour authentifier sur cet
|
||||
// appareil, donc la cle est perdue et le cache avec elle.
|
||||
@@ -895,13 +895,13 @@ begin
|
||||
// masquerait la vraie cause. L'utilisateur tranche en reessayant.
|
||||
if AAuto then
|
||||
begin
|
||||
Log('Authentification indisponible au lancement - cache conserve');
|
||||
Log('Authentication unavailable at launch - cache kept');
|
||||
Log(' ' + LastBiometricError);
|
||||
Status('Authentification indisponible - reessayer');
|
||||
Status('Authentication unavailable - try again');
|
||||
end
|
||||
else
|
||||
begin
|
||||
Log('Plus aucune protection sur l''appareil - cache efface');
|
||||
Log('No protection left on this device - cache cleared');
|
||||
Log(' ' + LastBiometricError);
|
||||
ClearVault;
|
||||
ShowUnlock;
|
||||
@@ -909,8 +909,8 @@ begin
|
||||
else
|
||||
// boFailed : la couche Java a leve quelque chose. Cela ne dit rien de
|
||||
// l'appareil, donc on ne touche a rien - on rapporte.
|
||||
Log('Echec de l''authentification : ' + LastBiometricError);
|
||||
Status('Echec de l''authentification');
|
||||
Log('Authentication failed: ' + LastBiometricError);
|
||||
Status('Authentication failed');
|
||||
end;
|
||||
end);
|
||||
end;
|
||||
@@ -930,7 +930,7 @@ begin
|
||||
if LPwd = '' then LPwd := FSyncPwd;
|
||||
if LPwd = '' then
|
||||
begin
|
||||
Status('Mot de passe de sync requis');
|
||||
Status('Sync password required');
|
||||
Exit;
|
||||
end;
|
||||
FLog.Lines.Clear;
|
||||
@@ -942,16 +942,16 @@ begin
|
||||
// cet appareil - c'est lui qui exprime le choix de l'utilisateur.
|
||||
if VaultNeedsAuth and (FVault.Count = 0) then
|
||||
begin
|
||||
Status('Authentification...');
|
||||
AuthenticateThen('Acceder au coffre',
|
||||
Status('Authenticating...');
|
||||
AuthenticateThen('Unlock the vault',
|
||||
procedure(AOutcome: TBioOutcome)
|
||||
begin
|
||||
if AOutcome = boOK then
|
||||
FetchAndDecrypt(LUrl, LTok, LPwd)
|
||||
else
|
||||
begin
|
||||
Log('Synchronisation refusee : ' + LastBiometricError);
|
||||
Status('Authentification requise');
|
||||
Log('Sync refused: ' + LastBiometricError);
|
||||
Status('Authentication required');
|
||||
end;
|
||||
end);
|
||||
Exit;
|
||||
@@ -966,7 +966,7 @@ var
|
||||
LCanAuth: Boolean;
|
||||
begin
|
||||
SetBusy(True);
|
||||
if not ASilent then Status('Telechargement...');
|
||||
if not ASilent then Status('Downloading...');
|
||||
// NE JAMAIS FERMER LE CACHE DERRIERE UNE PORTE QU'ON NE SAIT PAS OUVRIR.
|
||||
// Demander une cle protegee par authentification alors que l'invite ne peut
|
||||
// pas s'afficher (permission absente, aucune protection configuree) produit
|
||||
@@ -997,7 +997,7 @@ begin
|
||||
LSw := TStopwatch.StartNew;
|
||||
LRes := LClient.Fetch(FETag);
|
||||
LSw.Stop;
|
||||
Log(' HTTP ' + LRes.HttpCode.ToString + ' en ' +
|
||||
Log(' HTTP ' + LRes.HttpCode.ToString + ' in ' +
|
||||
LSw.ElapsedMilliseconds.ToString + ' ms');
|
||||
|
||||
case LRes.Status of
|
||||
@@ -1018,14 +1018,14 @@ begin
|
||||
// rafraichissement de fond c'est le cas courant, et il
|
||||
// doit passer inapercu - surtout pas de retour a la liste
|
||||
// alors que l'utilisateur consulte une entree.
|
||||
Log(' 304 : inchange, coffre deja ouvert')
|
||||
Log(' 304: unchanged, vault already open')
|
||||
else if LCached <> '' then
|
||||
begin
|
||||
Log(' 304 : inchange, coffre servi depuis le cache');
|
||||
Log(' 304: unchanged, vault served from cache');
|
||||
try
|
||||
AdoptVault(LCached);
|
||||
except
|
||||
on E: Exception do Status('Cache illisible : ' + E.Message);
|
||||
on E: Exception do Status('Cache unreadable: ' + E.Message);
|
||||
end;
|
||||
end
|
||||
else
|
||||
@@ -1034,7 +1034,7 @@ begin
|
||||
// On le jette pour que l'appel suivant retelecharge.
|
||||
FETag := '';
|
||||
if not ASilent then
|
||||
Status('Cache absent - appuyer a nouveau pour telecharger');
|
||||
Status('No cache - tap again to download');
|
||||
end;
|
||||
end);
|
||||
Exit;
|
||||
@@ -1042,10 +1042,10 @@ begin
|
||||
ssNoSnapshot:
|
||||
begin
|
||||
// Le serveur repond pareil dans les deux cas, par conception.
|
||||
Log(' 404 : pas d''instantane OU jeton invalide');
|
||||
Log(' 404: no snapshot OR invalid token');
|
||||
if not ASilent then
|
||||
TThread.Queue(nil, procedure
|
||||
begin Status('Rien a telecharger (404)'); end);
|
||||
begin Status('Nothing to download (404)'); end);
|
||||
Exit;
|
||||
end;
|
||||
ssRefused, ssHttpError, ssNetworkError:
|
||||
@@ -1053,17 +1053,17 @@ begin
|
||||
// En fond, un echec reseau ne se signale pas : le coffre local
|
||||
// est affiche, hors ligne est un etat normal, et une alerte ici
|
||||
// apprendrait a l'utilisateur a ignorer les alertes.
|
||||
Log(' echec : ' + LRes.Error);
|
||||
Log(' failed: ' + LRes.Error);
|
||||
if not ASilent then
|
||||
TThread.Queue(nil, procedure
|
||||
begin Status('Echec reseau'); end);
|
||||
begin Status('Network failure'); end);
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Log(' recu ' + Length(LRes.Container).ToString + ' octets');
|
||||
Log(' received ' + Length(LRes.Container).ToString + ' bytes');
|
||||
if not ASilent then
|
||||
TThread.Queue(nil, procedure begin Status('Dechiffrement...'); end);
|
||||
TThread.Queue(nil, procedure begin Status('Decrypting...'); end);
|
||||
|
||||
LSw := TStopwatch.StartNew;
|
||||
// Volontairement AVANT de retenir l'ETag : un echec ici doit laisser
|
||||
@@ -1071,7 +1071,7 @@ begin
|
||||
LPlain := DecryptContainer(LRes.Container, APwd);
|
||||
LSw.Stop;
|
||||
FETag := LRes.ETag;
|
||||
Log(' dechiffre en ' + LSw.ElapsedMilliseconds.ToString + ' ms');
|
||||
Log(' decrypted in ' + LSw.ElapsedMilliseconds.ToString + ' ms');
|
||||
|
||||
// Ecrit APRES un dechiffrement reussi seulement, et avec son ETag :
|
||||
// les deux doivent rester coherents.
|
||||
@@ -1083,16 +1083,16 @@ begin
|
||||
// pas des reglages saisis, on enregistre des reglages EPROUVES.
|
||||
SaveDeviceSettings(AUrl, ATok);
|
||||
if VaultNeedsAuth then
|
||||
Log(' cache ecrit - protege par biometrie/code')
|
||||
Log(' cache written - protected by biometrics/PIN')
|
||||
else if LCanAuth then
|
||||
Log(' cache ecrit - cle simple (Keystore a refuse la contrainte)')
|
||||
Log(' cache written - plain key (Keystore refused the constraint)')
|
||||
else
|
||||
Log(' cache ecrit - AUCUNE protection : pas d''authentification ici');
|
||||
Log(' cache written - NO protection: no authentication here');
|
||||
except
|
||||
// La classe compte autant que le message : "methode introuvable"
|
||||
// designe une signature JNI fausse, pas un probleme de stockage.
|
||||
on E: Exception do
|
||||
Log(' cache non ecrit : ' + E.ClassName + ' - ' + E.Message);
|
||||
Log(' cache not written: ' + E.ClassName + ' - ' + E.Message);
|
||||
end;
|
||||
|
||||
TThread.Queue(nil,
|
||||
@@ -1104,13 +1104,13 @@ begin
|
||||
except
|
||||
on E: Exception do
|
||||
if not ASilent then
|
||||
Status('Instantane illisible : ' + E.Message);
|
||||
Status('Snapshot unreadable: ' + E.Message);
|
||||
end;
|
||||
end);
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
Log('ERREUR ' + E.ClassName + ' : ' + E.Message);
|
||||
Log('ERROR ' + E.ClassName + ' : ' + E.Message);
|
||||
// Le cas de loin le plus frequent, et le message par defaut ne le
|
||||
// dit pas : GCM echoue a la verification quand la cle est fausse.
|
||||
//
|
||||
@@ -1120,7 +1120,7 @@ begin
|
||||
// le champ prerempli, et le coffre local reste consultable.
|
||||
if not ASilent then
|
||||
TThread.Queue(nil, procedure
|
||||
begin Status('Echec - mot de passe de sync incorrect ?'); end);
|
||||
begin Status('Failed - wrong sync password?'); end);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
@@ -1188,7 +1188,7 @@ begin
|
||||
LPrev := FFolderNames[FFolderSel];
|
||||
|
||||
SetLength(FFolderNames, 1);
|
||||
FFolderNames[0] := 'Tous les dossiers';
|
||||
FFolderNames[0] := 'All folders';
|
||||
for LF in FVault.Folders do
|
||||
begin
|
||||
SetLength(FFolderNames, Length(FFolderNames) + 1);
|
||||
@@ -1341,7 +1341,7 @@ begin
|
||||
end;
|
||||
|
||||
if (FSearch.Text.Trim = '') and (LFolder = '') then
|
||||
FCount.Text := FVault.LiveCount.ToString + ' entrees'
|
||||
FCount.Text := FVault.LiveCount.ToString + ' entries'
|
||||
else
|
||||
FCount.Text := Length(FFiltered).ToString + ' / ' +
|
||||
FVault.LiveCount.ToString;
|
||||
@@ -1369,12 +1369,12 @@ begin
|
||||
if FRowShown[I] then
|
||||
begin
|
||||
FRowValues[I].Text := FRows[I].Value;
|
||||
SetButtonText(TRectangle(Sender), 'Masquer');
|
||||
SetButtonText(TRectangle(Sender), 'Hide');
|
||||
end
|
||||
else
|
||||
begin
|
||||
FRowValues[I].Text := MASK;
|
||||
SetButtonText(TRectangle(Sender), 'Afficher');
|
||||
SetButtonText(TRectangle(Sender), 'Show');
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -1388,7 +1388,7 @@ begin
|
||||
// -1 : la ligne du TOTP, qui n'est pas dans FRows - sa valeur change chaque
|
||||
// periode et ne vit que dans FTotpCode. Copie sans l'espace d'affichage.
|
||||
if I = -1 then
|
||||
CopyToClipboard(FTotpCode, 'Code 2FA')
|
||||
CopyToClipboard(FTotpCode, '2FA code')
|
||||
else if (I >= 0) and (I <= High(FRows)) then
|
||||
CopyToClipboard(FRows[I].Value, FRows[I].Caption);
|
||||
end;
|
||||
@@ -1408,7 +1408,7 @@ begin
|
||||
// ponytail: le message reste jusqu'a la prochaine navigation, pas de minuterie
|
||||
// pour l'effacer. Un deuxieme TTimer pour deux secondes d'affichage serait
|
||||
// plus de code que ce que ca apporte.
|
||||
FDetToast.Text := ALabel + ' copie - presse-papiers efface dans ' +
|
||||
FDetToast.Text := ALabel + ' copied - clipboard cleared in ' +
|
||||
CLIPBOARD_CLEAR_SECONDS.ToString + ' s';
|
||||
end;
|
||||
|
||||
@@ -1477,7 +1477,7 @@ begin
|
||||
end;
|
||||
if MinutesBetween(Now, FLastActivity) >= AUTOLOCK_MINUTES then
|
||||
begin
|
||||
Log('Verrouille apres ' + AUTOLOCK_MINUTES.ToString + ' min d''inactivite');
|
||||
Log('Locked after ' + AUTOLOCK_MINUTES.ToString + ' min idle');
|
||||
LockVault;
|
||||
end;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user