mirror of
https://github.com/git-touch/git-touch
synced 2025-02-21 14:01:02 +01:00
feat: style of home and notification screen
This commit is contained in:
parent
2458c63a0c
commit
4e28608714
@ -1,8 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../widgets/event.dart';
|
||||
import '../providers/event.dart';
|
||||
import '../models/event.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
@override
|
||||
@ -14,6 +13,10 @@ class HomeScreen extends StatefulWidget {
|
||||
class HomeScreenState extends State<HomeScreen> {
|
||||
// final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
|
||||
// GlobalKey<RefreshIndicatorState>();
|
||||
int page = 1;
|
||||
bool loading = false;
|
||||
List<Event> events = [];
|
||||
ScrollController _controller = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -22,50 +25,79 @@ class HomeScreenState extends State<HomeScreen> {
|
||||
// Future.delayed(Duration(seconds: 0)).then((_) {
|
||||
// EventProvider.of(context).update.add(true);
|
||||
// });
|
||||
_refresh();
|
||||
_controller.addListener(() {
|
||||
if (_controller.offset + 100 > _controller.position.maxScrollExtent &&
|
||||
!_controller.position.outOfRange &&
|
||||
!loading) {
|
||||
_loadMore();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _refresh() async {
|
||||
setState(() {
|
||||
loading = true;
|
||||
});
|
||||
page = 1;
|
||||
var items = await fetchEvents(page);
|
||||
setState(() {
|
||||
loading = false;
|
||||
events = items;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _loadMore() async {
|
||||
print('more');
|
||||
setState(() {
|
||||
loading = true;
|
||||
});
|
||||
page = page + 1;
|
||||
var items = await fetchEvents(page);
|
||||
setState(() {
|
||||
loading = false;
|
||||
events.addAll(items);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildBottomIndicator() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15),
|
||||
child: CupertinoActivityIndicator(radius: 12));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(context) {
|
||||
// Navigator.of(context).pushNamed('/user');
|
||||
final eventBloc = EventProvider.of(context);
|
||||
// final eventBloc = EventProvider.of(context);
|
||||
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: Text("GitFlux"),
|
||||
),
|
||||
child: StreamBuilder<List<Event>>(
|
||||
stream: eventBloc.events,
|
||||
builder: (context, snapshot) {
|
||||
// print(snapshot.data);
|
||||
Widget widget;
|
||||
if (snapshot.hasData) {
|
||||
// List<Event> events = snapshot.data;
|
||||
// ScrollController(debugLabel: 'aaa', )
|
||||
|
||||
// widget = CupertinoRefreshControl(
|
||||
// // key: _refreshIndicatorKey,
|
||||
// onRefresh: () {
|
||||
// print(1);
|
||||
// loadFirst();
|
||||
// },
|
||||
// );
|
||||
widget = ListView.builder(itemBuilder: (context, index) {
|
||||
// print(index);
|
||||
try {
|
||||
return EventItem(snapshot.data[index]);
|
||||
} catch (err) {
|
||||
return Text(err.toString());
|
||||
// return null;
|
||||
}
|
||||
});
|
||||
} else if (snapshot.hasError) {
|
||||
widget = Text("${snapshot.error}");
|
||||
} else {
|
||||
widget = CupertinoActivityIndicator();
|
||||
}
|
||||
|
||||
return widget;
|
||||
},
|
||||
child: CustomScrollView(
|
||||
controller: _controller,
|
||||
slivers: <Widget>[
|
||||
CupertinoSliverNavigationBar(
|
||||
largeTitle: const Text('News'),
|
||||
trailing: Icon(Octicons.settings),
|
||||
),
|
||||
CupertinoSliverRefreshControl(
|
||||
onRefresh: _refresh,
|
||||
),
|
||||
SliverSafeArea(
|
||||
top: false,
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
if (index == events.length) {
|
||||
return _buildBottomIndicator();
|
||||
} else {
|
||||
return EventItem(events[index]);
|
||||
}
|
||||
},
|
||||
childCount: events.length + 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_flux/models/notification.dart';
|
||||
import 'dart:core';
|
||||
import 'package:flutter/material.dart' hide Notification;
|
||||
import 'package:flutter/cupertino.dart' hide Notification;
|
||||
import 'package:git_flux/providers/notification.dart';
|
||||
import 'package:git_flux/screens/issue.dart';
|
||||
import 'package:git_flux/octicons.dart';
|
||||
import 'package:git_flux/screens/screens.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
class NotificationScreen extends StatefulWidget {
|
||||
@override
|
||||
@ -11,11 +11,6 @@ class NotificationScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class NotificationScreenState extends State<NotificationScreen> {
|
||||
initState() {
|
||||
super.initState();
|
||||
// initFetch();
|
||||
}
|
||||
|
||||
Widget _getRouteWidget(String type) {
|
||||
switch (type) {
|
||||
case 'Issue':
|
||||
@ -39,7 +34,7 @@ class NotificationScreenState extends State<NotificationScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildItem(BuildContext context, NotificationItem item) {
|
||||
Widget _buildItem(BuildContext context, Notification item) {
|
||||
return Material(
|
||||
child: InkWell(
|
||||
splashColor: Colors.transparent,
|
||||
@ -59,31 +54,36 @@ class NotificationScreenState extends State<NotificationScreen> {
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Text(item.subject.title, style: TextStyle(height: 1)),
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
item.updatedAt,
|
||||
style: TextStyle(fontSize: 12),
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(item.subject.title,
|
||||
style: TextStyle(height: 1)),
|
||||
Padding(padding: EdgeInsets.only(top: 4)),
|
||||
Text(TimeAgo.format(item.updatedAt),
|
||||
style: TextStyle(fontSize: 12))
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Icon(
|
||||
CupertinoIcons.right_chevron,
|
||||
color: CupertinoColors.inactiveGray,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Icon(
|
||||
CupertinoIcons.right_chevron,
|
||||
color: CupertinoColors.inactiveGray,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -147,31 +147,22 @@ class NotificationScreenState extends State<NotificationScreen> {
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
StreamBuilder<bool>(
|
||||
stream: bloc.loading,
|
||||
builder: (context, snapshot) {
|
||||
return Flexible(
|
||||
child: snapshot.data == null || snapshot.data
|
||||
? CupertinoActivityIndicator()
|
||||
: StreamBuilder<List<NotificationGroup>>(
|
||||
stream: bloc.items,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == null) {
|
||||
return Text('loading...');
|
||||
}
|
||||
Container(
|
||||
child: StreamBuilder<List<NotificationGroup>>(
|
||||
stream: bloc.items,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == null) {
|
||||
return Text('loading...');
|
||||
}
|
||||
|
||||
List<NotificationGroup> groups = snapshot.data;
|
||||
|
||||
return ListView(
|
||||
children: groups
|
||||
.map((group) =>
|
||||
_buildGroupItem(context, group))
|
||||
.toList());
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
return ListView(
|
||||
shrinkWrap: true,
|
||||
children: snapshot.data
|
||||
.map((group) => _buildGroupItem(context, group))
|
||||
.toList());
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import '../models/user.dart';
|
||||
import '../utils.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
class IosUserPage extends StatelessWidget {
|
||||
String login;
|
||||
@ -22,11 +22,11 @@ class IosUserPage extends StatelessWidget {
|
||||
middle: Text(login),
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: fetchUser(login),
|
||||
// future: fetchUser(login),
|
||||
builder: (context, snapshot) {
|
||||
Widget widget;
|
||||
if (snapshot.hasData) {
|
||||
User user = snapshot.data;
|
||||
// User user = snapshot.data;
|
||||
return Text('');
|
||||
} else if (snapshot.hasError) {
|
||||
widget = Text("${snapshot.error}");
|
||||
|
@ -1,12 +1,9 @@
|
||||
// import 'package:uri/uri.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_flux/providers/event.dart';
|
||||
import 'package:git_flux/providers/notification.dart';
|
||||
import 'package:git_flux/providers/search.dart';
|
||||
import 'package:git_flux/ios/main.dart';
|
||||
// import 'package:git_flux/screens/user.dart';
|
||||
// import 'package:git_flux/screens/repo.dart';
|
||||
|
||||
class App extends StatelessWidget {
|
||||
final isIos = true;
|
||||
@ -26,7 +23,7 @@ class App extends StatelessWidget {
|
||||
bloc: eventBloc,
|
||||
child: MaterialApp(
|
||||
home: DefaultTextStyle(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
style: TextStyle(color: Color(0xff24292e)),
|
||||
child: IosHomePage(title: 'GitFlux'),
|
||||
),
|
||||
// theme: ThemeData(
|
||||
|
@ -3,16 +3,6 @@ import 'dart:async';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
import '../models/event.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import '../utils.dart';
|
||||
|
||||
Future<List<Event>> fetchEvents([int page = 1]) async {
|
||||
List data = await getWithCredentials(
|
||||
'/users/pd4d10/received_events/public?page=$page',
|
||||
);
|
||||
return data.map<Event>((item) {
|
||||
return Event.fromJson(item);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
class EventBloc {
|
||||
final _items = BehaviorSubject<List<Event>>(seedValue: []);
|
||||
@ -24,15 +14,15 @@ class EventBloc {
|
||||
Sink<bool> get update => _update.sink;
|
||||
|
||||
EventBloc() {
|
||||
_update.stream.listen((bool isRefresh) async {
|
||||
if (isRefresh) {
|
||||
_items.add(await fetchEvents());
|
||||
_page.add(1);
|
||||
} else {
|
||||
_items.add(await fetchEvents());
|
||||
_page.add(_page.value + 1);
|
||||
}
|
||||
});
|
||||
// _update.stream.listen((bool isRefresh) async {
|
||||
// if (isRefresh) {
|
||||
// _items.add(await fetchEvents(1));
|
||||
// _page.add(1);
|
||||
// } else {
|
||||
// _items.add(await fetchEvents(1));
|
||||
// _page.add(_page.value + 1);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
|
@ -1,35 +1,7 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import '../utils.dart';
|
||||
import '../models/notification.dart';
|
||||
|
||||
class NotificationGroup {
|
||||
String fullName;
|
||||
List<NotificationItem> items = [];
|
||||
|
||||
NotificationGroup(this.fullName);
|
||||
}
|
||||
|
||||
Future<List<NotificationGroup>> fetchNotifications([int index = 0]) async {
|
||||
String search = '';
|
||||
if (index == 1) {
|
||||
search = '?paticipating=true';
|
||||
} else if (index == 2) {
|
||||
search = '?all=true';
|
||||
}
|
||||
List data = await getWithCredentials('/notifications$search');
|
||||
Map<String, NotificationGroup> groupMap = {};
|
||||
data.forEach((item) {
|
||||
String repo = item['repository']['full_name'];
|
||||
if (groupMap[repo] == null) {
|
||||
groupMap[repo] = NotificationGroup(repo);
|
||||
}
|
||||
|
||||
groupMap[repo].items.add(NotificationItem.fromJson(item));
|
||||
});
|
||||
return groupMap.values.toList();
|
||||
}
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
class NotificationBloc {
|
||||
final _groups = BehaviorSubject<List<NotificationGroup>>(seedValue: []);
|
||||
|
@ -2,7 +2,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'dart:async';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import '../utils.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
Future search(String keyword, String type) async {
|
||||
var data = await query('''
|
||||
|
@ -1,8 +1,8 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'dart:async';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import '../utils.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
Future queryUser(String login) async {
|
||||
var data = await query('''
|
||||
|
3
lib/screens/screens.dart
Normal file
3
lib/screens/screens.dart
Normal file
@ -0,0 +1,3 @@
|
||||
export 'repo.dart';
|
||||
export 'user.dart';
|
||||
export 'issue.dart';
|
@ -1,43 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'token.dart';
|
||||
import 'models/user.dart';
|
||||
|
||||
final prefix = 'https://api.github.com';
|
||||
final endpoint = '/graphql';
|
||||
|
||||
Future<dynamic> getWithCredentials(String url) async {
|
||||
final res = await http.get(
|
||||
prefix + url,
|
||||
headers: {HttpHeaders.authorizationHeader: 'token $token'},
|
||||
);
|
||||
final data = json.decode(res.body);
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<dynamic> postWithCredentials(String url, String body) async {
|
||||
final res = await http.post(
|
||||
prefix + url,
|
||||
headers: {HttpHeaders.authorizationHeader: 'token $token'},
|
||||
body: body,
|
||||
);
|
||||
final data = json.decode(res.body);
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<dynamic> query(String query) async {
|
||||
final data =
|
||||
await postWithCredentials('/graphql', json.encode({'query': query}));
|
||||
if (data['errors'] != null) {
|
||||
throw new Exception(data['errors'].toString());
|
||||
}
|
||||
print(data);
|
||||
return data['data'];
|
||||
}
|
||||
|
||||
Future<User> fetchUser(String login) async {
|
||||
Map<String, dynamic> data = await getWithCredentials('/users/$login');
|
||||
return User.fromJson(data);
|
||||
}
|
72
lib/utils/github.dart
Normal file
72
lib/utils/github.dart
Normal file
@ -0,0 +1,72 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:github/server.dart';
|
||||
export 'package:github/server.dart';
|
||||
import '../token.dart';
|
||||
|
||||
var ghClient = createGitHubClient(auth: Authentication.withToken(token));
|
||||
|
||||
final prefix = 'https://api.github.com';
|
||||
final endpoint = '/graphql';
|
||||
|
||||
Future<dynamic> getWithCredentials(String url) async {
|
||||
final res = await http.get(
|
||||
prefix + url,
|
||||
headers: {HttpHeaders.authorizationHeader: 'token $token'},
|
||||
);
|
||||
final data = json.decode(res.body);
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<dynamic> postWithCredentials(String url, String body) async {
|
||||
final res = await http.post(
|
||||
prefix + url,
|
||||
headers: {HttpHeaders.authorizationHeader: 'token $token'},
|
||||
body: body,
|
||||
);
|
||||
final data = json.decode(res.body);
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<dynamic> query(String query) async {
|
||||
final data =
|
||||
await postWithCredentials('/graphql', json.encode({'query': query}));
|
||||
if (data['errors'] != null) {
|
||||
throw new Exception(data['errors'].toString());
|
||||
}
|
||||
print(data);
|
||||
return data['data'];
|
||||
}
|
||||
|
||||
Future<List<Event>> fetchEvents(int page) async {
|
||||
List data = await getWithCredentials(
|
||||
'/users/pd4d10/received_events/public?page=$page',
|
||||
);
|
||||
return data.map<Event>((item) => Event.fromJSON(item)).toList();
|
||||
}
|
||||
|
||||
class NotificationGroup {
|
||||
String fullName;
|
||||
List<Notification> items = [];
|
||||
|
||||
NotificationGroup(this.fullName);
|
||||
}
|
||||
|
||||
Future<List<NotificationGroup>> fetchNotifications([int index = 0]) async {
|
||||
var data = await ghClient.activity
|
||||
.listNotifications(all: index == 2, participating: index == 1)
|
||||
.toList();
|
||||
|
||||
Map<String, NotificationGroup> groupMap = {};
|
||||
data.forEach((item) {
|
||||
String repo = item.repository.fullName;
|
||||
if (groupMap[repo] == null) {
|
||||
groupMap[repo] = NotificationGroup(repo);
|
||||
}
|
||||
|
||||
groupMap[repo].items.add(item);
|
||||
});
|
||||
return groupMap.values.toList();
|
||||
}
|
25
lib/utils/timeago.dart
Normal file
25
lib/utils/timeago.dart
Normal file
@ -0,0 +1,25 @@
|
||||
import 'dart:core';
|
||||
|
||||
class TimeAgo {
|
||||
static String _ceil(double n) => n.ceil().toString();
|
||||
|
||||
static String _pluralize(double time, String unit) {
|
||||
if (time == 1) {
|
||||
return '${_ceil(time)} $unit ago';
|
||||
}
|
||||
return '${_ceil(time)} ${unit}s ago';
|
||||
}
|
||||
|
||||
static String format(DateTime time) {
|
||||
double diff =
|
||||
(DateTime.now().millisecondsSinceEpoch - time.millisecondsSinceEpoch) /
|
||||
1000;
|
||||
if (diff < 3600) {
|
||||
return _pluralize(diff / 60, 'minute');
|
||||
} else if (diff < 86400) {
|
||||
return _pluralize(diff / 3600, 'hour');
|
||||
} else {
|
||||
return _pluralize(diff / 86400, 'day');
|
||||
}
|
||||
}
|
||||
}
|
3
lib/utils/utils.dart
Normal file
3
lib/utils/utils.dart
Normal file
@ -0,0 +1,3 @@
|
||||
export 'github.dart';
|
||||
export 'octicons.dart';
|
||||
export 'timeago.dart';
|
@ -1,201 +1,180 @@
|
||||
import '../utils.dart';
|
||||
import '../models/event.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
// import '../issue.dart';
|
||||
// import '../user.dart';
|
||||
|
||||
// class Strong extends StatelessWidget {
|
||||
// final String text;
|
||||
|
||||
// @override
|
||||
// build(context) {
|
||||
// return TextSpan(
|
||||
// text: text,
|
||||
// style: TextStyle(
|
||||
// fontWeight: FontWeight.bold,
|
||||
// color: Color(0xff24292e),
|
||||
// ),
|
||||
// // recognizer: recognizer,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
class _Avatar extends StatelessWidget {
|
||||
final String url;
|
||||
_Avatar(this.url);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return CircleAvatar(
|
||||
backgroundImage: NetworkImage(url),
|
||||
radius: 24.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:git_flux/screens/screens.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
/// Events types:
|
||||
///
|
||||
/// https://developer.github.com/v3/activity/events/types/#event-types--payloads
|
||||
class EventItem extends StatelessWidget {
|
||||
final Event event;
|
||||
EventItem(this.event);
|
||||
|
||||
Widget getEventItemByType(BuildContext context) {
|
||||
TextSpan _buildEvent(BuildContext context) {
|
||||
switch (event.type) {
|
||||
case 'IssuesEvent':
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} issue '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(
|
||||
text: '#' + event.payload['issue']['number'].toString(),
|
||||
),
|
||||
TextSpan(
|
||||
text: event.payload['issue']['title'],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
return TextSpan(children: [
|
||||
TextSpan(text: ' ${event.payload['action']} issue '),
|
||||
_buildIssue(context),
|
||||
TextSpan(text: ' at '),
|
||||
_buildRepo(context),
|
||||
]);
|
||||
case 'PushEvent':
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' pushed to '),
|
||||
TextSpan(
|
||||
text: event.payload['ref'],
|
||||
style: TextStyle(color: CupertinoColors.activeBlue),
|
||||
),
|
||||
TextSpan(text: ' in '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(text: '')
|
||||
],
|
||||
return TextSpan(children: [
|
||||
TextSpan(text: ' pushed to '),
|
||||
TextSpan(
|
||||
text: event.payload['ref'],
|
||||
style: TextStyle(color: CupertinoColors.activeBlue),
|
||||
),
|
||||
);
|
||||
TextSpan(text: ' at '),
|
||||
_buildRepo(context),
|
||||
TextSpan(text: '')
|
||||
]);
|
||||
case 'PullRequestEvent':
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} pull request '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(text: '#' + event.payload['number'].toString()),
|
||||
TextSpan(text: event.payload['pull_request']['title'])
|
||||
],
|
||||
),
|
||||
);
|
||||
return TextSpan(children: [
|
||||
TextSpan(text: ' ${event.payload['action']} pull request '),
|
||||
_buildPullRequest(context),
|
||||
TextSpan(text: ' at '),
|
||||
_buildRepo(context),
|
||||
]);
|
||||
case 'PullRequestReviewCommentEvent':
|
||||
return TextSpan(children: [
|
||||
TextSpan(text: ' reviewed pull request '),
|
||||
_buildPullRequest(context),
|
||||
TextSpan(text: ' at '),
|
||||
_buildRepo(context),
|
||||
]);
|
||||
case 'WatchEvent':
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} '),
|
||||
_strong(event.repo.name),
|
||||
],
|
||||
),
|
||||
);
|
||||
return TextSpan(children: [
|
||||
TextSpan(text: ' ${event.payload['action']} '),
|
||||
_buildRepo(context)
|
||||
]);
|
||||
case 'IssueCommentEvent':
|
||||
return TextSpan(children: [
|
||||
TextSpan(text: ' commented on issue '),
|
||||
_buildIssue(context),
|
||||
TextSpan(text: ' at '),
|
||||
_buildRepo(context),
|
||||
// TextSpan(text: event.payload['comment']['body'])
|
||||
]);
|
||||
default:
|
||||
return Text(
|
||||
'Not implement yet',
|
||||
return TextSpan(
|
||||
text: 'Type ${event.type} Not implement yet',
|
||||
style: TextStyle(color: CupertinoColors.destructiveRed),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _buildOriginalComment() {
|
||||
switch (event.type) {
|
||||
case 'IssueCommentEvent':
|
||||
return event.payload['comment']['body'];
|
||||
case 'IssuesEvent':
|
||||
return event.payload['issue']['title'];
|
||||
case 'PullRequestEvent':
|
||||
return event.payload['pull_request']['title'];
|
||||
case 'PullRequestReviewCommentEvent':
|
||||
return event.payload['comment']['body'];
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String _buildComment() {
|
||||
return _buildOriginalComment();
|
||||
}
|
||||
|
||||
TextSpan _buildLink(BuildContext context, String text, Function handle) {
|
||||
return TextSpan(
|
||||
text: text,
|
||||
style: TextStyle(color: Color(0xff0366d6)),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Navigator.of(context).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (context) {
|
||||
return handle();
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
TextSpan _buildRepo(BuildContext context) {
|
||||
return _buildLink(context, event.repo.name, () => RepoScreen());
|
||||
}
|
||||
|
||||
TextSpan _buildIssue(BuildContext context) {
|
||||
return _buildLink(context,
|
||||
'#' + event.payload['issue']['number'].toString(), () => UserScreen());
|
||||
}
|
||||
|
||||
TextSpan _buildPullRequest(BuildContext context) {
|
||||
return _buildLink(
|
||||
context,
|
||||
'#' + event.payload['pull_request']['number'].toString(),
|
||||
() => UserScreen());
|
||||
}
|
||||
|
||||
IconData _buildIconData(BuildContext context) {
|
||||
switch (event.type) {
|
||||
case 'IssueCommentEvent':
|
||||
return Octicons.comment_discussion;
|
||||
case 'IssuesEvent':
|
||||
return Octicons.issue_opened;
|
||||
case 'PullRequestEvent':
|
||||
return Octicons.git_pull_request;
|
||||
case 'PushEvent':
|
||||
return Octicons.repo_push;
|
||||
case 'WatchEvent':
|
||||
return Octicons.star;
|
||||
default:
|
||||
return Octicons.octoface;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 16.0),
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
|
||||
left: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
|
||||
right: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
|
||||
bottom: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
_Avatar(event.actor.avatarUrl),
|
||||
Expanded(child: getEventItemByType(context)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TextSpan _strong(String text, [GestureRecognizer recognizer]) {
|
||||
return TextSpan(
|
||||
text: text,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xff24292e),
|
||||
),
|
||||
recognizer: recognizer,
|
||||
);
|
||||
}
|
||||
|
||||
TextSpan _user(Event event, context) {
|
||||
return _strong(
|
||||
event.actor.login,
|
||||
// TapGestureRecognizer()
|
||||
// ..onTap = () {
|
||||
// Navigator.of(context).push(
|
||||
// CupertinoPageRoute(
|
||||
// builder: (context) {
|
||||
// return IosUserPage(event.actor, event.avatar);
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
);
|
||||
}
|
||||
|
||||
class IssuesEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
IssuesEvent(this.event);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} issue '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(
|
||||
text: '#' + event.payload['issue']['number'].toString(),
|
||||
border: Border(
|
||||
bottom: BorderSide(color: CupertinoColors.lightBackgroundGray))),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
CircleAvatar(
|
||||
backgroundColor: Colors.transparent,
|
||||
backgroundImage: NetworkImage(event.actor.avatarUrl),
|
||||
radius: 16,
|
||||
),
|
||||
Padding(padding: EdgeInsets.only(left: 10)),
|
||||
Expanded(
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: Color(0xff24292e), height: 1.2),
|
||||
children: <TextSpan>[
|
||||
_buildLink(
|
||||
context, event.actor.login, () => UserScreen()),
|
||||
_buildEvent(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.only(left: 10)),
|
||||
Icon(_buildIconData(context),
|
||||
color: CupertinoColors.inactiveGray),
|
||||
],
|
||||
),
|
||||
TextSpan(
|
||||
text: event.payload['issue']['title'],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class IssueCommentEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
IssueCommentEvent(this.event);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' commented on issue '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(text: '#' + event.payload['issue']['number'].toString()),
|
||||
TextSpan(text: event.payload['comment']['body'])
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 42, top: 8),
|
||||
child: Text(_buildComment(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Color(0xffaaaaaa))))
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_flux/utils.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
Future queryUser(String login) async {
|
||||
var data = await query('''
|
||||
|
@ -22,6 +22,8 @@ dependencies:
|
||||
http: ^0.11.3
|
||||
rxdart: ^0.20.0
|
||||
uri: ^0.11.3
|
||||
github: ^4.1.0
|
||||
intl: ^0.15.7
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
x
Reference in New Issue
Block a user