Add user page

This commit is contained in:
Rongjian Zhang 2018-04-22 01:07:22 +08:00
parent dfb32cc0fd
commit 675d39a966
7 changed files with 296 additions and 228 deletions

View File

@ -1,81 +0,0 @@
import 'dart:async';
// import 'dart:convert';
import '../utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'home/event.dart';
class IosHomeTab extends StatefulWidget {
@override
createState() {
return new IosHomeTabState();
}
}
class IosHomeTabState extends State<IosHomeTab> {
int page = 1;
List<Event> events = [];
loadFirst() async {
events = await fetchEvents();
page = 1;
return events;
}
loadMore() async {
events.addAll(await fetchEvents(page + 1));
page++;
return events;
}
@override
Widget build(context) {
return new FutureBuilder(
future: loadFirst(),
builder: (context, snapshot) {
Widget widget;
if (snapshot.hasData) {
// List<Event> events = snapshot.data;
widget = new CustomScrollView(
slivers: [
new CupertinoRefreshControl(
onRefresh: () {
return loadFirst();
},
),
new SliverSafeArea(
// top: true,
sliver: new SliverList(
delegate: new SliverChildBuilderDelegate(
(context, index) {
var event = events[index];
switch (event.type) {
case 'IssuesEvent':
return new IssuesEvent(event);
case 'PushEvent':
return new PushEvent(event);
case 'PullRequestEvent':
return new PullRequestEvent(event);
case 'WatchEvent':
return new WatchEvent(event);
default:
return new Text('Not implement yet');
}
},
childCount: 30,
),
),
),
],
);
} else if (snapshot.hasError) {
widget = new Text("${snapshot.error}");
} else {
widget = new CupertinoActivityIndicator();
}
return widget;
},
);
}
}

View File

@ -1,27 +1,34 @@
import '../../utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import '../issue.dart';
import '../user.dart';
class _Avatar extends StatelessWidget {
final String avatar;
_Avatar(this.avatar);
@override
build(context) {
return new CircleAvatar(
backgroundImage: NetworkImage(avatar),
radius: 24.0,
);
}
}
TextSpan _strong(String text) {
TextSpan _strong(String text, [GestureRecognizer recognizer]) {
return new TextSpan(
text: text,
style: new TextStyle(
fontWeight: FontWeight.bold,
color: new Color(0xff24292e),
),
recognizer: recognizer,
);
}
TextSpan _user(Event event, context) {
return _strong(
event.actor,
new TapGestureRecognizer()
..onTap = () {
Navigator.of(context).push(
new CupertinoPageRoute(
builder: (context) {
return new IosUserPage(event.actor, event.avatar);
},
),
);
},
);
}
@ -30,29 +37,22 @@ class PushEvent extends StatelessWidget {
PushEvent(this.event);
@override
build(ctx) {
return new Row(
children: [
new _Avatar(event.avatar),
new Expanded(
child: new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_strong(event.actor),
new TextSpan(text: ' pushed to '),
new TextSpan(
text: event.payload['ref'],
style: new TextStyle(color: CupertinoColors.activeBlue),
),
new TextSpan(text: ' in '),
_strong(event.repo),
new TextSpan(text: '')
],
),
build(context) {
return new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_user(event, context),
new TextSpan(text: ' pushed to '),
new TextSpan(
text: event.payload['ref'],
style: new TextStyle(color: CupertinoColors.activeBlue),
),
),
],
new TextSpan(text: ' in '),
_strong(event.repo),
new TextSpan(text: '')
],
),
);
}
}
@ -62,26 +62,22 @@ class IssuesEvent extends StatelessWidget {
IssuesEvent(this.event);
@override
build(ctx) {
return new Row(
children: <Widget>[
new _Avatar(event.avatar),
new Expanded(
child: new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_strong(event.actor),
new TextSpan(text: ' ${event.payload['action']} issue '),
_strong(event.repo),
new TextSpan(
text: '#' + event.payload['issue']['number'].toString()),
new TextSpan(text: event.payload['issue']['title'])
],
),
build(context) {
return new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_user(event, context),
new TextSpan(text: ' ${event.payload['action']} issue '),
_strong(event.repo),
new TextSpan(
text: '#' + event.payload['issue']['number'].toString(),
),
),
],
new TextSpan(
text: event.payload['issue']['title'],
)
],
),
);
}
}
@ -91,25 +87,18 @@ class PullRequestEvent extends StatelessWidget {
PullRequestEvent(this.event);
@override
build(ctx) {
return new Row(
children: <Widget>[
new _Avatar(event.avatar),
new Expanded(
child: new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_strong(event.actor),
new TextSpan(text: ' ${event.payload['action']} pull request '),
_strong(event.repo),
new TextSpan(text: '#' + event.payload['number'].toString()),
new TextSpan(text: event.payload['pull_request']['title'])
],
),
),
),
],
build(context) {
return new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_user(event, context),
new TextSpan(text: ' ${event.payload['action']} pull request '),
_strong(event.repo),
new TextSpan(text: '#' + event.payload['number'].toString()),
new TextSpan(text: event.payload['pull_request']['title'])
],
),
);
}
}
@ -119,26 +108,18 @@ class IssueCommentEvent extends StatelessWidget {
IssueCommentEvent(this.event);
@override
build(ctx) {
return new Row(
children: <Widget>[
new _Avatar(event.avatar),
new Expanded(
child: new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_strong(event.actor),
new TextSpan(text: ' commented on issue '),
_strong(event.repo),
new TextSpan(
text: '#' + event.payload['issue']['number'].toString()),
new TextSpan(text: event.payload['comment']['body'])
],
),
),
),
],
build(context) {
return new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_user(event, context),
new TextSpan(text: ' commented on issue '),
_strong(event.repo),
new TextSpan(text: '#' + event.payload['issue']['number'].toString()),
new TextSpan(text: event.payload['comment']['body'])
],
),
);
}
}
@ -148,23 +129,16 @@ class WatchEvent extends StatelessWidget {
WatchEvent(this.event);
@override
build(ctx) {
return new Row(
children: <Widget>[
new _Avatar(event.avatar),
new Expanded(
child: new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_strong(event.actor),
new TextSpan(text: ' ${event.payload['action']} '),
_strong(event.repo),
],
),
),
),
],
build(context) {
return new RichText(
text: new TextSpan(
style: new TextStyle(color: CupertinoColors.black),
children: [
_user(event, context),
new TextSpan(text: ' ${event.payload['action']} '),
_strong(event.repo),
],
),
);
}
}

121
lib/ios/home/index.dart Normal file
View File

@ -0,0 +1,121 @@
// import 'dart:async';
// import 'dart:convert';
import '../../utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'event.dart';
import '../user.dart';
class _Avatar extends StatelessWidget {
final String avatar;
_Avatar(this.avatar);
@override
build(context) {
return new CircleAvatar(
backgroundImage: NetworkImage(avatar),
radius: 24.0,
);
}
}
class _EventItem extends StatelessWidget {
final Event event;
final Widget child;
_EventItem(this.event, this.child);
@override
build(context) {
// const Padding(padding: const EdgeInsets.only(top: 16.0)),
return new Row(
children: [
new _Avatar(event.avatar),
new Expanded(child: child),
],
);
}
}
class IosHomeTab extends StatefulWidget {
@override
createState() {
return new IosHomeTabState();
}
}
class IosHomeTabState extends State<IosHomeTab> {
int page = 1;
List<Event> events = [];
loadFirst() async {
events = await fetchEvents();
page = 1;
return events;
}
loadMore() async {
events.addAll(await fetchEvents(page + 1));
page++;
return events;
}
@override
Widget build(context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text('Home'),
),
child: new FutureBuilder(
future: loadFirst(),
builder: (context, snapshot) {
Widget widget;
if (snapshot.hasData) {
// List<Event> events = snapshot.data;
widget = new CustomScrollView(
slivers: [
new CupertinoRefreshControl(
onRefresh: () {
return loadFirst();
},
),
new SliverSafeArea(
// top: true,
sliver: new SliverList(
delegate: new SliverChildBuilderDelegate(
(context, index) {
var event = events[index];
var child = (() {
switch (event.type) {
case 'IssuesEvent':
return new IssuesEvent(event);
case 'PushEvent':
return new PushEvent(event);
case 'PullRequestEvent':
return new PullRequestEvent(event);
case 'WatchEvent':
return new WatchEvent(event);
default:
return new Text('Not implement yet');
}
})();
return new _EventItem(event, child);
},
childCount: 30,
),
),
),
],
);
} else if (snapshot.hasError) {
widget = new Text("${snapshot.error}");
} else {
widget = new CupertinoActivityIndicator();
}
return widget;
},
),
);
}
}

11
lib/ios/issue.dart Normal file
View File

@ -0,0 +1,11 @@
// import 'dart:async';
// import 'dart:convert';
// import '../utils.dart';
import 'package:flutter/cupertino.dart';
class IosIssue extends StatelessWidget {
@override
Widget build(context) {
return new Text('Issue');
}
}

View File

@ -1,12 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'home.dart';
import 'home/index.dart';
import 'notification.dart';
import 'profile.dart';
import 'issue.dart';
class IosApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
build(context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
@ -14,6 +15,7 @@ class IosApp extends StatelessWidget {
),
home: new IosHomePage(title: 'GitFlux'),
routes: {
'/issue': (context) => new IosIssue()
// '/notification': (context) => new IosNotificationTab(),
// '/profile': (context) => new IosProfileTab(),
},
@ -42,9 +44,6 @@ class _IosHomePageState extends State<IosHomePage> {
@override
Widget build(context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
middle: new Text(widget.title),
),
child: new CupertinoTabScaffold(
tabBar: new CupertinoTabBar(
items: const <BottomNavigationBarItem>[

39
lib/ios/user.dart Normal file
View File

@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../utils.dart';
class IosUserPage extends StatelessWidget {
String login;
String avatar;
IosUserPage(this.login, this.avatar);
@override
build(context) {
return new CupertinoPageScaffold(
navigationBar: new CupertinoNavigationBar(
leading: new CupertinoButton(
child: const Text('Cancel'),
padding: EdgeInsets.zero,
onPressed: () {
Navigator.of(context).pop(false);
},
),
middle: new Text(login),
),
child: new FutureBuilder(
future: fetchUser(login),
builder: (context, snapshot) {
Widget widget;
if (snapshot.hasData) {
User user = snapshot.data;
return new Text('');
} else if (snapshot.hasError) {
widget = new Text("${snapshot.error}");
} else {
widget = new CupertinoActivityIndicator();
}
return widget;
},
));
}
}

View File

@ -6,20 +6,6 @@ import 'token.dart';
final prefix = 'https://api.github.com';
// class PushEvent extends Event {
// PushEvent(Map<String, dynamic> json) : super(json) {}
// }
// class IssuesEvent extends Event {
// String issueTitle;
// String issueUrl;
// IssuesEvent(Map<String, dynamic> json) : super(json) {
// issueTitle = json['issue']['title'];
// issueUrl = json['issue']['url'];
// }
// }
class Event {
String type;
String actor;
@ -28,23 +14,32 @@ class Event {
String repo;
Map<String, dynamic> payload;
Event(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
actor = json['actor']['login'];
avatar = json['actor']['avatar_url'];
repo = json['repo']['name'];
payload = json['payload'];
Event(data) {
id = data['id'];
type = data['type'];
actor = data['actor']['login'];
avatar = data['actor']['avatar_url'];
repo = data['repo']['name'];
payload = data['payload'];
}
}
// factory Event.fromJson(Map<String, dynamic> json) {
// switch (json['type']) {
// case 'PushEvent':
// return new PushEvent(json);
// default:
// return null;
// }
// }
class User {
String login;
String avatar;
String name;
int repos;
int followers;
int following;
User(data) {
login = data['login'];
avatar = data['avatar_url'];
name = data['name'];
repos = data['public_repos'];
followers = data['followers'];
following = data['following'];
}
}
Future<List<Event>> fetchEvents([int page = 1]) async {
@ -52,9 +47,19 @@ Future<List<Event>> fetchEvents([int page = 1]) async {
prefix + '/users/pd4d10/received_events/public?page=$page',
headers: {HttpHeaders.AUTHORIZATION: 'token $token'},
);
List<dynamic> resJson = json.decode(res.body);
List<dynamic> data = json.decode(res.body);
return resJson.map((item) {
return data.map((item) {
return new Event(item);
}).toList();
}
Future<User> fetchUser(String login) async {
final res = await http.get(
prefix + '/users/$login',
headers: {HttpHeaders.AUTHORIZATION: 'token $token'},
);
Map<String, dynamic> data = json.decode(res.body);
return new User(data);
}