1087 lines
50 KiB
Dart
1087 lines
50 KiB
Dart
// ignore_for_file: deprecated_member_use_from_same_package, use_build_context_synchronously
|
|
|
|
import 'package:cross_file/cross_file.dart';
|
|
import 'package:dio/dio.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hoshan/core/gen/assets.gen.dart';
|
|
import 'package:hoshan/core/services/api/dio_service.dart';
|
|
import 'package:hoshan/core/utils/date_time.dart';
|
|
import 'package:hoshan/core/utils/strings.dart';
|
|
import 'package:hoshan/data/model/empty_states_enum.dart';
|
|
import 'package:hoshan/data/model/forum_model.dart';
|
|
import 'package:hoshan/data/model/sort_by_model.dart';
|
|
import 'package:hoshan/data/model/tools_categories_model.dart';
|
|
import 'package:hoshan/data/repository/forum_repository.dart';
|
|
import 'package:hoshan/ui/screens/main/forum/cubit/category_cubit.dart';
|
|
import 'package:hoshan/ui/screens/main/forum/cubit/comments_cubit.dart';
|
|
import 'package:hoshan/ui/screens/main/forum/cubit/replies_cubit.dart';
|
|
import 'package:hoshan/ui/screens/splash/cubit/user_info_cubit.dart';
|
|
import 'package:hoshan/ui/theme/colors.dart';
|
|
import 'package:hoshan/ui/theme/cubit/theme_mode_cubit.dart';
|
|
import 'package:hoshan/ui/theme/text.dart';
|
|
import 'package:hoshan/ui/widgets/components/dialog/bottom_sheets.dart';
|
|
import 'package:hoshan/ui/widgets/components/image/network_image.dart';
|
|
import 'package:hoshan/ui/widgets/sections/empty/empty_states.dart';
|
|
import 'package:hoshan/ui/widgets/sections/loading/default_placeholder.dart';
|
|
|
|
class ForumScreen extends StatefulWidget {
|
|
const ForumScreen({super.key});
|
|
|
|
@override
|
|
State<ForumScreen> createState() => _ForumScreenState();
|
|
}
|
|
|
|
class _ForumScreenState extends State<ForumScreen>
|
|
with AutomaticKeepAliveClientMixin {
|
|
@override
|
|
bool get wantKeepAlive => true;
|
|
final ScrollController scrollController = ScrollController();
|
|
|
|
void loadCommentsFromCategory(int id) {
|
|
if (id == CommentsCubit.categoriesId) return;
|
|
if (context.read<CommentsCubit>().state is CommentsInitial) return;
|
|
context.read<CommentsCubit>().loadComments(cId: id, retry: true);
|
|
}
|
|
|
|
void loadCommentsFromSortBy(SortByModel sortBy) {
|
|
context.read<CommentsCubit>().loadComments(
|
|
cId: CommentsCubit.categoriesId, retry: true, orderBy: sortBy);
|
|
}
|
|
|
|
Future sendComment({required String message, XFile? file}) async {
|
|
try {
|
|
final comment = await ForumRepository.sendForum(
|
|
text: message,
|
|
categoryId: CommentsCubit.categoriesId,
|
|
image: file,
|
|
);
|
|
if (mounted) {
|
|
final userInfo = UserInfoCubit.userInfoModel;
|
|
final user = User(
|
|
id: userInfo.id,
|
|
image: userInfo.image,
|
|
name: userInfo.name,
|
|
username: userInfo.username);
|
|
|
|
context
|
|
.read<CommentsCubit>()
|
|
.addComment(comment: comment.copyWith(user: user));
|
|
|
|
context.pop();
|
|
}
|
|
} on DioException catch (e) {
|
|
if (kDebugMode) {
|
|
print('Dio Error is: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
Future sendReply(
|
|
{required BuildContext context,
|
|
required String message,
|
|
required int parentId,
|
|
required String repliedUserId,
|
|
XFile? file}) async {}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
scrollController.addListener(
|
|
() {
|
|
if (scrollController.position.pixels ==
|
|
scrollController.position.maxScrollExtent &&
|
|
context.read<CommentsCubit>().state is CommentsSuccess) {
|
|
context
|
|
.read<CommentsCubit>()
|
|
.loadComments(cId: CommentsCubit.categoriesId);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
super.build(context);
|
|
return Scaffold(
|
|
floatingActionButton: FloatingActionButton.small(
|
|
heroTag: 'add-comment-fb',
|
|
onPressed: () async {
|
|
await BottomSheetHandler(context).showAddComment(
|
|
onSend: (message, file) async =>
|
|
sendComment(message: message, file: file),
|
|
);
|
|
},
|
|
shape: const CircleBorder(),
|
|
backgroundColor: AppColors.primaryColor.defaultShade,
|
|
child: const Icon(
|
|
CupertinoIcons.add,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
body: RefreshIndicator(
|
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
color: Theme.of(context).colorScheme.primary,
|
|
onRefresh: () async {
|
|
// context.read<CategoryCubit>().getAllCategorie();
|
|
context
|
|
.read<CommentsCubit>()
|
|
.loadComments(cId: CommentsCubit.categoriesId, retry: true);
|
|
scrollController.jumpTo(0);
|
|
},
|
|
child: SingleChildScrollView(
|
|
controller: scrollController,
|
|
physics: context.watch<CommentsCubit>().state is CommentsInitial
|
|
? const NeverScrollableScrollPhysics()
|
|
: const BouncingScrollPhysics(
|
|
parent: AlwaysScrollableScrollPhysics()),
|
|
child: Column(
|
|
children: [
|
|
BlocBuilder<CategoryCubit, CategoryState>(
|
|
builder: (context, state) {
|
|
if (state is CategoryLoading) {
|
|
return categoriesPlaceholder();
|
|
}
|
|
if (state is CategorySuccess) {
|
|
final categories = state.categories;
|
|
List<Categories> oddCategories = [];
|
|
List<Categories> evenCategories = [];
|
|
for (int i = 0; i < categories.length; i++) {
|
|
if (i % 2 == 0) {
|
|
evenCategories.add(categories[i]);
|
|
} else {
|
|
oddCategories.add(categories[i]);
|
|
}
|
|
}
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
child: Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Stack(
|
|
children: [
|
|
SizedBox(
|
|
width: MediaQuery.sizeOf(context).width,
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
padding:
|
|
const EdgeInsets.fromLTRB(120, 0, 16, 0),
|
|
physics: const BouncingScrollPhysics(),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (evenCategories.isNotEmpty)
|
|
SizedBox(
|
|
height: 36,
|
|
child: Row(
|
|
children: [
|
|
...List.generate(
|
|
evenCategories.length,
|
|
(index) {
|
|
final cat =
|
|
evenCategories[index];
|
|
return categoryContainer(cat);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
if (oddCategories.isNotEmpty)
|
|
SizedBox(
|
|
height: 36,
|
|
child: Row(
|
|
children: [
|
|
const SizedBox(
|
|
width: 16,
|
|
),
|
|
...List.generate(
|
|
oddCategories.length,
|
|
(index) {
|
|
final cat =
|
|
oddCategories[index];
|
|
return categoryContainer(cat);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (context.watch<CommentsCubit>().state
|
|
is CommentsSuccess ||
|
|
context.watch<CommentsCubit>().state
|
|
is CommentsFail)
|
|
Positioned(
|
|
left: 0,
|
|
bottom: 0,
|
|
top: 0,
|
|
child: Container(
|
|
padding:
|
|
const EdgeInsets.symmetric(horizontal: 4),
|
|
decoration: BoxDecoration(
|
|
boxShadow: [
|
|
BoxShadow(
|
|
blurRadius: 16,
|
|
color: Theme.of(context)
|
|
.scaffoldBackgroundColor,
|
|
spreadRadius: 10)
|
|
],
|
|
color: Theme.of(context)
|
|
.scaffoldBackgroundColor,
|
|
gradient: RadialGradient(colors: [
|
|
Theme.of(context)
|
|
.scaffoldBackgroundColor,
|
|
Theme.of(context)
|
|
.scaffoldBackgroundColor
|
|
.withValues(alpha: 0.7),
|
|
Theme.of(context)
|
|
.scaffoldBackgroundColor
|
|
.withValues(alpha: 0.6),
|
|
])),
|
|
child: GestureDetector(
|
|
onTap: () =>
|
|
BottomSheetHandler(context).showSortBy(
|
|
initailValue: CommentsCubit.sortByModel,
|
|
items: [
|
|
SortByModel(
|
|
text: 'جدیدترین', value: 'date'),
|
|
SortByModel(
|
|
text: 'پربحثترینها',
|
|
value: 'replies'),
|
|
],
|
|
onSelected: (item) =>
|
|
loadCommentsFromSortBy(item),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16),
|
|
child: Icon(
|
|
CupertinoIcons.sort_down,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.onSurface,
|
|
)),
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
return const SizedBox.shrink();
|
|
},
|
|
),
|
|
const SizedBox(
|
|
height: 12,
|
|
),
|
|
BlocBuilder<CommentsCubit, CommentsState>(
|
|
builder: (context, state) {
|
|
if (state is CommentsInitial) {
|
|
return ListView.builder(
|
|
itemCount: 20,
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemBuilder: (context, index) {
|
|
return commentContainerPlaceholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
if (state.comments.isEmpty) {
|
|
return Center(
|
|
child: EmptyStates.getEmptyState(
|
|
status: EmptyStatesEnum.messages));
|
|
}
|
|
|
|
return Column(
|
|
children: [
|
|
ListView.builder(
|
|
itemCount: state.comments.length,
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemBuilder: (context, index) {
|
|
final comment = state.comments[index];
|
|
|
|
return BlocProvider<RepliesCubit>(
|
|
create: (context) => RepliesCubit(),
|
|
child: Builder(builder: (context) {
|
|
return Column(
|
|
children: [
|
|
commentContainer(context, comment),
|
|
Padding(
|
|
padding: const EdgeInsets.only(right: 24),
|
|
child:
|
|
BlocBuilder<RepliesCubit, RepliesState>(
|
|
builder: (context, state) {
|
|
return Column(
|
|
children: [
|
|
if (state.replies.isNotEmpty)
|
|
ListView.builder(
|
|
physics:
|
|
const NeverScrollableScrollPhysics(),
|
|
itemCount: state.replies.length,
|
|
shrinkWrap: true,
|
|
itemBuilder: (context, index) {
|
|
final reply =
|
|
state.replies[index];
|
|
return commentContainer(
|
|
context,
|
|
reply,
|
|
parrentComment: comment,
|
|
);
|
|
},
|
|
),
|
|
BlocBuilder<RepliesCubit,
|
|
RepliesState>(
|
|
builder: (context, state) {
|
|
return Column(
|
|
children: [
|
|
if (state.lastPage !=
|
|
null &&
|
|
state.page >
|
|
state.lastPage!)
|
|
Padding(
|
|
padding:
|
|
const EdgeInsets
|
|
.symmetric(
|
|
vertical: 12.0),
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
if (comment.replies !=
|
|
null &&
|
|
comment.replies! >
|
|
0) {
|
|
if (state.lastPage !=
|
|
null &&
|
|
state.page >
|
|
state
|
|
.lastPage!) {
|
|
final lastPosition =
|
|
scrollController
|
|
.position;
|
|
context
|
|
.read<
|
|
RepliesCubit>()
|
|
.clear();
|
|
|
|
scrollController.jumpTo(scrollController
|
|
.position
|
|
.pixels -
|
|
lastPosition
|
|
.pixels);
|
|
} else {
|
|
context
|
|
.read<
|
|
RepliesCubit>()
|
|
.loadReplies(
|
|
comment:
|
|
comment);
|
|
}
|
|
}
|
|
},
|
|
child: Row(
|
|
children: [
|
|
const Expanded(
|
|
flex: 6,
|
|
child:
|
|
Divider()),
|
|
if (comment.replies !=
|
|
null &&
|
|
comment.replies! >
|
|
0)
|
|
Padding(
|
|
padding: const EdgeInsets
|
|
.symmetric(
|
|
horizontal:
|
|
8.0),
|
|
child: Text(
|
|
'پنهان کردن پاسخها',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: AppColors
|
|
.gray[context
|
|
.read<ThemeModeCubit>()
|
|
.isDark()
|
|
? 600
|
|
: 900]),
|
|
),
|
|
),
|
|
const Expanded(
|
|
child:
|
|
Divider()),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}),
|
|
);
|
|
},
|
|
),
|
|
if (state is CommentsLoading)
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
|
child: LinearProgressIndicator(
|
|
color: AppColors.primaryColor.defaultShade,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 36,
|
|
)
|
|
],
|
|
);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
GestureDetector categoryContainer(Categories cat) {
|
|
return GestureDetector(
|
|
onTap: () => loadCommentsFromCategory(cat.id!),
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
|
constraints: const BoxConstraints(minWidth: 100),
|
|
alignment: Alignment.center,
|
|
decoration: BoxDecoration(
|
|
color: CommentsCubit.categoriesId == cat.id
|
|
? AppColors.primaryColor[
|
|
context.read<ThemeModeCubit>().isDark() ? 500 : 50]
|
|
: AppColors
|
|
.gray[context.read<ThemeModeCubit>().isDark() ? 900 : 400],
|
|
borderRadius: BorderRadius.circular(360)),
|
|
child: Text(
|
|
cat.name ?? '',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: context.read<ThemeModeCubit>().isDark()
|
|
? Colors.white
|
|
: CommentsCubit.categoriesId == cat.id
|
|
? AppColors.primaryColor.defaultShade
|
|
: AppColors.black[300]),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget commentContainer(BuildContext context, Comment comment,
|
|
{final Comment? parrentComment}) {
|
|
final daysAgo = DateTimeUtils.getDaysBetweenNowAnd(comment.createdAt!);
|
|
|
|
return Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: parrentComment != null
|
|
? Theme.of(context).colorScheme.surface
|
|
: context.read<ThemeModeCubit>().isDark()
|
|
? AppColors.black[900]
|
|
: AppColors.primaryColor[50],
|
|
borderRadius: BorderRadius.circular(16)),
|
|
child: Column(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Expanded(
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
comment.createdAt != null
|
|
? Row(
|
|
children: [
|
|
Assets.icon.outline.clock.svg(
|
|
width: 20,
|
|
height: 20,
|
|
color: AppColors.gray[context
|
|
.read<ThemeModeCubit>()
|
|
.isDark()
|
|
? 600
|
|
: 900]),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
Text(
|
|
daysAgo == 0
|
|
? 'امروز'
|
|
: ('$daysAgo روز پیش'),
|
|
style: AppTextStyles.body5.copyWith(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.onSurface),
|
|
textDirection: TextDirection.rtl,
|
|
)
|
|
],
|
|
)
|
|
: const SizedBox.shrink(),
|
|
Row(
|
|
children: [
|
|
Text(
|
|
comment.user?.username ?? '',
|
|
style: AppTextStyles.body4.copyWith(
|
|
fontWeight: FontWeight.bold,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.onSurface),
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
SizedBox(
|
|
width: MediaQuery.sizeOf(context).width,
|
|
child: Text(
|
|
comment.text ?? '',
|
|
style: AppTextStyles.body3.copyWith(
|
|
color: Theme.of(context).colorScheme.onSurface),
|
|
textDirection: comment.text != null &&
|
|
comment.text!.startsWithEnglish()
|
|
? TextDirection.ltr
|
|
: TextDirection.rtl,
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
if (comment.image != null)
|
|
Column(
|
|
children: [
|
|
Container(
|
|
margin: const EdgeInsets.symmetric(vertical: 12),
|
|
constraints: BoxConstraints(
|
|
maxHeight:
|
|
MediaQuery.sizeOf(context).height * 0.2),
|
|
alignment: Alignment.centerRight,
|
|
child: AspectRatio(
|
|
aspectRatio: 16 / 9,
|
|
child: ImageNetwork(
|
|
url: DioService.baseURL + comment.image!,
|
|
radius: 16,
|
|
showHero: true,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
],
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () {
|
|
BottomSheetHandler(context)
|
|
.showReportOptions();
|
|
},
|
|
child: commentBtn(
|
|
icon: Assets.icon.outline.flag2,
|
|
text: 'گزارش')),
|
|
const SizedBox(
|
|
width: 12,
|
|
),
|
|
// BlocProvider<CommentLikeCubit>(
|
|
// create: (context) =>
|
|
// CommentLikeCubit()..getLike(comment.userFeedback),
|
|
// child: BlocConsumer<CommentLikeCubit, CommentLikeState>(
|
|
// listener: (context, state) {
|
|
// int likes = comment.likes!;
|
|
// int disLikes = comment.dislikes!;
|
|
// if (state.like != null) {
|
|
// likes = likes + state.like!;
|
|
// }
|
|
// if (state.disLike != null) {
|
|
// disLikes = disLikes + state.disLike!;
|
|
// }
|
|
// context.read<CommentsCubit>().changeComment(
|
|
// newComment: comment.copyWith(
|
|
// likes: likes,
|
|
// dislikes: disLikes,
|
|
// userFeedback: state is CommentLiked
|
|
// ? 1
|
|
// : state is CommentDisLiked
|
|
// ? 0
|
|
// : -1));
|
|
// },
|
|
// builder: (context, state) {
|
|
// return Row(
|
|
// children: [
|
|
// DefaultPlaceHolder(
|
|
// enabled: state is CommentLikeLoading,
|
|
// child: GestureDetector(
|
|
// onTap: () => context
|
|
// .read<CommentLikeCubit>()
|
|
// .setLiked(
|
|
// id: comment.id!,
|
|
// status:
|
|
// state is CommentLiked ? -1 : 1),
|
|
// child: commentBtn(
|
|
// color: state is CommentLiked
|
|
// ? AppColors.green.defaultShade
|
|
// : null,
|
|
// icon: state is CommentLiked
|
|
// ? Assets.icon.bold.like
|
|
// : Assets.icon.outline.like,
|
|
// text: comment.likes?.toString() ?? '0'),
|
|
// ),
|
|
// ),
|
|
// const SizedBox(
|
|
// width: 12,
|
|
// ),
|
|
// DefaultPlaceHolder(
|
|
// enabled: state is CommentLikeLoading,
|
|
// child: GestureDetector(
|
|
// onTap: () => context
|
|
// .read<CommentLikeCubit>()
|
|
// .setLiked(
|
|
// id: comment.id!,
|
|
// status: state is CommentDisLiked
|
|
// ? -1
|
|
// : 0),
|
|
// child: commentBtn(
|
|
// color: state is CommentDisLiked
|
|
// ? AppColors.red.defaultShade
|
|
// : null,
|
|
// icon: state is CommentDisLiked
|
|
// ? Assets.icon.bold.dislike
|
|
// : Assets.icon.outline.dislike,
|
|
// text:
|
|
// comment.dislikes?.toString() ?? '0'),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// );
|
|
// },
|
|
// ),
|
|
// ),
|
|
// const SizedBox(
|
|
// width: 12,
|
|
// ),
|
|
if (comment.replies != null &&
|
|
parrentComment == null &&
|
|
comment.replies != 0)
|
|
commentBtn(
|
|
icon: Assets.icon.outline.messageText,
|
|
text: comment.replies!.toString()),
|
|
],
|
|
),
|
|
GestureDetector(
|
|
onTap: () async {
|
|
await BottomSheetHandler(context).showAddComment(
|
|
comment: comment,
|
|
onSend: (message, file) async {
|
|
try {
|
|
final commentRes =
|
|
await ForumRepository.sendForum(
|
|
text: message,
|
|
categoryId:
|
|
CommentsCubit.categoriesId,
|
|
image: file,
|
|
parentId: parrentComment?.id ??
|
|
comment.id,
|
|
repliedUserId:
|
|
parrentComment?.user!.id ??
|
|
comment.user!.id);
|
|
if (mounted) {
|
|
final userInfo =
|
|
UserInfoCubit.userInfoModel;
|
|
final user = User(
|
|
id: userInfo.id,
|
|
image: userInfo.image,
|
|
name: userInfo.name,
|
|
username: userInfo.username);
|
|
context.read<RepliesCubit>().addReply(
|
|
parent: comment,
|
|
comment:
|
|
commentRes.copyWith(user: user));
|
|
context.read<CommentsCubit>().addReplies(
|
|
commentId: parrentComment?.id! ??
|
|
comment.id!);
|
|
|
|
context.pop();
|
|
}
|
|
} on DioException catch (e) {
|
|
if (kDebugMode) {
|
|
print('Dio Error is: $e');
|
|
}
|
|
}
|
|
},
|
|
);
|
|
},
|
|
child: Text('پاسخ دادن',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: Theme.of(context).colorScheme.primary,
|
|
)),
|
|
)
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 12,
|
|
),
|
|
ImageNetwork(
|
|
url: comment.user != null && comment.user!.image != null
|
|
? DioService.baseURL + comment.user!.image!
|
|
: 'https://placehold.co/600x400',
|
|
width: 40,
|
|
height: 40,
|
|
radius: 360,
|
|
)
|
|
],
|
|
),
|
|
),
|
|
if (comment.replies != null && comment.replies! > 0)
|
|
BlocBuilder<RepliesCubit, RepliesState>(
|
|
builder: (context, state) {
|
|
if (state.lastPage != null && state.page > state.lastPage!) {
|
|
return const SizedBox();
|
|
}
|
|
return Column(
|
|
children: [
|
|
state is RepliesLoading
|
|
? Padding(
|
|
padding: const EdgeInsets.only(top: 24.0),
|
|
child: SpinKitThreeBounce(
|
|
color: AppColors.primaryColor.defaultShade,
|
|
size: 32,
|
|
),
|
|
)
|
|
: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
if (comment.replies != null &&
|
|
comment.replies! > 0) {
|
|
if (state.lastPage != null &&
|
|
state.page > state.lastPage!) {
|
|
final lastPosition =
|
|
scrollController.position;
|
|
context.read<RepliesCubit>().clear();
|
|
|
|
scrollController.jumpTo(
|
|
scrollController.position.pixels -
|
|
lastPosition.pixels);
|
|
} else {
|
|
context
|
|
.read<RepliesCubit>()
|
|
.loadReplies(comment: comment);
|
|
}
|
|
}
|
|
},
|
|
child: Row(
|
|
children: [
|
|
const Expanded(flex: 6, child: Divider()),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8.0),
|
|
child: Text(
|
|
'مشاهده پاسخها',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: AppColors.gray[context
|
|
.read<ThemeModeCubit>()
|
|
.isDark()
|
|
? 600
|
|
: 900]),
|
|
),
|
|
),
|
|
const Expanded(child: Divider()),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Padding categoriesPlaceholder() {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
child: Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
child: Column(
|
|
children: [
|
|
SizedBox(
|
|
height: 36,
|
|
child: Row(
|
|
children: [
|
|
...List.generate(
|
|
20,
|
|
(index) {
|
|
return DefaultPlaceHolder(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
|
constraints: const BoxConstraints(minWidth: 100),
|
|
alignment: Alignment.center,
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).colorScheme.surface,
|
|
borderRadius: BorderRadius.circular(360)),
|
|
child: Text('$index'),
|
|
),
|
|
);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
SizedBox(
|
|
height: 36,
|
|
child: Row(
|
|
children: [
|
|
const SizedBox(
|
|
width: 24,
|
|
),
|
|
...List.generate(
|
|
20,
|
|
(index) {
|
|
return DefaultPlaceHolder(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
|
constraints: const BoxConstraints(minWidth: 100),
|
|
alignment: Alignment.center,
|
|
decoration: BoxDecoration(
|
|
color: AppColors.gray[400],
|
|
borderRadius: BorderRadius.circular(360)),
|
|
child: Text('$index'),
|
|
),
|
|
);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Container commentContainerPlaceholder() {
|
|
return Container(
|
|
padding: const EdgeInsets.all(24),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Expanded(
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
DefaultPlaceHolder(
|
|
child: Assets.icon.outline.clock.svg(
|
|
width: 20,
|
|
height: 20,
|
|
color: AppColors.gray[900]),
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
DefaultPlaceHolder(
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(8),
|
|
color: Colors.white,
|
|
),
|
|
child: Text(
|
|
'time ago',
|
|
style: AppTextStyles.body5,
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
Row(
|
|
children: [
|
|
DefaultPlaceHolder(
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(8),
|
|
color: Colors.white,
|
|
),
|
|
child: Text(
|
|
'this is a username',
|
|
style: AppTextStyles.body4
|
|
.copyWith(fontWeight: FontWeight.bold),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
DefaultPlaceHolder(
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(8),
|
|
color: Colors.white,
|
|
),
|
|
child: Text(
|
|
'باتهای تولید عکس میتونه تصاویری با سبکهای مختلف مثل نقاشی، سهبعدی یا رئال تولید کنه؟🎨🎨🎨',
|
|
style: AppTextStyles.body3,
|
|
textDirection: TextDirection.rtl,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
Row(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
DefaultPlaceHolder(
|
|
child: commentBtn(
|
|
icon: Assets.icon.outline.flag2,
|
|
text: 'گزارش'),
|
|
),
|
|
const SizedBox(
|
|
width: 12,
|
|
),
|
|
DefaultPlaceHolder(
|
|
child: commentBtn(
|
|
icon: Assets.icon.outline.like, text: '---'),
|
|
),
|
|
const SizedBox(
|
|
width: 12,
|
|
),
|
|
DefaultPlaceHolder(
|
|
child: commentBtn(
|
|
icon: Assets.icon.outline.dislike,
|
|
text: '---'),
|
|
),
|
|
const SizedBox(
|
|
width: 12,
|
|
),
|
|
DefaultPlaceHolder(
|
|
child: commentBtn(
|
|
icon: Assets.icon.outline.messageText,
|
|
text: '---'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
DefaultPlaceHolder(
|
|
child: Text('پاسخ دادن',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: AppColors.primaryColor.defaultShade,
|
|
)),
|
|
)
|
|
],
|
|
)
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 12,
|
|
),
|
|
const DefaultPlaceHolder(
|
|
child: ImageNetwork(
|
|
url: 'https://placehold.co/600x400',
|
|
width: 40,
|
|
height: 40,
|
|
radius: 360,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Row commentBtn(
|
|
{required final SvgGenImage icon,
|
|
final String? text,
|
|
final Color? color}) {
|
|
return Row(
|
|
children: [
|
|
icon.svg(
|
|
width: 18,
|
|
height: 18,
|
|
color: color ??
|
|
AppColors
|
|
.gray[context.read<ThemeModeCubit>().isDark() ? 600 : 900]),
|
|
if (text != null)
|
|
Row(
|
|
children: [
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Text(
|
|
text,
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: AppColors.gray[
|
|
context.read<ThemeModeCubit>().isDark() ? 600 : 900]),
|
|
),
|
|
],
|
|
)
|
|
],
|
|
);
|
|
}
|
|
}
|