docs(android): the plan catches up with the HTML interface

Section 3 bis asked whether Delphi controls were needed at all and said to decide before investing further in the interface. It is decided, so it now records the answer and the two traps buried in the bridge - the iframe, and the page having to stay ASCII - rather than leaving them to be re-discovered.

Section 1 ter described Skia as the fix for Arabic; it is gone, and what survives of that episode is the packaging constraint, which still governs the build.

The table in section 0 claimed template, icons, attachments, timestamps and folders were unread. They are read now; it says which parts, and what is genuinely still missing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-08-17 10:53:02 +01:00
parent 77809b09c8
commit b3fbaf44bd
+73 -48
View File
@@ -1,6 +1,6 @@
# Client Android — ce qu'il reste à faire
État au 2026-08-15. Le client lit l'instantané et l'affiche ; il n'écrit rien.
État au 2026-08-17. Le client lit l'instantané et l'affiche ; il n'écrit rien.
Ce document liste le reste, dans l'ordre où je le ferais.
Voir [README.md](README.md) pour l'architecture et les décisions déjà prises.
@@ -18,18 +18,21 @@ manques côté téléphone ne demandent **aucun** changement côté serveur.
| `folder`, `tags`, `kind` | oui | oui |
| `totp_secret` | oui | oui |
| `custom_fields` (`label`/`value`/`is_secret`) | oui | oui |
| `template` (carte, clé SSH, serveur…) | oui | **non** |
| `icon_b64`, `icon_custom` | oui | **non** |
| `attachments` (avec `content_b64`) | oui | **non** |
| `created_at`, `updated_at` | oui | **non** |
| `folders` (liste, couleur, icône) | oui | **non** |
| `template` (carte, clé SSH, serveur…) | oui | oui — ligne *Type* |
| `icon_b64` | oui | oui — pastille de la liste |
| `icon_custom` | oui | non — la provenance ne change rien à l'affichage |
| `attachments` — nom, type, taille | oui | oui — nommées, pas ouvrables |
| `attachments` — `content_b64` | oui | **non** — c'est l'enregistrement qui manque |
| `updated_at` | oui | oui |
| `created_at` | oui | **non** |
| `folders` (liste, couleur, icône) | oui | oui — le nom seulement |
| `avatar_b64`, `username` (compte) | oui | **non** |
| `tombstones` | oui | **non** |
| `tombstones` | oui | **non** — n'aura de sens qu'avec l'écriture |
| `favorite`, `pinned` | **non** — device-local par conception | — |
| corbeille | **non** — voyage dans les sauvegardes, pas la sync | — |
Autrement dit : dossiers, icônes, pièces jointes et horodatages sont déjà là,
il ne manque que la lecture. Seules les favoris/épinglés et la corbeille
Ce qui manque encore ne demande donc **rien** au poste Windows : c'est de la
lecture côté téléphone. Seules les favoris/épinglés et la corbeille
demanderaient une décision côté Windows — et pour les deux, la décision
actuelle est délibérée.
@@ -145,22 +148,27 @@ confort, ce qui est le mauvais sens pour un gestionnaire de mots de passe.
</details>
## 1 ter. Écritures complexes — Skia (2026-08-15)
## 1 ter. ~~Écritures complexes — Skia~~ — DEVENU INUTILE le 2026-08-17
Un nom de pièce jointe en arabe s'affichait en désordre. Ce n'était pas un
réglage manqué : le moteur de texte d'origine de FMX ne met pas en forme les
écritures complexes — pas de réordonnancement bidirectionnel, pas de liaison
des lettres. Séparer la taille du nom limitait les dégâts sans les supprimer.
Un nom de pièce jointe en arabe s'affichait en désordre : le moteur de texte
d'origine de FMX ne met pas en forme les écritures complexes — pas de
réordonnancement bidirectionnel, pas de liaison des lettres. `GlobalUseSkia`
réglait cela, au prix de `libsk4d.so` (25 Mo) et d'un **APK passé de 13 à 22 Mo**.
`GlobalUseSkia := True` avant `Application.Initialize` remplace le moteur de
rendu ; Skia embarque HarfBuzz et fait ce travail. Le prix est `libsk4d.so`,
25 Mo (8,9 Mo compressés), et un **APK qui passe de 13 à 22 Mo**.
**Retiré**, avec le style vendu, quand l'interface est passée au moteur du
système (§3 bis) : Skia ne servait qu'aux libellés FMX, et il n'en reste aucun.
Le moteur fait sa propre mise en forme — vérifié sur l'appareil, le même nom
arabe se lit correctement. L'APK **retombe à 12,7 Mo**.
Conséquence sur la fabrication : `Deploy` reconstruit `library\lib` avant
`aapt`, donc la bibliothèque posée à la main disparaît. D'où
Ce qui reste vrai de cet épisode, et qui gouverne encore la fabrication :
`Deploy` reconstruit `library\lib` avant `aapt`, donc tout ce qu'on y pose à la
main disparaît — aujourd'hui nos icônes, hier Skia. D'où
[repack-apk.ps1](repack-apk.ps1), qui refait *aapt → zipalign → signature* sur
le dossier déjà prêt. Une entrée `DeployFile` en bonne et due forme a été
tentée d'abord : MSBuild l'ignore, comme il ignore toutes les autres ici.
[build-apk.ps1](build-apk.ps1) enchaîne les quatre étapes, y compris la
régénération de `web.res` — l'oublier embarque la page d'avant l'édition, et le
symptôme se lit alors comme un bug applicatif.
## 2. Durcissement — petit, à faire avant tout usage réel
@@ -222,49 +230,66 @@ Rangé par ce que ça apporte réellement sur un téléphone.
À surveiller : quelques PDF suffiraient à peser plusieurs Mo, retéléchargés
entièrement à chaque instantané nouveau.
2. ~~**Filtre dossier**~~ — **fait**, liste déroulante à côté de la recherche,
alimentée par le tableau `folders`, et le choix survit à un rafraîchissement
de fond. **Pas de filtre d'étiquette** : la recherche texte couvre déjà les
2. ~~**Filtre dossier**~~ — **fait**, une rangée de pastilles avec leur compte,
alimentée par le tableau `folders`. Le filtrage se fait dans la page, donc
sans aller-retour, et le choix survit à un rafraîchissement de fond. **Pas de filtre d'étiquette** : la recherche texte couvre déjà les
étiquettes, en taper le nom suffit.
3. ~~**Icônes**~~ (`icon_b64`) — **fait**, décodées une fois par coffre et non à
chaque frappe (la liste est reconstruite à chaque caractère). Une icône SVG
n'est pas chargeable par FMX : l'entrée retombe sur ses initiales.
3. ~~**Icônes**~~ (`icon_b64`) — **fait**. Elles descendent telles quelles dans
la page, en URI `data:` : le moteur décode, y compris le SVG, que FMX ne
savait pas charger. Sans icône, l'entrée retombe sur son initiale.
4. ~~**`template`**~~ — **fait**, affiché comme *Type* dans le détail. Adapter
en plus les intitulés d'une carte bancaire reste à voir.
5. ~~**Tri par nom**~~ — **fait** dans `TVault.Search`. L'ordre de l'instantané
est celui de la base, donc arbitraire à l'œil.
6. **`TListView` à la place de `TListBox`** le jour où la reconstruction à
chaque frappe se voit. Marqué `ponytail:` dans le code, pas avant.
6. **Liste virtuelle** le jour où la reconstruction à chaque frappe se voit. Le
`innerHTML` complet est refait à chaque caractère ; sur quelques centaines
d'entrées c'est imperceptible. Marqué `ponytail:` dans la page, pas avant.
---
## 3 bis. Deux questions ouvertes sur l'interface
## 3 bis. ~~Faudrait-il des composants Delphi du tout ?~~ — TRANCHÉ le 2026-08-17
**Le thème n'est pas encore celui de la recherche globale.** Le bleu et la
pilule ont été repris, pas le reste : espacements, élévation, densité. À
reprendre capture en main plutôt qu'au jugé.
**Non. Il n'en reste aucun.** Les trois écrans sont une page HTML rendue par le
moteur du système ([web/app.html](web/app.html), servie par
[PMA.WebUI.pas](PMA.WebUI.pas)). Une sonde a décidé plutôt qu'un débat : la même
liste peinte par le moteur, en quarante lignes de CSS, rendait mieux que ce qui
avait coûté la journée à peindre à la main — et mettait l'arabe en forme seule.
**Et faudrait-il des composants Delphi du tout ?** Le poste Windows n'affiche
pas de contrôles natifs : il sert `js/app.js` et `css/style.css` dans un
WebView2. Le même montage est possible ici — `TWebBrowser` encapsule le WebView
d'Android — et il réglerait d'un coup ce qui a coûté le plus cher aujourd'hui :
plus de gabarits de style à contourner, plus d'ordre d'empilement à deviner,
une seule feuille de style pour les deux clients.
Ce que la migration a réglé, et qui revenait à chaque écran : un gabarit absent
du style chargé, un ordre d'alignement laissé au hasard, un `HitTest` qui avale
un appui, une vue native qui se peint par-dessus tout. Le dernier à partir a été
l'écran de déverrouillage, pour une raison précise : dans un `TEdit` Android le
curseur ne se place pas où on le touche, donc un jeton long est incorrigible.
Ce que ça demanderait, honnêtement :
**Le pont n'ouvre aucun port.** `evaluateJavascript` descend les données,
une navigation `cmd://` interceptée remonte les actions. Deux pièges y sont
enterrés, à ne pas re-découvrir :
- Un **pont** vers le Keystore, la biométrie et le presse-papiers, comme le
`cmd://` du poste. Ces trois-là resteront en Delphi de toute façon.
- Une **disposition mobile** dans le frontend, qui est écrit pour un écran
large. C'est le vrai coût, et il est dans `js/`, pas ici.
- Trancher où vit le HTML : servi par un serveur local comme sur le poste, ou
chargé depuis les ressources de l'application.
- FMX répond **toujours** au moteur qu'il n'a pas pris la navigation en charge.
Sur un schéma inconnu, le moteur essaie donc de la charger et remplace la page
par son écran d'erreur. D'où l'**iframe jetable**, où l'échec reste confiné.
- Le chargement de la page ne transporte pas l'encodage
(`loadDataWithBaseURL` reçoit `nil`), et `Navigate` refuse une URL `data:`.
**`app.html` doit donc rester en ASCII pur** ; les données, elles, passent par
une chaîne JNI et n'ont pas ce problème.
La crypto, elle, ne changerait pas de camp : `WebCrypto` fait déjà tout ce que
`PMA.Crypto` fait, et c'est le poste qui écrit le format.
**Les secrets ne traversent pas le pont.** La liste reçoit noms, sites et
identifiants — ce qui est déjà à l'écran. Copier depuis une ligne envoie un
**rang**, et Delphi relit le coffre chez lui. Seule l'entrée ouverte a ses
valeurs dans le tas JS, effacées par `PM.wipe` au verrouillage.
À décider avant d'investir davantage dans l'interface actuelle — chaque
correction d'affichage faite aujourd'hui serait perdue.
Reste en Delphi, et y restera : Keystore, biométrie, presse-papiers sensible,
`FLAG_SECURE`, réseau, déchiffrement.
**Ce que `js/` n'a pas donné.** Le CSS du poste est réutilisable presque tel
quel et c'est lui qui porte l'apparence ; `app.js` non — 12 000 lignes qui
supposent la session, le CSRF et l'API complète. La page du téléphone est
autonome.
**Le thème n'est pas encore exactement celui de la recherche globale.** Le
dégradé, les blocs translucides et les arrondis sont repris ; espacements,
élévation et densité restent au jugé. C'est maintenant du CSS, donc peu coûteux
à reprendre capture en main.
## 4. Le chemin d'écriture — le gros morceau