diff --git a/android-client/PLAN.md b/android-client/PLAN.md index d9be15c..63f6cac 100644 --- a/android-client/PLAN.md +++ b/android-client/PLAN.md @@ -708,6 +708,27 @@ save: published, new sha e14eabcf... 48 ms là où le journal disait 4395. Ce qui reste dans l'attente est le GET et le PUT vers le dépôt — plus rien de calculatoire. +### Ce que coûte réellement un enregistrement — mesuré 2026-08-21 + +``` +save: publishing against the snapshot in hand +save: decrypt+patch in 23 ms +save: re-encrypt in 23 ms +save: PUT 267700 chars in 2745 ms +``` + +Le calcul pèse 46 ms. **Tout le reste est le conteneur qui monte** : 267 Ko à +chaque écriture, dont l'essentiel est une pièce jointe de 116 Ko. C'est le +plancher de ce format — le conteneur est monolithique, il n'y a pas de +« publier seulement l'entrée modifiée ». + +Le tirage préalable, lui, a disparu : il coûtait 3,2 s et ne servait qu'à +s'assurer de modifier la dernière version publiée, ce que le sha prouve +gratuitement. **Conséquence : le chemin 409 est devenu porteur.** C'est lui, +désormais, qui garantit qu'un enregistrement n'écrase pas un autre appareil, +et il n'a toujours jamais tourné. Le provoquer : synchroniser depuis le poste, +puis enregistrer depuis le téléphone sans synchroniser d'abord. + ### Ce qui devient facultatif Sans dépôt configuré, *Sync* n'a rien à faire : les réglages du serveur diff --git a/android-client/web/app.html b/android-client/web/app.html index b1a1c87..6e1a041 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -67,9 +67,15 @@ body.on-detail #list { transform: translateX(-22%); } body.on-detail #detail { transform: translateX(0); } + /* LE CLAVIER RECOUVRE LA PAGE, IL NE LA RETRECIT PAS. Le cadre est cloue a + l'ecran entier, donc quand le clavier monte le contenu ne deborde de rien + et le tiers du bas devient inatteignable : le champ mot de passe du + formulaire ne se voyait qu'en repliant le clavier. Reserver dessous la + hauteur qu'il occupe rend au panneau de quoi defiler. */ .scroll { flex: 1; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; - overscroll-behavior: contain; padding: 0 12px 16px; } + overscroll-behavior: contain; + padding: 0 12px calc(16px + var(--kb, 0px)); } /* --- barre de recherche ------------------------------------------------ */ .top { padding: 10px 12px 6px; display: flex; gap: 8px; } @@ -669,6 +675,31 @@ addEventListener('scroll', function (ev) { if (box && box.scrollLeft && box.id !== 'folders') box.scrollLeft = 0; }, true); +// LE CLAVIER RECOUVRE LA PAGE, IL NE LA RETRECIT PAS. +// +// Le cadre est cloue a l'ecran entier (position:fixed, inset:0) et le moteur ne +// le redimensionne pas quand le clavier monte : la page garde sa hauteur, le +// clavier passe par-dessus, et le tiers du bas devient inatteignable. Rien ne +// depassait, donc rien ne defilait - le champ mot de passe du formulaire ne se +// voyait qu'en repliant le clavier. +// +// visualViewport donne la hauteur REELLEMENT visible. La reporter sur le corps +// retrecit les vues, le panneau defilant retrouve du contenu en trop, et le +// moteur peut de nouveau amener a l'ecran le champ qui prend le focus. +if (window.visualViewport) { + var vv = window.visualViewport; + // Ce que le clavier RECOUVRE, en pixels. Zero quand il est replie - et zero + // aussi si le moteur retrecit reellement la fenetre, auquel cas le panneau + // deborde tout seul et n'a besoin de rien. La meme mesure repond donc juste + // dans les deux cas, sans qu'on ait a savoir lequel s'applique. + var measureKeyboard = function () { + var hidden = Math.max(0, Math.round(window.innerHeight - vv.height)); + document.documentElement.style.setProperty('--kb', hidden + 'px'); + }; + vv.addEventListener('resize', measureKeyboard); + measureKeyboard(); +} + // AUCUN CHAMP D'UNE VUE AU REPOS NE GARDE LE FOCUS. // // Meme origine que le glissement ci-dessus. La touche de validation du clavier