import 'package:flutter/material.dart'; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Models/articleRead.dart'; import 'package:mymuseum_visitapp/Services/assistantService.dart'; import 'package:mymuseum_visitapp/Services/statisticsService.dart'; import 'package:mymuseum_visitapp/Models/beaconSection.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; import 'package:mymuseum_visitapp/client.dart'; import 'package:mymuseum_visitapp/constants.dart'; class VisitAppContext with ChangeNotifier { Client clientAPI = Client(kApiBaseUrl); String? id = ""; String? language = ""; String? instanceId = kInstanceId; String? apiKey; List? configurations; ConfigurationDTO? configuration; List? sectionIds; // Use to valid QR code found List? beaconSections; List? currentSections; List readSections = []; bool isContentCurrentlyShown = false; bool isScanningBeacons = false; bool isScanBeaconAlreadyAllowed = false; bool isMaximizeTextSize = false; Size? puzzleSize; List audiosNotWorking = []; ApplicationInstanceDTO? applicationInstanceDTO; // null = assistant non activé StatisticsService? statisticsService; AssistantService? _assistant; /// **La** conversation du visiteur avec le guide, partagée par le chat écrit, le /// vocal et le déclenchement proactif. Créée à la première utilisation. /// /// ⚠️ Chaque surface construisait auparavant la sienne : changer de surface donnait /// un guide amnésique et coupait la conversation en deux côté serveur. Ne pas /// réintroduire de `AssistantService(...)` ailleurs — c'est ce getter, ou rien. AssistantService get assistant => _assistant ??= AssistantService(visitAppContext: this); /// Retourne l'AppConfigurationLink de l'instance mobile pour la configuration courante. /// Contient roundedValue, isSectionImageBackground, etc. AppConfigurationLink? get currentAppConfigurationLink { if (applicationInstanceDTO == null || configuration == null) return null; return applicationInstanceDTO!.configurations ?.where((c) => c.configurationId == configuration!.id) .firstOrNull; } bool? isAdmin = false; bool? isAllLanguages = false; bool notificationsEnabled = true; /// Voix du guide choisie par le client dans manager-app (`Sulafat` = Viva, féminine ; /// `Umbriel` = Marco, masculine). Null tant que l'instance n'a pas été lue. /// /// ⚠️ C'est **le CMS qui décide**, pas le build : `kGeminiTtsVoice` n'est plus qu'un /// repli. Le sélecteur existait dans manager-app et la colonne côté serveur depuis le /// 07/08, mais rien ne les lisait ici — le choix du client était enregistré et ignoré. String? guideVoiceId; /// Mode proactif : l'assistant parle automatiquement à l'approche d'un beacon /// ou d'une zone géographique, sans que le visiteur pose de question. /// /// Indépendant du support : vaut pour les lunettes comme pour des écouteurs. /// C'est un **sous-réglage** du mode vocal, pas un mode à part — il n'a d'effet /// que lorsqu'un `VoiceMode` est actif, seul cas où il existe une sortie audio. /// /// ⚠️ Volontairement **non persisté** (absent de `toMap`), comme `VoiceController.mode` : /// un mode qui parle tout seul et se réactiverait en silence au lancement suivant /// est une mauvaise surprise. Opt-in par session. bool proactiveModeEnabled = false; String? localPath; VisitAppContext({this.language, this.id, this.configuration, this.isAdmin, this.isAllLanguages, this.instanceId, this.apiKey, this.notificationsEnabled = true}); Map toMap() { return { 'id': id, 'instanceId': instanceId, 'language': language, 'isAdmin': isAdmin != null ? isAdmin! ? 1 : 0 : 0, 'isAllLanguages': isAllLanguages != null ? isAllLanguages! ? 1 : 0 : 0, 'apiKey': apiKey, 'notificationsEnabled': notificationsEnabled ? 1 : 0, }; } factory VisitAppContext.fromJson(Map json) { return VisitAppContext( id: json['id'] as String, instanceId: json['instanceId'] as String, language: json['language'] as String, configuration: json['configuration'] == null ? null : ConfigurationDTO.fromJson(json['configuration']), apiKey: json['apiKey'] as String?, ); } @override String toString() { return 'VisitAppContext{id: $id, instanceId: $instanceId, language: $language, configuration: $configuration, beaconSections: $beaconSections, isAdmin: $isAdmin}'; } }