From 7fe5575d2557e1dd7645c9019c8ab219c3a57478 Mon Sep 17 00:00:00 2001 From: Rongjian Zhang Date: Thu, 21 Feb 2019 18:43:41 +0800 Subject: [PATCH] refactor: function params, add gitlab login screen --- lib/providers/settings.dart | 95 +++++++++++++--------------- lib/scaffolds/list.dart | 4 +- lib/scaffolds/long_list.dart | 4 +- lib/scaffolds/refresh.dart | 2 +- lib/scaffolds/refresh_stateless.dart | 2 +- lib/scaffolds/simple.dart | 4 +- lib/screens/login.dart | 47 +++++++++----- lib/screens/login_gitlab.dart | 40 ++++++++++++ lib/screens/notifications.dart | 2 +- lib/screens/user.dart | 2 +- lib/widgets/error_reload.dart | 6 +- lib/widgets/link.dart | 8 +-- lib/widgets/notification_item.dart | 4 +- lib/widgets/table_view.dart | 2 +- 14 files changed, 136 insertions(+), 86 deletions(-) create mode 100644 lib/screens/login_gitlab.dart diff --git a/lib/providers/settings.dart b/lib/providers/settings.dart index a6f10e3..8441d5f 100644 --- a/lib/providers/settings.dart +++ b/lib/providers/settings.dart @@ -10,6 +10,30 @@ import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../utils/utils.dart'; import '../utils/constants.dart'; +import '../models/account.dart'; + +// enum PlatformType { +// github, +// gitlab, +// } + +// abstract class Model { +// Future query(BuildContext context) { +// var settings = SettingsProvider.of(context); + +// switch (settings.platformType) { +// case PlatformType.github: +// return queryGithub(settings); +// case PlatformType.gitlab: +// return queryGitlab(settings); +// default: +// return null; +// } +// } + +// Future queryGithub(SettingsProviderState settings); +// Future queryGitlab(SettingsProviderState settings); +// } class ThemeMap { static const material = 0; @@ -17,59 +41,35 @@ class ThemeMap { static const all = [0, 1]; } -final prefix = 'https://api.github.com'; - -class Account { - String avatarUrl; - String token; - - /// for github enterprise - String domain; - - Account({ - @required this.avatarUrl, - @required this.token, - this.domain, - }); - - Account.fromJson(input) { - avatarUrl = input['avatarUrl']; - token = input['token']; - domain = input['domain']; - } - - Map toJson() { - var data = {'avatarUrl': avatarUrl, 'token': token}; - if (domain != null) { - data['domain'] = domain; - } - return data; - } -} - class SettingsProvider extends StatefulWidget { final Widget child; SettingsProvider({@required this.child}); - static _SettingsProviderState of(BuildContext context) { + static SettingsProviderState of(BuildContext context) { return (context.inheritFromWidgetOfExactType(_InheritedSettingsProvider) as _InheritedSettingsProvider) .data; } @override - _SettingsProviderState createState() => new _SettingsProviderState(); + SettingsProviderState createState() => new SettingsProviderState(); } -class _SettingsProviderState extends State { +class SettingsProviderState extends State { bool ready = false; int theme; - Map githubAccountMap; + + Map githubAccountMap; + String activeLogin; StreamSubscription _sub; bool loading = false; + // PlatformType platformType; + + String prefix = 'https://api.github.com'; + Future setTheme(int _theme) async { SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -104,7 +104,7 @@ class _SettingsProviderState extends State { } // https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#web-application-flow - void _onSchemeDetected(Uri uri) async { + Future _onSchemeDetected(Uri uri) async { try { // FIXME: await closeWebView(); @@ -132,8 +132,10 @@ class _SettingsProviderState extends State { ); // print(res.body); var data = json.decode(res.body); - String _token = data['access_token']; + _loginWithToken(data['access_token']); + } + Future _loginWithToken(String token) async { // get login and avatar url var queryData = await query(''' { @@ -142,11 +144,11 @@ class _SettingsProviderState extends State { avatarUrl } } -''', _token); +''', token); String login = queryData['viewer']['login']; String avatarUrl = queryData['viewer']['avatarUrl']; - githubAccountMap[login] = Account(avatarUrl: avatarUrl, token: _token); + githubAccountMap[login] = AccountModel(avatarUrl: avatarUrl, token: token); // write SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -168,8 +170,9 @@ class _SettingsProviderState extends State { var str = prefs.getString('github'); // print('read github: $str'); Map github = json.decode(str); - githubAccountMap = github.map((login, _accountMap) => - MapEntry(login, Account.fromJson(_accountMap))); + githubAccountMap = github.map( + (login, _accountMap) => + MapEntry(login, AccountModel.fromJson(_accountMap))); } catch (err) { print(err); githubAccountMap = {}; @@ -192,17 +195,9 @@ class _SettingsProviderState extends State { } void setActiveAccount(String login) { - // FIXME: This is pretty tricky to trigger home screen rebuild setState(() { - activeLogin = null; + activeLogin = login; }); - nextTick(() { - setState(() { - activeLogin = login; - // activeLogin = null; - // ready = true; - }); - }, 100); } // http timeout @@ -294,7 +289,7 @@ class _SettingsProviderState extends State { } class _InheritedSettingsProvider extends InheritedWidget { - final _SettingsProviderState data; + final SettingsProviderState data; _InheritedSettingsProvider({ Key key, diff --git a/lib/scaffolds/list.dart b/lib/scaffolds/list.dart index ec01510..b33056d 100644 --- a/lib/scaffolds/list.dart +++ b/lib/scaffolds/list.dart @@ -129,7 +129,7 @@ class _ListScaffoldState extends State> { Widget _buildSliver(BuildContext context) { if (error.isNotEmpty) { return SliverToBoxAdapter( - child: ErrorReload(text: error, reload: _refresh), + child: ErrorReload(text: error, onTap: _refresh), ); } else if (loading) { return SliverToBoxAdapter(child: Loading(more: false)); @@ -147,7 +147,7 @@ class _ListScaffoldState extends State> { Widget _buildBody(BuildContext context) { if (error.isNotEmpty) { - return ErrorReload(text: error, reload: _refresh); + return ErrorReload(text: error, onTap: _refresh); } else if (loading) { return Loading(more: false); } else if (items.isEmpty) { diff --git a/lib/scaffolds/long_list.dart b/lib/scaffolds/long_list.dart index 1d6181a..195a7db 100644 --- a/lib/scaffolds/long_list.dart +++ b/lib/scaffolds/long_list.dart @@ -127,7 +127,7 @@ class _LongListScaffoldState extends State> { ), child: Center( child: Link( - beforeRedirect: _loadMore, + onTap: _loadMore, child: Container( padding: EdgeInsets.all(10), decoration: BoxDecoration( @@ -168,7 +168,7 @@ class _LongListScaffoldState extends State> { Widget _buildSliver() { if (error.isNotEmpty) { return SliverToBoxAdapter( - child: ErrorReload(text: error, reload: _refresh)); + child: ErrorReload(text: error, onTap: _refresh)); } else if (loading) { return SliverToBoxAdapter(child: Loading(more: false)); } else { diff --git a/lib/scaffolds/refresh.dart b/lib/scaffolds/refresh.dart index f24e7e6..48899fd 100644 --- a/lib/scaffolds/refresh.dart +++ b/lib/scaffolds/refresh.dart @@ -40,7 +40,7 @@ class _RefreshScaffoldState extends State> { Widget _buildBody() { if (error.isNotEmpty) { - return ErrorReload(text: error, reload: _refresh); + return ErrorReload(text: error, onTap: _refresh); } else if (payload == null) { return Loading(more: false); } else { diff --git a/lib/scaffolds/refresh_stateless.dart b/lib/scaffolds/refresh_stateless.dart index a61e726..0e123a9 100644 --- a/lib/scaffolds/refresh_stateless.dart +++ b/lib/scaffolds/refresh_stateless.dart @@ -29,7 +29,7 @@ class RefreshStatelessScaffold extends StatelessWidget { Widget _buildBody() { if (error.isNotEmpty) { - return ErrorReload(text: error, reload: onRefresh); + return ErrorReload(text: error, onTap: onRefresh); } else if (loading) { return Loading(more: false); } else { diff --git a/lib/scaffolds/simple.dart b/lib/scaffolds/simple.dart index 58c0a2e..88a70b9 100644 --- a/lib/scaffolds/simple.dart +++ b/lib/scaffolds/simple.dart @@ -3,11 +3,9 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import '../providers/settings.dart'; -typedef WidgetBuilder = Widget Function(); - class SimpleScaffold extends StatelessWidget { final Widget title; - final WidgetBuilder bodyBuilder; + final Widget Function() bodyBuilder; final Widget trailing; final List actions; final PreferredSizeWidget bottom; diff --git a/lib/screens/login.dart b/lib/screens/login.dart index 267beb5..54a2c77 100644 --- a/lib/screens/login.dart +++ b/lib/screens/login.dart @@ -5,6 +5,7 @@ import '../scaffolds/simple.dart'; import '../utils/constants.dart'; import '../widgets/link.dart'; import '../widgets/loading.dart'; +import 'login_gitlab.dart'; class LoginScreen extends StatefulWidget { @override @@ -12,6 +13,27 @@ class LoginScreen extends StatefulWidget { } class _LoginScreenState extends State { + Widget _buildAddItem( + {String text, Function onTap, WidgetBuilder screenBuilder}) { + return Link( + child: Container( + padding: EdgeInsets.symmetric(vertical: 20), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.black12)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.add), + Text(text, style: TextStyle(fontSize: 16)), + ], + ), + ), + onTap: onTap, + screenBuilder: screenBuilder, + ); + } + @override Widget build(BuildContext context) { var settings = SettingsProvider.of(context); @@ -27,7 +49,7 @@ class _LoginScreenState extends State { child: Column( children: settings.githubAccountMap.entries.map((entry) { return Link( - beforeRedirect: () { + onTap: () { // Navigator.of(context).pop(); settings.setActiveAccount(entry.key); }, @@ -60,26 +82,21 @@ class _LoginScreenState extends State { ), ); }).toList() - ..add( - Link( - child: Container( - padding: EdgeInsets.symmetric(vertical: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.add), - Text('Add account', style: TextStyle(fontSize: 16)), - ], - ), - ), - beforeRedirect: () { + ..addAll([ + _buildAddItem( + text: 'GitHub Account', + onTap: () { var state = settings.generateRandomString(); launch( 'https://github.com/login/oauth/authorize?client_id=$clientId&redirect_uri=gittouch://login&scope=user%20repo&state=$state', ); }, ), - ), + _buildAddItem( + text: 'GitLab Account', + screenBuilder: (_) => LoginGitlabScreen(), + ) + ]), ), ); }, diff --git a/lib/screens/login_gitlab.dart b/lib/screens/login_gitlab.dart new file mode 100644 index 0000000..5349244 --- /dev/null +++ b/lib/screens/login_gitlab.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import '../scaffolds/simple.dart'; + +class LoginGitlabScreen extends StatefulWidget { + @override + _LoginGitlabScreenState createState() => _LoginGitlabScreenState(); +} + +class _LoginGitlabScreenState extends State { + String _token; + String _domain; + + @override + Widget build(BuildContext context) { + return SimpleScaffold( + title: Text('Login to GitLab'), + bodyBuilder: () { + return Column( + children: [ + TextField( + // decoration: InputDecoration(icon: Icon(Icons.more_vert)), + onChanged: (value) { + _domain = value; + }, + ), + TextField( + onChanged: (value) { + _token = value; + }, + ), + MaterialButton( + child: Text('Login'), + onPressed: () {}, + ) + ], + ); + }, + ); + } +} diff --git a/lib/screens/notifications.dart b/lib/screens/notifications.dart index a0922a4..b8b4155 100644 --- a/lib/screens/notifications.dart +++ b/lib/screens/notifications.dart @@ -128,7 +128,7 @@ $key: pullRequest(number: ${item.number}) { ), Link( material: false, - beforeRedirect: () async { + onTap: () async { await SettingsProvider.of(context) .putWithCredentials('/repos/$repo/notifications'); await _onSwitchTab(); diff --git a/lib/screens/user.dart b/lib/screens/user.dart index 7b8b38d..a81b7e8 100644 --- a/lib/screens/user.dart +++ b/lib/screens/user.dart @@ -101,7 +101,7 @@ class _UserScreenState extends State { Padding(padding: EdgeInsets.only(left: 4)), Text(email, style: TextStyle(color: Colors.black54, fontSize: 15)) ]), - beforeRedirect: () { + onTap: () { launch('mailto:' + email); }, ); diff --git a/lib/widgets/error_reload.dart b/lib/widgets/error_reload.dart index 1ae419a..b66ac74 100644 --- a/lib/widgets/error_reload.dart +++ b/lib/widgets/error_reload.dart @@ -3,9 +3,9 @@ import 'link.dart'; class ErrorReload extends StatelessWidget { final String text; - final Function reload; + final Function onTap; - ErrorReload({@required this.text, @required this.reload}); + ErrorReload({@required this.text, @required this.onTap}); @override Widget build(BuildContext context) { @@ -32,7 +32,7 @@ class ErrorReload extends StatelessWidget { 'Reload', style: TextStyle(fontSize: 20, color: Colors.blueAccent), ), - beforeRedirect: reload, + onTap: onTap, material: false, ), ], diff --git a/lib/widgets/link.dart b/lib/widgets/link.dart index c6ec25c..45abcd5 100644 --- a/lib/widgets/link.dart +++ b/lib/widgets/link.dart @@ -7,7 +7,7 @@ class Link extends StatelessWidget { final Widget child; final String url; final WidgetBuilder screenBuilder; - final Function beforeRedirect; + final Function onTap; final Color bgColor; final bool material; final bool fullscreenDialog; @@ -17,7 +17,7 @@ class Link extends StatelessWidget { this.child, this.url, this.screenBuilder, - this.beforeRedirect, + this.onTap, this.bgColor, this.material = true, this.fullscreenDialog = false, @@ -26,8 +26,8 @@ class Link extends StatelessWidget { assert(screenBuilder == null || url == null); void _onTap(BuildContext context, int theme) { - if (beforeRedirect != null) { - beforeRedirect(); + if (onTap != null) { + onTap(); } if (screenBuilder != null) { diff --git a/lib/widgets/notification_item.dart b/lib/widgets/notification_item.dart index 34c7515..69accef 100644 --- a/lib/widgets/notification_item.dart +++ b/lib/widgets/notification_item.dart @@ -150,7 +150,7 @@ class _NotificationItemState extends State { Widget build(BuildContext context) { return Link( screenBuilder: _buildRoute, - beforeRedirect: _markAsRead, + onTap: _markAsRead, child: Opacity( opacity: payload.unread ? 1 : 0.5, child: Container( @@ -168,7 +168,7 @@ class _NotificationItemState extends State { style: TextStyle(fontSize: 15), ), ), - Link(child: _buildCheckIcon(), beforeRedirect: _markAsRead), + Link(child: _buildCheckIcon(), onTap: _markAsRead), ], ), ), diff --git a/lib/widgets/table_view.dart b/lib/widgets/table_view.dart index 38e9faf..8686084 100644 --- a/lib/widgets/table_view.dart +++ b/lib/widgets/table_view.dart @@ -61,7 +61,7 @@ class TableView extends StatelessWidget { } return Link( - beforeRedirect: item.onTap, + onTap: item.onTap, screenBuilder: item.screenBuilder, child: Container( decoration: BoxDecoration(