Merge pull request #20 from R0m1k3/antigravity

feat: Implement Xtream IPTV integration including providers, a dedica…
This commit is contained in:
LogiFlow authored and GitHub committed 2025-12-06 09:45:48 +01:00
commit 1e05821782
4 files changed
+40 -3

No files matched your search

@@ -61,3 +61,28 @@ final epgProvider = FutureProvider.family.autoDispose((ref, String streamId) asy
final service = ref.watch(activeXtreamServiceProvider);
return await service.getShortEpg(streamId);
});
/// EPG request key for family provider (combines playlist and streamId)
class EpgRequestKey {
final PlaylistConfig playlist;
final String streamId;
const EpgRequestKey({required this.playlist, required this.streamId});
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is EpgRequestKey &&
runtimeType == other.runtimeType &&
playlist == other.playlist &&
streamId == other.streamId;
@override
int get hashCode => playlist.hashCode ^ streamId.hashCode;
}
/// Provider for EPG with playlist context
final epgByPlaylistProvider = FutureProvider.family.autoDispose((ref, EpgRequestKey key) async {
final service = ref.watch(xtreamServiceProvider(key.playlist));
return await service.getShortEpg(key.streamId);
});
+8 -2
View File
@@ -5,6 +5,7 @@ import 'package:chewie/chewie.dart';
import '../providers/xtream_provider.dart';
import '../widgets/epg_overlay.dart';
import '../../../core/models/iptv_models.dart';
import '../../../core/models/playlist_config.dart';
/// Stream type enum for player
enum StreamType { live, vod, series }
@@ -15,11 +16,13 @@ class PlayerScreen extends ConsumerStatefulWidget {
final String title;
final StreamType streamType;
final String containerExtension;
final PlaylistConfig playlist;
const PlayerScreen({
super.key,
required this.streamId,
required this.title,
required this.playlist,
this.streamType = StreamType.live,
this.containerExtension = 'm3u8',
});
@@ -42,7 +45,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
Future<void> _initializePlayer() async {
try {
final xtreamService = ref.read(activeXtreamServiceProvider);
final xtreamService = ref.read(xtreamServiceProvider(widget.playlist));
// Generate stream URL based on type
late String streamUrl;
@@ -177,7 +180,10 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
bottom: 80,
left: 0,
right: 0,
child: EpgOverlay(streamId: widget.streamId),
child: EpgOverlay(
streamId: widget.streamId,
playlist: widget.playlist,
),
),
],
),
+6 -1
View File
@@ -1,19 +1,24 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/models/playlist_config.dart';
import '../providers/xtream_provider.dart';
/// EPG overlay widget showing "Now" and "Next" programs
class EpgOverlay extends ConsumerWidget {
final String streamId;
final PlaylistConfig playlist;
const EpgOverlay({
super.key,
required this.streamId,
required this.playlist,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final epgAsync = ref.watch(epgProvider(streamId));
final epgAsync = ref.watch(epgByPlaylistProvider(
EpgRequestKey(playlist: playlist, streamId: streamId),
));
return epgAsync.when(
data: (epgEntries) {
@@ -255,6 +255,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
builder: (context) => PlayerScreen(
streamId: channel.streamId,
title: channel.name,
playlist: widget.playlist,
streamType: StreamType.live,
),
),