refactor(gitlab): lazy load languages and readme

This commit is contained in:
Rongjian Zhang
2020-11-04 16:16:03 +08:00
parent 40dff68e76
commit 78adfdfa88

View File

@@ -23,38 +23,43 @@ class GlProjectScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RefreshStatefulScaffold< return RefreshStatefulScaffold<
Tuple5<GitlabProject, Map<String, double>, List<GitlabProjectBadge>, Tuple4<GitlabProject, Future<Map<String, double>>, Future<int>,
int, String>>( Future<String>>>(
title: AppBarTitle('Project'), title: AppBarTitle('Project'),
fetch: () async { fetch: () async {
final auth = context.read<AuthModel>(); final auth = context.read<AuthModel>();
final res = await Future.wait([ final p =
auth.fetchGitlab('/projects/$id?statistics=1'), await auth.fetchGitlab('/projects/$id?statistics=1').then((res) {
auth.fetchGitlab('/projects/$id/languages'), return GitlabProject.fromJson(res);
auth.fetchGitlab('/projects/$id/badges'), });
auth.fetchGitlabWithPage('/projects/$id/members?per_page=1')
]); final langFuture =
final p = GitlabProject.fromJson(res[0]); auth.fetchGitlab('/projects/$id/languages').then((v) {
String readme; return Map<String, double>.from(v);
if (p.readmeUrl != null) { });
// we should get the markdown content, then render it // auth.fetchGitlab('/projects/$id/badges') // badges
// https://gitlab.com/gitlab-org/gitlab/-/issues/16335 final memberCountFuture = auth
final md = await auth.fetchWithGitlabToken( .fetchGitlabWithPage('/projects/$id/members?per_page=1')
p.readmeUrl.replaceFirst(r'/blob/', '/raw/')); .then((v) => v.total);
final res = await auth.fetchGitlab('/markdown', isPost: true, body: { final readmeFuture = p.readmeUrl == null
'text': md, ? Future.sync(() => null)
'gfm': true, : auth
'project': '${p.namespace.name}/${p.name}' .fetchWithGitlabToken(
}); p.readmeUrl.replaceFirst(r'/blob/', '/raw/'))
readme = (res['html'] as String).normalizedHtml; .then((md) async {
} // we should get the markdown content, then render it
return Tuple5( // https://gitlab.com/gitlab-org/gitlab/-/issues/16335
p, final res = await auth.fetchGitlab('/markdown',
Map<String, double>.from(res[1]), isPost: true,
(res[2] as List).map((v) => GitlabProjectBadge.fromJson(v)).toList(), body: {
(res[3] as DataWithPage).total, 'text': md,
readme, 'gfm': true,
); 'project': '${p.namespace.name}/${p.name}'
});
return (res['html'] as String).normalizedHtml;
});
return Tuple4(p, langFuture, memberCountFuture, readmeFuture);
}, },
actionBuilder: (t, setState) { actionBuilder: (t, setState) {
return ActionButton( return ActionButton(
@@ -66,8 +71,10 @@ class GlProjectScreen extends StatelessWidget {
}, },
bodyBuilder: (t, _) { bodyBuilder: (t, _) {
final p = t.item1; final p = t.item1;
final langs = t.item2; final langFuture = t.item2;
final badges = t.item3; final memberCountFuture = t.item3;
final readmeFuture = t.item4;
final theme = Provider.of<ThemeModel>(context); final theme = Provider.of<ThemeModel>(context);
final auth = Provider.of<AuthModel>(context); final auth = Provider.of<AuthModel>(context);
final prefix = final prefix =
@@ -95,10 +102,15 @@ class GlProjectScreen extends StatelessWidget {
CommonStyle.border, CommonStyle.border,
Row( Row(
children: <Widget>[ children: <Widget>[
EntryItem( FutureBuilder<int>(
count: t.item4, future: memberCountFuture,
text: 'Members', builder: (context, snapshot) {
url: '/gitlab/projects/$id/members', return EntryItem(
count: snapshot.data,
text: 'Members',
url: '/gitlab/projects/$id/members',
);
},
), ),
EntryItem( EntryItem(
count: p.starCount, count: p.starCount,
@@ -111,20 +123,39 @@ class GlProjectScreen extends StatelessWidget {
), ),
], ],
), ),
if (langs.isNotEmpty) ...[ CommonStyle.border,
CommonStyle.border, FutureBuilder<Map<String, double>>(
LanguageBar([ future: langFuture,
for (var e in langs.entries) builder: (context, snapshot) {
LanguageBarItem(name: e.key, ratio: e.value / 100) if (snapshot.data == null) {
]), return LanguageBar([
], LanguageBarItem(name: '', ratio: 1),
]);
} else {
return LanguageBar([
for (var e in snapshot.data?.entries ?? [])
LanguageBarItem(name: e.key, ratio: e.value / 100)
]);
}
},
),
CommonStyle.border, CommonStyle.border,
TableView( TableView(
hasIcon: true, hasIcon: true,
items: [ items: [
TableViewItem( TableViewItem(
leftIconData: Octicons.code, leftIconData: Octicons.code,
text: Text(langs.keys.isEmpty ? 'Code' : langs.keys.first), text: FutureBuilder<Map<String, double>>(
future: langFuture,
builder: (context, snapshot) {
if (snapshot.data == null) {
return Text('');
} else {
final langs = snapshot.data.keys;
return Text(langs.isEmpty ? 'Code' : langs.first);
}
},
),
rightWidget: p.statistics == null rightWidget: p.statistics == null
? null ? null
: Text(filesize(p.statistics.repositorySize)), : Text(filesize(p.statistics.repositorySize)),
@@ -154,7 +185,16 @@ class GlProjectScreen extends StatelessWidget {
], ],
), ),
CommonStyle.verticalGap, CommonStyle.verticalGap,
if (t.item5 != null) MarkdownHtmlView(t.item5) FutureBuilder<String>(
future: readmeFuture,
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container();
} else {
return MarkdownHtmlView(snapshot.data);
}
},
),
], ],
); );
}, },