mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-17 20:29:30 +02:00
feat: Add initial IPTV support with a dedicated player, series detail screen, Xtream API service, and a streaming API handler.
This commit is contained in:
1 parent
d1401711af
commit
d6405f3471
4 files changed
+68
-15
No files matched your search
@@ -345,6 +345,22 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
// Mute button for Live TV
|
||||
Material(
|
||||
color: Colors.black54,
|
||||
shape: const CircleBorder(),
|
||||
child: InkWell(
|
||||
onTap: _toggleMute,
|
||||
customBorder: const CircleBorder(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Icon(
|
||||
_isMuted ? Icons.volume_off_rounded : Icons.volume_up_rounded,
|
||||
color: Colors.white
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -616,6 +632,12 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
|
||||
],
|
||||
|
||||
const Spacer(),
|
||||
// Volume/Mute button
|
||||
_buildTvControl(
|
||||
_isMuted ? Icons.volume_off_rounded : Icons.volume_up_rounded,
|
||||
_toggleMute
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
_buildTvControl(Icons.subtitles_rounded, () {}),
|
||||
const SizedBox(width: 16),
|
||||
_buildTvControl(Icons.aspect_ratio_rounded, _toggleFullscreen),
|
||||
|
||||
@@ -267,10 +267,25 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
|
||||
color: Colors.grey.shade800,
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
onTap: () async {
|
||||
// Mark as watched when playing
|
||||
ref.read(watchHistoryProvider.notifier).markEpisodeWatched(episodeKey);
|
||||
|
||||
// Fetch actual duration from API if not available
|
||||
Duration? episodeDuration;
|
||||
if (episode.durationSecs != null && episode.durationSecs! > 0) {
|
||||
episodeDuration = Duration(seconds: episode.durationSecs!);
|
||||
} else {
|
||||
// Try to fetch from API using getVodDuration (episodes are often queryable as VODs)
|
||||
final service = ref.read(xtreamServiceProvider(widget.playlist));
|
||||
final durationSecs = await service.getVodDuration(episode.id);
|
||||
if (durationSecs != null && durationSecs > 0) {
|
||||
episodeDuration = Duration(seconds: durationSecs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.mounted) return;
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
@@ -280,7 +295,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
|
||||
playlist: widget.playlist,
|
||||
streamType: StreamType.series,
|
||||
containerExtension: episode.containerExtension ?? 'mkv',
|
||||
duration: episode.durationSecs != null ? Duration(seconds: episode.durationSecs!) : null,
|
||||
duration: episodeDuration,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -79,9 +79,9 @@ class XtreamService {
|
||||
String getSeriesStreamUrl(String streamId, String containerExtension) {
|
||||
if (_currentPlaylist == null) throw Exception('No playlist configured');
|
||||
|
||||
// Point to new dedicated VOD API (HLS playlist)
|
||||
// Point to new dedicated VOD API (HLS playlist) with series type
|
||||
final baseUrl = html.window.location.origin;
|
||||
return '$baseUrl/api/vod/$streamId/playlist.m3u8';
|
||||
return '$baseUrl/api/vod/$streamId/playlist.m3u8?type=series';
|
||||
}
|
||||
|
||||
/// Authenticate and get server info
|
||||
|
||||
Reference in new issue
Block a user