1
0
mirror of https://github.com/git-touch/git-touch synced 2024-12-16 10:20:55 +01:00

refactor: gitlab types

This commit is contained in:
Rongjian Zhang 2019-12-04 22:00:39 +08:00
parent 103f05b01c
commit ee027bb0d2
6 changed files with 268 additions and 59 deletions

81
lib/models/gitlab.dart Normal file
View File

@ -0,0 +1,81 @@
import 'package:json_annotation/json_annotation.dart';
part 'gitlab.g.dart';
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabUser {
int id;
String username;
String name;
String avatarUrl;
GitlabUser();
factory GitlabUser.fromJson(Map<String, dynamic> json) =>
_$GitlabUserFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabRepository {
int id;
GitlabUser owner;
String name;
String description;
int starCount;
int forksCount;
GitlabRepository();
factory GitlabRepository.fromJson(Map<String, dynamic> json) =>
_$GitlabRepositoryFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabTodoProject {
String pathWithNamespace;
GitlabTodoProject();
factory GitlabTodoProject.fromJson(Map<String, dynamic> json) =>
_$GitlabTodoProjectFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabTodo {
GitlabUser author;
GitlabTodoProject project;
String actionName;
String targetType;
GitlabIssue target;
GitlabTodo();
factory GitlabTodo.fromJson(Map<String, dynamic> json) =>
_$GitlabTodoFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabIssue {
int iid;
int projectId;
String title;
GitlabUser author;
String description;
String createdAt;
GitlabIssue();
factory GitlabIssue.fromJson(Map<String, dynamic> json) =>
_$GitlabIssueFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GitlabIssueNote {
GitlabUser author;
String body;
GitlabIssueNote();
factory GitlabIssueNote.fromJson(Map<String, dynamic> json) =>
_$GitlabIssueNoteFromJson(json);
}

115
lib/models/gitlab.g.dart Normal file
View File

@ -0,0 +1,115 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'gitlab.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GitlabUser _$GitlabUserFromJson(Map<String, dynamic> json) {
return GitlabUser()
..id = json['id'] as int
..username = json['username'] as String
..name = json['name'] as String
..avatarUrl = json['avatar_url'] as String;
}
Map<String, dynamic> _$GitlabUserToJson(GitlabUser instance) =>
<String, dynamic>{
'id': instance.id,
'username': instance.username,
'name': instance.name,
'avatar_url': instance.avatarUrl,
};
GitlabRepository _$GitlabRepositoryFromJson(Map<String, dynamic> json) {
return GitlabRepository()
..id = json['id'] as int
..owner = json['owner'] == null
? null
: GitlabUser.fromJson(json['owner'] as Map<String, dynamic>)
..name = json['name'] as String
..description = json['description'] as String
..starCount = json['star_count'] as int
..forksCount = json['forks_count'] as int;
}
Map<String, dynamic> _$GitlabRepositoryToJson(GitlabRepository instance) =>
<String, dynamic>{
'id': instance.id,
'owner': instance.owner,
'name': instance.name,
'description': instance.description,
'star_count': instance.starCount,
'forks_count': instance.forksCount,
};
GitlabTodoProject _$GitlabTodoProjectFromJson(Map<String, dynamic> json) {
return GitlabTodoProject()
..pathWithNamespace = json['path_with_namespace'] as String;
}
Map<String, dynamic> _$GitlabTodoProjectToJson(GitlabTodoProject instance) =>
<String, dynamic>{
'path_with_namespace': instance.pathWithNamespace,
};
GitlabTodo _$GitlabTodoFromJson(Map<String, dynamic> json) {
return GitlabTodo()
..author = json['author'] == null
? null
: GitlabUser.fromJson(json['author'] as Map<String, dynamic>)
..project = json['project'] == null
? null
: GitlabTodoProject.fromJson(json['project'] as Map<String, dynamic>)
..actionName = json['action_name'] as String
..targetType = json['target_type'] as String
..target = json['target'] == null
? null
: GitlabIssue.fromJson(json['target'] as Map<String, dynamic>);
}
Map<String, dynamic> _$GitlabTodoToJson(GitlabTodo instance) =>
<String, dynamic>{
'author': instance.author,
'project': instance.project,
'action_name': instance.actionName,
'target_type': instance.targetType,
'target': instance.target,
};
GitlabIssue _$GitlabIssueFromJson(Map<String, dynamic> json) {
return GitlabIssue()
..iid = json['iid'] as int
..projectId = json['project_id'] as int
..title = json['title'] as String
..author = json['author'] == null
? null
: GitlabUser.fromJson(json['author'] as Map<String, dynamic>)
..description = json['description'] as String
..createdAt = json['created_at'] as String;
}
Map<String, dynamic> _$GitlabIssueToJson(GitlabIssue instance) =>
<String, dynamic>{
'iid': instance.iid,
'project_id': instance.projectId,
'title': instance.title,
'author': instance.author,
'description': instance.description,
'created_at': instance.createdAt,
};
GitlabIssueNote _$GitlabIssueNoteFromJson(Map<String, dynamic> json) {
return GitlabIssueNote()
..author = json['author'] == null
? null
: GitlabUser.fromJson(json['author'] as Map<String, dynamic>)
..body = json['body'] as String;
}
Map<String, dynamic> _$GitlabIssueNoteToJson(GitlabIssueNote instance) =>
<String, dynamic>{
'author': instance.author,
'body': instance.body,
};

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart'; import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/utils/utils.dart'; import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/avatar.dart'; import 'package:git_touch/widgets/avatar.dart';
@ -6,34 +7,40 @@ import 'package:git_touch/widgets/markdown_view.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:git_touch/models/auth.dart'; import 'package:git_touch/models/auth.dart';
import 'package:timeago/timeago.dart' as timeago; import 'package:timeago/timeago.dart' as timeago;
import 'package:tuple/tuple.dart';
class GitlabIssueScreen extends StatelessWidget { class GitlabIssueScreen extends StatelessWidget {
final int projectId; final int projectId;
final int issueIid; final int iid;
final bool isMr; final bool isMr;
GitlabIssueScreen(this.projectId, this.issueIid, {this.isMr}); GitlabIssueScreen(this.projectId, this.iid, {this.isMr});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RefreshStatefulScaffold( return RefreshStatefulScaffold<
title: Text('Issue #$issueIid'), Tuple3<GitlabIssue, Iterable<GitlabIssueNote>, List>>(
title: Text('Issue #$iid'),
fetchData: () async { fetchData: () async {
final type = isMr ? 'merge_requests' : 'issues'; final type = isMr ? 'merge_requests' : 'issues';
final items = await Future.wait([ final items = await Future.wait([
Provider.of<AuthModel>(context) Provider.of<AuthModel>(context)
.fetchGitlab('/projects/$projectId/$type/$issueIid'), .fetchGitlab('/projects/$projectId/$type/$iid'),
Provider.of<AuthModel>(context) Provider.of<AuthModel>(context)
.fetchGitlab('/projects/$projectId/$type/$issueIid/notes'), .fetchGitlab('/projects/$projectId/$type/$iid/notes'),
Provider.of<AuthModel>(context) Provider.of<AuthModel>(context)
.fetchGitlab('/projects/$projectId/$type/$issueIid/award_emoji'), .fetchGitlab('/projects/$projectId/$type/$iid/award_emoji'),
]); ]);
return items; return Tuple3(
GitlabIssue.fromJson(items[0]),
(items[1] as List).map((v) => GitlabIssueNote.fromJson(v)),
items[2] as List,
);
}, },
bodyBuilder: (data, _) { bodyBuilder: (data, _) {
final issue = data[0]; final issue = data.item1;
final notes = data[1] as List; final notes = data.item2;
final emoji = data[2]; final emoji = data.item3;
return Column( return Column(
children: <Widget>[ children: <Widget>[
@ -41,16 +48,16 @@ class GitlabIssueScreen extends StatelessWidget {
padding: CommonStyle.padding, padding: CommonStyle.padding,
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
Text(issue['title']), Text(issue.title),
Row( Row(
children: <Widget>[ children: <Widget>[
Avatar.medium(url: issue['author']['avatar_url']), Avatar.medium(url: issue.author.avatarUrl),
Expanded( Expanded(
child: Text(issue['description']), child: Text(issue.description),
), ),
], ],
), ),
Text(timeago.format(DateTime.parse(issue['created_at']))) Text(timeago.format(DateTime.parse(issue.createdAt)))
], ],
), ),
), ),
@ -63,15 +70,15 @@ class GitlabIssueScreen extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Row( Row(
children: <Widget>[ children: <Widget>[
Avatar.medium(url: note['author']['avatar_url']), Avatar.medium(url: note.author.avatarUrl),
Expanded( Expanded(
child: Column( child: Column(
children: <Widget>[Text(note['author']['name'])], children: <Widget>[Text(note.author.name)],
), ),
) )
], ],
), ),
MarkdownView(note['body']), MarkdownView(note.body),
], ],
), ),
); );

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart'; import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/models/theme.dart'; import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart'; import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/screens/gitlab/issue.dart'; import 'package:git_touch/screens/gitlab/issue.dart';
@ -13,33 +14,32 @@ class GitlabTodosScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context); final theme = Provider.of<ThemeModel>(context);
return RefreshStatefulScaffold( return RefreshStatefulScaffold<Iterable<GitlabTodo>>(
title: Text('Todos'), title: Text('Todos'),
fetchData: () { fetchData: () async {
return Provider.of<AuthModel>(context).fetchGitlab('/todos'); final vs = await Provider.of<AuthModel>(context).fetchGitlab('/todos');
return (vs as List).map((v) => GitlabTodo.fromJson(v));
}, },
bodyBuilder: (data, _) { bodyBuilder: (data, _) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: (data as List).map((item) { children: data.map((item) {
return Link( return Link(
screenBuilder: (_) => GitlabIssueScreen( screenBuilder: (_) => GitlabIssueScreen(
item['target']['project_id'], item['target']['iid'], item.target.projectId, item.target.iid,
isMr: item['target_type'] == 'MergeRequest'), isMr: item.targetType == 'MergeRequest'),
child: Container( child: Container(
padding: CommonStyle.padding, padding: CommonStyle.padding,
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Avatar.medium( Avatar.medium(url: item.author.avatarUrl),
url: item['author']['avatar_url'],
),
SizedBox(width: 12), SizedBox(width: 12),
Expanded( Expanded(
child: Text.rich( child: Text.rich(
TextSpan( TextSpan(
children: [ children: [
TextSpan( TextSpan(
text: item['author']['name'], text: item.author.name,
style: TextStyle( style: TextStyle(
color: theme.palette.primary, color: theme.palette.primary,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -47,13 +47,13 @@ class GitlabTodosScreen extends StatelessWidget {
), ),
TextSpan( TextSpan(
text: ' ' + text: ' ' +
item['action_name'] + item.actionName +
' you ' + ' you ' +
item['target_type'] + item.targetType +
' ' + ' ' +
item['project']['path_with_namespace'] + item.project.pathWithNamespace +
' ' + ' ' +
item['target']['iid'].toString(), item.target.iid.toString(),
), ),
], ],
), ),

View File

@ -1,10 +1,12 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:git_touch/models/auth.dart'; import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart'; import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/widgets/border_view.dart'; import 'package:git_touch/widgets/border_view.dart';
import 'package:git_touch/widgets/repository_item.dart'; import 'package:git_touch/widgets/repository_item.dart';
import 'package:git_touch/widgets/user_item.dart'; import 'package:git_touch/widgets/user_item.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart';
class GitlabUserScreen extends StatelessWidget { class GitlabUserScreen extends StatelessWidget {
final String username; final String username;
@ -13,32 +15,35 @@ class GitlabUserScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RefreshStatefulScaffold( return RefreshStatefulScaffold<
Tuple3<GitlabUser, Iterable<GitlabRepository>,
List<Map<String, double>>>>(
title: Text('User'), title: Text('User'),
fetchData: () async { fetchData: () async {
final items = await Provider.of<AuthModel>(context) final auth = Provider.of<AuthModel>(context);
.fetchGitlab('/users?username=$username');
final user = items[0]; final v0 = await auth.fetchGitlab('/users?username=$username');
final projects = await Provider.of<AuthModel>(context) final user = GitlabUser.fromJson(v0[0]);
.fetchGitlab('/users/${user['id']}/projects') as List;
final langs = await Future.wait(projects.map((p) => final v1 = await auth.fetchGitlab('/users/${user.id}/projects');
Provider.of<AuthModel>(context) final projects = (v1 as List).map((v) => GitlabRepository.fromJson(v));
.fetchGitlab('/projects/${p['id']}/languages')));
for (var i = 0; i < projects.length; i++) { final languages = await Future.wait(projects
projects[i]['language'] = langs[i]; .map((p) => auth.fetchGitlab('/projects/${p.id}/languages')));
}
return [user, projects]; return Tuple3(user, projects, languages.cast<Map<String, double>>());
}, },
bodyBuilder: (data, _) { bodyBuilder: (data, _) {
final user = data[0]; final user = data.item1;
final projects = data[1] as List; final projects = data.item2;
final languages = data.item3;
return Column( return Column(
children: <Widget>[ children: <Widget>[
UserItem( UserItem(
login: user['username'], login: user.username,
avatarUrl: user['avatar_url'], avatarUrl: user.avatarUrl,
name: user['name'], name: user.name,
), ),
BorderView(height: 10), BorderView(height: 10),
Column( Column(

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/models/theme.dart'; import 'package:git_touch/models/theme.dart';
import 'package:git_touch/screens/repository.dart'; import 'package:git_touch/screens/repository.dart';
import 'package:git_touch/widgets/action_button.dart'; import 'package:git_touch/widgets/action_button.dart';
@ -65,18 +66,18 @@ class RepositoryItem extends StatelessWidget {
? [] ? []
: payload['repositoryTopics']['nodes']; : payload['repositoryTopics']['nodes'];
RepositoryItem.gitlab(payload, {this.inRepoScreen = false}) RepositoryItem.gitlab(GitlabRepository payload, {this.inRepoScreen = false})
: this.owner = payload['namespace']['name'], : this.owner = payload.owner.name,
this.avatarUrl = payload['owner']['avatar_url'], this.avatarUrl = payload.owner.avatarUrl,
this.name = payload['name'], this.name = payload.name,
this.description = payload['description'], this.description = payload.description,
this.iconData = Octicons.repo, this.iconData = Octicons.repo,
this.starCount = payload['star_count'], this.starCount = payload.starCount,
this.forkCount = payload['forks_count'], this.forkCount = payload.forksCount,
this.primaryLanguageName = null, this.primaryLanguageName = null,
this.primaryLanguageColor = null, this.primaryLanguageColor = null,
this.screenBuilder = ((_) => this.screenBuilder =
RepositoryScreen(payload['owner']['login'], payload['name'])), ((_) => RepositoryScreen(payload.owner.username, payload.name)),
this.topics = []; this.topics = [];
static IconData _buildIconData(payload) { static IconData _buildIconData(payload) {