delete direct messages + bug fixes

This commit is contained in:
MohammadTaha Basiri 2022-04-20 21:28:03 +04:30
parent 0c47465d2a
commit 5072704b86
6 changed files with 171 additions and 88 deletions

View File

@ -12,7 +12,7 @@ class ServerDataProvider {
static int labelToTypeId(String label) { static int labelToTypeId(String label) {
if (label.contains('پشتیبانی اپلیکیشن')) { if (label.contains('پشتیبانی اپلیکیشن')) {
return 8; return 8;
} else if (label.contains('پشتیبانی')) { } else if (label.contains('پشتیبانی محتوا')) {
return 7; return 7;
} else { } else {
return directTypes return directTypes

View File

@ -40,6 +40,8 @@ class RequestHelper {
static String direct(int id) => _baseDirectUrl + '/$id'; static String direct(int id) => _baseDirectUrl + '/$id';
static String sendDirectMessage(int id) => static String sendDirectMessage(int id) =>
_baseDirectUrl + '/$id/sendMessage'; _baseDirectUrl + '/$id/sendMessage';
static String deleteDirect(int id, int messageId) =>
_baseDirectUrl + '/$id/message/$messageId';
static String tag({ static String tag({
required List<int> ids, required List<int> ids,
String? type, String? type,

View File

@ -1,3 +1,4 @@
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart'; import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart'; import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/app_bar_data.dart'; import 'package:didvan/models/view/app_bar_data.dart';
@ -6,7 +7,9 @@ import 'package:didvan/services/media/media.dart';
import 'package:didvan/views/home/direct/direct_state.dart'; import 'package:didvan/views/home/direct/direct_state.dart';
import 'package:didvan/views/home/direct/widgets/message.dart'; import 'package:didvan/views/home/direct/widgets/message.dart';
import 'package:didvan/views/home/direct/widgets/message_box.dart'; import 'package:didvan/views/home/direct/widgets/message_box.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/scaffold.dart'; import 'package:didvan/views/widgets/didvan/scaffold.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/state_handlers/empty_state.dart'; import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart'; import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -52,11 +55,12 @@ class _DirectState extends State<Direct> {
left: 0, left: 0,
right: 0, right: 0,
child: DidvanScaffold( child: DidvanScaffold(
padding: EdgeInsets.zero,
reverse: true, reverse: true,
backgroundColor: Theme.of(context).colorScheme.surface, backgroundColor: Theme.of(context).colorScheme.surface,
appBarData: AppBarData( appBarData: AppBarData(
hasBack: true, hasBack: true,
subtitle: widget.pageData['type'] == null subtitle: widget.pageData['type'].contains('پشتیبانی')
? null ? null
: 'ارتباط با سردبیر', : 'ارتباط با سردبیر',
title: widget.pageData['type'] ?? 'پشتیبانی اپلیکیشن', title: widget.pageData['type'] ?? 'پشتیبانی اپلیکیشن',
@ -105,6 +109,43 @@ class _DirectState extends State<Direct> {
left: 0, left: 0,
child: const MessageBox(), child: const MessageBox(),
), ),
if (state.deletionQueue.isNotEmpty)
Positioned(
left: 0,
right: 0,
top: d.padding.top,
child: Container(
height: 72,
color: Theme.of(context).colorScheme.surface,
child: Row(
children: [
DidvanIconButton(
icon: DidvanIcons.close_solid,
size: 32,
gestureSize: 48,
color: Theme.of(context).colorScheme.secondary,
onPressed: () {
state.deletionQueue.clear();
state.update();
},
),
DidvanText(
'${state.deletionQueue.length} مورد انتخاب شد',
style: Theme.of(context).textTheme.subtitle1,
color: Theme.of(context).colorScheme.secondary,
),
const Spacer(),
DidvanIconButton(
icon: DidvanIcons.trash_solid,
size: 32,
gestureSize: 48,
color: Theme.of(context).colorScheme.primary,
onPressed: state.delete,
),
],
),
),
),
], ],
), ),
), ),

View File

@ -16,6 +16,7 @@ class DirectState extends CoreProvier {
final List<MessageData> messages = []; final List<MessageData> messages = [];
late final int typeId; late final int typeId;
final Map<String, List<int>> dailyMessages = {}; final Map<String, List<int>> dailyMessages = {};
final List<int> deletionQueue = [];
String? text; String? text;
RadarAttachment? replyRadar; RadarAttachment? replyRadar;
@ -77,6 +78,18 @@ class DirectState extends CoreProvier {
} }
} }
void delete() {
for (var i = 0; i < deletionQueue.length; i++) {
final service = RequestService(
RequestHelper.deleteDirect(typeId, deletionQueue[i]),
);
service.delete();
messages.removeWhere((element) => element.id == deletionQueue[i]);
}
deletionQueue.clear();
notifyListeners();
}
void _addToDailyGrouped(MessageData message) { void _addToDailyGrouped(MessageData message) {
String createdAt = message.createdAt.replaceAll('T', ' ').split(' ').first; String createdAt = message.createdAt.replaceAll('T', ' ').split(' ').first;
if (!dailyMessages.containsKey(createdAt)) { if (!dailyMessages.containsKey(createdAt)) {

View File

@ -20,24 +20,24 @@ class AudioWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StreamBuilder<bool>( return Row(
stream: MediaService.audioPlayer.isPlaying, children: [
builder: (context, snapshot) { Expanded(
return Row( child: AudioSlider(
children: [ tag: 'message-$id',
Expanded( ),
child: AudioSlider( ),
tag: 'message-$id', StreamBuilder<bool>(
), stream: MediaService.audioPlayer.isPlaying,
), builder: (context, snapshot) {
_AudioControllerButton( return _AudioControllerButton(
audioFile: audioFile, audioFile: audioFile,
audioUrl: audioUrl, audioUrl: audioUrl,
id: id, id: id,
), );
], },
); ),
}, ],
); );
} }
} }

View File

@ -18,85 +18,109 @@ class Message extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final firstMessageOfGroupId = context final state = context.read<DirectState>();
.read<DirectState>() final firstMessageOfGroupId = state
.dailyMessages[message.createdAt.replaceAll('T', ' ').split(' ').first]! .dailyMessages[message.createdAt.replaceAll('T', ' ').split(' ').first]!
.last; .last;
return Column( return GestureDetector(
crossAxisAlignment: message.writedByAdmin onLongPress: () {
? CrossAxisAlignment.end if (state.deletionQueue.contains(message.id) || message.writedByAdmin) {
: CrossAxisAlignment.start, return;
children: [ }
if (message.id == firstMessageOfGroupId) state.deletionQueue.add(message.id);
Center( state.update();
child: Container( },
margin: const EdgeInsets.only(bottom: 12), onTap: () {
padding: const EdgeInsets.all(4), if (state.deletionQueue.isEmpty || message.writedByAdmin) return;
decoration: BoxDecoration( if (!state.deletionQueue.contains(message.id)) {
color: Theme.of(context).colorScheme.splash, state.deletionQueue.add(message.id);
borderRadius: DesignConfig.lowBorderRadius, } else {
), state.deletionQueue.remove(message.id);
child: DidvanText( }
DateTime.parse(message.createdAt).toPersianDateStr(), state.update();
style: Theme.of(context).textTheme.overline, },
color: DesignConfig.isDark child: Container(
? Theme.of(context).colorScheme.white color: state.deletionQueue.contains(message.id)
: Theme.of(context).colorScheme.black, ? Theme.of(context).colorScheme.secondaryDisabled.withOpacity(0.5)
), : null,
), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
), child: Column(
Padding( crossAxisAlignment: message.writedByAdmin
padding: EdgeInsets.only( ? CrossAxisAlignment.end
right: message.writedByAdmin ? 20 : 0, : CrossAxisAlignment.start,
left: !message.writedByAdmin ? 20 : 0, children: [
), if (message.id == firstMessageOfGroupId)
child: Column( Center(
crossAxisAlignment: message.writedByAdmin child: Container(
? CrossAxisAlignment.start margin: const EdgeInsets.only(bottom: 12),
: CrossAxisAlignment.end, padding: const EdgeInsets.all(4),
children: [ decoration: BoxDecoration(
_MessageContainer( color: Theme.of(context).colorScheme.splash,
writedByAdmin: message.writedByAdmin, borderRadius: DesignConfig.lowBorderRadius,
child: Column( ),
crossAxisAlignment: CrossAxisAlignment.start, child: DidvanText(
children: [ DateTime.parse(message.createdAt).toPersianDateStr(),
if (message.text != null) DidvanText(message.text!), style: Theme.of(context).textTheme.overline,
if (message.audio != null || message.audioFile != null) color: DesignConfig.isDark
AudioWidget( ? Theme.of(context).colorScheme.white
audioFile: message.audioFile, : Theme.of(context).colorScheme.black,
audioUrl: message.audio, ),
id: message.id,
),
if (message.radar != null) const DidvanDivider(),
if (message.radar != null) const SizedBox(height: 4),
if (message.radar != null)
_ReplyRadarOverview(message: message),
if (message.radar != null) const SizedBox(height: 4),
],
), ),
), ),
const SizedBox(height: 4), Padding(
Row( padding: EdgeInsets.only(
mainAxisSize: MainAxisSize.min, right: message.writedByAdmin ? 20 : 0,
left: !message.writedByAdmin ? 20 : 0,
),
child: Column(
crossAxisAlignment: message.writedByAdmin
? CrossAxisAlignment.start
: CrossAxisAlignment.end,
children: [ children: [
DidvanText( _MessageContainer(
DateTimeUtils.timeWithAmPm(message.createdAt), writedByAdmin: message.writedByAdmin,
style: Theme.of(context).textTheme.overline, child: Column(
color: Theme.of(context).colorScheme.caption, 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) const DidvanDivider(),
if (message.radar != null) const SizedBox(height: 4),
if (message.radar != null)
_ReplyRadarOverview(message: message),
if (message.radar != null) const SizedBox(height: 4),
],
),
),
const SizedBox(height: 4),
Row(
mainAxisSize: MainAxisSize.min,
children: [
DidvanText(
DateTimeUtils.timeWithAmPm(message.createdAt),
style: Theme.of(context).textTheme.overline,
color: Theme.of(context).colorScheme.caption,
),
if (!message.writedByAdmin)
Icon(
message.readed
? DidvanIcons.check_double_light
: DidvanIcons.check_light,
size: 16,
)
],
), ),
if (!message.writedByAdmin)
Icon(
message.readed
? DidvanIcons.check_double_light
: DidvanIcons.check_light,
size: 16,
)
], ],
), ),
], ),
), ],
), ),
], ),
); );
} }
} }
@ -177,7 +201,10 @@ class _MessageContainer extends StatelessWidget {
bottomLeft: writedByAdmin ? Radius.zero : null, bottomLeft: writedByAdmin ? Radius.zero : null,
bottomRight: !writedByAdmin ? Radius.zero : null, bottomRight: !writedByAdmin ? Radius.zero : null,
), ),
color: writedByAdmin ? null : Theme.of(context).colorScheme.focused, color: (writedByAdmin
? Theme.of(context).colorScheme.surface
: Theme.of(context).colorScheme.focused)
.withOpacity(0.9),
border: Border.all( border: Border.all(
color: Theme.of(context).colorScheme.border, color: Theme.of(context).colorScheme.border,
width: 0.5, width: 0.5,