feat(App): update Finlytic Flutter app UI and blocs

This commit is contained in:
2026-08-09 21:01:46 +02:00
parent e7427b7464
commit a708d2977c
591 changed files with 1095105 additions and 0 deletions
@@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../core/theme/app_theme.dart';
import '../../features/favorites/cubit/favorites_cubit.dart';
/// Reusable animated Favorite Star Toggle Button connected to global FavoritesCubit.
class FavoriteStarButton extends StatefulWidget {
final String identifier;
final String? symbol;
final String? name;
final double size;
final EdgeInsetsGeometry? padding;
const FavoriteStarButton({
super.key,
required this.identifier,
this.symbol,
this.name,
this.size = 22,
this.padding = const EdgeInsets.all(8),
});
@override
State<FavoriteStarButton> createState() => _FavoriteStarButtonState();
}
class _FavoriteStarButtonState extends State<FavoriteStarButton> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 200),
);
_scaleAnimation = TweenSequence<double>([
TweenSequenceItem(tween: Tween(begin: 1.0, end: 1.3), weight: 50),
TweenSequenceItem(tween: Tween(begin: 1.3, end: 1.0), weight: 50),
]).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _onPressed() {
_controller.forward(from: 0.0);
context.read<FavoritesCubit>().toggleFavorite(
widget.identifier,
symbol: widget.symbol,
name: widget.name,
);
}
@override
Widget build(BuildContext context) {
return BlocBuilder<FavoritesCubit, FavoritesState>(
builder: (context, state) {
final isFav = state.isFavorite(widget.identifier) ||
(widget.symbol != null && state.isFavorite(widget.symbol!));
return ScaleTransition(
scale: _scaleAnimation,
child: IconButton(
padding: widget.padding ?? const EdgeInsets.all(8),
constraints: const BoxConstraints(),
icon: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
transitionBuilder: (child, anim) => ScaleTransition(scale: anim, child: child),
child: Icon(
isFav ? Icons.star_rounded : Icons.star_border_rounded,
key: ValueKey<bool>(isFav),
color: isFav ? Colors.amber : AppTheme.textMuted,
size: widget.size,
),
),
onPressed: _onPressed,
),
);
},
);
}
}