From 7218df2f6f4037ce26c3d1c9d6c1c526586171a9 Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Sun, 16 Aug 2026 23:16:18 +0100 Subject: [PATCH] feat(android): copy from the list, server params grouped, HTML probe The card no longer swallows the tap: it covered the whole row and OnItemClick never fired. It paints, nothing more - HitTest false - and its children keep theirs. The two buttons take a Left and a Right rather than fixed coordinates, which put them outside the frame. The sync password joins the URL and the token: it is a server parameter, and it filled the home screen although it is typed once. The panel opens by itself when one of the three is missing - folding away empty fields hides the only thing left to do. And an HTML probe, to answer a question rather than argue it: the same list painted by the system engine. It renders well, Arabic included. Two lessons: FMX passes a nil encoding to loadDataWithBaseURL, and this source file carries no byte-order mark, so Delphi reads it as ANSI and an Arabic literal is already broken at compile time - hence the numeric references. Neither is a weakness of the engine, which is what I first suspected. Co-Authored-By: Claude Opus 5 --- mainApk.pas | 131 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 11 deletions(-) diff --git a/mainApk.pas b/mainApk.pas index 3a4cc02..f437bab 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -29,6 +29,7 @@ uses FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Platform, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Memo, FMX.Memo.Types, FMX.ScrollBox, FMX.Layouts, FMX.Edit, FMX.ListBox, FMX.Objects, + FMX.WebBrowser, PMA.Vault; const @@ -100,7 +101,11 @@ type // --- ecran 1 : deverrouillage FLayUnlock: TLayout; FUrl, FToken, FPwd: TEdit; - FBtnOpen, FBtnSync, FBtnSettings, FBtnLog: TRectangle; + FBtnOpen, FBtnSync, FBtnSettings, FBtnLog, FBtnHtml: TRectangle; + /// Sondage HTML, cree au premier appui seulement : un moteur de rendu + /// entier ne se paie pas au lancement pour un essai. + FLayWeb: TLayout; + FWeb: TWebBrowser; FLaySettings: TLayout; FStatus: TLabel; FLog: TMemo; @@ -197,6 +202,8 @@ type procedure OnBackTap(Sender: TObject); procedure OnToggleSettings(Sender: TObject); procedure OnToggleLog(Sender: TObject); + procedure OnHtmlTest(Sender: TObject); + procedure OnHtmlClose(Sender: TObject); procedure OnClipTimer(Sender: TObject); procedure OnHardwareBack(Sender: TObject; var Key: Word; var KeyChar: WideChar; Shift: TShiftState); @@ -350,10 +357,15 @@ begin FLaySettings := TLayout.Create(Self); FLaySettings.Parent := FLayUnlock; FLaySettings.Align := TAlignLayout.Top; - FLaySettings.Height := 116; - FLaySettings.Visible := False; + FLaySettings.Height := 174; + // Les trois vont ensemble : ce sont les coordonnees du serveur, dont le mot + // de passe fait partie. Il occupait l'ecran d'accueil en permanence alors + // qu'on n'y touche qu'une fois. TopEdit empile du bas vers le haut, d'ou + // l'ordre inverse ici. + FPwd := TopEdit(FLaySettings, 'sync password', TEST_PWD, True); FToken := TopEdit(FLaySettings, 'bearer token', FIRSTRUN_TOKEN); FUrl := TopEdit(FLaySettings, 'endpoint URL', FIRSTRUN_URL); + FPwd.Margins.Rect := RectF(16, 8, 16, 0); 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. @@ -362,6 +374,9 @@ begin FUrl.Text := LUrl; if LToken <> '' then FToken.Text := LToken; end; + // Replier des champs vides revient a cacher la seule chose a faire. + FLaySettings.Visible := (FUrl.Text.Trim = '') or (FToken.Text.Trim = '') + or (FPwd.Text = ''); // Deux commandes discretes cote a cote : elles ne servent qu'au reglage et // au diagnostic, et n'ont pas a peser autant que les actions principales. @@ -379,14 +394,18 @@ begin FBtnSettings := FlatButton(LRow, 'Server settings', OnToggleSettings); FBtnSettings.Align := TAlignLayout.Client; + // Sondage, pas une fonction : il repond a une seule question, celle de + // savoir si une page HTML peinte par le moteur du systeme rend mieux que + // ces controles-ci. A retirer des que la reponse est prise. + FBtnHtml := FlatButton(LRow, 'HTML', OnHtmlTest); + FBtnHtml.Align := TAlignLayout.Left; + FBtnHtml.Width := 90; + FBtnHtml.Margins.Right := 8; + FBtnSync := TopButton(FLayUnlock, 'Sync', DoSync); // Accentue : c'est l'action attendue quand aucun coffre n'est encore la. FBtnOpen := TopButton(FLayUnlock, 'Open vault', DoOpenLocal, 52, True); - // Pre-rempli depuis le fichier local, jamais depuis ce fichier-ci. - FPwd := TopEdit(FLayUnlock, 'sync password', TEST_PWD, True); - FPwd.Margins.Rect := RectF(16, 16, 16, 0); - FStatus := TLabel.Create(Self); FStatus.Parent := FLayUnlock; FStatus.Align := TAlignLayout.Top; @@ -892,6 +911,89 @@ begin FLog.Visible := not FLog.Visible; end; +/// Sondage HTML : la meme liste, les memes blocs, mais peints par le moteur du +/// systeme au lieu de FMX. Ce qu'il faut regarder : le rendu de l'arabe, la +/// fluidite du defilement, et si la page se fond dans le degrade ou flotte +/// dans un rectangle blanc. Contenu factice - rien du coffre ne passe ici. +procedure TForm8.OnHtmlTest(Sender: TObject); +const + PAGE = + // SANS LA DECLARATION DE JEU DE CARACTERES l'arabe sort en charabia : le + // moteur recoit de l'UTF-8 et le lit en latin-1 faute d'indication. + '' + + '' + + '

Rendu HTML

' + + '
Rechercher
' + + '
G
Gitea' + + 'git.example.com
' + + '
' + + // L'ARABE EN REFERENCES NUMERIQUES, pas en clair : ce fichier n'a pas de + // marque d'ordre d'octets, Delphi le lit donc en ANSI et abimerait le + // litteral bien avant que le moteur de rendu le voie. Le detail affiche + // de l'arabe correct parce que celui-la vient du JSON, a l'execution. + '
م
' + + '
مرحبا بالعالم' + + 'اختبار العربية
' + + '
' + + '
N
Nextcloud' + + 'cloud.example.com
' + + '
'; +var + LBar: TLayout; + LBtn: TRectangle; +begin + if FLayWeb = nil then + begin + FLayWeb := TLayout.Create(Self); + FLayWeb.Parent := Self; + FLayWeb.Align := TAlignLayout.Client; + + // La barre est POSEE AVANT le navigateur et alignee en bas : sur Android + // le moteur est une vraie vue du systeme, qui se peint par-dessus tout ce + // que FMX dessine. Elle ne survivrait pas sous lui. + LBar := TLayout.Create(FLayWeb); + LBar.Parent := FLayWeb; + LBar.Align := TAlignLayout.Bottom; + LBar.Height := 60; + LBtn := FlatButton(LBar, 'Close', OnHtmlClose, True); + LBtn.Align := TAlignLayout.Client; + LBtn.Margins.Rect := RectF(16, 4, 16, 10); + + FWeb := TWebBrowser.Create(Self); + FWeb.Parent := FLayWeb; + FWeb.Align := TAlignLayout.Client; + // La page est en ASCII pur, d'ou les references numeriques plus haut : + // FMX appelle loadDataWithBaseURL en laissant l'encodage a nil, et une + // URL « data: », qui le porterait, est refusee par Navigate. + // ponytail: sonde. Une vraie page serait servie en HTTP, comme sur le + // poste, et la question de l'encodage ne se poserait plus. + FWeb.LoadFromStrings(PAGE, ''); + end; + FLayWeb.Visible := True; + FLayWeb.BringToFront; +end; + +procedure TForm8.OnHtmlClose(Sender: TObject); +begin + FLayWeb.Visible := False; +end; + { ---------------------------------------------------------------------------- Ouverture, synchronisation, verrouillage ---------------------------------------------------------------------------- } @@ -1486,6 +1588,10 @@ begin LCard := Surface(LItem); LCard.Align := TAlignLayout.Client; LCard.Margins.Rect := RectF(4, 3, 4, 3); + // SANS CECI L'ENTREE N'EST PLUS CLIQUABLE : le bloc couvre toute la + // ligne et absorbe le tap, donc OnItemClick ne part jamais. Il ne sert + // qu'a peindre. Ses enfants, eux, gardent leur propre HitTest. + LCard.HitTest := False; // Copier sans ouvrir l'entree - le geste le plus frequent. Les deux // boutons sont poses a la coordonnee dans leur propre conteneur : deux @@ -1496,14 +1602,17 @@ begin LActions.Width := 150; LActions.Margins.Rect := RectF(0, 8, 8, 8); + // Un Left et un Right, jamais deux fois le meme cote : leur ordre serait + // alors laisse au hasard. Ils prennent la hauteur du conteneur, ce qui + // evite de poser des coordonnees qui debordaient du bloc. LBtnUser := FlatButton(LActions, 'User', OnRowCopyUser); - LBtnUser.Align := TAlignLayout.None; - LBtnUser.SetBounds(0, 0, 70, 54); + LBtnUser.Align := TAlignLayout.Left; + LBtnUser.Width := 70; LBtnUser.Tag := FFiltered[I]; LBtnPwd := FlatButton(LActions, 'Pass', OnRowCopyPwd); - LBtnPwd.Align := TAlignLayout.None; - LBtnPwd.SetBounds(76, 0, 70, 54); + LBtnPwd.Align := TAlignLayout.Right; + LBtnPwd.Width := 70; LBtnPwd.Tag := FFiltered[I]; // CONTENU CONSTRUIT A LA MAIN, sans passer par Text/Detail/Bitmap ni par // un StyleLookup. Ces gabarits n'existent pas dans tous les styles :