feat: add repo item, extract list group widget

This commit is contained in:
Rongjian Zhang 2019-02-03 23:10:10 +08:00
parent a374a57f8f
commit f1414057e0
6 changed files with 250 additions and 158 deletions

View File

@ -2,9 +2,9 @@ import 'package:flutter/material.dart' hide Notification;
import 'package:flutter/cupertino.dart' hide Notification;
import '../providers/settings.dart';
import '../providers/notification.dart';
// import '../screens/screens.dart';
import '../widgets/notification_item.dart';
import '../widgets/loading.dart';
import '../widgets/list_group.dart';
import '../utils/utils.dart';
class NotificationGroup {
@ -39,28 +39,13 @@ class NotificationScreenState extends State<NotificationScreen> {
var group = groups[index];
return Padding(
padding: EdgeInsets.all(8),
child: Container(
decoration: BoxDecoration(border: Border.all(color: Colors.black12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
padding: EdgeInsets.all(4),
color: Colors.black12,
child: Text(
group.fullName,
style: TextStyle(color: Colors.black, fontSize: 15),
),
),
Column(
children: group.items
.map((item) => NotificationItem(item: item))
.toList())
],
),
return ListGroup(
title: Text(
group.fullName,
style: TextStyle(color: Colors.black, fontSize: 15),
),
items: group.items,
itemBuilder: (item) => NotificationItem(item: item),
);
}

View File

@ -3,6 +3,8 @@ import 'package:flutter/cupertino.dart';
import '../widgets/refresh_scaffold.dart';
import '../widgets/avatar.dart';
import '../widgets/link.dart';
import '../widgets/list_group.dart';
import '../widgets/repo_item.dart';
import '../utils/utils.dart';
Future queryUser(String login) async {
@ -29,9 +31,17 @@ Future queryUser(String login) async {
login
}
name
description
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
pinnedRepositories(first: 6) {
@ -40,6 +50,17 @@ Future queryUser(String login) async {
login
}
name
description
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
}
@ -49,7 +70,7 @@ Future queryUser(String login) async {
}
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();
GlobalKey<RefreshIndicatorState>();
class UserScreen extends StatefulWidget {
final String login;
@ -60,7 +81,7 @@ class UserScreen extends StatefulWidget {
}
class _UserScreenState extends State<UserScreen> {
var payload;
Map<String, dynamic> payload = {};
@override
Widget build(BuildContext context) {
@ -71,97 +92,105 @@ class _UserScreenState extends State<UserScreen> {
payload = _payload;
});
},
title: widget.login,
body: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Avatar(
login: widget.login,
url: payload['avatarUrl'],
size: 28,
),
Padding(padding: EdgeInsets.only(left: 10)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(payload['name'], style: TextStyle(height: 1.2)),
Padding(padding: EdgeInsets.only(top: 10)),
Row(children: <Widget>[
Icon(
Octicons.mail,
color: Colors.black54,
size: 16,
),
Padding(padding: EdgeInsets.only(left: 4)),
Text(
payload['email'],
style: TextStyle(color: Colors.black54, fontSize: 16),
)
])
],
title: Text(widget.login),
bodyBuilder: () {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Avatar(
login: widget.login,
url: payload['avatarUrl'],
size: 28,
),
)
],
Padding(padding: EdgeInsets.only(left: 10)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(payload['name'], style: TextStyle(height: 1.2)),
Padding(padding: EdgeInsets.only(top: 10)),
Row(children: <Widget>[
Icon(
Octicons.mail,
color: Colors.black54,
size: 16,
),
Padding(padding: EdgeInsets.only(left: 4)),
Text(
payload['email'],
style:
TextStyle(color: Colors.black54, fontSize: 16),
)
])
],
),
)
],
),
),
),
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Link(
child: Column(
children: <Widget>[
Text(payload['repositories']['totalCount'].toString()),
Text('Repos')
],
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Link(
child: Column(
children: <Widget>[
Text(payload['repositories']['totalCount'].toString()),
Text('Repos')
],
),
onTap: () {},
),
onTap: () {},
),
Link(
child: Column(
children: <Widget>[
Text(payload['starredRepositories']['totalCount']
.toString()),
Text('Stars')
],
Link(
child: Column(
children: <Widget>[
Text(payload['starredRepositories']['totalCount']
.toString()),
Text('Stars')
],
),
onTap: () {},
),
onTap: () {},
),
Link(
child: Column(
children: <Widget>[
Text(payload['followers']['totalCount'].toString()),
Text('Followers'),
],
Link(
child: Column(
children: <Widget>[
Text(payload['followers']['totalCount'].toString()),
Text('Followers'),
],
),
onTap: () {
// print(1);
},
),
onTap: () {
// print(1);
},
),
Link(
child: Column(
children: <Widget>[
Text(payload['following']['totalCount'].toString()),
Text('Following')
],
Link(
child: Column(
children: <Widget>[
Text(payload['following']['totalCount'].toString()),
Text('Following')
],
),
onTap: () {},
),
onTap: () {},
),
],
],
),
),
),
],
),
ListGroup(
title: Text('Repos'),
items: payload['repositories']['nodes'],
itemBuilder: (item) => RepoItem(item),
)
],
);
},
);
}
}

View File

@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
class ListGroup<T> extends StatelessWidget {
final Widget title;
final List<T> items;
final Widget Function(T item) itemBuilder;
ListGroup({this.title, this.items, this.itemBuilder});
Widget _buildItem(T item) {
return Container(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12)),
),
child: itemBuilder(item),
);
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(border: Border.all(color: Colors.black12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
padding: EdgeInsets.all(4),
color: Colors.black12,
child: title,
),
Column(children: items.map(_buildItem).toList())
],
),
),
);
}
}

View File

@ -45,55 +45,50 @@ class NotificationItem extends StatelessWidget {
CupertinoPageRoute(builder: (context) => _buildRoute(item)),
);
},
child: Container(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12)),
),
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Icon(
_buildIconData(item.subject.type),
color: Colors.black45,
),
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Icon(
_buildIconData(item.subject.type),
color: Colors.black45,
),
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.symmetric(vertical: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
item.subject.title,
style: TextStyle(fontSize: 15),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.symmetric(vertical: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
item.subject.title,
style: TextStyle(fontSize: 15),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
Padding(padding: EdgeInsets.only(top: 8)),
Text(
TimeAgo.format(item.updatedAt),
style: TextStyle(
fontSize: 12,
color: Colors.black87,
),
Padding(padding: EdgeInsets.only(top: 8)),
Text(
TimeAgo.format(item.updatedAt),
style: TextStyle(
fontSize: 12,
color: Colors.black87,
),
)
],
),
)
],
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Icon(Octicons.check, color: Colors.black45),
),
],
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Icon(Octicons.check, color: Colors.black45),
),
],
),
],
),
),
],
),
);
}

View File

@ -5,15 +5,16 @@ import '../providers/settings.dart';
import 'loading.dart';
typedef RefreshCallback = Future<void> Function();
typedef BodyBuilder = Widget Function();
class RefreshScaffold extends StatefulWidget {
final String title;
final Widget body;
final Widget title;
final BodyBuilder bodyBuilder;
final RefreshCallback onRefresh;
RefreshScaffold({
@required this.title,
@required this.body,
@required this.bodyBuilder,
@required this.onRefresh,
});
@ -50,7 +51,7 @@ class _RefreshScaffoldState extends State<RefreshScaffold> {
if (loading) {
return Loading(more: false);
} else {
return widget.body;
return widget.bodyBuilder();
}
}
@ -59,7 +60,7 @@ class _RefreshScaffoldState extends State<RefreshScaffold> {
switch (SettingsProvider.of(context).layout) {
case LayoutMap.cupertino:
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(middle: Text(widget.title)),
navigationBar: CupertinoNavigationBar(middle: widget.title),
child: SafeArea(
child: CustomScrollView(
slivers: <Widget>[
@ -71,7 +72,7 @@ class _RefreshScaffoldState extends State<RefreshScaffold> {
);
default:
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
appBar: AppBar(title: widget.title),
body: RefreshIndicator(
onRefresh: widget.onRefresh,
child: _buildBody(context),

View File

@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import '../utils/utils.dart';
import '../screens/repo.dart';
import 'link.dart';
class RepoItem extends StatelessWidget {
final Map<String, dynamic> item;
RepoItem(this.item);
@override
Widget build(BuildContext context) {
return Link(
onTap: () {},
child: Padding(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(item['name'], style: TextStyle(fontWeight: FontWeight.w600)),
Padding(padding: EdgeInsets.only(top: 4)),
Text(item['description']),
Padding(padding: EdgeInsets.only(top: 4)),
DefaultTextStyle(
style: TextStyle(color: Colors.black54),
child: Row(
children: <Widget>[
Icon(Octicons.star, size: 16, color: Colors.black54),
Text(item['stargazers']['totalCount'].toString()),
Padding(padding: EdgeInsets.only(left: 8)),
Icon(Octicons.repo_forked, size: 16, color: Colors.black54),
Text(item['forks']['totalCount'].toString()),
Padding(padding: EdgeInsets.only(left: 8)),
Text(item['primaryLanguage']['name'])
],
),
)
],
),
),
);
}
}