From 172530e00afaa56082644e5adb5cafcb04d4c4f4 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Tue, 15 Sep 2026 22:18:22 +0200 Subject: [PATCH] =?UTF-8?q?Studio=20lot=208d=20:=20portrait=20du=20narrate?= =?UTF-8?q?ur=20=C3=A0=20c=C3=B4t=C3=A9=20du=20lecteur=20audio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Portrait et nom à gauche du lecteur de l'article. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA --- lib/Components/narrator_avatar.dart | 36 +++++++++++++++++++++++++++ lib/Screens/Article/article_view.dart | 15 ++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 lib/Components/narrator_avatar.dart diff --git a/lib/Components/narrator_avatar.dart b/lib/Components/narrator_avatar.dart new file mode 100644 index 0000000..d4cee45 --- /dev/null +++ b/lib/Components/narrator_avatar.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +/// Le personnage qui parle, à côté du lecteur audio (plan Studio lot 8d) : portrait canon et +/// nom, sans libellé — un nom propre ne demande pas de traduction. +class NarratorAvatar extends StatelessWidget { + const NarratorAvatar({Key? key, required this.name, this.portraitUrl, this.size = 44}) : super(key: key); + + final String name; + final String? portraitUrl; + final double size; + + @override + Widget build(BuildContext context) { + final placeholder = Container( + color: const Color(0xFFE8E3DA), + child: Icon(Icons.person, size: size * 0.6, color: const Color(0xFF6B7B86)), + ); + + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + ClipOval( + child: SizedBox( + width: size, + height: size, + child: portraitUrl == null + ? placeholder + : Image.network(portraitUrl!, fit: BoxFit.cover, errorBuilder: (_, __, ___) => placeholder), + ), + ), + const SizedBox(width: 12), + Text(name, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), + ], + ); + } +} diff --git a/lib/Screens/Article/article_view.dart b/lib/Screens/Article/article_view.dart index c5c433f..ac0044c 100644 --- a/lib/Screens/Article/article_view.dart +++ b/lib/Screens/Article/article_view.dart @@ -1,3 +1,4 @@ +import 'package:tablet_app/Components/narrator_avatar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:manager_api_new/api.dart'; @@ -217,11 +218,23 @@ class _ArticleViewState extends State { ); } + /// Le personnage qui parle, à gauche du lecteur, quand l'audio est une narration (lot 8d). Widget _buildAudio() { - return CachedCustomResource( + final player = CachedCustomResource( resourceDTO: _audioResource!, isAuto: widget.section.isReadAudioAuto ?? false, webView: false, ); + final narratorName = _audioResource!.narratorName; + if (narratorName == null) return player; + + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + NarratorAvatar(name: narratorName, portraitUrl: _audioResource!.narratorPortraitUrl), + const SizedBox(width: 16), + player, + ], + ); } }