mirror of
https://github.com/R0m1k3/xtremobile.git
synced 2026-10-17 04:08:29 +02:00
feat: XMLTV EPG fallback, Warm Cinema theme, background release
Align the Android app with xtremflow on three fronts. EPG: add XmltvService, a streaming XMLTV parser (gunzip-aware, indexed to a -3h/+18h window, JSON disk cache with a 6h TTL). XtreamServiceMobile now falls back through the provider's xmltv.php, a user-supplied URL, then a community guide whenever get_short_epg returns nothing. Channels are matched on epg_channel_id first, then on a normalized name (accents, HD/FHD/4K suffixes, "FR:" and "|FR|" prefixes). A streamId -> Channel index populated by getLiveChannels supplies those keys, so no getShortEPG call site changed. EPG requests are also funnelled through a 3-slot semaphore, as in xtremflow: a 30-tile grid used to fire 30 parallel player_api.php calls, which rate-limited panels answered with errors, emptying the guide for the whole screen. Theme: port the Warm Cinema charter (ember/charcoal/cream, Fraunces + Karla) into app_colors, app_theme and app_decorations. The 21 Apple TV colour names already in use are kept as compatibility aliases. mobile_theme now derives from AppTheme instead of duplicating its 390 lines. Playback lifecycle: stop reacting to AppLifecycleState.inactive, which fires on transient Android interruptions such as pulling down the notification shade and was killing playback. Both engines now release on paused/hidden/detached via _releasePlayback(): stream stopped, decoder released, timers cancelled, wakelock dropped. An _isReleased latch keeps the watchdog and reconnect paths from restarting a stream from the background. Long-run stability: cancel the six player stream subscriptions on dispose, cap demuxer-max-back-bytes at 8MB (mpv defaults to 50MiB, which combined with the 150MB readahead pushed the native heap toward an Android memory kill after a few hours), rebuild on position only while the controls are visible, and dispose the Lite player's focus nodes. Startup: prewarmHost() pre-resolves DNS and opens then closes a bare TCP/TLS socket before playback. No HTTP request is issued, so no provider connection slot is consumed. Capped at 1.5s. Verified: flutter analyze clean on all touched files; 19/19 tests, including a run over a real 46MB/69802-programme dump (517 channels indexed in 1.1s, 5/5 name probes matched); flutter build apk --release succeeds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
63e77c5bc5
commit
8d74bbb320
15 files changed
+2138
-852
No files matched your search
@@ -5,6 +5,7 @@ import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:xtremobile/mobile/providers/mobile_settings_providers.dart';
|
||||
import 'package:xtremobile/mobile/widgets/tv_focusable.dart';
|
||||
import 'package:xtremobile/core/theme/app_decorations.dart';
|
||||
import 'package:xtremobile/core/theme/app_theme.dart';
|
||||
import 'package:xtremobile/core/providers/theme_provider.dart';
|
||||
import 'package:xtremobile/features/iptv/screens/mobile_playlist_selection_screen.dart';
|
||||
|
||||
@@ -20,6 +21,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
||||
late TextEditingController _liveTvController;
|
||||
late TextEditingController _moviesController;
|
||||
late TextEditingController _seriesController;
|
||||
late TextEditingController _xmltvController;
|
||||
bool _initialized = false;
|
||||
bool _isRefreshingCache = false;
|
||||
|
||||
@@ -29,6 +31,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
||||
_liveTvController = TextEditingController();
|
||||
_moviesController = TextEditingController();
|
||||
_seriesController = TextEditingController();
|
||||
_xmltvController = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -36,6 +39,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
||||
_liveTvController.dispose();
|
||||
_moviesController.dispose();
|
||||
_seriesController.dispose();
|
||||
_xmltvController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -44,6 +48,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
||||
_liveTvController.text = settings.liveTvKeywords.join(', ');
|
||||
_moviesController.text = settings.moviesKeywords.join(', ');
|
||||
_seriesController.text = settings.seriesKeywords.join(', ');
|
||||
_xmltvController.text = settings.xmltvUrl;
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
@@ -167,6 +172,38 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// === GUIDE TV (EPG) ===
|
||||
_buildSectionHeader('Guide TV (EPG)'),
|
||||
|
||||
_buildSettingItem(
|
||||
icon: Icons.public,
|
||||
title: 'EPG communautaire',
|
||||
subtitle:
|
||||
'Repli quand le fournisseur ne renvoie aucun programme',
|
||||
value: settings.useCommunityEpg ? 'Activé' : 'Désactivé',
|
||||
onTap: () => ref
|
||||
.read(mobileSettingsProvider.notifier)
|
||||
.toggleCommunityEpg(!settings.useCommunityEpg),
|
||||
),
|
||||
|
||||
_buildSettingItem(
|
||||
icon: Icons.link,
|
||||
title: 'URL XMLTV personnalisée',
|
||||
subtitle: settings.xmltvUrl.isEmpty
|
||||
? 'Aucune — xmltv.php du fournisseur, puis source communautaire'
|
||||
: settings.xmltvUrl,
|
||||
value: settings.xmltvUrl.isEmpty ? 'Ajouter' : 'Modifier',
|
||||
onTap: () => _showKeyboardDialog(
|
||||
'URL XMLTV',
|
||||
_xmltvController,
|
||||
(val) => ref
|
||||
.read(mobileSettingsProvider.notifier)
|
||||
.setXmltvUrl(val),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// === FILTRES ===
|
||||
_buildSectionHeader('Filtres de Contenu'),
|
||||
|
||||
@@ -417,11 +454,9 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
||||
padding: const EdgeInsets.only(left: 4, bottom: 8, top: 8),
|
||||
child: Text(
|
||||
title.toUpperCase(),
|
||||
style: GoogleFonts.inter(
|
||||
style: AppTheme.eyebrow(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
letterSpacing: 1.2,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user