03-02-1403 / Rhmn / edit mention section.
This commit is contained in:
parent
4c369c8588
commit
f4689f3391
|
|
@ -6,12 +6,9 @@ class CommentData {
|
||||||
int id;
|
int id;
|
||||||
final String text;
|
final String text;
|
||||||
final String createdAt;
|
final String createdAt;
|
||||||
String? type;
|
|
||||||
bool liked;
|
bool liked;
|
||||||
bool disliked;
|
bool disliked;
|
||||||
bool private;
|
|
||||||
int status;
|
int status;
|
||||||
dynamic mention;
|
|
||||||
final FeedbackData feedback;
|
final FeedbackData feedback;
|
||||||
final UserOverview user;
|
final UserOverview user;
|
||||||
final List<Reply> replies;
|
final List<Reply> replies;
|
||||||
|
|
@ -22,21 +19,17 @@ class CommentData {
|
||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
required this.liked,
|
required this.liked,
|
||||||
required this.disliked,
|
required this.disliked,
|
||||||
required this.private,
|
|
||||||
required this.feedback,
|
required this.feedback,
|
||||||
required this.user,
|
required this.user,
|
||||||
required this.replies,
|
required this.replies,
|
||||||
required this.status,
|
required this.status,
|
||||||
this.type,
|
|
||||||
required this.mention,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
factory CommentData.fromJson(Map<String, dynamic> json, bool private) => CommentData(
|
factory CommentData.fromJson(Map<String, dynamic> json) => CommentData(
|
||||||
id: json['id'],
|
id: json['id'],
|
||||||
text: json['text'],
|
text: json['text'],
|
||||||
createdAt: json['createdAt'],
|
createdAt: json['createdAt'],
|
||||||
liked: json['liked'],
|
liked: json['liked'],
|
||||||
private: private,
|
|
||||||
disliked: json['disliked'],
|
disliked: json['disliked'],
|
||||||
feedback: FeedbackData.fromJson(json['feedback']),
|
feedback: FeedbackData.fromJson(json['feedback']),
|
||||||
user: UserOverview.fromJson(json['user']),
|
user: UserOverview.fromJson(json['user']),
|
||||||
|
|
@ -46,19 +39,14 @@ class CommentData {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
status: json['status'],
|
status: json['status'],
|
||||||
mention: json['mention'],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
'id': id,
|
'id': id,
|
||||||
'text': text,
|
'text': text,
|
||||||
'createdAt': createdAt,
|
'createdAt': createdAt,
|
||||||
'liked': liked,
|
'liked': liked,
|
||||||
'disliked': disliked,
|
'disliked': disliked,
|
||||||
'private': private,
|
|
||||||
'mention': mention,
|
|
||||||
'type': type,
|
|
||||||
'feedback': feedback.toJson(),
|
'feedback': feedback.toJson(),
|
||||||
'user': user.toJson(),
|
'user': user.toJson(),
|
||||||
'replies': replies.map((e) => e.toJson()).toList(),
|
'replies': replies.map((e) => e.toJson()).toList(),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
class MentionData {
|
class MentionData {
|
||||||
final int id;
|
int id;
|
||||||
final String fullName;
|
String fullName;
|
||||||
final String text;
|
String text;
|
||||||
final String createdAt;
|
String createdAt;
|
||||||
final List<String> mentions;
|
List<String> mentions;
|
||||||
|
|
||||||
MentionData(
|
MentionData(
|
||||||
{required this.id,
|
{required this.id,
|
||||||
|
|
@ -12,8 +12,7 @@ class MentionData {
|
||||||
required this.fullName,
|
required this.fullName,
|
||||||
required this.mentions});
|
required this.mentions});
|
||||||
|
|
||||||
factory MentionData.fromJson(Map<String, dynamic> json, bool private) =>
|
factory MentionData.fromJson(Map<String, dynamic> json) => MentionData(
|
||||||
MentionData(
|
|
||||||
id: json['id'],
|
id: json['id'],
|
||||||
text: json['text'],
|
text: json['text'],
|
||||||
createdAt: json['createdAt'],
|
createdAt: json['createdAt'],
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
class UsersMention {
|
class UsersMention {
|
||||||
int? id;
|
int id;
|
||||||
String? name;
|
String name;
|
||||||
String? type;
|
String? type;
|
||||||
String? photo;
|
String? photo;
|
||||||
|
|
||||||
UsersMention({this.id, this.name, this.type, this.photo});
|
UsersMention({required this.id, required this.name, this.type, this.photo});
|
||||||
|
|
||||||
UsersMention.fromJson(Map<String, dynamic> json) {
|
factory UsersMention.fromJson(Map<String, dynamic> json) => UsersMention(
|
||||||
id = json['id'];
|
id: json['id'],
|
||||||
name = json['name'];
|
name: json['name'],
|
||||||
type = json['type'];
|
type: json['type'],
|
||||||
photo = json['photo'];
|
photo: json['photo']);
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final Map<String, dynamic> data = <String, dynamic>{};
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
import 'package:didvan/constants/assets.dart';
|
import 'package:didvan/constants/assets.dart';
|
||||||
import 'package:didvan/models/users_mention.dart';
|
|
||||||
import 'package:didvan/models/view/app_bar_data.dart';
|
import 'package:didvan/models/view/app_bar_data.dart';
|
||||||
import 'package:didvan/views/comments/comments_state.dart';
|
import 'package:didvan/views/comments/comments_state.dart';
|
||||||
import 'package:didvan/views/comments/widgets/comment.dart';
|
import 'package:didvan/views/comments/widgets/comment.dart';
|
||||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/checkbox.dart';
|
|
||||||
import 'package:didvan/views/widgets/didvan/icon_button.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/didvan/text.dart';
|
||||||
|
|
@ -19,12 +15,8 @@ import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../widgets/didvan/didvan_title_divider.dart';
|
|
||||||
import '../widgets/user_mention.dart';
|
|
||||||
|
|
||||||
class Comments extends StatefulWidget {
|
class Comments extends StatefulWidget {
|
||||||
final Map<String, dynamic> pageData;
|
final Map<String, dynamic> pageData;
|
||||||
|
|
||||||
const Comments({
|
const Comments({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.pageData,
|
required this.pageData,
|
||||||
|
|
@ -55,8 +47,6 @@ class _CommentsState extends State<Comments> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final commentsState = context.watch<CommentsState>();
|
|
||||||
|
|
||||||
final bottomViewInset = MediaQuery.of(context).viewInsets.bottom;
|
final bottomViewInset = MediaQuery.of(context).viewInsets.bottom;
|
||||||
if (bottomViewInset == 0) {
|
if (bottomViewInset == 0) {
|
||||||
if (_bottomPadding != 0) {
|
if (_bottomPadding != 0) {
|
||||||
|
|
@ -80,7 +70,6 @@ class _CommentsState extends State<Comments> {
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 92),
|
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 92),
|
||||||
showSliversFirst: false,
|
|
||||||
slivers: [
|
slivers: [
|
||||||
Consumer<CommentsState>(
|
Consumer<CommentsState>(
|
||||||
builder: (context, state, child) =>
|
builder: (context, state, child) =>
|
||||||
|
|
@ -91,8 +80,7 @@ class _CommentsState extends State<Comments> {
|
||||||
childCount: state.comments.length,
|
childCount: state.comments.length,
|
||||||
placeholder: const _CommentPlaceholder(),
|
placeholder: const _CommentPlaceholder(),
|
||||||
centerEmptyState: _isPage,
|
centerEmptyState: _isPage,
|
||||||
enableEmptyState:
|
enableEmptyState: state.comments.isEmpty,
|
||||||
state.comments.isEmpty && state.privateComments.isEmpty,
|
|
||||||
emptyState: EmptyState(
|
emptyState: EmptyState(
|
||||||
asset: Assets.emptyChat,
|
asset: Assets.emptyChat,
|
||||||
title: 'اولین نظر را بنویسید...',
|
title: 'اولین نظر را بنویسید...',
|
||||||
|
|
@ -108,84 +96,6 @@ class _CommentsState extends State<Comments> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
children: commentsState.privateComments.isNotEmpty
|
|
||||||
? [
|
|
||||||
const SizedBox(
|
|
||||||
height: 6,
|
|
||||||
),
|
|
||||||
DidvanTitleDivider(
|
|
||||||
title: "نظرات پنهان شده",
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
icon: Icon(
|
|
||||||
commentsState.showPrivates
|
|
||||||
? DidvanIcons.angle_up_regular
|
|
||||||
: DidvanIcons.angle_down_regular,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
onClick: () {
|
|
||||||
commentsState.showPrivates =
|
|
||||||
!commentsState.showPrivates;
|
|
||||||
commentsState.update();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
AnimatedVisibility(
|
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
|
||||||
isVisible: commentsState.showPrivates,
|
|
||||||
child: _buildPrivateComments(commentsState),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
const DidvanTitleDivider(
|
|
||||||
title: "سایر نظرات",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
AnimatedVisibility(
|
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
|
||||||
isVisible: commentsState.showUsersForMentionsLayout,
|
|
||||||
child: BackdropFilter(
|
|
||||||
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color:
|
|
||||||
Theme.of(context).colorScheme.focused.withOpacity(0.5)),
|
|
||||||
child: DidvanScaffold(
|
|
||||||
appBarData: null,
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 16, right: 16, top: 16, bottom: 92),
|
|
||||||
backgroundColor: Colors.white.withOpacity(0.0),
|
|
||||||
slivers: [
|
|
||||||
Consumer<CommentsState>(
|
|
||||||
builder: (context, state, child) =>
|
|
||||||
SliverStateHandler<CommentsState>(
|
|
||||||
onRetry: state.getUsersMention,
|
|
||||||
state: state,
|
|
||||||
itemPadding: const EdgeInsets.symmetric(vertical: 8),
|
|
||||||
childCount: state.usersMention.length,
|
|
||||||
placeholder: const _UsersPlaceholder(),
|
|
||||||
centerEmptyState: _isPage,
|
|
||||||
enableEmptyState: state.usersMention.isEmpty,
|
|
||||||
emptyState: EmptyState(
|
|
||||||
asset: Assets.emptyBookmark,
|
|
||||||
title: 'لیست خالی است',
|
|
||||||
),
|
|
||||||
builder: (context, state, index) {
|
|
||||||
return UserMention(
|
|
||||||
user: state.usersMention[index],
|
|
||||||
index: index,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 0,
|
left: 0,
|
||||||
|
|
@ -197,28 +107,10 @@ class _CommentsState extends State<Comments> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView _buildPrivateComments(CommentsState commentsState) {
|
|
||||||
return ListView.builder(
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
itemCount: commentsState.privateComments.length,
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return Comment(
|
|
||||||
key: ValueKey(
|
|
||||||
commentsState.privateComments[index].id.toString() +
|
|
||||||
commentsState.privateComments[index].text,
|
|
||||||
),
|
|
||||||
focusNode: _focusNode,
|
|
||||||
comment: commentsState.privateComments[index],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MessageBox extends StatefulWidget {
|
class _MessageBox extends StatefulWidget {
|
||||||
final FocusNode focusNode;
|
final FocusNode focusNode;
|
||||||
|
|
||||||
const _MessageBox({Key? key, required this.focusNode}) : super(key: key);
|
const _MessageBox({Key? key, required this.focusNode}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -226,179 +118,59 @@ class _MessageBox extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MessageBoxState extends State<_MessageBox> {
|
class _MessageBoxState extends State<_MessageBox> {
|
||||||
|
final _controller = TextEditingController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final state = context.watch<CommentsState>();
|
final state = context.watch<CommentsState>();
|
||||||
|
|
||||||
void onCheckBoxChange(bool b) {
|
|
||||||
state.hideMentionedUser = b;
|
|
||||||
state.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
duration: DesignConfig.lowAnimationDuration,
|
||||||
isVisible: state.showReplyBox,
|
isVisible: state.showReplyBox,
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
padding: const EdgeInsets.all(8),
|
||||||
Container(
|
decoration: BoxDecoration(
|
||||||
padding: const EdgeInsets.all(8),
|
color: Theme.of(context).colorScheme.surface,
|
||||||
decoration: BoxDecoration(
|
border: Border(
|
||||||
color: Theme.of(context).colorScheme.secondCTA,
|
top: BorderSide(
|
||||||
borderRadius: const BorderRadius.only(
|
|
||||||
topRight: Radius.circular(16),
|
|
||||||
topLeft: Radius.circular(16)),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.title
|
|
||||||
.withOpacity(0.2),
|
|
||||||
offset: const Offset(
|
|
||||||
5.0,
|
|
||||||
5.0,
|
|
||||||
),
|
|
||||||
blurRadius: 10.0,
|
|
||||||
spreadRadius: 2.0,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
// border: Border(
|
|
||||||
// top: BorderSide(
|
|
||||||
// color: Theme.of(context).colorScheme.border,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
if (state.replyingTo != null)
|
|
||||||
DidvanText(
|
|
||||||
'پاسخ به ${state.replyingTo!.fullName}:',
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
DidvanIconButton(
|
|
||||||
gestureSize: 24,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
icon: DidvanIcons.close_regular,
|
|
||||||
onPressed: () {
|
|
||||||
state.commentId = null;
|
|
||||||
state.replyingTo = null;
|
|
||||||
state.showReplyBox = false;
|
|
||||||
state.update();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
color: Theme.of(context).colorScheme.secondCTA,
|
|
||||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
|
|
||||||
child: Divider(
|
|
||||||
height: 2,
|
|
||||||
color: Theme.of(context).colorScheme.border,
|
color: Theme.of(context).colorScheme.border,
|
||||||
),
|
),
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
AnimatedVisibility(
|
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
|
||||||
isVisible: state.usersMentioned.name != null,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.secondCTA,
|
|
||||||
borderRadius: !state.showReplyBox
|
|
||||||
? const BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(16),
|
|
||||||
topRight: Radius.circular(16))
|
|
||||||
: null),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
width: 2,
|
|
||||||
height: 40,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 8,
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
DidvanText(
|
|
||||||
"اشاره به",
|
|
||||||
color: Theme.of(context).colorScheme.text,
|
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
|
||||||
),
|
|
||||||
DidvanText(
|
|
||||||
state.usersMentioned.name.toString(),
|
|
||||||
color: Theme.of(context).colorScheme.text,
|
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
DidvanIconButton(
|
|
||||||
gestureSize: 24,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
icon: DidvanIcons.close_regular,
|
|
||||||
onPressed: () {
|
|
||||||
state.usersMentioned = UsersMention();
|
|
||||||
state.update();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
!state.showReplyBox
|
|
||||||
? DidvanCheckbox(
|
|
||||||
title: "پنهان کردن فراخوانی",
|
|
||||||
value: state.hideMentionedUser,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
onChanged: onCheckBoxChange,
|
|
||||||
size: 12,
|
|
||||||
)
|
|
||||||
: const SizedBox(),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (state.replyingTo != null)
|
||||||
|
DidvanText(
|
||||||
|
'پاسخ به ${state.replyingTo!.fullName}:',
|
||||||
|
color: Theme.of(context).colorScheme.caption,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
DidvanIconButton(
|
||||||
|
gestureSize: 24,
|
||||||
|
color: Theme.of(context).colorScheme.caption,
|
||||||
|
icon: DidvanIcons.close_regular,
|
||||||
|
onPressed: () {
|
||||||
|
state.commentId = null;
|
||||||
|
state.replyingTo = null;
|
||||||
|
state.showReplyBox = false;
|
||||||
|
state.update();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
boxShadow: state.showReplyBox && state.usersMentioned.name == null
|
color: Theme.of(context).colorScheme.surface,
|
||||||
? null
|
border: Border(
|
||||||
: [
|
top: BorderSide(
|
||||||
BoxShadow(
|
color: Theme.of(context).colorScheme.border,
|
||||||
color:
|
),
|
||||||
Theme.of(context).colorScheme.title.withOpacity(0.2),
|
),
|
||||||
offset: const Offset(
|
|
||||||
5.0,
|
|
||||||
5.0,
|
|
||||||
),
|
|
||||||
blurRadius: 10.0,
|
|
||||||
spreadRadius: 2.0,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
color: state.showReplyBox && state.usersMentioned.name == null
|
|
||||||
? Theme.of(context).colorScheme.secondCTA
|
|
||||||
: Theme.of(context).colorScheme.surface,
|
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -411,7 +183,7 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: widget.focusNode,
|
focusNode: widget.focusNode,
|
||||||
controller: state.commentTextFieldController,
|
controller: _controller,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
textInputAction: TextInputAction.send,
|
textInputAction: TextInputAction.send,
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
|
@ -423,7 +195,7 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
color: Theme.of(context).colorScheme.disabledText),
|
color: Theme.of(context).colorScheme.disabledText),
|
||||||
),
|
),
|
||||||
onChanged: (value) => _onChange(state, value),
|
onChanged: (value) => state.text = value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -434,33 +206,9 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSend(CommentsState state) {
|
void _onSend(CommentsState state) {
|
||||||
if (state.commentTextFieldController.text.replaceAll(' ', '').isNotEmpty) {
|
if (state.text.replaceAll(' ', '').isNotEmpty) {
|
||||||
state.addComment();
|
state.addComment();
|
||||||
state.commentTextFieldController.text = '';
|
_controller.text = '';
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onChange(CommentsState state, value) {
|
|
||||||
state.commentTextFieldController.text = value;
|
|
||||||
if (state.usersMentioned.name == null) {
|
|
||||||
if (state.commentTextFieldController.text.contains("@")) {
|
|
||||||
int index = state.commentTextFieldController.text.indexOf("@");
|
|
||||||
if (state.commentTextFieldController.text.length > index + 1) {
|
|
||||||
if (state.commentTextFieldController.text
|
|
||||||
.substring(index)
|
|
||||||
.contains(" ")) {
|
|
||||||
state.showUsersForMentionsLayout = false;
|
|
||||||
} else {
|
|
||||||
state.mentionedText =
|
|
||||||
state.commentTextFieldController.text.substring(index);
|
|
||||||
state.getUsersMention();
|
|
||||||
state.showUsersForMentionsLayout = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.showUsersForMentionsLayout = false;
|
|
||||||
}
|
|
||||||
state.update();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -528,28 +276,3 @@ class _CommentPlaceholder extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UsersPlaceholder extends StatelessWidget {
|
|
||||||
const _UsersPlaceholder({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
ShimmerPlaceholder(
|
|
||||||
height: 40,
|
|
||||||
width: 40,
|
|
||||||
borderRadius: DesignConfig.highBorderRadius,
|
|
||||||
),
|
|
||||||
SizedBox(width: 16),
|
|
||||||
Expanded(
|
|
||||||
child: ShimmerPlaceholder(
|
|
||||||
borderRadius: DesignConfig.highBorderRadius,
|
|
||||||
height: 40,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -4,33 +4,24 @@ import 'package:didvan/models/comment/feedback.dart';
|
||||||
import 'package:didvan/models/comment/reply.dart';
|
import 'package:didvan/models/comment/reply.dart';
|
||||||
import 'package:didvan/models/comment/user.dart';
|
import 'package:didvan/models/comment/user.dart';
|
||||||
import 'package:didvan/models/enums.dart';
|
import 'package:didvan/models/enums.dart';
|
||||||
import 'package:didvan/models/users_mention.dart';
|
|
||||||
import 'package:didvan/models/view/alert_data.dart';
|
import 'package:didvan/models/view/alert_data.dart';
|
||||||
import 'package:didvan/providers/core.dart';
|
import 'package:didvan/providers/core.dart';
|
||||||
import 'package:didvan/providers/user.dart';
|
import 'package:didvan/providers/user.dart';
|
||||||
import 'package:didvan/services/network/request.dart';
|
import 'package:didvan/services/network/request.dart';
|
||||||
import 'package:didvan/services/network/request_helper.dart';
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
import 'package:didvan/utils/action_sheet.dart';
|
import 'package:didvan/utils/action_sheet.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class CommentsState extends CoreProvier {
|
class CommentsState extends CoreProvier {
|
||||||
TextEditingController commentTextFieldController = TextEditingController();
|
String text = '';
|
||||||
UsersMention usersMentioned = UsersMention();
|
|
||||||
String mentionedText = '';
|
|
||||||
int? commentId;
|
int? commentId;
|
||||||
UserOverview? replyingTo;
|
UserOverview? replyingTo;
|
||||||
bool showReplyBox = false;
|
bool showReplyBox = false;
|
||||||
bool showUsersForMentionsLayout = false;
|
|
||||||
bool showPrivates = false;
|
|
||||||
bool hideMentionedUser = false;
|
|
||||||
late void Function(int count) onCommentsChanged;
|
late void Function(int count) onCommentsChanged;
|
||||||
int _count = 0;
|
int _count = 0;
|
||||||
late String type;
|
late String type;
|
||||||
|
|
||||||
final List<CommentData> comments = [];
|
final List<CommentData> comments = [];
|
||||||
final List<CommentData> privateComments = [];
|
|
||||||
final List<UsersMention> usersMention = [];
|
|
||||||
final Map<int, MapEntry<bool, bool>> _feedbackQueue = {};
|
final Map<int, MapEntry<bool, bool>> _feedbackQueue = {};
|
||||||
|
|
||||||
int itemId = 0;
|
int itemId = 0;
|
||||||
|
|
@ -42,40 +33,14 @@ class CommentsState extends CoreProvier {
|
||||||
await service.httpGet();
|
await service.httpGet();
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
comments.clear();
|
comments.clear();
|
||||||
final messagesPublic = service.result['comments']['public'];
|
final messages = service.result['comments'];
|
||||||
for (var i = 0; i < messagesPublic.length; i++) {
|
for (var i = 0; i < messages.length; i++) {
|
||||||
comments.add(CommentData.fromJson(messagesPublic[i], false));
|
comments.add(CommentData.fromJson(messages[i]));
|
||||||
_count++;
|
_count++;
|
||||||
for (var j = 0; j < messagesPublic[i]['replies'].length; j++) {
|
for (var j = 0; j < messages[i]['replies'].length; j++) {
|
||||||
_count++;
|
_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final messagesPrivate = service.result['comments']['private'];
|
|
||||||
for (var i = 0; i < messagesPrivate.length; i++) {
|
|
||||||
privateComments.add(CommentData.fromJson(messagesPrivate[i], true));
|
|
||||||
_count++;
|
|
||||||
for (var j = 0; j < messagesPrivate[i]['replies'].length; j++) {
|
|
||||||
_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appState = AppState.idle;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
appState = AppState.failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> getUsersMention() async {
|
|
||||||
final service = RequestService(
|
|
||||||
RequestHelper.usersMentions(mentionedText.replaceAll("@", "")),
|
|
||||||
);
|
|
||||||
await service.httpGet();
|
|
||||||
if (service.isSuccess) {
|
|
||||||
usersMention.clear();
|
|
||||||
final List<dynamic> users = service.data('users');
|
|
||||||
usersMention
|
|
||||||
.addAll(users.map((users) => UsersMention.fromJson(users)).toList());
|
|
||||||
|
|
||||||
appState = AppState.idle;
|
appState = AppState.idle;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -122,14 +87,12 @@ class CommentsState extends CoreProvier {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addComment() async {
|
Future<void> addComment() async {
|
||||||
late List<CommentData> cList =
|
|
||||||
hideMentionedUser ? privateComments : comments;
|
|
||||||
final user = DesignConfig.context!.read<UserProvider>().user;
|
final user = DesignConfig.context!.read<UserProvider>().user;
|
||||||
if (replyingTo != null) {
|
if (replyingTo != null) {
|
||||||
comments.firstWhere((comment) => comment.id == commentId).replies.add(
|
comments.firstWhere((comment) => comment.id == commentId).replies.add(
|
||||||
Reply(
|
Reply(
|
||||||
id: 0,
|
id: 0,
|
||||||
text: commentTextFieldController.text,
|
text: text,
|
||||||
createdAt: DateTime.now().toString(),
|
createdAt: DateTime.now().toString(),
|
||||||
liked: false,
|
liked: false,
|
||||||
disliked: false,
|
disliked: false,
|
||||||
|
|
@ -141,15 +104,14 @@ class CommentsState extends CoreProvier {
|
||||||
photo: user.photo,
|
photo: user.photo,
|
||||||
),
|
),
|
||||||
status: 2,
|
status: 2,
|
||||||
mention: usersMentioned.name,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
cList.insert(
|
comments.insert(
|
||||||
0,
|
0,
|
||||||
CommentData(
|
CommentData(
|
||||||
id: 0,
|
id: 0,
|
||||||
text: commentTextFieldController.text,
|
text: text,
|
||||||
createdAt: DateTime.now().toString(),
|
createdAt: DateTime.now().toString(),
|
||||||
liked: false,
|
liked: false,
|
||||||
disliked: false,
|
disliked: false,
|
||||||
|
|
@ -161,8 +123,6 @@ class CommentsState extends CoreProvier {
|
||||||
),
|
),
|
||||||
replies: [],
|
replies: [],
|
||||||
status: 2,
|
status: 2,
|
||||||
private: hideMentionedUser,
|
|
||||||
mention: usersMentioned.name,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -178,12 +138,8 @@ class CommentsState extends CoreProvier {
|
||||||
body.addAll({'status': 2});
|
body.addAll({'status': 2});
|
||||||
|
|
||||||
showReplyBox = false;
|
showReplyBox = false;
|
||||||
// update();
|
update();
|
||||||
body.addAll({
|
body.addAll({'text': text});
|
||||||
'text': commentTextFieldController.text,
|
|
||||||
"mention": usersMentioned.id,
|
|
||||||
"private": hideMentionedUser
|
|
||||||
});
|
|
||||||
final service = RequestService(
|
final service = RequestService(
|
||||||
RequestHelper.addComment(itemId, type),
|
RequestHelper.addComment(itemId, type),
|
||||||
body: body,
|
body: body,
|
||||||
|
|
@ -192,20 +148,17 @@ class CommentsState extends CoreProvier {
|
||||||
await service.post();
|
await service.post();
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
if (replyingTo != null) {
|
if (replyingTo != null) {
|
||||||
cList
|
comments
|
||||||
.firstWhere((comment) => comment.id == commentId)
|
.firstWhere((comment) => comment.id == commentId)
|
||||||
.replies
|
.replies
|
||||||
.firstWhere((reply) => reply.id == 0)
|
.firstWhere((reply) => reply.id == 0)
|
||||||
.id = service.result['comment']['id'];
|
.id = service.result['comment']['id'];
|
||||||
} else {
|
} else {
|
||||||
cList.firstWhere((comment) => comment.id == 0).id =
|
comments.firstWhere((comment) => comment.id == 0).id =
|
||||||
service.result['comment']['id'];
|
service.result['comment']['id'];
|
||||||
}
|
}
|
||||||
commentId = null;
|
commentId = null;
|
||||||
replyingTo = null;
|
replyingTo = null;
|
||||||
usersMentioned = UsersMention();
|
|
||||||
mentionedText = '';
|
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import 'package:provider/provider.dart';
|
||||||
class Comment extends StatefulWidget {
|
class Comment extends StatefulWidget {
|
||||||
final FocusNode focusNode;
|
final FocusNode focusNode;
|
||||||
final CommentData comment;
|
final CommentData comment;
|
||||||
|
|
||||||
const Comment({
|
const Comment({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.focusNode,
|
required this.focusNode,
|
||||||
|
|
@ -110,13 +109,6 @@ class CommentState extends State<Comment> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
comment.mention != null
|
|
||||||
? DidvanText(
|
|
||||||
comment.mention.toString(),
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
style: Theme.of(context).textTheme.titleSmall,
|
|
||||||
)
|
|
||||||
: const SizedBox(),
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
if (isReply)
|
if (isReply)
|
||||||
DidvanText(
|
DidvanText(
|
||||||
|
|
@ -132,22 +124,19 @@ class CommentState extends State<Comment> {
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
Icons.circle,
|
Icons.circle,
|
||||||
color:
|
color: Theme.of(context)
|
||||||
Theme.of(context).colorScheme.secondaryDisabled,
|
.colorScheme
|
||||||
|
.secondary
|
||||||
|
.withOpacity(0.3),
|
||||||
size: 18,
|
size: 18,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
DidvanText(
|
DidvanText(
|
||||||
'در انتظار تایید',
|
'در انتظار تایید',
|
||||||
style: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.textTheme
|
.colorScheme
|
||||||
.titleSmall!
|
.secondary
|
||||||
.copyWith(
|
.withOpacity(0.3),
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.secondaryDisabled),
|
|
||||||
color:
|
|
||||||
Theme.of(context).colorScheme.secondaryDisabled,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -265,7 +254,6 @@ class _FeedbackButtons extends StatefulWidget {
|
||||||
final bool dislikeValue;
|
final bool dislikeValue;
|
||||||
final void Function(bool like, bool dislike, int likeCount, int dislikeCount)
|
final void Function(bool like, bool dislike, int likeCount, int dislikeCount)
|
||||||
onFeedback;
|
onFeedback;
|
||||||
|
|
||||||
const _FeedbackButtons({
|
const _FeedbackButtons({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.onFeedback,
|
required this.onFeedback,
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,9 @@ import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
import 'package:didvan/constants/assets.dart';
|
import 'package:didvan/constants/assets.dart';
|
||||||
import 'package:didvan/models/users_mention.dart';
|
|
||||||
import 'package:didvan/models/view/app_bar_data.dart';
|
import 'package:didvan/models/view/app_bar_data.dart';
|
||||||
import 'package:didvan/views/comments/widgets/comment.dart';
|
|
||||||
import 'package:didvan/views/mentions/mentions_state.dart';
|
import 'package:didvan/views/mentions/mentions_state.dart';
|
||||||
|
import 'package:didvan/views/mentions/widgets/mention.dart';
|
||||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/checkbox.dart';
|
import 'package:didvan/views/widgets/didvan/checkbox.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||||
|
|
@ -18,8 +17,7 @@ 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';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import '../comments/comments_state.dart';
|
||||||
import '../widgets/didvan/didvan_title_divider.dart';
|
|
||||||
import '../widgets/user_mention.dart';
|
import '../widgets/user_mention.dart';
|
||||||
|
|
||||||
class Mentions extends StatefulWidget {
|
class Mentions extends StatefulWidget {
|
||||||
|
|
@ -54,6 +52,12 @@ class _MentionsState extends State<Mentions> {
|
||||||
|
|
||||||
bool get _isPage => widget.pageData['isPage'] != false;
|
bool get _isPage => widget.pageData['isPage'] != false;
|
||||||
|
|
||||||
|
void _onChange(MentionsState state, value) {
|
||||||
|
state.searchUsers = value;
|
||||||
|
state.getUsersMention();
|
||||||
|
state.update();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final commentsState = context.watch<MentionsState>();
|
final commentsState = context.watch<MentionsState>();
|
||||||
|
|
@ -92,12 +96,11 @@ class _MentionsState extends State<Mentions> {
|
||||||
childCount: state.comments.length,
|
childCount: state.comments.length,
|
||||||
placeholder: const _CommentPlaceholder(),
|
placeholder: const _CommentPlaceholder(),
|
||||||
centerEmptyState: _isPage,
|
centerEmptyState: _isPage,
|
||||||
enableEmptyState:
|
enableEmptyState: state.comments.isEmpty,
|
||||||
state.comments.isEmpty && state.privateComments.isEmpty,
|
|
||||||
emptyState: EmptyState(
|
emptyState: EmptyState(
|
||||||
asset: Assets.emptyChat,
|
asset: Assets.emptyChat,
|
||||||
title: 'دوستان خود را فراخوانی کنید'),
|
title: 'دوستان خود را فراخوانی کنید'),
|
||||||
builder: (context, state, index) => Comment(
|
builder: (context, state, index) => Mention(
|
||||||
key: ValueKey(
|
key: ValueKey(
|
||||||
state.comments[index].id.toString() +
|
state.comments[index].id.toString() +
|
||||||
state.comments[index].text,
|
state.comments[index].text,
|
||||||
|
|
@ -108,42 +111,6 @@ class _MentionsState extends State<Mentions> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
children: commentsState.privateComments.isNotEmpty
|
|
||||||
? [
|
|
||||||
const SizedBox(
|
|
||||||
height: 6,
|
|
||||||
),
|
|
||||||
DidvanTitleDivider(
|
|
||||||
title: "نظرات پنهان شده",
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
icon: Icon(
|
|
||||||
commentsState.showPrivates
|
|
||||||
? DidvanIcons.angle_up_regular
|
|
||||||
: DidvanIcons.angle_down_regular,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
onClick: () {
|
|
||||||
commentsState.showPrivates =
|
|
||||||
!commentsState.showPrivates;
|
|
||||||
commentsState.update();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
AnimatedVisibility(
|
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
|
||||||
isVisible: commentsState.showPrivates,
|
|
||||||
child: _buildPrivateComments(commentsState),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
const DidvanTitleDivider(
|
|
||||||
title: "سایر نظرات",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
duration: DesignConfig.lowAnimationDuration,
|
||||||
|
|
@ -159,30 +126,73 @@ class _MentionsState extends State<Mentions> {
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 16, right: 16, top: 16, bottom: 92),
|
left: 16, right: 16, top: 16, bottom: 92),
|
||||||
backgroundColor: Colors.white.withOpacity(0.0),
|
backgroundColor: Colors.white.withOpacity(0.0),
|
||||||
|
showSliversFirst: false,
|
||||||
slivers: [
|
slivers: [
|
||||||
Consumer<MentionsState>(
|
Consumer<MentionsState>(
|
||||||
builder: (context, state, child) =>
|
builder: (context, state, child) =>
|
||||||
SliverStateHandler<MentionsState>(
|
SliverStateHandler<MentionsState>(
|
||||||
onRetry: state.getUsersMention,
|
onRetry: state.getUsersMention,
|
||||||
state: state,
|
state: state,
|
||||||
itemPadding: const EdgeInsets.symmetric(vertical: 8),
|
childCount: state.users.length,
|
||||||
childCount: state.usersMention.length,
|
|
||||||
placeholder: const _UsersPlaceholder(),
|
placeholder: const _UsersPlaceholder(),
|
||||||
centerEmptyState: _isPage,
|
centerEmptyState: _isPage,
|
||||||
enableEmptyState: state.usersMention.isEmpty,
|
enableEmptyState: state.users.isEmpty,
|
||||||
emptyState: EmptyState(
|
emptyState: EmptyState(
|
||||||
asset: Assets.emptyBookmark,
|
asset: Assets.emptyBookmark,
|
||||||
title: 'لیست خالی است',
|
title: 'لیست خالی است',
|
||||||
),
|
),
|
||||||
builder: (context, state, index) {
|
builder: (context, state, index) {
|
||||||
return UserMention(
|
return UserMention(
|
||||||
user: state.usersMention[index],
|
user: state.users[index],
|
||||||
index: index,
|
index: index,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
|
textInputAction: TextInputAction.send,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
onEditingComplete: () {},
|
||||||
|
onChanged: (val) => _onChange(commentsState, val),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
icon: const Icon(DidvanIcons.search_regular),
|
||||||
|
border: InputBorder.none,
|
||||||
|
hintText: 'جستجو کنید...',
|
||||||
|
hintStyle: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.disabledText),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DidvanIconButton(
|
||||||
|
icon: DidvanIcons.close_regular,
|
||||||
|
onPressed: () {
|
||||||
|
commentsState.showUsersForMentionsLayout = false;
|
||||||
|
commentsState.update();
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 4,
|
||||||
|
),
|
||||||
|
Divider(
|
||||||
|
height: 1,
|
||||||
|
color: Theme.of(context).colorScheme.splash,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -197,23 +207,6 @@ class _MentionsState extends State<Mentions> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView _buildPrivateComments(MentionsState commentsState) {
|
|
||||||
return ListView.builder(
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
itemCount: commentsState.privateComments.length,
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return Comment(
|
|
||||||
key: ValueKey(
|
|
||||||
commentsState.privateComments[index].id.toString() +
|
|
||||||
commentsState.privateComments[index].text,
|
|
||||||
),
|
|
||||||
focusNode: _focusNode,
|
|
||||||
comment: commentsState.privateComments[index],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MessageBox extends StatefulWidget {
|
class _MessageBox extends StatefulWidget {
|
||||||
|
|
@ -245,31 +238,23 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.secondCTA,
|
color: Theme.of(context).colorScheme.secondCTA,
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
topRight: Radius.circular(16),
|
topRight: Radius.circular(16),
|
||||||
topLeft: Radius.circular(16)),
|
topLeft: Radius.circular(16)),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Theme.of(context)
|
color:
|
||||||
.colorScheme
|
Theme.of(context).colorScheme.title.withOpacity(0.2),
|
||||||
.title
|
offset: const Offset(
|
||||||
.withOpacity(0.2),
|
5.0,
|
||||||
offset: const Offset(
|
5.0,
|
||||||
5.0,
|
),
|
||||||
5.0,
|
blurRadius: 10.0,
|
||||||
),
|
spreadRadius: 2.0,
|
||||||
blurRadius: 10.0,
|
|
||||||
spreadRadius: 2.0,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
// border: Border(
|
|
||||||
// top: BorderSide(
|
|
||||||
// color: Theme.of(context).colorScheme.border,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -307,7 +292,7 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
),
|
),
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
duration: DesignConfig.lowAnimationDuration,
|
||||||
isVisible: state.usersMentioned.name != null,
|
isVisible: state.mentionedUsers.isNotEmpty,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
|
|
@ -343,7 +328,9 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
),
|
),
|
||||||
DidvanText(
|
DidvanText(
|
||||||
state.usersMentioned.name.toString(),
|
state.mentionedUsers
|
||||||
|
.map((user) => user.name)
|
||||||
|
.join("، "),
|
||||||
color: Theme.of(context).colorScheme.text,
|
color: Theme.of(context).colorScheme.text,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
),
|
),
|
||||||
|
|
@ -359,19 +346,10 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
icon: DidvanIcons.close_regular,
|
icon: DidvanIcons.close_regular,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
state.usersMentioned = UsersMention();
|
state.mentionedUsers = [];
|
||||||
state.update();
|
state.update();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
!state.showReplyBox
|
|
||||||
? DidvanCheckbox(
|
|
||||||
title: "پنهان کردن فراخوانی",
|
|
||||||
value: state.hideMentionedUser,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
onChanged: onCheckBoxChange,
|
|
||||||
size: 12,
|
|
||||||
)
|
|
||||||
: const SizedBox(),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
@ -382,23 +360,12 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
boxShadow: state.showReplyBox && state.usersMentioned.name == null
|
color: Theme.of(context).colorScheme.surface,
|
||||||
? null
|
border: Border(
|
||||||
: [
|
top: BorderSide(
|
||||||
BoxShadow(
|
color: Theme.of(context).colorScheme.border,
|
||||||
color:
|
),
|
||||||
Theme.of(context).colorScheme.title.withOpacity(0.2),
|
),
|
||||||
offset: const Offset(
|
|
||||||
5.0,
|
|
||||||
5.0,
|
|
||||||
),
|
|
||||||
blurRadius: 10.0,
|
|
||||||
spreadRadius: 2.0,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
color: state.showReplyBox && state.usersMentioned.name == null
|
|
||||||
? Theme.of(context).colorScheme.secondCTA
|
|
||||||
: Theme.of(context).colorScheme.surface,
|
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -423,9 +390,19 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
color: Theme.of(context).colorScheme.disabledText),
|
color: Theme.of(context).colorScheme.disabledText),
|
||||||
),
|
),
|
||||||
onChanged: (value) => _onChange(state, value),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const Spacer(),
|
||||||
|
if (!state.showUsersForMentionsLayout)
|
||||||
|
DidvanIconButton(
|
||||||
|
onPressed: () {
|
||||||
|
state.showUsersForMentionsLayout = true;
|
||||||
|
state.update();
|
||||||
|
},
|
||||||
|
icon: DidvanIcons.user_shield_regular,
|
||||||
|
size: 24,
|
||||||
|
color: Theme.of(context).colorScheme.focusedBorder,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -437,30 +414,8 @@ class _MessageBoxState extends State<_MessageBox> {
|
||||||
if (state.commentTextFieldController.text.replaceAll(' ', '').isNotEmpty) {
|
if (state.commentTextFieldController.text.replaceAll(' ', '').isNotEmpty) {
|
||||||
state.addComment();
|
state.addComment();
|
||||||
state.commentTextFieldController.text = '';
|
state.commentTextFieldController.text = '';
|
||||||
}
|
state.searchUsers = '';
|
||||||
}
|
state.mentionedUsers.clear();
|
||||||
|
|
||||||
void _onChange(MentionsState state, value) {
|
|
||||||
state.commentTextFieldController.text = value;
|
|
||||||
if (state.usersMentioned.name == null) {
|
|
||||||
if (state.commentTextFieldController.text.contains("@")) {
|
|
||||||
int index = state.commentTextFieldController.text.indexOf("@");
|
|
||||||
if (state.commentTextFieldController.text.length > index + 1) {
|
|
||||||
if (state.commentTextFieldController.text
|
|
||||||
.substring(index)
|
|
||||||
.contains(" ")) {
|
|
||||||
state.showUsersForMentionsLayout = false;
|
|
||||||
} else {
|
|
||||||
state.mentionedText =
|
|
||||||
state.commentTextFieldController.text.substring(index);
|
|
||||||
state.getUsersMention();
|
|
||||||
state.showUsersForMentionsLayout = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.showUsersForMentionsLayout = false;
|
|
||||||
}
|
|
||||||
state.update();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,19 @@
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/models/comment/comment.dart';
|
import 'package:didvan/models/mention/mention.dart';
|
||||||
import 'package:didvan/models/comment/feedback.dart';
|
|
||||||
import 'package:didvan/models/comment/reply.dart';
|
|
||||||
import 'package:didvan/models/comment/user.dart';
|
import 'package:didvan/models/comment/user.dart';
|
||||||
import 'package:didvan/models/enums.dart';
|
import 'package:didvan/models/enums.dart';
|
||||||
import 'package:didvan/models/users_mention.dart';
|
import 'package:didvan/models/users_mention.dart';
|
||||||
import 'package:didvan/models/view/alert_data.dart';
|
|
||||||
import 'package:didvan/providers/core.dart';
|
import 'package:didvan/providers/core.dart';
|
||||||
import 'package:didvan/providers/user.dart';
|
import 'package:didvan/providers/user.dart';
|
||||||
import 'package:didvan/services/network/request.dart';
|
import 'package:didvan/services/network/request.dart';
|
||||||
import 'package:didvan/services/network/request_helper.dart';
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
import 'package:didvan/utils/action_sheet.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class MentionsState extends CoreProvier {
|
class MentionsState extends CoreProvier {
|
||||||
TextEditingController commentTextFieldController = TextEditingController();
|
TextEditingController commentTextFieldController = TextEditingController();
|
||||||
UsersMention usersMentioned = UsersMention();
|
List<UsersMention> mentionedUsers = [];
|
||||||
String mentionedText = '';
|
String searchUsers = '';
|
||||||
int? commentId;
|
int? commentId;
|
||||||
UserOverview? replyingTo;
|
UserOverview? replyingTo;
|
||||||
bool showReplyBox = false;
|
bool showReplyBox = false;
|
||||||
|
|
@ -27,38 +23,27 @@ class MentionsState extends CoreProvier {
|
||||||
int _count = 0;
|
int _count = 0;
|
||||||
late String type;
|
late String type;
|
||||||
|
|
||||||
final List<CommentData> comments = [];
|
final List<MentionData> comments = [];
|
||||||
final List<CommentData> privateComments = [];
|
final List<UsersMention> users = [];
|
||||||
final List<UsersMention> usersMention = [];
|
|
||||||
final Map<int, MapEntry<bool, bool>> _feedbackQueue = {};
|
|
||||||
|
|
||||||
int itemId = 0;
|
int itemId = 0;
|
||||||
|
|
||||||
Future<void> getComments() async {
|
Future<void> getComments() async {
|
||||||
final service = RequestService(
|
final service = RequestService(
|
||||||
RequestHelper.comments(itemId, type),
|
RequestHelper.mention(itemId, type),
|
||||||
);
|
);
|
||||||
await service.httpGet();
|
await service.httpGet();
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
comments.clear();
|
comments.clear();
|
||||||
final messagesPublic = service.result['comments']['public'];
|
final messages = service.result['comments'];
|
||||||
for (var i = 0; i < messagesPublic.length; i++) {
|
|
||||||
comments.add(CommentData.fromJson(messagesPublic[i], false));
|
for (var i = 0; i < messages.length; i++) {
|
||||||
|
comments.add(MentionData.fromJson(messages[i]));
|
||||||
_count++;
|
_count++;
|
||||||
for (var j = 0; j < messagesPublic[i]['replies'].length; j++) {
|
|
||||||
_count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final messagesPrivate = service.result['comments']['private'];
|
|
||||||
for (var i = 0; i < messagesPrivate.length; i++) {
|
|
||||||
privateComments.add(CommentData.fromJson(messagesPrivate[i], true));
|
|
||||||
_count++;
|
|
||||||
for (var j = 0; j < messagesPrivate[i]['replies'].length; j++) {
|
|
||||||
_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appState = AppState.idle;
|
appState = AppState.idle;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
appState = AppState.failed;
|
appState = AppState.failed;
|
||||||
|
|
@ -66,14 +51,17 @@ class MentionsState extends CoreProvier {
|
||||||
|
|
||||||
Future<void> getUsersMention() async {
|
Future<void> getUsersMention() async {
|
||||||
final service = RequestService(
|
final service = RequestService(
|
||||||
RequestHelper.usersMentions(mentionedText.replaceAll("@", "")),
|
RequestHelper.usersMentions(searchUsers),
|
||||||
);
|
);
|
||||||
|
|
||||||
await service.httpGet();
|
await service.httpGet();
|
||||||
|
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
usersMention.clear();
|
users.clear();
|
||||||
final List<dynamic> users = service.data('users');
|
final List<dynamic> resUsers = service.data('users');
|
||||||
usersMention
|
|
||||||
.addAll(users.map((users) => UsersMention.fromJson(users)).toList());
|
users
|
||||||
|
.addAll(resUsers.map((user) => UsersMention.fromJson(user)).toList());
|
||||||
|
|
||||||
appState = AppState.idle;
|
appState = AppState.idle;
|
||||||
return;
|
return;
|
||||||
|
|
@ -81,169 +69,49 @@ class MentionsState extends CoreProvier {
|
||||||
appState = AppState.failed;
|
appState = AppState.failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> feedback({
|
|
||||||
required int id,
|
|
||||||
required bool like,
|
|
||||||
required bool dislike,
|
|
||||||
required int likeCount,
|
|
||||||
required int dislikeCount,
|
|
||||||
int? replyId,
|
|
||||||
}) async {
|
|
||||||
_feedbackQueue.addAll({id: MapEntry(like, dislike)});
|
|
||||||
dynamic comment;
|
|
||||||
if (replyId == null) {
|
|
||||||
comment = comments.firstWhere((comment) => comment.id == id);
|
|
||||||
} else {
|
|
||||||
comment = comments
|
|
||||||
.firstWhere((comment) => comment.id == id)
|
|
||||||
.replies
|
|
||||||
.firstWhere((element) => element.id == replyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comment != null) {
|
|
||||||
comment.feedback.like = likeCount;
|
|
||||||
comment.feedback.dislike = dislikeCount;
|
|
||||||
comment.disliked = dislike;
|
|
||||||
comment.liked = like;
|
|
||||||
}
|
|
||||||
Future.delayed(const Duration(milliseconds: 500), () async {
|
|
||||||
if (!_feedbackQueue.containsKey(id)) return;
|
|
||||||
final service = RequestService(
|
|
||||||
RequestHelper.feedback(itemId, id, type),
|
|
||||||
body: {
|
|
||||||
'like': _feedbackQueue[id]!.key,
|
|
||||||
'dislike': _feedbackQueue[id]!.value,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
await service.put();
|
|
||||||
_feedbackQueue.remove(id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> addComment() async {
|
Future<void> addComment() async {
|
||||||
late List<CommentData> cList =
|
late List<MentionData> cList = comments;
|
||||||
hideMentionedUser ? privateComments : comments;
|
|
||||||
final user = DesignConfig.context!.read<UserProvider>().user;
|
final user = DesignConfig.context!.read<UserProvider>().user;
|
||||||
if (replyingTo != null) {
|
|
||||||
comments.firstWhere((comment) => comment.id == commentId).replies.add(
|
cList.insert(
|
||||||
Reply(
|
0,
|
||||||
id: 0,
|
MentionData(
|
||||||
text: commentTextFieldController.text,
|
id: 0,
|
||||||
createdAt: DateTime.now().toString(),
|
fullName: user.fullName,
|
||||||
liked: false,
|
text: commentTextFieldController.text,
|
||||||
disliked: false,
|
createdAt: DateTime.now().toString(),
|
||||||
feedback: FeedbackData(like: 0, dislike: 0),
|
mentions: mentionedUsers.map((user) => user.name).toList(),
|
||||||
toUser: replyingTo!,
|
),
|
||||||
user: UserOverview(
|
);
|
||||||
id: user.id,
|
|
||||||
fullName: user.fullName,
|
|
||||||
photo: user.photo,
|
|
||||||
),
|
|
||||||
status: 2,
|
|
||||||
mention: usersMentioned.name,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
cList.insert(
|
|
||||||
0,
|
|
||||||
CommentData(
|
|
||||||
id: 0,
|
|
||||||
text: commentTextFieldController.text,
|
|
||||||
createdAt: DateTime.now().toString(),
|
|
||||||
liked: false,
|
|
||||||
disliked: false,
|
|
||||||
feedback: FeedbackData(like: 0, dislike: 0),
|
|
||||||
user: UserOverview(
|
|
||||||
id: user.id,
|
|
||||||
fullName: user.fullName,
|
|
||||||
photo: user.photo,
|
|
||||||
),
|
|
||||||
replies: [],
|
|
||||||
status: 2,
|
|
||||||
private: hideMentionedUser,
|
|
||||||
mention: usersMentioned.name,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final body = {};
|
final body = {};
|
||||||
|
|
||||||
if (commentId != null) {
|
|
||||||
body.addAll({'commentId': commentId});
|
|
||||||
}
|
|
||||||
if (replyingTo != null) {
|
|
||||||
body.addAll({'replyUserId': replyingTo!.id});
|
|
||||||
}
|
|
||||||
body.addAll({'status': 2});
|
|
||||||
|
|
||||||
showReplyBox = false;
|
|
||||||
// update();
|
|
||||||
body.addAll({
|
body.addAll({
|
||||||
'text': commentTextFieldController.text,
|
'text': commentTextFieldController.text,
|
||||||
"mention": usersMentioned.id,
|
"mentions": mentionedUsers.map((user) => user.id.toString()).toList(),
|
||||||
"private": hideMentionedUser
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final service = RequestService(
|
final service = RequestService(
|
||||||
RequestHelper.addComment(itemId, type),
|
RequestHelper.mention(itemId, type),
|
||||||
body: body,
|
body: body,
|
||||||
);
|
);
|
||||||
|
|
||||||
await service.post();
|
await service.post();
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
if (replyingTo != null) {
|
cList.firstWhere((comment) => comment.id == 0).id =
|
||||||
cList
|
service.result['comment']['id'];
|
||||||
.firstWhere((comment) => comment.id == commentId)
|
|
||||||
.replies
|
mentionedUsers = [];
|
||||||
.firstWhere((reply) => reply.id == 0)
|
searchUsers = '';
|
||||||
.id = service.result['comment']['id'];
|
|
||||||
} else {
|
|
||||||
cList.firstWhere((comment) => comment.id == 0).id =
|
|
||||||
service.result['comment']['id'];
|
|
||||||
}
|
|
||||||
commentId = null;
|
|
||||||
replyingTo = null;
|
|
||||||
usersMentioned = UsersMention();
|
|
||||||
mentionedText = '';
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reportComment(int id) {
|
|
||||||
final service = RequestService(RequestHelper.reportComment(id));
|
|
||||||
service.post();
|
|
||||||
ActionSheetUtils.showAlert(
|
|
||||||
AlertData(
|
|
||||||
message: 'گزارش شما با موفقیت ثبت شد و به زودی بررسی میگردد.',
|
|
||||||
aLertType: ALertType.success,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void deleteComment(int id, int status, int? rootId) async {
|
void deleteComment(int id, int status, int? rootId) async {
|
||||||
final service = RequestService(RequestHelper.deleteComment(id));
|
final service = RequestService(RequestHelper.deleteComment(id));
|
||||||
service.delete();
|
await service.delete();
|
||||||
if (rootId == null) {
|
|
||||||
final comment = comments.firstWhere((element) => element.id == id);
|
|
||||||
if (comment.replies.isNotEmpty) {
|
|
||||||
_count = 0;
|
|
||||||
await getComments();
|
|
||||||
} else {
|
|
||||||
comments.remove(comment);
|
|
||||||
|
|
||||||
if (status != 2) {
|
if (service.isSuccess) await getComments();
|
||||||
_count--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
comments
|
|
||||||
.firstWhere((element) => element.id == rootId)
|
|
||||||
.replies
|
|
||||||
.removeWhere((element) => element.id == id);
|
|
||||||
|
|
||||||
if (status != 2) {
|
|
||||||
_count--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
import 'package:didvan/models/comment/comment.dart';
|
|
||||||
import 'package:didvan/models/comment/reply.dart';
|
import 'package:didvan/models/comment/reply.dart';
|
||||||
import 'package:didvan/models/mention/mention.dart';
|
import 'package:didvan/models/mention/mention.dart';
|
||||||
import 'package:didvan/models/view/action_sheet_data.dart';
|
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||||
import 'package:didvan/providers/user.dart';
|
import 'package:didvan/providers/user.dart';
|
||||||
import 'package:didvan/utils/action_sheet.dart';
|
import 'package:didvan/utils/action_sheet.dart';
|
||||||
import 'package:didvan/utils/date_time.dart';
|
import 'package:didvan/utils/date_time.dart';
|
||||||
import 'package:didvan/views/comments/comments_state.dart';
|
|
||||||
import 'package:didvan/views/mentions/mentions_state.dart';
|
import 'package:didvan/views/mentions/mentions_state.dart';
|
||||||
import 'package:didvan/views/widgets/menu_item.dart';
|
import 'package:didvan/views/widgets/menu_item.dart';
|
||||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
|
||||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
|
import 'package:didvan/views/mentions/mentions_state.dart';
|
||||||
|
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||||
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
||||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -6,7 +9,6 @@ import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../../constants/app_icons.dart';
|
import '../../constants/app_icons.dart';
|
||||||
import '../../models/users_mention.dart';
|
import '../../models/users_mention.dart';
|
||||||
import '../comments/comments_state.dart';
|
|
||||||
import 'didvan/text.dart';
|
import 'didvan/text.dart';
|
||||||
|
|
||||||
class UserMention extends StatefulWidget {
|
class UserMention extends StatefulWidget {
|
||||||
|
|
@ -26,28 +28,62 @@ class UserMention extends StatefulWidget {
|
||||||
class _UserMentionState extends State<UserMention> {
|
class _UserMentionState extends State<UserMention> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final state = context.watch<CommentsState>();
|
final state = context.watch<MentionsState>();
|
||||||
|
final userFound = state.mentionedUsers.contains(widget.user);
|
||||||
|
|
||||||
return InkWrapper(
|
return InkWrapper(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
state.usersMentioned = widget.user;
|
if (userFound) {
|
||||||
state.commentTextFieldController.text = state
|
state.mentionedUsers.remove(widget.user);
|
||||||
.commentTextFieldController.text
|
} else {
|
||||||
.replaceAll(state.mentionedText.toString(), "")
|
state.mentionedUsers.add(widget.user);
|
||||||
.replaceAll("@", "");
|
}
|
||||||
state.showUsersForMentionsLayout = false;
|
|
||||||
state.update();
|
state.update();
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
border: Border.all(
|
||||||
|
width: 1.0,
|
||||||
|
color: userFound
|
||||||
|
? Theme.of(context).colorScheme.checkFav
|
||||||
|
: Theme.of(context).colorScheme.text),
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.all(8),
|
||||||
|
child: AnimatedVisibility(
|
||||||
|
isVisible: userFound,
|
||||||
|
duration: DesignConfig.mediumAnimationDuration,
|
||||||
|
child: Center(
|
||||||
|
child: Icon(
|
||||||
|
Icons.check,
|
||||||
|
size: 12,
|
||||||
|
color: userFound
|
||||||
|
? Theme.of(context).colorScheme.checkFav
|
||||||
|
: Theme.of(context).colorScheme.text,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
widget.user.photo == null
|
widget.user.photo == null
|
||||||
? const Icon(DidvanIcons.avatar_light,size: 40,)
|
? const Icon(
|
||||||
|
DidvanIcons.avatar_light,
|
||||||
|
size: 40,
|
||||||
|
)
|
||||||
: SkeletonImage(
|
: SkeletonImage(
|
||||||
imageUrl: widget.user.photo.toString(),
|
imageUrl: widget.user.photo.toString(),
|
||||||
height: 40,
|
height: 36,
|
||||||
width: 40,
|
width: 36,
|
||||||
borderRadius: BorderRadius.circular(360),
|
borderRadius: BorderRadius.circular(360),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
|
|
@ -62,7 +98,7 @@ class _UserMentionState extends State<UserMention> {
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
widget.index == state.usersMention.length - 1
|
widget.index == state.users.length - 1
|
||||||
? const SizedBox()
|
? const SizedBox()
|
||||||
: Divider(
|
: Divider(
|
||||||
height: 2,
|
height: 2,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue