Complete mention section

This commit is contained in:
Amir Hossein Mousavi 2024-05-23 20:00:31 +03:30
parent f4689f3391
commit f9745a792a
12 changed files with 111 additions and 72 deletions

Binary file not shown.

View File

@ -17,6 +17,7 @@
///
import 'package:flutter/widgets.dart';
class DidvanIcons {
DidvanIcons._();
@ -551,4 +552,6 @@ class DidvanIcons {
IconData(0xe906, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData video_solid =
IconData(0xe907, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData mention_icon =
IconData(0xe908, fontFamily: _kFontFam, fontPackage: _kFontPkg);
}

View File

@ -1,30 +1,33 @@
import 'package:didvan/models/comment/user.dart';
class MentionData {
int id;
String fullName;
String text;
String createdAt;
List<String> mentions;
final UserOverview user;
MentionData(
{required this.id,
required this.text,
required this.createdAt,
required this.fullName,
required this.mentions});
MentionData({
required this.id,
required this.text,
required this.createdAt,
required this.mentions,
required this.user,
});
factory MentionData.fromJson(Map<String, dynamic> json) => MentionData(
id: json['id'],
text: json['text'],
createdAt: json['createdAt'],
fullName: json['fullName'],
mentions: json['mentions'],
mentions: List<String>.from(json['mentions']),
user: UserOverview.fromJson(json['user']),
);
Map<String, dynamic> toJson() => {
'id': id,
'text': text,
'createdAt': createdAt,
'fullName': fullName,
'mentions': mentions,
'user': user.toJson(),
};
}

View File

@ -84,8 +84,16 @@ class CustomizeCategoryState extends CoreProvier {
);
await service.put();
if (service.isSuccess) {
Navigator.of(context).pushNamed(Routes.notificationStatusStep,
arguments: {"toTimer": toTimer});
if (toTimer) {
Navigator.of(context).pushNamed(Routes.notificationTime,
arguments: {"fromFav": toTimer});
} else {
Navigator.of(context).pop();
ActionSheetUtils.showAlert(AlertData(
message: "تغییرات شما با موفقیت اعمال شد.",
aLertType: ALertType.success));
}
appState = AppState.idle;
await HomeWidgetRepository.fetchWidget();

View File

@ -153,11 +153,11 @@ class InfographyItem extends StatelessWidget {
Routes.mentions,
arguments: {
'id': id,
'type': 'infography',
'type': 'banner',
'title': title,
},
),
icon: DidvanIcons.chats_light,
icon: DidvanIcons.mention_icon,
),
const SizedBox(
width: 8.0,

View File

@ -1,3 +1,4 @@
import 'dart:math';
import 'dart:ui';
import 'package:didvan/config/design_config.dart';
@ -5,10 +6,10 @@ import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/providers/user.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/didvan/checkbox.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/scaffold.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
@ -17,7 +18,6 @@ import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../comments/comments_state.dart';
import '../widgets/user_mention.dart';
class Mentions extends StatefulWidget {
@ -54,13 +54,13 @@ class _MentionsState extends State<Mentions> {
void _onChange(MentionsState state, value) {
state.searchUsers = value;
state.getUsersMention();
state.getUsersMention(context.read<UserProvider>().user.id);
state.update();
}
@override
Widget build(BuildContext context) {
final commentsState = context.watch<MentionsState>();
final mentionsState = context.watch<MentionsState>();
final bottomViewInset = MediaQuery.of(context).viewInsets.bottom;
if (bottomViewInset == 0) {
@ -94,7 +94,7 @@ class _MentionsState extends State<Mentions> {
state: state,
itemPadding: const EdgeInsets.symmetric(vertical: 16),
childCount: state.comments.length,
placeholder: const _CommentPlaceholder(),
placeholder: const _MentionPlaceholder(),
centerEmptyState: _isPage,
enableEmptyState: state.comments.isEmpty,
emptyState: EmptyState(
@ -114,7 +114,7 @@ class _MentionsState extends State<Mentions> {
),
AnimatedVisibility(
duration: DesignConfig.lowAnimationDuration,
isVisible: commentsState.showUsersForMentionsLayout,
isVisible: mentionsState.showUsersForMentionsLayout,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
child: Container(
@ -131,7 +131,10 @@ class _MentionsState extends State<Mentions> {
Consumer<MentionsState>(
builder: (context, state, child) =>
SliverStateHandler<MentionsState>(
onRetry: state.getUsersMention,
onRetry: () {
state.getUsersMention(
context.read<UserProvider>().user.id);
},
state: state,
childCount: state.users.length,
placeholder: const _UsersPlaceholder(),
@ -159,7 +162,7 @@ class _MentionsState extends State<Mentions> {
textInputAction: TextInputAction.send,
style: Theme.of(context).textTheme.bodyMedium,
onEditingComplete: () {},
onChanged: (val) => _onChange(commentsState, val),
onChanged: (val) => _onChange(mentionsState, val),
decoration: InputDecoration(
icon: const Icon(DidvanIcons.search_regular),
border: InputBorder.none,
@ -177,8 +180,8 @@ class _MentionsState extends State<Mentions> {
DidvanIconButton(
icon: DidvanIcons.close_regular,
onPressed: () {
commentsState.showUsersForMentionsLayout = false;
commentsState.update();
mentionsState.showUsersForMentionsLayout = false;
mentionsState.update();
}),
],
),
@ -329,10 +332,17 @@ class _MessageBoxState extends State<_MessageBox> {
),
DidvanText(
state.mentionedUsers
.map((user) => user.name)
.join("، "),
.sublist(0,
min(state.mentionedUsers.length, 2))
.map((user) => user.name)
.join("، ") +
(state.mentionedUsers.length > 2
? " و ${state.mentionedUsers.length - 2} مورد دیگر"
: ""),
color: Theme.of(context).colorScheme.text,
style: Theme.of(context).textTheme.bodySmall,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
)
@ -378,7 +388,7 @@ class _MessageBoxState extends State<_MessageBox> {
Expanded(
child: TextField(
focusNode: widget.focusNode,
controller: state.commentTextFieldController,
controller: state.textFieldController,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.send,
style: Theme.of(context).textTheme.bodyMedium,
@ -399,7 +409,7 @@ class _MessageBoxState extends State<_MessageBox> {
state.showUsersForMentionsLayout = true;
state.update();
},
icon: DidvanIcons.user_shield_regular,
icon: DidvanIcons.mention_icon,
size: 24,
color: Theme.of(context).colorScheme.focusedBorder,
),
@ -411,17 +421,15 @@ class _MessageBoxState extends State<_MessageBox> {
}
void _onSend(MentionsState state) {
if (state.commentTextFieldController.text.replaceAll(' ', '').isNotEmpty) {
state.addComment();
state.commentTextFieldController.text = '';
state.searchUsers = '';
state.mentionedUsers.clear();
if (state.textFieldController.text.replaceAll(' ', '').isNotEmpty &&
state.mentionedUsers.isNotEmpty) {
state.addMention();
}
}
}
class _CommentPlaceholder extends StatelessWidget {
const _CommentPlaceholder({Key? key}) : super(key: key);
class _MentionPlaceholder extends StatelessWidget {
const _MentionPlaceholder({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -11,7 +11,7 @@ import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
class MentionsState extends CoreProvier {
TextEditingController commentTextFieldController = TextEditingController();
TextEditingController textFieldController = TextEditingController();
List<UsersMention> mentionedUsers = [];
String searchUsers = '';
int? commentId;
@ -20,7 +20,6 @@ class MentionsState extends CoreProvier {
bool showUsersForMentionsLayout = false;
bool showPrivates = false;
bool hideMentionedUser = false;
int _count = 0;
late String type;
final List<MentionData> comments = [];
@ -32,14 +31,15 @@ class MentionsState extends CoreProvier {
final service = RequestService(
RequestHelper.mention(itemId, type),
);
await service.httpGet();
if (service.isSuccess) {
comments.clear();
final messages = service.result['comments'];
final List<dynamic> messages = service.result['comments'];
for (var i = 0; i < messages.length; i++) {
comments.add(MentionData.fromJson(messages[i]));
_count++;
}
appState = AppState.idle;
@ -49,7 +49,7 @@ class MentionsState extends CoreProvier {
appState = AppState.failed;
}
Future<void> getUsersMention() async {
Future<void> getUsersMention(int id) async {
final service = RequestService(
RequestHelper.usersMentions(searchUsers),
);
@ -60,8 +60,16 @@ class MentionsState extends CoreProvier {
users.clear();
final List<dynamic> resUsers = service.data('users');
users
.addAll(resUsers.map((user) => UsersMention.fromJson(user)).toList());
users.addAll(mentionedUsers);
for (var i = 0; i < resUsers.length; i++) {
final user = UsersMention.fromJson(resUsers[i]);
if (!mentionedUsers.map((e) => e.id).contains(user.id) &&
user.id != id) {
users.add(user);
}
}
appState = AppState.idle;
return;
@ -69,7 +77,7 @@ class MentionsState extends CoreProvier {
appState = AppState.failed;
}
Future<void> addComment() async {
Future<void> addMention() async {
late List<MentionData> cList = comments;
final user = DesignConfig.context!.read<UserProvider>().user;
@ -77,8 +85,12 @@ class MentionsState extends CoreProvier {
0,
MentionData(
id: 0,
fullName: user.fullName,
text: commentTextFieldController.text,
user: UserOverview(
id: user.id,
fullName: user.fullName,
photo: user.photo,
),
text: textFieldController.text,
createdAt: DateTime.now().toString(),
mentions: mentionedUsers.map((user) => user.name).toList(),
),
@ -87,8 +99,8 @@ class MentionsState extends CoreProvier {
final body = {};
body.addAll({
'text': commentTextFieldController.text,
"mentions": mentionedUsers.map((user) => user.id.toString()).toList(),
'text': textFieldController.text,
"mentions": mentionedUsers.map((user) => user.id).toList(),
});
final service = RequestService(
@ -97,21 +109,28 @@ class MentionsState extends CoreProvier {
);
await service.post();
if (service.isSuccess) {
cList.firstWhere((comment) => comment.id == 0).id =
service.result['comment']['id'];
mentionedUsers = [];
mentionedUsers.clear();
users.clear();
searchUsers = '';
textFieldController.text = '';
showUsersForMentionsLayout = false;
update();
}
}
void deleteComment(int id, int status, int? rootId) async {
void deleteMention(int id) async {
final service = RequestService(RequestHelper.deleteComment(id));
await service.delete();
if (service.isSuccess) await getComments();
if (service.isSuccess) {
comments.removeWhere((element) => element.id == id);
}
notifyListeners();
}

View File

@ -1,7 +1,6 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/comment/reply.dart';
import 'package:didvan/models/mention/mention.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/providers/user.dart';
@ -95,10 +94,11 @@ class MentionState extends State<Mention> {
],
),
DidvanText(
comment.mention.toString(),
"اشاره به ${comment.mentions.join("، ").toString()}",
color: Theme.of(context).colorScheme.primary,
style: Theme.of(context).textTheme.titleSmall,
),
DidvanText(comment.text),
],
),
),
@ -114,14 +114,10 @@ class MentionState extends State<Mention> {
children: [
if (comment.user.id == context.read<UserProvider>().user.id)
MenuOption(
title: 'حذف نظر',
title: 'حذف فراخوانی',
color: Theme.of(context).colorScheme.secondary,
onTap: () {
state.deleteComment(
comment.id,
comment.status,
comment.runtimeType == Reply ? _comment.id : null,
);
state.deleteMention(comment.id);
ActionSheetUtils.pop();
},
icon: DidvanIcons.trash_solid,

View File

@ -42,7 +42,6 @@ class FloatingNavigationBar extends StatefulWidget {
class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
bool _isScrolled = false;
int _comments = 0;
int _mentions = 0;
@override
void didUpdateWidget(covariant FloatingNavigationBar oldWidget) {
@ -143,11 +142,6 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_mentions != 0)
DidvanText(
_mentions.toString(),
color: foregroundColor,
),
DidvanIconButton(
gestureSize: 32,
onPressed: () => Navigator.of(context).pushNamed(
@ -158,7 +152,7 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
'title': widget.item.title,
},
),
icon: DidvanIcons.chart_light,
icon: DidvanIcons.mention_icon,
),
],
),

View File

@ -122,7 +122,7 @@ class PodcastOverview extends StatelessWidget {
'title': podcast.title,
},
),
icon: DidvanIcons.chats_light,
icon: DidvanIcons.mention_icon,
),
const SizedBox(width: 8.0),
BookmarkButton(

View File

@ -105,7 +105,7 @@ class VideoOverview extends StatelessWidget {
'title': video.title,
},
),
icon: DidvanIcons.chats_light,
icon: DidvanIcons.mention_icon,
),
const SizedBox(width: 8.0),
BookmarkButton(

View File

@ -80,11 +80,19 @@ class _UserMentionState extends State<UserMention> {
DidvanIcons.avatar_light,
size: 40,
)
: SkeletonImage(
imageUrl: widget.user.photo.toString(),
height: 36,
width: 36,
borderRadius: BorderRadius.circular(360),
: SizedBox(
width: 40,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SkeletonImage(
imageUrl: widget.user.photo.toString(),
height: 32,
width: 32,
borderRadius: BorderRadius.circular(360),
),
],
),
),
const SizedBox(
width: 8,