Refonte du logo et des icônes aux couleurs du thème (Android, Fire TV, iOS)
- Nouveau logo vectoriel : bouton play dégradé cyan→bleu (#0A84FF) avec traînées de vitesse, sur tuile graphite (#2C2C33→#1B1B1F) comme l'app - scripts/generate_icons.py génère toutes les tailles depuis les SVG (assets/branding/) - Android : icône adaptative dans la zone sûre, icône ronde, écran de lancement graphite avec logo - Android TV / Fire TV : bannière 320x180, LEANBACK_LAUNCHER, écran tactile et leanback non requis - iOS : icône carrée sans alpha dédiée (app_icon_ios.png) - Remplace l'ancien logo (JPEG avec damier incrusté) et corrige la référence à logo_xtremobile.png inexistant dans les réglages Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GyudLt8TgggqbWWkqjB19K
No files matched your search
@@ -3,10 +3,17 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
|
||||||
|
<!-- Android TV / Fire TV : l'app reste installable sur téléphone
|
||||||
|
et apparaît dans le lanceur TV (pas d'écran tactile requis). -->
|
||||||
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||||
|
<uses-feature android:name="android.software.leanback" android:required="false"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="XtremFlow"
|
android:label="XtremFlow"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:banner="@drawable/banner"
|
||||||
android:usesCleartextTraffic="true">
|
android:usesCleartextTraffic="true">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
@@ -28,6 +35,7 @@
|
|||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -1,12 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Modify this file to customize your launch splash screen -->
|
<!-- Écran de lancement : fond graphite du thème + logo centré -->
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="?android:colorBackground" />
|
<item android:drawable="@color/ic_launcher_background" />
|
||||||
|
<item>
|
||||||
<!-- You can insert your own image assets here -->
|
|
||||||
<!-- <item>
|
|
||||||
<bitmap
|
<bitmap
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:src="@mipmap/launch_image" />
|
android:src="@drawable/ic_launcher_foreground" />
|
||||||
</item> -->
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 22 KiB |
@@ -1,12 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Modify this file to customize your launch splash screen -->
|
<!-- Écran de lancement : fond graphite du thème + logo centré -->
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="@android:color/white" />
|
<item android:drawable="@color/ic_launcher_background" />
|
||||||
|
<item>
|
||||||
<!-- You can insert your own image assets here -->
|
|
||||||
<!-- <item>
|
|
||||||
<bitmap
|
<bitmap
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:src="@mipmap/launch_image" />
|
android:src="@drawable/ic_launcher_foreground" />
|
||||||
</item> -->
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Icône adaptative : le calque avant est déjà dessiné dans la zone sûre
|
||||||
|
(66dp sur 108dp), aucun inset supplémentaire n'est nécessaire.
|
||||||
|
Généré par scripts/generate_icons.py -->
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<inset
|
|
||||||
android:drawable="@drawable/ic_launcher_foreground"
|
|
||||||
android:inset="16%" />
|
|
||||||
</foreground>
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Icône adaptative : le calque avant est déjà dessiné dans la zone sûre
|
||||||
|
(66dp sur 108dp), aucun inset supplémentaire n'est nécessaire.
|
||||||
|
Généré par scripts/generate_icons.py -->
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
@@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="ic_launcher_background">#1a1a2e</color>
|
<!-- baseLevel0 de lib/core/theme/app_colors.dart -->
|
||||||
|
<color name="ic_launcher_background">#1B1B1F</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#2C2C33"/>
|
||||||
|
<stop offset="1" stop-color="#1B1B1F"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#0A84FF" stop-opacity="0.35"/>
|
||||||
|
<stop offset="1" stop-color="#0A84FF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="play" x1="0.2" y1="0" x2="0.9" y2="1">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2"/>
|
||||||
|
<stop offset="0.55" stop-color="#0A84FF"/>
|
||||||
|
<stop offset="1" stop-color="#0A5BD6"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="streak" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="28" y2="0">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="#7DD3F2" stop-opacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.07"/>
|
||||||
|
<stop offset="0.5" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g transform="translate(215.04 215.04) scale(5.9392)">
|
||||||
|
<circle cx="56" cy="50" r="50" fill="url(#glow)"/>
|
||||||
|
<path d="M40 22 L84 50 L40 78 Z" fill="url(#play)" stroke="url(#play)"
|
||||||
|
stroke-width="12" stroke-linejoin="round"/>
|
||||||
|
<path d="M44 34 L66 48" stroke="#FFFFFF" stroke-opacity="0.28"
|
||||||
|
stroke-width="4" stroke-linecap="round"/>
|
||||||
|
<g stroke="url(#streak)" stroke-linecap="round" fill="none">
|
||||||
|
<path d="M6 38 L28 38" stroke-width="7"/>
|
||||||
|
<path d="M0 50 L28 50" stroke-width="7"/>
|
||||||
|
<path d="M10 62 L28 62" stroke-width="7"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,40 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#2C2C33"/>
|
||||||
|
<stop offset="1" stop-color="#1B1B1F"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#0A84FF" stop-opacity="0.35"/>
|
||||||
|
<stop offset="1" stop-color="#0A84FF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="play" x1="0.2" y1="0" x2="0.9" y2="1">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2"/>
|
||||||
|
<stop offset="0.55" stop-color="#0A84FF"/>
|
||||||
|
<stop offset="1" stop-color="#0A5BD6"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="streak" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="28" y2="0">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="#7DD3F2" stop-opacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.07"/>
|
||||||
|
<stop offset="0.5" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<circle cx="512.0" cy="512.0" r="512.0" fill="url(#bg)"/>
|
||||||
|
<circle cx="512.0" cy="512.0" r="512.0" fill="url(#shine)"/>
|
||||||
|
|
||||||
|
<g transform="translate(194.56 194.56) scale(6.3488)">
|
||||||
|
<circle cx="56" cy="50" r="50" fill="url(#glow)"/>
|
||||||
|
<path d="M40 22 L84 50 L40 78 Z" fill="url(#play)" stroke="url(#play)"
|
||||||
|
stroke-width="12" stroke-linejoin="round"/>
|
||||||
|
<path d="M44 34 L66 48" stroke="#FFFFFF" stroke-opacity="0.28"
|
||||||
|
stroke-width="4" stroke-linecap="round"/>
|
||||||
|
<g stroke="url(#streak)" stroke-linecap="round" fill="none">
|
||||||
|
<path d="M6 38 L28 38" stroke-width="7"/>
|
||||||
|
<path d="M0 50 L28 50" stroke-width="7"/>
|
||||||
|
<path d="M10 62 L28 62" stroke-width="7"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,42 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#2C2C33"/>
|
||||||
|
<stop offset="1" stop-color="#1B1B1F"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#0A84FF" stop-opacity="0.35"/>
|
||||||
|
<stop offset="1" stop-color="#0A84FF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="play" x1="0.2" y1="0" x2="0.9" y2="1">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2"/>
|
||||||
|
<stop offset="0.55" stop-color="#0A84FF"/>
|
||||||
|
<stop offset="1" stop-color="#0A5BD6"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="streak" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="28" y2="0">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="#7DD3F2" stop-opacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.07"/>
|
||||||
|
<stop offset="0.5" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="1024" height="1024" rx="230.4" fill="url(#bg)"/>
|
||||||
|
<rect width="1024" height="1024" rx="230.4" fill="url(#shine)"/>
|
||||||
|
<rect x="1.5" y="1.5" width="1021" height="1021" rx="228.9"
|
||||||
|
fill="none" stroke="#FFFFFF" stroke-opacity="0.06" stroke-width="3"/>
|
||||||
|
|
||||||
|
<g transform="translate(184.32 184.32) scale(6.5536)">
|
||||||
|
<circle cx="56" cy="50" r="50" fill="url(#glow)"/>
|
||||||
|
<path d="M40 22 L84 50 L40 78 Z" fill="url(#play)" stroke="url(#play)"
|
||||||
|
stroke-width="12" stroke-linejoin="round"/>
|
||||||
|
<path d="M44 34 L66 48" stroke="#FFFFFF" stroke-opacity="0.28"
|
||||||
|
stroke-width="4" stroke-linecap="round"/>
|
||||||
|
<g stroke="url(#streak)" stroke-linecap="round" fill="none">
|
||||||
|
<path d="M6 38 L28 38" stroke-width="7"/>
|
||||||
|
<path d="M0 50 L28 50" stroke-width="7"/>
|
||||||
|
<path d="M10 62 L28 62" stroke-width="7"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,42 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#2C2C33"/>
|
||||||
|
<stop offset="1" stop-color="#1B1B1F"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#0A84FF" stop-opacity="0.35"/>
|
||||||
|
<stop offset="1" stop-color="#0A84FF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="play" x1="0.2" y1="0" x2="0.9" y2="1">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2"/>
|
||||||
|
<stop offset="0.55" stop-color="#0A84FF"/>
|
||||||
|
<stop offset="1" stop-color="#0A5BD6"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="streak" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="28" y2="0">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="#7DD3F2" stop-opacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.07"/>
|
||||||
|
<stop offset="0.5" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="1024" height="1024" rx="0" fill="url(#bg)"/>
|
||||||
|
<rect width="1024" height="1024" rx="0" fill="url(#shine)"/>
|
||||||
|
<rect x="1.5" y="1.5" width="1021" height="1021" rx="0"
|
||||||
|
fill="none" stroke="#FFFFFF" stroke-opacity="0.06" stroke-width="3"/>
|
||||||
|
|
||||||
|
<g transform="translate(184.32 184.32) scale(6.5536)">
|
||||||
|
<circle cx="56" cy="50" r="50" fill="url(#glow)"/>
|
||||||
|
<path d="M40 22 L84 50 L40 78 Z" fill="url(#play)" stroke="url(#play)"
|
||||||
|
stroke-width="12" stroke-linejoin="round"/>
|
||||||
|
<path d="M44 34 L66 48" stroke="#FFFFFF" stroke-opacity="0.28"
|
||||||
|
stroke-width="4" stroke-linecap="round"/>
|
||||||
|
<g stroke="url(#streak)" stroke-linecap="round" fill="none">
|
||||||
|
<path d="M6 38 L28 38" stroke-width="7"/>
|
||||||
|
<path d="M0 50 L28 50" stroke-width="7"/>
|
||||||
|
<path d="M10 62 L28 62" stroke-width="7"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,44 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="180" viewBox="0 0 320 180">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#2C2C33"/>
|
||||||
|
<stop offset="1" stop-color="#1B1B1F"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#0A84FF" stop-opacity="0.35"/>
|
||||||
|
<stop offset="1" stop-color="#0A84FF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="play" x1="0.2" y1="0" x2="0.9" y2="1">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2"/>
|
||||||
|
<stop offset="0.55" stop-color="#0A84FF"/>
|
||||||
|
<stop offset="1" stop-color="#0A5BD6"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="streak" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="28" y2="0">
|
||||||
|
<stop offset="0" stop-color="#7DD3F2" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="#7DD3F2" stop-opacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.07"/>
|
||||||
|
<stop offset="0.5" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="320" height="180" fill="url(#bg)"/>
|
||||||
|
<rect width="320" height="180" fill="url(#shine)"/>
|
||||||
|
|
||||||
|
<g transform="translate(29.60 39.60) scale(1.0080)">
|
||||||
|
<circle cx="56" cy="50" r="50" fill="url(#glow)"/>
|
||||||
|
<path d="M40 22 L84 50 L40 78 Z" fill="url(#play)" stroke="url(#play)"
|
||||||
|
stroke-width="12" stroke-linejoin="round"/>
|
||||||
|
<path d="M44 34 L66 48" stroke="#FFFFFF" stroke-opacity="0.28"
|
||||||
|
stroke-width="4" stroke-linecap="round"/>
|
||||||
|
<g stroke="url(#streak)" stroke-linecap="round" fill="none">
|
||||||
|
<path d="M6 38 L28 38" stroke-width="7"/>
|
||||||
|
<path d="M0 50 L28 50" stroke-width="7"/>
|
||||||
|
<path d="M10 62 L28 62" stroke-width="7"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<text x="140.8" y="101.0" font-family="Inter" font-weight="bold"
|
||||||
|
font-size="32" fill="#F5F5F7" letter-spacing="-0.6">Xtrem<tspan fill="#8AB9FF">Flow</tspan></text>
|
||||||
|
<text x="141.8" y="124.0" font-family="Inter" font-weight="600"
|
||||||
|
font-size="12" fill="#98989F" letter-spacing="2.4">IPTV PLAYER</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 477 KiB After Width: | Height: | Size: 38 KiB |
@@ -5,6 +5,6 @@
|
|||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
ios: true
|
ios: true
|
||||||
android: false
|
android: false
|
||||||
image_path: "assets/images/logo_xtremflow.png"
|
image_path: "assets/images/app_icon_ios.png"
|
||||||
# L'App Store et iOS refusent une icône avec canal alpha.
|
# L'App Store et iOS refusent une icône avec canal alpha.
|
||||||
remove_alpha_ios: true
|
remove_alpha_ios: true
|
||||||
@@ -85,7 +85,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
|
|||||||
height: 48,
|
height: 48,
|
||||||
// No decoration for free-floating logo
|
// No decoration for free-floating logo
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/logo_xtremobile.png',
|
'assets/images/logo_xtremflow.png',
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
errorBuilder: (_, __, ___) => Icon(
|
errorBuilder: (_, __, ___) => Icon(
|
||||||
Icons.play_circle_filled,
|
Icons.play_circle_filled,
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ dev_dependencies:
|
|||||||
riverpod_generator: ^2.4.0
|
riverpod_generator: ^2.4.0
|
||||||
hive_generator: ^2.0.1
|
hive_generator: ^2.0.1
|
||||||
|
|
||||||
|
# Les icônes Android (mipmap, adaptative, bannière TV) sont générées par
|
||||||
|
# scripts/generate_icons.py et versionnées : ne pas les écraser ici.
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
android: true
|
android: false
|
||||||
ios: true
|
ios: true
|
||||||
image_path: "assets/images/logo_xtremflow.png"
|
image_path: "assets/images/app_icon_ios.png"
|
||||||
adaptive_icon_background: "#1a1a2e"
|
|
||||||
adaptive_icon_foreground: "assets/images/logo_xtremflow.png"
|
|
||||||
# iOS refuse une icône comportant un canal alpha.
|
# iOS refuse une icône comportant un canal alpha.
|
||||||
remove_alpha_ios: true
|
remove_alpha_ios: true
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Génère toutes les icônes XtremFlow à partir d'un seul dessin vectoriel.
|
||||||
|
|
||||||
|
Palette alignée sur lib/core/theme/app_colors.dart (graphite + bleu Apple).
|
||||||
|
|
||||||
|
Sorties :
|
||||||
|
assets/branding/*.svg sources vectorielles
|
||||||
|
assets/images/logo_xtremflow.png logo in-app (fond transparent)
|
||||||
|
assets/images/app_icon_ios.png icône iOS (carré plein, sans alpha)
|
||||||
|
android/.../mipmap-*/ic_launcher.png icône legacy (tuile arrondie)
|
||||||
|
android/.../mipmap-*/ic_launcher_round.png icône legacy ronde
|
||||||
|
android/.../drawable-*/ic_launcher_foreground.png calque adaptatif
|
||||||
|
android/.../drawable-xhdpi/banner.png bannière Android TV / Fire TV
|
||||||
|
|
||||||
|
Usage : pip install cairosvg pillow && python3 scripts/generate_icons.py
|
||||||
|
La bannière utilise la police Inter (Bold) si elle est installée.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
|
||||||
|
import cairosvg
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
RES = os.path.join(ROOT, "android", "app", "src", "main", "res")
|
||||||
|
|
||||||
|
# Couleurs du thème (app_colors.dart)
|
||||||
|
BG_TOP = "#2C2C33" # surfaceContainerLow
|
||||||
|
BG_BOTTOM = "#1B1B1F" # baseLevel0
|
||||||
|
BLUE = "#0A84FF" # primaryContainer
|
||||||
|
BLUE_LIGHT = "#8AB9FF" # primary
|
||||||
|
CYAN = "#7DD3F2" # tertiary
|
||||||
|
|
||||||
|
DEFS = f"""
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="{BG_TOP}"/>
|
||||||
|
<stop offset="1" stop-color="{BG_BOTTOM}"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="{BLUE}" stop-opacity="0.35"/>
|
||||||
|
<stop offset="1" stop-color="{BLUE}" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="play" x1="0.2" y1="0" x2="0.9" y2="1">
|
||||||
|
<stop offset="0" stop-color="{CYAN}"/>
|
||||||
|
<stop offset="0.55" stop-color="{BLUE}"/>
|
||||||
|
<stop offset="1" stop-color="#0A5BD6"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="streak" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="28" y2="0">
|
||||||
|
<stop offset="0" stop-color="{CYAN}" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="{CYAN}" stop-opacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.07"/>
|
||||||
|
<stop offset="0.5" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>"""
|
||||||
|
|
||||||
|
|
||||||
|
def mark(cx, cy, size):
|
||||||
|
"""Le symbole : un bouton play fluide précédé de traînées de vitesse.
|
||||||
|
|
||||||
|
Dessiné dans une boîte de 100x100 centrée sur (cx, cy), mise à l'échelle
|
||||||
|
à `size` pixels.
|
||||||
|
"""
|
||||||
|
s = size / 100.0
|
||||||
|
tx, ty = cx - 50 * s, cy - 50 * s
|
||||||
|
return f"""
|
||||||
|
<g transform="translate({tx:.2f} {ty:.2f}) scale({s:.4f})">
|
||||||
|
<circle cx="56" cy="50" r="50" fill="url(#glow)"/>
|
||||||
|
<path d="M40 22 L84 50 L40 78 Z" fill="url(#play)" stroke="url(#play)"
|
||||||
|
stroke-width="12" stroke-linejoin="round"/>
|
||||||
|
<path d="M44 34 L66 48" stroke="#FFFFFF" stroke-opacity="0.28"
|
||||||
|
stroke-width="4" stroke-linecap="round"/>
|
||||||
|
<g stroke="url(#streak)" stroke-linecap="round" fill="none">
|
||||||
|
<path d="M6 38 L28 38" stroke-width="7"/>
|
||||||
|
<path d="M0 50 L28 50" stroke-width="7"/>
|
||||||
|
<path d="M10 62 L28 62" stroke-width="7"/>
|
||||||
|
</g>
|
||||||
|
</g>"""
|
||||||
|
|
||||||
|
|
||||||
|
def svg(w, h, body):
|
||||||
|
return (
|
||||||
|
f'<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" '
|
||||||
|
f'viewBox="0 0 {w} {h}">{DEFS}{body}\n</svg>\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def tile(size, radius_ratio, mark_ratio=0.64):
|
||||||
|
"""Tuile graphite (arrondie ou pleine) avec le symbole centré."""
|
||||||
|
r = size * radius_ratio
|
||||||
|
body = f"""
|
||||||
|
<rect width="{size}" height="{size}" rx="{r}" fill="url(#bg)"/>
|
||||||
|
<rect width="{size}" height="{size}" rx="{r}" fill="url(#shine)"/>
|
||||||
|
<rect x="1.5" y="1.5" width="{size - 3}" height="{size - 3}" rx="{max(r - 1.5, 0)}"
|
||||||
|
fill="none" stroke="#FFFFFF" stroke-opacity="0.06" stroke-width="3"/>
|
||||||
|
{mark(size / 2, size / 2, size * mark_ratio)}"""
|
||||||
|
return svg(size, size, body)
|
||||||
|
|
||||||
|
|
||||||
|
def round_tile(size):
|
||||||
|
body = f"""
|
||||||
|
<circle cx="{size / 2}" cy="{size / 2}" r="{size / 2}" fill="url(#bg)"/>
|
||||||
|
<circle cx="{size / 2}" cy="{size / 2}" r="{size / 2}" fill="url(#shine)"/>
|
||||||
|
{mark(size / 2, size / 2, size * 0.62)}"""
|
||||||
|
return svg(size, size, body)
|
||||||
|
|
||||||
|
|
||||||
|
def adaptive_foreground(size):
|
||||||
|
# 108dp de canevas, zone sûre de 66dp : le symbole occupe ~58% du canevas,
|
||||||
|
# soit l'intérieur du cercle sûr quelle que soit la forme du masque.
|
||||||
|
return svg(size, size, mark(size / 2, size / 2, size * 0.58))
|
||||||
|
|
||||||
|
|
||||||
|
def banner(w=320, h=180):
|
||||||
|
"""Bannière TV (Android TV / Fire TV) : 320x180 px en xhdpi."""
|
||||||
|
body = f"""
|
||||||
|
<rect width="{w}" height="{h}" fill="url(#bg)"/>
|
||||||
|
<rect width="{w}" height="{h}" fill="url(#shine)"/>
|
||||||
|
{mark(w * 0.25, h / 2, h * 0.56)}
|
||||||
|
<text x="{w * 0.44}" y="{h / 2 + 11}" font-family="Inter" font-weight="bold"
|
||||||
|
font-size="32" fill="#F5F5F7" letter-spacing="-0.6">Xtrem<tspan fill="{BLUE_LIGHT}">Flow</tspan></text>
|
||||||
|
<text x="{w * 0.44 + 1}" y="{h / 2 + 34}" font-family="Inter" font-weight="600"
|
||||||
|
font-size="12" fill="#98989F" letter-spacing="2.4">IPTV PLAYER</text>"""
|
||||||
|
return svg(w, h, body)
|
||||||
|
|
||||||
|
|
||||||
|
def render(svg_text, out_path, size=None, flatten=None):
|
||||||
|
png = cairosvg.svg2png(
|
||||||
|
bytestring=svg_text.encode(),
|
||||||
|
output_width=size[0] if size else None,
|
||||||
|
output_height=size[1] if size else None,
|
||||||
|
)
|
||||||
|
img = Image.open(io.BytesIO(png)).convert("RGBA")
|
||||||
|
if flatten:
|
||||||
|
bg = Image.new("RGBA", img.size, flatten)
|
||||||
|
bg.alpha_composite(img)
|
||||||
|
img = bg.convert("RGB")
|
||||||
|
os.makedirs(os.path.dirname(out_path), exist_ok=True)
|
||||||
|
img.save(out_path, optimize=True)
|
||||||
|
print(" ", os.path.relpath(out_path, ROOT), img.size)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
brand = os.path.join(ROOT, "assets", "branding")
|
||||||
|
os.makedirs(brand, exist_ok=True)
|
||||||
|
sources = {
|
||||||
|
"icon_rounded.svg": tile(1024, 0.225),
|
||||||
|
"icon_square.svg": tile(1024, 0),
|
||||||
|
"icon_round.svg": round_tile(1024),
|
||||||
|
"icon_foreground.svg": adaptive_foreground(1024),
|
||||||
|
"tv_banner.svg": banner(),
|
||||||
|
}
|
||||||
|
for name, text in sources.items():
|
||||||
|
with open(os.path.join(brand, name), "w") as f:
|
||||||
|
f.write(text)
|
||||||
|
|
||||||
|
print("Assets Flutter :")
|
||||||
|
render(sources["icon_rounded.svg"], os.path.join(ROOT, "assets/images/logo_xtremflow.png"), (512, 512))
|
||||||
|
# iOS applique son propre masque et refuse l'alpha : carré plein.
|
||||||
|
render(sources["icon_square.svg"], os.path.join(ROOT, "assets/images/app_icon_ios.png"), (1024, 1024), flatten=BG_BOTTOM)
|
||||||
|
|
||||||
|
print("Android :")
|
||||||
|
densities = {"mdpi": 1, "hdpi": 1.5, "xhdpi": 2, "xxhdpi": 3, "xxxhdpi": 4}
|
||||||
|
for d, k in densities.items():
|
||||||
|
legacy = round(48 * k)
|
||||||
|
fg = round(108 * k)
|
||||||
|
render(sources["icon_rounded.svg"], f"{RES}/mipmap-{d}/ic_launcher.png", (legacy, legacy))
|
||||||
|
render(sources["icon_round.svg"], f"{RES}/mipmap-{d}/ic_launcher_round.png", (legacy, legacy))
|
||||||
|
render(sources["icon_foreground.svg"], f"{RES}/drawable-{d}/ic_launcher_foreground.png", (fg, fg))
|
||||||
|
# Bannière TV : 160x90dp -> 320x180 en xhdpi (taille de référence Google/Amazon).
|
||||||
|
render(sources["tv_banner.svg"], f"{RES}/drawable-xhdpi/banner.png", (320, 180), flatten=BG_BOTTOM)
|
||||||
|
render(sources["tv_banner.svg"], f"{RES}/drawable-xxhdpi/banner.png", (480, 270), flatten=BG_BOTTOM)
|
||||||
|
render(sources["tv_banner.svg"], f"{RES}/drawable-xxxhdpi/banner.png", (640, 360), flatten=BG_BOTTOM)
|
||||||
|
# Aperçu grand format pour les stores / README.
|
||||||
|
render(sources["tv_banner.svg"], os.path.join(brand, "tv_banner_1280x720.png"), (1280, 720), flatten=BG_BOTTOM)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||