elCaribe app - customization and branding
This commit is contained in:
275
news-app/lib/ui/screens/authorDetailsScreen.dart
Normal file
275
news-app/lib/ui/screens/authorDetailsScreen.dart
Normal file
@@ -0,0 +1,275 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:news/app/routes.dart';
|
||||
import 'package:news/cubits/Author/authorNewsCubit.dart';
|
||||
import 'package:news/cubits/NewsByIdCubit.dart';
|
||||
import 'package:news/cubits/appLocalizationCubit.dart';
|
||||
import 'package:news/data/models/NewsModel.dart';
|
||||
import 'package:news/ui/screens/auth/Widgets/svgPictureWidget.dart';
|
||||
import 'package:news/ui/styles/colors.dart';
|
||||
import 'package:news/ui/widgets/customBackBtn.dart';
|
||||
import 'package:news/ui/widgets/customTextLabel.dart';
|
||||
import 'package:news/ui/widgets/errorContainerWidget.dart';
|
||||
import 'package:news/ui/widgets/networkImage.dart';
|
||||
import 'package:news/utils/constant.dart';
|
||||
import 'package:news/utils/uiUtils.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class AuthorDetailsScreen extends StatefulWidget {
|
||||
final String authorId;
|
||||
const AuthorDetailsScreen({super.key, required this.authorId});
|
||||
|
||||
@override
|
||||
State<AuthorDetailsScreen> createState() => _AuthorDetailsScreenState();
|
||||
|
||||
static Route route(RouteSettings routeSettings) {
|
||||
final arguments = routeSettings.arguments as Map<String, dynamic>;
|
||||
return CupertinoPageRoute(builder: (_) => AuthorDetailsScreen(authorId: arguments['authorId']));
|
||||
}
|
||||
}
|
||||
|
||||
class _AuthorDetailsScreenState extends State<AuthorDetailsScreen> {
|
||||
AuthorLayoutType layout = AuthorLayoutType.list;
|
||||
double borderRadius = 10;
|
||||
late NewsModel newsData;
|
||||
String totalViews = "0", totalLikes = "0";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
getNewsByAuthor();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void getNewsByAuthor() {
|
||||
context.read<AuthorNewsCubit>().getAuthorNews(authorId: widget.authorId);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const CustomTextLabel(text: 'authorLbl'),
|
||||
leading: CustomBackButton(),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(3.0),
|
||||
child: Container(
|
||||
margin: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(border: Border.all(color: UiUtils.getColorScheme(context).outline), borderRadius: BorderRadius.circular(5)),
|
||||
child: GestureDetector(
|
||||
child: Icon(layout == AuthorLayoutType.list ? Icons.grid_view : Icons.view_list, size: 25),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
layout = layout == AuthorLayoutType.list ? AuthorLayoutType.grid : AuthorLayoutType.list;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: BlocBuilder<AuthorNewsCubit, AuthorNewsState>(
|
||||
builder: (context, state) {
|
||||
if (state is AuthorNewsFetchSuccess) {
|
||||
return Column(
|
||||
children: [
|
||||
authorHeader(state: state),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(child: layout == AuthorLayoutType.list ? authorNewsListView(state: state) : authorNewsGridView(state: state)),
|
||||
],
|
||||
);
|
||||
} else if (state is AuthorNewsFetchFailed) {
|
||||
return ErrorContainerWidget(errorMsg: state.errorMessage, onRetry: getNewsByAuthor);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget authorHeader({required AuthorNewsFetchSuccess state}) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: UiUtils.getColorScheme(context).surface,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
// author image
|
||||
ClipRRect(borderRadius: BorderRadius.circular(6), child: CustomNetworkImage(networkImageUrl: state.authorData.profile ?? "")),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CustomTextLabel(text: state.authorData.name ?? "", textStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.w600)),
|
||||
SizedBox(height: 6),
|
||||
CustomTextLabel(text: state.authorData.authorData!.bio ?? "", textStyle: TextStyle(fontSize: 13)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
children: [
|
||||
CustomTextLabel(text: 'followLbl'),
|
||||
SizedBox(width: 6),
|
||||
(state.authorData.authorData != null)
|
||||
? Row(spacing: 6.5, children: [
|
||||
showSocialMediaLinks(socialMediaLink: state.authorData.authorData!.telegramLink ?? "", socialMediaIconName: "telegram"),
|
||||
showSocialMediaLinks(socialMediaLink: state.authorData.authorData!.facebookLink ?? "", socialMediaIconName: "facebook"),
|
||||
showSocialMediaLinks(socialMediaLink: state.authorData.authorData!.whatsappLink ?? "", socialMediaIconName: "whatsapp"),
|
||||
showSocialMediaLinks(socialMediaLink: state.authorData.authorData!.linkedinLink ?? "", socialMediaIconName: "linkedin"),
|
||||
])
|
||||
: SizedBox.shrink()
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget showSocialMediaLinks({required String socialMediaLink, required String socialMediaIconName}) {
|
||||
return Container(
|
||||
height: 30,
|
||||
width: 30,
|
||||
padding: EdgeInsets.all(3),
|
||||
decoration: BoxDecoration(shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(7), color: UiUtils.getColorScheme(context).outline.withOpacity(0.2)),
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
if (await canLaunchUrl(Uri.parse(socialMediaLink))) {
|
||||
await launchUrl(Uri.parse(socialMediaLink), mode: LaunchMode.externalApplication);
|
||||
}
|
||||
},
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
child: SvgPictureWidget(
|
||||
assetName: socialMediaIconName,
|
||||
height: 11,
|
||||
width: 11,
|
||||
fit: BoxFit.contain,
|
||||
assetColor: ColorFilter.mode(UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.7), BlendMode.srcIn)),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget authorNewsListView({required AuthorNewsFetchSuccess state}) {
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: state.AuthorNewsList.length, itemBuilder: (BuildContext, index) => newsListTile(newsItem: state.AuthorNewsList[index]));
|
||||
}
|
||||
|
||||
Widget newsListTile({required NewsModel newsItem}) {
|
||||
return GestureDetector(
|
||||
onTap: () => redirectToNewsDetailsScreen(newsItem: newsItem),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
decoration: BoxDecoration(color: UiUtils.getColorScheme(context).surface, borderRadius: BorderRadius.circular(12)),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(borderRadius), bottomLeft: Radius.circular(borderRadius)),
|
||||
child: CustomNetworkImage(networkImageUrl: newsItem.image!, width: 110, height: 110, fit: BoxFit.cover)),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CustomTextLabel(text: newsItem.title ?? "", maxLines: 2, overflow: TextOverflow.ellipsis, textStyle: TextStyle(fontSize: 15, fontWeight: FontWeight.w600)),
|
||||
SizedBox(height: 6),
|
||||
CustomTextLabel(text: newsItem.desc ?? "", maxLines: 3, overflow: TextOverflow.ellipsis, textStyle: TextStyle(fontSize: 13)),
|
||||
SizedBox(height: 6),
|
||||
Divider(),
|
||||
SizedBox(height: 3),
|
||||
Row(
|
||||
children: [
|
||||
CustomTextLabel(
|
||||
text: UiUtils.convertToAgo(context, DateTime.parse(newsItem.publishDate ?? newsItem.date!), 0)!,
|
||||
textStyle: TextStyle(fontSize: 12, color: UiUtils.getColorScheme(context).outline)),
|
||||
Spacer(),
|
||||
showViewsAndLikes(newsId: newsItem.id ?? "0", totalViews: newsItem.totalViews ?? "0", totalLikes: newsItem.totalLikes ?? "0")
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget showViewsAndLikes({required String newsId, required String totalViews, required String totalLikes}) {
|
||||
return FutureBuilder(
|
||||
future: context.read<NewsByIdCubit>().getNewsById(newsId: newsId, langId: context.read<AppLocalizationCubit>().state.id),
|
||||
builder: (context, snapshot) {
|
||||
final updated = snapshot.data![0];
|
||||
totalViews = updated.totalViews ?? "0";
|
||||
totalLikes = updated.totalLikes ?? "0";
|
||||
return Row(
|
||||
spacing: 15,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 5,
|
||||
children: [Icon(Icons.remove_red_eye_rounded, size: 10), CustomTextLabel(text: totalViews, textStyle: TextStyle(fontSize: 12))],
|
||||
),
|
||||
Row(
|
||||
spacing: 5,
|
||||
children: [Icon(Icons.thumb_up_alt_outlined, size: 10), CustomTextLabel(text: totalLikes, textStyle: TextStyle(fontSize: 12))],
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget authorNewsGridView({required AuthorNewsFetchSuccess state}) {
|
||||
return GridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
itemCount: state.AuthorNewsList.length,
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, mainAxisSpacing: 16, crossAxisSpacing: 16, childAspectRatio: 0.65),
|
||||
itemBuilder: (BuildContext, index) {
|
||||
return newsGridTile(newsItem: state.AuthorNewsList[index]);
|
||||
});
|
||||
}
|
||||
|
||||
Widget newsGridTile({required NewsModel newsItem}) {
|
||||
return GestureDetector(
|
||||
onTap: () => redirectToNewsDetailsScreen(newsItem: newsItem),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(borderRadius), color: UiUtils.getColorScheme(context).surface, boxShadow: const [BoxShadow(blurRadius: 5, spreadRadius: 1, color: dividerColor)]),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ClipRRect(borderRadius: BorderRadius.circular(8), child: CustomNetworkImage(networkImageUrl: newsItem.image!, height: 120, width: double.infinity, fit: BoxFit.cover)),
|
||||
const SizedBox(height: 8),
|
||||
CustomTextLabel(
|
||||
text: UiUtils.convertToAgo(context, DateTime.parse(newsItem.publishDate ?? newsItem.date!), 0)!, textStyle: TextStyle(color: UiUtils.getColorScheme(context).outline, fontSize: 11)),
|
||||
const SizedBox(height: 4),
|
||||
CustomTextLabel(text: newsItem.title ?? "", maxLines: 2, overflow: TextOverflow.ellipsis, textStyle: TextStyle(fontWeight: FontWeight.w600, fontSize: 14)),
|
||||
const SizedBox(height: 4),
|
||||
CustomTextLabel(text: newsItem.desc ?? "", maxLines: 2, overflow: TextOverflow.ellipsis, textStyle: TextStyle(fontSize: 12)),
|
||||
Divider(),
|
||||
showViewsAndLikes(newsId: newsItem.id ?? "0", totalViews: newsItem.totalViews ?? "0", totalLikes: newsItem.totalLikes ?? "0")
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void redirectToNewsDetailsScreen({required NewsModel newsItem}) {
|
||||
Navigator.of(context).pushNamed(Routes.newsDetails, arguments: {"model": newsItem, "isFromBreak": false, "fromShowMore": false});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user