didvan-app/lib/views/home/direct/widgets/message.dart

271 lines
9.7 KiB
Dart

import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/message_data/message_data.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/views/home/direct/direct_state.dart';
import 'package:didvan/views/home/direct/widgets/audio_widget.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:provider/provider.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
class Message extends StatelessWidget {
final MessageData message;
const Message({Key? key, required this.message}) : super(key: key);
@override
Widget build(BuildContext context) {
final state = context.read<DirectState>();
final firstMessageOfGroupId = state
.dailyMessages[message.createdAt.replaceAll('T', ' ').split(' ').first]!
.last;
return GestureDetector(
onLongPress: () {
if (state.deletionQueue.contains(message.id) || message.writedByAdmin) {
return;
}
state.deletionQueue.add(message.id);
state.update();
},
onTap: () {
if (state.deletionQueue.isEmpty || message.writedByAdmin) return;
if (!state.deletionQueue.contains(message.id)) {
state.deletionQueue.add(message.id);
} else {
state.deletionQueue.remove(message.id);
}
state.update();
},
child: Container(
color: state.deletionQueue.contains(message.id)
? Theme.of(context).colorScheme.secondaryDisabled.withOpacity(0.5)
: null,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Column(
crossAxisAlignment: message.writedByAdmin
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
if (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.lowBorderRadius,
),
child: DidvanText(
DateTime.parse(message.createdAt).toPersianDateStr(),
style: Theme.of(context).textTheme.labelSmall,
color: DesignConfig.isDark
? Theme.of(context).colorScheme.white
: Theme.of(context).colorScheme.black,
),
),
),
Padding(
padding: EdgeInsets.only(
right: message.writedByAdmin ? 20 : 0,
left: !message.writedByAdmin ? 20 : 0,
),
child: Column(
crossAxisAlignment: message.writedByAdmin
? CrossAxisAlignment.start
: CrossAxisAlignment.end,
children: [
_MessageContainer(
writedByAdmin: message.writedByAdmin,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (message.text != null) DidvanText(message.text!),
if (message.audio != null || message.audioFile != null)
AudioWidget(
audioFile: message.audioFile,
audioUrl: message.audio,
id: message.id,
),
if (message.radar != null || message.news != null)
const DidvanDivider(),
if (message.radar != null || message.news != null)
const SizedBox(height: 4),
if (message.radar != null)
_ReplyRadarOverview(message: message),
if (message.news != null)
_ReplyNewsOverview(message: message),
if (message.radar != null || message.news != null)
const SizedBox(height: 4),
],
),
),
const SizedBox(height: 4),
Row(
mainAxisSize: MainAxisSize.min,
children: [
DidvanText(
DateTimeUtils.timeWithAmPm(message.createdAt),
style: Theme.of(context).textTheme.labelSmall,
color: Theme.of(context).colorScheme.caption,
),
if (!message.writedByAdmin)
Icon(
message.readed
? DidvanIcons.check_double_light
: DidvanIcons.check_light,
size: 16,
)
],
),
],
),
),
],
),
),
);
}
}
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: Theme.of(context).colorScheme.focusedBorder,
),
Row(
children: [
DidvanText(
'رادار ${message.radar!.categories.first.label}',
style: Theme.of(context).textTheme.labelSmall,
color: Theme.of(context).colorScheme.focusedBorder,
),
const Spacer(),
DidvanText(
'${DateTimeUtils.momentGenerator(message.radar!.createdAt)} | خواندن در ${message.radar!.timeToRead} دقیقه',
color: Theme.of(context).colorScheme.focusedBorder,
style: Theme.of(context).textTheme.labelSmall,
),
],
),
],
),
),
),
],
);
}
}
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.mediumBorderRadius.copyWith(
bottomLeft: writedByAdmin ? Radius.zero : null,
bottomRight: !writedByAdmin ? Radius.zero : null,
),
color: (writedByAdmin
? Theme.of(context).colorScheme.surface
: Theme.of(context).colorScheme.focused)
.withOpacity(0.9),
border: Border.all(
color: Theme.of(context).colorScheme.border,
width: 0.5,
),
),
child: child,
);
}
}