From 559d6756e8d0e6bda7ba266e9adafa451be1d05d Mon Sep 17 00:00:00 2001 From: Rongjian Zhang Date: Sat, 1 Feb 2020 17:00:30 +0800 Subject: [PATCH] refactor: login screen --- lib/models/auth.dart | 37 +++---- lib/screens/login.dart | 238 +++++++++++++++++++++-------------------- 2 files changed, 135 insertions(+), 140 deletions(-) diff --git a/lib/models/auth.dart b/lib/models/auth.dart index 854e529..b5c85e2 100644 --- a/lib/models/auth.dart +++ b/lib/models/auth.dart @@ -91,8 +91,8 @@ class AuthModel with ChangeNotifier { } Future loginWithToken(String token) async { - // Get login and avatar url - final queryData = await query(''' + try { + final queryData = await query(''' { viewer { login @@ -101,23 +101,23 @@ class AuthModel with ChangeNotifier { } ''', token); - await _addAccount(Account( - platform: PlatformType.github, - domain: 'https://github.com', - token: token, - login: queryData['viewer']['login'] as String, - avatarUrl: queryData['viewer']['avatarUrl'] as String, - )); - - loading = false; - notifyListeners(); + await _addAccount(Account( + platform: PlatformType.github, + domain: 'https://github.com', + token: token, + login: queryData['viewer']['login'] as String, + avatarUrl: queryData['viewer']['avatarUrl'] as String, + )); + } finally { + loading = false; + notifyListeners(); + } } Future loginToGitlab(String domain, String token) async { + loading = true; + notifyListeners(); try { - loading = true; - notifyListeners(); - final res = await http .get('$domain/api/v4/user', headers: {'Private-Token': token}); final info = json.decode(res.body); @@ -134,9 +134,6 @@ class AuthModel with ChangeNotifier { avatarUrl: user.avatarUrl, gitlabId: user.id, )); - } catch (err) { - Fimber.e('loginToGitlab failed', ex: err); - // TODO: show errors } finally { loading = false; notifyListeners(); @@ -176,7 +173,6 @@ class AuthModel with ChangeNotifier { try { loading = true; notifyListeners(); - final res = await http.get('$domain/api/v1/user', headers: {'Authorization': 'token $token'}); final info = json.decode(res.body); @@ -192,9 +188,6 @@ class AuthModel with ChangeNotifier { login: user.login, avatarUrl: user.avatarUrl, )); - } catch (err) { - Fimber.e('loginToGitea failed', ex: err); - // TODO: show errors } finally { loading = false; notifyListeners(); diff --git a/lib/screens/login.dart b/lib/screens/login.dart index 220ffba..d37c783 100644 --- a/lib/screens/login.dart +++ b/lib/screens/login.dart @@ -4,6 +4,7 @@ import 'package:git_touch/models/auth.dart'; import 'package:git_touch/models/theme.dart'; import 'package:git_touch/scaffolds/single.dart'; import 'package:git_touch/utils/utils.dart'; +import 'package:git_touch/widgets/action_button.dart'; import 'package:git_touch/widgets/app_bar_title.dart'; import 'package:provider/provider.dart'; import '../widgets/link.dart'; @@ -16,17 +17,21 @@ class LoginScreen extends StatefulWidget { } class _LoginScreenState extends State { - String _token = ''; - String _gitlabToken = ''; - String _gitlabDomain = 'https://gitlab.com'; - String _giteaToken = ''; - String _giteaDomain = 'https://try.gitea.io'; + final _tokenController = TextEditingController(); + final _domainController = TextEditingController(); + + // @override + // initState() { + // super.initState(); + // _tokenController.addListener(() { + // print(_tokenController.text); + // }); + // } Widget _buildAccountItem(int index) { final theme = Provider.of(context); final auth = Provider.of(context); final account = auth.accounts[index]; - return Link( onTap: () { auth.setActiveAccountAndReload(index); @@ -59,9 +64,8 @@ class _LoginScreenState extends State { ); } - Widget _buildAddItem({String text, Function onTap}) { + Widget _buildAddItem({IconData brand, String text, Function onTap}) { final theme = Provider.of(context); - return Link( child: Container( padding: EdgeInsets.symmetric(vertical: 20), @@ -72,6 +76,9 @@ class _LoginScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.add), + SizedBox(width: 4), + Icon(brand), + SizedBox(width: 8), Text(text, style: TextStyle(fontSize: 16)), ], ), @@ -80,11 +87,38 @@ class _LoginScreenState extends State { ); } + Widget _buildPopup( + BuildContext context, { + List notes, + bool showDomain = false, + }) { + return Column( + children: [ + if (showDomain) + CupertinoTextField( + controller: _domainController, + placeholder: 'Domain', + ), + SizedBox(height: 8), + CupertinoTextField( + placeholder: 'Access token', + controller: _tokenController, + ), + SizedBox(height: 8), + if (notes != null) ...notes, + ], + ); + } + + void showError(err) { + final theme = Provider.of(context); + theme.showConfirm(context, Text('Something bad happens: $err')); + } + @override Widget build(BuildContext context) { final auth = Provider.of(context); final theme = Provider.of(context); - return SingleScaffold( title: AppBarTitle('Select account'), body: auth.loading @@ -94,26 +128,62 @@ class _LoginScreenState extends State { children: [ ...List.generate(auth.accounts.length, _buildAccountItem), _buildAddItem( - text: 'GitHub Account by OAuth', - onTap: auth.redirectToGithubOauth, + text: 'GitHub Account', + brand: FontAwesome5Brands.github, + onTap: () async { + theme.showActions(context, [ + ActionItem( + text: 'via OAuth', + onTap: (_) { + auth.redirectToGithubOauth(); + }, + ), + ActionItem( + text: 'via Personal token', + onTap: (_) async { + final result = await theme.showConfirm( + context, + _buildPopup(context, notes: [ + Text( + 'GitTouch needs these permissions', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400), + ), + SizedBox(height: 8), + Text( + 'user, repo, read:org, notifications', + style: TextStyle( + fontSize: 16, + color: theme.palette.primary), + ) + ]), + ); + if (result == true) { + try { + await auth + .loginWithToken(_tokenController.text); + _tokenController.clear(); + } catch (err) { + showError(err); + } + } + }, + ), + ]); + }, ), _buildAddItem( - text: 'GitHub Account by Token', + text: 'GitLab Account', + brand: FontAwesome5Brands.gitlab, onTap: () async { - var result = - await Provider.of(context).showConfirm( + _domainController.text = 'https://gitlab.com'; + final result = await theme.showConfirm( context, - Column( - children: [ - CupertinoTextField( - placeholder: 'Access token', - onChanged: (v) { - setState(() { - _token = v; - }); - }, - ), - SizedBox(height: 8), + _buildPopup( + context, + showDomain: true, + notes: [ Text( 'GitTouch needs these permissions', style: TextStyle( @@ -121,7 +191,7 @@ class _LoginScreenState extends State { ), SizedBox(height: 8), Text( - 'user, repo, read:org, notifications', + 'api, read_user, read_repository', style: TextStyle( fontSize: 16, color: theme.palette.primary), ) @@ -130,103 +200,35 @@ class _LoginScreenState extends State { ); if (result == true) { try { - await auth.loginWithToken(_token); + await auth.loginToGitlab( + _domainController.text, _tokenController.text); + _tokenController.clear(); } catch (err) { - Provider.of(context).showConfirm( - context, Text('Token invalid: $err')); + showError(err); } } }, ), - // _buildAddItem( - // text: 'GitLab Account by Token', - // onTap: () async { - // final result = - // await Provider.of(context).showConfirm( - // context, - // Column( - // children: [ - // CupertinoTextField( - // placeholder: 'Domain', - // onChanged: (v) { - // setState(() { - // _gitlabDomain = v; - // }); - // }, - // ), - // SizedBox(height: 8), - // CupertinoTextField( - // placeholder: 'Access token', - // onChanged: (v) { - // setState(() { - // _gitlabToken = v; - // }); - // }, - // ), - // SizedBox(height: 8), - // Text( - // 'GitTouch needs these permissions', - // style: TextStyle( - // fontSize: 14, fontWeight: FontWeight.w400), - // ), - // SizedBox(height: 8), - // Text( - // 'api, read_user, read_repository', - // style: TextStyle( - // fontSize: 16, color: theme.palette.primary), - // ) - // ], - // ), - // ); - // if (result == true) { - // try { - // await auth.loginToGitlab(_gitlabDomain, _gitlabToken); - // // TODO: Custom domain - // } catch (err) { - // Provider.of(context).showConfirm( - // context, Text('Token invalid: $err')); - // } - // } - // }, - // ), - // _buildAddItem( - // text: 'Gitea Account by Token', - // onTap: () async { - // final result = - // await Provider.of(context).showConfirm( - // context, - // Column( - // children: [ - // CupertinoTextField( - // placeholder: 'Domain', - // onChanged: (v) { - // setState(() { - // _giteaDomain = v; - // }); - // }, - // ), - // SizedBox(height: 8), - // CupertinoTextField( - // placeholder: 'Access token', - // onChanged: (v) { - // setState(() { - // _giteaToken = v; - // }); - // }, - // ), - // ], - // ), - // ); - // if (result == true) { - // try { - // await auth.loginToGitea(_giteaDomain, _giteaToken); - // } catch (err) { - // Provider.of(context).showConfirm( - // context, Text('Token invalid: $err')); - // } - // } - // }, - // ) + _buildAddItem( + text: 'Gitea Account', + brand: Octicons.git_branch, // TODO: brand icon + onTap: () async { + _domainController.text = 'https://try.gitea.io'; + final result = await theme.showConfirm( + context, + _buildPopup(context, showDomain: true), + ); + if (result == true) { + try { + await auth.loginToGitea( + _domainController.text, _tokenController.text); + _tokenController.clear(); + } catch (err) { + showError(err); + } + } + }, + ) ], ), ),