fix(android): les refus se voient, et la croix se recale sur le champ
Un refus s'affichait du meme gris qu'un etat : "Master password: 8 characters at least" se lisait comme "Vault on this device", et rien ne disait que l'application venait de refuser. StatusErr le met en rouge - deux procedures plutot qu'un drapeau devine du texte, parce que trier des messages sur leur contenu a deja detruit un cache dans ce projet. C'est l'appelant qui sait s'il refuse. La croix des champs etait calee a top: 8px, en compensation du margin-top du champ. Les piles annulent ce margin depuis qu'on y a unifie l'espacement, et la croix restait donc 8 px trop bas. Elle s'ancre desormais au bord INFERIEUR, le seul que le champ touche dans les deux cas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -270,6 +270,10 @@
|
|||||||
|
|
||||||
/* --- deverrouillage ----------------------------------------------------- */
|
/* --- deverrouillage ----------------------------------------------------- */
|
||||||
.status { color: var(--muted); margin: 22px 4px 14px; min-height: 20px; }
|
.status { color: var(--muted); margin: 22px 4px 14px; min-height: 20px; }
|
||||||
|
/* UN REFUS N'EST PAS UN ETAT. "Master password: 8 characters at least" se
|
||||||
|
lisait du meme gris que "Vault on this device" - on ne voyait pas que
|
||||||
|
l'application venait de refuser quelque chose. */
|
||||||
|
.status.err { color: #ff9d9d; }
|
||||||
.stack { display: flex; flex-direction: column; gap: 8px; }
|
.stack { display: flex; flex-direction: column; gap: 8px; }
|
||||||
/* L'espace de 8 px vit A L'INTERIEUR de chaque pile. Deux piles voisines se
|
/* L'espace de 8 px vit A L'INTERIEUR de chaque pile. Deux piles voisines se
|
||||||
touchaient donc, et "Create vault" collait a "Download vault" alors que
|
touchaient donc, et "Create vault" collait a "Download vault" alors que
|
||||||
@@ -304,8 +308,12 @@
|
|||||||
.in-wrap { position: relative; }
|
.in-wrap { position: relative; }
|
||||||
/* Le champ laisse la place a la croix, sinon le texte passe dessous. */
|
/* Le champ laisse la place a la croix, sinon le texte passe dessous. */
|
||||||
.in-wrap .field-in { padding-right: 44px; }
|
.in-wrap .field-in { padding-right: 44px; }
|
||||||
|
/* ANCREE EN BAS, PAS EN HAUT. Le champ porte un margin-top de 8 px, que les
|
||||||
|
piles annulent : caler la croix a `top: 8px` la laissait donc 8 px trop bas
|
||||||
|
des que le margin disparaissait. Le bord INFERIEUR, lui, est celui que le
|
||||||
|
champ touche dans les deux cas - le margin est au-dessus. */
|
||||||
.in-x {
|
.in-x {
|
||||||
position: absolute; right: 0; top: 8px; width: 44px; height: 46px;
|
position: absolute; right: 0; bottom: 0; width: 44px; height: 46px;
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex; align-items: center; justify-content: center;
|
||||||
color: var(--muted); font-size: 22px;
|
color: var(--muted); font-size: 22px;
|
||||||
}
|
}
|
||||||
@@ -1601,8 +1609,12 @@ var PM = {
|
|||||||
document.body.classList.remove('on-list', 'on-detail', 'searching');
|
document.body.classList.remove('on-list', 'on-detail', 'searching');
|
||||||
view = 'unlock';
|
view = 'unlock';
|
||||||
},
|
},
|
||||||
setStatus: function (text) {
|
setStatus: function (text, err) {
|
||||||
document.getElementById('status').textContent = text;
|
var s = document.getElementById('status');
|
||||||
|
s.textContent = text;
|
||||||
|
// classList.toggle avec un second argument : la classe suit le drapeau,
|
||||||
|
// sans qu'un message neutre ait a penser a l'enlever.
|
||||||
|
s.classList.toggle('err', !!err);
|
||||||
},
|
},
|
||||||
/// Etat des deux actions : ouvrir n'a de sens qu'avec un coffre local
|
/// Etat des deux actions : ouvrir n'a de sens qu'avec un coffre local
|
||||||
/// lisible, et synchroniser s'appelle autrement quand il n'y en a pas.
|
/// lisible, et synchroniser s'appelle autrement quand il n'y en a pas.
|
||||||
|
|||||||
+26
-15
@@ -351,6 +351,7 @@ type
|
|||||||
function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
|
function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
|
||||||
procedure Log(const AMsg: string);
|
procedure Log(const AMsg: string);
|
||||||
procedure Status(const AMsg: string);
|
procedure Status(const AMsg: string);
|
||||||
|
procedure StatusErr(const AMsg: string);
|
||||||
procedure SetBusy(ABusy: Boolean);
|
procedure SetBusy(ABusy: Boolean);
|
||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
@@ -1252,14 +1253,14 @@ begin
|
|||||||
if FBusy then Exit;
|
if FBusy then Exit;
|
||||||
if not HasLocalContainer then
|
if not HasLocalContainer then
|
||||||
begin
|
begin
|
||||||
Status('No local vault to reconcile');
|
StatusErr('No local vault to reconcile');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
// LES DEUX SONT REQUIS ICI, ET NULLE PART AILLEURS : c'est le seul moment ou
|
// LES DEUX SONT REQUIS ICI, ET NULLE PART AILLEURS : c'est le seul moment ou
|
||||||
// le conteneur local et l'instantane du depot se rencontrent.
|
// le conteneur local et l'instantane du depot se rencontrent.
|
||||||
if FVaultPwd = '' then
|
if FVaultPwd = '' then
|
||||||
begin
|
begin
|
||||||
Status('Open the vault first');
|
StatusErr('Open the vault first');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
// CE QUI EST DANS LES REGLAGES FAIT FOI quand le coffre n'en porte pas encore.
|
// CE QUI EST DANS LES REGLAGES FAIT FOI quand le coffre n'en porte pas encore.
|
||||||
@@ -1269,7 +1270,7 @@ begin
|
|||||||
if FSyncPwd = '' then FSyncPwd := FPwd;
|
if FSyncPwd = '' then FSyncPwd := FPwd;
|
||||||
if FSyncPwd = '' then
|
if FSyncPwd = '' then
|
||||||
begin
|
begin
|
||||||
Status('Set the sync password in Settings');
|
StatusErr('Set the sync password in Settings');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
SetBusy(True);
|
SetBusy(True);
|
||||||
@@ -1851,7 +1852,7 @@ begin
|
|||||||
if FBusy then Exit;
|
if FBusy then Exit;
|
||||||
if AUser = '' then
|
if AUser = '' then
|
||||||
begin
|
begin
|
||||||
Status('Pick a username');
|
StatusErr('Pick a username');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
// Huit caracteres, comme le poste. Ce mot de passe est la SEULE chose qui
|
// Huit caracteres, comme le poste. Ce mot de passe est la SEULE chose qui
|
||||||
@@ -1859,14 +1860,14 @@ begin
|
|||||||
// tentatives, et le fichier est un fichier.
|
// tentatives, et le fichier est un fichier.
|
||||||
if Length(APwd) < 8 then
|
if Length(APwd) < 8 then
|
||||||
begin
|
begin
|
||||||
Status('Master password: 8 characters at least');
|
StatusErr('Master password: 8 characters at least');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
// Un coffre existant ne se remplace pas par accident : ce serait perdre tout
|
// Un coffre existant ne se remplace pas par accident : ce serait perdre tout
|
||||||
// ce qu'il contient, sans retour possible.
|
// ce qu'il contient, sans retour possible.
|
||||||
if HasLocalContainer or HasVault then
|
if HasLocalContainer or HasVault then
|
||||||
begin
|
begin
|
||||||
Status('This device already holds a vault');
|
StatusErr('This device already holds a vault');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1920,7 +1921,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
SetBusy(False);
|
SetBusy(False);
|
||||||
Log('Register failed: ' + E.ClassName + ' - ' + E.Message);
|
Log('Register failed: ' + E.ClassName + ' - ' + E.Message);
|
||||||
Status('Could not create the vault - see log');
|
StatusErr('Could not create the vault - see log');
|
||||||
end);
|
end);
|
||||||
end;
|
end;
|
||||||
end).Start;
|
end).Start;
|
||||||
@@ -1937,7 +1938,7 @@ begin
|
|||||||
if FBusy then Exit;
|
if FBusy then Exit;
|
||||||
if not HasLocalContainer then
|
if not HasLocalContainer then
|
||||||
begin
|
begin
|
||||||
Status('No vault on this device');
|
StatusErr('No vault on this device');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
if APwd = '' then
|
if APwd = '' then
|
||||||
@@ -2157,7 +2158,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
Log('Vault did not open under this unlock code');
|
Log('Vault did not open under this unlock code');
|
||||||
ShowUnlock;
|
ShowUnlock;
|
||||||
Status('Wrong unlock code');
|
StatusErr('Wrong unlock code');
|
||||||
WebCall('PM.focusPin()');
|
WebCall('PM.focusPin()');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
@@ -2172,13 +2173,13 @@ begin
|
|||||||
// une panne.
|
// une panne.
|
||||||
if LastStoreKeyInvalidated then
|
if LastStoreKeyInvalidated then
|
||||||
begin
|
begin
|
||||||
Status('Device protection changed - download the vault again');
|
StatusErr('Device protection changed - download the vault again');
|
||||||
WebCall('PM.toast("This phone''s screen lock was removed or reset, so ' +
|
WebCall('PM.toast("This phone''s screen lock was removed or reset, so ' +
|
||||||
'Android destroyed the key that sealed the local copy. ' +
|
'Android destroyed the key that sealed the local copy. ' +
|
||||||
'Nothing is lost - the vault is in the repository.")');
|
'Nothing is lost - the vault is in the repository.")');
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Status('Local vault unreadable - see log');
|
StatusErr('Local vault unreadable - see log');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -2196,7 +2197,7 @@ begin
|
|||||||
// detruit le cache alors qu'il le protegeait.
|
// detruit le cache alors qu'il le protegeait.
|
||||||
if VaultNeedsPin and (FPin = '') then
|
if VaultNeedsPin and (FPin = '') then
|
||||||
begin
|
begin
|
||||||
Status('Unlock code required');
|
StatusErr('Unlock code required');
|
||||||
WebCall('PM.focusPin()');
|
WebCall('PM.focusPin()');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
@@ -2266,7 +2267,7 @@ begin
|
|||||||
if LPwd = '' then LPwd := FSyncPwd;
|
if LPwd = '' then LPwd := FSyncPwd;
|
||||||
if LPwd = '' then
|
if LPwd = '' then
|
||||||
begin
|
begin
|
||||||
Status('Sync password required');
|
StatusErr('Sync password required');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
WebCall('PM.clearLog()');
|
WebCall('PM.clearLog()');
|
||||||
@@ -2296,7 +2297,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if VaultNeedsPin and (FPin = '') then
|
if VaultNeedsPin and (FPin = '') then
|
||||||
begin
|
begin
|
||||||
Status('Unlock code required');
|
StatusErr('Unlock code required');
|
||||||
WebCall('PM.focusPin()');
|
WebCall('PM.focusPin()');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
@@ -2483,7 +2484,7 @@ begin
|
|||||||
Log(' failed: ' + LRes.Error);
|
Log(' failed: ' + LRes.Error);
|
||||||
if not ASilent then
|
if not ASilent then
|
||||||
TThread.Queue(nil, procedure
|
TThread.Queue(nil, procedure
|
||||||
begin Status('Network failure'); end);
|
begin StatusErr('Network failure'); end);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -3016,6 +3017,16 @@ begin
|
|||||||
WebCall('PM.setStatus(' + JsArg(AMsg) + ')');
|
WebCall('PM.setStatus(' + JsArg(AMsg) + ')');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Le meme endroit, mais en rouge : ce qui suit est un REFUS, pas un etat.
|
||||||
|
///
|
||||||
|
/// Deux procedures plutot qu'un drapeau devine du texte : trier des messages
|
||||||
|
/// sur leur contenu est exactement ce qui a deja detruit un cache dans ce
|
||||||
|
/// projet. C'est l'appelant qui sait s'il refuse.
|
||||||
|
procedure TForm8.StatusErr(const AMsg: string);
|
||||||
|
begin
|
||||||
|
WebCall('PM.setStatus(' + JsArg(AMsg) + ', true)');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TForm8.SetBusy(ABusy: Boolean);
|
procedure TForm8.SetBusy(ABusy: Boolean);
|
||||||
var
|
var
|
||||||
LCanOpen: Boolean;
|
LCanOpen: Boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user