v1.7.0 : unités des axes du graphique (portage Android) + note auto-backup

- chart-canvas.js : pg/mL (E2, axe gauche) / ng/mL (T, axe droit) au
  sommet des colonnes de labels — miroir exact du fix Android (padTop
  élargi 12 → 26 px). Universelles, PAS des clés i18n.
- WEB_VERSION 1.7.0 (versions sync Android) ; E2E assertions version.
- CHANGELOG [1.7.0] : unités portées ; auto-backup Android NON porté
  (structurellement impossible côté navigateur — cf §12 Limites :
  pas d'OPEN_DOCUMENT_TREE persisté + WorkManager ; l'export/import
  manuel couvre la même donnée).
- Doc : §12 limites, README statut. check.sh vert (140 tests + E2E +
  garde de parité §3.bis).
This commit is contained in:
Siphonight 2026-09-16 19:53:41 +02:00
parent 524f122f15
commit d822af2dd2
6 changed files with 36 additions and 7 deletions

View File

@ -17,8 +17,9 @@
> Fie-toi toujours à tes analyses de sang et aux consignes de ton
> endocrinologue.
- **Statut** : web v1.6.1 — parité fonctionnelle avec l'Android v1.6.0
(+ fix web-only : options du graphique préservées entre re-rendus) ·
- **Statut** : web v1.7.0 — parité fonctionnelle avec l'Android v1.7.0
(unités des axes portées ; l'auto-backup journalier Android est
structurellement non porté, cf §12 — l'export manuel couvre la donnée) ·
**140 tests verts** · E2E navigateur ✅ · conteneur testé en
configuration durcie ✅ · lint/i18n ✅
- **Journal des versions web** : [docs/CHANGELOG.md](docs/CHANGELOG.md)

View File

@ -5,6 +5,20 @@
> section la plus récente EN PREMIER ; ce fichier est lu par le dialog
> « Nouveautés » de l'app web (fetch `docs/CHANGELOG.md`).
## [1.7.0] — 2026-09-13
### Unités des axes du graphique — portage de l'Android v1.7.0 (versions sync)
- **pg/mL** (E2, axe gauche) et **ng/mL** (T, axe droit) affichées au sommet
des colonnes de labels du graphique de simulation — miroir exact du fix
Android (padTop élargi 12 → 26 px, texte gris dans la couleur des labels).
- Universelles, PAS des clés i18n (déjà en dur dans les légendes).
> Note de parité : la **sauvegarde automatique quotidienne** de l'Android
> v1.7.0 n'est PAS portée — le navigateur ne peut pas écrire périodiquement
> dans un dossier arbitraire sans intervention (voir §12 Limites) ;
> l'export/import manuel du backup couvre la même donnée.
## [1.6.1] — 2026-09-13
### Corrigé — les options du graphique se réinitialisaient « toutes seules »

View File

@ -748,6 +748,12 @@ Structurels (plateforme), pas des bugs :
serveur de push (contre la règle « 100 % local, aucun serveur »).
- **Agenda récurrent** : impossible (pas de CalendarProvider). L'éditeur
affiche une note explicative ; `calendarEventId` reste null.
- **Auto-backup journalier** (v1.7.0 Android) : non porté — le navigateur
ne peut pas écrire périodiquement dans un dossier arbitraire sans
intervention (pas d'équivalent d'ACTION_OPEN_DOCUMENT_TREE persisté +
WorkManager ; File System Access API : Chromium seul, et exige une
re-validation de permission). La donnée est couverte par l'export/import
MANUEL du backup (même format, interchangeable avec l'Android).
- **Montre** : hors sujet navigateur.
- **Fuseau système** : si le navigateur change de fuseau (voyage), les
labels X suivent le fuseau CHOISI (Paramètres) ou le nouveau fuseau

View File

@ -75,10 +75,13 @@ export function drawChart(canvas, series, e2Labs, tLabs, options, forecastDoses
const allPoints = series.flatMap((s) => s.points);
if (allPoints.length < 2) return;
// Marges (px) — miroir padLeft/padRight/padTop/padBottom (42/42/12/26 dp)
// Marges (px) — miroir padLeft/padRight/padTop/padBottom (42/42/26/26 dp).
// v1.7.0 : padTop élargi (12 → 26) pour loger les UNITÉS d'axe au sommet
// des colonnes de labels (portage de l'Android v1.7.0 — remontée « on
// n'a jamais ajouté les unités » : pg/mL à gauche, ng/mL à droite).
const padLeft = 42;
const padRight = 42;
const padTop = 12;
const padTop = 26;
const padBottom = 26;
const w = cssW - padLeft - padRight;
const h = cssH - padTop - padBottom;
@ -120,11 +123,16 @@ export function drawChart(canvas, series, e2Labs, tLabs, options, forecastDoses
ctx.font = '10px system-ui, sans-serif';
ctx.textAlign = 'right';
ctx.textBaseline = 'middle';
// Unités des axes (v1.7.0, portage Android) : au sommet de chaque colonne
// de labels, au-dessus du premier tick — universelles, PAS des clés i18n
// (elles sont déjà en dur dans les légendes du chart).
ctx.fillText('pg/mL', padLeft - 6, padTop - 6);
for (let i = 0; i <= 4; i++) {
ctx.fillText(formatValue((e2Max * i) / 4), padLeft - 6, padTop + h * (1 - i / 4));
}
if (options.showT && series.some((s) => s.tStyle)) {
ctx.textAlign = 'left';
ctx.fillText('ng/mL', padLeft + w + 6, padTop - 6);
for (let i = 0; i <= 4; i++) {
ctx.fillText(formatValue((tMax * i) / 4), padLeft + w + 6, padTop + h * (1 - i / 4));
}

View File

@ -31,7 +31,7 @@ import { el, showDialog, field, switchRow, filterChip, toast } from './component
* (APK + web au MÊME numéro, tags appariés `vX.Y.Z` + `vX.Y.Z-web`).
* v1.4.10 = portage initial de l'Android v1.4.10.
*/
export const WEB_VERSION = '1.6.1';
export const WEB_VERSION = '1.7.0';
/** Parse un champ numérique FR (virgule → point) ; null si vide/invalide. */
function parseNumOrNull(text) {

View File

@ -131,7 +131,7 @@ async function main() {
ok(dialog !== null, 'dialog « Nouveautés » au premier lancement (markdown rendu)');
if (dialog) {
const dlgText = await dialog.textContent();
ok(dlgText.includes('Version 1.6.1'), 'dialog : section de la version courante');
ok(dlgText.includes('Version 1.7.0'), 'dialog : section de la version courante');
const hasRenderedMd = await dialog.$('.md-body h3, .md-body strong');
ok(hasRenderedMd !== null, 'dialog : markdown RENDU (titres/gras), pas de brut');
await page.click('.dialog .actions button');
@ -282,7 +282,7 @@ async function main() {
await page.waitForTimeout(300);
text = await page.textContent('main.content');
ok(text.includes('Langue'), 'Paramètres : carte langue');
ok(text.includes('Version 1.6.1 (web)'), 'Paramètres : version affichée');
ok(text.includes('Version 1.7.0 (web)'), 'Paramètres : version affichée');
ok(text.includes('100 % local'), 'Paramètres : note vie privée');
await page.screenshot({ path: join(SHOTS, 'e2e-settings.png') });