mirror of
https://github.com/git-touch/git-touch
synced 2025-01-20 19:28:42 +01:00
refactor: move screens to screens folder
This commit is contained in:
parent
23003bcff9
commit
cde5b21dcd
@ -1,43 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'news.dart';
|
||||
import 'notifications.dart';
|
||||
|
||||
class AndroidHome extends StatefulWidget {
|
||||
@override
|
||||
createState() => _AndroidHomeState();
|
||||
}
|
||||
|
||||
class _AndroidHomeState extends State<AndroidHome> {
|
||||
int active = 0;
|
||||
|
||||
Widget _buildBody() {
|
||||
switch (active) {
|
||||
case 0:
|
||||
return NewsScreen();
|
||||
case 1:
|
||||
return NotificationScreen();
|
||||
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,48 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:git_touch/widgets/news_provider.dart';
|
||||
import 'package:git_touch/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: () async {
|
||||
await refresh();
|
||||
// Scaffold.of(context).showSnackBar(SnackBar(
|
||||
// content: Container(
|
||||
// child: Text('data'),
|
||||
// padding: EdgeInsets.only(bottom: 10),
|
||||
// )
|
||||
// ));
|
||||
},
|
||||
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]);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
import 'dart:core';
|
||||
import 'package:flutter/material.dart' hide Notification;
|
||||
import 'package:flutter/cupertino.dart' hide Notification;
|
||||
import 'package:git_touch/providers/notification.dart';
|
||||
import 'package:git_touch/widgets/notification_item.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
|
||||
class NotificationGroup {
|
||||
String fullName;
|
||||
List<Notification> items = [];
|
||||
|
||||
NotificationGroup(this.fullName);
|
||||
}
|
||||
|
||||
class NotificationScreen extends StatefulWidget {
|
||||
@override
|
||||
NotificationScreenState createState() => NotificationScreenState();
|
||||
}
|
||||
|
||||
class NotificationScreenState extends State<NotificationScreen> {
|
||||
int active = 0;
|
||||
bool loading = false;
|
||||
List<NotificationGroup> groups = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Future.delayed(Duration(seconds: 0)).then((_) {
|
||||
_onSwitchTab(context, 0);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildGroupItem(BuildContext context, int index) {
|
||||
var group = groups[index];
|
||||
|
||||
return Container(
|
||||
// padding: EdgeInsets.all(10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 10, left: 4, bottom: 4),
|
||||
color: CupertinoColors.extraLightBackgroundGray,
|
||||
child: Text(
|
||||
group.fullName,
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: group.items
|
||||
.map((item) => NotificationItem(item: item))
|
||||
.toList())
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onSwitchTab(BuildContext context, int index) async {
|
||||
setState(() {
|
||||
active = index;
|
||||
loading = true;
|
||||
});
|
||||
|
||||
var ns = await ghClient.activity
|
||||
.listNotifications(all: index == 2, participating: index == 1)
|
||||
.toList();
|
||||
|
||||
NotificationProvider.of(context).countUpdate.add(ns.length);
|
||||
|
||||
Map<String, NotificationGroup> groupMap = {};
|
||||
ns.forEach((item) {
|
||||
String repo = item.repository.fullName;
|
||||
if (groupMap[repo] == null) {
|
||||
groupMap[repo] = NotificationGroup(repo);
|
||||
}
|
||||
|
||||
groupMap[repo].items.add(item);
|
||||
});
|
||||
|
||||
setState(() {
|
||||
groups = groupMap.values.toList();
|
||||
loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Notification')),
|
||||
body: ListView.builder(
|
||||
itemCount: groups.length,
|
||||
itemBuilder: _buildGroupItem,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
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)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
]));
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/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,11 +0,0 @@
|
||||
// import 'dart:async';
|
||||
// import 'dart:convert';
|
||||
// import '../utils.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class IosIssue extends StatelessWidget {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return Text('Issue');
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:git_touch/widgets/news_provider.dart';
|
||||
import 'package:git_touch/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,114 +0,0 @@
|
||||
import 'package:flutter/material.dart' hide Notification;
|
||||
import 'package:flutter/cupertino.dart' hide Notification;
|
||||
import 'package:git_touch/providers/notification.dart';
|
||||
import 'package:git_touch/widgets/notification_item.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
|
||||
class NotificationGroup {
|
||||
String fullName;
|
||||
List<Notification> items = [];
|
||||
|
||||
NotificationGroup(this.fullName);
|
||||
}
|
||||
|
||||
class NotificationScreen extends StatefulWidget {
|
||||
@override
|
||||
NotificationScreenState createState() => NotificationScreenState();
|
||||
}
|
||||
|
||||
class NotificationScreenState extends State<NotificationScreen> {
|
||||
int active = 0;
|
||||
bool loading = false;
|
||||
List<NotificationGroup> groups = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Future.delayed(Duration(seconds: 0)).then((_) {
|
||||
_onSwitchTab(context, 0);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildGroupItem(BuildContext context, int index) {
|
||||
var group = groups[index];
|
||||
|
||||
return Container(
|
||||
// padding: EdgeInsets.all(10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 10, left: 4, bottom: 4),
|
||||
color: CupertinoColors.extraLightBackgroundGray,
|
||||
child: Text(
|
||||
group.fullName,
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: group.items
|
||||
.map((item) => NotificationItem(item: item))
|
||||
.toList())
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onSwitchTab(BuildContext context, int index) async {
|
||||
setState(() {
|
||||
active = index;
|
||||
loading = true;
|
||||
});
|
||||
|
||||
var ns = await ghClient.activity
|
||||
.listNotifications(all: index == 2, participating: index == 1)
|
||||
.toList();
|
||||
|
||||
NotificationProvider.of(context).countUpdate.add(ns.length);
|
||||
|
||||
Map<String, NotificationGroup> groupMap = {};
|
||||
ns.forEach((item) {
|
||||
String repo = item.repository.fullName;
|
||||
if (groupMap[repo] == null) {
|
||||
groupMap[repo] = NotificationGroup(repo);
|
||||
}
|
||||
|
||||
groupMap[repo].items.add(item);
|
||||
});
|
||||
|
||||
setState(() {
|
||||
groups = groupMap.values.toList();
|
||||
loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(context) {
|
||||
NotificationBloc bloc = NotificationProvider.of(context);
|
||||
TextStyle _textStyle = DefaultTextStyle.of(context).style;
|
||||
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: SizedBox.expand(
|
||||
child: DefaultTextStyle(
|
||||
style: _textStyle,
|
||||
child: CupertinoSegmentedControl(
|
||||
groupValue: active,
|
||||
onValueChanged: (index) => _onSwitchTab(context, index),
|
||||
children: {
|
||||
0: Text('Unread'),
|
||||
1: Text('Paticipating'),
|
||||
2: Text('All')
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: groups.length,
|
||||
itemBuilder: _buildGroupItem,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class ProfileScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return Text("profile");
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import '../models/user.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
|
||||
class IosUserPage extends StatelessWidget {
|
||||
String login;
|
||||
String avatar;
|
||||
IosUserPage(this.login, this.avatar);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
leading: CupertinoButton(
|
||||
child: Text('Cancel'),
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
),
|
||||
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;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
138
lib/main.dart
138
lib/main.dart
@ -1,30 +1,118 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/providers/providers.dart';
|
||||
import 'package:git_touch/providers/settings.dart';
|
||||
import 'package:git_touch/ios/ios.dart';
|
||||
import 'package:git_touch/android/android.dart';
|
||||
import 'providers/providers.dart';
|
||||
import 'providers/settings.dart';
|
||||
import 'screens/screens.dart';
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
@override
|
||||
createState() => _HomeState();
|
||||
}
|
||||
|
||||
class _HomeState extends State<Home> {
|
||||
int active = 0;
|
||||
|
||||
List<BottomNavigationBarItem> _buildNavigationItems() {
|
||||
return [
|
||||
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'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
_buildScreen(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return NewsScreen();
|
||||
case 1:
|
||||
return NotificationScreen();
|
||||
case 2:
|
||||
return SearchScreen();
|
||||
case 3:
|
||||
return ProfileScreen();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
switch (SettingsProvider.of(context).layout) {
|
||||
case LayoutMap.cupertino:
|
||||
return CupertinoApp(
|
||||
home: 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) {
|
||||
return _buildScreen(index);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
default:
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
// appBar: AppBar(title: Text('Home')),
|
||||
body: _buildScreen(active),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
items: _buildNavigationItems(),
|
||||
currentIndex: active,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
onTap: (int index) {
|
||||
setState(() {
|
||||
active = index;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class App extends StatelessWidget {
|
||||
final isIos = Platform.isIOS;
|
||||
final SettingsBloc settingsBloc;
|
||||
final NotificationBloc notificationBloc;
|
||||
final SearchBloc searchBloc;
|
||||
|
||||
App(this.settingsBloc, this.notificationBloc, this.searchBloc);
|
||||
|
||||
_buildScreen() {
|
||||
// return IssueScreen(11609, 'flutter', 'flutter');
|
||||
|
||||
// return IosHome();
|
||||
|
||||
if (Platform.isIOS) {
|
||||
return IosHome();
|
||||
} else if (Platform.isAndroid) {
|
||||
return AndroidHome();
|
||||
}
|
||||
}
|
||||
App(this.notificationBloc, this.searchBloc);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
@ -32,13 +120,10 @@ class App extends StatelessWidget {
|
||||
bloc: searchBloc,
|
||||
child: NotificationProvider(
|
||||
bloc: notificationBloc,
|
||||
child: EventProvider(
|
||||
bloc: settingsBloc,
|
||||
child: MaterialApp(
|
||||
home: DefaultTextStyle(
|
||||
style: TextStyle(color: Color(0xff24292e)),
|
||||
child: _buildScreen(),
|
||||
),
|
||||
child: SettingsProvider(
|
||||
child: DefaultTextStyle(
|
||||
style: TextStyle(color: Color(0xff24292e)),
|
||||
child: Home(),
|
||||
// theme: ThemeData(
|
||||
// textTheme: TextTheme(
|
||||
// title: TextStyle(color: Colors.red),
|
||||
@ -52,7 +137,6 @@ class App extends StatelessWidget {
|
||||
}
|
||||
|
||||
void main() async {
|
||||
SettingsBloc eventBloc = SettingsBloc();
|
||||
NotificationBloc notificationBloc = NotificationBloc();
|
||||
SearchBloc searchBloc = SearchBloc();
|
||||
|
||||
@ -63,5 +147,5 @@ void main() async {
|
||||
// IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
|
||||
// print('Running on ${iosInfo.utsname.machine}'); // e.g. "iPod7,1"
|
||||
|
||||
runApp(App(eventBloc, notificationBloc, searchBloc));
|
||||
runApp(App(notificationBloc, searchBloc));
|
||||
}
|
||||
|
@ -1,39 +1,58 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LayoutMap {
|
||||
static const material = 0;
|
||||
static const cupertino = 1;
|
||||
}
|
||||
|
||||
class SettingsBloc {
|
||||
final _layout = BehaviorSubject(seedValue: LayoutMap.material);
|
||||
// final _update = StreamController<bool>();
|
||||
class SettingsState {}
|
||||
|
||||
Stream<int> get layout {
|
||||
// _layout.value
|
||||
class SettingsProvider extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
SettingsProvider({@required this.child});
|
||||
|
||||
static _SettingsProviderState of(BuildContext context) {
|
||||
return (context.inheritFromWidgetOfExactType(_InheritedSettingsProvider)
|
||||
as _InheritedSettingsProvider)
|
||||
.data;
|
||||
}
|
||||
Sink<int> get layoutUpdate => _layout.sink;
|
||||
|
||||
SettingsBloc() {}
|
||||
}
|
||||
|
||||
class EventProvider extends InheritedWidget {
|
||||
final SettingsBloc bloc;
|
||||
|
||||
EventProvider({
|
||||
Key key,
|
||||
Widget child,
|
||||
@required SettingsBloc bloc,
|
||||
}) : bloc = bloc,
|
||||
super(key: key, child: child);
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(InheritedWidget oldWidget) => true;
|
||||
|
||||
static SettingsBloc of(BuildContext context) =>
|
||||
(context.inheritFromWidgetOfExactType(EventProvider) as EventProvider)
|
||||
.bloc;
|
||||
_SettingsProviderState createState() => new _SettingsProviderState();
|
||||
}
|
||||
|
||||
class _SettingsProviderState extends State<SettingsProvider> {
|
||||
int layout;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (Platform.isIOS) {
|
||||
layout = LayoutMap.cupertino;
|
||||
}
|
||||
// layout = LayoutMap.material;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new _InheritedSettingsProvider(
|
||||
data: this,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _InheritedSettingsProvider extends InheritedWidget {
|
||||
final _SettingsProviderState data;
|
||||
|
||||
_InheritedSettingsProvider({
|
||||
Key key,
|
||||
@required this.data,
|
||||
@required Widget child,
|
||||
}) : super(key: key, child: child);
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(_InheritedSettingsProvider old) => true;
|
||||
}
|
||||
|
118
lib/screens/news.dart
Normal file
118
lib/screens/news.dart
Normal file
@ -0,0 +1,118 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import '../providers/settings.dart';
|
||||
import '../widgets/event_item.dart';
|
||||
import '../utils/utils.dart';
|
||||
|
||||
class NewsScreen extends StatefulWidget {
|
||||
@override
|
||||
NewsScreenState createState() => NewsScreenState();
|
||||
}
|
||||
|
||||
class NewsScreenState extends State<NewsScreen> {
|
||||
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) {
|
||||
switch (SettingsProvider.of(context).layout) {
|
||||
case LayoutMap.cupertino:
|
||||
return CupertinoPageScaffold(
|
||||
child: CustomScrollView(
|
||||
controller: _controller,
|
||||
slivers: <Widget>[
|
||||
CupertinoSliverNavigationBar(largeTitle: const Text('News')),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
default:
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('News')),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _refresh();
|
||||
// Scaffold.of(context).showSnackBar(SnackBar(
|
||||
// content: Container(
|
||||
// child: Text('data'),
|
||||
// padding: EdgeInsets.only(bottom: 10),
|
||||
// )
|
||||
// ));
|
||||
},
|
||||
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]);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
149
lib/screens/notifications.dart
Normal file
149
lib/screens/notifications.dart
Normal file
@ -0,0 +1,149 @@
|
||||
import 'package:flutter/material.dart' hide Notification;
|
||||
import 'package:flutter/cupertino.dart' hide Notification;
|
||||
import '../providers/settings.dart';
|
||||
import '../screens/screens.dart';
|
||||
import '../widgets/notification_item.dart';
|
||||
import '../utils/utils.dart';
|
||||
|
||||
class NotificationGroup {
|
||||
String fullName;
|
||||
List<Notification> items = [];
|
||||
|
||||
NotificationGroup(this.fullName);
|
||||
}
|
||||
|
||||
class NotificationScreen extends StatefulWidget {
|
||||
@override
|
||||
NotificationScreenState createState() => NotificationScreenState();
|
||||
}
|
||||
|
||||
class NotificationScreenState extends State<NotificationScreen> {
|
||||
int active = 0;
|
||||
bool loading = false;
|
||||
List<NotificationGroup> groups = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Future.delayed(Duration(seconds: 0)).then((_) {
|
||||
_onSwitchTab(context, 0);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildGroupItem(BuildContext context, int index) {
|
||||
var group = groups[index];
|
||||
|
||||
return Container(
|
||||
// padding: EdgeInsets.all(10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 10, left: 4, bottom: 4),
|
||||
color: CupertinoColors.extraLightBackgroundGray,
|
||||
child: Text(
|
||||
group.fullName,
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: group.items
|
||||
.map((item) => NotificationItem(item: item))
|
||||
.toList())
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onSwitchTab(BuildContext context, int index) async {
|
||||
setState(() {
|
||||
active = index;
|
||||
loading = true;
|
||||
});
|
||||
|
||||
var ns = await ghClient.activity
|
||||
.listNotifications(all: index == 2, participating: index == 1)
|
||||
.toList();
|
||||
|
||||
// NotificationProvider.of(context).countUpdate.add(ns.length);
|
||||
|
||||
Map<String, NotificationGroup> groupMap = {};
|
||||
ns.forEach((item) {
|
||||
String repo = item.repository.fullName;
|
||||
if (groupMap[repo] == null) {
|
||||
groupMap[repo] = NotificationGroup(repo);
|
||||
}
|
||||
|
||||
groupMap[repo].items.add(item);
|
||||
});
|
||||
|
||||
setState(() {
|
||||
groups = groupMap.values.toList();
|
||||
loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(context) {
|
||||
// NotificationBloc bloc = NotificationProvider.of(context);
|
||||
TextStyle _textStyle = DefaultTextStyle.of(context).style;
|
||||
|
||||
switch (SettingsProvider.of(context).layout) {
|
||||
case LayoutMap.cupertino:
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: SizedBox.expand(
|
||||
child: DefaultTextStyle(
|
||||
style: _textStyle,
|
||||
child: CupertinoSegmentedControl(
|
||||
groupValue: active,
|
||||
onValueChanged: (index) => _onSwitchTab(context, index),
|
||||
children: {
|
||||
0: Text('Unread'),
|
||||
1: Text('Paticipating'),
|
||||
2: Text('All')
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: CustomScrollView(slivers: [
|
||||
CupertinoSliverRefreshControl(),
|
||||
SliverSafeArea(
|
||||
top: false,
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
if (index == groups.length) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15),
|
||||
child: CupertinoActivityIndicator(radius: 12),
|
||||
);
|
||||
} else {
|
||||
return _buildGroupItem(context, index);
|
||||
}
|
||||
},
|
||||
childCount: groups.length + 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
// ListView.builder(
|
||||
// shrinkWrap: true,
|
||||
// itemCount: groups.length,
|
||||
// itemBuilder: _buildGroupItem,
|
||||
// ),
|
||||
);
|
||||
default:
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Notification')),
|
||||
body: ListView.builder(
|
||||
itemCount: groups.length,
|
||||
itemBuilder: _buildGroupItem,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
64
lib/screens/profile.dart
Normal file
64
lib/screens/profile.dart
Normal file
@ -0,0 +1,64 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class ProfileScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
Text("profile"),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
export 'repo.dart';
|
||||
export 'news.dart';
|
||||
export 'user.dart';
|
||||
export 'issue.dart';
|
||||
export 'pull_request.dart';
|
||||
export 'repo.dart';
|
||||
export 'issue.dart';
|
||||
export 'notifications.dart';
|
||||
export 'search.dart';
|
||||
export 'profile.dart';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:git_touch/screens/screens.dart';
|
||||
import '../screens/screens.dart';
|
||||
export 'github.dart';
|
||||
export 'octicons.dart';
|
||||
export 'timeago.dart';
|
||||
@ -27,44 +27,6 @@ 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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/screens/screens.dart';
|
||||
import '../screens/screens.dart';
|
||||
|
||||
class Avatar extends StatelessWidget {
|
||||
final String login;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:git_touch/screens/screens.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:git_touch/widgets/widgets.dart';
|
||||
import '../screens/screens.dart';
|
||||
import '../utils/utils.dart';
|
||||
import '../widgets/widgets.dart';
|
||||
|
||||
/// Events types:
|
||||
///
|
||||
@ -159,41 +159,47 @@ class EventItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(color: CupertinoColors.lightBackgroundGray))),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
return Material(
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom:
|
||||
BorderSide(color: CupertinoColors.lightBackgroundGray))),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Avatar(event.actor.login, event.actor.avatarUrl),
|
||||
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(event.actor.login)),
|
||||
_buildEvent(context),
|
||||
],
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Avatar(event.actor.login, event.actor.avatarUrl),
|
||||
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(event.actor.login)),
|
||||
_buildEvent(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(padding: EdgeInsets.only(left: 10)),
|
||||
Icon(_buildIconData(context),
|
||||
color: CupertinoColors.inactiveGray),
|
||||
],
|
||||
),
|
||||
Padding(padding: EdgeInsets.only(left: 10)),
|
||||
Icon(_buildIconData(context),
|
||||
color: CupertinoColors.inactiveGray),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 42, top: 8),
|
||||
child: Text(_buildComment(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Color(0xffaaaaaa))))
|
||||
],
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 42, top: 8),
|
||||
child: Text(_buildComment(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Color(0xffaaaaaa))))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ class NotificationItem extends StatelessWidget {
|
||||
case 'PullRequest':
|
||||
// return IssueScreen(item.repository.);
|
||||
default:
|
||||
throw new Exception('Unhandled notification type: $type');
|
||||
// throw new Exception('Unhandled notification type: $type');
|
||||
return Text('test');
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +32,7 @@ class NotificationItem extends StatelessWidget {
|
||||
return Octicons.git_pull_request;
|
||||
// color: Color.fromRGBO(0x6f, 0x42, 0xc1, 1),
|
||||
default:
|
||||
throw new Exception('Unhandled icon type: $type');
|
||||
return Octicons.person;
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,13 +51,18 @@ class NotificationItem extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Icon(_buildIconData(item.subject.type),
|
||||
color: CupertinoColors.inactiveGray),
|
||||
child: Icon(
|
||||
_buildIconData(item.subject.type),
|
||||
// color: CupertinoColors.inactiveGray,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
// color: Colors.grey,
|
||||
))),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
@ -78,7 +84,7 @@ class NotificationItem extends StatelessWidget {
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Icon(
|
||||
Octicons.check,
|
||||
color: CupertinoColors.inactiveGray,
|
||||
// color: CupertinoColors.inactiveGray,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user