diff --git a/bin/api/auth_handler.dart b/bin/api/auth_handler.dart index 2bd7448..cd2da5f 100644 --- a/bin/api/auth_handler.dart +++ b/bin/api/auth_handler.dart @@ -29,7 +29,7 @@ class AuthHandler { return Response(400, body: jsonEncode({ 'success': false, 'error': 'Username and password are required', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } // Verify credentials @@ -38,7 +38,7 @@ class AuthHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Invalid credentials', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } // Create session @@ -48,7 +48,7 @@ class AuthHandler { 'success': true, 'user': user.toJson(), 'token': session.token, - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), @@ -65,14 +65,14 @@ class AuthHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Unauthorized', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } db.deleteSession(token); return Response.ok(jsonEncode({ 'success': true, - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), @@ -89,7 +89,7 @@ class AuthHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Unauthorized', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } final session = db.findSessionByToken(token); @@ -97,7 +97,7 @@ class AuthHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Invalid or expired session', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } final user = db.findUserById(session.userId); @@ -105,12 +105,12 @@ class AuthHandler { return Response(404, body: jsonEncode({ 'success': false, 'error': 'User not found', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } return Response.ok(jsonEncode({ 'user': user.toJson(), - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), diff --git a/bin/api/playlists_handler.dart b/bin/api/playlists_handler.dart index 40527f6..5575b47 100644 --- a/bin/api/playlists_handler.dart +++ b/bin/api/playlists_handler.dart @@ -27,14 +27,14 @@ class PlaylistsHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Unauthorized', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } final playlists = db.getPlaylists(userId); return Response.ok(jsonEncode({ 'playlists': playlists.map((p) => p.toJson()).toList(), - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), @@ -51,7 +51,7 @@ class PlaylistsHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Unauthorized', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } final payload = jsonDecode(await request.readAsString()) as Map; @@ -65,7 +65,7 @@ class PlaylistsHandler { return Response(400, body: jsonEncode({ 'success': false, 'error': 'Missing required fields', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } final playlist = db.createPlaylist( @@ -80,7 +80,7 @@ class PlaylistsHandler { return Response.ok(jsonEncode({ 'success': true, 'playlist': playlist.toJson(), - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), @@ -97,7 +97,7 @@ class PlaylistsHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Unauthorized', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } // Verify playlist belongs to user @@ -106,14 +106,14 @@ class PlaylistsHandler { return Response(404, body: jsonEncode({ 'success': false, 'error': 'Playlist not found', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } if (existing.userId != userId) { return Response(403, body: jsonEncode({ 'success': false, 'error': 'Forbidden', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } final payload = jsonDecode(await request.readAsString()) as Map; @@ -135,7 +135,7 @@ class PlaylistsHandler { return Response.ok(jsonEncode({ 'success': true, 'playlist': playlist.toJson(), - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), @@ -152,7 +152,7 @@ class PlaylistsHandler { return Response(401, body: jsonEncode({ 'success': false, 'error': 'Unauthorized', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } // Verify playlist belongs to user @@ -161,21 +161,21 @@ class PlaylistsHandler { return Response(404,body: jsonEncode({ 'success': false, 'error': 'Playlist not found', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } if (existing.userId != userId) { return Response(403, body: jsonEncode({ 'success': false, 'error': 'Forbidden', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } db.deletePlaylist(id); return Response.ok(jsonEncode({ 'success': true, - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), diff --git a/bin/api/users_handler.dart b/bin/api/users_handler.dart index e653695..de3a7e9 100644 --- a/bin/api/users_handler.dart +++ b/bin/api/users_handler.dart @@ -37,7 +37,7 @@ class UsersHandler { return Response.ok(jsonEncode({ 'success': true, 'users': users.map((u) => u.toJson()).toList(), - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( body: jsonEncode({'success': false, 'error': e.toString()}), @@ -62,21 +62,21 @@ class UsersHandler { return Response.badRequest(body: jsonEncode({ 'success': false, 'error': 'Missing required fields', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } if (db.findUserByUsername(username) != null) { return Response.badRequest(body: jsonEncode({ 'success': false, 'error': 'Username already exists', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } final user = db.createUser(username, password, isAdmin: isAdmin); return Response.ok(jsonEncode({ 'success': true, 'user': user.toJson(), - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } catch (e) { return Response.internalServerError( @@ -100,7 +100,7 @@ class UsersHandler { return Response.badRequest(body: jsonEncode({ 'success': false, 'error': 'Missing password', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } db.updateUserPassword(id, password); @@ -151,7 +151,7 @@ class UsersHandler { return Response.badRequest(body: jsonEncode({ 'success': false, 'error': 'Cannot delete yourself', - }), headers: {'Content-Type': 'application/json'}); + }), headers: {'Content-Type': 'application/json'},); } db.deleteUser(id); diff --git a/bin/database/database.dart b/bin/database/database.dart index 6bceacd..e4254b0 100644 --- a/bin/database/database.dart +++ b/bin/database/database.dart @@ -86,7 +86,7 @@ class AppDatabase { _db.execute(''' INSERT INTO users (id, username, password_hash, is_admin) VALUES (?, ?, ?, 1) - ''', [adminId, 'admin', passwordHash]); + ''', [adminId, 'admin', passwordHash],); print('Default admin user created (username: admin, password: admin)'); } @@ -141,7 +141,7 @@ class AppDatabase { _db.execute(''' INSERT INTO users (id, username, password_hash, is_admin) VALUES (?, ?, ?, ?) - ''', [userId, username, passwordHash, isAdmin ? 1 : 0]); + ''', [userId, username, passwordHash, isAdmin ? 1 : 0],); return User( id: userId, @@ -190,7 +190,7 @@ class AppDatabase { _db.execute(''' INSERT INTO sessions (id, user_id, token, expires_at) VALUES (?, ?, ?, ?) - ''', [sessionId, userId, token, expiresAt.toIso8601String()]); + ''', [sessionId, userId, token, expiresAt.toIso8601String()],); return models.Session( id: sessionId, @@ -272,7 +272,7 @@ class AppDatabase { _db.execute(''' INSERT INTO playlists (id, user_id, name, server_url, username, password, dns, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) - ''', [playlistId, userId, name, serverUrl, username, password, dns, now, now]); + ''', [playlistId, userId, name, serverUrl, username, password, dns, now, now],); return Playlist( id: playlistId, @@ -302,7 +302,7 @@ class AppDatabase { UPDATE playlists SET name = ?, server_url = ?, username = ?, password = ?, dns = ?, updated_at = ? WHERE id = ? - ''', [name, serverUrl, username, password, dns, now, playlistId]); + ''', [name, serverUrl, username, password, dns, now, playlistId],); return getPlaylistById(playlistId)!; } diff --git a/bin/middleware/auth_middleware.dart b/bin/middleware/auth_middleware.dart index 71e3ca9..96327d3 100644 --- a/bin/middleware/auth_middleware.dart +++ b/bin/middleware/auth_middleware.dart @@ -26,7 +26,7 @@ Middleware authMiddleware(AppDatabase db) { final updatedRequest = request.change(context: { ...request.context, 'userId': session.userId, - }); + },); return handler(updatedRequest); }; diff --git a/bin/middleware/security_middleware.dart b/bin/middleware/security_middleware.dart index 1558941..90262ce 100644 --- a/bin/middleware/security_middleware.dart +++ b/bin/middleware/security_middleware.dart @@ -23,7 +23,7 @@ Middleware securityHeadersMiddleware() { 'Referrer-Policy': 'strict-origin-when-cross-origin', // Note: CSP is tricky with Flutter Web (requires 'unsafe-eval' for Dart), // so we omit it here to avoid breaking the app, or use a permissive one. - }); + },); }; }; } @@ -42,7 +42,7 @@ Middleware honeypotMiddleware() { '/config.php', '/api/.env', '/console', - '/actuator/health' + '/actuator/health', ]; return (Handler handler) { diff --git a/bin/server.dart b/bin/server.dart index 591620f..409f600 100644 --- a/bin/server.dart +++ b/bin/server.dart @@ -43,11 +43,11 @@ void main(List args) async { // Playlists endpoints (with auth middleware) ..mount('/api/playlists', Pipeline() .addMiddleware(authMiddleware(db)) - .addHandler(playlistsHandler.router.call)) + .addHandler(playlistsHandler.router.call),) // Users endpoints (with auth middleware) ..mount('/api/users', Pipeline() .addMiddleware(authMiddleware(db)) - .addHandler(usersHandler.router.call)); + .addHandler(usersHandler.router.call),); // Initialize Cleanup Service final cleanupService = CleanupService(); @@ -75,12 +75,12 @@ void main(List args) async { final result = await cleanupService.runCleanup(); return Response.ok( jsonEncode(result), - headers: {'content-type': 'application/json'} + headers: {'content-type': 'application/json'}, ); }); return router(request); - })); + }),); // Create handlers final staticHandler = createStaticHandler( @@ -532,14 +532,14 @@ Handler _createStreamHandler() { '-vf', 'scale=-2:480', '-b:v', '800k', '-maxrate', '800k', - '-bufsize', '1600k' + '-bufsize', '1600k', ]); } else { // Medium: Original res (or cap at 720p?), 2500k ffmpegArgs.addAll([ '-b:v', '2500k', '-maxrate', '2500k', - '-bufsize', '5000k' + '-bufsize', '5000k', ]); } } @@ -556,7 +556,7 @@ Handler _createStreamHandler() { '-fflags', '+genpts', // Output to stdout pipe - 'pipe:1' + 'pipe:1', ]); // Start the process diff --git a/bin/services/cleanup_service.dart b/bin/services/cleanup_service.dart index 7f10703..7a46f72 100644 --- a/bin/services/cleanup_service.dart +++ b/bin/services/cleanup_service.dart @@ -66,7 +66,7 @@ class CleanupService { 'deleted_files': deletedCount, 'freed_bytes': freedBytes, 'timestamp': DateTime.now().toIso8601String(), - 'errors': errors + 'errors': errors, }; print('CleanupService: Cleanup complete. Deleted $deletedCount files, freed ${(freedBytes / 1024 / 1024).toStringAsFixed(2)} MB'); diff --git a/current_build_log.txt b/current_build_log.txt new file mode 100644 index 0000000..c557468 Binary files /dev/null and b/current_build_log.txt differ diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index ec5436e..dcfa6c5 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -15,13 +15,13 @@ class ApiClient { headers: {'Content-Type': 'application/json'}, connectTimeout: const Duration(seconds: 10), receiveTimeout: const Duration(seconds: 10), - )); + ),); // Add interceptor for logging _dio.interceptors.add(LogInterceptor( requestBody: true, responseBody: true, - )); + ),); } /// Get base URL (same origin for production) diff --git a/lib/core/services/auth_api_service.dart b/lib/core/services/auth_api_service.dart index 1d4fabe..891d236 100644 --- a/lib/core/services/auth_api_service.dart +++ b/lib/core/services/auth_api_service.dart @@ -11,7 +11,7 @@ class AuthApiService { final response = await _api.post('/api/auth/login', data: { 'username': username, 'password': password, - }); + },); final data = response.data as Map; diff --git a/lib/core/services/playlist_api_service.dart b/lib/core/services/playlist_api_service.dart index 4227d67..db1dc43 100644 --- a/lib/core/services/playlist_api_service.dart +++ b/lib/core/services/playlist_api_service.dart @@ -43,7 +43,7 @@ class PlaylistApiService { 'username': username, 'password': password, 'dns': dns, - }); + },); final data = response.data as Map; @@ -80,7 +80,7 @@ class PlaylistApiService { 'username': username, 'password': password, 'dns': dns, - }); + },); final data = response.data as Map; diff --git a/lib/core/services/user_api_service.dart b/lib/core/services/user_api_service.dart index 24ebdd7..27ffa62 100644 --- a/lib/core/services/user_api_service.dart +++ b/lib/core/services/user_api_service.dart @@ -20,7 +20,7 @@ class UserApiService { passwordHash: '', isAdmin: u['isAdmin'] as bool? ?? false, createdAt: DateTime.tryParse(u['createdAt'] ?? '') ?? DateTime.now(), - )).toList(); + ),).toList(); } return []; } catch (e) { @@ -40,7 +40,7 @@ class UserApiService { 'username': username, 'password': password, 'isAdmin': isAdmin, - }); + },); final data = response.data as Map; @@ -75,7 +75,7 @@ class UserApiService { _api.restoreToken(); final response = await _api.put('/api/users/$userId/password', data: { 'password': newPassword, - }); + },); final data = response.data as Map; @@ -117,7 +117,7 @@ class UserApiService { _api.restoreToken(); final response = await _api.put('/api/users/$userId', data: { 'isAdmin': isAdmin, - }); + },); final data = response.data as Map; diff --git a/lib/core/widgets/components/ui_components.dart b/lib/core/widgets/components/ui_components.dart index d708b7c..139d907 100644 --- a/lib/core/widgets/components/ui_components.dart +++ b/lib/core/widgets/components/ui_components.dart @@ -373,14 +373,14 @@ class _MediaCardState extends State color: Colors.black.withOpacity(0.5), blurRadius: 20, offset: const Offset(0, 10), - ) + ), ] : [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 4, offset: const Offset(0, 2), - ) + ), ], ), child: ClipRRect( diff --git a/lib/features/admin/screens/admin_panel.dart b/lib/features/admin/screens/admin_panel.dart index 651e988..020ee8b 100644 --- a/lib/features/admin/screens/admin_panel.dart +++ b/lib/features/admin/screens/admin_panel.dart @@ -410,7 +410,7 @@ class _UsersTab extends ConsumerWidget { child: Icon( user.isAdmin ? Icons.admin_panel_settings : Icons.person, color: user.isAdmin ? Colors.black : AppColors.textPrimary, - size: 24 + size: 24, ), ), const SizedBox(width: 16), diff --git a/lib/features/iptv/providers/playback_positions_provider.dart b/lib/features/iptv/providers/playback_positions_provider.dart index aa0f7e3..f71214f 100644 --- a/lib/features/iptv/providers/playback_positions_provider.dart +++ b/lib/features/iptv/providers/playback_positions_provider.dart @@ -48,7 +48,7 @@ class PlaybackPositionsNotifier extends StateNotifier { if (positionsJson != null) { final decoded = jsonDecode(positionsJson) as Map; final positions = decoded.map((key, value) => - MapEntry(key, (value as num).toDouble()) + MapEntry(key, (value as num).toDouble()), ); state = PlaybackPositions(positions: positions); diff --git a/lib/features/iptv/screens/dashboard_screen.dart b/lib/features/iptv/screens/dashboard_screen.dart index 6f067ba..c48e0f7 100644 --- a/lib/features/iptv/screens/dashboard_screen.dart +++ b/lib/features/iptv/screens/dashboard_screen.dart @@ -210,7 +210,7 @@ class _DashboardScreenState extends ConsumerState with SingleTi fontWeight: FontWeight.w300, fontSize: 16, color: Colors.white.withOpacity(0.8), - height: 0.8 + height: 0.8, ), ), ], diff --git a/lib/features/iptv/screens/player_screen.dart b/lib/features/iptv/screens/player_screen.dart index e6a116d..d7238ff 100644 --- a/lib/features/iptv/screens/player_screen.dart +++ b/lib/features/iptv/screens/player_screen.dart @@ -95,7 +95,7 @@ class _PlayerScreenState extends ConsumerState { _totalDuration = duration > 0 ? duration : 1; }); ref.read(playbackPositionsProvider.notifier).savePosition( - _contentId, currentTime, duration + _contentId, currentTime, duration, ); } else if (type == 'playback_status') { final status = data['status']; @@ -674,7 +674,7 @@ class _PlayerScreenState extends ConsumerState { appBar: _showControls ? AppBar( title: Text(widget.channels != null && widget.channels!.isNotEmpty ? widget.channels![_currentIndex].name - : widget.title), + : widget.title,), backgroundColor: Colors.transparent, foregroundColor: Colors.white, elevation: 0, @@ -775,7 +775,7 @@ class _PlayerScreenState extends ConsumerState { ? Icons.volume_off : _volume < 0.5 ? Icons.volume_down : Icons.volume_up, color: Colors.white, - size: 20 + size: 20, ), onPressed: _toggleMute, tooltip: _volume == 0 ? 'Unmute' : 'Mute', diff --git a/lib/features/iptv/screens/playlist_selection_screen.dart b/lib/features/iptv/screens/playlist_selection_screen.dart index e536c54..4024526 100644 --- a/lib/features/iptv/screens/playlist_selection_screen.dart +++ b/lib/features/iptv/screens/playlist_selection_screen.dart @@ -180,7 +180,7 @@ class _PlaylistCardState extends State<_PlaylistCard> { color: Colors.black.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 10), - ) + ), ] : [], ), padding: const EdgeInsets.all(24), diff --git a/lib/features/iptv/services/xtream_service.dart b/lib/features/iptv/services/xtream_service.dart index 0bdcdab..5b7f2d4 100644 --- a/lib/features/iptv/services/xtream_service.dart +++ b/lib/features/iptv/services/xtream_service.dart @@ -19,7 +19,7 @@ class XtreamService { _dio = Dio(BaseOptions( connectTimeout: const Duration(seconds: 15), receiveTimeout: const Duration(seconds: 15), - )); + ),); // Setup caching for API responses _cacheOptions = CacheOptions( diff --git a/lib/features/iptv/widgets/channel_card.dart b/lib/features/iptv/widgets/channel_card.dart index 4e42a9e..b0d4d8b 100644 --- a/lib/features/iptv/widgets/channel_card.dart +++ b/lib/features/iptv/widgets/channel_card.dart @@ -50,7 +50,7 @@ class _ChannelCardState extends ConsumerState super.initState(); _pulseController = AnimationController( vsync: this, - duration: const Duration(milliseconds: 1000) + duration: const Duration(milliseconds: 1000), )..repeat(reverse: true); // Fetch EPG immediately when card is built diff --git a/lib/features/iptv/widgets/epg_overlay.dart b/lib/features/iptv/widgets/epg_overlay.dart index 53fe5b1..a4a6ba1 100644 --- a/lib/features/iptv/widgets/epg_overlay.dart +++ b/lib/features/iptv/widgets/epg_overlay.dart @@ -20,7 +20,7 @@ class EpgOverlay extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final epgAsync = ref.watch(epgByPlaylistProvider( EpgRequestKey(playlist: playlist, streamId: streamId), - )); + ),); return epgAsync.when( data: (epgEntries) { diff --git a/lib/features/iptv/widgets/live_tv_tab.dart b/lib/features/iptv/widgets/live_tv_tab.dart index d1b16fd..1991c14 100644 --- a/lib/features/iptv/widgets/live_tv_tab.dart +++ b/lib/features/iptv/widgets/live_tv_tab.dart @@ -165,7 +165,7 @@ class _LiveTVTabState extends ConsumerState if (_searchQuery.isNotEmpty) GestureDetector( onTap: () => _searchController.clear(), - child: const Icon(Icons.close, size: 16, color: AppColors.textSecondary) + child: const Icon(Icons.close, size: 16, color: AppColors.textSecondary), ), ], ), diff --git a/lib/features/iptv/widgets/movies_tab.dart b/lib/features/iptv/widgets/movies_tab.dart index 3780d3e..7261db5 100644 --- a/lib/features/iptv/widgets/movies_tab.dart +++ b/lib/features/iptv/widgets/movies_tab.dart @@ -141,8 +141,8 @@ class _MoviesTabState extends ConsumerState { } /// Proxy HTTP images through backend to avoid CORS/mixed-content issues - String? _getProxiedImageUrl(String? originalUrl) { - if (originalUrl == null || originalUrl.isEmpty) return null; + String _getProxiedImageUrl(String? originalUrl) { + if (originalUrl == null || originalUrl.isEmpty) return ''; if (originalUrl.startsWith('http://')) { return '/api/xtream/$originalUrl'; } diff --git a/lib/features/iptv/widgets/series_tab.dart b/lib/features/iptv/widgets/series_tab.dart index 0487d65..81dc6a5 100644 --- a/lib/features/iptv/widgets/series_tab.dart +++ b/lib/features/iptv/widgets/series_tab.dart @@ -141,8 +141,8 @@ class _SeriesTabState extends ConsumerState { } /// Proxy HTTP images through backend to avoid CORS/mixed-content issues - String? _getProxiedImageUrl(String? originalUrl) { - if (originalUrl == null || originalUrl.isEmpty) return null; + String _getProxiedImageUrl(String? originalUrl) { + if (originalUrl == null || originalUrl.isEmpty) return ''; if (originalUrl.startsWith('http://')) { return '/api/xtream/$originalUrl'; } diff --git a/lib/mobile/features/iptv/widgets/mobile_movies_tab.dart b/lib/mobile/features/iptv/widgets/mobile_movies_tab.dart index c88779b..e5bbf47 100644 --- a/lib/mobile/features/iptv/widgets/mobile_movies_tab.dart +++ b/lib/mobile/features/iptv/widgets/mobile_movies_tab.dart @@ -126,8 +126,8 @@ class _MobileMoviesTabState extends ConsumerState { } /// Proxy HTTP images through backend to avoid CORS/mixed-content issues - String? _getProxiedImageUrl(String? originalUrl) { - if (originalUrl == null || originalUrl.isEmpty) return null; + String _getProxiedImageUrl(String? originalUrl) { + if (originalUrl == null || originalUrl.isEmpty) return ''; if (originalUrl.startsWith('http://')) { return '/api/xtream/$originalUrl'; } diff --git a/lib/mobile/features/iptv/widgets/mobile_series_tab.dart b/lib/mobile/features/iptv/widgets/mobile_series_tab.dart index a3e52d9..29505db 100644 --- a/lib/mobile/features/iptv/widgets/mobile_series_tab.dart +++ b/lib/mobile/features/iptv/widgets/mobile_series_tab.dart @@ -125,8 +125,8 @@ class _MobileSeriesTabState extends ConsumerState { } /// Proxy HTTP images through backend to avoid CORS/mixed-content issues - String? _getProxiedImageUrl(String? originalUrl) { - if (originalUrl == null || originalUrl.isEmpty) return null; + String _getProxiedImageUrl(String? originalUrl) { + if (originalUrl == null || originalUrl.isEmpty) return ''; if (originalUrl.startsWith('http://')) { return '/api/xtream/$originalUrl'; } diff --git a/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart b/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart index 5ee5af6..c2e9eb9 100644 --- a/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart +++ b/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart @@ -122,7 +122,7 @@ class _MobileSettingsTabState extends ConsumerState { const SizedBox(height: 24), // Appearance - _SectionHeader(title: 'Appearance'), + const _SectionHeader(title: 'Appearance'), Container( decoration: BoxDecoration( color: AppColors.surface, @@ -151,7 +151,7 @@ class _MobileSettingsTabState extends ConsumerState { const SizedBox(height: 24), // Streaming Settings - _SectionHeader(title: 'Streaming'), + const _SectionHeader(title: 'Streaming'), Container( decoration: BoxDecoration( color: AppColors.surface, @@ -206,7 +206,7 @@ class _MobileSettingsTabState extends ConsumerState { const SizedBox(height: 24), // Content Filters - _SectionHeader(title: 'Content Filters'), + const _SectionHeader(title: 'Content Filters'), Container( decoration: BoxDecoration( color: AppColors.surface, diff --git a/task.md b/task.md index bfe46c7..1f84bc1 100644 --- a/task.md +++ b/task.md @@ -3,7 +3,7 @@ - [x] Analyze `Dockerfile` and `docker-compose.yml` dependencies. - [x] Attempt to reproduce the build failure or gather more logs. - [x] Fix the build issue. -- [ ] Verify the fix. +- [x] Verify the fix. # Audio Investigation in Movies (Paused)