mirror of
https://github.com/git-touch/git-touch
synced 2025-02-22 14:27:46 +01:00
Add
This commit is contained in:
parent
d6aeb873f1
commit
dd456132f4
0
lib/android/drawer.dart
Normal file
0
lib/android/drawer.dart
Normal file
111
lib/android/home.dart
Normal file
111
lib/android/home.dart
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import '../common/event.dart';
|
||||||
|
import '../utils.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
class HomePage extends StatefulWidget {
|
||||||
|
// HomePage({Key key, this.title, this.message}) : super(key: key);
|
||||||
|
HomePage(this.message);
|
||||||
|
|
||||||
|
// final String title;
|
||||||
|
final Function message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
createState() => _HomePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HomePageState extends State<HomePage> {
|
||||||
|
int page = 1;
|
||||||
|
List<Event> events = [];
|
||||||
|
bool isLoading = false;
|
||||||
|
|
||||||
|
loadFirst() async {
|
||||||
|
var data = await fetchEvents();
|
||||||
|
setState(() {
|
||||||
|
events.clear();
|
||||||
|
events.addAll(data);
|
||||||
|
// print(events);
|
||||||
|
page = 1;
|
||||||
|
// isLoading = false;
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadMore() async {
|
||||||
|
// if (isLoading) return;
|
||||||
|
// print('more');
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
var data = await fetchEvents(page + 1);
|
||||||
|
setState(() {
|
||||||
|
events.addAll(data);
|
||||||
|
// print(events.length);
|
||||||
|
page++;
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(BuildContext context) {
|
||||||
|
return FutureBuilder(
|
||||||
|
future: loadFirst(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
Widget widget;
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
widget = RefreshIndicator(
|
||||||
|
key: _refreshIndicatorKey,
|
||||||
|
onRefresh: () async {
|
||||||
|
await loadFirst();
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
child: ListView.builder(
|
||||||
|
// reverse: true,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
try {
|
||||||
|
if (index >= events.length) {
|
||||||
|
// print(events.length);
|
||||||
|
if (!isLoading) {
|
||||||
|
print('index: $index');
|
||||||
|
print('length: ${events.length}');
|
||||||
|
loadMore();
|
||||||
|
}
|
||||||
|
return Text('Loading...');
|
||||||
|
// print(index);
|
||||||
|
// Load next page
|
||||||
|
// return CupertinoActivityIndicator();
|
||||||
|
// if (isLoading) {
|
||||||
|
// return Text('Loading...');
|
||||||
|
// } else {
|
||||||
|
// // print(isLoading);
|
||||||
|
// // setState(() {
|
||||||
|
// // isLoading = true;
|
||||||
|
// // });
|
||||||
|
// return CupertinoRefreshControl();
|
||||||
|
// }
|
||||||
|
// return Text('Loading...');
|
||||||
|
}
|
||||||
|
|
||||||
|
return EventItem(events[index]);
|
||||||
|
} catch (err) {
|
||||||
|
return Text(err.toString());
|
||||||
|
// return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
widget = Text("${snapshot.error}");
|
||||||
|
} else {
|
||||||
|
widget = CupertinoActivityIndicator();
|
||||||
|
// widget = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'user.dart';
|
||||||
|
import 'home.dart';
|
||||||
|
|
||||||
class AndroidHomePage extends StatefulWidget {
|
class AndroidHomePage extends StatefulWidget {
|
||||||
AndroidHomePage({Key key, this.title}) : super(key: key);
|
AndroidHomePage({Key key, this.title}) : super(key: key);
|
||||||
@ -6,7 +8,7 @@ class AndroidHomePage extends StatefulWidget {
|
|||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AndroidHomePageState createState() => new _AndroidHomePageState();
|
_AndroidHomePageState createState() => _AndroidHomePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AndroidHomePageState extends State<AndroidHomePage> {
|
class _AndroidHomePageState extends State<AndroidHomePage> {
|
||||||
@ -18,17 +20,34 @@ class _AndroidHomePageState extends State<AndroidHomePage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
|
message() {
|
||||||
|
_scaffoldKey.currentState?.showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('Refresh complete'),
|
||||||
|
action: SnackBarAction(
|
||||||
|
label: 'RETRY',
|
||||||
|
onPressed: () {
|
||||||
|
// _refreshIndicatorKey.currentState.show();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return new Scaffold(
|
return Scaffold(
|
||||||
drawer: new Drawer(
|
key: _scaffoldKey,
|
||||||
child: new Column(
|
drawer: Drawer(
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
new UserAccountsDrawerHeader(
|
UserAccountsDrawerHeader(
|
||||||
accountName: const Text('xxx'),
|
accountName: Text('123'),
|
||||||
accountEmail: const Text('xxx@gmail.com'),
|
accountEmail: Text('xxx@gmail.com'),
|
||||||
currentAccountPicture: const CircleAvatar(
|
currentAccountPicture: CircleAvatar(
|
||||||
backgroundImage: const NetworkImage(
|
backgroundImage: NetworkImage(
|
||||||
'https://avatars0.githubusercontent.com/u/9524411',
|
'https://avatars0.githubusercontent.com/u/9524411',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -36,24 +55,37 @@ class _AndroidHomePageState extends State<AndroidHomePage> {
|
|||||||
// onDetailsPressed: () {
|
// onDetailsPressed: () {
|
||||||
// },
|
// },
|
||||||
),
|
),
|
||||||
new MediaQuery.removePadding(
|
MediaQuery.removePadding(
|
||||||
context: context,
|
context: context,
|
||||||
// DrawerHeader consumes top MediaQuery padding.
|
// DrawerHeader consumes top MediaQuery padding.
|
||||||
removeTop: true,
|
removeTop: true,
|
||||||
child: new Expanded(
|
child: Expanded(
|
||||||
child: new ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
padding: EdgeInsets.only(top: 8.0),
|
||||||
children: <Widget>[
|
children: [
|
||||||
new Stack(
|
Stack(
|
||||||
children: [
|
children: [
|
||||||
new Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: ['A', 'B'].map((String id) {
|
children: ['Home', 'Settings'].map((id) {
|
||||||
return new ListTile(
|
return ListTile(
|
||||||
leading: new CircleAvatar(child: new Text(id)),
|
// leading: CircleAvatar(child: Text(id)),
|
||||||
title: new Text('Drawer item $id'),
|
title: Text(id),
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
var route = PageRouteBuilder(
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: 'test',
|
||||||
|
isInitialRoute: false,
|
||||||
|
),
|
||||||
|
pageBuilder:
|
||||||
|
(context, animation, secondaryAnimation) {
|
||||||
|
return UserPage('a', 'avatar');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Navigator.of(context).push(route);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
)
|
)
|
||||||
@ -66,27 +98,14 @@ class _AndroidHomePageState extends State<AndroidHomePage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
appBar: new AppBar(
|
appBar: AppBar(
|
||||||
title: new Text(widget.title),
|
title: Text(widget.title),
|
||||||
),
|
),
|
||||||
body: new Center(
|
body: HomePage(message),
|
||||||
child: new Column(
|
floatingActionButton: FloatingActionButton(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
new Text(
|
|
||||||
'You have pushed the button this many times:',
|
|
||||||
),
|
|
||||||
new Text(
|
|
||||||
'$_counter',
|
|
||||||
style: Theme.of(context).textTheme.display1,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: new FloatingActionButton(
|
|
||||||
onPressed: _incrementCounter,
|
onPressed: _incrementCounter,
|
||||||
tooltip: 'Increment',
|
tooltip: 'Increment',
|
||||||
child: new Icon(Icons.add),
|
child: Icon(Icons.add),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
58
lib/android/user.dart
Normal file
58
lib/android/user.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
// import '../utils.dart';
|
||||||
|
|
||||||
|
enum AppBarBehavior { normal, pinned, floating, snapping }
|
||||||
|
|
||||||
|
class UserPage extends StatelessWidget {
|
||||||
|
final String login;
|
||||||
|
final String avatar;
|
||||||
|
UserPage(this.login, this.avatar);
|
||||||
|
final double _appBarHeight = 256.0;
|
||||||
|
|
||||||
|
AppBarBehavior _appBarBehavior = AppBarBehavior.pinned;
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: CustomScrollView(slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
expandedHeight: _appBarHeight,
|
||||||
|
pinned: _appBarBehavior == AppBarBehavior.pinned,
|
||||||
|
floating: _appBarBehavior == AppBarBehavior.floating ||
|
||||||
|
_appBarBehavior == AppBarBehavior.snapping,
|
||||||
|
snap: _appBarBehavior == AppBarBehavior.snapping,
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.edit),
|
||||||
|
tooltip: 'Edit',
|
||||||
|
onPressed: () {
|
||||||
|
// _scaffoldKey.currentState.showSnackBar( SnackBar(
|
||||||
|
// content: Text(
|
||||||
|
// 'This is actually just a demo. Editing isn\'t supported.')));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
title: Text(login),
|
||||||
|
background: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment(0.0, -1.0),
|
||||||
|
end: Alignment(0.0, -0.4),
|
||||||
|
colors: <Color>[
|
||||||
|
Color(0x60000000),
|
||||||
|
Color(0x00000000)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
205
lib/common/event.dart
Normal file
205
lib/common/event.dart
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
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 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventItem extends StatelessWidget {
|
||||||
|
final Event event;
|
||||||
|
EventItem(this.event);
|
||||||
|
|
||||||
|
getEventItemByType() {
|
||||||
|
switch (event.type) {
|
||||||
|
case 'IssuesEvent':
|
||||||
|
return IssuesEvent(event);
|
||||||
|
case 'PushEvent':
|
||||||
|
return PushEvent(event);
|
||||||
|
case 'PullRequestEvent':
|
||||||
|
return PullRequestEvent(event);
|
||||||
|
case 'WatchEvent':
|
||||||
|
return WatchEvent(event);
|
||||||
|
default:
|
||||||
|
return Text('Not implement yet');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(context) {
|
||||||
|
// Padding(padding: EdgeInsets.only(top: 16.0)),
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
_Avatar(event.avatar),
|
||||||
|
Expanded(child: getEventItemByType()),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
// TapGestureRecognizer()
|
||||||
|
// ..onTap = () {
|
||||||
|
// Navigator.of(context).push(
|
||||||
|
// CupertinoPageRoute(
|
||||||
|
// builder: (context) {
|
||||||
|
// return IosUserPage(event.actor, event.avatar);
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PushEvent extends StatelessWidget {
|
||||||
|
final Event event;
|
||||||
|
PushEvent(this.event);
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(context) {
|
||||||
|
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),
|
||||||
|
TextSpan(text: '')
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
TextSpan(
|
||||||
|
text: '#' + event.payload['issue']['number'].toString(),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: event.payload['issue']['title'],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PullRequestEvent extends StatelessWidget {
|
||||||
|
final Event event;
|
||||||
|
PullRequestEvent(this.event);
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(context) {
|
||||||
|
return RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
style: TextStyle(color: CupertinoColors.black),
|
||||||
|
children: [
|
||||||
|
_user(event, context),
|
||||||
|
TextSpan(text: ' ${event.payload['action']} pull request '),
|
||||||
|
_strong(event.repo),
|
||||||
|
TextSpan(text: '#' + event.payload['number'].toString()),
|
||||||
|
TextSpan(text: event.payload['pull_request']['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),
|
||||||
|
TextSpan(text: '#' + event.payload['issue']['number'].toString()),
|
||||||
|
TextSpan(text: event.payload['comment']['body'])
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WatchEvent extends StatelessWidget {
|
||||||
|
final Event event;
|
||||||
|
WatchEvent(this.event);
|
||||||
|
|
||||||
|
@override
|
||||||
|
build(context) {
|
||||||
|
return RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
style: TextStyle(color: CupertinoColors.black),
|
||||||
|
children: [
|
||||||
|
_user(event, context),
|
||||||
|
TextSpan(text: ' ${event.payload['action']} '),
|
||||||
|
_strong(event.repo),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
78
lib/ios/home.dart
Normal file
78
lib/ios/home.dart
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// 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 '../common/event.dart';
|
||||||
|
import 'user.dart';
|
||||||
|
|
||||||
|
class IosHomeTab extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
createState() {
|
||||||
|
return IosHomeTabState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IosHomeTabState extends State<IosHomeTab> {
|
||||||
|
int page = 1;
|
||||||
|
List<Event> events = [];
|
||||||
|
|
||||||
|
loadFirst() async {
|
||||||
|
events = await fetchEvents();
|
||||||
|
print(events);
|
||||||
|
page = 1;
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadMore() async {
|
||||||
|
events.addAll(await fetchEvents(page + 1));
|
||||||
|
page++;
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
|
||||||
|
GlobalKey<RefreshIndicatorState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(context) {
|
||||||
|
return CupertinoPageScaffold(
|
||||||
|
navigationBar: CupertinoNavigationBar(
|
||||||
|
middle: Text('Home'),
|
||||||
|
),
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: loadFirst(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
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(events[index]);
|
||||||
|
} catch (err) {
|
||||||
|
return Text(err.toString());
|
||||||
|
// return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
widget = Text("${snapshot.error}");
|
||||||
|
} else {
|
||||||
|
widget = CupertinoActivityIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,144 +0,0 @@
|
|||||||
import '../../utils.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import '../issue.dart';
|
|
||||||
import '../user.dart';
|
|
||||||
|
|
||||||
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);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class PushEvent extends StatelessWidget {
|
|
||||||
final Event event;
|
|
||||||
PushEvent(this.event);
|
|
||||||
|
|
||||||
@override
|
|
||||||
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: '')
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class IssuesEvent extends StatelessWidget {
|
|
||||||
final Event event;
|
|
||||||
IssuesEvent(this.event);
|
|
||||||
|
|
||||||
@override
|
|
||||||
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'],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PullRequestEvent extends StatelessWidget {
|
|
||||||
final Event event;
|
|
||||||
PullRequestEvent(this.event);
|
|
||||||
|
|
||||||
@override
|
|
||||||
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'])
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class IssueCommentEvent extends StatelessWidget {
|
|
||||||
final Event event;
|
|
||||||
IssueCommentEvent(this.event);
|
|
||||||
|
|
||||||
@override
|
|
||||||
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'])
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WatchEvent extends StatelessWidget {
|
|
||||||
final Event event;
|
|
||||||
WatchEvent(this.event);
|
|
||||||
|
|
||||||
@override
|
|
||||||
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),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
// 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;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,6 +6,6 @@ import 'package:flutter/cupertino.dart';
|
|||||||
class IosIssue extends StatelessWidget {
|
class IosIssue extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(context) {
|
Widget build(context) {
|
||||||
return new Text('Issue');
|
return Text('Issue');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'home/index.dart';
|
import 'home.dart';
|
||||||
import 'notification.dart';
|
import 'notification.dart';
|
||||||
import 'profile.dart';
|
import 'profile.dart';
|
||||||
import 'issue.dart';
|
import 'issue.dart';
|
||||||
@ -11,7 +11,7 @@ class IosHomePage extends StatefulWidget {
|
|||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_IosHomePageState createState() => new _IosHomePageState();
|
_IosHomePageState createState() => _IosHomePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _IosHomePageState extends State<IosHomePage> {
|
class _IosHomePageState extends State<IosHomePage> {
|
||||||
@ -25,42 +25,42 @@ class _IosHomePageState extends State<IosHomePage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(context) {
|
Widget build(context) {
|
||||||
return new CupertinoPageScaffold(
|
return CupertinoPageScaffold(
|
||||||
child: new CupertinoTabScaffold(
|
child: CupertinoTabScaffold(
|
||||||
tabBar: new CupertinoTabBar(
|
tabBar: CupertinoTabBar(
|
||||||
items: const <BottomNavigationBarItem>[
|
items: <BottomNavigationBarItem>[
|
||||||
const BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: const Icon(CupertinoIcons.home),
|
icon: Icon(CupertinoIcons.home),
|
||||||
title: const Text('Home'),
|
title: Text('Home'),
|
||||||
),
|
),
|
||||||
const BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: const Icon(CupertinoIcons.conversation_bubble),
|
icon: Icon(CupertinoIcons.conversation_bubble),
|
||||||
title: const Text('Notification'),
|
title: Text('Notification'),
|
||||||
),
|
),
|
||||||
const BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: const Icon(CupertinoIcons.profile_circled),
|
icon: Icon(CupertinoIcons.profile_circled),
|
||||||
title: const Text('Profile'),
|
title: Text('Profile'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
tabBuilder: (context, int index) {
|
tabBuilder: (context, index) {
|
||||||
return new DefaultTextStyle(
|
return DefaultTextStyle(
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: '.SF UI Text',
|
// fontFamily: '.SF UI Text',
|
||||||
fontSize: 17.0,
|
// fontSize: 17.0,
|
||||||
color: CupertinoColors.black,
|
color: CupertinoColors.black,
|
||||||
),
|
),
|
||||||
child: new CupertinoTabView(
|
child: CupertinoTabView(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
return new IosHomeTab();
|
return IosHomeTab();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
return new IosNotificationTab();
|
return IosNotificationTab();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
return new IosProfileTab();
|
return IosProfileTab();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@ import 'package:flutter/cupertino.dart';
|
|||||||
class IosNotificationTab extends StatelessWidget {
|
class IosNotificationTab extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(context) {
|
Widget build(context) {
|
||||||
return new Text('Notification');
|
return Text('Notification');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@ import 'package:flutter/cupertino.dart';
|
|||||||
class IosProfileTab extends StatelessWidget {
|
class IosProfileTab extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(context) {
|
Widget build(context) {
|
||||||
return new Text('Profile');
|
return Text('Profile');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,31 +9,32 @@ class IosUserPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
build(context) {
|
build(context) {
|
||||||
return new CupertinoPageScaffold(
|
return CupertinoPageScaffold(
|
||||||
navigationBar: new CupertinoNavigationBar(
|
navigationBar: CupertinoNavigationBar(
|
||||||
leading: new CupertinoButton(
|
leading: CupertinoButton(
|
||||||
child: const Text('Cancel'),
|
child: Text('Cancel'),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(false);
|
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;
|
|
||||||
},
|
},
|
||||||
));
|
),
|
||||||
|
middle: Text(login),
|
||||||
|
),
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: fetchUser(login),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
Widget widget;
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
User user = snapshot.data;
|
||||||
|
return Text('');
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
widget = Text("${snapshot.error}");
|
||||||
|
} else {
|
||||||
|
widget = CupertinoActivityIndicator();
|
||||||
|
}
|
||||||
|
return widget;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,22 +3,24 @@ import 'android/main.dart';
|
|||||||
import 'ios/main.dart';
|
import 'ios/main.dart';
|
||||||
|
|
||||||
class App extends StatelessWidget {
|
class App extends StatelessWidget {
|
||||||
final isIos = true;
|
final isIos = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
build(context) {
|
build(context) {
|
||||||
return new MaterialApp(
|
return MaterialApp(
|
||||||
title: 'GitFlux',
|
title: 'GitFlux',
|
||||||
theme: new ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
),
|
),
|
||||||
home: isIos ? new IosHomePage(title: 'GitFlux') : new AndroidHomePage(title: 'GitFlux'),
|
home: isIos
|
||||||
|
? IosHomePage(title: 'GitFlux')
|
||||||
|
: AndroidHomePage(title: 'GitFlux'),
|
||||||
routes: {
|
routes: {
|
||||||
// '/notification': (context) => new IosNotificationTab(),
|
// '/notification': (context) => IosNotificationTab(),
|
||||||
// '/profile': (context) => new IosProfileTab(),
|
// '/profile': (context) => IosProfileTab(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() => runApp(new App());
|
void main() => runApp(App());
|
||||||
|
@ -14,7 +14,7 @@ class Event {
|
|||||||
String repo;
|
String repo;
|
||||||
Map<String, dynamic> payload;
|
Map<String, dynamic> payload;
|
||||||
|
|
||||||
Event(data) {
|
Event.fromJson(data) {
|
||||||
id = data['id'];
|
id = data['id'];
|
||||||
type = data['type'];
|
type = data['type'];
|
||||||
actor = data['actor']['login'];
|
actor = data['actor']['login'];
|
||||||
@ -32,7 +32,7 @@ class User {
|
|||||||
int followers;
|
int followers;
|
||||||
int following;
|
int following;
|
||||||
|
|
||||||
User(data) {
|
User.fromJson(data) {
|
||||||
login = data['login'];
|
login = data['login'];
|
||||||
avatar = data['avatar_url'];
|
avatar = data['avatar_url'];
|
||||||
name = data['name'];
|
name = data['name'];
|
||||||
@ -50,7 +50,7 @@ Future<List<Event>> fetchEvents([int page = 1]) async {
|
|||||||
List<dynamic> data = json.decode(res.body);
|
List<dynamic> data = json.decode(res.body);
|
||||||
|
|
||||||
return data.map((item) {
|
return data.map((item) {
|
||||||
return new Event(item);
|
return Event.fromJson(item);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,5 +61,5 @@ Future<User> fetchUser(String login) async {
|
|||||||
);
|
);
|
||||||
Map<String, dynamic> data = json.decode(res.body);
|
Map<String, dynamic> data = json.decode(res.body);
|
||||||
|
|
||||||
return new User(data);
|
return User.fromJson(data);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user