mirror of
https://github.com/R0m1k3/xtremobile.git
synced 2026-10-23 23:28:15 +02:00
feat: Add mobile-specific Riverpod providers for Xtream services, including live channels, movies, series, and series info.
This commit is contained in:
1 parent
51f73d102d
commit
e6281ff912
6 files changed
+47
-20
No files matched your search
@@ -493,6 +493,10 @@ class _PlaylistCard extends StatelessWidget {
|
|||||||
Icons.chevron_right,
|
Icons.chevron_right,
|
||||||
color: AppColors.textTertiary,
|
color: AppColors.textTertiary,
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.more_vert, color: AppColors.textSecondary),
|
||||||
|
onPressed: onLongPress, // Re-use the options sheet logic
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class _MobileSeriesDetailScreenState extends ConsumerState<MobileSeriesDetailScr
|
|||||||
_error = null;
|
_error = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
final service = ref.read(mobileXtreamServiceProvider(widget.playlist));
|
final service = await ref.read(mobileXtreamServiceProvider(widget.playlist).future);
|
||||||
final info = await service.getSeriesInfo(widget.series.seriesId.toString());
|
final info = await service.getSeriesInfo(widget.series.seriesId.toString());
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:video_player/video_player.dart';
|
import 'package:video_player/video_player.dart';
|
||||||
import 'package:chewie/chewie.dart';
|
import 'package:chewie/chewie.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
import '../../../../core/models/playlist_config.dart';
|
import '../../../../core/models/playlist_config.dart';
|
||||||
import '../../../../core/models/iptv_models.dart';
|
import '../../../../core/models/iptv_models.dart';
|
||||||
import '../../../../core/theme/app_colors.dart';
|
import '../../../../core/theme/app_colors.dart';
|
||||||
@@ -43,14 +44,12 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen> {
|
|||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
String? _errorMessage;
|
String? _errorMessage;
|
||||||
late int _currentIndex;
|
late int _currentIndex;
|
||||||
late XtreamServiceMobile _xtreamService;
|
XtreamServiceMobile? _xtreamService; // Make nullable to handle async init
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_currentIndex = widget.initialIndex;
|
_currentIndex = widget.initialIndex;
|
||||||
_xtreamService = XtreamServiceMobile();
|
|
||||||
_xtreamService.setPlaylist(widget.playlist);
|
|
||||||
|
|
||||||
// Lock to landscape for video playback
|
// Lock to landscape for video playback
|
||||||
SystemChrome.setPreferredOrientations([
|
SystemChrome.setPreferredOrientations([
|
||||||
@@ -59,11 +58,31 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen> {
|
|||||||
]);
|
]);
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
|
||||||
|
|
||||||
_initializePlayer();
|
// Initialize service and then player
|
||||||
|
_initializeServiceAndPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _initializeServiceAndPlayer() async {
|
||||||
|
try {
|
||||||
|
final dir = await getApplicationDocumentsDirectory();
|
||||||
|
_xtreamService = XtreamServiceMobile(dir.path);
|
||||||
|
_xtreamService!.setPlaylist(widget.playlist);
|
||||||
|
|
||||||
|
await _initializePlayer();
|
||||||
|
} catch (e) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
_errorMessage = "Service Error: $e";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initializePlayer() async {
|
Future<void> _initializePlayer() async {
|
||||||
try {
|
try {
|
||||||
|
if (_xtreamService == null) return; // Should not happen if called correctly
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
@@ -82,13 +101,13 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen> {
|
|||||||
|
|
||||||
if (widget.streamType == StreamType.live) {
|
if (widget.streamType == StreamType.live) {
|
||||||
// Live TV - use HLS format for best mobile compatibility
|
// Live TV - use HLS format for best mobile compatibility
|
||||||
streamUrl = _xtreamService.getLiveStreamUrl(currentStreamId);
|
streamUrl = _xtreamService!.getLiveStreamUrl(currentStreamId);
|
||||||
} else if (widget.streamType == StreamType.vod) {
|
} else if (widget.streamType == StreamType.vod) {
|
||||||
// Movies
|
// Movies
|
||||||
streamUrl = _xtreamService.getVodStreamUrl(currentStreamId, widget.containerExtension);
|
streamUrl = _xtreamService!.getVodStreamUrl(currentStreamId, widget.containerExtension);
|
||||||
} else {
|
} else {
|
||||||
// Series
|
// Series
|
||||||
streamUrl = _xtreamService.getSeriesStreamUrl(currentStreamId, widget.containerExtension);
|
streamUrl = _xtreamService!.getSeriesStreamUrl(currentStreamId, widget.containerExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint('NativePlayer: Loading stream: $streamUrl');
|
debugPrint('NativePlayer: Loading stream: $streamUrl');
|
||||||
@@ -183,13 +202,13 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_currentIndex = index;
|
_currentIndex = index;
|
||||||
});
|
});
|
||||||
_initializePlayer();
|
_initializeServiceAndPlayer(); // Re-trigger init purely for player part
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_disposeControllers();
|
_disposeControllers();
|
||||||
_xtreamService.dispose();
|
_xtreamService?.dispose();
|
||||||
|
|
||||||
// Restore normal orientation
|
// Restore normal orientation
|
||||||
SystemChrome.setPreferredOrientations([
|
SystemChrome.setPreferredOrientations([
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
|
|||||||
setState(() => _isSearching = true);
|
setState(() => _isSearching = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(widget.playlist));
|
final service = await ref.read(mobileXtreamServiceProvider(widget.playlist).future);
|
||||||
final results = await service.searchMovies(query);
|
final results = await service.searchMovies(query);
|
||||||
|
|
||||||
if (mounted && _searchQuery == query) {
|
if (mounted && _searchQuery == query) {
|
||||||
@@ -98,7 +98,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
|
|||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(widget.playlist));
|
final service = await ref.read(mobileXtreamServiceProvider(widget.playlist).future);
|
||||||
final newMovies = await service.getMoviesPaginated(
|
final newMovies = await service.getMoviesPaginated(
|
||||||
offset: _currentOffset,
|
offset: _currentOffset,
|
||||||
limit: _pageSize,
|
limit: _pageSize,
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
|
|||||||
setState(() => _isSearching = true);
|
setState(() => _isSearching = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(widget.playlist));
|
final service = await ref.read(mobileXtreamServiceProvider(widget.playlist).future);
|
||||||
final results = await service.searchSeries(query);
|
final results = await service.searchSeries(query);
|
||||||
|
|
||||||
if (mounted && _searchQuery == query) {
|
if (mounted && _searchQuery == query) {
|
||||||
@@ -98,7 +98,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
|
|||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(widget.playlist));
|
final service = await ref.read(mobileXtreamServiceProvider(widget.playlist).future);
|
||||||
final newSeries = await service.getSeriesPaginated(
|
final newSeries = await service.getSeriesPaginated(
|
||||||
offset: _currentOffset,
|
offset: _currentOffset,
|
||||||
limit: _pageSize,
|
limit: _pageSize,
|
||||||
|
|||||||
@@ -7,27 +7,31 @@ import '../../features/iptv/models/xtream_models.dart';
|
|||||||
export '../../features/iptv/models/xtream_models.dart';
|
export '../../features/iptv/models/xtream_models.dart';
|
||||||
|
|
||||||
/// Mobile-specific Xtream service provider (no dart:html dependency)
|
/// Mobile-specific Xtream service provider (no dart:html dependency)
|
||||||
final mobileXtreamServiceProvider = Provider.family<XtreamServiceMobile, PlaylistConfig>((ref, playlist) {
|
import 'package:path_provider/path_provider.dart';
|
||||||
final service = XtreamServiceMobile();
|
|
||||||
|
/// Mobile-specific Xtream service provider (no dart:html dependency)
|
||||||
|
final mobileXtreamServiceProvider = FutureProvider.family<XtreamServiceMobile, PlaylistConfig>((ref, playlist) async {
|
||||||
|
final dir = await getApplicationDocumentsDirectory();
|
||||||
|
final service = XtreamServiceMobile(dir.path);
|
||||||
service.setPlaylist(playlist);
|
service.setPlaylist(playlist);
|
||||||
return service;
|
return service;
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Mobile-specific live channels provider
|
/// Mobile-specific live channels provider
|
||||||
final mobileLiveChannelsProvider = FutureProvider.family<Map<String, List<Channel>>, PlaylistConfig>((ref, playlist) async {
|
final mobileLiveChannelsProvider = FutureProvider.family<Map<String, List<Channel>>, PlaylistConfig>((ref, playlist) async {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(playlist));
|
final service = await ref.watch(mobileXtreamServiceProvider(playlist).future);
|
||||||
return service.getLiveChannels();
|
return service.getLiveChannels();
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Mobile-specific movies pagination provider
|
/// Mobile-specific movies pagination provider
|
||||||
final mobileMoviesProvider = FutureProvider.family<List<Movie>, PlaylistConfig>((ref, playlist) async {
|
final mobileMoviesProvider = FutureProvider.family<List<Movie>, PlaylistConfig>((ref, playlist) async {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(playlist));
|
final service = await ref.watch(mobileXtreamServiceProvider(playlist).future);
|
||||||
return service.getMoviesPaginated(offset: 0, limit: 100);
|
return service.getMoviesPaginated(offset: 0, limit: 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Mobile-specific series pagination provider
|
/// Mobile-specific series pagination provider
|
||||||
final mobileSeriesProvider = FutureProvider.family<List<Series>, PlaylistConfig>((ref, playlist) async {
|
final mobileSeriesProvider = FutureProvider.family<List<Series>, PlaylistConfig>((ref, playlist) async {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(playlist));
|
final service = await ref.watch(mobileXtreamServiceProvider(playlist).future);
|
||||||
return service.getSeriesPaginated(offset: 0, limit: 100);
|
return service.getSeriesPaginated(offset: 0, limit: 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -56,6 +60,6 @@ class SeriesInfoRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final mobileSeriesInfoByPlaylistProvider = FutureProvider.family<SeriesInfo, SeriesInfoRequest>((ref, request) async {
|
final mobileSeriesInfoByPlaylistProvider = FutureProvider.family<SeriesInfo, SeriesInfoRequest>((ref, request) async {
|
||||||
final service = ref.read(mobileXtreamServiceProvider(request.playlist));
|
final service = await ref.watch(mobileXtreamServiceProvider(request.playlist).future);
|
||||||
return service.getSeriesInfo(request.seriesId);
|
return service.getSeriesInfo(request.seriesId);
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user