diff --git a/bin/api/epg_api.dart b/bin/api/epg_api.dart index 2082905..cf3e031 100644 --- a/bin/api/epg_api.dart +++ b/bin/api/epg_api.dart @@ -350,7 +350,10 @@ class EpgApi { if (response != null && response.statusCode == 200) { // Décodage dans un isolate : 7 Mo de JSON sur la boucle principale la // gelaient, et le relais turbo.ts cessait d'émettre pendant ce temps. - final body = response.body; + // UTF-8 explicite : sans charset annoncé, `response.body` peut décoder + // en latin-1 et abîmer les noms (« Chérie », « ◉ »), donc leur + // correspondance avec le guide. + final body = utf8.decode(response.bodyBytes, allowMalformed: true); try { (epgIds, names) = await Isolate.run(() => _parseChannelTable(body)); } catch (e) { diff --git a/bin/test/epg_api_test.dart b/bin/test/epg_api_test.dart index 46e1f44..af67247 100644 --- a/bin/test/epg_api_test.dart +++ b/bin/test/epg_api_test.dart @@ -249,11 +249,13 @@ void main() { if (url.path.endsWith('/xmltv.php')) return http.Response('', 200); final action = url.queryParameters['action'] ?? ''; if (action == 'get_live_streams') { - return http.Response( - jsonEncode([ + // Octets UTF-8 et JSON sans charset annoncé, comme le panneau réel. + return http.Response.bytes( + utf8.encode(jsonEncode([ {'stream_id': 1, 'name': 'FR - TF1 FHD ◉', 'epg_channel_id': ''}, - ]), + ])), 200, + headers: {'content-type': 'application/json'}, ); } throw http.ClientException('Connection closed', url);