feat: Implement MobileMoviesTab for displaying IPTV movies with category browsing and search functionality.

This commit is contained in:
Michael committed 2026-03-27 12:10:23 +01:00
1 parent 0010fe12ba
commit f85f43e42f
17 files changed
+268 -136

No files matched your search

@@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:xtremobile/core/utils/image_cache_config.dart';
import 'dart:io';
import 'dart:async';
import 'package:xtremobile/mobile/providers/mobile_xtream_providers.dart';
import 'package:xtremobile/mobile/providers/mobile_settings_providers.dart';
@@ -11,8 +10,6 @@ import 'package:xtremobile/features/iptv/screens/native_player_screen.dart';
import 'package:xtremobile/core/models/iptv_models.dart';
import 'package:xtremobile/core/models/playlist_config.dart';
import 'package:xtremobile/core/theme/app_colors.dart';
import 'package:xtremobile/core/api/dns_resolver.dart';
import 'package:xtremobile/mobile/theme/mobile_theme.dart';
import 'package:xtremobile/mobile/widgets/tv_focusable.dart';
import 'package:xtremobile/features/iptv/screens/lite_player_screen.dart';
import 'package:flutter/services.dart';
@@ -158,7 +155,8 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
),
data: (groupedChannels) {
// Prepare categories
var categories = groupedChannels.map((c) => c.categoryName).toSet().toList();
var categories =
groupedChannels.map((c) => c.categoryName).toSet().toList();
if (settings.liveTvKeywords.isNotEmpty) {
categories = categories
.where((cat) => settings.matchesLiveTvFilter(cat))
@@ -198,8 +196,9 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
.where((c) => favorites.contains(c.streamId))
.toList();
} else if (uiState.selectedCategory != null) {
displayedChannels =
groupedChannels.where((c) => c.categoryName == uiState.selectedCategory).toList();
displayedChannels = groupedChannels
.where((c) => c.categoryName == uiState.selectedCategory)
.toList();
}
}
@@ -86,7 +86,9 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab>
final service =
await ref.read(mobileXtreamServiceProvider(widget.playlist).future);
final movies = await service.getMovies();
final results = movies.where((m) => m.name.toLowerCase().contains(query.toLowerCase())).toList();
final results = movies
.where((m) => m.name.toLowerCase().contains(query.toLowerCase()))
.toList();
if (mounted && _searchQuery == query) {
setState(() {
@@ -110,7 +112,9 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab>
if (mounted) {
setState(() {
_categories = categories.map((c) => MapEntry(c.categoryId, c.categoryName)).toList()
_categories = categories
.map((c) => MapEntry(c.categoryId, c.categoryName))
.toList()
..sort((a, b) => a.value.compareTo(b.value));
_isLoading = false;
});
@@ -400,7 +404,8 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab>
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(bottom: 11),
contentPadding:
const EdgeInsets.only(bottom: 11),
),
onChanged: _onSearchChanged,
onSubmitted: (_) =>
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
// import 'package:dio_cache_interceptor_hive_store/dio_cache_interceptor_hive_store.dart';