feat: extract provider, add android news screen
This commit is contained in:
parent
9ae00dff6d
commit
908d6df478
|
@ -0,0 +1,40 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
import 'news.dart';
|
||||
|
||||
class AndroidHome extends StatefulWidget {
|
||||
@override
|
||||
createState() => _AndroidHomeState();
|
||||
}
|
||||
|
||||
class _AndroidHomeState extends State<AndroidHome> {
|
||||
int active = 0;
|
||||
|
||||
Widget _buildBody() {
|
||||
switch (active) {
|
||||
case 0:
|
||||
return NewsScreen();
|
||||
default:
|
||||
return Text('d');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return Scaffold(
|
||||
// appBar: AppBar(title: Text('Home')),
|
||||
body: _buildBody(),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
items: buildNavigationItems(),
|
||||
currentIndex: active,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
onTap: (int index) {
|
||||
setState(() {
|
||||
active = index;
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import '../components/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,112 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'user.dart';
|
||||
import 'home.dart';
|
||||
|
||||
class AndroidHomePage extends StatefulWidget {
|
||||
AndroidHomePage({Key key, this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
_AndroidHomePageState createState() => _AndroidHomePageState();
|
||||
}
|
||||
|
||||
class _AndroidHomePageState extends State<AndroidHomePage> {
|
||||
int _counter = 0;
|
||||
|
||||
void _incrementCounter() {
|
||||
setState(() {
|
||||
_counter++;
|
||||
});
|
||||
}
|
||||
|
||||
final _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
message() {
|
||||
_scaffoldKey.currentState?.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Refresh complete'),
|
||||
action: SnackBarAction(
|
||||
label: 'RETRY',
|
||||
onPressed: () {
|
||||
// _refreshIndicatorKey.currentState.show();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
drawer: Drawer(
|
||||
child: Column(
|
||||
children: [
|
||||
UserAccountsDrawerHeader(
|
||||
accountName: Text('123'),
|
||||
accountEmail: Text('xxx@gmail.com'),
|
||||
currentAccountPicture: CircleAvatar(
|
||||
backgroundImage: NetworkImage(
|
||||
'https://avatars0.githubusercontent.com/u/9524411',
|
||||
),
|
||||
),
|
||||
margin: EdgeInsets.zero,
|
||||
// onDetailsPressed: () {
|
||||
// },
|
||||
),
|
||||
MediaQuery.removePadding(
|
||||
context: context,
|
||||
// DrawerHeader consumes top MediaQuery padding.
|
||||
removeTop: true,
|
||||
child: Expanded(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: ['Home', 'Settings'].map((id) {
|
||||
return ListTile(
|
||||
// leading: CircleAvatar(child: Text(id)),
|
||||
title: Text(id),
|
||||
onTap: () {
|
||||
var route = PageRouteBuilder(
|
||||
settings: RouteSettings(
|
||||
name: 'test',
|
||||
isInitialRoute: false,
|
||||
),
|
||||
pageBuilder:
|
||||
(context, animation, secondaryAnimation) {
|
||||
return UserPage('a', 'avatar');
|
||||
},
|
||||
);
|
||||
|
||||
Navigator.of(context).push(route);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
appBar: AppBar(
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: HomePage(message),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _incrementCounter,
|
||||
tooltip: 'Increment',
|
||||
child: Icon(Icons.add),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
import 'package:git_flux/widgets/news_provider.dart';
|
||||
import 'package:git_flux/widgets/event_item.dart';
|
||||
|
||||
class NewsScreen extends StatefulWidget {
|
||||
@override
|
||||
NewsScreenState createState() => NewsScreenState();
|
||||
}
|
||||
|
||||
class NewsScreenState extends State<NewsScreen> {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return NewsProvider(_buildWithData);
|
||||
}
|
||||
|
||||
Widget _buildWithData(
|
||||
{ScrollController controller, Refresh refresh, List<Event> events}) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('News')),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: refresh,
|
||||
child: ListView.builder(
|
||||
controller: controller,
|
||||
itemCount: events.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == events.length) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15),
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
} else {
|
||||
return EventItem(events[index]);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
import 'package:flutter/material.dart';
|
|
@ -1,104 +0,0 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
import 'package:git_flux/widgets/widgets.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
@override
|
||||
createState() {
|
||||
return HomeScreenState();
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
super.initState();
|
||||
// FIXME: context hack
|
||||
// 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);
|
||||
|
||||
return CupertinoPageScaffold(
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
import 'news.dart';
|
||||
import 'notification.dart';
|
||||
import 'search.dart';
|
||||
import 'profile.dart';
|
||||
|
||||
class IosHome extends StatefulWidget {
|
||||
IosHome({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_IosHomeState createState() => _IosHomeState();
|
||||
}
|
||||
|
||||
class _IosHomeState extends State<IosHome> {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return CupertinoTheme(
|
||||
data: CupertinoThemeData(
|
||||
// brightness: Brightness.dark,
|
||||
// barBackgroundColor: Color.fromRGBO(0x24, 0x29, 0x2e, 1),
|
||||
),
|
||||
child: CupertinoTabScaffold(
|
||||
tabBar: CupertinoTabBar(items: buildNavigationItems()),
|
||||
tabBuilder: (context, index) {
|
||||
return CupertinoTabView(builder: (context) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return NewsScreen();
|
||||
case 1:
|
||||
return NotificationScreen();
|
||||
case 2:
|
||||
return SearchScreen();
|
||||
case 3:
|
||||
return ProfileScreen();
|
||||
default:
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'home.dart';
|
||||
import 'notification.dart';
|
||||
import 'search.dart';
|
||||
import 'profile.dart';
|
||||
|
||||
class IosHomePage extends StatefulWidget {
|
||||
IosHomePage({Key key, this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
_IosHomePageState createState() => _IosHomePageState();
|
||||
}
|
||||
|
||||
class _IosHomePageState extends State<IosHomePage> {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return CupertinoTheme(
|
||||
data: CupertinoThemeData(
|
||||
// brightness: Brightness.dark,
|
||||
// barBackgroundColor: Color.fromRGBO(0x24, 0x29, 0x2e, 1),
|
||||
),
|
||||
child: CupertinoTabScaffold(
|
||||
tabBar: CupertinoTabBar(
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.rss_feed),
|
||||
title: Text('News'),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: StreamBuilder<int>(builder: (context, snapshot) {
|
||||
int count = snapshot.data;
|
||||
print(count);
|
||||
|
||||
// https://stackoverflow.com/a/45434404
|
||||
if (count != null && count > 0) {
|
||||
return Stack(children: <Widget>[
|
||||
Icon(Icons.notifications),
|
||||
Positioned(
|
||||
// draw a red marble
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: Icon(Icons.brightness_1,
|
||||
size: 8.0, color: Colors.redAccent),
|
||||
)
|
||||
]);
|
||||
} else {
|
||||
return Icon(Icons.notifications);
|
||||
}
|
||||
}),
|
||||
title: Text('Notification'),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.search),
|
||||
title: Text('Search'),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.person),
|
||||
title: Text('Me'),
|
||||
),
|
||||
],
|
||||
),
|
||||
tabBuilder: (context, index) {
|
||||
return CupertinoTabView(builder: (context) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return HomeScreen();
|
||||
case 1:
|
||||
return NotificationScreen();
|
||||
case 2:
|
||||
return SearchScreen();
|
||||
case 3:
|
||||
return ProfileScreen();
|
||||
default:
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
import 'package:git_flux/widgets/news_provider.dart';
|
||||
import 'package:git_flux/widgets/event_item.dart';
|
||||
|
||||
class NewsScreen extends StatefulWidget {
|
||||
@override
|
||||
NewsScreenState createState() => NewsScreenState();
|
||||
}
|
||||
|
||||
class NewsScreenState extends State<NewsScreen> {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return NewsProvider(_buildWithData);
|
||||
}
|
||||
|
||||
Widget _buildWithData({
|
||||
ScrollController controller,
|
||||
Refresh refresh,
|
||||
List<Event> events,
|
||||
}) {
|
||||
return CupertinoPageScaffold(
|
||||
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 Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15),
|
||||
child: CupertinoActivityIndicator(radius: 12),
|
||||
);
|
||||
} else {
|
||||
return EventItem(events[index]);
|
||||
}
|
||||
},
|
||||
childCount: events.length + 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,17 +1,31 @@
|
|||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
// import 'package:device_info/device_info.dart';
|
||||
import 'package:git_flux/providers/providers.dart';
|
||||
import 'package:git_flux/ios/main.dart';
|
||||
import 'package:git_flux/screens/screens.dart';
|
||||
import 'package:git_flux/ios/ios.dart';
|
||||
import 'package:git_flux/android/android.dart';
|
||||
|
||||
class App extends StatelessWidget {
|
||||
final isIos = true;
|
||||
final isIos = Platform.isIOS;
|
||||
final EventBloc eventBloc;
|
||||
final NotificationBloc notificationBloc;
|
||||
final SearchBloc searchBloc;
|
||||
|
||||
App(this.eventBloc, this.notificationBloc, this.searchBloc);
|
||||
|
||||
_buildScreen() {
|
||||
// return IssueScreen(11609, 'flutter', 'flutter');
|
||||
|
||||
// return IosHome();
|
||||
|
||||
if (Platform.isIOS) {
|
||||
return IosHome();
|
||||
} else if (Platform.isAndroid) {
|
||||
return AndroidHome();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return SearchProvider(
|
||||
|
@ -23,8 +37,7 @@ class App extends StatelessWidget {
|
|||
child: MaterialApp(
|
||||
home: DefaultTextStyle(
|
||||
style: TextStyle(color: Color(0xff24292e)),
|
||||
child: IosHomePage(title: 'GitFlux'),
|
||||
// child: IssueScreen(11609, 'flutter', 'flutter'),
|
||||
child: _buildScreen(),
|
||||
),
|
||||
// theme: ThemeData(
|
||||
// textTheme: TextTheme(
|
||||
|
@ -38,10 +51,17 @@ class App extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
void main() async {
|
||||
EventBloc eventBloc = EventBloc();
|
||||
NotificationBloc notificationBloc = NotificationBloc();
|
||||
SearchBloc searchBloc = SearchBloc();
|
||||
|
||||
// DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||
// AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||
// print('Running on ${androidInfo.model}'); // e.g. "Moto G (4)"
|
||||
|
||||
// IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
|
||||
// print('Running on ${iosInfo.utsname.machine}'); // e.g. "iPod7,1"
|
||||
|
||||
runApp(App(eventBloc, notificationBloc, searchBloc));
|
||||
}
|
||||
|
|
|
@ -1,8 +1,70 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:git_flux/screens/screens.dart';
|
||||
export 'github.dart';
|
||||
export 'octicons.dart';
|
||||
export 'timeago.dart';
|
||||
|
||||
TextSpan createLinkSpan(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 createRepoLinkSpan(BuildContext context, String owner, String name) {
|
||||
return createLinkSpan(context, '$owner/$name', () => RepoScreen(owner, name));
|
||||
}
|
||||
|
||||
List<BottomNavigationBarItem> buildNavigationItems() => [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.rss_feed),
|
||||
title: Text('News'),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: StreamBuilder<int>(builder: (context, snapshot) {
|
||||
int count = snapshot.data;
|
||||
print(count);
|
||||
|
||||
// https://stackoverflow.com/a/45434404
|
||||
if (count != null && count > 0) {
|
||||
return Stack(children: <Widget>[
|
||||
Icon(Icons.notifications),
|
||||
Positioned(
|
||||
// draw a red marble
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: Icon(Icons.brightness_1,
|
||||
size: 8.0, color: Colors.redAccent),
|
||||
)
|
||||
]);
|
||||
} else {
|
||||
return Icon(Icons.notifications);
|
||||
}
|
||||
}),
|
||||
title: Text('Notification'),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.search),
|
||||
title: Text('Search'),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.person),
|
||||
title: Text('Me'),
|
||||
),
|
||||
];
|
||||
|
||||
class Palette {
|
||||
static const green = 0xff2cbe4e;
|
||||
static const purple = 0xff6f42c1;
|
||||
|
|
|
@ -68,6 +68,10 @@ class EventItem extends StatelessWidget {
|
|||
case 'ForkEvent':
|
||||
return TextSpan(children: [
|
||||
TextSpan(text: ' forked '),
|
||||
createRepoLinkSpan(context, event.payload['forkee']['owner']['login'],
|
||||
event.payload['forkee']['name']),
|
||||
TextSpan(text: ' from '),
|
||||
_buildRepo(context),
|
||||
]);
|
||||
default:
|
||||
return TextSpan(
|
||||
|
@ -116,7 +120,7 @@ class EventItem extends StatelessWidget {
|
|||
TextSpan _buildRepo(BuildContext context) {
|
||||
String name = event.repo.name;
|
||||
var arr = name.split('/');
|
||||
return _buildLink(context, name, () => RepoScreen(arr[0], arr[1]));
|
||||
return createRepoLinkSpan(context, arr[0], arr[1]);
|
||||
}
|
||||
|
||||
TextSpan _buildIssue(BuildContext context) {
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_flux/utils/utils.dart';
|
||||
|
||||
typedef Future<void> Refresh();
|
||||
typedef Widget BuildWithContent(
|
||||
{List<Event> events, ScrollController controller, Refresh refresh});
|
||||
|
||||
class NewsProvider extends StatefulWidget {
|
||||
final BuildWithContent build;
|
||||
|
||||
NewsProvider(this.build);
|
||||
|
||||
@override
|
||||
NewsProviderState createState() => NewsProviderState();
|
||||
}
|
||||
|
||||
class NewsProviderState extends State<NewsProvider> {
|
||||
int page = 1;
|
||||
bool loading = false;
|
||||
List<Event> _events = [];
|
||||
ScrollController _controller = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_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;
|
||||
});
|
||||
}
|
||||
|
||||
_loadMore() async {
|
||||
print('more');
|
||||
setState(() {
|
||||
loading = true;
|
||||
});
|
||||
page = page + 1;
|
||||
var items = await fetchEvents(page);
|
||||
setState(() {
|
||||
loading = false;
|
||||
_events.addAll(items);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(context) {
|
||||
return widget.build(
|
||||
events: _events, controller: _controller, refresh: _refresh);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
export 'avatar.dart';
|
||||
export 'event_item.dart';
|
||||
export 'user_name.dart';
|
||||
export 'timeline_item.dart';
|
||||
export 'comment_item.dart';
|
||||
|
|
Loading…
Reference in New Issue