• v1.4.0 Stable

    Siphonight released this 2026-09-06 22:28:18 +02:00 | 48 commits to main since this release

    Ajouté

    • Modèle Transfem Science reconstruit sur la méta-analyse officielle
      (https://transfemscience.org/articles/injectable-e2-meta-analysis/) :
      la courbe TFS n'est plus dérivée des tables horaires du tableur — elle
      est désormais la forme close exacte du modèle à 3 compartiments (V3C)
      publié par le simulateur TFS, avec les paramètres D/k1/k2/k3 des 7 esters
      (EV, EEn, EU, EB, EC huile, EC suspension, PEP). PICS DE RÉFÉRENCE
      REPRODUITS À ~1 % (épinglés par TransfemScienceModelsTest) : EV 295
      pg/mL @ 2,1 j ; EEn 160 @ 6,5 j ; EB 971 @ 0,65 j ; EC 155 @ 4,3 j ;
      EC susp. 241 @ 1,2 j ; PEP 34 @ 32,5 mg @ 18 j ; AUC et état d'équilibre
      EV 5 mg/7 j (Cmax 384 / Cmin 142 / Cavg 269) conformes à la Figure 11.
      Avantages : plus de plancher d'arrondi 0,01 en queue de table, pas de
      coupure à 8001 h (extrapolation exacte), coupure moteur à 10 demi-vies
      terminales.
    • Nouveaux esters : benzoate (EB), cypionate huile (EC), cypionate
      suspension aqueuse (ECS) et polyestradiol phosphate (PEP) — 4 presets
      TFS, override d'ester par dose étendu (la liste suit le modèle du
      traitement : TFS = les 7 esters, Estrannaise = EV/EU/EEn faute de tables
      ODS). PEP = biodisponibilité réduite, doses ~6,5× (cf article).
    • Rappels qui suivent la Posologie (fix #52, Corrigé ci-dessous) :
      la carte « Prochaine dose » de l'accueil passe par le même moteur que
      les alarmes.
    • 12 nouveaux tests (102 au total / 84 sans les données locales) :
      TransfemScienceModelsTest (pics, t½, AUC, équilibre de la Figure 11)
      et ReminderScheduleTest (grille Posologie, créneau manqué, fallback
      quotidien).

    Corrigé

    • Les rappels se déclenchaient TOUS LES JOURS sans tenir compte de
      l'intervalle entre prises (#52, remontée utilisateur : « je m'injecte
      tous les samedis à 18 h, je dois recevoir le rappel uniquement le
      samedi à 18 h ») : le calcul du prochain déclenchement ignorait doses et
      Posologie. Désormais, un traitement avec Posologie + historique sonne
      le jour du créneau à l'heure choisie (dernière dose + k × intervalle,
      créneaux passés sautés comme la prévision) ; sans Posologie ou sans
      historique → comportement quotidien inchangé. De plus, l'alarme suivante
      est reprogrammée après chaque notification et après « Pris »
      (les alarmes sont one-shot : la chaîne n'existait qu'au boot/au save).
    Downloads
  • v1.3.5 Stable

    Siphonight released this 2026-09-06 14:46:50 +02:00 | 49 commits to main since this release

    Corrigé

    • Création du calendrier d'agenda impossible (remontée via les logs de
      diagnostic — le mécanisme v1.3.1 a tout de suite nourri le diagnostic
      à distance : Sync adapters must specify an account and account type) :
      l'URI d'insertion CALLER_IS_SYNCADAPTER=true du calendrier local
      « HormoneTrack » n'embarquait pas ACCOUNT_NAME + ACCOUNT_TYPE —
      exigé par le CalendarProvider pour toute opération sync-adapter
      (CalendarEvents.ensureCalendar, §14 #50). Ces mêmes logs prouvent aussi
      que la permission agenda est désormais accordée (fix manifest v1.3.3 ✓)
      et que l'export des logs fonctionne sur le téléphone (fix #48 ✓) —
      la chaîne de diagnostic est opérationnelle.
    • Suppression d'événement d'agenda silencieusement manquée (#50 bis) :
      l'URI de DELETE avait le même défaut (CALLER_IS_SYNCADAPTER sans params
      account) → « switch OFF » + save loguait « supprimé » mais l'événement
      restait dans le provider. Fix : mêmes paramètres sur l'URI de delete.
      Validé émulateur : cycle complet ON→save→OFF→save = événement créé puis
      réellement supprimé (content query vide).
    • Événement d'agenda orphelin après tout re-save (#51) :
      TreatmentEditorScreen.buildTreatment() ne transmettait pas
      calendarEventId → l'id revenait à null à chaque sauvegarde : après le
      premier save, l'événement devenait définitivement orphelin (plus jamais
      supprimable/désactivable par l'app). L'id existant est désormais chargé à
      l'ouverture et conservé par le save.
    • Log « événement agenda supprimé » mensonger : imprimé aussi quand rien
      n'a été supprimé (switch désactivé, posologie absente, permission absente).
      Désormais trois messages distincts : « créé/mis à jour (id=…) »,
      « supprimé », « non activé (switch/posologie/permission) ».

    Ajouté

    • Validation émulateur de l'agenda end-to-end (recette §16.ter, permissions
      accordées via pm grant) : calendrier + événement récurrent créés et
      visibles dans le provider (content query).
    Downloads
  • v1.3.4 Stable

    Siphonight released this 2026-09-06 12:38:57 +02:00 | 50 commits to main since this release

    Corrigé

    • L'écran Doses faisait crasher l'app (remontée) : MissingFormatArgumentException: Format specifier '%3$d' — la string hrt_duration a TROIS placeholders
      (%1$d mois, %2$d jours, %3$d total) mais l'appel transmettait 2 arguments.
      Crash dès le premier affichage de l'écran Doses avec une donnée antérieure à
      aujourd'hui. Le bug est né en v1.3.1 (string + appel dans le même commit,
      jamais testés ensemble) et a survécu aux releases v1.3.1→v1.3.3. Fix : passer
      totalDays en 3ᵉ argument (cf §14 #47).
    • L'export des logs de diagnostic faisait crasher l'app (remontée répétée ;
      les « fixes » IO de v1.3.2 et v1.3.3 étaient corrects mais à côté du vrai
      problème) : le nom de fichier était construit via
      LocalDate.now().format(ofPattern("yyyyMMdd-HHmm")) — un LocalDate n'a pas
      de champ horaire → UnsupportedTemporalTypeException: Unsupported field: HourOfDay, levée SYNCHRONEMENT dans le onClick (thread UI) au tap sur
      « Exporter », avant même l'ouverture du gestionnaire de fichiers. L'export
      JSON fonctionnait car son pattern yyyyMMdd est valide pour un LocalDate.
      FIX : utilitaire ExportFileNames (pur, testé) — diagnosticLogFileName()
      utilise un LocalDateTime ; backupFileName() reste sur LocalDate.
      Cf §14 #48.
    • Lint StringFormatMatches (détecté en implantant le lint — nouveau filet
      de la v1.3.4) : la notification de rappel passait un Double à une %s.
      Fix : dose.toString() (comportement d'affichage inchangé, #49).

    Ajouté

    • Lint en filet bloquant : ./gradlew lint est désormais vert (it aurait
      attrapé dès v1.3.1 les deux crashs ci-dessus via StringFormatMatches).
      Les deux checks Compose 1.12+ théoriques (NonObservableLocale,
      LocalContextGetResourceValueCall) sont rétrogradés en warning via
      app/lint.xml (staleness de config, refonte i18n plus tard, cf §19/§20).
    • Recette reproductible : test manuel sur émulateur (documentée §16.ter) :
      émulateur + image ATD ou google_apis, seed de la DB du debug avec un backup
      JSON via le nouveau script scripts/seed-emulator.py (générique, sans
      aucune donnée embarquée), installation du APK release par-dessus (données
      conservées, même signature), pilotage par uiautomator dump + input tap,
      crashs via adb logcat -b crash. C'est cette recette qui a reproduit et
      confirmé les deux crashs ci-dessus ainsi que LEUR correction (flux SAF
      complet : picker → SAVE → fichier écrit → message de confirmation, sur
      l'APK release données réelles).
    • 3 nouveaux tests (ExportFileNamesTest, 90 au total / 72 sans les
      données locales) : épinglent le format des noms de fichiers d'export —
      auraient attrapé le bug #48 le jour même.
    Downloads
  • v1.3.3 Stable

    Siphonight released this 2026-09-06 11:24:22 +02:00 | 52 commits to main since this release

    Corrigé

    • Export des logs plantait TOUJOURS l'app (remontée ; le « fix » v1.3.2
      était insuffisant) : l'écriture était réimplémentée en inline au lieu de
      réutiliser l'IO éprouvée de l'export JSON, et les appels AppLog.log du
      callback étaient hors try/catch — une exception dans une coroutine à scope
      racine (CoroutineScope standalone) remonte au handler de la thread =
      crash du process. FIX : l'export passe désormais par
      BackupManager.writeBackup tel quel (le même code path que l'export
      JSON qui fonctionne sur le téléphone), tout le callback est gardé, et
      AppLog.log ne lève plus jamais d'exception (IO fichier avalée en interne,
      on perd au pire une ligne de journal). Feedback visible succès/échec
      (comme l'export JSON) + compteur de lignes rafraîchi après l'export.
    • Événements d'agenda inopérants depuis v1.3.0 : les permissions
      WRITE_CALENDAR / READ_CALENDAR n'étaient pas déclarées dans le manifest
      (jamais présentes dans tout l'historique git, bien que documentées §9) —
      la demande à l'exécution était donc refusée d'office et
      CalendarEvents lève SecurityException. Cause racine manquante des bugs
      « toggle agenda » « corrigés » en v1.3.1/v1.3.2 : la logique UI était
      correcte, il ne venait à l'esprit de personne que la déclaration manquait.
    • Métadonnées de version fausses : le bump de version n'avait jamais
      été commité — les tags v1.3.0, v1.3.1 et v1.3.2 contenaient tous
      versionCode = 14 / versionName = "1.3.0", donc les APK publiés
      affichaient « 1.3.0 » dans Paramètres et en titre du dialog « Nouveautés ».
      Désormais bumpé + commité avant chaque tag (checklist §16 étape 1).

    Technique

    • Doc de développement mise à jour (DB v3, targetSdk 36, fichiers de
      données de régression, bugs #43–#45) ; téléphone de test documenté :
      Google Pixel 9 /e/OS (AOSP, DocumentsUI standard — l'export JSON y
      fonctionne, l'export logs réutilise ce même path).
    • Compteur de tests inchangé : 87 (44 sans les données locales, gitignorées).
    Downloads
  • v1.3.2 Stable

    Siphonight released this 2026-09-06 10:41:34 +02:00 | 55 commits to main since this release

    Corrigé

    • Toggle de l'agenda : le switch ne s'activait pas (le résultat de la
      permission arrive ASYNCHRONE — le test synchrone juste après launch()
      était toujours faux). FIX : le callback active le switch ; Posologie
      désormais requise pour l'agenda (refus + message si absente) ;
      permission vérifiée RÉELLEMENT via ContextCompat au save (le flag
      remembered pouvait être faux après recomposition) ; journalisation
      AppLog à chaque étape.
    • Export des logs plantait l'app : réécrit avec le pattern éprouvé de
      l'export JSON (BackupManager) ; chaque étape journalisée dans AppLog.
    • Dialog « Nouveautés » réapparaissait à chaque réouverture : la version
      vue est désormais mémorisée AVANT l'affichage (et non après) + AppLog
      pour diagnostiquer si ça se reproduit.
    • Titre du dialog « Nouveautés » : affiche la version de l'APP
      (BuildConfig.VERSION_NAME) — si l'APK installé est 1.3.0, le titre
      montre 1.3.0 même si le contenu parle d'une version plus récente
      (l'asset changelog.md peut contenir des sections plus récentes si
      l'APK a été reconstruit après coup). Installer le dernier APK
      (HormoneTrack-v1.3.2-release.apk) pour avoir la version correcte.
    Downloads
  • v1.3.1 Stable

    Siphonight released this 2026-09-06 10:16:51 +02:00 | 59 commits to main since this release

    Ajouté

    • En-tête « temps sous THS » sur la page Doses : depuis la 1re prise
      enregistrée, en jours totaux et décomposition mois/jours (mois = 30 j,
      estimation documentée).
    • Logs de diagnostic (v1.3.1) : journal horodaté des événements notables
      (agenda, rappels, import/export, erreurs), buffer circulaire de 500 lignes,
      persisté dans filesDir/debug-log.txt ; export (SAF) et effacement depuis
      Paramètres. Objectif : debug à distance via les logs joints aux retours.
    • 9 nouveaux tests (87 au total) : AppLog (formatage, buffer circulaire) et
      HrtDuration (jours, décomposition mois/jours).

    Corrigé

    • Toggle de l'agenda ne s'activait pas (bug remonté) : le résultat de la
      permission arrive ASYNCHRONE — le test synchrone juste après launch()
      était toujours faux → le switch rebondissait sans s'activer et sans
      feedback. FIX : le callback active le switch ; feedback visible (hint) et
      journalisation (AppLog).
    Downloads
  • v1.3.0 Stable

    Siphonight released this 2026-09-06 08:30:32 +02:00 | 65 commits to main since this release

    Ajouté

    • Dialog « Nouveautés » : après chaque mise à jour (et à la première
      installation), l'app affiche le changelog des versions non vues dans une
      fenêtre fermable — ne réapparaît pas avant la prochaine mise à jour
      (version vue mémorisée). Contenu = docs/CHANGELOG.md embarqué en asset,
      synchronisé automatiquement à chaque build (tâche Gradle copyChangelog).
    • Événements d'agenda récurrents : dans l'éditeur de traitement, sous
      « Rappels », un switch « Événement d'agenda récurrent » crée un événement
      dans un calendrier local dédié « HormoneTrack » (visible dans l'agenda du
      téléphone) avec répétition RRULE dérivée de la Posologie (tous les N
      jours, arrondi demi-supérieur). Permission agenda demandée à l'activation ;
      suppression/recréation automatique au save.
    • Paramètres : version installée + lien cliquable vers les releases Gitea
      (télécharger les APK sans attendre le rappel de mise à jour).
    • 11 nouveaux tests (78 au total) : ChangelogHelper (8 : comparaison SemVer
      numérique 1.2.9 < 1.2.10 — lexicographique aurait tort, extraction de
      sections, première installation), CalendarRruleTest (3 : RRULE, arrondi
      demi-supérieur — kotlin.math.round arrondit les ties vers l'entier PAIR
      (6,5 → 6)
      , piège documenté).
    Downloads
  • v1.2.10 Stable

    Siphonight released this 2026-09-05 23:36:32 +02:00 | 69 commits to main since this release

    Corrigé

    • Sens des boutons de zoom inversé (retour utilisateur) : convention
      carte — « + » = zoom avant (fenêtre plus courte, plus de détail) et
      « − » = zoom arrière (fenêtre plus longue, plus de temps). Avant,
      le « + » dézoomait (montrait plus de temps) — pas intuitif. Le pinch
      (écarter = zoom avant) était déjà correct.
    Downloads
  • v1.2.9 Stable

    Siphonight released this 2026-09-05 22:51:28 +02:00 | 71 commits to main since this release

    Ajouté

    • Zoom du graphique de simulation : pinch à 2 doigts et boutons − / +
      (accessibilité), plage bornée 6 h → 300 j ; le point focal du pinch reste
      fixe dans le temps ; échantillonnage adaptatif (15 min ≤ 12 h, 30 min ≤
      24 h, sinon 1 h — courbes lisses à fort zoom) ; labels X adaptatifs
      (1 h / 3 h). Un seul gestionnaire de gestes gère pan + zoom (pas de
      conflit de consommation).
    • README : disclaimer IA en en-tête — projet développé avec l'IA,
      contribution humaine essentielle (feedback, retours utilisateur, suggestions) ;
      mention factuelle reprise en §1/§2 de la doc de développement.
    • 3 tests stepForRange (67 au total).
    Downloads
  • v1.2.8 Stable

    Siphonight released this 2026-09-05 22:24:25 +02:00 | 74 commits to main since this release

    Modifié

    • « Fréquence d'injection » renommé « Posologie » (section Traitements) :
      le terme « fréquence d'injection » n'avait pas de sens pour les prises
      d'hormones non injectables (gel, patch, oral). L'astuce d'intervalle est
      inchangée ; les textes d'aide disent désormais « dernière prise
      enregistrée » au lieu de « dernière injection » (EN : « Dosage »).
    Downloads