diff --git a/android-client/PLAN.md b/android-client/PLAN.md index 9c8ca3a..fcb96ef 100644 --- a/android-client/PLAN.md +++ b/android-client/PLAN.md @@ -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. -## 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