feat(android): the palette taken from the phone's global search

Not the desktop's slate any more: a blue gradient behind, blocks that are only translucent white laid over it, no borders at all, wide radii, white text. Depth comes from transparency, which is why the frames are gone - a hairline reads as a desktop application immediately.

There is no coloured accent in the reference either: primary and secondary differ by how much white they carry, 30 against 18 per cent. The 2FA code goes white, carried by its size. Nothing is uppercase - the second plane is marked by colour and size alone.

Three compiler traps on the way, all worth knowing: TBrush needs FMX.Graphics in the INTERFACE clause, a fresh TGradient already runs top to bottom, and TForm already owns a parameterless PaintBackground that shadowed the unit's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-08-16 19:47:44 +01:00
parent 1609b4d328
commit 27a7a322d6
4 changed files with 66 additions and 52 deletions
+52 -39
View File
@@ -20,22 +20,28 @@ unit PMA.Theme;
interface interface
uses uses
System.UITypes, System.Classes, FMX.Types, FMX.Objects, FMX.StdCtrls; // FMX.Graphics pour TBrush, que PaintBackground prend en parametre.
System.UITypes, System.Classes, FMX.Types, FMX.Graphics, FMX.Objects,
FMX.StdCtrls;
const const
// Ardoise et bleu. Le poste Windows accentue en cyan ; ici c'est le bleu // Releve sur la recherche globale du telephone, qui est la reference pour
// d'Android - celui de la recherche globale et des applications systeme. // tout ce qui se touche - l'application doit ressembler a l'endroit ou elle
// Une application mobile a deux references legitimes, celle dont elle // tourne, pas seulement au service qu'elle prolonge.
// prolonge le service et celle du systeme qui l'heberge ; pour ce qui se //
// touche, la seconde l'emporte. // CE QUI FAIT CE STYLE, et qu'il faut tenir : un DEGRADE bleu en fond, des
COL_BG = TAlphaColor($FF0F172A); // fond general // blocs qui ne sont que du BLANC TRANSLUCIDE pose dessus, AUCUNE bordure, de
COL_SURFACE = TAlphaColor($FF1E293B); // blocs poses dessus // grands arrondis, du texte blanc. La profondeur vient de la transparence,
COL_RAISED = TAlphaColor($FF334155); // bouton au repos // pas des filets - c'est pour ca que les cadres ont disparu.
COL_LINE = TAlphaColor($FF334155); // filet des cadres COL_BG_TOP = TAlphaColor($FF3E6394); // haut du degrade
COL_TEXT = TAlphaColor($FFE2E8F0); COL_BG = TAlphaColor($FF1B3563); // bas du degrade, et repli uni
COL_MUTED = TAlphaColor($FF94A3B8); COL_SURFACE = TAlphaColor($1FFFFFFF); // bloc : 12 % de blanc
COL_ACCENT = TAlphaColor($FF3B82F6); COL_RAISED = TAlphaColor($2EFFFFFF); // bouton au repos : 18 %
COL_ON_ACC = TAlphaColor($FFFFFFFF); // texte sur fond accentue COL_ACCENT = TAlphaColor($4DFFFFFF); // action principale : 30 %
COL_LINE = TAlphaColor($00000000); // plus de filet : garde pour l'API
COL_TEXT = TAlphaColor($FFFFFFFF);
COL_MUTED = TAlphaColor($B3E8F0FA);
COL_ON_ACC = TAlphaColor($FFFFFFFF); // le blanc reste lisible sur 30 %
/// A appeler une fois, avant la creation de la forme. /// A appeler une fois, avant la creation de la forme.
procedure ApplyDarkTheme; procedure ApplyDarkTheme;
@@ -53,16 +59,19 @@ procedure SetButtonEnabled(AButton: TRectangle; AEnabled: Boolean);
/// Bloc de fond, coins arrondis, filet discret. /// Bloc de fond, coins arrondis, filet discret.
function Surface(AParent: TFmxObject): TRectangle; function Surface(AParent: TFmxObject): TRectangle;
/// Intitule de section : majuscules, petit, discret. /// Intitule au-dessus d'une valeur : petit et discret, sans majuscules.
procedure SectionLabel(ALabel: TLabel); procedure SectionLabel(ALabel: TLabel);
/// Applique le degrade bleu du fond. A poser sur le Fill de la forme.
procedure PaintBackground(AFill: TBrush);
/// Met un libelle a la palette. AMuted pour les intitules discrets. /// Met un libelle a la palette. AMuted pour les intitules discrets.
procedure Tint(ALabel: TLabel; ASize: Single; AMuted: Boolean = False); procedure Tint(ALabel: TLabel; ASize: Single; AMuted: Boolean = False);
implementation implementation
uses uses
System.SysUtils, System.Types, FMX.Styles, FMX.Graphics, FMX.Controls; System.SysUtils, System.Types, FMX.Styles, FMX.Controls;
{$R 'theme\theme.res' 'theme\theme.rc'} {$R 'theme\theme.res' 'theme\theme.rc'}
@@ -116,23 +125,31 @@ begin
Result := TRectangle.Create(AParent); Result := TRectangle.Create(AParent);
Result.Parent := AParent; Result.Parent := AParent;
Result.Fill.Color := COL_SURFACE; Result.Fill.Color := COL_SURFACE;
// Filet discret plutot qu'aucune bordure : c'est lui qui detache un bloc du // AUCUNE bordure, et un grand arrondi : c'est la translucidite qui detache
// fond sans avoir a l'eclaircir, comme sur le poste Windows. // le bloc du fond. Un filet rendrait tout de suite l'air « application de
Result.Stroke.Color := COL_LINE; // bureau ».
Result.Stroke.Thickness := 1; Result.Stroke.Kind := TBrushKind.None;
Result.XRadius := 10; Result.XRadius := 20;
Result.YRadius := 10; Result.YRadius := 20;
end; end;
/// Intitule de section : majuscules, petit, discret. C'est ce qui donne au /// Intitule au-dessus d'une valeur. Ni majuscules ni petites capitales : rien
/// poste Windows sa lisibilite - l'oeil saute d'un intitule a l'autre sans /// n'est en majuscules dans la reference, le second plan s'y marque par la
/// confondre avec les valeurs. /// couleur et la taille seules.
procedure SectionLabel(ALabel: TLabel); procedure SectionLabel(ALabel: TLabel);
begin begin
ALabel.StyledSettings := []; ALabel.StyledSettings := [];
ALabel.TextSettings.Font.Size := 11; ALabel.TextSettings.Font.Size := 12;
ALabel.TextSettings.FontColor := COL_MUTED; ALabel.TextSettings.FontColor := COL_MUTED;
ALabel.Text := ALabel.Text.ToUpper; end;
/// Peint le degrade de fond sur une forme.
procedure PaintBackground(AFill: TBrush);
begin
AFill.Kind := TBrushKind.Gradient;
AFill.Gradient.Color := COL_BG_TOP;
AFill.Gradient.Color1 := COL_BG;
// Rien de plus : un TGradient neuf descend deja du haut vers le bas.
end; end;
function FlatButton(AParent: TFmxObject; const AText: string; function FlatButton(AParent: TFmxObject; const AText: string;
@@ -143,20 +160,16 @@ var
begin begin
Result := TRectangle.Create(AParent); Result := TRectangle.Create(AParent);
Result.Parent := AParent; Result.Parent := AParent;
Result.XRadius := 10; // Pilule : l'arrondi vaut la moitie de la hauteur usuelle d'un bouton. Tout
Result.YRadius := 10; // ce qui se touche est arrondi ainsi dans la reference.
Result.XRadius := 26;
Result.YRadius := 26;
Result.Cursor := crHandPoint; Result.Cursor := crHandPoint;
if APrimary then
begin
Result.Fill.Color := COL_ACCENT;
Result.Stroke.Kind := TBrushKind.None; Result.Stroke.Kind := TBrushKind.None;
end // La difference entre principal et secondaire tient a l'opacite du blanc,
else // pas a une couleur : la reference n'a aucun accent colore.
begin if APrimary then Result.Fill.Color := COL_ACCENT
Result.Fill.Color := COL_SURFACE; else Result.Fill.Color := COL_RAISED;
Result.Stroke.Color := COL_LINE;
Result.Stroke.Thickness := 1;
end;
Result.OnClick := AOnClick; Result.OnClick := AOnClick;
LCaption := TLabel.Create(Result); LCaption := TLabel.Create(Result);
+3 -3
View File
@@ -19,9 +19,9 @@ $src = 'C:\Program Files (x86)\Embarcadero\Studio\23.0\Redist\styles\Fmx\Dark.st
$dst = Join-Path $PSScriptRoot 'pm-dark.style' $dst = Join-Path $PSScriptRoot 'pm-dark.style'
# Doivent suivre les constantes de PMA.Theme. # Doivent suivre les constantes de PMA.Theme.
$surface = 'xFF1E293B' # COL_SURFACE $surface = 'x2EFFFFFF' # COL_RAISED : blanc translucide, sans bordure
$border = 'xFF334155' # COL_RAISED, en bordure discrete $border = 'x00000000' # plus de filet : la reference n'en a aucun
$text = 'xFFE2E8F0' # COL_TEXT $text = 'xFFFFFFFF' # COL_TEXT
$lines = Get-Content $src $lines = Get-Content $src
$patched = 0 $patched = 0
+5 -5
View File
@@ -2075,18 +2075,18 @@
object TRectangle object TRectangle
StyleName = 'background' StyleName = 'background'
Align = Contents Align = Contents
Fill.Color = xFF1E293B Fill.Color = x2EFFFFFF
Locked = True Locked = True
Height = 22.000000000000000000 Height = 22.000000000000000000
HitTest = False HitTest = False
Stroke.Color = xFF334155 Stroke.Color = x00000000
XRadius = 24.000000000000000000 XRadius = 24.000000000000000000
YRadius = 24.000000000000000000 YRadius = 24.000000000000000000
Width = 107.000000000000000000 Width = 107.000000000000000000
end end
object TBrushObject object TBrushObject
StyleName = 'foreground' StyleName = 'foreground'
Brush.Color = xFFE2E8F0 Brush.Color = xFFFFFFFF
end end
object TBrushObject object TBrushObject
StyleName = 'selection' StyleName = 'selection'
@@ -2509,7 +2509,7 @@
object TRectangle object TRectangle
StyleName = 'background' StyleName = 'background'
Align = Contents Align = Contents
Fill.Color = xFF1E293B Fill.Color = x2EFFFFFF
Locked = True Locked = True
Height = 131.000000000000000000 Height = 131.000000000000000000
HitTest = False HitTest = False
@@ -2517,7 +2517,7 @@
Padding.Top = 2.000000000000000000 Padding.Top = 2.000000000000000000
Padding.Right = 2.000000000000000000 Padding.Right = 2.000000000000000000
Padding.Bottom = 2.000000000000000000 Padding.Bottom = 2.000000000000000000
Stroke.Color = xFF334155 Stroke.Color = x00000000
XRadius = 10.000000000000000000 XRadius = 10.000000000000000000
YRadius = 10.000000000000000000 YRadius = 10.000000000000000000
Width = 334.000000000000000000 Width = 334.000000000000000000
+5 -4
View File
@@ -237,8 +237,9 @@ begin
Caption := 'Vault'; Caption := 'Vault';
// Le fond de la forme, et non celui du style : tout le reste est peint // 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. // par-dessus, et un gris herite se verrait entre les blocs.
Fill.Kind := TBrushKind.Solid; // Qualifie : TForm a deja une methode PaintBackground, sans parametre, qui
Fill.Color := COL_BG; // masque celle de l'unite.
PMA.Theme.PaintBackground(Fill);
SecureScreen; // avant tout affichage de contenu SecureScreen; // avant tout affichage de contenu
FVault := TVault.Create; FVault := TVault.Create;
FIcons := TObjectDictionary<Integer, TBitmap>.Create([doOwnsValues]); FIcons := TObjectDictionary<Integer, TBitmap>.Create([doOwnsValues]);
@@ -765,7 +766,7 @@ begin
SetLength(FRowCtls, Length(FRowCtls) + 1); SetLength(FRowCtls, Length(FRowCtls) + 1);
FRowCtls[High(FRowCtls)] := LRow; FRowCtls[High(FRowCtls)] := LRow;
FTotpValue.TextSettings.Font.Size := 28; FTotpValue.TextSettings.Font.Size := 28;
FTotpValue.TextSettings.FontColor := COL_ACCENT; FTotpValue.TextSettings.FontColor := COL_TEXT;
AddRowButton(LRow, 'Copy', -1, OnCopyTap); AddRowButton(LRow, 'Copy', -1, OnCopyTap);
// Barre de progression sous le code, comme sur le poste : elle dit d'un // Barre de progression sous le code, comme sur le poste : elle dit d'un
@@ -773,7 +774,7 @@ begin
FTotpBar := TRectangle.Create(LRow); FTotpBar := TRectangle.Create(LRow);
FTotpBar.Parent := LRow; FTotpBar.Parent := LRow;
FTotpBar.Align := TAlignLayout.None; FTotpBar.Align := TAlignLayout.None;
FTotpBar.Fill.Color := COL_ACCENT; FTotpBar.Fill.Color := COL_TEXT;
FTotpBar.Stroke.Kind := TBrushKind.None; FTotpBar.Stroke.Kind := TBrushKind.None;
FTotpBar.XRadius := 1; FTotpBar.XRadius := 1;
FTotpBar.YRadius := 1; FTotpBar.YRadius := 1;