diff --git a/lib/main.dart b/lib/main.dart index c0304f1..c5936d1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,8 @@ import 'package:git_touch/models/theme.dart'; import 'package:git_touch/screens/about.dart'; import 'package:git_touch/screens/code_theme.dart'; import 'package:git_touch/screens/commits.dart'; +import 'package:git_touch/screens/gitea_repo.dart'; +import 'package:git_touch/screens/gitea_user.dart'; import 'package:git_touch/screens/gitlab_blob.dart'; import 'package:git_touch/screens/gitlab_commits.dart'; import 'package:git_touch/screens/gitlab_issue.dart'; @@ -74,6 +76,8 @@ void main() async { gitlabIssuesRouter, gitlabMergeRequestsRouter, gitlabCommitsRouter, + giteaUserRouter, + giteaRepoRouter, loginRouter, settingsRouter, userRouter, diff --git a/lib/models/gitea.dart b/lib/models/gitea.dart index 494dfd4..a54ba2f 100644 --- a/lib/models/gitea.dart +++ b/lib/models/gitea.dart @@ -23,6 +23,10 @@ class GiteaRepository { int starsCount; int forksCount; DateTime updatedAt; + String website; + int size; + int openIssuesCount; + int openPrCounter; GiteaRepository(); factory GiteaRepository.fromJson(Map json) => _$GiteaRepositoryFromJson(json); diff --git a/lib/models/gitea.g.dart b/lib/models/gitea.g.dart index 9e920ce..9067f84 100644 --- a/lib/models/gitea.g.dart +++ b/lib/models/gitea.g.dart @@ -37,7 +37,11 @@ GiteaRepository _$GiteaRepositoryFromJson(Map json) { ..forksCount = json['forks_count'] as int ..updatedAt = json['updated_at'] == null ? null - : DateTime.parse(json['updated_at'] as String); + : DateTime.parse(json['updated_at'] as String) + ..website = json['website'] as String + ..size = json['size'] as int + ..openIssuesCount = json['open_issues_count'] as int + ..openPrCounter = json['open_pr_counter'] as int; } Map _$GiteaRepositoryToJson(GiteaRepository instance) => @@ -49,4 +53,8 @@ Map _$GiteaRepositoryToJson(GiteaRepository instance) => 'stars_count': instance.starsCount, 'forks_count': instance.forksCount, 'updated_at': instance.updatedAt?.toIso8601String(), + 'website': instance.website, + 'size': instance.size, + 'open_issues_count': instance.openIssuesCount, + 'open_pr_counter': instance.openPrCounter, }; diff --git a/lib/screens/gitea_repo.dart b/lib/screens/gitea_repo.dart new file mode 100644 index 0000000..1396002 --- /dev/null +++ b/lib/screens/gitea_repo.dart @@ -0,0 +1,111 @@ +import 'package:filesize/filesize.dart'; +import 'package:flutter/material.dart'; +import 'package:git_touch/models/auth.dart'; +import 'package:git_touch/models/gitea.dart'; +import 'package:git_touch/models/theme.dart'; +import 'package:git_touch/scaffolds/refresh_stateful.dart'; +import 'package:git_touch/utils/utils.dart'; +import 'package:git_touch/widgets/app_bar_title.dart'; +import 'package:git_touch/widgets/entry_item.dart'; +import 'package:git_touch/widgets/markdown_view.dart'; +import 'package:git_touch/widgets/repo_header.dart'; +import 'package:git_touch/widgets/table_view.dart'; +import 'package:provider/provider.dart'; +import 'package:tuple/tuple.dart'; + +final giteaRepoRouter = RouterScreen( + '/gitea/:owner/:name', + (context, params) => + GiteaRepoScreen(params['owner'].first, params['name'].first), +); + +class GiteaRepoScreen extends StatelessWidget { + final String owner; + final String name; + GiteaRepoScreen(this.owner, this.name); + + @override + Widget build(BuildContext context) { + return RefreshStatefulScaffold>( + title: AppBarTitle('Repository'), + fetchData: () async { + final auth = Provider.of(context); + final res = await Future.wait([ + auth.fetchGitea('/repos/$owner/$name'), + auth.fetchGitea('/repos/$owner/$name/contents/README.md'), + ]); + return Tuple2( + GiteaRepository.fromJson(res[0]), + convertBase64ToString(res[1]['content']), + ); + }, + bodyBuilder: (t, setState) { + final theme = Provider.of(context); + final p = t.item1; + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RepoHeader( + avatarUrl: p.owner.avatarUrl, + avatarLink: '/gitea/${p.owner.login}', + owner: p.owner.login, + name: p.name, + description: p.description, + homepageUrl: p.website, + ), + CommonStyle.border, + Row( + children: [ + EntryItem( + count: p.starsCount, + text: 'Stars', + ), + EntryItem( + count: p.forksCount, + text: 'Forks', // TODO: + ), + ], + ), + CommonStyle.border, + TableView( + hasIcon: true, + items: [ + TableViewItem( + leftIconData: Octicons.code, + text: Text('Code'), + rightWidget: Text(filesize(p.size * 1000)), + url: '/gitea/blob', + ), + TableViewItem( + leftIconData: Octicons.issue_opened, + text: Text('Issues'), + rightWidget: Text(numberFormat.format(p.openIssuesCount)), + url: '/gitea/$owner/$name/issues', + ), + TableViewItem( + leftIconData: Octicons.git_pull_request, + text: Text('Pull requests'), + rightWidget: Text(numberFormat.format(p.openPrCounter)), + url: '/gitea/$owner/$name/pulls', + ), + TableViewItem( + leftIconData: Octicons.history, + text: Text('Commits'), + url: '/gitea/$owner/$name/commits', + ), + ], + ), + CommonStyle.verticalGap, + if (t.item2 != null) + Container( + padding: CommonStyle.padding, + color: theme.palette.background, + child: MarkdownView(t.item2), + ), + CommonStyle.verticalGap, + ], + ); + }, + ); + } +} diff --git a/lib/screens/gitea_user.dart b/lib/screens/gitea_user.dart index 249ce58..54eac33 100644 --- a/lib/screens/gitea_user.dart +++ b/lib/screens/gitea_user.dart @@ -12,6 +12,11 @@ import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; import 'package:timeago/timeago.dart' as timeago; +final giteaUserRouter = RouterScreen( + '/gitea/:login', + (context, params) => GiteaUserScreen(params['login'].first), +); + class GiteaUserScreen extends StatelessWidget { final String login; GiteaUserScreen(this.login); @@ -66,7 +71,7 @@ class GiteaUserScreen extends StatelessWidget { starCount: v.starsCount, forkCount: v.forksCount, note: 'Updated ${timeago.format(v.updatedAt)}', - url: '', // TODO: + url: '/gitea/${v.owner.login}/${v.name}', // TODO: ) ], ) diff --git a/lib/screens/repository.dart b/lib/screens/repository.dart index bbd41dd..b2f883d 100644 --- a/lib/screens/repository.dart +++ b/lib/screens/repository.dart @@ -47,16 +47,9 @@ class RepositoryScreen extends StatelessWidget { } Future _fetchReadme(BuildContext context) async { - var data = await Provider.of(context) + final data = await Provider.of(context) .getWithCredentials('/repos/$owner/$name/readme'); - - if (data['content'] == null) { - return null; - } - - var bits = base64.decode((data['content'] as String).replaceAll('\n', '')); - var str = utf8.decode(bits); - return str; + return convertBase64ToString(data['content']); } Widget _buildLanguages(BuildContext context, GhRepoRepository repo) { diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 14ff6c4..e6ccedb 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:fluro/fluro.dart'; import 'package:flutter/material.dart'; @@ -187,3 +188,9 @@ class RouterScreen { } final dateFormat = DateFormat.yMMMMd(); + +String convertBase64ToString(String input) { + if (input == null) return null; + final bits = base64.decode(input.replaceAll('\n', '')); + return utf8.decode(bits); +}