mirror of
https://github.com/git-touch/git-touch
synced 2025-02-12 09:30:38 +01:00
feat: add repo item, extract list group widget
This commit is contained in:
parent
a374a57f8f
commit
f1414057e0
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
39
lib/widgets/list_group.dart
Normal file
39
lib/widgets/list_group.dart
Normal 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())
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -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),
|
||||
|
43
lib/widgets/repo_item.dart
Normal file
43
lib/widgets/repo_item.dart
Normal 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'])
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user