1
0
mirror of https://github.com/git-touch/git-touch synced 2025-01-31 08:04:51 +01:00

feat(gitlab): commits screen

This commit is contained in:
Rongjian Zhang 2020-01-28 22:10:44 +08:00
parent 248212c95c
commit 5d453ccbd5
6 changed files with 210 additions and 93 deletions

View File

@ -8,6 +8,7 @@ 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/gitlab_blob.dart';
import 'package:git_touch/screens/gitlab_commits.dart';
import 'package:git_touch/screens/gitlab_issue.dart';
import 'package:git_touch/screens/gitlab_project.dart';
import 'package:git_touch/screens/gitlab_tree.dart';
@ -67,6 +68,7 @@ void main() async {
gitlabTreeRouter,
gitlabProjectRouter,
gitlabIssueRouter,
gitlabCommitsRouter,
loginRouter,
settingsRouter,
userRouter,

View File

@ -81,23 +81,6 @@ class GitlabIssueNote {
_$GitlabIssueNoteFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabProjectBadge {
String renderedImageUrl;
GitlabProjectBadge();
factory GitlabProjectBadge.fromJson(Map<String, dynamic> json) =>
_$GitlabProjectBadgeFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabProjectStatistics {
int commitCount;
int repositorySize;
GitlabProjectStatistics();
factory GitlabProjectStatistics.fromJson(Map<String, dynamic> json) =>
_$GitlabProjectStatisticsFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabProject {
int id;
@ -119,6 +102,23 @@ class GitlabProject {
_$GitlabProjectFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabProjectBadge {
String renderedImageUrl;
GitlabProjectBadge();
factory GitlabProjectBadge.fromJson(Map<String, dynamic> json) =>
_$GitlabProjectBadgeFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabProjectStatistics {
int commitCount;
int repositorySize;
GitlabProjectStatistics();
factory GitlabProjectStatistics.fromJson(Map<String, dynamic> json) =>
_$GitlabProjectStatisticsFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabProjectNamespace {
int id;
@ -175,3 +175,16 @@ class GitlabEventNote {
factory GitlabEventNote.fromJson(Map<String, dynamic> json) =>
_$GitlabEventNoteFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabCommit {
String id;
String shortId;
String title;
DateTime createdAt;
String authorName;
String message;
GitlabCommit();
factory GitlabCommit.fromJson(Map<String, dynamic> json) =>
_$GitlabCommitFromJson(json);
}

View File

@ -116,30 +116,6 @@ Map<String, dynamic> _$GitlabIssueNoteToJson(GitlabIssueNote instance) =>
'body': instance.body,
};
GitlabProjectBadge _$GitlabProjectBadgeFromJson(Map<String, dynamic> json) {
return GitlabProjectBadge()
..renderedImageUrl = json['rendered_image_url'] as String;
}
Map<String, dynamic> _$GitlabProjectBadgeToJson(GitlabProjectBadge instance) =>
<String, dynamic>{
'rendered_image_url': instance.renderedImageUrl,
};
GitlabProjectStatistics _$GitlabProjectStatisticsFromJson(
Map<String, dynamic> json) {
return GitlabProjectStatistics()
..commitCount = json['commit_count'] as int
..repositorySize = json['repository_size'] as int;
}
Map<String, dynamic> _$GitlabProjectStatisticsToJson(
GitlabProjectStatistics instance) =>
<String, dynamic>{
'commit_count': instance.commitCount,
'repository_size': instance.repositorySize,
};
GitlabProject _$GitlabProjectFromJson(Map<String, dynamic> json) {
return GitlabProject()
..id = json['id'] as int
@ -182,6 +158,30 @@ Map<String, dynamic> _$GitlabProjectToJson(GitlabProject instance) =>
'statistics': instance.statistics,
};
GitlabProjectBadge _$GitlabProjectBadgeFromJson(Map<String, dynamic> json) {
return GitlabProjectBadge()
..renderedImageUrl = json['rendered_image_url'] as String;
}
Map<String, dynamic> _$GitlabProjectBadgeToJson(GitlabProjectBadge instance) =>
<String, dynamic>{
'rendered_image_url': instance.renderedImageUrl,
};
GitlabProjectStatistics _$GitlabProjectStatisticsFromJson(
Map<String, dynamic> json) {
return GitlabProjectStatistics()
..commitCount = json['commit_count'] as int
..repositorySize = json['repository_size'] as int;
}
Map<String, dynamic> _$GitlabProjectStatisticsToJson(
GitlabProjectStatistics instance) =>
<String, dynamic>{
'commit_count': instance.commitCount,
'repository_size': instance.repositorySize,
};
GitlabProjectNamespace _$GitlabProjectNamespaceFromJson(
Map<String, dynamic> json) {
return GitlabProjectNamespace()
@ -252,3 +252,25 @@ Map<String, dynamic> _$GitlabEventNoteToJson(GitlabEventNote instance) =>
'noteable_type': instance.noteableType,
'noteable_iid': instance.noteableIid,
};
GitlabCommit _$GitlabCommitFromJson(Map<String, dynamic> json) {
return GitlabCommit()
..id = json['id'] as String
..shortId = json['short_id'] as String
..title = json['title'] as String
..createdAt = json['created_at'] == null
? null
: DateTime.parse(json['created_at'] as String)
..authorName = json['author_name'] as String
..message = json['message'] as String;
}
Map<String, dynamic> _$GitlabCommitToJson(GitlabCommit instance) =>
<String, dynamic>{
'id': instance.id,
'short_id': instance.shortId,
'title': instance.title,
'created_at': instance.createdAt?.toIso8601String(),
'author_name': instance.authorName,
'message': instance.message,
};

View File

@ -1,14 +1,11 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/link.dart';
import 'package:git_touch/widgets/commit_item.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
import 'package:git_touch/widgets/avatar.dart';
final commitsRouter = RouterScreen(
'/:owner/:name/commits',
@ -55,60 +52,23 @@ class CommitsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
return ListStatefulScaffold<GhCommitsCommit, String>(
title: AppBarTitle('Commits'),
onRefresh: () => _query(context),
onLoadMore: (cursor) => _query(context, cursor),
itemBuilder: (payload) {
return Link(
return CommitItem(
url: payload.url,
child: Container(
padding: CommonStyle.padding,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Avatar(url: payload.author?.avatarUrl),
SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
payload.messageHeadline,
style: TextStyle(
fontSize: 17,
color: theme.palette.text,
),
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 4),
Wrap(
children: <Widget>[
Text(
payload.author?.user?.login ??
payload.author.name,
style: TextStyle(fontSize: 15)),
Text(
' committed ${timeago.format(payload.committedDate)}',
style: TextStyle(
color: theme.palette.secondaryText,
fontSize: 15,
),
),
if (payload.status != null) ...[
avatarUrl: payload.author?.avatarUrl,
message: payload.messageHeadline,
author: payload.author?.user?.login ?? payload.author.name,
createdAt: payload.committedDate,
widgets: payload.status == null
? null
: [
SizedBox(width: 4),
_buildStatus(payload.status.state),
],
],
)
],
),
)
],
),
),
);
},
);

View File

@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/commit_item.dart';
import 'package:provider/provider.dart';
final gitlabCommitsRouter = RouterScreen('/gitlab/projects/:id/commits',
(context, params) => GitlabCommitsScreen(params['id'].first));
class GitlabCommitsScreen extends StatelessWidget {
final String id;
// final String branch; // TODO:
GitlabCommitsScreen(this.id);
Future<ListPayload<GitlabCommit, int>> _query(BuildContext context,
[int page = 1]) async {
final auth = Provider.of<AuthModel>(context);
final res =
await auth.fetchGitlab('/projects/$id/repository/commits?page=$page');
return ListPayload(
cursor: page + 1,
hasMore: true, // TODO:
items: (res as List).map((v) => GitlabCommit.fromJson(v)).toList(),
);
}
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GitlabCommit, int>(
title: AppBarTitle('Commits'),
onRefresh: () => _query(context),
onLoadMore: (cursor) => _query(context, cursor),
itemBuilder: (c) {
return CommitItem(
author: c.authorName,
avatarUrl: null,
createdAt: c.createdAt,
message: c.message,
// url: '${auth.activeAccount.domain}/',
url: null, // TODO:
);
},
);
}
}

View File

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/avatar.dart';
import 'package:git_touch/widgets/link.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
class CommitItem extends StatelessWidget {
final String url;
final String avatarUrl;
final String message;
final String author;
final DateTime createdAt;
final List<Widget> widgets;
CommitItem({
@required this.url,
@required this.avatarUrl,
@required this.message,
@required this.author,
@required this.createdAt,
this.widgets,
});
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
return Link(
url: url,
child: Container(
padding: CommonStyle.padding,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Avatar(url: avatarUrl),
SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
message,
style: TextStyle(
fontSize: 17,
color: theme.palette.text,
),
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 4),
Wrap(
children: <Widget>[
Text(author, style: TextStyle(fontSize: 15)),
Text(
' committed ${timeago.format(createdAt)}',
style: TextStyle(
color: theme.palette.secondaryText,
fontSize: 15,
),
),
if (widgets != null) ...widgets,
],
)
],
),
)
],
),
),
);
}
}