1
0
mirror of https://github.com/git-touch/git-touch synced 2024-12-15 17:59:35 +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:git_touch/models/gitlab.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/utils/utils.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:git_touch/models/auth.dart';
import 'package:timeago/timeago.dart' as timeago;
import 'package:tuple/tuple.dart';
class GitlabIssueScreen extends StatelessWidget {
final int projectId;
final int issueIid;
final int iid;
final bool isMr;
GitlabIssueScreen(this.projectId, this.issueIid, {this.isMr});
GitlabIssueScreen(this.projectId, this.iid, {this.isMr});
@override
Widget build(BuildContext context) {
return RefreshStatefulScaffold(
title: Text('Issue #$issueIid'),
return RefreshStatefulScaffold<
Tuple3<GitlabIssue, Iterable<GitlabIssueNote>, List>>(
title: Text('Issue #$iid'),
fetchData: () async {
final type = isMr ? 'merge_requests' : 'issues';
final items = await Future.wait([
Provider.of<AuthModel>(context)
.fetchGitlab('/projects/$projectId/$type/$issueIid'),
.fetchGitlab('/projects/$projectId/$type/$iid'),
Provider.of<AuthModel>(context)
.fetchGitlab('/projects/$projectId/$type/$issueIid/notes'),
.fetchGitlab('/projects/$projectId/$type/$iid/notes'),
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, _) {
final issue = data[0];
final notes = data[1] as List;
final emoji = data[2];
final issue = data.item1;
final notes = data.item2;
final emoji = data.item3;
return Column(
children: <Widget>[
@ -41,16 +48,16 @@ class GitlabIssueScreen extends StatelessWidget {
padding: CommonStyle.padding,
child: Column(
children: <Widget>[
Text(issue['title']),
Text(issue.title),
Row(
children: <Widget>[
Avatar.medium(url: issue['author']['avatar_url']),
Avatar.medium(url: issue.author.avatarUrl),
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>[
Row(
children: <Widget>[
Avatar.medium(url: note['author']['avatar_url']),
Avatar.medium(url: note.author.avatarUrl),
Expanded(
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:git_touch/models/auth.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/screens/gitlab/issue.dart';
@ -13,33 +14,32 @@ class GitlabTodosScreen extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
return RefreshStatefulScaffold(
return RefreshStatefulScaffold<Iterable<GitlabTodo>>(
title: Text('Todos'),
fetchData: () {
return Provider.of<AuthModel>(context).fetchGitlab('/todos');
fetchData: () async {
final vs = await Provider.of<AuthModel>(context).fetchGitlab('/todos');
return (vs as List).map((v) => GitlabTodo.fromJson(v));
},
bodyBuilder: (data, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: (data as List).map((item) {
children: data.map((item) {
return Link(
screenBuilder: (_) => GitlabIssueScreen(
item['target']['project_id'], item['target']['iid'],
isMr: item['target_type'] == 'MergeRequest'),
item.target.projectId, item.target.iid,
isMr: item.targetType == 'MergeRequest'),
child: Container(
padding: CommonStyle.padding,
child: Row(
children: <Widget>[
Avatar.medium(
url: item['author']['avatar_url'],
),
Avatar.medium(url: item.author.avatarUrl),
SizedBox(width: 12),
Expanded(
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: item['author']['name'],
text: item.author.name,
style: TextStyle(
color: theme.palette.primary,
fontWeight: FontWeight.w500,
@ -47,13 +47,13 @@ class GitlabTodosScreen extends StatelessWidget {
),
TextSpan(
text: ' ' +
item['action_name'] +
item.actionName +
' 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:git_touch/models/auth.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/widgets/border_view.dart';
import 'package:git_touch/widgets/repository_item.dart';
import 'package:git_touch/widgets/user_item.dart';
import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart';
class GitlabUserScreen extends StatelessWidget {
final String username;
@ -13,32 +15,35 @@ class GitlabUserScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RefreshStatefulScaffold(
return RefreshStatefulScaffold<
Tuple3<GitlabUser, Iterable<GitlabRepository>,
List<Map<String, double>>>>(
title: Text('User'),
fetchData: () async {
final items = await Provider.of<AuthModel>(context)
.fetchGitlab('/users?username=$username');
final user = items[0];
final projects = await Provider.of<AuthModel>(context)
.fetchGitlab('/users/${user['id']}/projects') as List;
final langs = await Future.wait(projects.map((p) =>
Provider.of<AuthModel>(context)
.fetchGitlab('/projects/${p['id']}/languages')));
for (var i = 0; i < projects.length; i++) {
projects[i]['language'] = langs[i];
}
return [user, projects];
final auth = Provider.of<AuthModel>(context);
final v0 = await auth.fetchGitlab('/users?username=$username');
final user = GitlabUser.fromJson(v0[0]);
final v1 = await auth.fetchGitlab('/users/${user.id}/projects');
final projects = (v1 as List).map((v) => GitlabRepository.fromJson(v));
final languages = await Future.wait(projects
.map((p) => auth.fetchGitlab('/projects/${p.id}/languages')));
return Tuple3(user, projects, languages.cast<Map<String, double>>());
},
bodyBuilder: (data, _) {
final user = data[0];
final projects = data[1] as List;
final user = data.item1;
final projects = data.item2;
final languages = data.item3;
return Column(
children: <Widget>[
UserItem(
login: user['username'],
avatarUrl: user['avatar_url'],
name: user['name'],
login: user.username,
avatarUrl: user.avatarUrl,
name: user.name,
),
BorderView(height: 10),
Column(

View File

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