mirror of
https://github.com/R0m1k3/xtremobile.git
synced 2026-10-24 07:38:16 +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.
|
||||
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) ============
|
||||
static const Color secondary = Color(0xFFE7C3AC);
|
||||
static const Color onSecondary = Color(0xFF442A1B);
|
||||
@@ -92,6 +100,7 @@ class AppColors {
|
||||
static const Color onSurface24 = Color(0x3DF3E9DF);
|
||||
static const Color onSurface38 = Color(0x61F3E9DF);
|
||||
static const Color onSurface54 = Color(0x8AF3E9DF);
|
||||
static const Color onSurface70 = Color(0xB3F3E9DF);
|
||||
|
||||
// ============ STATUS ============
|
||||
static const Color success = Color(0xFF9BC46A); // olive lumineux
|
||||
|
||||
@@ -10,6 +10,7 @@ library;
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.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
|
||||
class AppCacheManager {
|
||||
@@ -103,7 +104,7 @@ class ImageCacheConfig {
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF2C2C2E),
|
||||
color: AppColors.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
@@ -111,10 +112,10 @@ class ImageCacheConfig {
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF3A3A3C),
|
||||
color: AppColors.surfaceContainerHigh,
|
||||
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(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -161,7 +161,7 @@ class _HeroCarouselState extends State<HeroCarousel> {
|
||||
item.subtitle!,
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 16,
|
||||
color: Colors.white.withOpacity(0.8),
|
||||
color: AppColors.onSurface.withOpacity(0.8),
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -227,8 +227,8 @@ class _HeroButtonState extends State<_HeroButton> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.isPrimary
|
||||
? (_isHovered ? Colors.white : Colors.white.withOpacity(0.9))
|
||||
: (_isHovered ? Colors.white.withOpacity(0.2) : Colors.white.withOpacity(0.1)),
|
||||
? (_isHovered ? AppColors.onSurface : AppColors.onSurface.withOpacity(0.9))
|
||||
: (_isHovered ? AppColors.onSurface.withOpacity(0.2) : AppColors.onSurface.withOpacity(0.1)),
|
||||
borderRadius: BorderRadius.circular(AppTheme.radiusFull),
|
||||
),
|
||||
child: Row(
|
||||
@@ -236,14 +236,14 @@ class _HeroButtonState extends State<_HeroButton> {
|
||||
children: [
|
||||
Icon(
|
||||
widget.icon,
|
||||
color: widget.isPrimary ? Colors.black : Colors.white,
|
||||
color: widget.isPrimary ? AppColors.onPrimaryFixed : AppColors.onSurface,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
widget.label,
|
||||
style: GoogleFonts.inter(
|
||||
color: widget.isPrimary ? Colors.black : Colors.white,
|
||||
color: widget.isPrimary ? AppColors.onPrimaryFixed : AppColors.onSurface,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -134,7 +134,7 @@ class _GradientButtonState extends State<GradientButton>
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Colors.black,
|
||||
color: AppColors.onPrimaryFixed,
|
||||
),
|
||||
)
|
||||
: Row(
|
||||
@@ -143,13 +143,13 @@ class _GradientButtonState extends State<GradientButton>
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (widget.icon != null) ...[
|
||||
Icon(widget.icon, color: Colors.black, size: 20),
|
||||
Icon(widget.icon, color: AppColors.onPrimaryFixed, size: 20),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
Text(
|
||||
widget.label,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
color: AppColors.onPrimaryFixed,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 14,
|
||||
),
|
||||
@@ -247,12 +247,12 @@ class LiveBadge extends StatelessWidget {
|
||||
child: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.circle, size: 6, color: Colors.white),
|
||||
Icon(Icons.circle, size: 6, color: AppColors.onSurface),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'LIVE',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -427,11 +427,11 @@ class _MediaCardState extends State<MediaCard>
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.star, size: 10, color: Color(0xFFFFD700)),
|
||||
const Icon(Icons.star, size: 10, color: AppColors.ratingGold),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
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,
|
||||
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:google_fonts/google_fonts.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||
|
||||
class DigitalClock extends StatefulWidget {
|
||||
const DigitalClock({super.key});
|
||||
@@ -31,16 +32,16 @@ class _DigitalClockState extends State<DigitalClock> {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.1),
|
||||
color: AppColors.onSurface.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(color: Colors.white.withOpacity(0.05)),
|
||||
border: Border.all(color: AppColors.onSurface.withOpacity(0.05)),
|
||||
),
|
||||
child: Text(
|
||||
timeString,
|
||||
style: GoogleFonts.inter(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:xtremobile/core/theme/app_colors.dart';
|
||||
|
||||
class ThemedLoading extends StatelessWidget {
|
||||
const ThemedLoading({super.key});
|
||||
@@ -11,7 +12,7 @@ class ThemedLoading extends StatelessWidget {
|
||||
center: Alignment(0, -0.2),
|
||||
radius: 1.5,
|
||||
colors: [
|
||||
Color(0xFF2C2C2E),
|
||||
AppColors.surfaceContainerHigh,
|
||||
Color(0xFF000000),
|
||||
],
|
||||
stops: [0.0, 1.0],
|
||||
@@ -19,7 +20,7 @@ class ThemedLoading extends StatelessWidget {
|
||||
),
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
strokeWidth: 3,
|
||||
),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user