chore: Stop explicitly copying pubspec.lock as flutter pub get generates it.

This commit is contained in:
Michael committed 2025-12-05 18:44:45 +01:00
1 parent 154e2b2246
commit 5943cd9587
9 files changed
+97 -9

No files matched your search

+3 -2
View File
@@ -14,9 +14,10 @@ RUN git config --global --add safe.directory /app
RUN flutter config --enable-web
# Copy dependency files first for better caching
COPY pubspec.yaml pubspec.lock ./
# Note: pubspec.lock will be generated by flutter pub get if missing
COPY pubspec.yaml ./
# Get dependencies
# Get dependencies (generates pubspec.lock automatically)
RUN flutter pub get
# Copy source code
@@ -71,6 +71,7 @@ class Series {
final String name;
final String? cover;
final String? categoryId;
final String categoryName;
final String? rating;
const Series({
@@ -78,6 +79,7 @@ class Series {
required this.name,
this.cover,
this.categoryId,
this.categoryName = '',
this.rating,
});
@@ -87,6 +89,7 @@ class Series {
name: json['name']?.toString() ?? 'Unknown',
cover: json['cover']?.toString(),
categoryId: json['category_id']?.toString(),
categoryName: json['category_name']?.toString() ?? '',
rating: json['rating']?.toString(),
);
}
@@ -2,8 +2,16 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/models/playlist_config.dart';
import '../services/xtream_service.dart';
/// Singleton Xtream service provider
final xtreamServiceProvider = Provider<XtreamService>((ref) {
/// Family provider for Xtream service - one instance per playlist
final xtreamServiceProvider = Provider.family<XtreamService, PlaylistConfig>((ref, playlist) {
final service = XtreamService();
service.setPlaylist(playlist);
ref.onDispose(() => service.dispose());
return service;
});
/// Singleton Xtream service provider (legacy, for activeXtreamServiceProvider)
final _singletonXtreamServiceProvider = Provider<XtreamService>((ref) {
final service = XtreamService();
ref.onDispose(() => service.dispose());
return service;
@@ -14,7 +22,7 @@ final selectedPlaylistProvider = StateProvider<PlaylistConfig?>((ref) => null);
/// Provider that watches for playlist changes and updates Xtream service
final activeXtreamServiceProvider = Provider<XtreamService>((ref) {
final service = ref.watch(xtreamServiceProvider);
final service = ref.watch(_singletonXtreamServiceProvider);
final playlist = ref.watch(selectedPlaylistProvider);
if (playlist != null) {
@@ -28,7 +28,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
void initState() {
super.initState();
_tabs = [
LiveTVTab(playlist: widget.playlist),
const LiveTVTab(),
MoviesTab(playlist: widget.playlist),
SeriesTab(playlist: widget.playlist),
const SettingsTab(),
@@ -3,6 +3,7 @@ import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:dio_cache_interceptor_hive_store/dio_cache_interceptor_hive_store.dart';
import '../../../core/models/playlist_config.dart';
import '../../../core/models/iptv_models.dart';
import '../models/xtream_models.dart' as xm;
/// Xtream Codes API Service
///
@@ -180,6 +181,68 @@ class XtreamService {
}
}
/// Get movies with pagination support
Future<List<xm.Movie>> getMovies({int offset = 0, int limit = 100}) async {
if (_currentPlaylist == null) throw Exception('No playlist configured');
try {
final response = await _dio.get(
_currentPlaylist!.apiBaseUrl,
queryParameters: {
'username': _currentPlaylist!.username,
'password': _currentPlaylist!.password,
'action': 'get_vod_streams',
},
options: Options(extra: _cacheOptions.toExtra()),
);
final List<dynamic> allMovies = response.data as List<dynamic>;
// Apply pagination
final endIndex = (offset + limit) > allMovies.length ? allMovies.length : offset + limit;
if (offset >= allMovies.length) return [];
final paginatedMovies = allMovies.sublist(offset, endIndex);
return paginatedMovies
.map((movieData) => xm.Movie.fromJson(movieData as Map<String, dynamic>))
.toList();
} catch (e) {
throw Exception('Failed to fetch movies: $e');
}
}
/// Get series with pagination support (returns flat list)
Future<List<xm.Series>> getSeriesPaginated({int offset = 0, int limit = 100}) async {
if (_currentPlaylist == null) throw Exception('No playlist configured');
try {
final response = await _dio.get(
_currentPlaylist!.apiBaseUrl,
queryParameters: {
'username': _currentPlaylist!.username,
'password': _currentPlaylist!.password,
'action': 'get_series',
},
options: Options(extra: _cacheOptions.toExtra()),
);
final List<dynamic> allSeries = response.data as List<dynamic>;
// Apply pagination
final endIndex = (offset + limit) > allSeries.length ? allSeries.length : offset + limit;
if (offset >= allSeries.length) return [];
final paginatedSeries = allSeries.sublist(offset, endIndex);
return paginatedSeries
.map((seriesData) => xm.Series.fromJson(seriesData as Map<String, dynamic>))
.toList();
} catch (e) {
throw Exception('Failed to fetch series: $e');
}
}
/// Get short EPG for a specific stream
///
/// Returns "Now" and "Next" program info
+10
View File
@@ -1,3 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../../core/models/playlist_config.dart';
import '../models/xtream_models.dart';
import '../providers/xtream_provider.dart';
import '../screens/video_player_screen.dart';
class MoviesTab extends ConsumerStatefulWidget {
final PlaylistConfig playlist;
const MoviesTab({super.key, required this.playlist});
+2 -1
View File
@@ -5,6 +5,7 @@ import 'package:google_fonts/google_fonts.dart';
import '../../../core/models/playlist_config.dart';
import '../services/xtream_service.dart';
import '../models/xtream_models.dart';
import '../providers/xtream_provider.dart';
class SeriesTab extends ConsumerStatefulWidget {
final PlaylistConfig playlist;
@@ -52,7 +53,7 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
try {
final service = ref.read(xtreamServiceProvider(widget.playlist));
final newSeries = await service.getSeries(
final newSeries = await service.getSeriesPaginated(
offset: _currentOffset,
limit: _pageSize,
);
+2 -2
View File
@@ -28,7 +28,7 @@ class MyApp extends ConsumerWidget {
seedColor: Colors.blue,
brightness: Brightness.light,
),
cardTheme: CardTheme(
cardTheme: CardThemeData(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
@@ -41,7 +41,7 @@ class MyApp extends ConsumerWidget {
seedColor: Colors.blue,
brightness: Brightness.dark,
),
cardTheme: CardTheme(
cardTheme: CardThemeData(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
+2
View File
@@ -30,6 +30,8 @@ dependencies:
video_player: ^2.8.2
video_player_web: ^2.3.0 # Required for web platform
chewie: ^1.7.5
media_kit: ^1.1.10
media_kit_video: ^1.2.4
# UI Components
google_fonts: ^6.1.0