Studio lot 8d : portrait du narrateur à côté du lecteur audio

Portrait et nom à gauche du lecteur de l'article.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA
This commit is contained in:
Thomas Fransolet 2026-09-15 22:18:22 +02:00
parent bac086f1e1
commit 172530e00a
2 changed files with 50 additions and 1 deletions

View File

@ -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)),
],
);
}
}

View File

@ -1,3 +1,4 @@
import 'package:tablet_app/Components/narrator_avatar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:manager_api_new/api.dart'; import 'package:manager_api_new/api.dart';
@ -217,11 +218,23 @@ class _ArticleViewState extends State<ArticleView> {
); );
} }
/// Le personnage qui parle, à gauche du lecteur, quand l'audio est une narration (lot 8d).
Widget _buildAudio() { Widget _buildAudio() {
return CachedCustomResource( final player = CachedCustomResource(
resourceDTO: _audioResource!, resourceDTO: _audioResource!,
isAuto: widget.section.isReadAudioAuto ?? false, isAuto: widget.section.isReadAudioAuto ?? false,
webView: 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,
],
);
} }
} }