84f16c25f6
Design system mandates Lucide, not Material. Foundation before the mechanical Icons.* sweep: - pubspec: add flutter_lucide ^1.11.0 - shared/widgets/lucide_heart.dart: LucideHeart renders the verified lucide-icons/lucide heart path as outline (stroke) or filled, via flutter_svg, tinted by color — Lucide ships no filled heart, so the liked state fills the same Lucide silhouette (user-chosen approach) - like_button: use LucideHeart instead of Icons.favorite/_border - notification drawables re-derived from the verbatim Lucide heart path (border = stroke, filled = fill); separators spaced for Android pathData Unit 2 (mechanical Icons.* -> LucideIcons.* sweep) follows once this is CI-green. pubspec.lock regenerated by CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
38 lines
981 B
Dart
38 lines
981 B
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../api/endpoints/likes.dart';
|
|
import '../shared/widgets/lucide_heart.dart';
|
|
import '../theme/theme_extension.dart';
|
|
import 'likes_provider.dart';
|
|
|
|
class LikeButton extends ConsumerWidget {
|
|
const LikeButton({
|
|
required this.kind,
|
|
required this.id,
|
|
this.size = 22,
|
|
super.key,
|
|
});
|
|
final LikeKind kind;
|
|
final String id;
|
|
final double size;
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final fs = Theme.of(context).extension<FabledSwordTheme>()!;
|
|
final state = ref.watch(likedIdsProvider);
|
|
final liked = state.maybeWhen(
|
|
data: (s) => s.has(kind, id),
|
|
orElse: () => false,
|
|
);
|
|
return IconButton(
|
|
icon: LucideHeart(
|
|
filled: liked,
|
|
color: liked ? fs.accent : fs.ash,
|
|
size: size,
|
|
),
|
|
onPressed: () => ref.read(likesControllerProvider).toggle(kind, id),
|
|
);
|
|
}
|
|
}
|