import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:onufitness/constants/api_enum_constant.dart'; import 'package:onufitness/constants/asset_constants.dart'; import 'package:onufitness/constants/color_constant.dart'; import 'package:onufitness/utils/helper_function.dart'; class ReactionButton { final String emoji; final String label; final Color backgroundColor; final int reactionTypeID; ReactionButton({ required this.emoji, required this.label, required this.backgroundColor, required this.reactionTypeID, }); } class ReactionPopup extends StatelessWidget { final Function(String, int) onReactionSelected; final GlobalKey parentKey; List reactions = [ ReactionButton( emoji: AssetConstants.highFiveIcon, label: 'High Five', backgroundColor: Color(primaryColor), reactionTypeID: ApiEnum.highFive, ), ReactionButton( emoji: AssetConstants.heartReactionicon, label: 'Love', backgroundColor: Colors.red, reactionTypeID: ApiEnum.heart, ), ReactionButton( emoji: AssetConstants.beastModeIcon, label: 'Beas tMode', backgroundColor: Colors.green, reactionTypeID: ApiEnum.beastMode, ), ]; ReactionPopup({ super.key, required this.onReactionSelected, required this.parentKey, }); @override Widget build(BuildContext context) { return Material( color: Colors.transparent, child: Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 8.h), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Row( mainAxisSize: MainAxisSize.min, children: reactions.map((reaction) { return GestureDetector( onTap: () => onReactionSelected( reaction.label, reaction.reactionTypeID, ), child: Container( margin: EdgeInsets.symmetric(horizontal: 4.w), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: EdgeInsets.all(8.r), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.grey[100], ), child: Image.asset( reaction.emoji, height: isTablet ? 25.h : 20.h, width: isTablet ? 25.w : 20.w, ), ), SizedBox(height: 4.h), ], ), ), ); }).toList(), ), ), ); } } class ReactionPopupOverlay extends StatefulWidget { final Widget child; final Function(String, int) onReactionSelected; final GlobalKey buttonKey; const ReactionPopupOverlay({ super.key, required this.child, required this.onReactionSelected, required this.buttonKey, }); @override State createState() => _ReactionPopupOverlayState(); } class _ReactionPopupOverlayState extends State { OverlayEntry? _overlayEntry; @override void dispose() { _removeOverlay(); super.dispose(); } void _showOverlay(BuildContext context) { _removeOverlay(); final RenderBox? renderBox = widget.buttonKey.currentContext?.findRenderObject() as RenderBox?; if (renderBox == null) { return; } final position = renderBox.localToGlobal(Offset.zero); _overlayEntry = OverlayEntry( builder: (context) => Stack( children: [ Positioned.fill( child: GestureDetector( onTap: _removeOverlay, behavior: HitTestBehavior.opaque, child: Container(color: Colors.transparent), ), ), Positioned( left: position.dx, child: ReactionPopup( onReactionSelected: (reaction, reactionTypeID) { widget.onReactionSelected(reaction, reactionTypeID); _removeOverlay(); }, parentKey: widget.buttonKey, ), ), ], ), ); Overlay.of(context).insert(_overlayEntry!); } void _removeOverlay() { _overlayEntry?.remove(); _overlayEntry = null; } @override Widget build(BuildContext context) { return GestureDetector( onLongPress: () => _showOverlay(context), child: widget.child, ); } } void showReactions({ required BuildContext context, required GlobalKey buttonKey, required Function(String, int) onReactionSelected, }) { late OverlayEntry overlayEntry; final RenderBox? renderBox = buttonKey.currentContext?.findRenderObject() as RenderBox?; if (renderBox == null) { return; } final position = renderBox.localToGlobal(Offset.zero); final OverlayState overlayState = Overlay.of(context); overlayEntry = OverlayEntry( builder: (context) => Stack( children: [ Positioned.fill( child: GestureDetector( onTap: () { overlayEntry.remove(); }, behavior: HitTestBehavior.opaque, child: Container(color: Colors.transparent), ), ), Positioned( left: position.dx, top: position.dy - 100.h, child: ReactionPopup( onReactionSelected: (reaction, reactionTypeID) { onReactionSelected(reaction, reactionTypeID); overlayEntry.remove(); }, parentKey: buttonKey, ), ), ], ), ); overlayState.insert(overlayEntry); }