Rearrange the github adapter

This commit is contained in:
Aaron Fischer 2019-07-27 00:09:51 +02:00
parent 761717d0ab
commit 05ca125f87
4 changed files with 112 additions and 103 deletions

View file

@ -15,7 +15,7 @@ class GitHubAdapter extends ChangeNotifier {
DateTime _lastSync; DateTime _lastSync;
List<WarbandRoster> _rosters = []; List<WarbandRoster> _rosters = [];
String _activePlayerName; WarbandRoster _activeRoster;
String get repository => PrefService.getString('repository'); String get repository => PrefService.getString('repository');
String get path => PrefService.getString('path'); String get path => PrefService.getString('path');
@ -29,23 +29,13 @@ class GitHubAdapter extends ChangeNotifier {
UnmodifiableListView<WarbandRoster> get rosters => UnmodifiableListView<WarbandRoster> get rosters =>
UnmodifiableListView(_rosters); UnmodifiableListView(_rosters);
WarbandRoster activeRoster() { WarbandRoster get activeRoster => _activeRoster;
if (_activePlayerName == null || _rosters.length == 0) {
return null;
}
return _rosters.firstWhere((roster) { set activeRoster(WarbandRoster roster) {
return roster.playerName == _activePlayerName; _activeRoster = roster;
}, orElse: () => null);
}
void changeActiveRoster(String playerName) {
_activePlayerName = playerName;
notifyListeners(); notifyListeners();
} }
// TODO: Add persistence layer here
/// Search for warband files in the GitHub repository /// Search for warband files in the GitHub repository
/// ///
/// This method will search for matching files and check their content in a /// This method will search for matching files and check their content in a
@ -56,7 +46,7 @@ class GitHubAdapter extends ChangeNotifier {
_syncErrors.clear(); _syncErrors.clear();
_syncinProgress = true; _syncinProgress = true;
Stream<Map<String, String>> rosterStream() async* { Stream<String> warbandFileStream() async* {
// Get all files which could be potential warband files (end with // Get all files which could be potential warband files (end with
// mordheim.yml and contain the word "heros"). // mordheim.yml and contain the word "heros").
http.Response response = await http.get( http.Response response = await http.get(
@ -69,7 +59,7 @@ class GitHubAdapter extends ChangeNotifier {
// GitHub is not reachable // GitHub is not reachable
if (response.statusCode != 200) { if (response.statusCode != 200) {
_syncErrors.add('Could not find any warband roster files.'); _syncErrors.add('Could not find any warband roster files.');
yield {}; yield null;
return; return;
} }
@ -79,7 +69,7 @@ class GitHubAdapter extends ChangeNotifier {
searchResults = jsonDecode(response.body); searchResults = jsonDecode(response.body);
} on FormatException catch (e) { } on FormatException catch (e) {
_syncErrors.add('Could not parse GitHub response. ' + e.toString()); _syncErrors.add('Could not parse GitHub response. ' + e.toString());
yield {}; yield null;
return; return;
} }
@ -87,95 +77,37 @@ class GitHubAdapter extends ChangeNotifier {
RegExp fileRegex = new RegExp(r"[a-zA-Z]+\.mordheim\.ya?ml"); RegExp fileRegex = new RegExp(r"[a-zA-Z]+\.mordheim\.ya?ml");
for (dynamic searchResult in searchResults['items']) { for (dynamic searchResult in searchResults['items']) {
if (fileRegex.hasMatch(searchResult['name'])) { if (fileRegex.hasMatch(searchResult['name'])) {
// We try to get the name of the player from the name of the folder yield searchResult['path'].toString();
// in which the file resists
String completePath = searchResult['path'];
List<String> pathParts =
completePath.substring(path.length + 1).split('/');
String playerName;
if (pathParts.length >= 2) {
playerName = pathParts.first;
}
// Fetch last change and some metainformation of the file
http.Response response = await http.get(
"https://api.github.com/repos/" +
repository +
"/commits?path=" +
completePath);
if (response.statusCode != 200) {
_syncErrors.add('Could not load the warband metadata from GitHub.');
continue;
}
// No valid response from GitHub
dynamic commits;
try {
commits = jsonDecode(response.body);
} on FormatException catch (e) {
_syncErrors.add('Could not parse GitHub response. ' + e.toString());
continue;
}
// No commits available
if (commits.length == 0) {
continue;
}
dynamic latestCommit = commits.first;
yield {
'filePath': completePath.toString(),
'shaHash': latestCommit['sha'],
'player': playerName.toString(),
'author': latestCommit['commit']['author']['name'],
'date': latestCommit['commit']['committer']['date'],
'message': latestCommit['commit']['message']
};
} }
} }
} }
storage.clear();
_rosters.clear(); _rosters.clear();
notifyListeners(); notifyListeners();
if (_syncErrors.length == 0) { if (_syncErrors.length == 0) {
await for (Map<String, String> player in rosterStream()) { await for (String filePath in warbandFileStream()) {
http.Response response; WarbandRoster roster = await fetchWarband(filePath);
try { Version latestVersion = await getLatestCommit(filePath);
response = await http.get("https://raw.githubusercontent.com/" +
repository +
'/master/' +
player['filePath']);
} catch (e) {
// TODO: Ignore this error, we catch it elsewhere.
}
try { roster.playerName = getPlayerNameFromFilePath(filePath);
if (response != null) { roster.currentVersion = latestVersion;
YamlMap yamlObject = loadYaml(response.body);
WarbandRoster roster = WarbandRoster.fromJson(yamlObject);
if (player['player'] != '') {
roster.playerName = player['player'];
}
roster.currentVersion = new Version(player['shaHash'], // On a search, we drop all previous information about the warbands,
player['date'], player['author'], player['message']); // So, lastSyncVersion is equal to the currentVersion.
roster.lastSyncVersion = roster.currentVersion;
// On a search, we drop all previous information about the warbands, _rosters.add(roster);
// Sp, lastSyncVersion is equal to the currentVersion.
roster.lastSyncVersion = roster.currentVersion;
_rosters.add(roster); //https://github.com/lesnitsky/flutter_localstorage/blob/master/example/lib/main.dart
//https://github.com/lesnitsky/flutter_localstorage/blob/master/example/lib/main.dart // FIXME: store it correctly
// FIXME: store it correctly //storage.setItem(player['player'] + '-warband-yaml', response.body);
//storage.setItem(player['player'], roster); //storage.setItem(
notifyListeners(); // player['player'] + '-current-version', roster.currentVersion);
} //storage.setItem(
} catch (e) { // player['player'] + '-last-sync-version', roster.lastSyncVersion);
_syncErrors.add(e.toString()); notifyListeners();
}
} }
} }
@ -184,7 +116,7 @@ class GitHubAdapter extends ChangeNotifier {
// Select first as active player if no active player is selected // Select first as active player if no active player is selected
if (_rosters.length > 0) { if (_rosters.length > 0) {
_activePlayerName = _rosters.first.playerName; _activeRoster = _rosters.first;
} }
_lastSync = DateTime.now(); _lastSync = DateTime.now();
@ -195,12 +127,86 @@ class GitHubAdapter extends ChangeNotifier {
void update() async { void update() async {
_syncinProgress = true; _syncinProgress = true;
// TODO: Search for warband yml files
// TODO: Check if it is in the right format // TODO: Loop through the found warbands and update it.
// TODO: Store it into the database if valid
_lastSync = DateTime.now(); _lastSync = DateTime.now();
_syncinProgress = false; _syncinProgress = false;
notifyListeners(); notifyListeners();
} }
String getPlayerNameFromFilePath(String filePath) {
// We try to get the name of the player from the name of the folder
// in which the file resists
List<String> pathParts = filePath.substring(path.length + 1).split('/');
String playerName = 'Lonely Recluse';
if (pathParts.length >= 2) {
playerName = pathParts.first;
}
return playerName;
}
Future<Version> getLatestCommit(String filePath) async {
// Fetch last change and some metainformation of the file
http.Response response = await http.get("https://api.github.com/repos/" +
repository +
"/commits?path=" +
filePath);
if (response.statusCode != 200) {
_syncErrors.add('Could not load the warband metadata from GitHub.');
return null;
}
// No valid response from GitHub
dynamic commits;
try {
commits = jsonDecode(response.body);
} on FormatException catch (e) {
_syncErrors.add('Could not parse GitHub response. ' + e.toString());
return null;
}
// No commits available
if (commits.length == 0) {
return null;
}
dynamic latestCommit = commits.first;
return new Version(
latestCommit['sha'],
latestCommit['commit']['committer']['date'],
latestCommit['commit']['author']['name'],
latestCommit['commit']['message']);
}
Future<WarbandRoster> fetchWarband(String filePath) async {
http.Response response;
try {
response = await http.get("https://raw.githubusercontent.com/" +
repository +
'/master/' +
filePath);
} catch (e) {
// We ignore this error, because it will handle from the _syncErrors
// later (see below).
}
try {
if (response != null) {
YamlMap yamlObject = loadYaml(response.body);
return WarbandRoster.fromJson(yamlObject);
}
} catch (e) {
_syncErrors.add(e.toString());
}
return null;
}
void readWarband(WarbandRoster roster, String yamlContent) {
// TODO: Read the warband from the shared preferences
}
} }

View file

@ -204,10 +204,13 @@ class WarbandRoster {
final List<HenchmenGroup> henchmenGroups; final List<HenchmenGroup> henchmenGroups;
/// The players name is not defined in the yml file. This will be added later /// The players name is not defined in the yml file. This will be added later
/// from the GitHubAdapter. /// from the GitHubAdapter. Same goes for the lastSyncVersion and currentVersion.
@JsonKey(ignore: true) @JsonKey(ignore: true)
String playerName = 'Lonely Recluse'; String playerName = 'Lonely Recluse';
@JsonKey(ignore: true)
String filePath;
@JsonKey(ignore: true) @JsonKey(ignore: true)
Version lastSyncVersion; Version lastSyncVersion;

View file

@ -9,7 +9,7 @@ class WarbandRosterScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
GitHubAdapter github = Provider.of<GitHubAdapter>(context); GitHubAdapter github = Provider.of<GitHubAdapter>(context);
WarbandRoster roster = github.activeRoster(); WarbandRoster roster = github.activeRoster;
if (roster == null) { if (roster == null) {
return Scaffold( return Scaffold(

View file

@ -32,7 +32,7 @@ class WarbandDrawerWidget extends StatelessWidget {
} }
// Never fetched any data // Never fetched any data
if (github.activeRoster() == null) { if (github.activeRoster == null) {
return Padding( return Padding(
padding: const EdgeInsets.only(top: 100, left: 30, right: 30), padding: const EdgeInsets.only(top: 100, left: 30, right: 30),
child: Column(children: <Widget>[ child: Column(children: <Widget>[
@ -56,7 +56,7 @@ class WarbandDrawerWidget extends StatelessWidget {
Widget buildRosterList(BuildContext context) { Widget buildRosterList(BuildContext context) {
GitHubAdapter github = Provider.of<GitHubAdapter>(context); GitHubAdapter github = Provider.of<GitHubAdapter>(context);
WarbandRoster activeroster = github.activeRoster(); WarbandRoster activeroster = github.activeRoster;
List<WarbandRoster> rosters = github.rosters; List<WarbandRoster> rosters = github.rosters;
List<Widget> tiles = new List(); List<Widget> tiles = new List();
@ -96,7 +96,7 @@ class WarbandDrawerWidget extends StatelessWidget {
tiles.add(ListTile( tiles.add(ListTile(
onTap: () { onTap: () {
github.changeActiveRoster(roster.playerName); github.activeRoster = roster;
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
title: Text(roster.name + ' (' + roster.playerName + ')', title: Text(roster.name + ' (' + roster.playerName + ')',