mirror of
https://github.com/R0m1k3/xtremobile.git
synced 2026-10-11 17:29:26 +02:00
fix(theme): remove every hardcoded Apple/Material colour left in the UI
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>
This commit is contained in:
1 parent
8d74bbb320
commit
694b1257b9
21 files changed
+221
-184
No files matched your search
@@ -53,6 +53,14 @@ class AppColors {
|
|||||||
/// en restant la même couleur perçue.
|
/// en restant la même couleur perçue.
|
||||||
static const Color primaryFill = Color(0xFFA8360C);
|
static const Color primaryFill = Color(0xFFA8360C);
|
||||||
|
|
||||||
|
/// Encre chaude — remplace le noir pur pour du texte/des icônes posés sur un
|
||||||
|
/// remplissage clair (crème, ember clair). Un noir pur sur une teinte chaude
|
||||||
|
/// paraît sale ; ce brun très sombre garde le contraste sans le décalage.
|
||||||
|
static const Color onPrimaryFixed = Color(0xFF360F00);
|
||||||
|
static const Color primaryFixed = Color(0xFFFFDBC8);
|
||||||
|
static const Color primaryFixedDim = Color(0xFFFFB68C);
|
||||||
|
static const Color onPrimaryFixedVariant = Color(0xFF7A2C08);
|
||||||
|
|
||||||
// ============ SECONDARY (Terre cuite / argile) ============
|
// ============ SECONDARY (Terre cuite / argile) ============
|
||||||
static const Color secondary = Color(0xFFE7C3AC);
|
static const Color secondary = Color(0xFFE7C3AC);
|
||||||
static const Color onSecondary = Color(0xFF442A1B);
|
static const Color onSecondary = Color(0xFF442A1B);
|
||||||
@@ -92,6 +100,7 @@ class AppColors {
|
|||||||
static const Color onSurface24 = Color(0x3DF3E9DF);
|
static const Color onSurface24 = Color(0x3DF3E9DF);
|
||||||
static const Color onSurface38 = Color(0x61F3E9DF);
|
static const Color onSurface38 = Color(0x61F3E9DF);
|
||||||
static const Color onSurface54 = Color(0x8AF3E9DF);
|
static const Color onSurface54 = Color(0x8AF3E9DF);
|
||||||
|
static const Color onSurface70 = Color(0xB3F3E9DF);
|
||||||
|
|
||||||
// ============ STATUS ============
|
// ============ STATUS ============
|
||||||
static const Color success = Color(0xFF9BC46A); // olive lumineux
|
static const Color success = Color(0xFF9BC46A); // olive lumineux
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ library;
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
/// Standard cache manager with 200MB size limit
|
/// Standard cache manager with 200MB size limit
|
||||||
class AppCacheManager {
|
class AppCacheManager {
|
||||||
@@ -103,7 +104,7 @@ class ImageCacheConfig {
|
|||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF2C2C2E),
|
color: AppColors.surfaceContainer,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -111,10 +112,10 @@ class ImageCacheConfig {
|
|||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF3A3A3C),
|
color: AppColors.surfaceContainerHigh,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.image_not_supported, color: Color(0xFF8E8E93)),
|
child: const Icon(Icons.image_not_supported, color: AppColors.textTertiary),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ class _HeroCarouselState extends State<HeroCarousel> {
|
|||||||
style: GoogleFonts.outfit(
|
style: GoogleFonts.outfit(
|
||||||
fontSize: 32,
|
fontSize: 32,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
),
|
),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
@@ -161,7 +161,7 @@ class _HeroCarouselState extends State<HeroCarousel> {
|
|||||||
item.subtitle!,
|
item.subtitle!,
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: Colors.white.withOpacity(0.8),
|
color: AppColors.onSurface.withOpacity(0.8),
|
||||||
),
|
),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
@@ -227,8 +227,8 @@ class _HeroButtonState extends State<_HeroButton> {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.isPrimary
|
color: widget.isPrimary
|
||||||
? (_isHovered ? Colors.white : Colors.white.withOpacity(0.9))
|
? (_isHovered ? AppColors.onSurface : AppColors.onSurface.withOpacity(0.9))
|
||||||
: (_isHovered ? Colors.white.withOpacity(0.2) : Colors.white.withOpacity(0.1)),
|
: (_isHovered ? AppColors.onSurface.withOpacity(0.2) : AppColors.onSurface.withOpacity(0.1)),
|
||||||
borderRadius: BorderRadius.circular(AppTheme.radiusFull),
|
borderRadius: BorderRadius.circular(AppTheme.radiusFull),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -236,14 +236,14 @@ class _HeroButtonState extends State<_HeroButton> {
|
|||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
widget.icon,
|
widget.icon,
|
||||||
color: widget.isPrimary ? Colors.black : Colors.white,
|
color: widget.isPrimary ? AppColors.onPrimaryFixed : AppColors.onSurface,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
Text(
|
||||||
widget.label,
|
widget.label,
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: widget.isPrimary ? Colors.black : Colors.white,
|
color: widget.isPrimary ? AppColors.onPrimaryFixed : AppColors.onSurface,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class _GradientButtonState extends State<GradientButton>
|
|||||||
height: 20,
|
height: 20,
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
color: Colors.black,
|
color: AppColors.onPrimaryFixed,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Row(
|
: Row(
|
||||||
@@ -143,13 +143,13 @@ class _GradientButtonState extends State<GradientButton>
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
if (widget.icon != null) ...[
|
if (widget.icon != null) ...[
|
||||||
Icon(widget.icon, color: Colors.black, size: 20),
|
Icon(widget.icon, color: AppColors.onPrimaryFixed, size: 20),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
Text(
|
Text(
|
||||||
widget.label,
|
widget.label,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.black,
|
color: AppColors.onPrimaryFixed,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
),
|
),
|
||||||
@@ -247,12 +247,12 @@ class LiveBadge extends StatelessWidget {
|
|||||||
child: const Row(
|
child: const Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.circle, size: 6, color: Colors.white),
|
Icon(Icons.circle, size: 6, color: AppColors.onSurface),
|
||||||
SizedBox(width: 4),
|
SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
'LIVE',
|
'LIVE',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
@@ -427,11 +427,11 @@ class _MediaCardState extends State<MediaCard>
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.star, size: 10, color: Color(0xFFFFD700)),
|
const Icon(Icons.star, size: 10, color: AppColors.ratingGold),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
widget.rating!,
|
widget.rating!,
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold),
|
style: const TextStyle(color: AppColors.onSurface, fontSize: 10, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -449,7 +449,7 @@ class _MediaCardState extends State<MediaCard>
|
|||||||
color: AppColors.success,
|
color: AppColors.success,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.check, size: 12, color: Colors.white),
|
child: const Icon(Icons.check, size: 12, color: AppColors.onSurface),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class DigitalClock extends StatefulWidget {
|
class DigitalClock extends StatefulWidget {
|
||||||
const DigitalClock({super.key});
|
const DigitalClock({super.key});
|
||||||
@@ -31,16 +32,16 @@ class _DigitalClockState extends State<DigitalClock> {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white.withOpacity(0.1),
|
color: AppColors.onSurface.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(color: Colors.white.withOpacity(0.05)),
|
border: Border.all(color: AppColors.onSurface.withOpacity(0.05)),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
timeString,
|
timeString,
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class ThemedLoading extends StatelessWidget {
|
class ThemedLoading extends StatelessWidget {
|
||||||
const ThemedLoading({super.key});
|
const ThemedLoading({super.key});
|
||||||
@@ -11,7 +12,7 @@ class ThemedLoading extends StatelessWidget {
|
|||||||
center: Alignment(0, -0.2),
|
center: Alignment(0, -0.2),
|
||||||
radius: 1.5,
|
radius: 1.5,
|
||||||
colors: [
|
colors: [
|
||||||
Color(0xFF2C2C2E),
|
AppColors.surfaceContainerHigh,
|
||||||
Color(0xFF000000),
|
Color(0xFF000000),
|
||||||
],
|
],
|
||||||
stops: [0.0, 1.0],
|
stops: [0.0, 1.0],
|
||||||
@@ -19,7 +20,7 @@ class ThemedLoading extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: const Center(
|
child: const Center(
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
strokeWidth: 3,
|
strokeWidth: 3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -416,6 +416,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
: widget.title;
|
: widget.title;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
// True black behind the video surface, never the warm ink.
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
body: GestureDetector(
|
body: GestureDetector(
|
||||||
onTap: _onUserInteraction,
|
onTap: _onUserInteraction,
|
||||||
@@ -453,7 +454,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 28,
|
size: 28,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -472,7 +473,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
child: Text(
|
child: Text(
|
||||||
_currentTime,
|
_currentTime,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -495,7 +496,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
_errorMessage!,
|
_errorMessage!,
|
||||||
style: const TextStyle(color: Colors.red),
|
style: const TextStyle(color: AppColors.error),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -554,7 +555,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black.withOpacity(0.7),
|
color: Colors.black.withOpacity(0.7),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: Colors.white10),
|
border: Border.all(color: AppColors.onSurface12),
|
||||||
),
|
),
|
||||||
child: IntrinsicHeight(
|
child: IntrinsicHeight(
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -579,7 +580,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.skip_previous,
|
Icons.skip_previous,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 36,
|
size: 36,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -591,7 +592,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
_isPlaying
|
_isPlaying
|
||||||
? Icons.pause_circle_filled
|
? Icons.pause_circle_filled
|
||||||
: Icons.play_circle_filled,
|
: Icons.play_circle_filled,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 56,
|
size: 56,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -605,7 +606,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.skip_next,
|
Icons.skip_next,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 36,
|
size: 36,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -642,7 +643,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons
|
Icons
|
||||||
.grid_on, // Icon representing interlaced grid/mesh
|
.grid_on, // Icon representing interlaced grid/mesh
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 32,
|
size: 32,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -684,7 +685,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
child: Text(
|
child: Text(
|
||||||
title,
|
title,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -710,7 +711,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: progress,
|
value: progress,
|
||||||
backgroundColor: Colors.white10,
|
backgroundColor: AppColors.onSurface12,
|
||||||
color: AppColors.primary,
|
color: AppColors.primary,
|
||||||
minHeight: 4,
|
minHeight: 4,
|
||||||
),
|
),
|
||||||
@@ -718,7 +719,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
Text(
|
Text(
|
||||||
next,
|
next,
|
||||||
style: const TextStyle(color: Colors.white54, fontSize: 12),
|
style: const TextStyle(color: AppColors.onSurface54, fontSize: 12),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
@@ -758,7 +759,7 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
|||||||
min: 0,
|
min: 0,
|
||||||
max: _duration.inSeconds.toDouble(),
|
max: _duration.inSeconds.toDouble(),
|
||||||
activeColor: AppColors.primary,
|
activeColor: AppColors.primary,
|
||||||
inactiveColor: Colors.white24,
|
inactiveColor: AppColors.onSurface24,
|
||||||
onChanged: (v) => setState(() {
|
onChanged: (v) => setState(() {
|
||||||
_position = Duration(seconds: v.toInt());
|
_position = Duration(seconds: v.toInt());
|
||||||
_isSeeking = true;
|
_isSeeking = true;
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ class _MobilePlaylistScreenState extends ConsumerState<MobilePlaylistScreen> {
|
|||||||
? 'Playlist modifiée'
|
? 'Playlist modifiée'
|
||||||
: 'Playlist ajoutée',
|
: 'Playlist ajoutée',
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: AppColors.success,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class _MobilePlaylistSelectionScreenState
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'Erreur de chargement',
|
'Erreur de chargement',
|
||||||
style: GoogleFonts.inter(color: Colors.white),
|
style: GoogleFonts.inter(color: AppColors.onSurface),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => ref.invalidate(playlistsProvider),
|
onPressed: () => ref.invalidate(playlistsProvider),
|
||||||
@@ -143,14 +143,14 @@ class _MobilePlaylistSelectionScreenState
|
|||||||
const Icon(
|
const Icon(
|
||||||
Icons.playlist_add,
|
Icons.playlist_add,
|
||||||
size: 64,
|
size: 64,
|
||||||
color: Colors.white54,
|
color: AppColors.onSurface54,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Text(
|
Text(
|
||||||
'Aucune playlist configurée',
|
'Aucune playlist configurée',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: Colors.white70,
|
color: AppColors.onSurface70,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
@@ -163,18 +163,18 @@ class _MobilePlaylistSelectionScreenState
|
|||||||
vertical: 14,
|
vertical: 14,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF0A84FF),
|
color: AppColors.primaryFill,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: const Row(
|
child: const Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.add, color: Colors.white, size: 20),
|
Icon(Icons.add, color: AppColors.onSurface, size: 20),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
Text(
|
Text(
|
||||||
'Ajouter une Playlist',
|
'Ajouter une Playlist',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
),
|
),
|
||||||
@@ -268,21 +268,21 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (ctx) => AlertDialog(
|
builder: (ctx) => AlertDialog(
|
||||||
backgroundColor: AppColors.surface,
|
backgroundColor: AppColors.surface,
|
||||||
title: Text(label, style: const TextStyle(color: Colors.white)),
|
title: Text(label, style: const TextStyle(color: AppColors.onSurface)),
|
||||||
content: TextField(
|
content: TextField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
obscureText: obscure,
|
obscureText: obscure,
|
||||||
keyboardType: keyboardType,
|
keyboardType: keyboardType,
|
||||||
textInputAction: TextInputAction.done,
|
textInputAction: TextInputAction.done,
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: AppColors.onSurface),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelStyle: TextStyle(color: Colors.white70),
|
labelStyle: TextStyle(color: AppColors.onSurface70),
|
||||||
enabledBorder: UnderlineInputBorder(
|
enabledBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.white24),
|
borderSide: BorderSide(color: AppColors.onSurface24),
|
||||||
),
|
),
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.white),
|
borderSide: BorderSide(color: AppColors.onSurface),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onSubmitted: (val) => Navigator.pop(ctx, val),
|
onSubmitted: (val) => Navigator.pop(ctx, val),
|
||||||
@@ -327,7 +327,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white.withOpacity(0.07),
|
color: AppColors.onSurface.withOpacity(0.07),
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -341,7 +341,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white70,
|
color: AppColors.onSurface70,
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
@@ -350,7 +350,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
Text(
|
Text(
|
||||||
displayValue,
|
displayValue,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: value.isEmpty ? Colors.white38 : Colors.white,
|
color: value.isEmpty ? AppColors.onSurface38 : AppColors.onSurface,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
@@ -360,7 +360,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Icon(Icons.edit, color: Colors.white38, size: 18),
|
const Icon(Icons.edit, color: AppColors.onSurface38, size: 18),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -374,7 +374,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
backgroundColor: AppColors.surface,
|
backgroundColor: AppColors.surface,
|
||||||
title: Text(
|
title: Text(
|
||||||
widget.isEditing ? 'Modifier la Playlist' : 'Ajouter une Playlist',
|
widget.isEditing ? 'Modifier la Playlist' : 'Ajouter une Playlist',
|
||||||
style: GoogleFonts.inter(color: Colors.white),
|
style: GoogleFonts.inter(color: AppColors.onSurface),
|
||||||
),
|
),
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: 480,
|
width: 480,
|
||||||
@@ -435,8 +435,8 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (ctx) => AlertDialog(
|
builder: (ctx) => AlertDialog(
|
||||||
backgroundColor: AppColors.surface,
|
backgroundColor: AppColors.surface,
|
||||||
title: const Text('Confirmer', style: TextStyle(color: Colors.white)),
|
title: const Text('Confirmer', style: TextStyle(color: AppColors.onSurface)),
|
||||||
content: const Text('Supprimer cette playlist ?', style: TextStyle(color: Colors.white70)),
|
content: const Text('Supprimer cette playlist ?', style: TextStyle(color: AppColors.onSurface70)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(ctx, false),
|
onPressed: () => Navigator.pop(ctx, false),
|
||||||
@@ -444,7 +444,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(ctx, true),
|
onPressed: () => Navigator.pop(ctx, true),
|
||||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
style: TextButton.styleFrom(foregroundColor: AppColors.error),
|
||||||
child: const Text('Supprimer'),
|
child: const Text('Supprimer'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -458,7 +458,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
child: Text('Supprimer', style: TextStyle(color: Colors.red)),
|
child: Text('Supprimer', style: TextStyle(color: AppColors.error)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TVFocusable(
|
TVFocusable(
|
||||||
@@ -466,7 +466,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
child: Text('Annuler', style: TextStyle(color: Colors.white70)),
|
child: Text('Annuler', style: TextStyle(color: AppColors.onSurface70)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TVFocusable(
|
TVFocusable(
|
||||||
@@ -482,14 +482,14 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _name.isEmpty || _dns.isEmpty
|
color: _name.isEmpty || _dns.isEmpty
|
||||||
? Colors.white12
|
? AppColors.onSurface12
|
||||||
: AppColors.primary,
|
: AppColors.primary,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
_isSaving ? '...' : 'Enregistrer',
|
_isSaving ? '...' : 'Enregistrer',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class _MobileSeriesDetailScreenState
|
|||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
icon: const Icon(Icons.arrow_back, color: AppColors.onSurface),
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
tooltip: 'Back',
|
tooltip: 'Back',
|
||||||
),
|
),
|
||||||
@@ -149,7 +149,7 @@ class _MobileSeriesDetailScreenState
|
|||||||
maxHeightDiskCache: 720,
|
maxHeightDiskCache: 720,
|
||||||
cacheManager: AppCacheManager.instance,
|
cacheManager: AppCacheManager.instance,
|
||||||
errorWidget: (_, __, ___) =>
|
errorWidget: (_, __, ___) =>
|
||||||
Container(color: Colors.grey.shade900),
|
Container(color: AppColors.surfaceContainerLowest),
|
||||||
),
|
),
|
||||||
// Gradient Overlay
|
// Gradient Overlay
|
||||||
Container(
|
Container(
|
||||||
@@ -190,7 +190,7 @@ class _MobileSeriesDetailScreenState
|
|||||||
const Icon(
|
const Icon(
|
||||||
Icons.star,
|
Icons.star,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: Colors.amber,
|
color: AppColors.ratingGold,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
@@ -261,15 +261,15 @@ class _MobileSeriesDetailScreenState
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
backgroundColor: isDark
|
backgroundColor: isDark
|
||||||
? const Color(0xFF1C1C1E)
|
? AppColors.surfaceContainer
|
||||||
: Colors.grey.shade300,
|
: AppColors.surfaceContainerHigh,
|
||||||
selectedColor: isDark ? Colors.white : Colors.blue,
|
selectedColor: isDark ? AppColors.onSurface : AppColors.primaryFill,
|
||||||
labelStyle: TextStyle(
|
labelStyle: TextStyle(
|
||||||
color: isSelected
|
color: isSelected
|
||||||
? (isDark ? Colors.black : Colors.white)
|
? (isDark ? AppColors.onPrimaryFixed : AppColors.onSurface)
|
||||||
: (isDark
|
: (isDark
|
||||||
? Colors.grey.shade400
|
? AppColors.textSecondary
|
||||||
: Colors.grey.shade700),
|
: AppColors.outlineVariant),
|
||||||
fontWeight:
|
fontWeight:
|
||||||
isSelected ? FontWeight.w600 : FontWeight.w400,
|
isSelected ? FontWeight.w600 : FontWeight.w400,
|
||||||
),
|
),
|
||||||
@@ -323,10 +323,10 @@ class _MobileSeriesDetailScreenState
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Force dark mode colors since background is hardcoded dark
|
// Force dark mode colors since background is hardcoded dark
|
||||||
const textColor = Colors.white;
|
const textColor = AppColors.onSurface;
|
||||||
final secondaryTextColor = Colors.grey.shade400;
|
final secondaryTextColor = AppColors.textSecondary;
|
||||||
const surfaceColor = Color(0xFF1C1C1E);
|
const surfaceColor = AppColors.surfaceContainer;
|
||||||
const primaryColor = Colors.white; // Or accent color if preferred
|
const primaryColor = AppColors.onSurface; // Or accent color if preferred
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -356,7 +356,7 @@ class _MobileSeriesDetailScreenState
|
|||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
border: Border(bottom: BorderSide(color: Colors.white10)),
|
border: Border(bottom: BorderSide(color: AppColors.onSurface12)),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -374,7 +374,7 @@ class _MobileSeriesDetailScreenState
|
|||||||
child: Icon(
|
child: Icon(
|
||||||
isWatched ? Icons.check : Icons.play_arrow,
|
isWatched ? Icons.check : Icons.play_arrow,
|
||||||
color: isWatched
|
color: isWatched
|
||||||
? Colors.black // Checkmark on white bg
|
? AppColors.onPrimaryFixed // Checkmark on white bg
|
||||||
: primaryColor, // Play icon
|
: primaryColor, // Play icon
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
@@ -413,7 +413,7 @@ class _MobileSeriesDetailScreenState
|
|||||||
LinearProgressIndicator(
|
LinearProgressIndicator(
|
||||||
value: progress,
|
value: progress,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
valueColor: const AlwaysStoppedAnimation<Color>(Colors.red),
|
valueColor: const AlwaysStoppedAnimation<Color>(AppColors.error),
|
||||||
minHeight: 2,
|
minHeight: 2,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -654,7 +654,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
'Reprise à ${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}',
|
'Reprise à ${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}',
|
||||||
),
|
),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
backgroundColor: Colors.green.shade700,
|
backgroundColor: AppColors.success,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -1293,6 +1293,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
// Loading Overlay — black only on FIRST load
|
// Loading Overlay — black only on FIRST load
|
||||||
if (_isLoading && _errorMessage == null)
|
if (_isLoading && _errorMessage == null)
|
||||||
Container(
|
Container(
|
||||||
|
// True black, not the warm ink: this sits over the video surface.
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
child: _buildLoadingView(),
|
child: _buildLoadingView(),
|
||||||
),
|
),
|
||||||
@@ -1313,7 +1314,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
height: 20,
|
height: 20,
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
color: Colors.white70,
|
color: AppColors.onSurface70,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1349,7 +1350,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
),
|
),
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
),
|
),
|
||||||
@@ -1380,7 +1381,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
@@ -1392,7 +1393,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
_currentTime,
|
_currentTime,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white70,
|
color: AppColors.onSurface70,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
@@ -1485,7 +1486,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black.withOpacity(0.7),
|
color: Colors.black.withOpacity(0.7),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: Colors.white10),
|
border: Border.all(color: AppColors.onSurface12),
|
||||||
),
|
),
|
||||||
child: IntrinsicHeight(
|
child: IntrinsicHeight(
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -1506,7 +1507,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
onFocus: _resetControlsTimer,
|
onFocus: _resetControlsTimer,
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.skip_previous,
|
Icons.skip_previous,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 36,
|
size: 36,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1521,7 +1522,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
_isPlaying
|
_isPlaying
|
||||||
? Icons.pause_circle_filled
|
? Icons.pause_circle_filled
|
||||||
: Icons.play_circle_filled,
|
: Icons.play_circle_filled,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 56,
|
size: 56,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1534,7 +1535,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
onFocus: _resetControlsTimer,
|
onFocus: _resetControlsTimer,
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.skip_next,
|
Icons.skip_next,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 36,
|
size: 36,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1570,7 +1571,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
onFocus: _resetControlsTimer,
|
onFocus: _resetControlsTimer,
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.grid_off,
|
Icons.grid_off,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 32,
|
size: 32,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1618,7 +1619,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
imageUrl: widget.channels![_currentIndex].streamIcon,
|
imageUrl: widget.channels![_currentIndex].streamIcon,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
errorWidget: (_, __, ___) =>
|
errorWidget: (_, __, ___) =>
|
||||||
const Icon(Icons.tv, color: Colors.white38),
|
const Icon(Icons.tv, color: AppColors.onSurface38),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -1628,7 +1629,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white70,
|
color: AppColors.onSurface70,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
@@ -1639,7 +1640,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
nowPlaying,
|
nowPlaying,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -1654,7 +1655,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
startTime,
|
startTime,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white54, fontSize: 11),
|
color: AppColors.onSurface54, fontSize: 11),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -1663,9 +1664,9 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: epgProgress.clamp(0.0, 1.0),
|
value: epgProgress.clamp(0.0, 1.0),
|
||||||
minHeight: 4,
|
minHeight: 4,
|
||||||
backgroundColor: Colors.white24,
|
backgroundColor: AppColors.onSurface24,
|
||||||
valueColor: const AlwaysStoppedAnimation<Color>(
|
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||||
Color(0xFF4FC3F7),
|
AppColors.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1674,7 +1675,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
endTime,
|
endTime,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white54, fontSize: 11),
|
color: AppColors.onSurface54, fontSize: 11),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -1714,7 +1715,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black.withOpacity(0.82),
|
color: Colors.black.withOpacity(0.82),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: Colors.white12),
|
border: Border.all(color: AppColors.onSurface12),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -1728,7 +1729,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
margin: const EdgeInsets.only(right: 16),
|
margin: const EdgeInsets.only(right: 16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
color: Colors.white10,
|
color: AppColors.onSurface12,
|
||||||
),
|
),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
@@ -1736,7 +1737,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
imageUrl: ch.streamIcon,
|
imageUrl: ch.streamIcon,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
errorWidget: (_, __, ___) =>
|
errorWidget: (_, __, ___) =>
|
||||||
const Icon(Icons.tv, color: Colors.white38, size: 32),
|
const Icon(Icons.tv, color: AppColors.onSurface38, size: 32),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1747,9 +1748,9 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
margin: const EdgeInsets.only(right: 16),
|
margin: const EdgeInsets.only(right: 16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
color: Colors.white10,
|
color: AppColors.onSurface12,
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.tv, color: Colors.white38, size: 32),
|
child: const Icon(Icons.tv, color: AppColors.onSurface38, size: 32),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Channel info
|
// Channel info
|
||||||
@@ -1765,13 +1766,13 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
horizontal: 6, vertical: 2),
|
horizontal: 6, vertical: 2),
|
||||||
margin: const EdgeInsets.only(right: 8),
|
margin: const EdgeInsets.only(right: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF1565C0),
|
color: const AppColors.primaryFill,
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'CH $chNum',
|
'CH $chNum',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -1781,7 +1782,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: Text(
|
child: Text(
|
||||||
ch.name,
|
ch.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -1797,9 +1798,9 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 3,
|
height: 3,
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
backgroundColor: Colors.white24,
|
backgroundColor: AppColors.onSurface24,
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(
|
valueColor: AlwaysStoppedAnimation<Color>(
|
||||||
Color(0xFF4FC3F7)),
|
AppColors.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1808,7 +1809,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
nowPlaying,
|
nowPlaying,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white70,
|
color: AppColors.onSurface70,
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
@@ -1820,9 +1821,9 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: epgProgress.clamp(0.0, 1.0),
|
value: epgProgress.clamp(0.0, 1.0),
|
||||||
minHeight: 3,
|
minHeight: 3,
|
||||||
backgroundColor: Colors.white24,
|
backgroundColor: AppColors.onSurface24,
|
||||||
valueColor: const AlwaysStoppedAnimation<Color>(
|
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||||
Color(0xFF4FC3F7)),
|
AppColors.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1861,18 +1862,18 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 8),
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 8),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
bottom: BorderSide(color: Colors.white12),
|
bottom: BorderSide(color: AppColors.onSurface12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.list, color: Colors.white70, size: 18),
|
const Icon(Icons.list, color: AppColors.onSurface70, size: 18),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
const Expanded(
|
const Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Chaînes',
|
'Chaînes',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -1881,7 +1882,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => setState(() => _showChannelList = false),
|
onTap: () => setState(() => _showChannelList = false),
|
||||||
child: const Icon(Icons.close,
|
child: const Icon(Icons.close,
|
||||||
color: Colors.white54, size: 18),
|
color: AppColors.onSurface54, size: 18),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -1903,12 +1904,12 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isActive
|
color: isActive
|
||||||
? const Color(0xFF1565C0).withOpacity(0.6)
|
? AppColors.primaryFill.withValues(alpha: 0.6)
|
||||||
: Colors.transparent,
|
: Colors.transparent,
|
||||||
border: isActive
|
border: isActive
|
||||||
? const Border(
|
? const Border(
|
||||||
left: BorderSide(
|
left: BorderSide(
|
||||||
color: Color(0xFF4FC3F7),
|
color: AppColors.primary,
|
||||||
width: 3,
|
width: 3,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1924,7 +1925,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
height: 40,
|
height: 40,
|
||||||
margin: const EdgeInsets.only(right: 10),
|
margin: const EdgeInsets.only(right: 10),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white10,
|
color: AppColors.onSurface12,
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
child: ch.streamIcon.isNotEmpty
|
child: ch.streamIcon.isNotEmpty
|
||||||
@@ -1935,12 +1936,12 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
errorWidget: (_, __, ___) =>
|
errorWidget: (_, __, ___) =>
|
||||||
const Icon(Icons.tv,
|
const Icon(Icons.tv,
|
||||||
color: Colors.white38,
|
color: AppColors.onSurface38,
|
||||||
size: 20),
|
size: 20),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const Icon(Icons.tv,
|
: const Icon(Icons.tv,
|
||||||
color: Colors.white38, size: 20),
|
color: AppColors.onSurface38, size: 20),
|
||||||
),
|
),
|
||||||
// Name + num
|
// Name + num
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -1952,8 +1953,8 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
ch.name,
|
ch.name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: isActive
|
color: isActive
|
||||||
? Colors.white
|
? AppColors.onSurface
|
||||||
: Colors.white70,
|
: AppColors.onSurface70,
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: isActive
|
fontWeight: isActive
|
||||||
? FontWeight.bold
|
? FontWeight.bold
|
||||||
@@ -1965,7 +1966,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
'CH ${index + 1}',
|
'CH ${index + 1}',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white38,
|
color: AppColors.onSurface38,
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1976,7 +1977,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
if (isActive)
|
if (isActive)
|
||||||
const Icon(
|
const Icon(
|
||||||
Icons.play_arrow,
|
Icons.play_arrow,
|
||||||
color: Color(0xFF4FC3F7),
|
color: AppColors.primary,
|
||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -2021,7 +2022,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.replay_10,
|
Icons.replay_10,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 48,
|
size: 48,
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -2046,7 +2047,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
_isPlaying
|
_isPlaying
|
||||||
? Icons.pause_circle_filled
|
? Icons.pause_circle_filled
|
||||||
: Icons.play_circle_filled,
|
: Icons.play_circle_filled,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
),
|
),
|
||||||
onPressed: _togglePlayPause,
|
onPressed: _togglePlayPause,
|
||||||
),
|
),
|
||||||
@@ -2067,7 +2068,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.forward_10,
|
Icons.forward_10,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 48,
|
size: 48,
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -2103,7 +2104,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
_formatDuration(_position),
|
_formatDuration(_position),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -2157,14 +2158,14 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
_resetControlsTimer();
|
_resetControlsTimer();
|
||||||
},
|
},
|
||||||
activeColor: AppColors.primary,
|
activeColor: AppColors.primary,
|
||||||
inactiveColor: Colors.white24,
|
inactiveColor: AppColors.onSurface24,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
_formatDuration(_duration),
|
_formatDuration(_duration),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -2199,7 +2200,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
height: 72,
|
height: 72,
|
||||||
margin: const EdgeInsets.only(bottom: 16),
|
margin: const EdgeInsets.only(bottom: 16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white10,
|
color: AppColors.onSurface12,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
@@ -2208,7 +2209,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
imageUrl: ch.streamIcon,
|
imageUrl: ch.streamIcon,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
errorWidget: (_, __, ___) =>
|
errorWidget: (_, __, ___) =>
|
||||||
const Icon(Icons.tv, color: Colors.white38, size: 40),
|
const Icon(Icons.tv, color: AppColors.onSurface38, size: 40),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -2217,7 +2218,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
Text(
|
Text(
|
||||||
ch != null ? ch.name : 'Chargement...',
|
ch != null ? ch.name : 'Chargement...',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white70,
|
color: AppColors.onSurface70,
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
@@ -2232,18 +2233,18 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.error_outline, size: 64, color: Colors.red),
|
const Icon(Icons.error_outline, size: 64, color: AppColors.error),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const Text(
|
const Text(
|
||||||
'Erreur de lecture',
|
'Erreur de lecture',
|
||||||
style: TextStyle(color: Colors.white, fontSize: 18),
|
style: TextStyle(color: AppColors.onSurface, fontSize: 18),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||||
child: Text(
|
child: Text(
|
||||||
_errorMessage ?? 'Une erreur inconnue est survenue',
|
_errorMessage ?? 'Une erreur inconnue est survenue',
|
||||||
style: const TextStyle(color: Colors.white70),
|
style: const TextStyle(color: AppColors.onSurface70),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -2256,8 +2257,8 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
icon: const Icon(Icons.arrow_back),
|
icon: const Icon(Icons.arrow_back),
|
||||||
label: const Text('Retour'),
|
label: const Text('Retour'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: AppColors.onSurface,
|
||||||
foregroundColor: Colors.black,
|
foregroundColor: AppColors.onPrimaryFixed,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
@@ -2267,7 +2268,7 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
|||||||
label: const Text('Réessayer'),
|
label: const Text('Réessayer'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: AppColors.primary,
|
backgroundColor: AppColors.primary,
|
||||||
foregroundColor: Colors.black,
|
foregroundColor: AppColors.onPrimaryFixed,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -2328,7 +2329,7 @@ class _StatsOverlayWidgetState extends ConsumerState<StatsOverlayWidget> {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black.withOpacity(0.7),
|
color: Colors.black.withOpacity(0.7),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
border: Border.all(color: Colors.green.withOpacity(0.5)),
|
border: Border.all(color: AppColors.success.withOpacity(0.5)),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -2337,7 +2338,7 @@ class _StatsOverlayWidgetState extends ConsumerState<StatsOverlayWidget> {
|
|||||||
const Text(
|
const Text(
|
||||||
'STATS FOR NERDS 🤓',
|
'STATS FOR NERDS 🤓',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.green,
|
color: AppColors.success,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
),
|
),
|
||||||
@@ -2345,11 +2346,11 @@ class _StatsOverlayWidgetState extends ConsumerState<StatsOverlayWidget> {
|
|||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
'Buffer: ${_buffer.inSeconds}s',
|
'Buffer: ${_buffer.inSeconds}s',
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 12),
|
style: const TextStyle(color: AppColors.onSurface, fontSize: 12),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Decoder: $_decoder',
|
'Decoder: $_decoder',
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 12),
|
style: const TextStyle(color: AppColors.onSurface, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import 'package:xtremobile/features/iptv/screens/lite_player_screen.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:xtremobile/core/services/ip_service.dart';
|
import 'package:xtremobile/core/services/ip_service.dart';
|
||||||
import 'package:xtremobile/core/models/iptv_models.dart' as model;
|
import 'package:xtremobile/core/models/iptv_models.dart' as model;
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class MobileLiveTVTab extends ConsumerStatefulWidget {
|
class MobileLiveTVTab extends ConsumerStatefulWidget {
|
||||||
final PlaylistConfig playlist;
|
final PlaylistConfig playlist;
|
||||||
@@ -130,14 +131,14 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
|
|||||||
final shouldExit = await showDialog<bool>(
|
final shouldExit = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
backgroundColor: Colors.grey[900],
|
backgroundColor: AppColors.surfaceContainerLowest,
|
||||||
title: const Text(
|
title: const Text(
|
||||||
"Quitter l'application",
|
"Quitter l'application",
|
||||||
style: TextStyle(color: Colors.white),
|
style: TextStyle(color: AppColors.onSurface),
|
||||||
),
|
),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
"Voulez-vous vraiment quitter l'application ?",
|
"Voulez-vous vraiment quitter l'application ?",
|
||||||
style: TextStyle(color: Colors.white70),
|
style: TextStyle(color: AppColors.onSurface70),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -145,14 +146,14 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
|
|||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Annuler',
|
'Annuler',
|
||||||
style: TextStyle(color: Colors.blueAccent),
|
style: TextStyle(color: AppColors.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Quitter',
|
'Quitter',
|
||||||
style: TextStyle(color: Colors.redAccent),
|
style: TextStyle(color: AppColors.error),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -171,7 +172,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
|
|||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Erreur: $e',
|
'Erreur: $e',
|
||||||
style: const TextStyle(color: Colors.red),
|
style: const TextStyle(color: AppColors.error),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -235,7 +236,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
|
|||||||
// Search Bar
|
// Search Bar
|
||||||
TVFocusable(
|
TVFocusable(
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
focusColor: Colors.white,
|
focusColor: AppColors.onSurface,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() => _isSearchEditing = true);
|
setState(() => _isSearchEditing = true);
|
||||||
WidgetsBinding.instance
|
WidgetsBinding.instance
|
||||||
@@ -263,7 +264,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
|
|||||||
child: ExcludeFocus(
|
child: ExcludeFocus(
|
||||||
excluding: !_isSearchEditing,
|
excluding: !_isSearchEditing,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
cursorColor: Colors.white,
|
cursorColor: AppColors.onSurface,
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
focusNode: _searchFocusNode,
|
focusNode: _searchFocusNode,
|
||||||
readOnly: !_isSearchEditing,
|
readOnly: !_isSearchEditing,
|
||||||
@@ -357,7 +358,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab>
|
|||||||
? Icons.favorite
|
? Icons.favorite
|
||||||
: Icons.favorite_border,
|
: Icons.favorite_border,
|
||||||
color: _showFavoritesOnly
|
color: _showFavoritesOnly
|
||||||
? const Color(0xFFFF453A)
|
? AppColors.live
|
||||||
: AppDecorations.textSecondary(
|
: AppDecorations.textSecondary(
|
||||||
context),
|
context),
|
||||||
),
|
),
|
||||||
@@ -535,7 +536,7 @@ class _ChannelListView extends ConsumerWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Aucune catégorie sélectionnée',
|
'Aucune catégorie sélectionnée',
|
||||||
style: TextStyle(color: Colors.white70),
|
style: TextStyle(color: AppColors.onSurface70),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -557,7 +558,7 @@ class _ChannelListView extends ConsumerWidget {
|
|||||||
showFavoritesOnly
|
showFavoritesOnly
|
||||||
? 'Sélectionnez une catégorie pour voir vos favoris'
|
? 'Sélectionnez une catégorie pour voir vos favoris'
|
||||||
: 'Sélectionnez une catégorie pour rechercher',
|
: 'Sélectionnez une catégorie pour rechercher',
|
||||||
style: const TextStyle(color: Colors.white70),
|
style: const TextStyle(color: AppColors.onSurface70),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -575,7 +576,7 @@ class _ChannelListView extends ConsumerWidget {
|
|||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Erreur: $e',
|
'Erreur: $e',
|
||||||
style: const TextStyle(color: Colors.red),
|
style: const TextStyle(color: AppColors.error),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -600,7 +601,7 @@ class _ChannelListView extends ConsumerWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Aucune chaîne trouvée',
|
'Aucune chaîne trouvée',
|
||||||
style: TextStyle(color: Colors.white70),
|
style: TextStyle(color: AppColors.onSurface70),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -754,12 +755,12 @@ class _MobileChannelCardState extends ConsumerState<_MobileChannelCard> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.red,
|
color: AppColors.error,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.favorite,
|
Icons.favorite,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 10,
|
size: 10,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -779,7 +780,7 @@ class _MobileChannelCardState extends ConsumerState<_MobileChannelCard> {
|
|||||||
Text(
|
Text(
|
||||||
widget.channel.name,
|
widget.channel.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
),
|
),
|
||||||
@@ -792,7 +793,7 @@ class _MobileChannelCardState extends ConsumerState<_MobileChannelCard> {
|
|||||||
Text(
|
Text(
|
||||||
_epgTitle!,
|
_epgTitle!,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.yellow,
|
color: AppColors.ratingGold,
|
||||||
fontSize: 8,
|
fontSize: 8,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:xtremobile/mobile/providers/mobile_settings_providers.dart';
|
|||||||
import 'package:xtremobile/mobile/providers/mobile_xtream_providers.dart';
|
import 'package:xtremobile/mobile/providers/mobile_xtream_providers.dart';
|
||||||
import 'package:xtremobile/core/models/iptv_models.dart' as model;
|
import 'package:xtremobile/core/models/iptv_models.dart' as model;
|
||||||
import 'package:xtremobile/features/iptv/screens/native_player_screen.dart';
|
import 'package:xtremobile/features/iptv/screens/native_player_screen.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class MobileMoviesTab extends ConsumerStatefulWidget {
|
class MobileMoviesTab extends ConsumerStatefulWidget {
|
||||||
final PlaylistConfig playlist;
|
final PlaylistConfig playlist;
|
||||||
@@ -285,14 +286,14 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab>
|
|||||||
final shouldExit = await showDialog<bool>(
|
final shouldExit = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
backgroundColor: Colors.grey[900],
|
backgroundColor: AppColors.surfaceContainerLowest,
|
||||||
title: const Text(
|
title: const Text(
|
||||||
"Quitter l'application",
|
"Quitter l'application",
|
||||||
style: TextStyle(color: Colors.white),
|
style: TextStyle(color: AppColors.onSurface),
|
||||||
),
|
),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
"Voulez-vous vraiment quitter l'application ?",
|
"Voulez-vous vraiment quitter l'application ?",
|
||||||
style: TextStyle(color: Colors.white70),
|
style: TextStyle(color: AppColors.onSurface70),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -300,14 +301,14 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab>
|
|||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Annuler',
|
'Annuler',
|
||||||
style: TextStyle(color: Colors.blueAccent),
|
style: TextStyle(color: AppColors.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Quitter',
|
'Quitter',
|
||||||
style: TextStyle(color: Colors.redAccent),
|
style: TextStyle(color: AppColors.error),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -346,7 +347,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab>
|
|||||||
// Search Bar
|
// Search Bar
|
||||||
TVFocusable(
|
TVFocusable(
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
focusColor: Colors.white,
|
focusColor: AppColors.onSurface,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() => _isSearchEditing = true);
|
setState(() => _isSearchEditing = true);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
@@ -367,7 +368,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab>
|
|||||||
child: ExcludeFocus(
|
child: ExcludeFocus(
|
||||||
excluding: !_isSearchEditing,
|
excluding: !_isSearchEditing,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
cursorColor: Colors.white,
|
cursorColor: AppColors.onSurface,
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
focusNode: _searchFocusNode,
|
focusNode: _searchFocusNode,
|
||||||
readOnly: !_isSearchEditing,
|
readOnly: !_isSearchEditing,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:xtremobile/mobile/providers/mobile_settings_providers.dart';
|
|||||||
import 'package:xtremobile/mobile/providers/mobile_xtream_providers.dart';
|
import 'package:xtremobile/mobile/providers/mobile_xtream_providers.dart';
|
||||||
import 'package:xtremobile/core/models/iptv_models.dart' as model;
|
import 'package:xtremobile/core/models/iptv_models.dart' as model;
|
||||||
import 'package:xtremobile/features/iptv/screens/mobile_series_detail_screen.dart';
|
import 'package:xtremobile/features/iptv/screens/mobile_series_detail_screen.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class MobileSeriesTab extends ConsumerStatefulWidget {
|
class MobileSeriesTab extends ConsumerStatefulWidget {
|
||||||
final PlaylistConfig playlist;
|
final PlaylistConfig playlist;
|
||||||
@@ -269,18 +270,18 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab>
|
|||||||
final shouldExit = await showDialog<bool>(
|
final shouldExit = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
backgroundColor: Colors.grey[900],
|
backgroundColor: AppColors.surfaceContainerLowest,
|
||||||
title: const Text("Quitter l'application", style: TextStyle(color: Colors.white)),
|
title: const Text("Quitter l'application", style: TextStyle(color: AppColors.onSurface)),
|
||||||
content: const Text("Voulez-vous vraiment quitter l'application ?", style: TextStyle(color: Colors.white70)),
|
content: const Text("Voulez-vous vraiment quitter l'application ?", style: TextStyle(color: AppColors.onSurface70)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: const Text('Annuler', style: TextStyle(color: Colors.blueAccent)),
|
child: const Text('Annuler', style: TextStyle(color: AppColors.primary)),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
child: const Text('Quitter', style: TextStyle(color: Colors.redAccent)),
|
child: const Text('Quitter', style: TextStyle(color: AppColors.error)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -316,7 +317,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab>
|
|||||||
// Search Bar
|
// Search Bar
|
||||||
TVFocusable(
|
TVFocusable(
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
focusColor: Colors.white,
|
focusColor: AppColors.onSurface,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() => _isSearchEditing = true);
|
setState(() => _isSearchEditing = true);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
@@ -337,7 +338,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab>
|
|||||||
child: ExcludeFocus(
|
child: ExcludeFocus(
|
||||||
excluding: !_isSearchEditing,
|
excluding: !_isSearchEditing,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
cursorColor: Colors.white,
|
cursorColor: AppColors.onSurface,
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
focusNode: _searchFocusNode,
|
focusNode: _searchFocusNode,
|
||||||
readOnly: !_isSearchEditing,
|
readOnly: !_isSearchEditing,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:xtremobile/core/theme/app_decorations.dart';
|
|||||||
import 'package:xtremobile/core/theme/app_theme.dart';
|
import 'package:xtremobile/core/theme/app_theme.dart';
|
||||||
import 'package:xtremobile/core/providers/theme_provider.dart';
|
import 'package:xtremobile/core/providers/theme_provider.dart';
|
||||||
import 'package:xtremobile/features/iptv/screens/mobile_playlist_selection_screen.dart';
|
import 'package:xtremobile/features/iptv/screens/mobile_playlist_selection_screen.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
/// Simplified mobile settings tab - optimized for TV remote control
|
/// Simplified mobile settings tab - optimized for TV remote control
|
||||||
class MobileSettingsTab extends ConsumerStatefulWidget {
|
class MobileSettingsTab extends ConsumerStatefulWidget {
|
||||||
@@ -105,7 +106,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Version 1.5.1',
|
'Version 1.6.1',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
color: AppDecorations.textSecondary(context),
|
color: AppDecorations.textSecondary(context),
|
||||||
@@ -327,7 +328,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text('Cache actualisé ! Relancez l\'app pour recharger.'),
|
content: Text('Cache actualisé ! Relancez l\'app pour recharger.'),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: AppColors.success,
|
||||||
duration: Duration(seconds: 3),
|
duration: Duration(seconds: 3),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -335,7 +336,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Erreur: $e'), backgroundColor: Colors.red),
|
SnackBar(content: Text('Erreur: $e'), backgroundColor: AppColors.error),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -415,7 +416,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
|||||||
icon,
|
icon,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: selected
|
color: selected
|
||||||
? Colors.white
|
? AppColors.onSurface
|
||||||
: AppDecorations.textSecondary(context),
|
: AppDecorations.textSecondary(context),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 3),
|
const SizedBox(height: 3),
|
||||||
@@ -427,7 +428,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
|||||||
? FontWeight.w700
|
? FontWeight.w700
|
||||||
: FontWeight.w500,
|
: FontWeight.w500,
|
||||||
color: selected
|
color: selected
|
||||||
? Colors.white
|
? AppColors.onSurface
|
||||||
: AppDecorations.textSecondary(context),
|
: AppDecorations.textSecondary(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:xtremobile/core/theme/app_decorations.dart';
|
import 'package:xtremobile/core/theme/app_decorations.dart';
|
||||||
import 'package:xtremobile/mobile/widgets/tv_focusable.dart';
|
import 'package:xtremobile/mobile/widgets/tv_focusable.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class MobileCategoryCard extends StatelessWidget {
|
class MobileCategoryCard extends StatelessWidget {
|
||||||
final String title;
|
final String title;
|
||||||
@@ -13,7 +14,7 @@ class MobileCategoryCard extends StatelessWidget {
|
|||||||
required this.title,
|
required this.title,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
this.icon = Icons.folder_rounded,
|
this.icon = Icons.folder_rounded,
|
||||||
this.iconColor = const Color(0xFF0A84FF),
|
this.iconColor = AppColors.primary,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||||||
import 'package:xtremobile/core/theme/app_decorations.dart';
|
import 'package:xtremobile/core/theme/app_decorations.dart';
|
||||||
import 'package:xtremobile/mobile/widgets/tv_focusable.dart';
|
import 'package:xtremobile/mobile/widgets/tv_focusable.dart';
|
||||||
import 'package:xtremobile/core/utils/image_cache_config.dart';
|
import 'package:xtremobile/core/utils/image_cache_config.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class MobilePosterCard extends StatelessWidget {
|
class MobilePosterCard extends StatelessWidget {
|
||||||
final String title;
|
final String title;
|
||||||
@@ -134,12 +135,12 @@ class MobilePosterCard extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.star, color: Colors.amber, size: 10),
|
const Icon(Icons.star, color: AppColors.ratingGold, size: 10),
|
||||||
const SizedBox(width: 2),
|
const SizedBox(width: 2),
|
||||||
Text(
|
Text(
|
||||||
rating!,
|
rating!,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -157,13 +158,13 @@ class MobilePosterCard extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Color(0xFF30D158),
|
color: AppColors.success,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.check,
|
Icons.check,
|
||||||
size: 10,
|
size: 10,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import '../../core/theme/app_decorations.dart';
|
import '../../core/theme/app_decorations.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class MobileScaffold extends ConsumerStatefulWidget {
|
class MobileScaffold extends ConsumerStatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@@ -71,7 +72,7 @@ class _MobileScaffoldState extends ConsumerState<MobileScaffold> {
|
|||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
errorBuilder: (_, __, ___) => const Icon(
|
errorBuilder: (_, __, ___) => const Icon(
|
||||||
Icons.play_circle_filled,
|
Icons.play_circle_filled,
|
||||||
color: Colors.white,
|
color: AppColors.onSurface,
|
||||||
size: 40,
|
size: 40,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -201,12 +202,12 @@ class _AppleTVNavItemState extends State<_AppleTVNavItem> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const Color selectedColor = Color(0xFF0A84FF);
|
const Color selectedColor = AppColors.primaryFill;
|
||||||
final Color unselectedColor = AppDecorations.textSecondary(context);
|
final Color unselectedColor = AppDecorations.textSecondary(context);
|
||||||
final Color textColor =
|
final Color textColor =
|
||||||
widget.isSelected ? Colors.white : unselectedColor;
|
widget.isSelected ? AppColors.onSurface : unselectedColor;
|
||||||
final Color iconColor =
|
final Color iconColor =
|
||||||
widget.isSelected ? Colors.white : unselectedColor;
|
widget.isSelected ? AppColors.onSurface : unselectedColor;
|
||||||
final FontWeight fontWeight =
|
final FontWeight fontWeight =
|
||||||
widget.isSelected ? FontWeight.w700 : FontWeight.w500;
|
widget.isSelected ? FontWeight.w700 : FontWeight.w500;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||||
|
|
||||||
class TVFocusable extends StatefulWidget {
|
class TVFocusable extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@@ -25,7 +26,7 @@ class TVFocusable extends StatefulWidget {
|
|||||||
this.autofocus = false,
|
this.autofocus = false,
|
||||||
this.scale = 1.05, // Apple TV subtle lift
|
this.scale = 1.05, // Apple TV subtle lift
|
||||||
this.borderWidth = 2.0,
|
this.borderWidth = 2.0,
|
||||||
this.focusColor = Colors.white,
|
this.focusColor = AppColors.onSurface,
|
||||||
this.borderRadius,
|
this.borderRadius,
|
||||||
this.longPressDuration = const Duration(seconds: 3),
|
this.longPressDuration = const Duration(seconds: 3),
|
||||||
});
|
});
|
||||||
@@ -162,7 +163,7 @@ class _TVFocusableState extends State<TVFocusable> {
|
|||||||
offset: const Offset(0, 6),
|
offset: const Offset(0, 6),
|
||||||
),
|
),
|
||||||
const BoxShadow(
|
const BoxShadow(
|
||||||
color: Color(0x40FFFFFF), // White glow
|
color: Color(0x59D9541F), // Ember glow
|
||||||
blurRadius: 12,
|
blurRadius: 12,
|
||||||
spreadRadius: 0,
|
spreadRadius: 0,
|
||||||
),
|
),
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
name: xtremobile
|
name: xtremobile
|
||||||
description: High-performance IPTV Android Application with Xtream Codes API
|
description: High-performance IPTV Android Application with Xtream Codes API
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 1.6.0+12
|
version: 1.6.1+13
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
|
|||||||
@@ -25,6 +25,21 @@
|
|||||||
- [x] `mobile_theme.dart` : dérive désormais de `AppTheme` (échelle typo mobile)
|
- [x] `mobile_theme.dart` : dérive désormais de `AppTheme` (échelle typo mobile)
|
||||||
au lieu de dupliquer 390 lignes
|
au lieu de dupliquer 390 lignes
|
||||||
- [x] `app_decorations.dart` : hexs Apple codés en dur remplacés par la palette
|
- [x] `app_decorations.dart` : hexs Apple codés en dur remplacés par la palette
|
||||||
|
- [x] **Passe 2 (v1.6.1)** — le thème ne suffisait pas : du bleu restait codé en
|
||||||
|
dur dans 19 fichiers d'écran/widget, hors palette. Balayage complet :
|
||||||
|
- `0xFF0A84FF` (bleu Apple) dans la **pilule de navigation sélectionnée**
|
||||||
|
(`mobile_scaffold`), les icônes de catégorie et le bouton « ajouter »
|
||||||
|
- `0xFF4FC3F7` / `0xFF1565C0` (bleus) dans les overlays du lecteur
|
||||||
|
- `Colors.blueAccent` / `Colors.blue` dans les boîtes de dialogue
|
||||||
|
- gris Apple `1C1C1E` / `2C2C2E` / `3A3A3C` / `8E8E93` → charbons chauds
|
||||||
|
- `Colors.white*` (128 occurrences) → paliers crème `onSurfaceNN`
|
||||||
|
- `Colors.red/green/amber/yellow/grey*` → `error` / `success` /
|
||||||
|
`ratingGold` / `outlineVariant`
|
||||||
|
- noir pur sur remplissage clair → encre chaude `onPrimaryFixed`
|
||||||
|
- halo de focus blanc → halo ember
|
||||||
|
- Conservés en noir vrai : fonds de surface vidéo et voiles (`scrims`)
|
||||||
|
- Vérification : plus **aucune** couleur Material/Apple codée en dur hors
|
||||||
|
de `lib/core/theme/`
|
||||||
|
|
||||||
## 3. Lecture — arrêt en arrière-plan et tenue dans la durée
|
## 3. Lecture — arrêt en arrière-plan et tenue dans la durée
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user