OnBoarding: Move cloning logic to parent widget

There were a few cases when since we were calling an async function in
initState, which would then call setState, we would get an exception.

Also this way, the entire logic of the onboarding is in one place, and
the individual screens are far far simpler.
This commit is contained in:
Vishesh Handa
2019-01-16 22:47:30 +01:00
parent f7e67309bd
commit 3d88ed9c05
2 changed files with 50 additions and 80 deletions

View File

@ -1,73 +1,16 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:path/path.dart' as p;
class OnBoardingGitClone extends StatelessWidget {
final String errorMessage;
import 'package:journal/analytics.dart';
import 'package:journal/state_container.dart';
import 'package:journal/storage/git.dart';
class OnBoardingGitClone extends StatefulWidget {
final Function doneFunction;
OnBoardingGitClone({@required this.doneFunction});
@override
OnBoardingGitCloneState createState() {
return new OnBoardingGitCloneState();
}
}
class OnBoardingGitCloneState extends State<OnBoardingGitClone> {
String errorMessage = "";
@override
void initState() {
super.initState();
// FIXME: This is throwing an exception!
_initStateAsync();
}
void _initStateAsync() async {
var pref = await SharedPreferences.getInstance();
String sshCloneUrl = pref.getString("sshCloneUrl");
// Just in case it was half cloned because of an error
await _removeExistingClone();
String error = await gitClone(sshCloneUrl, "journal");
if (error != null && error.isNotEmpty) {
setState(() {
getAnalytics().logEvent(
name: "onboarding_gitClone_error",
parameters: <String, dynamic>{
'error': error,
},
);
errorMessage = error;
});
} else {
this.widget.doneFunction();
}
}
Future _removeExistingClone() async {
var baseDir = await getNotesDir();
var dotGitDir = new Directory(p.join(baseDir.path, ".git"));
bool exists = await dotGitDir.exists();
if (exists) {
await baseDir.delete(recursive: true);
await baseDir.create();
}
}
OnBoardingGitClone({
this.errorMessage,
});
@override
Widget build(BuildContext context) {
var children = <Widget>[];
if (this.errorMessage.isEmpty) {
if (this.errorMessage == null || this.errorMessage.isEmpty) {
children = <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
@ -85,7 +28,7 @@ class OnBoardingGitCloneState extends State<OnBoardingGitClone> {
),
),
];
} else if (this.errorMessage.isNotEmpty) {
} else {
children = <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),

View File

@ -1,6 +1,7 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:path/path.dart' as p;
@ -32,6 +33,7 @@ class OnBoardingScreenState extends State<OnBoardingScreen> {
var _pageSshKeyDone = false;
var _gitCloneUrl = "";
String gitCloneErrorMessage = "";
var pageController = PageController();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@ -108,13 +110,10 @@ class OnBoardingScreenState extends State<OnBoardingScreen> {
curve: Curves.easeIn,
);
SharedPreferences.getInstance().then((SharedPreferences pref) {
// We aren't calling setState as this isn't being used for rendering
_gitCloneUrl = sshUrl;
// We aren't calling setState as this isn't being used for rendering
_gitCloneUrl = sshUrl;
pref.setString("sshCloneUrl", sshUrl);
this._generateSshKey();
});
this._generateSshKey();
getAnalytics().logEvent(
name: "onboarding_git_url_enterred",
@ -131,6 +130,8 @@ class OnBoardingScreenState extends State<OnBoardingScreen> {
curve: Curves.easeIn,
);
_startGitClone();
getAnalytics().logEvent(
name: "onboarding_public_key_copied",
parameters: <String, dynamic>{},
@ -141,15 +142,7 @@ class OnBoardingScreenState extends State<OnBoardingScreen> {
}
if ((pos == 4 && _createNewRepo) || pos == 3) {
return OnBoardingGitClone(
doneFunction: () {
getAnalytics().logEvent(
name: "onboarding_complete",
parameters: <String, dynamic>{},
);
this.widget.onBoardingCompletedFunction();
},
);
return OnBoardingGitClone(errorMessage: gitCloneErrorMessage);
}
},
itemCount: pageCount,
@ -243,6 +236,40 @@ class OnBoardingScreenState extends State<OnBoardingScreen> {
print(stack.toString());
}
}
void _startGitClone() async {
// Just in case it was half cloned because of an error
await _removeExistingClone();
String error = await gitClone(_gitCloneUrl, "journal");
if (error != null && error.isNotEmpty) {
setState(() {
getAnalytics().logEvent(
name: "onboarding_gitClone_error",
parameters: <String, dynamic>{
'error': error,
},
);
gitCloneErrorMessage = error;
});
} else {
getAnalytics().logEvent(
name: "onboarding_complete",
parameters: <String, dynamic>{},
);
this.widget.onBoardingCompletedFunction();
}
}
Future _removeExistingClone() async {
var baseDir = await getNotesDir();
var dotGitDir = new Directory(p.join(baseDir.path, ".git"));
bool exists = await dotGitDir.exists();
if (exists) {
await baseDir.delete(recursive: true);
await baseDir.create();
}
}
}
class OnBoardingInitialChoice extends StatelessWidget {