From 4c1009f42f27e0f9b83ed6ccadc71a5cb5329505 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Thu, 24 Jan 2019 16:45:40 +0100 Subject: [PATCH] OnBoarding: Add auto-configure mode for Github In this mode the user doesn't need to do anything but give the GitJournal app permissions, and then it will go and create the repo, add the ssh key and everything. This currently does not work for Gitlab. --- lib/apis/github.dart | 8 +- lib/screens/onboarding_autoconfigure.dart | 71 +++++++++++++++++ lib/screens/onboarding_screens.dart | 92 ++++++++++++++++++----- 3 files changed, 151 insertions(+), 20 deletions(-) create mode 100644 lib/screens/onboarding_autoconfigure.dart diff --git a/lib/apis/github.dart b/lib/apis/github.dart index 4db2ffab..1e7e1859 100644 --- a/lib/apis/github.dart +++ b/lib/apis/github.dart @@ -161,10 +161,14 @@ class GitHub { class Repo { String fullName; + String cloneUrl; - Repo({this.fullName}); + Repo({this.fullName, this.cloneUrl}); factory Repo.fromJson(Map parsedJson) { - return new Repo(fullName: parsedJson['full_name']); + return new Repo( + fullName: parsedJson['full_name'], + cloneUrl: parsedJson['ssh_url'], + ); } @override diff --git a/lib/screens/onboarding_autoconfigure.dart b/lib/screens/onboarding_autoconfigure.dart new file mode 100644 index 00000000..d3b6f690 --- /dev/null +++ b/lib/screens/onboarding_autoconfigure.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; + +import 'package:journal/apis/github.dart'; +import 'package:journal/apis/git.dart'; + +enum GitRemoteRepo { + GitHub, + Gitlab, + Custom, +} + +class OnBoardingAutoConfigure extends StatefulWidget { + final GitRemoteRepo remoteRepo; + final Function onDone; + + OnBoardingAutoConfigure({ + @required this.remoteRepo, + @required this.onDone, + }) { + assert(remoteRepo == GitRemoteRepo.GitHub); + } + + @override + OnBoardingAutoConfigureState createState() { + return new OnBoardingAutoConfigureState(); + } +} + +class OnBoardingAutoConfigureState extends State { + var gitHub = new GitHub(); + + @override + void initState() { + super.initState(); + + gitHub.init(() async { + print("GitHub Initalized"); + + var repo = await gitHub.createRepo("journal"); + var publicKey = await generateSSHKeys(comment: "GitJournal"); + await gitHub.addDeployKey(publicKey, repo.fullName); + + widget.onDone(repo.cloneUrl); + }); + gitHub.launchOAuthScreen(); + } + + @override + Widget build(BuildContext context) { + var children = [ + Text( + 'Configuring ...', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.display1, + ), + SizedBox(height: 8.0), + Padding( + padding: const EdgeInsets.all(8.0), + child: CircularProgressIndicator( + value: null, + ), + ), + ]; + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: children, + ); + } +} diff --git a/lib/screens/onboarding_screens.dart b/lib/screens/onboarding_screens.dart index db71eb52..b8468f7f 100644 --- a/lib/screens/onboarding_screens.dart +++ b/lib/screens/onboarding_screens.dart @@ -13,6 +13,7 @@ import 'package:journal/apis/git.dart'; import 'package:journal/screens/onboarding_git_url.dart'; import 'package:journal/screens/onboarding_git_clone.dart'; +import 'package:journal/screens/onboarding_autoconfigure.dart'; class OnBoardingScreen extends StatefulWidget { final Function onBoardingCompletedFunction; @@ -32,6 +33,9 @@ class OnBoardingScreenState extends State { var _pageCreateNewRepoDone = false; var _pageInputUrlDone = false; var _pageSshKeyDone = false; + var _autoConfigureStarted = false; + var _autoConfigureDone = false; + GitRemoteRepo _remoteRepo; var _gitCloneUrl = ""; String gitCloneErrorMessage = ""; @@ -59,6 +63,9 @@ class OnBoardingScreenState extends State { if (_pageSshKeyDone) { pageCount++; } + if (_autoConfigureStarted) { + pageCount++; + } var pageView = PageView.builder( controller: pageController, @@ -92,10 +99,16 @@ class OnBoardingScreenState extends State { if (pos == 1 && _createNewRepo) { return OnBoardingCreateRepo( - onDone: () { + onDone: (GitRemoteRepo remoteRepo, bool autoConfigure) { + if (!autoConfigure) { + _launchCreateRepoPage(remoteRepo); + } + setState(() { _createNewRepo = true; _pageCreateNewRepoDone = true; + _autoConfigureStarted = autoConfigure; + _remoteRepo = remoteRepo; pageController.nextPage( duration: Duration(milliseconds: 200), @@ -106,6 +119,30 @@ class OnBoardingScreenState extends State { ); } + if (pos == 2 && _createNewRepo && _autoConfigureStarted) { + return OnBoardingAutoConfigure( + remoteRepo: _remoteRepo, + onDone: (String gitCloneUrl) { + setState(() { + _gitCloneUrl = gitCloneUrl; + _autoConfigureDone = true; + + pageController.nextPage( + duration: Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + + var appState = StateContainer.of(context).appState; + _startGitClone(context, appState.gitBaseDirectory); + }); + }, + ); + } + + if (pos == 3 && _createNewRepo && _autoConfigureDone) { + return OnBoardingGitClone(errorMessage: gitCloneErrorMessage); + } + if ((pos == 2 && _createNewRepo) || pos == 1) { return OnBoardingGitUrl(doneFunction: (String sshUrl) { setPageInputUrlDone(); @@ -278,6 +315,20 @@ class OnBoardingScreenState extends State { } } + void _launchCreateRepoPage(GitRemoteRepo repo) async { + try { + if (repo == GitRemoteRepo.GitHub) { + await launch("https://github.com/new"); + } else if (repo == GitRemoteRepo.Gitlab) { + await launch("https://gitlab.com/projects/new"); + } + } catch (err, stack) { + // FIXME: Error handling? + print("_launchCreateRepoPage: " + err.toString()); + print(stack); + } + } + void _startGitClone(BuildContext context, String basePath) async { // Just in case it was half cloned because of an error await _removeExistingClone(basePath); @@ -376,6 +427,7 @@ class OnBoardingInitialChoice extends StatelessWidget { class OnBoardingCreateRepo extends StatelessWidget { final Function onDone; + final _configureKey = new GlobalKey(); OnBoardingCreateRepo({@required this.onDone}); @@ -394,15 +446,9 @@ class OnBoardingCreateRepo extends StatelessWidget { OnBoardingButton( text: "GitHub", iconUrl: 'assets/icon/github-icon.png', - onPressed: () async { - try { - await launch("https://github.com/new"); - } catch (err, stack) { - // FIXME: Error handling? - print(err); - print(stack); - } - onDone(); + onPressed: () { + var switchWidget = _configureKey.currentWidget as Switch; + onDone(GitRemoteRepo.GitHub, switchWidget.value); }, ), SizedBox(height: 8.0), @@ -410,16 +456,26 @@ class OnBoardingCreateRepo extends StatelessWidget { text: "GitLab", iconUrl: 'assets/icon/gitlab-icon.png', onPressed: () async { - try { - await launch("https://gitlab.com/projects/new"); - } catch (err, stack) { - // FIXME: Error handling? - print(err); - print(stack); - } - onDone(); + var switchWidget = _configureKey.currentWidget as Switch; + onDone(GitRemoteRepo.Gitlab, switchWidget.value); }, ), + SizedBox(height: 8.0), + Row( + children: [ + Switch( + key: _configureKey, + value: true, + onChanged: (bool value) {}, + ), + Text( + "Auto Configure", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.headline, + ), + ], + mainAxisAlignment: MainAxisAlignment.end, + ), ], mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start,