import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/models/message_data/message_data.dart'; import 'package:didvan/utils/date_time.dart'; import 'package:didvan/views/ai/widgets/audio_wave.dart'; import 'package:didvan/views/direct/direct_state.dart'; import 'package:didvan/views/widgets/didvan/divider.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/skeleton_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; class Message extends StatefulWidget { final MessageData message; const Message({Key? key, required this.message}) : super(key: key); @override State createState() => _MessageState(); } class _MessageState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _slideAnimation; late Animation _opacityAnimation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 300), ); _slideAnimation = Tween( begin: const Offset(0, 0.5), end: Offset.zero, ).animate(CurvedAnimation( parent: _controller, curve: Curves.easeOut, )); _opacityAnimation = Tween( begin: 0.0, end: 1.0, ).animate(CurvedAnimation( parent: _controller, curve: Curves.easeIn, )); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final state = context.read(); final firstMessageOfGroupId = state .dailyMessages[ widget.message.createdAt.replaceAll('T', ' ').split(' ').first]! .last; return FadeTransition( opacity: _opacityAnimation, child: SlideTransition( position: _slideAnimation, child: GestureDetector( onLongPress: () { if (state.deletionQueue.contains(widget.message.id) || widget.message.writedByAdmin) { return; } state.deletionQueue.add(widget.message.id); state.update(); }, onTap: () { if (state.deletionQueue.isEmpty || widget.message.writedByAdmin) return; if (!state.deletionQueue.contains(widget.message.id)) { state.deletionQueue.add(widget.message.id); } else { state.deletionQueue.remove(widget.message.id); } state.update(); }, child: Container( color: state.deletionQueue.contains(widget.message.id) ? Theme.of(context) .colorScheme .secondaryDisabled .withValues(alpha: 0.5) : null, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Column( crossAxisAlignment: widget.message.writedByAdmin ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [ if (widget.message.id == firstMessageOfGroupId) Center( child: Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: Theme.of(context).colorScheme.splash, borderRadius: DesignConfig.mediumBorderRadius, ), child: Padding( padding: const EdgeInsets.all(3.0), child: DidvanText( DateTime.parse(widget.message.createdAt) .toPersianDateStr(), style: Theme.of(context).textTheme.labelMedium, color: DesignConfig.isDark ? Theme.of(context).colorScheme.white : Theme.of(context).colorScheme.black, ), ), ), ), Padding( padding: const EdgeInsets.all(0), child: Column( crossAxisAlignment: widget.message.writedByAdmin ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [ _MessageContainer( writedByAdmin: widget.message.writedByAdmin, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (widget.message.text != null) DidvanText( widget.message.text!, fontWeight: FontWeight.normal, ), if (widget.message.audio != null) AudioWave( file: widget.message.audio!, totalDuration: widget.message.duration != null ? Duration( seconds: widget.message.duration!) : null, ), if (widget.message.radar != null || widget.message.news != null) const DidvanDivider(), if (widget.message.radar != null || widget.message.news != null) const SizedBox(height: 4), if (widget.message.radar != null) _ReplyRadarOverview(message: widget.message), if (widget.message.news != null) _ReplyNewsOverview(message: widget.message), if (widget.message.radar != null || widget.message.news != null) const SizedBox(height: 4), ], ), ), const SizedBox(height: 4), Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: widget.message.writedByAdmin ? MainAxisAlignment.end : MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ if (widget.message.writedByAdmin) Padding( padding: const EdgeInsets.only(left: 8), child: Container( width: 20, height: 20, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: const Color.fromARGB( 255, 184, 184, 184))), child: Center( child: SvgPicture.asset( 'lib/assets/icons/Didvan.svg', width: 12, height: 12, color: DesignConfig.isDark ? Colors.white : null, ), ), )) else Padding( padding: const EdgeInsets.only(left: 8), child: widget.message.writerPhoto != null && widget.message.writerPhoto!.isNotEmpty ? Container( width: 20, height: 20, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: const Color.fromARGB( 255, 184, 184, 184), width: 1, ), ), child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Image.network( widget.message.writerPhoto!, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( width: 20, height: 20, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: const Color.fromARGB( 255, 184, 184, 184), width: 1, ), ), child: Icon( Icons.person_rounded, size: 12, color: DesignConfig.isDark ? Colors.white : Colors.black, ), ); }, ), ), ) : Container( width: 20, height: 20, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: const Color.fromARGB( 255, 184, 184, 184), width: 1, ), ), child: Icon( Icons.person_rounded, size: 12, color: DesignConfig.isDark ? Colors.white : Colors.black, ), ), ), DidvanText( DateTimeUtils.timeWithAmPm(widget.message.createdAt) .toPersianDigit(), style: Theme.of(context).textTheme.labelSmall, color: Theme.of(context).colorScheme.caption, ), const SizedBox(width: 4), if (!widget.message.writedByAdmin) SvgPicture.asset( widget.message.readed ? 'lib/assets/icons/Seen.svg' : 'lib/assets/icons/unseen-tick.svg', height: 10, ) ], ), ], ), ), ], ), ), ), ), ); } } class _ReplyRadarOverview extends StatelessWidget { final MessageData message; const _ReplyRadarOverview({Key? key, required this.message}) : super(key: key); @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SkeletonImage( imageUrl: message.radar!.image, height: 52, width: 52, ), const SizedBox(width: 8), Expanded( child: SizedBox( height: 52, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ DidvanText( message.radar!.title, style: Theme.of(context).textTheme.bodyLarge, maxLines: 1, overflow: TextOverflow.ellipsis, color: const Color.fromARGB(255, 0, 126, 167), ), Row( children: [ Expanded( child: DidvanText( 'رادار ${message.radar!.categories.first.label}', style: Theme.of(context) .textTheme .labelSmall ?.copyWith(fontWeight: FontWeight.bold), color: const Color.fromARGB(255, 0, 126, 167), ), ), DidvanText( '${DateTimeUtils.momentGenerator(message.radar!.createdAt)} / خواندن در ${message.radar!.timeToRead} دقیقه', color: const Color.fromARGB(255, 0, 126, 167), style: Theme.of(context) .textTheme .labelSmall ?.copyWith(fontWeight: FontWeight.bold), ), ], ), ], ), ), ), ], ); } } class _ReplyNewsOverview extends StatelessWidget { final MessageData message; const _ReplyNewsOverview({Key? key, required this.message}) : super(key: key); @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SkeletonImage( imageUrl: message.news!.image, height: 52, width: 52, ), const SizedBox(width: 8), Expanded( child: SizedBox( height: 52, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ DidvanText( message.news!.title, style: Theme.of(context).textTheme.bodyLarge, maxLines: 1, overflow: TextOverflow.ellipsis, color: Theme.of(context).colorScheme.focusedBorder, ), Row( children: [ DidvanText( 'خبر', style: Theme.of(context).textTheme.labelSmall, color: Theme.of(context).colorScheme.focusedBorder, ), const Spacer(), DidvanText( DateTimeUtils.momentGenerator(message.news!.createdAt), color: Theme.of(context).colorScheme.focusedBorder, style: Theme.of(context).textTheme.labelSmall, ), ], ), ], ), ), ), ], ); } } class _MessageContainer extends StatelessWidget { final bool writedByAdmin; final Widget child; const _MessageContainer({ Key? key, required this.writedByAdmin, required this.child, }) : super(key: key); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), decoration: BoxDecoration( borderRadius: DesignConfig.highBorderRadius.copyWith( bottomLeft: writedByAdmin ? Radius.zero : null, bottomRight: !writedByAdmin ? Radius.zero : null, ), border: Border.all( color: writedByAdmin ? const Color.fromARGB(255, 184, 184, 184) : Colors.transparent, width: 0.5, ), color: (writedByAdmin ? Theme.of(context).colorScheme.surface : Theme.of(context).colorScheme.focused) .withValues(alpha: 0.9), ), child: child, ); } }