197 Commits

Author SHA1 Message Date
Thomas Fransolet
e967678dd2 Émission des événements vocaux — le vocal est un attribut, pas un canal
StatisticsService.track porte isVoice, qui pose "voice": true dans
VisitEvent.Metadata. Le flux lunettes n'émettait aucun VisitEvent : une visite
vocale ne produisait ni session, ni section vue, ni durée.

Le sectionView vocal part après la synthèse, pas avant : un déclenchement dont le
TTS échoue n'a rien fait entendre, le compter serait faux. Aucun événement par
question posée — elles sont déjà dans VisitorQuestion et remontent dans l'onglet
Guide IA ; les compter ici serait le même fait dans deux écrans.

isAutoTriggered suit le renommage serveur en isVisitorQuestion.

flutter analyze lib sans erreur, flutter build apk --debug --flavor dev vert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 14:32:56 +02:00
Thomas Fransolet
591775cd30 Une conversation, plusieurs surfaces — miroir vocal et conversationId
Le chat écrit, le vocal et le déclenchement proactif partagent désormais une
seule conversation, portée par VisitAppContext.assistant. Les trois
AssistantService séparés ont disparu : poser une question aux lunettes puis
ouvrir le chat donnait un guide qui ne savait rien de ce qu'on venait de
demander, et produisait deux lignes VisitorQuestion sans lien pour un visiteur
qui avait simplement changé de surface.

Le maxHistory du vocal (6) s'aligne sur 10 : deux surfaces qui partagent une
conversation ne peuvent pas la tronquer différemment selon le point d'entrée. La
concision vocale vient d'isVoice, qui change le prompt côté serveur.

Le vrai obstacle n'était pas l'affichage mais la forme du chat :
AssistantChatSheet gardait ses messages en List<Widget>, des bulles déjà
construites. On ne rejoue pas une conversation à partir de widgets, et un tour
vocal survenu pendant que la feuille était fermée n'aurait jamais pu y entrer. Le
service porte maintenant les tours en données et notifie ses écouteurs.

Deux listes, délibérément : celle envoyée au modèle et celle affichée ne
coïncident pas. Un message d'erreur se montre sans repartir au guide, et le
prompt d'un déclenchement proactif part au guide sans jamais s'afficher — seule
sa réponse apparaît, marquée « À voix haute ». Sans ce marquage, le visiteur
trouverait dans son chat des messages qu'il n'a jamais tapés.

conversationId est enfin envoyé, et renouvelé quand la conversation est vidée :
sinon la visite entière d'un visiteur n'en formerait qu'une.

flutter analyze lib sans erreur, flutter build apk --debug --flavor dev vert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 13:39:33 +02:00
Thomas Fransolet
6e6b40e185 Le mode proactif marque ses tours comme déclenchés par le système
AssistantService.chat porte isAutoTriggered, et geo_beacon_trigger_service le
passe à true. Sans lui, le prompt que le service s'écrit à lui-même atterrissait
dans VisitorQuestion, donc dans « Ce que demandent vos visiteurs », et gonflait
le bloc des questions sans réponse. Les jetons restent comptés côté serveur.

C'était le dernier bloquant avant d'activer le mode chez un client.

flutter analyze lib sans erreur, flutter build apk --debug --flavor dev vert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 13:14:17 +02:00
Thomas Fransolet
e9e68942c9 Proactif câblé, M3 fermé, voix du CMS honorée, et trois services morts supprimés
Déclenchement proactif (lot F) — quatre branchements : la garde, le cycle de
vie accroché à VoiceController, les points GPS peuplés depuis la configuration,
et un réglage visiteur.

⚠️ La garde recommandée par le plan aurait coûté de l'argent. _trigger appelle
le LLM d'abord et ne parle qu'ensuite via activeVoiceOrchestrator?.ttsEngine,
dont le ?. avale le cas « aucun mode vocal actif ». Avec proactiveModeEnabled
seul, un visiteur traversant une zone avec l'app en poche et le vocal éteint
consommait des jetons Gemini facturés au client pour une phrase que personne
n'entend. La garde interroge l'orchestrateur : la vraie condition n'est pas
« quel matériel » mais « y a-t-il quelqu'un pour écouter ».

Il n'y avait pas de troisième mode à inventer : VoiceMode.voiceOnly existe déjà
et construit le même orchestrateur que le mode lunettes. Le proactif est donc un
sous-réglage, pas une tuile. glassesEnabled est supprimé, ses trois usages
étaient morts — dont une pastille « Lunettes / Déconnecté » jamais affichée.

M3 — meterZoneGPS devient le rayon par section, la constante n'étant plus qu'un
défaut. Deux pièges de format vérifiés : currentSections porte des maps JSON
brutes, pas des DTO, et latitude/longitude y sont des chaînes.

Voix du guide — le sélecteur Viva/Marco de manager-app écrivait dans le vide :
Instance.GuideVoiceId n'était lu nulle part ici, l'app utilisant une constante
de build dont le défaut était Algieba, une voix que personne n'a écoutée. Même
forme que W1. Et aucun APK ne parlait avec la voix du produit : GeminiTtsEngine
n'est choisi que si GEMINI_API_KEY est injectée, ce qui n'était fait nulle part,
donc repli silencieux sur la voix système. Le repli reste le défaut — les tests
ne coûtent alors ni jetons ni argent — mais il s'annonce dans les logs.

Code mort supprimé : wake_word_service.dart, glasses_qr_scanner_service.dart et
glasses_tts_service.dart, les ancêtres de Services/Glasses/. Ils portaient les 4
erreurs kElevenLabs* et l'APK se construisait quand même, personne ne les
important. flutter analyze lib rend désormais zéro erreur.
⚠️ android/.../WakeWordService.kt est un homonyme bien vivant, non touché.
impl/elevenlabs_tts_engine.dart est conservé comme option.

flutter build apk --debug --flavor dev : vert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 11:57:44 +02:00
Thomas Fransolet
55869e025c D2 : borner la reprise des .unknown à un seul essai
Complète d5f3686, qui rendait la reprise illimitée : un type MIME réellement
absent de la table se serait re-téléchargé à chaque visite pour se réécrire en
.unknown, en boucle, sur le réseau mobile du visiteur.

La date nulle sert de borne — elle ne vaut que pour les fichiers écrits avant
D2, donc la reprise ne joue qu'une fois. Déduire l'extension de l'URL en repli
n'est pas possible : une URL Firebase n'en porte pas.

flutter analyze : aucune erreur sur le fichier.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:50:40 +02:00
Thomas Fransolet
d5f36865b6 D2 : re-télécharger une ressource périmée, base locale v3 vers v4
Le filtre incrémental testait la présence du fichier, jamais sa version.

La prémisse d'origine était fausse, et ça change ce que le correctif répare :
« une image remplacée dans le CMS ne remonte jamais » n'existe pas, parce que
Upload appelle GenerateHexId() à chaque téléversement — remplacer une image
produit un nouvel id, donc une nouvelle URL, que l'ancien filtre téléchargeait
déjà.

Le vrai cas de péremption vient d'être créé par D3 : les MP3 déjà présents sur
les devices y sont en <id>.unknown, et « le fichier est présent » les déclarait
à jour. Sans D2, D3 ne réparait que les installations neuves. isResourceOutdated
traite donc .unknown comme absent.

Deux pièges tranchés en écrivant. La montée v4 laisse les dates existantes à
NULL et les considère à jour : backfiller à zéro aurait fait re-télécharger
l'intégralité des visites de tous les visiteurs sur leur réseau mobile, au
premier lancement. Et la boucle en masse héritée de D1 écrasait la date que la
boucle de téléchargement venait d'écrire, DatabaseHelper.insert faisant un
UPDATE de la ligne entière quand l'id existe ; pour un téléchargement échoué,
c'est l'ancienne date locale qui est conservée, jamais celle du serveur.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:47:16 +02:00
Thomas Fransolet
40c2e618c5 K5 : outillage Android aligné, les 3 flavors construisent
La prémisse du lot était périmée. Trois documents annonçaient un
`flutter build apk` en échec côté Gradle/NDK, revérifié le 11/08 : les
trois flavors (dev, mdlf, fortsaintheribert) construisent, exit 0.

La config Android de ce repo était déjà à niveau — Gradle 8.11.1, AGP
8.9.0, -Xmx4096M, enableJetifier=false, aucun forçage androidx.lifecycle.
Les dix crans du 12/08 ont amené tablet-app jusqu'à mymuseum ; il n'y
avait pas la même migration à refaire ici. Le repo qui a servi de modèle
au portage K2 n'avait pas de raison d'être en retard d'outillage sur
celui qui le copiait.

Restaient les deux avertissements du build :

- NDK 27.0.12077973 -> 28.2.13676358, réclamé nommément par speech_to_text
- Kotlin 2.1.0 -> 2.3.10, sous le seuil 2.2.20 annoncé comme rupture par
  Flutter. C'est la version de tablet-app : un alignement, pas une
  version neuve introduite dans le projet.

Six builds — les trois flavors avant, les trois après. APK de 382 à 349 Mo.

Non pris volontairement : Kotlin réglé, Flutter réclame Gradle 8.14.0 et
AGP 8.11.1. C'est du terrain neuf pour les deux repos (tablet-app est à
8.11.1/8.9.1, mêmes avertissements latents) — le faire ici seul désaligne
les deux apps au lieu de les aligner. À faire d'un bloc sur les deux, ou
pas du tout.

Débloque D0 / test-plan §21 sur device, donc la mesure des bugs offline
D2-D5 et la confirmation du volet visiteur de D1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 14:18:35 +02:00
Thomas Fransolet
dccf211e6f D1 : enregistrer les ressources de la charge au lieu de les redécouvrir
Le bloc commenté parsait section.data type par type pour retrouver les
ressources à télécharger. Il n'y a plus rien à redécouvrir : le serveur
collecte désormais via GetReferencedResourceIds() et met toutes les
ressources référencées dans la charge d'export.

Répare aussi la purge des fichiers obsolètes : elle est pilotée par
usedImageOrAudioIds, qui ne contenait jusqu'ici que les images de sections —
tout le reste était donc considéré comme inutilisé.

Un nouveau type de section est couvert sans toucher à ce fichier.

flutter analyze sans erreur. ⚠️ Non vérifiable par un build : l'APK ne compile
pas (Gradle/NDK). À confirmer sur device au §21 du plan de test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 16:57:22 +02:00
Thomas Fransolet
d237987889 Lot E : rendu PDF des médias d'étape, et QuestionType nommé
Le cas PDF n'était traité nulle part : un PDF tombait dans le `default` et
affichait "Not supported type".

⚠️ Le correctif ne va pas dans showElementForResource comme l'annonçait le
plan : cette fonction fait un `return CachedCustomResource(...)` avant son
switch, donc tout son switch est du code mort. Le vrai dispatcher est
CachedCustomResource, et il en a deux — ressource distante et fichier local
déjà téléchargé pour l'offline. Les deux sont traités. Le cas distant doit
télécharger avant d'afficher, PDFView n'acceptant qu'un chemin de fichier.

QuestionType : _kindOf comparait des entiers bruts, remplacé par les alias
nommés du client.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 15:31:07 +02:00
Thomas Fransolet
ec1490d964 Suppression du déclencheur de génération du client API
lib/api/openApiTest.dart portait une annotation @Openapi générant, depuis
le swagger local de ce repo, un package manager_api_new dans le repo —
alors que le pubspec consomme celui de manager-app par `path:`. Un
build_runner lancé ici aurait donc créé un second client divergent.

Importé nulle part, et porteur d'une des 5 erreurs Dart du repo
(extends_non_class). Après suppression : 720 → 718 issues, 5 → 4 erreurs,
les 4 restantes étant les constantes ElevenLabs de la branche Ray-Ban,
préexistantes et hors du graphe de main.dart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 12:12:23 +02:00
Thomas Fransolet
af44927d4a Assistant IA aligné sur le web + parcours guidés + centrage de carte
Assistant
  AssistantChatSheet.dart (+252), Helpers/assistantSuggestions.dart,
  Services/assistantService.dart — même comportement et mêmes suggestions que
  visitapp-web, dérivées du contenu réel.

Parcours guidés
  guided_path_content_progression_page (+72), guided_path_map_progression_page (+39),
  parcours_page : alignés sur les 3 questions de progression qui remplacent les
  9 booléens côté manager-app.

Carte
  Helpers/mapCenter.dart + les trois vues (flutter_map, google_map, map_box) et
  marker_view : centrage et icônes honorés.

Fix du build
  guided_step_challenge.dart:83 — typage explicite. Avec le // @dart=2.18 de
  manager_api_new côté manager-app, c'est ce qui débloque flutter build apk.

flutter build apk .
Reste ouvert : M3 — meterZoneGPS toujours ignoré, une constante en dur à 100 m
remplace le rayon configuré par section.
2026-08-09 22:15:26 +02:00
Thomas Fransolet
0f2b4ed6bd multi wakeword + misc 2026-07-17 15:23:12 +02:00
Thomas Fransolet
c6526046c8 Working flow also in background ! With custom wakeword working (hey visit and hey viva). flow llm working + take photo (not stored for now) + scan qr code working (need to be tested but the issue was llm config in backend) 2026-06-04 17:00:43 +02:00
Thomas Fransolet
2701f4c963 Remove useless local manager api folder generation 2026-03-26 16:20:05 +01:00
Thomas Fransolet
bdabfad92e added launch screen + update in ai chat + notifs (to be tested) + EventAgenda layout (to be tested) + home 3.0 update (event) + event mode layout (to be tested) + guided Path layout (to be tested) + map parcours (to be tested) + update readme 2026-03-25 17:47:10 +01:00
Thomas Fransolet
e8ef78d0e2 Update fix after service generation + need test geoloc ! + need test for connexion with apikey also ! + check where http needed.. need to pass by service generation 2026-03-13 17:43:17 +01:00
Thomas Fransolet
538e677993 Update gradle, remove bluetooth beacon (gralde update etc..) + ai assistant (wip) + stats + layout update + clean repo (remove old release) + link to unique backend generation managerapp (TO BE TESTED) 2026-03-13 15:15:18 +01:00
Thomas Fransolet
c6599e13c9 Updates visit name to configuration + scan + misc 2025-07-09 17:45:27 +02:00
Thomas Fransolet
959b494b12 Support also mymuseum url 2025-07-09 14:48:36 +02:00
Thomas Fransolet
f0e41adace Test update scanner background color 2025-07-09 13:22:21 +02:00
Thomas Fransolet
303e50a255 Menu done + article refonte wip 2025-07-04 17:21:17 +02:00
Thomas Fransolet
c50083b19f Agenda + misc for sub menu (pdf, agenda) 2025-07-03 17:37:24 +02:00
Thomas Fransolet
f07570d8ee Weather done 2025-07-02 17:11:02 +02:00
Thomas Fransolet
5e5d92a510 misc 2025-07-02 13:11:16 +02:00
Thomas Fransolet
b20a112eb2 Map working - (only google, mapContext issue on selected point) 2025-06-19 16:50:28 +02:00
Thomas Fransolet
4e9dc59df9 Slider ok, map wip + update gradle etc + qr scanner to mobile scanner 2025-06-18 18:00:29 +02:00
Thomas Fransolet
7aca0638ce Puzzle working + slider wip + misc 2025-06-12 17:27:53 +02:00
Thomas Fransolet
bddde86974 Working Web, Pdf and Video type + misc and clean code 2025-06-11 17:26:36 +02:00
Thomas Fransolet
4946247812 Misc + clean code logic future for configurations and sections 2025-06-11 12:04:01 +02:00
Thomas Fransolet
9c5ae56549 misc + wip load section (not working) 2025-06-10 16:51:48 +02:00
Thomas Fransolet
b7ca69162c Misc, update layout, nice main page + hero to configuration detail 2025-06-05 18:20:48 +02:00
Thomas Fransolet
878a2e4cf0 Wip version 3.0.0 2025-05-28 17:16:18 +02:00
Thomas Fransolet
53dff98388 WIP version 3.0.0 2025-05-28 14:08:32 +02:00
Thomas Fransolet
42d3e257b2 Reintegrate carousel slider (fix rename 5.0) 2025-02-26 13:56:27 +01:00
Thomas Fransolet
ffbeccec5d Fix overlay qr code + plugin apply update + fix audio future issue on dispose 2025-02-25 17:24:19 +01:00
Thomas Fransolet
05dd2dff52 appbundle fort 2024-12-05 17:05:09 +01:00
Thomas Fransolet
b04b699ad0 update readme 2024-10-17 14:50:01 +02:00
Thomas Fransolet
a73d27036c update to match ios bundle id 2024-10-17 14:49:51 +02:00
Thomas Fransolet
686a631c27 updated title for custom bar 2024-10-17 14:13:52 +02:00
Thomas Fransolet
8b88b50c1f Update download popup 2024-10-17 14:03:55 +02:00
Thomas Fransolet
44581c12c5 update build appId 2024-10-17 11:40:25 +02:00
Thomas Fransolet
679ed5d286 update title ellipsis 2024-10-17 11:13:22 +02:00
Thomas Fransolet
17ef37b45a Update icons (adaptive) 2024-10-17 11:01:32 +02:00
Thomas Fransolet
e5249795f3 update app label 2024-10-17 09:14:22 +02:00
Thomas Fransolet
ce085a731f icon test 2024-10-16 16:39:53 +02:00
Thomas Fransolet
19b715192a misc update 2024-10-16 16:22:11 +02:00
Thomas Fransolet
077b373052 manifest and plist + added readme 2024-10-16 14:40:32 +02:00
Thomas Fransolet
157fefc2af update icon and instanceId 2024-10-16 14:34:18 +02:00
Thomas Fransolet
91d83806a1 Remove request background for google play 2024-08-01 09:56:46 +02:00
Thomas Fransolet
54310a3d54 appbundle 2024-07-12 08:47:36 +02:00