Files
pluriwave/lib/widgets/pluri_icon.dart
T
FreeTLab 089b8b4227
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m34s
fix(i18n): normalize translations and fallbacks
2026-06-03 21:20:08 +02:00

123 lines
4.2 KiB
Dart

import 'package:flutter/material.dart';
import '../l10n/gen/app_localizations.dart';
import '../tema/pluriwave_tokens.dart';
import '../tema/pluriwave_theme.dart';
enum PluriIconGlyph { home, search, favorites, alarm, player, settings }
enum PluriIconVariant { outline, filled, activeGlow }
class PluriIcon extends StatelessWidget {
const PluriIcon({
super.key,
required this.glyph,
this.variant = PluriIconVariant.outline,
this.size = 24,
this.semanticLabel,
});
final PluriIconGlyph glyph;
final PluriIconVariant variant;
final double size;
final String? semanticLabel;
@override
Widget build(BuildContext context) {
final tokens = context.pluriTokens;
final asset = _resolveAsset();
final resolvedColor = _resolveColor(context, tokens);
final icon =
asset == null
? Icon(_resolveData(), size: size, color: resolvedColor)
: Opacity(
opacity: variant == PluriIconVariant.outline ? 0.78 : 1,
child: Image.asset(
asset,
width: size,
height: size,
fit: BoxFit.contain,
errorBuilder:
(_, __, ___) =>
Icon(_resolveData(), size: size, color: resolvedColor),
),
);
final child =
variant == PluriIconVariant.activeGlow
? Container(
width: size + 14,
height: size + 14,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: tokens.glowColor,
blurRadius: 18,
spreadRadius: 1,
),
],
),
alignment: Alignment.center,
child: icon,
)
: icon;
return Semantics(
label: semanticLabel ?? _fallbackLabel(AppLocalizations.of(context), glyph),
image: true,
child: ExcludeSemantics(child: child),
);
}
String? _resolveAsset() {
return switch (glyph) {
PluriIconGlyph.home => 'assets/icons/pluri_home.png',
PluriIconGlyph.search => 'assets/icons/pluri_search.png',
PluriIconGlyph.favorites => 'assets/icons/pluri_favorites.png',
PluriIconGlyph.alarm => 'assets/icons/pluri_alarm.png',
PluriIconGlyph.player => 'assets/icons/pluri_player.png',
PluriIconGlyph.settings => 'assets/icons/pluri_settings.png',
};
}
Color _resolveColor(BuildContext context, PluriWaveTokens tokens) {
if (variant == PluriIconVariant.activeGlow) return tokens.electricMagenta;
if (variant == PluriIconVariant.filled) {
return Theme.of(context).colorScheme.onSurface;
}
return Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.78);
}
IconData _resolveData() {
return switch ((glyph, variant)) {
(PluriIconGlyph.home, PluriIconVariant.outline) => Icons.home_outlined,
(PluriIconGlyph.home, _) => Icons.home_rounded,
(PluriIconGlyph.search, PluriIconVariant.outline) =>
Icons.search_outlined,
(PluriIconGlyph.search, _) => Icons.search_rounded,
(PluriIconGlyph.favorites, PluriIconVariant.outline) =>
Icons.favorite_border_rounded,
(PluriIconGlyph.favorites, _) => Icons.favorite_rounded,
(PluriIconGlyph.alarm, PluriIconVariant.outline) => Icons.alarm_outlined,
(PluriIconGlyph.alarm, _) => Icons.alarm_rounded,
(PluriIconGlyph.player, PluriIconVariant.outline) =>
Icons.play_circle_outline_rounded,
(PluriIconGlyph.player, _) => Icons.play_circle_rounded,
(PluriIconGlyph.settings, PluriIconVariant.outline) =>
Icons.settings_outlined,
(PluriIconGlyph.settings, _) => Icons.settings_rounded,
};
}
String _fallbackLabel(AppLocalizations l10n, PluriIconGlyph glyph) {
return switch (glyph) {
PluriIconGlyph.home => l10n.navHome,
PluriIconGlyph.search => l10n.navSearch,
PluriIconGlyph.favorites => l10n.navFavorites,
PluriIconGlyph.alarm => l10n.navAlarms,
PluriIconGlyph.player => l10n.playerIconLabel,
PluriIconGlyph.settings => l10n.navSettings,
};
}
}