feat(ui): la carte reprend l'image importée en fond (voile pour lisibilité)
Build APK / build (push) Successful in 2m49s

- ServerCard: fond = image (MemoryImage) + scrim dégradé si présente, sinon
  dégradé thématique ; vignette d'icône masquée quand image de fond.
- servers_screen: fetch des bytes image (cache par id, vidé au refresh) → passe
  à la carte ; plus de FutureBuilder iconUrl inutile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
neckfire
2026-07-13 13:00:10 +02:00
co-authored by Claude Opus 4.8
parent 2862fdd408
commit fb4ab95f13
2 changed files with 48 additions and 13 deletions
+32 -10
View File
@@ -1,3 +1,5 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
@@ -11,6 +13,7 @@ class ServerCard extends StatelessWidget {
required this.busy,
required this.onToggle,
this.onTap,
this.imageBytes,
});
final GameServer server;
@@ -18,31 +21,49 @@ class ServerCard extends StatelessWidget {
final bool busy;
final VoidCallback onToggle;
final VoidCallback? onTap;
final Uint8List? imageBytes;
@override
Widget build(BuildContext context) {
final t = server.theme;
final badge = server.statusBadge;
final hasImg = imageBytes != null;
return Card(
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: onTap,
child: Ink(
decoration: hasImg
? BoxDecoration(
image: DecorationImage(image: MemoryImage(imageBytes!), fit: BoxFit.cover),
)
: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [t.start, t.end],
),
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [t.start, t.end],
),
),
decoration: hasImg
? const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0x66000000), Color(0xCC000000)],
),
)
: null,
padding: const EdgeInsets.all(18),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
_Icon(server: server, iconUrl: iconUrl, fallback: t.icon),
const SizedBox(width: 14),
if (!hasImg) ...[
_Icon(server: server, iconUrl: iconUrl, fallback: t.icon),
const SizedBox(width: 14),
],
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -107,6 +128,7 @@ class ServerCard extends StatelessWidget {
),
),
),
),
);
}
}
@@ -124,7 +146,7 @@ class _Icon extends StatelessWidget {
child: SizedBox(
width: 52,
height: 52,
child: (server.hasIcon)
child: (server.hasIcon && iconUrl.isNotEmpty)
? Image.network(iconUrl,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => _fallbackBox())