From fd53acbb92fedae4210dae903754e7dc88d37b75 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Fri, 13 Feb 2026 17:23:02 +0100 Subject: [PATCH] fix(tv): use channel key for tuning and EPG matching --- lib/models/livetv_channel.dart | 2 +- lib/screens/livetv/live_tv_screen.dart | 6 +----- lib/screens/livetv/tabs/guide_tab.dart | 3 +-- lib/screens/video_player_screen.dart | 10 ++++------ lib/utils/live_tv_player_navigation.dart | 9 ++++----- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/lib/models/livetv_channel.dart b/lib/models/livetv_channel.dart index 880fa272..71bc39bb 100644 --- a/lib/models/livetv_channel.dart +++ b/lib/models/livetv_channel.dart @@ -40,7 +40,7 @@ class LiveTvChannel { title: json['title'] as String? ?? json['callSign'] as String?, thumb: json['thumb'] as String?, art: json['art'] as String?, - number: json['number'] as String? ?? json['channelNumber'] as String?, + number: json['number'] as String? ?? json['channelNumber'] as String? ?? json['channelVcn']?.toString(), hd: json['hd'] == true || json['hd'] == 1, lineup: json['lineup'] as String?, slug: json['slug'] as String?, diff --git a/lib/screens/livetv/live_tv_screen.dart b/lib/screens/livetv/live_tv_screen.dart index 41edfae2..3ec5c8a8 100644 --- a/lib/screens/livetv/live_tv_screen.dart +++ b/lib/screens/livetv/live_tv_screen.dart @@ -118,12 +118,8 @@ class _LiveTvScreenState extends State with SingleTickerProviderSt final channels = await client.getEpgChannels(lineup: serverInfo.lineup); appLogger.d('Channels from DVR ${serverInfo.dvrKey}: ${channels.length} channels'); - if (channels.isNotEmpty) { - final sample = channels.first; - appLogger.d('Sample channel: key=${sample.key} identifier=${sample.identifier} number=${sample.number} slug=${sample.slug}'); - } for (final channel in channels) { - final dedupKey = '${serverInfo.serverId}:${channel.identifier ?? channel.key}'; + final dedupKey = '${serverInfo.serverId}:${channel.key}'; if (seenChannels.add(dedupKey)) { allChannels.add(channel); } diff --git a/lib/screens/livetv/tabs/guide_tab.dart b/lib/screens/livetv/tabs/guide_tab.dart index 3660ac1d..61279572 100644 --- a/lib/screens/livetv/tabs/guide_tab.dart +++ b/lib/screens/livetv/tabs/guide_tab.dart @@ -258,8 +258,7 @@ class GuideTabState extends State { } List _getProgramsForChannel(LiveTvChannel channel) { - final channelId = channel.identifier ?? channel.key; - return _programs.where((p) => p.channelIdentifier == channelId).toList() + return _programs.where((p) => p.channelIdentifier == channel.key).toList() ..sort((a, b) => (a.beginsAt ?? 0).compareTo(b.beginsAt ?? 0)); } diff --git a/lib/screens/video_player_screen.dart b/lib/screens/video_player_screen.dart index 71cd8a69..d6071653 100644 --- a/lib/screens/video_player_screen.dart +++ b/lib/screens/video_player_screen.dart @@ -867,10 +867,9 @@ class VideoPlayerScreenState extends State with WidgetsBindin throw Exception('No channel to tune'); } final channel = channels[channelIndex]; - final channelId = channel.identifier ?? channel.key; - appLogger.d('Tune: dvrKey=${widget.liveDvrKey} channelId=$channelId (identifier=${channel.identifier}, key=${channel.key})'); + appLogger.d('Tune: dvrKey=${widget.liveDvrKey} channelKey=${channel.key}'); final client = widget.liveClient!; - final result = await client.tuneChannel(widget.liveDvrKey!, channelId); + final result = await client.tuneChannel(widget.liveDvrKey!, channel.key); if (result == null) throw Exception('Failed to tune channel'); streamUrl = '${client.config.baseUrl}${result.streamPath}' @@ -1722,8 +1721,7 @@ class VideoPlayerScreenState extends State with WidgetsBindin await _sendLiveTimeline('stopped'); final channel = channels[newIndex]; - final channelId = channel.identifier ?? channel.key; - appLogger.d('Switching to channel: ${channel.displayName} ($channelId) (identifier=${channel.identifier}, key=${channel.key})'); + appLogger.d('Switching to channel: ${channel.displayName} (${channel.key})'); setState(() => _hasFirstFrame.value = false); @@ -1739,7 +1737,7 @@ class VideoPlayerScreenState extends State with WidgetsBindin final client = multiServer.getClientForServer(serverInfo.serverId); if (client == null) return; - final result = await client.tuneChannel(serverInfo.dvrKey, channelId); + final result = await client.tuneChannel(serverInfo.dvrKey, channel.key); if (result == null || !mounted) return; final streamUrl = '${client.config.baseUrl}${result.streamPath}'.withPlexToken(client.config.token); diff --git a/lib/utils/live_tv_player_navigation.dart b/lib/utils/live_tv_player_navigation.dart index d93ad1a1..7b047115 100644 --- a/lib/utils/live_tv_player_navigation.dart +++ b/lib/utils/live_tv_player_navigation.dart @@ -21,14 +21,13 @@ Future navigateToLiveTv( required LiveTvChannel channel, List? channels, }) async { - final channelId = channel.identifier ?? channel.key; final navigator = Navigator.of(context); - appLogger.d('Navigating to live channel: ${channel.displayName} ($channelId)'); + appLogger.d('Navigating to live channel: ${channel.displayName} (${channel.key})'); final placeholder = PlexMetadata( - ratingKey: channelId, - key: channelId, + ratingKey: channel.key, + key: channel.key, type: 'clip', title: channel.displayName, ); @@ -42,7 +41,7 @@ Future navigateToLiveTv( liveStreamUrl: null, liveChannels: channels, liveCurrentChannelIndex: channels?.indexWhere( - (ch) => (ch.identifier ?? ch.key) == channelId, + (ch) => ch.key == channel.key, ), liveDvrKey: dvrKey, liveClient: client,