mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-11 17:30:00 +02:00
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:
1 parent
9595afcc99
commit
e332895d7d
33 files changed
+392
-397
No files matched your search
+38
-44
@@ -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
|
||||||
@@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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 */
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user