feat(design): Projector Noir theme - tungsten amber on film-black

Full visual refonte replacing the generic neon-blue glass look:

- palette: warm film-black surface ladder, tungsten amber primary,
  warm taupe secondary, verdigris teal tertiary; semantic and
  category colors retuned to match (coral live, gold movies)
- typography: Syne (display/headlines) + Instrument Sans (body/UI)
  replace Space Grotesk/Inter/Outfit across all screens
- glassmorphism tokens warmed (amber inner glow, warm-white borders)
- web player theme.css + index.html loader mirror the new tokens
- hardcoded Colors.blue* in streaming settings and recordings tabs
  now use AppColors tokens
- DESIGN_SYSTEM.md updated to v3.0 Projector Noir

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Fable 5 committed 2026-06-10 14:52:45 +02:00
1 parent 9595afcc99
commit e332895d7d
33 files changed
+392 -397

No files matched your search

+38 -44
View File
@@ -1,12 +1,12 @@
# XtremFlow Apple TV Modern Design System # XtremFlow Projector Noir Design System
## Overview ## Overview
XtremFlow has been completely redesigned with a **premium Apple TV modern aesthetic** inspired by tvOS 18+. The new design system prioritizes: XtremFlow uses a **Projector Noir aesthetic**: warm tungsten light cutting through a dark screening room. The design system prioritizes:
- **Sophisticated Glassmorphism** - Elegant blur effects with subtle gradients - **Sophisticated Glassmorphism** - Elegant blur effects with warm-tinted borders
- **Premium Color Palette** - Vibrant accents (Cyan, Mint, Red) on pure black - **Tungsten Palette** - Amber projector-beam accents on deep film-black
- **Cinematic Typography** - Bold headlines (Outfit) + refined UI text (Inter) - **Art-House Typography** - Geometric headlines (Syne) + refined UI text (Instrument Sans)
- **Focus-Driven Interactions** - TV-friendly hover states and animations - **Focus-Driven Interactions** - TV-friendly hover states and animations
- **Responsive Layouts** - Seamless adaptation from web to mobile - **Responsive Layouts** - Seamless adaptation from web to mobile
@@ -14,46 +14,40 @@ XtremFlow has been completely redesigned with a **premium Apple TV modern aesthe
## Color Palette ## Color Palette
### Backgrounds ### Backgrounds (warm film-black ladder)
- **`background`** (#000000) - Pure black, OLED optimized - **`baseLevel0`** (#0B0A08) - Deepest black, OLED optimized
- **`surface`** (#1C1C1E) - Primary dark surface - **`background` / `surface`** (#14110C) - Primary dark surface
- **`surfaceVariant`** (#2A2A2E) - Secondary surface for hierarchy - **`surfaceContainerLow`** (#1B1812) to **`surfaceContainerHighest`** (#363027) - Warm charcoal hierarchy
- **`surfaceTertiary`** (#383838) - Tertiary depth layer
### Primary Accents ### Primary Accents
- **`primary`** (#00D4FF) - Main brand color (Cyan/Sky Blue) - **`primary`** (#FFB35C) - Tungsten amber (main brand color)
- **`secondary`** (#FF6B6B) - Secondary accent (Soft Red) - **`primaryContainer`** (#F39A1F) - Vivid amber (buttons, focus rings)
- **`tertiary`** (#00E5BB) - Highlight accent (Mint) - **`secondary`** (#D3C6B2) - Warm taupe
- **`accent`** - Alias for primary (for consistency) - **`tertiary`** (#A4CCBE) - Verdigris teal (counterpoint accent)
### Semantic Colors ### Semantic Colors
- **`success`** (#34C759) - Success/completed state - **`success`** (#6BD89B) - Success/completed state
- **`warning`** (#FF9500) - Warning/caution state - **`warning`** (#FFAB00) - Warning/caution state
- **`error`** (#FF3B30) - Error/danger state - **`error`** (#FFB4AB) - Error/danger state (Material 3 dark)
- **`info`** (#30B0C0) - Information state - **`info`** (#64B6AC) - Information state (soft teal)
- **`disabled`** (#8E8E93) - Disabled/inactive state
### Text Hierarchy ### Text Hierarchy (warm ivory)
- **`textPrimary`** (#FFFFFF) - Main text (white) - **`textPrimary`** (#ECE6DA) - Main text
- **`textSecondary`** (#999999) - Secondary text (60% grey) - **`textSecondary`** (#CDC4B4) - Secondary text
- **`textTertiary`** (#666666) - Tertiary text (40% grey) - **`textTertiary`** (#998F7C) - Tertiary text
- **`textQuaternary`** (#404040) - Subtle text (25% grey)
### Category Colors ### Category Colors
- **`live`** (#FF3B30) - Live streams (red) - **`live`** (#FF6E5E) - Live streams (signal coral)
- **`movies`** (#00B4E8) - Movie content (blue) - **`movies`** (#E8B64C) - Movie content (warm gold)
- **`series`** (#00E5BB) - Series content (mint) - **`series`** (#5FC9AE) - Series content (teal)
- **`sports`** (#BF5AF0) - Sports content (purple)
- **`news`** (#FFC300) - News content (yellow)
- **`music`** (#FF2D55) - Music content (pink)
--- ---
## Typography ## Typography
### Font Stack ### Font Stack
1. **Outfit** (headings/display) - Bold, geometric, premium feel 1. **Syne** (headings/display) - Geometric, art-house, distinctive
2. **Inter** (UI/body) - Clean, readable, high contrast 2. **Instrument Sans** (UI/body) - Clean, readable, characterful
3. Fallback to system fonts 3. Fallback to system fonts
### Sizes & Weights ### Sizes & Weights
@@ -287,14 +281,14 @@ TvSideNav(
## Usage Guidelines ## Usage Guidelines
### Color Usage ### Color Usage
- **Primary (Cyan):** Call-to-action buttons, focus states, active indicators - **Primary (Tungsten Amber):** Call-to-action buttons, focus states, active indicators
- **Secondary (Red):** Alerts, favorite toggles, urgent actions - **Secondary (Warm Taupe):** Alerts, favorite toggles, urgent actions
- **Tertiary (Mint):** Accent highlights, success states, featured badges - **Tertiary (Verdigris Teal):** Accent highlights, success states, featured badges
- **White/Grey text:** Maintain WCAG AA contrast ratio (4.5:1 minimum) - **White/Grey text:** Maintain WCAG AA contrast ratio (4.5:1 minimum)
### Typography ### Typography
- **Outfit:** Only for headings/hero text (sizes 20px and above) - **Syne:** Only for headings/hero text (sizes 20px and above)
- **Inter:** All UI, buttons, body text - **Instrument Sans:** All UI, buttons, body text
- **Letter spacing:** Increase for larger sizes (hero titles: -1.0 to -1.5), decrease for body text - **Letter spacing:** Increase for larger sizes (hero titles: -1.0 to -1.5), decrease for body text
### Spacing ### Spacing
@@ -319,8 +313,8 @@ TvSideNav(
## Mobile Adaptations ## Mobile Adaptations
### Touch Targets ### Touch Targets
- **Minimum button size:** 48×48px - **Minimum button size:** 48x48px
- **Minimum tap area:** 44×44px - **Minimum tap area:** 44x44px
- **Between buttons:** 16px spacing minimum - **Between buttons:** 16px spacing minimum
### Typography Scaling ### Typography Scaling
@@ -349,7 +343,7 @@ TvSideNav(
2. Extend with custom styling if needed 2. Extend with custom styling if needed
3. Follow spacing/animation guidelines 3. Follow spacing/animation guidelines
4. Test hover states on desktop, tap on mobile 4. Test hover states on desktop, tap on mobile
5. Ensure text contrast ≥ 4.5:1 5. Ensure text contrast >= 4.5:1
### Color Customization ### Color Customization
- Never override `AppColors` constants directly - Never override `AppColors` constants directly
@@ -378,7 +372,7 @@ TvSideNav(
## Accessibility ## Accessibility
- **Text Contrast:** All text must meet WCAG AA (4.5:1) - **Text Contrast:** All text must meet WCAG AA (4.5:1)
- **Touch Targets:** 48×48px minimum on mobile - **Touch Targets:** 48x48px minimum on mobile
- **Focus States:** Always visible with 2px border or scale change - **Focus States:** Always visible with 2px border or scale change
- **Semantic HTML:** Use proper widget hierarchy - **Semantic HTML:** Use proper widget hierarchy
- **Tooltips:** Always add for icon-only buttons - **Tooltips:** Always add for icon-only buttons
@@ -435,6 +429,6 @@ Curve animCurve = AppTheme.curveDefault;
--- ---
**Design System Version:** 2.0 Apple TV Modern **Design System Version:** 3.0 Projector Noir
**Last Updated:** 2026-03-26 **Last Updated:** 2026-06-10
**Status:** Production Ready ✅ **Status:** Production Ready OK
+80 -79
View File
@@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// Cyber-Cinematic Glass Design System — Material 3 Token Palette /// Projector Noir Design System — Material 3 Token Palette
/// ///
/// Extracted from the Stitch design system for XtremFlow. /// Warm tungsten light on deep film-black, like a projector beam cutting
/// through a dark screening room. Verdigris teal as the counterpoint accent.
/// Optimized for OLED displays and low-light environments. /// Optimized for OLED displays and low-light environments.
/// Primary accent: Neon blue (#4b8eff / #adc6ff) /// Primary accent: Tungsten amber (#F39A1F / #FFB35C)
class AppColors { class AppColors {
AppColors._(); AppColors._();
@@ -13,58 +14,58 @@ class AppColors {
static Color get border => outlineVariant; static Color get border => outlineVariant;
// ============ SURFACE / ON SURFACE ============ // ============ SURFACE / ON SURFACE ============
static const Color onSurface = Color(0xFFe3e2e7); static const Color onSurface = Color(0xFFECE6DA);
static const Color onSurfaceVariant = Color(0xFFc1c6d7); static const Color onSurfaceVariant = Color(0xFFCDC4B4);
// ============ BASE LEVEL 0 ============ // ============ BASE LEVEL 0 ============
static const Color baseLevel0 = Color(0xFF0F1014); static const Color baseLevel0 = Color(0xFF0B0A08);
// ============ BACKGROUNDS ============ // ============ BACKGROUNDS ============
static const Color background = Color(0xFF121317); static const Color background = Color(0xFF14110C);
static const Color onBackground = Color(0xFFe3e2e7); static const Color onBackground = Color(0xFFECE6DA);
static const Color surface = Color(0xFF121317); static const Color surface = Color(0xFF14110C);
static const Color surfaceDim = Color(0xFF121317); static const Color surfaceDim = Color(0xFF14110C);
static const Color surfaceBright = Color(0xFF38393d); static const Color surfaceBright = Color(0xFF3E382C);
// Surface Containers (Material 3 hierarchy) // Surface Containers (Material 3 hierarchy)
static const Color surfaceContainerLowest = Color(0xFF0d0e12); static const Color surfaceContainerLowest = Color(0xFF0E0C09);
static const Color surfaceContainerLow = Color(0xFF1a1b20); static const Color surfaceContainerLow = Color(0xFF1B1812);
static const Color surfaceContainer = Color(0xFF1f1f24); static const Color surfaceContainer = Color(0xFF211D16);
static const Color surfaceContainerHigh = Color(0xFF292a2e); static const Color surfaceContainerHigh = Color(0xFF2B261E);
static const Color surfaceContainerHighest = Color(0xFF343439); static const Color surfaceContainerHighest = Color(0xFF363027);
static const Color surfaceVariant = Color(0xFF343439); static const Color surfaceVariant = Color(0xFF363027);
// ============ PRIMARY (Neon Blue) ============ // ============ PRIMARY (Tungsten Amber) ============
static const Color primary = Color(0xFFadc6ff); static const Color primary = Color(0xFFFFB35C);
static const Color onPrimary = Color(0xFF002e69); static const Color onPrimary = Color(0xFF452800);
static const Color primaryContainer = Color(0xFF4b8eff); static const Color primaryContainer = Color(0xFFF39A1F);
static const Color onPrimaryContainer = Color(0xFF00285c); static const Color onPrimaryContainer = Color(0xFF2E1B00);
static const Color inversePrimary = Color(0xFF005bc1); static const Color inversePrimary = Color(0xFF8F5B00);
static const Color primaryFixed = Color(0xFFd8e2ff); static const Color primaryFixed = Color(0xFFFFDDB3);
static const Color primaryFixedDim = Color(0xFFadc6ff); static const Color primaryFixedDim = Color(0xFFFFB35C);
static const Color onPrimaryFixed = Color(0xFF001a41); static const Color onPrimaryFixed = Color(0xFF2A1700);
static const Color onPrimaryFixedVariant = Color(0xFF004493); static const Color onPrimaryFixedVariant = Color(0xFF6B4300);
// ============ SECONDARY ============ // ============ SECONDARY (Warm Taupe) ============
static const Color secondary = Color(0xFFc6c5cf); static const Color secondary = Color(0xFFD3C6B2);
static const Color onSecondary = Color(0xFF2f3037); static const Color onSecondary = Color(0xFF382F21);
static const Color secondaryContainer = Color(0xFF4a4b53); static const Color secondaryContainer = Color(0xFF504535);
static const Color onSecondaryContainer = Color(0xFFbcbbc4); static const Color onSecondaryContainer = Color(0xFFD8CCB9);
static const Color secondaryFixed = Color(0xFFe3e1eb); static const Color secondaryFixed = Color(0xFFF0E4D0);
static const Color secondaryFixedDim = Color(0xFFc6c5cf); static const Color secondaryFixedDim = Color(0xFFD3C6B2);
static const Color onSecondaryFixed = Color(0xFF1a1b22); static const Color onSecondaryFixed = Color(0xFF231B0E);
static const Color onSecondaryFixedVariant = Color(0xFF46464e); static const Color onSecondaryFixedVariant = Color(0xFF4D4232);
// ============ TERTIARY ============ // ============ TERTIARY (Verdigris Teal) ============
static const Color tertiary = Color(0xFFc6c6c7); static const Color tertiary = Color(0xFFA4CCBE);
static const Color onTertiary = Color(0xFF2f3131); static const Color onTertiary = Color(0xFF0F352B);
static const Color tertiaryContainer = Color(0xFF909191); static const Color tertiaryContainer = Color(0xFF2F5A4C);
static const Color onTertiaryContainer = Color(0xFF282a2a); static const Color onTertiaryContainer = Color(0xFFC0E8D9);
static const Color tertiaryFixed = Color(0xFFe2e2e2); static const Color tertiaryFixed = Color(0xFFC0E8D9);
static const Color tertiaryFixedDim = Color(0xFFc6c6c7); static const Color tertiaryFixedDim = Color(0xFFA4CCBE);
static const Color onTertiaryFixed = Color(0xFF1a1c1c); static const Color onTertiaryFixed = Color(0xFF04201A);
static const Color onTertiaryFixedVariant = Color(0xFF454747); static const Color onTertiaryFixedVariant = Color(0xFF274B40);
// ============ ERROR ============ // ============ ERROR ============
static const Color error = Color(0xFFffb4ab); static const Color error = Color(0xFFffb4ab);
@@ -73,61 +74,61 @@ class AppColors {
static const Color onErrorContainer = Color(0xFFffdad6); static const Color onErrorContainer = Color(0xFFffdad6);
// ============ OUTLINE ============ // ============ OUTLINE ============
static const Color outline = Color(0xFF8b90a0); static const Color outline = Color(0xFF998F7C);
static const Color outlineVariant = Color(0xFF414755); static const Color outlineVariant = Color(0xFF4A4334);
// ============ INVERSE SURFACE ============ // ============ INVERSE SURFACE ============
static const Color inverseSurface = Color(0xFFe3e2e7); static const Color inverseSurface = Color(0xFFECE6DA);
static const Color inverseOnSurface = Color(0xFF2f3035); static const Color inverseOnSurface = Color(0xFF332F26);
// ============ SURFACE TINT ============ // ============ SURFACE TINT ============
static const Color surfaceTint = Color(0xFFadc6ff); static const Color surfaceTint = Color(0xFFFFB35C);
// ============ TEXT / CONTENT COLORS ============ // ============ TEXT / CONTENT COLORS ============
static const Color textPrimary = Color(0xFFe3e2e7); static const Color textPrimary = Color(0xFFECE6DA);
static const Color textSecondary = Color(0xFFc1c6d7); static const Color textSecondary = Color(0xFFCDC4B4);
static const Color textTertiary = Color(0xFF8b90a0); static const Color textTertiary = Color(0xFF998F7C);
// ============ STATUS COLORS ============ // ============ STATUS COLORS ============
static const Color success = Color(0xFF00E676); static const Color success = Color(0xFF6BD89B);
static const Color warning = Color(0xFFFFAB00); static const Color warning = Color(0xFFFFAB00);
static const Color info = Color(0xFF2979FF); static const Color info = Color(0xFF64B6AC);
// ============ CATEGORY COLORS (kept for semantic meaning) ============ // ============ CATEGORY COLORS (kept for semantic meaning) ============
static const Color live = Color(0xFFFF5252); static const Color live = Color(0xFFFF6E5E);
static const Color movies = Color(0xFF448AFF); static const Color movies = Color(0xFFE8B64C);
static const Color series = Color(0xFF69F0AE); static const Color series = Color(0xFF5FC9AE);
// ============ RATING / PREMIUM ============ // ============ RATING / PREMIUM ============
static const Color ratingGold = Color(0xFFFFD700); static const Color ratingGold = Color(0xFFFFD166);
static const Color premiumGold = Color(0xFFFFA000); static const Color premiumGold = Color(0xFFFFA000);
// ============ GLASSMORPHISM LEVELS ============ // ============ GLASSMORPHISM LEVELS ============
static const Color glassLevel1Bg = Color(0x66121317); // 40% opacity static const Color glassLevel1Bg = Color(0x6614110C); // 40% opacity
static const Color glassLevel1Border = Color(0x1AFFFFFF); // 10% white static const Color glassLevel1Border = Color(0x1AFFE9C9); // 10% warm white
static const Color glassLevel2Bg = Color(0x99121317); // 60% opacity static const Color glassLevel2Bg = Color(0x9914110C); // 60% opacity
static const Color glassLevel2Border = Color(0x1AFFFFFF); // 10% white static const Color glassLevel2Border = Color(0x1AFFE9C9); // 10% warm white
static const Color glassLevel2InnerGlow = Color(0x33adc6ff); // 20% primary top-left static const Color glassLevel2InnerGlow = Color(0x33FFB35C); // 20% primary top-left
// ============ GRADIENTS ============ // ============ GRADIENTS ============
static const LinearGradient primaryGradient = LinearGradient( static const LinearGradient primaryGradient = LinearGradient(
colors: [Color(0xFF007AFF), Color(0xFF00C6FF)], colors: [Color(0xFFE8941A), Color(0xFFFFC36A)],
begin: Alignment.centerLeft, begin: Alignment.centerLeft,
end: Alignment.centerRight, end: Alignment.centerRight,
); );
static const LinearGradient backgroundGradient = LinearGradient( static const LinearGradient backgroundGradient = LinearGradient(
colors: [Color(0xFF0F1014), Color(0xFF121317)], colors: [Color(0xFF0B0A08), Color(0xFF14110C)],
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
); );
// ============ GLOW / SHADOWS ============ // ============ GLOW / SHADOWS ============
static Color glowPrimary(double opacity) => static Color glowPrimary(double opacity) =>
const Color(0xFF007AFF).withOpacity(opacity); const Color(0xFFF39A1F).withOpacity(opacity);
static Color glowPrimaryDim(double opacity) => static Color glowPrimaryDim(double opacity) =>
const Color(0xFFadc6ff).withOpacity(opacity); const Color(0xFFFFB35C).withOpacity(opacity);
// ============ COLOR SCHEMES ============ // ============ COLOR SCHEMES ============
static ColorScheme get darkColorScheme => const ColorScheme.dark( static ColorScheme get darkColorScheme => const ColorScheme.dark(
@@ -162,24 +163,24 @@ class AppColors {
brightness: Brightness.dark, brightness: Brightness.dark,
); );
// Light scheme is minimal — Stitch is dark-only // Light scheme is minimal — Projector Noir is dark-first
static ColorScheme get lightColorScheme => const ColorScheme.light( static ColorScheme get lightColorScheme => const ColorScheme.light(
primary: Color(0xFF005bc1), primary: Color(0xFF8F5B00),
onPrimary: Colors.white, onPrimary: Colors.white,
primaryContainer: Color(0xFFd8e2ff), primaryContainer: Color(0xFFFFDDB3),
onPrimaryContainer: Color(0xFF001a41), onPrimaryContainer: Color(0xFF2A1700),
secondary: Color(0xFF5e5c68), secondary: Color(0xFF6F6353),
onSecondary: Colors.white, onSecondary: Colors.white,
secondaryContainer: Color(0xFFe3e1eb), secondaryContainer: Color(0xFFF0E4D0),
onSecondaryContainer: Color(0xFF1a1b22), onSecondaryContainer: Color(0xFF231B0E),
error: Color(0xFFba1a1a), error: Color(0xFFba1a1a),
onError: Colors.white, onError: Colors.white,
errorContainer: Color(0xFFFFdad6), errorContainer: Color(0xFFFFdad6),
onErrorContainer: Color(0xFF410002), onErrorContainer: Color(0xFF410002),
surface: Color(0xFFF9F9FF), surface: Color(0xFFFFF8F0),
onSurface: Color(0xFF1a1b22), onSurface: Color(0xFF1E1B15),
outline: Color(0xFF757680), outline: Color(0xFF7F766A),
outlineVariant: Color(0xFFc5c6d0), outlineVariant: Color(0xFFD0C5B4),
brightness: Brightness.light, brightness: Brightness.light,
); );
} }
+42 -42
View File
@@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'app_colors.dart'; import 'app_colors.dart';
/// XtremFlow Cyber-Cinematic Glass Theme /// XtremFlow Projector Noir Theme
/// ///
/// Design system extracted from Google Stitch. /// Warm tungsten light on deep film-black.
/// Fonts: Space Grotesk (headlines) + Inter (body/labels) /// Fonts: Syne (headlines, art-house geometric) + Instrument Sans (body/labels)
/// Style: Dark-only glassmorphism with neon blue accents. /// Style: Dark-first glassmorphism with tungsten amber accents.
class AppTheme { class AppTheme {
AppTheme._(); AppTheme._();
@@ -39,14 +39,14 @@ class AppTheme {
static const Curve curveSmooth = Curves.fastOutSlowIn; static const Curve curveSmooth = Curves.fastOutSlowIn;
// ============ TYPOGRAPHY HELPERS ============ // ============ TYPOGRAPHY HELPERS ============
static TextStyle _spaceGrotesk({ static TextStyle _syne({
required double fontSize, required double fontSize,
required FontWeight fontWeight, required FontWeight fontWeight,
double? letterSpacing, double? letterSpacing,
double? height, double? height,
Color color = AppColors.onSurface, Color color = AppColors.onSurface,
}) { }) {
return GoogleFonts.spaceGrotesk( return GoogleFonts.syne(
fontSize: fontSize, fontSize: fontSize,
fontWeight: fontWeight, fontWeight: fontWeight,
letterSpacing: letterSpacing, letterSpacing: letterSpacing,
@@ -55,14 +55,14 @@ class AppTheme {
); );
} }
static TextStyle _inter({ static TextStyle _instrumentSans({
required double fontSize, required double fontSize,
required FontWeight fontWeight, required FontWeight fontWeight,
double? letterSpacing, double? letterSpacing,
double? height, double? height,
Color color = AppColors.onSurface, Color color = AppColors.onSurface,
}) { }) {
return GoogleFonts.inter( return GoogleFonts.instrumentSans(
fontSize: fontSize, fontSize: fontSize,
fontWeight: fontWeight, fontWeight: fontWeight,
letterSpacing: letterSpacing, letterSpacing: letterSpacing,
@@ -81,85 +81,85 @@ class AppTheme {
// Typography // Typography
textTheme: TextTheme( textTheme: TextTheme(
// Display / Headline (Space Grotesk) // Display / Headline (Syne)
displayLarge: _spaceGrotesk( displayLarge: _syne(
fontSize: 48, fontSize: 48,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
letterSpacing: -0.02, letterSpacing: -0.02,
height: 1.1, height: 1.1,
), ),
displayMedium: _spaceGrotesk( displayMedium: _syne(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: -0.01, letterSpacing: -0.01,
height: 1.2, height: 1.2,
), ),
displaySmall: _spaceGrotesk( displaySmall: _syne(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
height: 1.3, height: 1.3,
), ),
headlineLarge: _spaceGrotesk( headlineLarge: _syne(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: -0.01, letterSpacing: -0.01,
height: 1.2, height: 1.2,
), ),
headlineMedium: _spaceGrotesk( headlineMedium: _syne(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
height: 1.3, height: 1.3,
), ),
headlineSmall: _spaceGrotesk( headlineSmall: _syne(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
height: 1.3, height: 1.3,
), ),
titleLarge: _spaceGrotesk( titleLarge: _syne(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleMedium: _inter( titleMedium: _instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
titleSmall: _inter( titleSmall: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
// Body (Inter) // Body (Instrument Sans)
bodyLarge: _inter( bodyLarge: _instrumentSans(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
height: 1.6, height: 1.6,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
), ),
bodyMedium: _inter( bodyMedium: _instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
height: 1.5, height: 1.5,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
), ),
bodySmall: _inter( bodySmall: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
height: 1.4, height: 1.4,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
), ),
// Labels (Inter with tracking) // Labels (Instrument Sans with tracking)
labelLarge: _inter( labelLarge: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: 0.05, letterSpacing: 0.05,
height: 1.2, height: 1.2,
), ),
labelMedium: _inter( labelMedium: _instrumentSans(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
letterSpacing: 0.02, letterSpacing: 0.02,
height: 1.2, height: 1.2,
), ),
labelSmall: _inter( labelSmall: _instrumentSans(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
letterSpacing: 0.02, letterSpacing: 0.02,
@@ -174,13 +174,13 @@ class AppTheme {
elevation: 0, elevation: 0,
centerTitle: true, centerTitle: true,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
titleTextStyle: _spaceGrotesk( titleTextStyle: _syne(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
// Inputs: Dark filled with blue glow on focus // Inputs: Dark filled with amber glow on focus
inputDecorationTheme: InputDecorationTheme( inputDecorationTheme: InputDecorationTheme(
filled: true, filled: true,
fillColor: AppColors.surfaceContainerLow, fillColor: AppColors.surfaceContainerLow,
@@ -204,12 +204,12 @@ class AppTheme {
borderRadius: BorderRadius.circular(radiusMd), borderRadius: BorderRadius.circular(radiusMd),
borderSide: const BorderSide(color: AppColors.error, width: 1), borderSide: const BorderSide(color: AppColors.error, width: 1),
), ),
hintStyle: _inter( hintStyle: _instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: AppColors.outline, color: AppColors.outline,
), ),
labelStyle: _inter( labelStyle: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
@@ -226,7 +226,7 @@ class AppTheme {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radiusMd), borderRadius: BorderRadius.circular(radiusMd),
), ),
textStyle: _inter( textStyle: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: 0.05, letterSpacing: 0.05,
@@ -253,7 +253,7 @@ class AppTheme {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radiusMd), borderRadius: BorderRadius.circular(radiusMd),
), ),
textStyle: _inter( textStyle: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: 0.05, letterSpacing: 0.05,
@@ -266,7 +266,7 @@ class AppTheme {
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: AppColors.primary, foregroundColor: AppColors.primary,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
textStyle: _inter( textStyle: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@@ -292,11 +292,11 @@ class AppTheme {
borderRadius: BorderRadius.circular(radiusXl), borderRadius: BorderRadius.circular(radiusXl),
side: const BorderSide(color: AppColors.glassLevel2Border, width: 1), side: const BorderSide(color: AppColors.glassLevel2Border, width: 1),
), ),
titleTextStyle: _spaceGrotesk( titleTextStyle: _syne(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
contentTextStyle: _inter( contentTextStyle: _instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
@@ -314,7 +314,7 @@ class AppTheme {
// Snackbars // Snackbars
snackBarTheme: SnackBarThemeData( snackBarTheme: SnackBarThemeData(
backgroundColor: AppColors.surfaceContainerHigh, backgroundColor: AppColors.surfaceContainerHigh,
contentTextStyle: _inter( contentTextStyle: _instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -336,12 +336,12 @@ class AppTheme {
shape: StadiumBorder( shape: StadiumBorder(
side: BorderSide(color: AppColors.primary.withOpacity(0.3)), side: BorderSide(color: AppColors.primary.withOpacity(0.3)),
), ),
labelStyle: _inter( labelStyle: _instrumentSans(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
secondaryLabelStyle: _inter( secondaryLabelStyle: _instrumentSans(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onPrimaryContainer, color: AppColors.onPrimaryContainer,
@@ -353,8 +353,8 @@ class AppTheme {
labelColor: AppColors.onSurface, labelColor: AppColors.onSurface,
unselectedLabelColor: AppColors.outline, unselectedLabelColor: AppColors.outline,
indicatorColor: AppColors.primaryContainer, indicatorColor: AppColors.primaryContainer,
labelStyle: _inter(fontSize: 14, fontWeight: FontWeight.w600), labelStyle: _instrumentSans(fontSize: 14, fontWeight: FontWeight.w600),
unselectedLabelStyle: _inter(fontSize: 14, fontWeight: FontWeight.w500), unselectedLabelStyle: _instrumentSans(fontSize: 14, fontWeight: FontWeight.w500),
), ),
// Divider // Divider
@@ -389,10 +389,10 @@ class AppTheme {
); );
} }
// Light theme is minimal — Stitch is dark-only // Light theme is minimal — Projector Noir is dark-first
static ThemeData get lightTheme => ThemeData.light(useMaterial3: true).copyWith( static ThemeData get lightTheme => ThemeData.light(useMaterial3: true).copyWith(
colorScheme: AppColors.lightColorScheme, colorScheme: AppColors.lightColorScheme,
scaffoldBackgroundColor: AppColors.lightColorScheme.surface, scaffoldBackgroundColor: AppColors.lightColorScheme.surface,
textTheme: GoogleFonts.interTextTheme(ThemeData.light().textTheme), textTheme: GoogleFonts.instrumentSansTextTheme(ThemeData.light().textTheme),
); );
} }
@@ -1,4 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
@@ -140,7 +140,7 @@ class _HeroCarouselState extends State<HeroCarousel> {
children: [ children: [
Text( Text(
item.title, item.title,
style: GoogleFonts.spaceGrotesk( style: GoogleFonts.syne(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -152,7 +152,7 @@ class _HeroCarouselState extends State<HeroCarousel> {
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
item.subtitle!, item.subtitle!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
@@ -245,7 +245,7 @@ class _HeroButtonState extends State<_HeroButton> {
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
widget.label, widget.label,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@@ -149,7 +149,7 @@ class _GradientButtonState extends State<GradientButton>
], ],
Text( Text(
widget.label, widget.label,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14, fontSize: 14,
@@ -253,7 +253,7 @@ class LiveBadge extends StatelessWidget {
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
'LIVE', 'LIVE',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
@@ -302,7 +302,7 @@ class CategoryChip extends StatelessWidget {
), ),
child: Text( child: Text(
label, label,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 13, fontSize: 13,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
color: isSelected ? AppColors.primary : AppColors.onSurfaceVariant, color: isSelected ? AppColors.primary : AppColors.onSurfaceVariant,
@@ -458,7 +458,7 @@ class _MediaCardState extends State<MediaCard>
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
widget.rating!, widget.rating!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
@@ -502,7 +502,7 @@ class _MediaCardState extends State<MediaCard>
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: _isHovered color: _isHovered
? AppColors.primary ? AppColors.primary
: AppColors.onSurface, : AppColors.onSurface,
@@ -518,7 +518,7 @@ class _MediaCardState extends State<MediaCard>
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
fontSize: 11, fontSize: 11,
), ),
+2 -2
View File
@@ -1,4 +1,4 @@
import 'dart:async'; 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';
@@ -38,7 +38,7 @@ class _DigitalClockState extends State<DigitalClock> {
), ),
child: Text( child: Text(
timeString, timeString,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: AppColors.onSurface, color: AppColors.onSurface,
+6 -6
View File
@@ -1,4 +1,4 @@
import 'dart:async'; 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 '../theme/app_colors.dart'; import '../theme/app_colors.dart';
@@ -220,7 +220,7 @@ class _HeroCarouselState extends State<HeroCarousel>
), ),
child: Text( child: Text(
item.badge!, item.badge!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: AppColors.primary, color: AppColors.primary,
@@ -233,7 +233,7 @@ class _HeroCarouselState extends State<HeroCarousel>
item.title, item.title,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
fontSize: 48, fontSize: 48,
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
color: AppColors.textPrimary, color: AppColors.textPrimary,
@@ -247,7 +247,7 @@ class _HeroCarouselState extends State<HeroCarousel>
item.subtitle!, item.subtitle!,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: AppColors.textSecondary, color: AppColors.textSecondary,
@@ -292,7 +292,7 @@ class _HeroCarouselState extends State<HeroCarousel>
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
'Play', 'Play',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: AppColors.primary, color: AppColors.primary,
@@ -330,7 +330,7 @@ class _HeroCarouselState extends State<HeroCarousel>
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
'More Info', 'More Info',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: AppColors.textPrimary, color: AppColors.textPrimary,
+2 -2
View File
@@ -1,4 +1,4 @@
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 '../theme/app_colors.dart'; import '../theme/app_colors.dart';
@@ -30,7 +30,7 @@ class ThemedLoading extends StatelessWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'Loading...', 'Loading...',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
+1 -1
View File
@@ -152,7 +152,7 @@ class _AdminContentState extends ConsumerState<AdminContent>
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
label, label,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14, fontSize: 14,
color: isSelected ? AppColors.textPrimary : AppColors.textSecondary, color: isSelected ? AppColors.textPrimary : AppColors.textSecondary,
+7 -7
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -144,7 +144,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
// Title // Title
Text( Text(
'XtremFlow', 'XtremFlow',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 42, fontSize: 42,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: AppColors.textPrimary, color: AppColors.textPrimary,
@@ -154,7 +154,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'Sign in to sync your playlists', 'Sign in to sync your playlists',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 18, fontSize: 18,
color: AppColors.textSecondary, color: AppColors.textSecondary,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@@ -266,7 +266,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
) )
: Text( : Text(
'Sign In', 'Sign In',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.primary, color: AppColors.primary,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -282,7 +282,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
const SizedBox(height: 32), const SizedBox(height: 32),
Text( Text(
'Default: admin / admin', 'Default: admin / admin',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
color: AppColors.textTertiary, color: AppColors.textTertiary,
), ),
@@ -310,13 +310,13 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
return TextFormField( return TextFormField(
controller: controller, controller: controller,
obscureText: obscureText, obscureText: obscureText,
style: GoogleFonts.inter(fontSize: 18, color: AppColors.textPrimary), style: GoogleFonts.instrumentSans(fontSize: 18, color: AppColors.textPrimary),
autofocus: autofocus, autofocus: autofocus,
textInputAction: nextFocus ? TextInputAction.next : TextInputAction.done, textInputAction: nextFocus ? TextInputAction.next : TextInputAction.done,
onFieldSubmitted: isLast ? (_) => onSubmitted?.call() : null, onFieldSubmitted: isLast ? (_) => onSubmitted?.call() : null,
decoration: InputDecoration( decoration: InputDecoration(
labelText: label, labelText: label,
labelStyle: GoogleFonts.inter(color: AppColors.textSecondary), labelStyle: GoogleFonts.instrumentSans(color: AppColors.textSecondary),
prefixIcon: Icon(icon, color: AppColors.textSecondary), prefixIcon: Icon(icon, color: AppColors.textSecondary),
suffixIcon: suffix, suffixIcon: suffix,
filled: true, filled: true,
+10 -10
View File
@@ -535,7 +535,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
'Unknown') 'Unknown')
.toString() .toString()
: widget.title, : widget.title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: AppColors.textPrimary, color: AppColors.textPrimary,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -544,7 +544,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
), ),
Text( Text(
'Live TV', 'Live TV',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.primary, color: AppColors.primary,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -706,7 +706,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
Expanded( Expanded(
child: Text( child: Text(
widget.title, widget.title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.white, color: Colors.white,
@@ -747,7 +747,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
seconds: _currentPosition.toInt(), seconds: _currentPosition.toInt(),
), ),
), ),
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white70, color: Colors.white70,
), ),
), ),
@@ -799,7 +799,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
seconds: _totalDuration.toInt(), seconds: _totalDuration.toInt(),
), ),
), ),
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white70, color: Colors.white70,
), ),
), ),
@@ -1060,7 +1060,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
widget.channels != null widget.channels != null
? widget.channels![_currentIndex].name ? widget.channels![_currentIndex].name
: widget.title, : widget.title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -1110,7 +1110,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
children: [ children: [
Text( Text(
currentProgram.title, currentProgram.title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontSize: 15, fontSize: 15,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -1121,7 +1121,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
if (currentProgram.description.isNotEmpty) if (currentProgram.description.isNotEmpty)
Text( Text(
currentProgram.description, currentProgram.description,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white60, color: Colors.white60,
fontSize: 12, fontSize: 12,
), ),
@@ -1156,7 +1156,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
widget.channels != null widget.channels != null
? widget.channels![_currentIndex].name ? widget.channels![_currentIndex].name
: widget.title, : widget.title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -1168,7 +1168,7 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
widget.channels != null widget.channels != null
? widget.channels![_currentIndex].name ? widget.channels![_currentIndex].name
: widget.title, : widget.title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -97,7 +97,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'Error loading playlists', 'Error loading playlists',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
fontSize: 18, fontSize: 18,
color: AppColors.textSecondary, color: AppColors.textSecondary,
), ),
@@ -109,7 +109,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
backgroundColor: AppColors.primary, backgroundColor: AppColors.primary,
foregroundColor: AppColors.textPrimary, foregroundColor: AppColors.textPrimary,
), ),
child: Text('Retry', style: GoogleFonts.inter()), child: Text('Retry', style: GoogleFonts.instrumentSans()),
), ),
], ],
), ),
@@ -128,7 +128,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'No playlists available', 'No playlists available',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
fontSize: 18, fontSize: 18,
color: Colors.white60, color: Colors.white60,
), ),
@@ -138,7 +138,7 @@ class PlaylistSelectionScreen extends ConsumerWidget {
currentUser?.isAdmin ?? false currentUser?.isAdmin ?? false
? 'Add playlists in Admin Panel' ? 'Add playlists in Admin Panel'
: 'Contact administrator', : 'Contact administrator',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
color: Colors.white38, color: Colors.white38,
), ),
@@ -269,7 +269,7 @@ class _PlaylistCardState extends State<_PlaylistCard> {
const SizedBox(height: 20), const SizedBox(height: 20),
Text( Text(
widget.playlist.name, widget.playlist.name,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.white, color: Colors.white,
@@ -281,7 +281,7 @@ class _PlaylistCardState extends State<_PlaylistCard> {
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
Uri.tryParse(widget.playlist.dns)?.host ?? widget.playlist.dns, Uri.tryParse(widget.playlist.dns)?.host ?? widget.playlist.dns,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 13, fontSize: 13,
color: Colors.white38, color: Colors.white38,
letterSpacing: 0.5, letterSpacing: 0.5,
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -143,7 +143,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
// Title // Title
Text( Text(
_seriesInfo!.name, _seriesInfo!.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -178,7 +178,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
// Season selector // Season selector
Text( Text(
'Seasons', 'Seasons',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -200,7 +200,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
}, },
selectedColor: AppColors.primaryContainer, selectedColor: AppColors.primaryContainer,
backgroundColor: AppColors.surfaceContainer, backgroundColor: AppColors.surfaceContainer,
labelStyle: GoogleFonts.inter( labelStyle: GoogleFonts.instrumentSans(
color: isSelected ? AppColors.onPrimary : AppColors.onSurfaceVariant, color: isSelected ? AppColors.onPrimary : AppColors.onSurfaceVariant,
fontSize: 12, fontSize: 12,
), ),
@@ -224,7 +224,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Text( child: Text(
'Season $_selectedSeason - ${currentEpisodes.length} Episodes', 'Season $_selectedSeason - ${currentEpisodes.length} Episodes',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -323,7 +323,7 @@ class _SeriesDetailScreenState extends ConsumerState<SeriesDetailScreen> {
? const Icon(Icons.check, color: AppColors.onSurface, size: 20) ? const Icon(Icons.check, color: AppColors.onSurface, size: 20)
: Text( : Text(
'${episode.episodeNum}', '${episode.episodeNum}',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
+2 -2
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import '../../../core/models/playlist_config.dart'; import '../../../core/models/playlist_config.dart';
@@ -99,7 +99,7 @@ class _EPGWidgetState extends ConsumerState<EPGWidget> {
), ),
child: Text( child: Text(
'LIVE', 'LIVE',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 9, fontSize: 9,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
+12 -12
View File
@@ -137,7 +137,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
: _showFavoritesOnly : _showFavoritesOnly
? 'Favorites' ? 'Favorites'
: _selectedCategory ?? 'Live TV', : _selectedCategory ?? 'Live TV',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: Colors.white, color: Colors.white,
@@ -157,10 +157,10 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
), ),
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
style: GoogleFonts.inter(color: Colors.white), style: GoogleFonts.instrumentSans(color: Colors.white),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Search channels...', hintText: 'Search channels...',
hintStyle: GoogleFonts.inter(color: Colors.white54), hintStyle: GoogleFonts.instrumentSans(color: Colors.white54),
prefixIcon: prefixIcon:
const Icon(Icons.search, color: Colors.white54), const Icon(Icons.search, color: Colors.white54),
border: InputBorder.none, border: InputBorder.none,
@@ -235,7 +235,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'No channels found', 'No channels found',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white54, color: Colors.white54,
fontSize: 18, fontSize: 18,
), ),
@@ -319,7 +319,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
child: Text( child: Text(
category, category,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.white, color: Colors.white,
@@ -331,7 +331,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
'$count Channels', '$count Channels',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 13, fontSize: 13,
color: Colors.white54, color: Colors.white54,
), ),
@@ -406,7 +406,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
) )
: Text( : Text(
channel.name.characters.first.toUpperCase(), channel.name.characters.first.toUpperCase(),
style: GoogleFonts.outfit( style: GoogleFonts.syne(
fontSize: 40, fontSize: 40,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.white24, color: Colors.white24,
@@ -427,7 +427,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
children: [ children: [
Text( Text(
channel.name, channel.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white, color: Colors.white,
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@@ -452,7 +452,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
if (epgList.isEmpty) { if (epgList.isEmpty) {
return Text( return Text(
'No Info', 'No Info',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white54, color: Colors.white54,
fontSize: 10, fontSize: 10,
), ),
@@ -480,7 +480,7 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
return Text( return Text(
currentProgram.title, currentProgram.title,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.ratingGold, color: AppColors.ratingGold,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -491,14 +491,14 @@ class _LiveTVTabState extends ConsumerState<LiveTVTab>
}, },
loading: () => Text( loading: () => Text(
'...', '...',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white24, color: Colors.white24,
fontSize: 10, fontSize: 10,
), ),
), ),
error: (_, __) => Text( error: (_, __) => Text(
'Err', 'Err',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.red, color: Colors.red,
fontSize: 10, fontSize: 10,
), ),
+8 -8
View File
@@ -1,4 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -219,7 +219,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
children: [ children: [
Text( Text(
'Movies', 'Movies',
style: GoogleFonts.spaceGrotesk( style: GoogleFonts.syne(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -251,14 +251,14 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
Expanded( Expanded(
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Search movies...', hintText: 'Search movies...',
hintStyle: hintStyle:
GoogleFonts.inter(color: AppColors.outline), GoogleFonts.instrumentSans(color: AppColors.outline),
border: InputBorder.none, border: InputBorder.none,
isDense: true, isDense: true,
contentPadding: contentPadding:
@@ -311,7 +311,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
title: m.name, title: m.name,
imageUrl: _getProxiedImageUrl(m.streamIcon), imageUrl: _getProxiedImageUrl(m.streamIcon),
subtitle: m.rating != null subtitle: m.rating != null
? '${_formatRating(m.rating)} ★' ? '${_formatRating(m.rating)} ★'
: null, : null,
onPlay: () => _playMovie(m), onPlay: () => _playMovie(m),
onTap: () => _playMovie(m), onTap: () => _playMovie(m),
@@ -426,7 +426,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
_formatRating(movie.rating)!, _formatRating(movie.rating)!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -448,7 +448,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
children: [ children: [
Text( Text(
movie.name, movie.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -467,7 +467,7 @@ class _MoviesTabState extends ConsumerState<MoviesTab> {
padding: const EdgeInsets.only(top: 4), padding: const EdgeInsets.only(top: 4),
child: Text( child: Text(
'WATCHED', 'WATCHED',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.primary, color: AppColors.primary,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -64,7 +64,7 @@ class QualitySelectorButton extends StatelessWidget {
Text( Text(
q.label, q.label,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.textPrimary, color: AppColors.textPrimary,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14, fontSize: 14,
@@ -73,7 +73,7 @@ class QualitySelectorButton extends StatelessWidget {
Text( Text(
q.description, q.description,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.textTertiary, color: AppColors.textTertiary,
fontSize: 11, fontSize: 11,
), ),
+12 -12
View File
@@ -106,7 +106,7 @@ class _RecordingModalState extends State<RecordingModal> {
Expanded( Expanded(
child: Text( child: Text(
'Programmer un enregistrement', 'Programmer un enregistrement',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -120,12 +120,12 @@ class _RecordingModalState extends State<RecordingModal> {
// Informations Chaine // Informations Chaine
Text( Text(
'Chaîne ciblée :', 'Chaîne ciblée :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14), style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
widget.channel.name, widget.channel.name,
style: GoogleFonts.inter(color: AppColors.onSurface, fontSize: 18), style: GoogleFonts.instrumentSans(color: AppColors.onSurface, fontSize: 18),
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
@@ -139,7 +139,7 @@ class _RecordingModalState extends State<RecordingModal> {
children: [ children: [
Text( Text(
'Date :', 'Date :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14), style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
TvFocusableCard( TvFocusableCard(
@@ -173,7 +173,7 @@ class _RecordingModalState extends State<RecordingModal> {
Expanded( Expanded(
child: Text( child: Text(
'${_startTime.day.toString().padLeft(2, '0')}/${_startTime.month.toString().padLeft(2, '0')}/${_startTime.year}', '${_startTime.day.toString().padLeft(2, '0')}/${_startTime.month.toString().padLeft(2, '0')}/${_startTime.year}',
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ),
@@ -193,7 +193,7 @@ class _RecordingModalState extends State<RecordingModal> {
children: [ children: [
Text( Text(
'Heure :', 'Heure :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14), style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
TvFocusableCard( TvFocusableCard(
@@ -236,7 +236,7 @@ class _RecordingModalState extends State<RecordingModal> {
Expanded( Expanded(
child: Text( child: Text(
'${_startTime.hour.toString().padLeft(2, '0')}:${_startTime.minute.toString().padLeft(2, '0')}', '${_startTime.hour.toString().padLeft(2, '0')}:${_startTime.minute.toString().padLeft(2, '0')}',
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
), ),
), ),
], ],
@@ -255,7 +255,7 @@ class _RecordingModalState extends State<RecordingModal> {
children: [ children: [
Text( Text(
'Durée (min) :', 'Durée (min) :',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, fontSize: 14), style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, fontSize: 14),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
GlassContainer.glass( GlassContainer.glass(
@@ -277,7 +277,7 @@ class _RecordingModalState extends State<RecordingModal> {
child: Text( child: Text(
'$_durationMinutes', '$_durationMinutes',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
), ),
), ),
IconButton( IconButton(
@@ -308,7 +308,7 @@ class _RecordingModalState extends State<RecordingModal> {
onPressed: _isLoading ? null : () => Navigator.of(context).pop(), onPressed: _isLoading ? null : () => Navigator.of(context).pop(),
child: Text( child: Text(
'Annuler', 'Annuler',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
@@ -328,7 +328,7 @@ class _RecordingModalState extends State<RecordingModal> {
) )
: Text( : Text(
'Enregistrer de suite', 'Enregistrer de suite',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -352,7 +352,7 @@ class _RecordingModalState extends State<RecordingModal> {
) )
: Text( : Text(
'Programmer', 'Programmer',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
+24 -24
View File
@@ -183,7 +183,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
children: [ children: [
Text( Text(
'GROUPES', 'GROUPES',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white38, color: Colors.white38,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -217,7 +217,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
), ),
child: Text( child: Text(
cat, cat,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: isSelected color: isSelected
? Colors.white ? Colors.white
: Colors.white60, : Colors.white60,
@@ -331,7 +331,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
Expanded( Expanded(
child: Text( child: Text(
ch.name, ch.name,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: isSelected color: isSelected
? Colors.white ? Colors.white
: Colors.white70, : Colors.white70,
@@ -370,7 +370,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
Text( Text(
'Sélectionnez une chaîne\npour voir son guide des programmes', 'Sélectionnez une chaîne\npour voir son guide des programmes',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white38, color: Colors.white38,
fontSize: 15, fontSize: 15,
), ),
@@ -385,7 +385,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
children: [ children: [
Text( Text(
_selectedChannel!.name, _selectedChannel!.name,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 16, fontSize: 16,
@@ -425,7 +425,7 @@ class _EpgGuideViewState extends ConsumerState<_EpgGuideView>
child: Text( child: Text(
'Aucun programme EPG disponible\npour cette chaîne', 'Aucun programme EPG disponible\npour cette chaîne',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white38, color: Colors.white38,
), ),
), ),
@@ -525,7 +525,7 @@ class _ProgrammeCard extends StatelessWidget {
Expanded( Expanded(
child: Text( child: Text(
'Enregistrer', 'Enregistrer',
style: GoogleFonts.outfit(color: Colors.white), style: GoogleFonts.syne(color: Colors.white),
), ),
), ),
], ],
@@ -536,7 +536,7 @@ class _ProgrammeCard extends StatelessWidget {
children: [ children: [
Text( Text(
title.isEmpty ? channel.name : title, title.isEmpty ? channel.name : title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 16, fontSize: 16,
@@ -658,7 +658,7 @@ class _ProgrammeCard extends StatelessWidget {
), ),
child: Text( child: Text(
'LIVE', 'LIVE',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontSize: 8, fontSize: 8,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -668,7 +668,7 @@ class _ProgrammeCard extends StatelessWidget {
else else
Text( Text(
_fmt(_start), _fmt(_start),
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: isPast ? Colors.white24 : Colors.white70, color: isPast ? Colors.white24 : Colors.white70,
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -678,14 +678,14 @@ class _ProgrammeCard extends StatelessWidget {
Text( Text(
_fmt(_end), _fmt(_end),
style: style:
GoogleFonts.outfit(color: Colors.white24, fontSize: 10), GoogleFonts.syne(color: Colors.white24, fontSize: 10),
), ),
], ],
), ),
), ),
title: Text( title: Text(
_title.isEmpty ? '—' : _title, _title.isEmpty ? '—' : _title,
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: isPast ? Colors.white38 : Colors.white, color: isPast ? Colors.white38 : Colors.white,
fontWeight: isNow ? FontWeight.bold : FontWeight.normal, fontWeight: isNow ? FontWeight.bold : FontWeight.normal,
), ),
@@ -827,7 +827,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
backgroundColor: AppColors.surfaceContainer, backgroundColor: AppColors.surfaceContainer,
title: Text( title: Text(
title, title,
style: GoogleFonts.outfit(color: Colors.white, fontSize: 14), style: GoogleFonts.syne(color: Colors.white, fontSize: 14),
), ),
content: SizedBox( content: SizedBox(
width: 500, width: 500,
@@ -863,7 +863,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
'recording' => Colors.redAccent, 'recording' => Colors.redAccent,
'completed' => Colors.green, 'completed' => Colors.green,
'failed' => Colors.orangeAccent, 'failed' => Colors.orangeAccent,
_ => Colors.blueAccent, _ => AppColors.primaryContainer,
}; };
String _statusLabel(String status) => switch (status) { String _statusLabel(String status) => switch (status) {
@@ -924,7 +924,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'Aucun enregistrement', 'Aucun enregistrement',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white38, color: Colors.white38,
fontSize: 16, fontSize: 16,
), ),
@@ -962,7 +962,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
), ),
title: Text( title: Text(
rec['title'] ?? '—', rec['title'] ?? '—',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@@ -1039,7 +1039,7 @@ class _RecordingsListViewState extends State<_RecordingsListView> {
IconButton( IconButton(
icon: const Icon( icon: const Icon(
Icons.description_outlined, Icons.description_outlined,
color: Colors.blueAccent, color: AppColors.primaryContainer,
size: 20, size: 20,
), ),
tooltip: 'Logs', tooltip: 'Logs',
@@ -1132,7 +1132,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
'Nouveau Season Pass', 'Nouveau Season Pass',
style: GoogleFonts.outfit(color: Colors.white), style: GoogleFonts.syne(color: Colors.white),
), ),
], ],
), ),
@@ -1143,7 +1143,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
children: [ children: [
Text( Text(
'Enregistre automatiquement toutes les nouvelles diffusions d\'une émission.', 'Enregistre automatiquement toutes les nouvelles diffusions d\'une émission.',
style: GoogleFonts.outfit(color: Colors.white54, fontSize: 13), style: GoogleFonts.syne(color: Colors.white54, fontSize: 13),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildField( _buildField(
@@ -1231,7 +1231,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
children: [ children: [
Text( Text(
'Enregistrements automatiques', 'Enregistrements automatiques',
style: GoogleFonts.outfit(color: Colors.white54, fontSize: 13), style: GoogleFonts.syne(color: Colors.white54, fontSize: 13),
), ),
ElevatedButton.icon( ElevatedButton.icon(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
@@ -1262,7 +1262,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
Expanded( Expanded(
child: Text( child: Text(
'Scanne l\'EPG toutes les 4h et programme automatiquement les nouvelles diffusions. Seuls les nouveaux épisodes sont enregistrés.', 'Scanne l\'EPG toutes les 4h et programme automatiquement les nouvelles diffusions. Seuls les nouveaux épisodes sont enregistrés.',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.purpleAccent.shade100, color: Colors.purpleAccent.shade100,
fontSize: 12, fontSize: 12,
), ),
@@ -1288,7 +1288,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'Aucun Season Pass actif', 'Aucun Season Pass actif',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white38, color: Colors.white38,
fontSize: 16, fontSize: 16,
), ),
@@ -1296,7 +1296,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'Créez-en un pour enregistrer automatiquement vos émissions préférées', 'Créez-en un pour enregistrer automatiquement vos émissions préférées',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white24, color: Colors.white24,
fontSize: 12, fontSize: 12,
), ),
@@ -1325,7 +1325,7 @@ class _SeasonPassesViewState extends State<_SeasonPassesView> {
), ),
title: Text( title: Text(
p['show_title'] ?? '—', p['show_title'] ?? '—',
style: GoogleFonts.outfit( style: GoogleFonts.syne(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
+5 -5
View File
@@ -199,7 +199,7 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
children: [ children: [
Text( Text(
'TV Series', 'TV Series',
style: GoogleFonts.spaceGrotesk( style: GoogleFonts.syne(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -229,14 +229,14 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
Expanded( Expanded(
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Search series...', hintText: 'Search series...',
hintStyle: hintStyle:
GoogleFonts.inter(color: AppColors.outline), GoogleFonts.instrumentSans(color: AppColors.outline),
border: InputBorder.none, border: InputBorder.none,
isDense: true, isDense: true,
contentPadding: contentPadding:
@@ -397,7 +397,7 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
bottom: 12, bottom: 12,
child: Text( child: Text(
serie.name, serie.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -440,7 +440,7 @@ class _SeriesTabState extends ConsumerState<SeriesTab> {
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
_formatRating(serie.rating)!, _formatRating(serie.rating)!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
+18 -18
View File
@@ -155,7 +155,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
const SizedBox(width: 12), const SizedBox(width: 12),
Text( Text(
'Thème', 'Thème',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -212,7 +212,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
), ),
title: Text( title: Text(
'Mode actuel', 'Mode actuel',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
@@ -279,7 +279,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
children: [ children: [
Text( Text(
title, title,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: isSelected color: isSelected
? colorScheme.primary ? colorScheme.primary
@@ -288,7 +288,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
), ),
Text( Text(
subtitle, subtitle,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 12, fontSize: 12,
color: colorScheme.onSurfaceVariant, color: colorScheme.onSurfaceVariant,
), ),
@@ -327,11 +327,11 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.person, color: AppColors.onSurface), leading: const Icon(Icons.person, color: AppColors.onSurface),
title: Text( title: Text(
'Connecté en tant que', 'Connecté en tant que',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
), ),
subtitle: Text( subtitle: Text(
currentUser?.username ?? 'Unknown', currentUser?.username ?? 'Unknown',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
@@ -340,7 +340,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
? Chip( ? Chip(
label: Text( label: Text(
'Admin', 'Admin',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 11, fontSize: 11,
color: AppColors.onPrimaryContainer, color: AppColors.onPrimaryContainer,
), ),
@@ -355,7 +355,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
// Category filters section // Category filters section
Text( Text(
'Filtres de Catégories', 'Filtres de Catégories',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 16, fontSize: 16,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -364,7 +364,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
'Seules les catégories contenant un de ces mots-clés seront affichées. Séparez par des virgules.', 'Seules les catégories contenant un de ces mots-clés seront affichées. Séparez par des virgules.',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 12, fontSize: 12,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
), ),
@@ -430,7 +430,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.playlist_play, color: AppColors.onSurface), leading: const Icon(Icons.playlist_play, color: AppColors.onSurface),
title: Text( title: Text(
'Changer de Playlist', 'Changer de Playlist',
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
), ),
trailing: const Icon(Icons.chevron_right, color: AppColors.onSurfaceVariant), trailing: const Icon(Icons.chevron_right, color: AppColors.onSurfaceVariant),
onTap: () => context.go('/playlists'), onTap: () => context.go('/playlists'),
@@ -449,11 +449,11 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.info_outline, color: AppColors.onSurface), leading: const Icon(Icons.info_outline, color: AppColors.onSurface),
title: Text( title: Text(
'À propos', 'À propos',
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
), ),
subtitle: Text( subtitle: Text(
'XtremFlow IPTV v1.0.0', 'XtremFlow IPTV v1.0.0',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
), ),
), ),
), ),
@@ -470,11 +470,11 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
leading: const Icon(Icons.cleaning_services, color: AppColors.warning), leading: const Icon(Icons.cleaning_services, color: AppColors.warning),
title: Text( title: Text(
'Maintenance', 'Maintenance',
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
), ),
subtitle: Text( subtitle: Text(
'En cas de problèmes d\'affichage ou de mise à jour', 'En cas de problèmes d\'affichage ou de mise à jour',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
), ),
trailing: FilledButton.icon( trailing: FilledButton.icon(
onPressed: () { onPressed: () {
@@ -573,7 +573,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
title, title,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 13, fontSize: 13,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -587,7 +587,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Ex: FR,FRANCE,HD,SPORT', hintText: 'Ex: FR,FRANCE,HD,SPORT',
hintStyle: hintStyle:
GoogleFonts.inter(fontSize: 12, color: AppColors.outline), GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.outline),
filled: true, filled: true,
fillColor: AppColors.surfaceContainerHigh, fillColor: AppColors.surfaceContainerHigh,
border: OutlineInputBorder( border: OutlineInputBorder(
@@ -612,7 +612,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
) )
: null, : null,
), ),
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurface), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurface),
onChanged: onChanged, onChanged: onChanged,
), ),
if (keywords.isNotEmpty) ...[ if (keywords.isNotEmpty) ...[
@@ -633,7 +633,7 @@ class _SettingsTabState extends ConsumerState<SettingsTab>
child: Text( child: Text(
keyword, keyword,
style: style:
GoogleFonts.inter(fontSize: 11, color: AppColors.onSurface), GoogleFonts.instrumentSans(fontSize: 11, color: AppColors.onSurface),
), ),
); );
}).toList(), }).toList(),
@@ -19,7 +19,7 @@ class StreamingSettingsTab extends ConsumerWidget {
// Header // Header
Text( Text(
'Paramètres Streaming Live TV', 'Paramètres Streaming Live TV',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -28,7 +28,7 @@ class StreamingSettingsTab extends ConsumerWidget {
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
'Ces paramètres s\'appliquent uniquement aux flux TV en direct.', 'Ces paramètres s\'appliquent uniquement aux flux TV en direct.',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 12, fontSize: 12,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
), ),
@@ -105,14 +105,14 @@ class StreamingSettingsTab extends ConsumerWidget {
SwitchListTile( SwitchListTile(
title: Text( title: Text(
'Reconnexion automatique', 'Reconnexion automatique',
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface), style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
), ),
subtitle: Text( subtitle: Text(
'Se reconnecter en cas de coupure', 'Se reconnecter en cas de coupure',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
), ),
value: settings.autoReconnect, value: settings.autoReconnect,
activeThumbColor: Colors.blueAccent, activeThumbColor: AppColors.primaryContainer,
onChanged: (v) => notifier.setAutoReconnect(v), onChanged: (v) => notifier.setAutoReconnect(v),
), ),
], ],
@@ -141,14 +141,14 @@ class StreamingSettingsTab extends ConsumerWidget {
SwitchListTile( SwitchListTile(
title: Text( title: Text(
'Préférer lecture directe', 'Préférer lecture directe',
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface), style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
), ),
subtitle: Text( subtitle: Text(
'Utiliser le flux original si compatible', 'Utiliser le flux original si compatible',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
), ),
value: settings.preferDirectPlay, value: settings.preferDirectPlay,
activeThumbColor: Colors.blueAccent, activeThumbColor: AppColors.primaryContainer,
onChanged: (v) => notifier.setPreferDirectPlay(v), onChanged: (v) => notifier.setPreferDirectPlay(v),
), ),
], ],
@@ -186,11 +186,11 @@ class StreamingSettingsTab extends ConsumerWidget {
SwitchListTile( SwitchListTile(
title: Text( title: Text(
'Accélération NVIDIA GPU', 'Accélération NVIDIA GPU',
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface), style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
), ),
subtitle: Text( subtitle: Text(
'Utiliser NVENC/NVDEC pour le transcodage (requiert GPU NVIDIA)', 'Utiliser NVENC/NVDEC pour le transcodage (requiert GPU NVIDIA)',
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
), ),
value: settings.enableNvidiaGpu, value: settings.enableNvidiaGpu,
activeThumbColor: Colors.green, activeThumbColor: Colors.green,
@@ -204,20 +204,20 @@ class StreamingSettingsTab extends ConsumerWidget {
Container( Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1), color: AppColors.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.blue.withOpacity(0.3)), border: Border.all(color: AppColors.primary.withOpacity(0.3)),
), ),
child: Row( child: Row(
children: [ children: [
const Icon(Icons.info_outline, color: Colors.blue), const Icon(Icons.info_outline, color: AppColors.primary),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Text(
'Les changements prennent effet immédiatement pour les nouveaux flux.', 'Les changements prennent effet immédiatement pour les nouveaux flux.',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 12, fontSize: 12,
color: Colors.blue.shade700, color: AppColors.primary,
), ),
), ),
), ),
@@ -247,11 +247,11 @@ class StreamingSettingsTab extends ConsumerWidget {
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Row( child: Row(
children: [ children: [
Icon(icon, size: 20, color: Colors.blueAccent), Icon(icon, size: 20, color: AppColors.primaryContainer),
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
title, title,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -278,11 +278,11 @@ class StreamingSettingsTab extends ConsumerWidget {
return ListTile( return ListTile(
title: Text( title: Text(
title, title,
style: GoogleFonts.inter(fontSize: 14, color: AppColors.onSurface), style: GoogleFonts.instrumentSans(fontSize: 14, color: AppColors.onSurface),
), ),
subtitle: Text( subtitle: Text(
subtitle, subtitle,
style: GoogleFonts.inter(fontSize: 12, color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(fontSize: 12, color: AppColors.onSurfaceVariant),
), ),
trailing: DropdownButton<T>( trailing: DropdownButton<T>(
value: value, value: value,
@@ -293,12 +293,12 @@ class StreamingSettingsTab extends ConsumerWidget {
value: item, value: item,
child: Text( child: Text(
labelBuilder(item), labelBuilder(item),
style: GoogleFonts.inter(fontSize: 13, color: AppColors.onSurface), style: GoogleFonts.instrumentSans(fontSize: 13, color: AppColors.onSurface),
), ),
); );
}).toList(), }).toList(),
onChanged: onChanged, onChanged: onChanged,
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
iconEnabledColor: AppColors.onSurfaceVariant, iconEnabledColor: AppColors.onSurfaceVariant,
), ),
); );
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -124,7 +124,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
const SizedBox(height: 24), const SizedBox(height: 24),
Text( Text(
'XtremFlow', 'XtremFlow',
style: GoogleFonts.spaceGrotesk( style: GoogleFonts.syne(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -133,7 +133,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
), ),
Text( Text(
'Mobile Edition', 'Mobile Edition',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
letterSpacing: 0.5, letterSpacing: 0.5,
@@ -173,7 +173,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
), ),
child: Text( child: Text(
authState.errorMessage!, authState.errorMessage!,
style: GoogleFonts.inter(color: AppColors.error, fontSize: 13), style: GoogleFonts.instrumentSans(color: AppColors.error, fontSize: 13),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
@@ -213,7 +213,7 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
) )
: Text( : Text(
'Sign In', 'Sign In',
style: GoogleFonts.inter(fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white), style: GoogleFonts.instrumentSans(fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white),
), ),
), ),
), ),
@@ -243,10 +243,10 @@ class _MobileLoginScreenState extends ConsumerState<MobileLoginScreen> {
return TextFormField( return TextFormField(
controller: controller, controller: controller,
obscureText: obscureText, obscureText: obscureText,
style: GoogleFonts.inter(color: AppColors.onSurface), style: GoogleFonts.instrumentSans(color: AppColors.onSurface),
decoration: InputDecoration( decoration: InputDecoration(
labelText: label, labelText: label,
labelStyle: GoogleFonts.inter(color: AppColors.onSurfaceVariant), labelStyle: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
prefixIcon: Icon(icon, color: AppColors.onSurfaceVariant), prefixIcon: Icon(icon, color: AppColors.onSurfaceVariant),
suffixIcon: isPassword suffixIcon: isPassword
? IconButton( ? IconButton(
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../../../features/iptv/providers/xtream_provider.dart'; import '../../../../features/iptv/providers/xtream_provider.dart';
@@ -70,7 +70,7 @@ class MobilePlaylistSelectionScreen extends ConsumerWidget {
color: AppColors.error, color: AppColors.error,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text('Error loading playlists', style: GoogleFonts.inter()), Text('Error loading playlists', style: GoogleFonts.instrumentSans()),
TextButton( TextButton(
onPressed: () => ref.refresh(playlistsProvider), onPressed: () => ref.refresh(playlistsProvider),
child: const Text('Retry'), child: const Text('Retry'),
@@ -92,7 +92,7 @@ class MobilePlaylistSelectionScreen extends ConsumerWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'No playlists available', 'No playlists available',
style: GoogleFonts.inter(color: AppColors.textSecondary), style: GoogleFonts.instrumentSans(color: AppColors.textSecondary),
), ),
], ],
), ),
@@ -177,7 +177,7 @@ class _MobilePlaylistCard extends StatelessWidget {
children: [ children: [
Text( Text(
playlist.name, playlist.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.textPrimary, color: AppColors.textPrimary,
@@ -188,7 +188,7 @@ class _MobilePlaylistCard extends StatelessWidget {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
Uri.tryParse(playlist.dns)?.host ?? playlist.dns, Uri.tryParse(playlist.dns)?.host ?? playlist.dns,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 13, fontSize: 13,
color: AppColors.textSecondary, color: AppColors.textSecondary,
), ),
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -110,7 +110,7 @@ class _MobileSeriesDetailScreenState
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'Error: $_error', 'Error: $_error',
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant), style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
), ),
TextButton( TextButton(
onPressed: _loadSeriesInfo, onPressed: _loadSeriesInfo,
@@ -186,7 +186,7 @@ class _MobileSeriesDetailScreenState
children: [ children: [
Text( Text(
_seriesInfo!.name, _seriesInfo!.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -204,7 +204,7 @@ class _MobileSeriesDetailScreenState
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
_formatRating(_seriesInfo!.rating!)!, _formatRating(_seriesInfo!.rating!)!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
fontSize: 13, fontSize: 13,
), ),
@@ -213,7 +213,7 @@ class _MobileSeriesDetailScreenState
], ],
Text( Text(
'${_seriesInfo!.episodes.keys.length} Seasons', '${_seriesInfo!.episodes.keys.length} Seasons',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
fontSize: 13, fontSize: 13,
), ),
@@ -235,7 +235,7 @@ class _MobileSeriesDetailScreenState
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Text( child: Text(
_seriesInfo!.plot!, _seriesInfo!.plot!,
style: GoogleFonts.inter(color: AppColors.onSurfaceVariant, height: 1.4), style: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant, height: 1.4),
maxLines: 4, maxLines: 4,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@@ -262,7 +262,7 @@ class _MobileSeriesDetailScreenState
}, },
backgroundColor: AppColors.surfaceContainer, backgroundColor: AppColors.surfaceContainer,
selectedColor: AppColors.primary, selectedColor: AppColors.primary,
labelStyle: GoogleFonts.inter( labelStyle: GoogleFonts.instrumentSans(
color: isSelected ? AppColors.onPrimary : AppColors.onSurfaceVariant, color: isSelected ? AppColors.onPrimary : AppColors.onSurfaceVariant,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
), ),
@@ -357,7 +357,7 @@ class _MobileSeriesDetailScreenState
children: [ children: [
Text( Text(
'E${episode.episodeNum} - ${episode.title}', 'E${episode.episodeNum} - ${episode.title}',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14, fontSize: 14,
@@ -369,7 +369,7 @@ class _MobileSeriesDetailScreenState
episode.durationSecs! > 0) episode.durationSecs! > 0)
Text( Text(
_formatDuration(episode.durationSecs!), _formatDuration(episode.durationSecs!),
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
fontSize: 12, fontSize: 12,
), ),
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import '../../../../features/iptv/providers/xtream_provider.dart'; import '../../../../features/iptv/providers/xtream_provider.dart';
@@ -80,7 +80,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'Failed to load channels', 'Failed to load channels',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white, color: Colors.white,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -153,11 +153,11 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
Expanded( Expanded(
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
style: GoogleFonts.inter(color: Colors.white), style: GoogleFonts.instrumentSans(color: Colors.white),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Search channels...', hintText: 'Search channels...',
hintStyle: hintStyle:
GoogleFonts.inter(color: Colors.white54), GoogleFonts.instrumentSans(color: Colors.white54),
border: InputBorder.none, border: InputBorder.none,
prefixIcon: const Icon( prefixIcon: const Icon(
Icons.search, Icons.search,
@@ -207,7 +207,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
), ),
child: Text( child: Text(
category, category,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: color:
isSelected ? Colors.black : Colors.white70, isSelected ? Colors.black : Colors.white70,
fontWeight: isSelected fontWeight: isSelected
@@ -233,7 +233,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
: _showFavoritesOnly : _showFavoritesOnly
? 'Favorites' ? 'Favorites'
: _selectedCategory ?? 'Channels', : _selectedCategory ?? 'Channels',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18, fontSize: 18,
@@ -285,7 +285,7 @@ class _MobileLiveTVTabState extends ConsumerState<MobileLiveTVTab> {
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
'No channels found', 'No channels found',
style: GoogleFonts.inter(color: Colors.white38), style: GoogleFonts.instrumentSans(color: Colors.white38),
), ),
], ],
), ),
@@ -382,7 +382,7 @@ class _MobileChannelTile extends StatelessWidget {
Expanded( Expanded(
child: Text( child: Text(
channel.name, channel.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: 14, fontSize: 14,
@@ -1,4 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -180,7 +180,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
id: m.streamId, id: m.streamId,
title: m.name, title: m.name,
imageUrl: _getProxiedImageUrl(m.streamIcon, ref), imageUrl: _getProxiedImageUrl(m.streamIcon, ref),
subtitle: m.rating != null ? '${_formatRating(m.rating)} ★' : null, subtitle: m.rating != null ? '${_formatRating(m.rating)} ★' : null,
onMoreInfo: () => _playMovie(m, displayMovies), onMoreInfo: () => _playMovie(m, displayMovies),
), ),
) )
@@ -206,13 +206,13 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
Expanded( Expanded(
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Search Movies...', hintText: 'Search Movies...',
hintStyle: GoogleFonts.inter(color: AppColors.onSurfaceVariant), hintStyle: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
border: InputBorder.none, border: InputBorder.none,
isDense: true, isDense: true,
contentPadding: const EdgeInsets.only(bottom: 11), contentPadding: const EdgeInsets.only(bottom: 11),
@@ -346,7 +346,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
children: [ children: [
Text( Text(
movie.name, movie.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -357,7 +357,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
if (isWatched) if (isWatched)
Text( Text(
'WATCHED', 'WATCHED',
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.primary, color: AppColors.primary,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -389,7 +389,7 @@ class _MobileMoviesTabState extends ConsumerState<MobileMoviesTab> {
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
_formatRating(movie.rating)!, _formatRating(movie.rating)!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -1,4 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -171,7 +171,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
id: s.seriesId.toString(), id: s.seriesId.toString(),
title: s.name, title: s.name,
imageUrl: _getProxiedImageUrl(s.cover, ref), imageUrl: _getProxiedImageUrl(s.cover, ref),
subtitle: s.rating != null ? '${_formatRating(s.rating)} ★' : null, subtitle: s.rating != null ? '${_formatRating(s.rating)} ★' : null,
onMoreInfo: () => _openSeries(s), onMoreInfo: () => _openSeries(s),
), ),
) )
@@ -197,13 +197,13 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
Expanded( Expanded(
child: TextField( child: TextField(
controller: _searchController, controller: _searchController,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Search Series...', hintText: 'Search Series...',
hintStyle: GoogleFonts.inter(color: AppColors.onSurfaceVariant), hintStyle: GoogleFonts.instrumentSans(color: AppColors.onSurfaceVariant),
border: InputBorder.none, border: InputBorder.none,
isDense: true, isDense: true,
contentPadding: const EdgeInsets.only(bottom: 11), contentPadding: const EdgeInsets.only(bottom: 11),
@@ -332,7 +332,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
right: 12, right: 12,
child: Text( child: Text(
series.name, series.name,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
color: AppColors.onSurface, color: AppColors.onSurface,
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@@ -364,7 +364,7 @@ class _MobileSeriesTabState extends ConsumerState<MobileSeriesTab> {
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
_formatRating(series.rating)!, _formatRating(series.rating)!,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -398,7 +398,7 @@ class _SectionHeader extends StatelessWidget {
padding: const EdgeInsets.only(left: 8, bottom: 8), padding: const EdgeInsets.only(left: 8, bottom: 8),
child: Text( child: Text(
title, title,
style: GoogleFonts.inter( style: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
+17 -17
View File
@@ -1,4 +1,4 @@
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 '../../core/theme/app_colors.dart'; import '../../core/theme/app_colors.dart';
@@ -32,69 +32,69 @@ class MobileTheme {
// Typography: Scaled down for mobile // Typography: Scaled down for mobile
textTheme: TextTheme( textTheme: TextTheme(
displayLarge: GoogleFonts.spaceGrotesk( displayLarge: GoogleFonts.syne(
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
letterSpacing: -0.02, letterSpacing: -0.02,
height: 1.1, height: 1.1,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
displayMedium: GoogleFonts.spaceGrotesk( displayMedium: GoogleFonts.syne(
fontSize: 28, fontSize: 28,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: -0.01, letterSpacing: -0.01,
height: 1.2, height: 1.2,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
displaySmall: GoogleFonts.spaceGrotesk( displaySmall: GoogleFonts.syne(
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
height: 1.3, height: 1.3,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
headlineMedium: GoogleFonts.spaceGrotesk( headlineMedium: GoogleFonts.syne(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
height: 1.3, height: 1.3,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
titleLarge: GoogleFonts.spaceGrotesk( titleLarge: GoogleFonts.syne(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
titleMedium: GoogleFonts.inter( titleMedium: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
bodyLarge: GoogleFonts.inter( bodyLarge: GoogleFonts.instrumentSans(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
height: 1.5, height: 1.5,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
), ),
bodyMedium: GoogleFonts.inter( bodyMedium: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
height: 1.5, height: 1.5,
color: AppColors.onSurfaceVariant, color: AppColors.onSurfaceVariant,
), ),
labelLarge: GoogleFonts.inter( labelLarge: GoogleFonts.instrumentSans(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: 0.05, letterSpacing: 0.05,
height: 1.2, height: 1.2,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
labelMedium: GoogleFonts.inter( labelMedium: GoogleFonts.instrumentSans(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
letterSpacing: 0.02, letterSpacing: 0.02,
height: 1.2, height: 1.2,
color: AppColors.onSurface, color: AppColors.onSurface,
), ),
labelSmall: GoogleFonts.inter( labelSmall: GoogleFonts.instrumentSans(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
letterSpacing: 0.02, letterSpacing: 0.02,
@@ -110,7 +110,7 @@ class MobileTheme {
elevation: 0, elevation: 0,
centerTitle: true, centerTitle: true,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
titleTextStyle: GoogleFonts.spaceGrotesk( titleTextStyle: GoogleFonts.syne(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.onSurface, color: AppColors.onSurface,
@@ -122,11 +122,11 @@ class MobileTheme {
backgroundColor: AppColors.surfaceContainerLow.withOpacity(0.9), backgroundColor: AppColors.surfaceContainerLow.withOpacity(0.9),
selectedItemColor: AppColors.onSurface, selectedItemColor: AppColors.onSurface,
unselectedItemColor: AppColors.outline, unselectedItemColor: AppColors.outline,
selectedLabelStyle: GoogleFonts.inter( selectedLabelStyle: GoogleFonts.instrumentSans(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
unselectedLabelStyle: GoogleFonts.inter( unselectedLabelStyle: GoogleFonts.instrumentSans(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -157,7 +157,7 @@ class MobileTheme {
width: 2, width: 2,
), ),
), ),
hintStyle: GoogleFonts.inter( hintStyle: GoogleFonts.instrumentSans(
color: AppColors.outline, color: AppColors.outline,
fontSize: 14, fontSize: 14,
), ),
@@ -173,7 +173,7 @@ class MobileTheme {
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radiusMd), borderRadius: BorderRadius.circular(radiusMd),
), ),
textStyle: GoogleFonts.inter( textStyle: GoogleFonts.instrumentSans(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14, fontSize: 14,
), ),
+3 -3
View File
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import '../../core/theme/app_colors.dart'; import '../../core/theme/app_colors.dart';
@@ -60,9 +60,9 @@ class MobileScaffold extends ConsumerWidget {
selectedItemColor: AppColors.primary, selectedItemColor: AppColors.primary,
unselectedItemColor: AppColors.textSecondary, unselectedItemColor: AppColors.textSecondary,
selectedLabelStyle: selectedLabelStyle:
GoogleFonts.inter(fontWeight: FontWeight.w600, fontSize: 11), GoogleFonts.instrumentSans(fontWeight: FontWeight.w600, fontSize: 11),
unselectedLabelStyle: unselectedLabelStyle:
GoogleFonts.inter(fontWeight: FontWeight.w500, fontSize: 11), GoogleFonts.instrumentSans(fontWeight: FontWeight.w500, fontSize: 11),
items: const [ items: const [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.live_tv_rounded), icon: Icon(Icons.live_tv_rounded),
+4 -4
View File
@@ -27,7 +27,7 @@
} }
body { body {
background: linear-gradient(135deg, #0F1014 0%, #181920 100%); background: linear-gradient(135deg, #0B0A08 0%, #1B1812 100%);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@@ -55,7 +55,7 @@
.logo { .logo {
font-size: 48px; font-size: 48px;
font-weight: 700; font-weight: 700;
background: linear-gradient(135deg, #007AFF 0%, #00C6FF 100%); background: linear-gradient(135deg, #E8941A 0%, #FFC36A 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
background-clip: text; background-clip: text;
@@ -67,8 +67,8 @@
width: 40px; width: 40px;
height: 40px; height: 40px;
margin: 0 auto 16px; margin: 0 auto 16px;
border: 3px solid rgba(0, 122, 255, 0.2); border: 3px solid rgba(243, 154, 31, 0.2);
border-top-color: #007AFF; border-top-color: #F39A1F;
border-radius: 50%; border-radius: 50%;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
} }
+9 -9
View File
@@ -1,14 +1,14 @@
/* XtremFlow web player theme tokens. /* XtremFlow web player theme tokens.
Mirrors lib/core/theme/app_colors.dart (Cyber-Cinematic Glass). Mirrors lib/core/theme/app_colors.dart (Projector Noir).
Keep both files in sync when the palette changes. */ Keep both files in sync when the palette changes. */
:root { :root {
--color-bg: #0F1014; /* AppColors.baseLevel0 */ --color-bg: #0B0A08; /* AppColors.baseLevel0 */
--color-surface: #121317; /* AppColors.surface */ --color-surface: #14110C; /* AppColors.surface */
--color-text: #e3e2e7; /* AppColors.textPrimary */ --color-text: #ECE6DA; /* AppColors.textPrimary */
--color-text-secondary: #c1c6d7;/* AppColors.textSecondary */ --color-text-secondary: #CDC4B4;/* AppColors.textSecondary */
--color-accent: #adc6ff; /* AppColors.primary */ --color-accent: #FFB35C; /* AppColors.primary */
--color-accent-strong: #4b8eff; /* AppColors.primaryContainer */ --color-accent-strong: #F39A1F; /* AppColors.primaryContainer */
--color-error: #ffb4ab; /* AppColors.error */ --color-error: #ffb4ab; /* AppColors.error */
--color-overlay: rgba(15, 16, 20, 0.6); --color-overlay: rgba(11, 10, 8, 0.6);
--color-border: rgba(255, 255, 255, 0.1); /* glassLevel1Border */ --color-border: rgba(255, 233, 201, 0.1); /* glassLevel1Border */
} }