Adding TopNews
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
class News {
|
||||
final String uid;
|
||||
final String title;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
final String previewUrl;
|
||||
final String sourceUrl;
|
||||
final DateTime publishedAt;
|
||||
final String fullPostUrl;
|
||||
|
||||
News({
|
||||
this.uid,
|
||||
this.title,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.previewUrl,
|
||||
this.sourceUrl,
|
||||
this.publishedAt,
|
||||
this.fullPostUrl,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
final title = "Epoxy is an Android library for building complex screens in a RecyclerView. It abstracts the boilerplate of view holders, item types, item ids, span counts, and more, in order to simplify building screens with multiple view types. Additionally, Epoxy adds support for saving view state and automatic diffing of item changes.";
|
||||
final sourceUrl = "https://firebasestorage.googleapis.com/v0/b/discover-backend.appspot.com/o/providers%2Fcm%2Fsource.png?alt=media&token=c05913ac-07e0-4402-9fc8-2fc6cc484440";
|
||||
final url = "https://s.france24.com/media/display/be59c500-68ea-11eb-aefa-005056a98db9/w:1280/p:16x9/e8bbac6ad2d9bac2d5d6410a5394a177fc978f78.webp";
|
||||
final newsTest = [
|
||||
News(uid: "1", title: title, previewUrl: url, sourceUrl: sourceUrl),
|
||||
News(uid: "2", title: title, previewUrl: url, sourceUrl: sourceUrl),
|
||||
News(uid: "3", title: title, previewUrl: url, sourceUrl: sourceUrl),
|
||||
News(uid: "4", title: title, previewUrl: url, sourceUrl: sourceUrl),
|
||||
News(uid: "5", title: title, previewUrl: url, sourceUrl: sourceUrl),
|
||||
News(uid: "6", title: title, previewUrl: url, sourceUrl: sourceUrl),
|
||||
News(uid: "7", title: title, previewUrl: url, sourceUrl: sourceUrl),
|
||||
];
|
||||
@@ -32,6 +32,7 @@ class ItemMagLarge extends StatelessWidget {
|
||||
height: 235,
|
||||
width: 168,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
shape: BoxShape.rectangle,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(5),
|
||||
|
||||
@@ -49,6 +49,7 @@ class ItemMagRow extends StatelessWidget {
|
||||
rowTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
|
||||
@@ -31,6 +31,7 @@ class ItemMagRowNewest extends StatelessWidget {
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22,
|
||||
),
|
||||
),
|
||||
@@ -62,7 +63,7 @@ class ItemMagRowNewest extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -18,6 +18,7 @@ class ItemMagSmall extends StatelessWidget {
|
||||
height: 167,
|
||||
width: 119,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
shape: BoxShape.rectangle,
|
||||
borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
image: DecorationImage(
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:le_kiosque_by_gcs/model/news.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/home.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/news.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/news/news.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/profile.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/search/search.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/setting/setting.dart';
|
||||
@@ -18,7 +19,7 @@ class _MainViewState extends State<MainView> {
|
||||
|
||||
List<Widget> _widgetOptions = [
|
||||
HomeView(),
|
||||
NewsView(),
|
||||
NewsView(newsList: newsTest),
|
||||
SubscriptionView(),
|
||||
ProfileView()
|
||||
];
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class NewsView extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:le_kiosque_by_gcs/model/news.dart';
|
||||
|
||||
class ItemRegularNews extends StatelessWidget {
|
||||
const ItemRegularNews({Key key, this.news}) : super(key: key);
|
||||
|
||||
final News news;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 12, right: 12),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_showDetailNews(context);
|
||||
},
|
||||
child: Card(
|
||||
elevation: 4,
|
||||
child: Container(
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Container(
|
||||
height: 90,
|
||||
width: 90,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
shape: BoxShape.rectangle,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
),
|
||||
image: DecorationImage(
|
||||
image: NetworkImage(news.previewUrl),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
news.title,
|
||||
textAlign: TextAlign.justify,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 3,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 14),
|
||||
SizedBox(
|
||||
height: 16,
|
||||
child: Image.network(news.sourceUrl),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
_showDetailNews(context);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Card(
|
||||
elevation: 4,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 120,
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 100,
|
||||
width: 100,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
shape: BoxShape.rectangle,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
),
|
||||
image: DecorationImage(
|
||||
image: NetworkImage(news.previewUrl),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
news.title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 4,
|
||||
style: TextStyle(
|
||||
fontSize: 17,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Image.network(news.sourceUrl),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showDetailNews(BuildContext context) {}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:le_kiosque_by_gcs/model/news.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class ItemTopNews extends StatelessWidget {
|
||||
const ItemTopNews({Key key, this.news}) : super(key: key);
|
||||
|
||||
final News news;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 259,
|
||||
width: 270,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_showFullArticle(context, news.fullPostUrl);
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomLeft,
|
||||
children: [
|
||||
Container(
|
||||
height: 259,
|
||||
width: 270,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
shape: BoxShape.rectangle,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
),
|
||||
image: DecorationImage(
|
||||
image: NetworkImage(news.previewUrl),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 259,
|
||||
width: 270,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black38,
|
||||
shape: BoxShape.rectangle,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
news.title,
|
||||
maxLines: 4,
|
||||
style: TextStyle(
|
||||
fontSize: 17,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, bottom: 16),
|
||||
child: SizedBox(
|
||||
height: 16,
|
||||
child: Image.network(news.sourceUrl),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showFullArticle(BuildContext context, String fullPostUrl) async {
|
||||
if (await canLaunch(fullPostUrl)) {
|
||||
await launch(fullPostUrl);
|
||||
} else {
|
||||
throw 'Could not launch $fullPostUrl';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:le_kiosque_by_gcs/model/magazine.dart';
|
||||
import 'package:le_kiosque_by_gcs/model/news.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/news/item_regular_news.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/news/item_top_news.dart';
|
||||
|
||||
class NewsView extends StatelessWidget {
|
||||
const NewsView({
|
||||
Key key,
|
||||
@required this.newsList,
|
||||
}) : super(key: key);
|
||||
|
||||
final List<News> newsList;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.all(16),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Text(
|
||||
"Top actualité",
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF3B3B3B),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
height: 280,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: magazinesTest.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
bottom: 16,
|
||||
),
|
||||
child: ItemTopNews(
|
||||
news: newsList[index],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.all(16),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Text(
|
||||
"Actualité de la semaine",
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF3B3B3B),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildBuilderDelegate((context, index) {
|
||||
return ItemRegularNews(news: newsList[index]);
|
||||
}, childCount: newsList.length),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,20 +13,7 @@ class ProfileView extends StatefulWidget {
|
||||
class _ProfileViewState extends State<ProfileView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// TODO Removig
|
||||
final summary =
|
||||
"Voyez ce jeu exquis wallon, de graphie en kit mais bref. Portez ce vieux whisky au juge blond qui fume sur son île intérieure, à côté de l\"alcôve ovoïde, où les bûches se consument dans l\"âtre";
|
||||
final url =
|
||||
"https://miningandbusiness.com/wp-content/uploads/2021/02/03f19c3a-1d92-4be7-ac54-f52b37e626ad-561x771.jpg";
|
||||
final urlPrd = "http://www.africau.edu/images/default/sample.pdf";
|
||||
|
||||
final magazines = [
|
||||
Magazine(urlCover: url, magazineUrl: urlPrd, summaryText: summary),
|
||||
Magazine(urlCover: url, magazineUrl: urlPrd, summaryText: summary),
|
||||
Magazine(urlCover: url, magazineUrl: urlPrd, summaryText: summary),
|
||||
Magazine(urlCover: url, magazineUrl: urlPrd, summaryText: summary),
|
||||
Magazine(urlCover: url, magazineUrl: urlPrd, summaryText: summary)
|
||||
];
|
||||
// TODO Removing
|
||||
return Scaffold(
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
@@ -64,8 +51,8 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
mainAxisExtent: 250
|
||||
),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, int index) => ItemMagLarge(magazine: magazines[index]),
|
||||
childCount: magazines.length,
|
||||
(context, int index) => ItemMagLarge(magazine: magazinesTest[index]),
|
||||
childCount: magazinesTest.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:le_kiosque_by_gcs/model/magazine.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/pdf_reader.dart';
|
||||
|
||||
class ItemMagLargeSearch extends StatelessWidget {
|
||||
const ItemMagLargeSearch({
|
||||
Key key,
|
||||
@required this.magazine,
|
||||
}) : super(key: key);
|
||||
|
||||
final Magazine magazine;
|
||||
|
||||
void showPdfReader(BuildContext context, String magazineUrl) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return PdfReader(
|
||||
pdfUrl: magazine.magazineUrl,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showPdfReader(context, magazine.magazineUrl);
|
||||
},
|
||||
child: Container(
|
||||
height: 235,
|
||||
width: 168,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.rectangle,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(5),
|
||||
),
|
||||
image: DecorationImage(
|
||||
image: NetworkImage(magazine.urlCover),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.black54,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Icon(
|
||||
Icons.close_rounded,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ class ItemMagazineSearch extends StatelessWidget {
|
||||
height: 50,
|
||||
width: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
shape: BoxShape.circle,
|
||||
image: DecorationImage(
|
||||
image: NetworkImage(magazine.urlCover),
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:le_kiosque_by_gcs/model/magazine.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/custom/item_mag_large.dart';
|
||||
import 'package:le_kiosque_by_gcs/ui/view/search/item_mag_search.dart';
|
||||
|
||||
class SearchView extends StatelessWidget {
|
||||
import 'item_mag_large_search.dart';
|
||||
|
||||
class SearchView extends StatefulWidget {
|
||||
@override
|
||||
_SearchViewState createState() => _SearchViewState();
|
||||
}
|
||||
|
||||
class _SearchViewState extends State<SearchView> {
|
||||
bool _isGrid = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// TODO: Removing test data
|
||||
@@ -40,27 +50,94 @@ class SearchView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
body: ListView.builder(
|
||||
itemCount: magazinesTest.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
"Recherches récentes",
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
color: Color(0xFF3B3B3B),
|
||||
body: _isGrid ? _buildGrid() : _buildList(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList() {
|
||||
return ListView.builder(
|
||||
itemCount: magazinesTest.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Recherches récentes",
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
color: Color(0xFF3B3B3B),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return ItemMagazineSearch(
|
||||
magazine: magazinesTest[index - 1],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
InkWell(
|
||||
onTap: () => _updateListAppearance(),
|
||||
child: Icon(
|
||||
_isGrid ? Icons.list : Icons.grid_view,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return ItemMagazineSearch(
|
||||
magazine: magazinesTest[index - 1],
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
_updateListAppearance() {
|
||||
setState(() {
|
||||
_isGrid = !_isGrid;
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildGrid() {
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Recherches récentes",
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
color: Color(0xFF3B3B3B),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () => _updateListAppearance(),
|
||||
child: Icon(
|
||||
_isGrid ? Icons.list : Icons.grid_view,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.all(16),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 16.0,
|
||||
crossAxisSpacing: 16.0,
|
||||
mainAxisExtent: 250,
|
||||
),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, int index) =>
|
||||
ItemMagLargeSearch(magazine: magazinesTest[index]),
|
||||
childCount: magazinesTest.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class SettingView extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// Todo: remplace
|
||||
final String licenceUrl = "http://example.com";
|
||||
|
||||
_showTermAndCond(BuildContext context) async {
|
||||
|
||||
Reference in New Issue
Block a user