2026-01-13 11:36:24 +05:30

236 lines
6.3 KiB
Dart

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<ReactionButton> 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<ReactionPopupOverlay> createState() => _ReactionPopupOverlayState();
}
class _ReactionPopupOverlayState extends State<ReactionPopupOverlay> {
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);
}