D5 — les échecs de téléchargement ne disparaissent plus dans un print : ils sont collectés et la visite n'est déclarée téléchargée que si elle l'est vraiment. Nouvelle clé downloadIncomplete dans les 10 langues, sans quoi getFromLocale aurait rendu une chaîne vide. Trouvé en câblant l'écran, et c'est pire que le bug d'origine : sans état d'échec, une visite incomplète restait sur « téléchargement en cours » indéfiniment. Le compteur d'avancement n'est incrémenté qu'en cas de succès, donc il n'atteignait jamais le total et l'écran ne concluait jamais. Relancer ne re-télécharge que ce qui manque. J4 — mention d'information accessible depuis l'assistant lui-même, là où la collecte a lieu (§8.3 des CGU). Texte repris mot pour mot de DOCS/mention-information-visiteurs.md. FR/NL/EN seulement, repli sur l'anglais : traduire une mention de protection des données sans relecture humaine serait pire que la servir en anglais. Les 7 autres langues attendent une traduction relue, à demander avec la relecture juridique. flutter analyze lib sans erreur, flutter build apk --debug --flavor dev vert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
98 lines
5.0 KiB
Dart
98 lines
5.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:mymuseum_visitapp/Models/visitContext.dart';
|
|
|
|
/// Mention d'information aux visiteurs sur le traitement de leurs questions (§8.3 des CGU).
|
|
///
|
|
/// ⚠️ **Texte repris mot pour mot de `DOCS/mention-information-visiteurs.md`**, qui est le
|
|
/// document de référence remis au client. Toute correction se fait là-bas d'abord : c'est lui
|
|
/// que le client publie dans sa politique de confidentialité, et les deux ne doivent pas
|
|
/// diverger. ⚠️ Il est **rédigé côté produit et non validé juridiquement** (lot J, J5).
|
|
///
|
|
/// ⚠️ **Trois langues seulement, repli sur l'anglais — c'est un choix, pas un oubli.** L'app
|
|
/// en porte dix, mais traduire une mention de protection des données sans relecture humaine
|
|
/// serait pire que la servir en anglais : une nuance perdue sur « nous n'enregistrons pas
|
|
/// votre adresse IP » n'est pas une coquille d'interface. Les sept autres langues attendent
|
|
/// une traduction relue, à demander en même temps que la relecture juridique.
|
|
class VisitorPrivacyNotice extends StatelessWidget {
|
|
final VisitAppContext visitAppContext;
|
|
|
|
const VisitorPrivacyNotice({Key? key, required this.visitAppContext}) : super(key: key);
|
|
|
|
static void show(BuildContext context, VisitAppContext visitAppContext) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (_) => VisitorPrivacyNotice(visitAppContext: visitAppContext),
|
|
);
|
|
}
|
|
|
|
static const Map<String, ({String title, String body})> _texts = {
|
|
'FR': (
|
|
title: 'Vos questions au guide',
|
|
body:
|
|
"Lorsque vous posez une question à notre guide, votre question et la réponse qui vous "
|
|
"est donnée sont enregistrées. Cela nous sert à repérer ce que nos visiteurs cherchent "
|
|
"sans le trouver, et à compléter nos contenus en conséquence.\n\n"
|
|
"Nous n'enregistrons ni votre nom, ni votre compte, ni votre adresse IP. Un identifiant "
|
|
"de session tiré au hasard permet seulement de relier entre elles les questions d'une "
|
|
"même conversation ; il disparaît avec elle.\n\n"
|
|
"Votre question est transmise à notre fournisseur d'intelligence artificielle (Google) "
|
|
"pour produire la réponse. Le texte de vos questions est supprimé au bout de 90 jours ; "
|
|
"seuls des regroupements par sujet, sans le texte de vos questions, sont conservés "
|
|
"au-delà.\n\n"
|
|
"Le champ de question est libre : nous vous invitons à ne pas y saisir d'informations "
|
|
"personnelles."
|
|
),
|
|
'NL': (
|
|
title: 'Uw vragen aan de gids',
|
|
body:
|
|
"Wanneer u onze gids een vraag stelt, worden uw vraag en het gegeven antwoord "
|
|
"opgeslagen. Zo zien we wat onze bezoekers zoeken zonder het te vinden, en vullen we "
|
|
"onze inhoud aan.\n\n"
|
|
"Wij registreren noch uw naam, noch een account, noch uw IP-adres. Een willekeurig "
|
|
"gegenereerde sessie-identificatie dient enkel om de vragen van eenzelfde gesprek aan "
|
|
"elkaar te koppelen; ze verdwijnt samen met dat gesprek.\n\n"
|
|
"Uw vraag wordt doorgestuurd naar onze aanbieder van kunstmatige intelligentie (Google) "
|
|
"om het antwoord op te stellen. De tekst van uw vragen wordt na 90 dagen verwijderd; "
|
|
"daarna blijven enkel groeperingen per onderwerp bewaard, zonder de tekst van uw "
|
|
"vragen.\n\n"
|
|
"Het vraagveld is vrij in te vullen: wij raden u aan er geen persoonsgegevens in te "
|
|
"typen."
|
|
),
|
|
'EN': (
|
|
title: 'Your questions to the guide',
|
|
body:
|
|
"When you ask our guide a question, your question and the answer you are given are "
|
|
"recorded. This helps us see what our visitors look for without finding it, and improve "
|
|
"our content accordingly.\n\n"
|
|
"We record neither your name, nor an account, nor your IP address. A randomly generated "
|
|
"session identifier only links together the questions of a single conversation; it "
|
|
"disappears with it.\n\n"
|
|
"Your question is sent to our artificial intelligence provider (Google) to produce the "
|
|
"answer. The text of your questions is deleted after 90 days; beyond that, only "
|
|
"groupings by topic are kept, without the text of your questions.\n\n"
|
|
"The question field is free text: we invite you not to enter personal information in it."
|
|
),
|
|
};
|
|
|
|
static ({String title, String body}) textFor(String? language) =>
|
|
_texts[(language ?? 'FR').toUpperCase()] ?? _texts['EN']!;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final text = textFor(visitAppContext.language);
|
|
|
|
return AlertDialog(
|
|
title: Text(text.title, style: const TextStyle(fontSize: 17)),
|
|
content: SingleChildScrollView(
|
|
child: Text(text.body, style: const TextStyle(fontSize: 13.5, height: 1.45)),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
child: const Text('OK'),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|