- Nouveau logo vectoriel : bouton play dégradé cyan→bleu (#0A84FF) avec
traînées de vitesse, sur tuile graphite (#2C2C33→#1B1B1F) comme l'app
- scripts/generate_icons.py génère toutes les tailles depuis les SVG
(assets/branding/)
- Android : icône adaptative dans la zone sûre, icône ronde, écran de
lancement graphite avec logo
- Android TV / Fire TV : bannière 320x180, LEANBACK_LAUNCHER, écran
tactile et leanback non requis
- iOS : icône carrée sans alpha dédiée (app_icon_ios.png)
- Remplace l'ancien logo (JPEG avec damier incrusté) et corrige la
référence à logo_xtremobile.png inexistant dans les réglages
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GyudLt8TgggqbWWkqjB19K
Deuxième run du workflow Build iOS : volume_controller passe, la compilation
s'arrête maintenant sur device_info_plus 12.4.0 :
No visible @interface for 'NSProcessInfo' declares the selector
'isiOSAppOnVision'
Le plugin appelle cette propriété derrière un `@available(iOS 26.1, *)`, garde
d'exécution qui n'évite pas la compilation : le symbole doit exister dans les
en-têtes, donc le SDK d'Xcode 26.1 est requis alors que le runner macOS en
embarque un plus ancien. La 12.3.0 est la dernière version sans cet appel.
Même cause de fond que l'épinglage précédent : faute de pubspec.lock versionné,
la CI résout les plugins à leur dernière version, laquelle vise un outillage
Apple plus récent que le Flutter 3.35.3 et l'Xcode des workflows.
Un balayage des sources natives iOS de l'ensemble des plugins du graphe (API
`@available(iOS >= 18)` et API scene de Flutter 3.38) ne remonte que ces deux
paquets ; les douze autres compilent en l'état.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WoXgHivbAphDk9ArgKDg8Q
Premier run du workflow Build iOS : toute la chaîne passe (génération du
projet Xcode, Info.plist, CocoaPods, icônes), mais la compilation Swift
échoue sur volume_controller 3.4.4, tiré transitivement par media_kit_video :
Cannot find type 'FlutterSceneLifeCycleDelegate' in scope
Value of type 'any FlutterPluginRegistrar' has no member 'addSceneDelegate'
Ces API sont apparues dans Flutter 3.38. volume_controller les utilise depuis
la 3.4.2 sans relever sa contrainte `flutter:` (toujours >=3.0.0), si bien que
pub la sélectionne sur le Flutter 3.35.3 des workflows. La 3.4.1 est la
dernière version sans ces appels — vérifié en inspectant les sources iOS des
versions 3.4.0 à 3.4.4.
Le côté Android du plugin n'utilise pas ces API, ce qui explique que seul le
build iOS soit touché. Un balayage des autres plugins à code natif iOS du
projet ne remonte que screen_brightness_ios (2.1.3+), absent du graphe depuis
que media_kit_video 1.3.x ne dépend plus que de screen_brightness_android.
Ajoute par ailleurs au guide iOS la marche à suivre pour un appareil qui n'est
pas toujours sur le même réseau que l'ordinateur (SideStore, compte payant).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WoXgHivbAphDk9ArgKDg8Q
Le projet était Android-only : le dossier ios/ avait été supprimé et aucune
cible Apple n'existait. Le code Dart, lui, est resté portable (aucun appel
spécifique à Android) et media_kit_libs_video embarque déjà libmpv pour iOS.
- scripts/prepare_ios.sh régénère le projet Xcode via `flutter create` puis
applique les réglages nécessaires à une app IPTV : exception App Transport
Security (les serveurs Xtream sont en http:// simple), audio en arrière-plan,
orientations paysage et 4 sens sur iPad, autorisation réseau local, cible
iOS 13 exigée par media_kit et bundle id aligné sur l'applicationId Android.
Le script est idempotent et respecte un dossier ios/ déjà versionné.
- Nouveau workflow Build iOS : runner macOS, build --no-codesign, empaquetage
en IPA non signé publié sur la Release de la version, à côté de l'APK.
Pas de déclenchement sur les PR, un runner macOS coûtant 10x en minutes.
- IOS_GUIDE.md documente les voies d'installation hors App Store (AltStore /
SideStore, Sideloadly, compte développeur, TestFlight) et leurs limites.
- flutter_launcher_icons : image_path pointait sur app-icon.png, absent du
dépôt ; correction vers le logo existant et ajout de la génération iOS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WoXgHivbAphDk9ArgKDg8Q
Add a visible playlist button in both players (native + lite) that opens
the TiviMate-style channel sidebar (channels of the current category).
The sidebar existed in the native player but was only reachable via an
edge swipe or the M/Menu key; the lite player had none.
- New OSD button next to channel zapping (live only)
- Lite player: full sidebar port (swipe from right edge, M/Menu key)
- D-pad support: focus lands on the current channel when the list opens,
arrows navigate, OK switches channel, Back/Menu closes
- Auto-hide timer (6s) restarted on D-pad focus and touch scroll
- Bump version to 1.8.0+15
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EG1frWE7suYF7hp4q2sDiR
Adds a Build APK workflow: on every push to main it builds the release
APK with Flutter 3.35.3 and publishes it as a GitHub Release tagged
with the pubspec version (v1.7.0 → xtremobile-v1.7.0.apk). On pull
requests and manual runs the APK is built and uploaded as an artifact
only. Bumps app version to 1.7.0+14 for this release.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0156exq7fejVrD3HKU3MmS8X
Porting the palette was not enough: the Warm Cinema charter only reached the
widgets that read from AppColors. Nineteen screen and widget files still painted
Apple TV values inline, so the app kept showing blue — most visibly on the
selected navigation pill.
Swept out:
- 0xFF0A84FF (Apple blue) on the selected nav pill, category card icons and the
"add playlist" button
- 0xFF4FC3F7 and 0xFF1565C0 in the player overlays
- Colors.blueAccent / Colors.blue in dialogs
- Apple greys 1C1C1E / 2C2C2E / 3A3A3C / 8E8E93 -> warm charcoals
- 128 Colors.white* -> the onSurfaceNN cream ladder (a pure white on a warm
ground reads blue, which is the charter's whole point)
- Colors.red / green / amber / yellow / grey* -> error, success, ratingGold,
outlineVariant
- pure black ink on light fills -> onPrimaryFixed, a warm near-black
- the white focus glow -> an ember glow
Deliberately left true black: the video surface backgrounds and the scrims over
posters and video, where a warm tint would clash with the picture.
Adds the onPrimaryFixed / primaryFixed / onSurface70 tokens the sweep needed.
Verified: no Material or Apple colour literal remains outside lib/core/theme;
flutter analyze reports no errors; 19/19 tests pass; release APK builds.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>