861 lines
47 KiB
Dart
861 lines
47 KiB
Dart
// ignore_for_file: use_build_context_synchronously, deprecated_member_use_from_same_package
|
|
|
|
import 'package:cross_file/cross_file.dart';
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:hoshan/core/gen/assets.gen.dart';
|
|
import 'package:hoshan/core/services/file_manager/pick_file_services.dart';
|
|
import 'package:hoshan/core/utils/date_time.dart';
|
|
import 'package:hoshan/core/utils/file.dart';
|
|
import 'package:hoshan/core/utils/strings.dart';
|
|
import 'package:hoshan/data/model/empty_states_enum.dart';
|
|
import 'package:hoshan/data/model/ticket_model.dart';
|
|
import 'package:hoshan/ui/screens/ticket/bloc/send_ticket_bloc.dart';
|
|
import 'package:hoshan/ui/theme/colors.dart';
|
|
import 'package:hoshan/ui/theme/responsive.dart';
|
|
import 'package:hoshan/ui/theme/text.dart';
|
|
import 'package:hoshan/ui/widgets/components/audio/player.dart';
|
|
import 'package:hoshan/ui/widgets/components/audio/recorder.dart';
|
|
import 'package:hoshan/ui/widgets/components/button/circle_icon_btn.dart';
|
|
import 'package:hoshan/ui/widgets/components/dialog/bottom_sheets.dart';
|
|
import 'package:hoshan/ui/widgets/components/dialog/dialog_handler.dart';
|
|
import 'package:hoshan/ui/widgets/components/dropdown/more_popup_menu.dart';
|
|
import 'package:hoshan/ui/widgets/components/image/custome_image.dart';
|
|
import 'package:hoshan/ui/widgets/components/image/network_image.dart';
|
|
import 'package:hoshan/ui/widgets/components/snackbar/snackbar_manager.dart';
|
|
import 'package:hoshan/ui/widgets/sections/empty/empty_states.dart';
|
|
import 'package:hoshan/ui/widgets/sections/header/reversible_appbar.dart';
|
|
import 'package:hoshan/ui/widgets/sections/loading/random_container.dart';
|
|
|
|
class TicketPage extends StatefulWidget {
|
|
const TicketPage({super.key});
|
|
|
|
@override
|
|
State<TicketPage> createState() => _TicketPageState();
|
|
}
|
|
|
|
class _TicketPageState extends State<TicketPage> {
|
|
ValueNotifier<bool> visibleAttach = ValueNotifier(false);
|
|
ValueNotifier<bool> visibleRecorder = ValueNotifier(false);
|
|
ValueNotifier<XFile?> selectedFile = ValueNotifier(null);
|
|
|
|
final TextEditingController message = TextEditingController();
|
|
final GlobalKey containerKey = GlobalKey();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: ReversibleAppbar(
|
|
context,
|
|
titleText: 'ارسال تیکت به پشتیبانی',
|
|
),
|
|
body: Responsive(context).maxWidthInDesktop(
|
|
child: (contxet, maxWidth) =>
|
|
BlocBuilder<SendTicketBloc, SendTicketState>(
|
|
builder: (context, state) {
|
|
if (state is SendTicketInitial) {
|
|
return ListView.builder(
|
|
shrinkWrap: true,
|
|
itemCount: 20,
|
|
reverse: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
padding: const EdgeInsets.only(top: 24, bottom: 90),
|
|
itemBuilder: (context, index) {
|
|
return RandomContainer(isUser: index % 2 == 0);
|
|
},
|
|
);
|
|
}
|
|
return state.tickets.isEmpty
|
|
? EmptyStates.getEmptyState(status: EmptyStatesEnum.inbox)
|
|
: SingleChildScrollView(
|
|
reverse: true,
|
|
physics: const BouncingScrollPhysics(),
|
|
child: ListView.builder(
|
|
shrinkWrap: true,
|
|
itemCount: state.tickets.length,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
padding: const EdgeInsets.only(top: 24, bottom: 90),
|
|
itemBuilder: (context, index) {
|
|
final ticketList = state.tickets[index].tickets;
|
|
return Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
const Expanded(child: Divider()),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 24.0),
|
|
child: Text(
|
|
state.tickets[index].date ?? '',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.onSurface),
|
|
textDirection: TextDirection.rtl,
|
|
),
|
|
),
|
|
const Expanded(child: Divider()),
|
|
],
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
ListView.builder(
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemCount: ticketList.length,
|
|
shrinkWrap: true,
|
|
itemBuilder: (context, tIndex) {
|
|
Ticket ticket = ticketList[tIndex];
|
|
return chatBubble(ticket, maxWidth,
|
|
state.tickets[index].date ?? '');
|
|
},
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
bottomSheet: chatBar(),
|
|
);
|
|
}
|
|
|
|
Container chatBar() {
|
|
return Container(
|
|
key: containerKey,
|
|
color: Theme.of(context).colorScheme.surface,
|
|
child: ValueListenableBuilder(
|
|
valueListenable: selectedFile,
|
|
builder: (context, file, child) {
|
|
return ValueListenableBuilder(
|
|
valueListenable: visibleRecorder,
|
|
builder: (context, inRrecording, child) {
|
|
return inRrecording
|
|
? Container(
|
|
margin: const EdgeInsets.symmetric(
|
|
horizontal: 18.0, vertical: 12),
|
|
padding: const EdgeInsets.all(4),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(20),
|
|
color: Theme.of(context).colorScheme.surface),
|
|
child: Recorder(
|
|
play: true,
|
|
onDelete: () {
|
|
visibleRecorder.value = false;
|
|
selectedFile.value = null;
|
|
visibleAttach.value = false;
|
|
},
|
|
onRecordFinish: (fileRecorded) {
|
|
visibleRecorder.value = false;
|
|
visibleAttach.value = false;
|
|
|
|
selectedFile.value = fileRecorded;
|
|
},
|
|
onError: (p0) {
|
|
visibleRecorder.value = false;
|
|
selectedFile.value = null;
|
|
visibleAttach.value = false;
|
|
},
|
|
),
|
|
)
|
|
: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
ValueListenableBuilder(
|
|
valueListenable: visibleAttach,
|
|
builder: (context, show, child) {
|
|
return show
|
|
? Container(
|
|
margin: const EdgeInsets.fromLTRB(
|
|
32, 24, 16, 24)
|
|
.copyWith(bottom: 0),
|
|
child: Row(
|
|
children: [
|
|
CircleIconBtn(
|
|
icon: Assets
|
|
.icon.outline.galleryAdd,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary,
|
|
iconColor: Colors.white,
|
|
onTap: () async {
|
|
await BottomSheetHandler(
|
|
context)
|
|
.showPickImage(
|
|
onSelect: (file) {
|
|
selectedFile.value = file;
|
|
|
|
visibleAttach.value = false;
|
|
},
|
|
);
|
|
}),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
CircleIconBtn(
|
|
icon: Assets.icon.outline.musicnote,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary,
|
|
iconColor: Colors.white,
|
|
onTap: () async {
|
|
final file =
|
|
await PickFileService(context)
|
|
.getFile(
|
|
fileType:
|
|
FileType.audio);
|
|
if (file != null) {
|
|
selectedFile.value =
|
|
file.single;
|
|
|
|
visibleAttach.value = false;
|
|
}
|
|
},
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
CircleIconBtn(
|
|
icon: Assets.icon.outline.cardAdd,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary,
|
|
iconColor: Colors.white,
|
|
onTap: () async {
|
|
final file =
|
|
await PickFileService(
|
|
context)
|
|
.getFile(
|
|
fileType:
|
|
FileType.custom,
|
|
allowedExtensions: [
|
|
'pdf',
|
|
'doc',
|
|
'docx',
|
|
'xls',
|
|
'xlsx',
|
|
'xlsm',
|
|
'xlsb',
|
|
'xlt',
|
|
'xltx',
|
|
'xltm'
|
|
]);
|
|
if (file != null) {
|
|
selectedFile.value =
|
|
file.single;
|
|
|
|
visibleAttach.value = false;
|
|
}
|
|
})
|
|
],
|
|
),
|
|
)
|
|
: const SizedBox.shrink();
|
|
},
|
|
),
|
|
if (file != null)
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 8, horizontal: 18),
|
|
margin:
|
|
const EdgeInsets.all(16).copyWith(bottom: 0),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.primaryColor.defaultShade,
|
|
borderRadius: BorderRadius.circular(16)
|
|
.copyWith(topRight: Radius.zero)),
|
|
child: file.isAudio()
|
|
? Player(
|
|
fileUrl: file.path,
|
|
inMessages: true,
|
|
)
|
|
: Row(
|
|
children: [
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
Expanded(
|
|
child: Text(
|
|
file.name,
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.onSurface),
|
|
)),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
SizedBox(
|
|
width: 46,
|
|
child: AspectRatio(
|
|
aspectRatio: 3 / 4,
|
|
child: ClipRRect(
|
|
borderRadius:
|
|
BorderRadius.circular(10),
|
|
child: file.isImage()
|
|
? GestureDetector(
|
|
onTap: () =>
|
|
DialogHandler(
|
|
context:
|
|
context)
|
|
.showImageHero(
|
|
image: file
|
|
.path),
|
|
child: SizedBox(
|
|
child: CustomeImage(
|
|
src: file.path,
|
|
fit: BoxFit.cover,
|
|
)),
|
|
)
|
|
: Container(
|
|
color: Colors.white,
|
|
child: const Icon(
|
|
CupertinoIcons.doc)),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Padding(
|
|
padding:
|
|
const EdgeInsets.only(bottom: 8.0),
|
|
child:
|
|
// ValueListenableBuilder(
|
|
// valueListenable: message,
|
|
// builder: (context, val, _) {
|
|
// if (val.text.isEmpty) {
|
|
// return CircleIconBtn(
|
|
// icon: Assets
|
|
// .icon.outline.microphoneChat,
|
|
// color: Colors.white,
|
|
// onTap: () {
|
|
// visibleRecorder.value = true;
|
|
// },
|
|
// );
|
|
// }
|
|
// return
|
|
ValueListenableBuilder(
|
|
valueListenable: message,
|
|
builder:
|
|
(context, controller, _) {
|
|
return controller
|
|
.text.isEmpty &&
|
|
file == null
|
|
? CircleIconBtn(
|
|
icon: Assets
|
|
.icon
|
|
.outline
|
|
.microphoneChat,
|
|
color:
|
|
Theme.of(context)
|
|
.colorScheme
|
|
.primary,
|
|
iconColor:
|
|
Colors.white,
|
|
onTap: () async {
|
|
visibleRecorder
|
|
.value = true;
|
|
})
|
|
: CircleIconBtn(
|
|
icon: Assets
|
|
.icon.bold.send,
|
|
color: Colors.white,
|
|
onTap: () async {
|
|
//SEND MESSAGE
|
|
context
|
|
.read<
|
|
SendTicketBloc>()
|
|
.add(SendTicket(
|
|
text: message
|
|
.text,
|
|
file: selectedFile
|
|
.value));
|
|
message.clear();
|
|
selectedFile.value =
|
|
null;
|
|
},
|
|
);
|
|
})
|
|
// ;
|
|
// }),
|
|
),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Expanded(
|
|
child: ValueListenableBuilder(
|
|
valueListenable: message,
|
|
builder: (context, val, _) {
|
|
return Directionality(
|
|
textDirection:
|
|
val.text.startsWithEnglish()
|
|
? TextDirection.ltr
|
|
: TextDirection.rtl,
|
|
child: TextField(
|
|
controller: message,
|
|
onChanged: (value) {},
|
|
// enabled: ,
|
|
minLines: 1,
|
|
style: AppTextStyles.body4
|
|
.copyWith(
|
|
color:
|
|
Theme.of(context)
|
|
.colorScheme
|
|
.onSurface),
|
|
maxLines: 6, // Set this
|
|
keyboardType:
|
|
TextInputType.multiline,
|
|
|
|
decoration: InputDecoration(
|
|
filled: true,
|
|
hintText:
|
|
'بنویسید یا پیام صوتی بگذارید...',
|
|
hintStyle:
|
|
AppTextStyles.body4,
|
|
fillColor: Theme.of(context)
|
|
.scaffoldBackgroundColor,
|
|
contentPadding:
|
|
const EdgeInsets
|
|
.fromLTRB(
|
|
18, 12, 18, 12),
|
|
border: OutlineInputBorder(
|
|
borderSide:
|
|
BorderSide.none,
|
|
borderRadius:
|
|
BorderRadius.circular(
|
|
24),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
})),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Padding(
|
|
padding:
|
|
const EdgeInsets.only(bottom: 8.0),
|
|
child: CircleIconBtn(
|
|
icon: file != null
|
|
? Assets.icon.outline.trash
|
|
: Assets.icon.outline.elementPlus,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary,
|
|
iconColor: Colors.white,
|
|
onTap: () {
|
|
if (file != null) {
|
|
selectedFile.value = null;
|
|
return;
|
|
}
|
|
visibleAttach.value =
|
|
!visibleAttach.value;
|
|
},
|
|
),
|
|
),
|
|
|
|
/*
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 8.0),
|
|
child: Row(
|
|
children: [
|
|
ValueListenableBuilder(
|
|
valueListenable: visibleAttach,
|
|
builder: (context, isVisible, _) {
|
|
return AnimatedVisibility(
|
|
isVisible: isVisible,
|
|
duration: const Duration(
|
|
milliseconds: 200),
|
|
child: Padding(
|
|
padding:
|
|
const EdgeInsets.symmetric(
|
|
horizontal: 4.0),
|
|
child: Row(children: [
|
|
CircleIconBtn(
|
|
icon: Assets.icon.outline
|
|
.galleryAdd,
|
|
color: Colors.white,
|
|
onTap: () async {
|
|
await BottomSheetHandler(
|
|
context)
|
|
.showPickImage(
|
|
onSelect: (file) {
|
|
selectedFile.value =
|
|
file;
|
|
},
|
|
);
|
|
}),
|
|
Padding(
|
|
padding:
|
|
const EdgeInsets.only(
|
|
right: 4.0),
|
|
child: CircleIconBtn(
|
|
icon: Assets.icon.outline
|
|
.musicnote,
|
|
color: Colors.white,
|
|
onTap: () async {
|
|
final file =
|
|
await PickFileService
|
|
.getFile(
|
|
fileType:
|
|
FileType
|
|
.audio);
|
|
if (file != null) {
|
|
selectedFile.value =
|
|
file.single;
|
|
}
|
|
},
|
|
),
|
|
),
|
|
Padding(
|
|
padding:
|
|
const EdgeInsets.only(
|
|
right: 4.0),
|
|
child: CircleIconBtn(
|
|
icon: Assets.icon
|
|
.outline.cardAdd,
|
|
color: Colors.white,
|
|
onTap: () async {
|
|
final file =
|
|
await PickFileService.getFile(
|
|
fileType:
|
|
FileType
|
|
.custom,
|
|
allowedExtensions: [
|
|
'pdf'
|
|
]);
|
|
if (file != null) {
|
|
selectedFile.value =
|
|
file.single;
|
|
}
|
|
}),
|
|
),
|
|
]),
|
|
));
|
|
}),
|
|
CircleIconBtn(
|
|
icon: Assets.icon.outline.elementPlus,
|
|
color: Colors.white,
|
|
onTap: () => visibleAttach.value =
|
|
!visibleAttach.value,
|
|
),
|
|
],
|
|
),
|
|
)*/
|
|
],
|
|
)),
|
|
)
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
|
|
Widget chatBubble(Ticket ticket, double maxWidthDesktop, String date) {
|
|
final GlobalKey containerKey = GlobalKey();
|
|
|
|
final isUser = ticket.role == 'user';
|
|
XFile? localFile = ticket.localFile;
|
|
String? fileUrl = ticket.file;
|
|
return GestureDetector(
|
|
onLongPress: () {
|
|
MorePopupMenuHandler(context: context).showMorePopupMenu(
|
|
containerKey: containerKey,
|
|
color: isUser
|
|
? AppColors.primaryColor.defaultShade
|
|
: Theme.of(context).colorScheme.surface,
|
|
items: [
|
|
if (isUser)
|
|
PopUpMenuItemModel(
|
|
popupMenuItem: PopupMenuItem(
|
|
value: 0,
|
|
child: MorePopupMenuHandler.morePopUpItem(
|
|
color: isUser
|
|
? Colors.white
|
|
: Theme.of(context).colorScheme.primary,
|
|
icon: Assets.icon.outline.trash,
|
|
title: 'حذف')),
|
|
click: () {
|
|
try {
|
|
context
|
|
.read<SendTicketBloc>()
|
|
.add(DeleteTicket(id: ticket.id!, date: date));
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print("Error when delete message: $e");
|
|
}
|
|
}
|
|
},
|
|
),
|
|
if (ticket.text != null && ticket.text!.isNotEmpty)
|
|
PopUpMenuItemModel(
|
|
popupMenuItem: PopupMenuItem<int>(
|
|
value: 1,
|
|
child: MorePopupMenuHandler.morePopUpItem(
|
|
color: isUser
|
|
? Colors.white
|
|
: Theme.of(context).colorScheme.primary,
|
|
icon: Assets.icon.outline.copy,
|
|
title: 'کپی',
|
|
),
|
|
),
|
|
click: () async {
|
|
await Clipboard.setData(
|
|
ClipboardData(text: ticket.text ?? ''));
|
|
Future.delayed(
|
|
Duration.zero,
|
|
() => SnackBarManager(context, id: 'Copy').show(
|
|
status: SnackBarStatus.info,
|
|
message: 'متن کپی شد 😃',
|
|
isTop: false));
|
|
},
|
|
),
|
|
// PopUpMenuItemModel(
|
|
// popupMenuItem: PopupMenuItem<int>(
|
|
// value: 1,
|
|
// child: MorePopupMenuHandler.morePopUpItem(
|
|
// icon: Assets.icon.outline.trash,
|
|
// title: 'حذف',
|
|
// ),
|
|
// ),
|
|
// click: () async {
|
|
// await DialogHandler(context: context).showDeleteItem(
|
|
// title: 'پیام مورد نظر پاک شود؟',
|
|
// description: '.با این کار اطلاعات شما از بین خواهد رفت',
|
|
// onConfirm: () async {},
|
|
// );
|
|
// },
|
|
// )
|
|
]);
|
|
},
|
|
child: Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
alignment: isUser ? Alignment.centerRight : Alignment.centerLeft,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
key: containerKey,
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: ticket.id == -2
|
|
? AppColors.red[50]
|
|
: isUser
|
|
? AppColors.primaryColor.defaultShade
|
|
: Theme.of(context).colorScheme.surface,
|
|
borderRadius: BorderRadius.circular(16).copyWith(
|
|
bottomLeft: isUser
|
|
? const Radius.circular(16)
|
|
: const Radius.circular(0),
|
|
bottomRight: isUser
|
|
? const Radius.circular(0)
|
|
: const Radius.circular(16)),
|
|
),
|
|
constraints: BoxConstraints(
|
|
maxWidth: MediaQuery.sizeOf(context).width * 0.8),
|
|
child: Directionality(
|
|
textDirection: (ticket.text ?? '').startsWithEnglish()
|
|
? TextDirection.ltr
|
|
: TextDirection.rtl,
|
|
child: Column(
|
|
children: [
|
|
localFile != null
|
|
? Container(
|
|
margin: const EdgeInsets.only(bottom: 8),
|
|
child: localFile.name.isImage()
|
|
? GestureDetector(
|
|
onTap: () => DialogHandler(context: context)
|
|
.showImageHero(image: localFile.path),
|
|
child: Container(
|
|
constraints: BoxConstraints(
|
|
maxWidth:
|
|
Responsive(context).isMobile()
|
|
? MediaQuery.sizeOf(context)
|
|
.width *
|
|
0.5
|
|
: maxWidthDesktop * 0.3,
|
|
maxHeight:
|
|
Responsive(context).isMobile()
|
|
? MediaQuery.sizeOf(context)
|
|
.width *
|
|
0.6
|
|
: maxWidthDesktop * 0.4),
|
|
child: ClipRRect(
|
|
borderRadius:
|
|
BorderRadius.circular(8),
|
|
child: CustomeImage(
|
|
src: localFile.path,
|
|
fit: BoxFit.cover,
|
|
)),
|
|
),
|
|
)
|
|
: localFile.name.isAudio()
|
|
? Player(
|
|
fileUrl: localFile.path,
|
|
inMessages: true,
|
|
)
|
|
: Container(
|
|
decoration: BoxDecoration(
|
|
color: AppColors.gray.defaultShade,
|
|
borderRadius:
|
|
BorderRadius.circular(10)),
|
|
padding: const EdgeInsets.all(8),
|
|
constraints:
|
|
const BoxConstraints(minHeight: 64),
|
|
child: Row(
|
|
children: [
|
|
SizedBox(
|
|
child: localFile.name.isDocument()
|
|
? const Icon(
|
|
CupertinoIcons.doc)
|
|
: const SizedBox.shrink(),
|
|
),
|
|
Expanded(
|
|
child: Padding(
|
|
padding:
|
|
const EdgeInsets.symmetric(
|
|
horizontal: 12.0),
|
|
child: Text(
|
|
localFile.name,
|
|
textDirection: localFile.name
|
|
.startsWithEnglish()
|
|
? TextDirection.ltr
|
|
: TextDirection.rtl,
|
|
style: const TextStyle(
|
|
fontSize: 16),
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 2,
|
|
),
|
|
)),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
: fileUrl != null
|
|
? Container(
|
|
margin: const EdgeInsets.only(bottom: 8),
|
|
child: fileUrl.isImage()
|
|
? GestureDetector(
|
|
onTap: () =>
|
|
DialogHandler(context: context)
|
|
.showImageHero(
|
|
image: fileUrl,
|
|
isUrl: true),
|
|
child: Container(
|
|
constraints: BoxConstraints(
|
|
maxWidth:
|
|
Responsive(context).isMobile()
|
|
? maxWidthDesktop * 0.5
|
|
: maxWidthDesktop * 0.3,
|
|
maxHeight:
|
|
Responsive(context).isMobile()
|
|
? maxWidthDesktop * 0.6
|
|
: maxWidthDesktop * 0.4),
|
|
child: ClipRRect(
|
|
borderRadius:
|
|
BorderRadius.circular(8),
|
|
child: ImageNetwork(
|
|
url: fileUrl,
|
|
fit: BoxFit.cover,
|
|
)),
|
|
),
|
|
)
|
|
: fileUrl.isAudio()
|
|
? Player(
|
|
fileUrl: fileUrl,
|
|
inMessages: true,
|
|
)
|
|
: Container(
|
|
decoration: BoxDecoration(
|
|
color:
|
|
AppColors.gray.defaultShade,
|
|
borderRadius:
|
|
BorderRadius.circular(10)),
|
|
padding: const EdgeInsets.all(8),
|
|
constraints: const BoxConstraints(
|
|
minHeight: 64),
|
|
child: Row(
|
|
children: [
|
|
SizedBox(
|
|
child: fileUrl.isDocument()
|
|
? const Icon(
|
|
CupertinoIcons.doc)
|
|
: const SizedBox.shrink(),
|
|
),
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets
|
|
.symmetric(
|
|
horizontal: 12.0),
|
|
child: Text(
|
|
fileUrl.split('/').last,
|
|
textDirection: fileUrl
|
|
.split('/')
|
|
.last
|
|
.startsWithEnglish()
|
|
? TextDirection.ltr
|
|
: TextDirection.rtl,
|
|
style: const TextStyle(
|
|
fontSize: 16),
|
|
overflow:
|
|
TextOverflow.ellipsis,
|
|
maxLines: 2,
|
|
),
|
|
)),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
: const SizedBox.shrink(),
|
|
Text(
|
|
(ticket.text ?? ''),
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: isUser
|
|
? Colors.white
|
|
: Theme.of(context).colorScheme.onSurface),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (ticket.createdAt != null)
|
|
Padding(
|
|
padding: const EdgeInsets.fromLTRB(8, 4, 0, 0),
|
|
child: ticket.id == -1
|
|
? const SizedBox(
|
|
width: 12,
|
|
height: 12,
|
|
child: CircularProgressIndicator())
|
|
: Text(
|
|
DateTimeUtils.convertToSentTime(ticket.createdAt!),
|
|
style: AppTextStyles.body5
|
|
.copyWith(color: AppColors.gray[700]),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|