refactor: generate model class from json
This commit is contained in:
parent
bd515cbbb6
commit
263913f60b
|
@ -0,0 +1,23 @@
|
|||
targets:
|
||||
$default:
|
||||
builders:
|
||||
json_serializable:
|
||||
options:
|
||||
# Options configure how source code is generated for every
|
||||
# `@JsonSerializable`-annotated class in the package.
|
||||
#
|
||||
# The default value for each is listed.
|
||||
#
|
||||
# For usage information, reference the corresponding field in
|
||||
# `JsonSerializableGenerator`.
|
||||
# any_map: false
|
||||
# checked: false
|
||||
# create_factory: true
|
||||
# create_to_json: true
|
||||
# disallow_unrecognized_keys: false
|
||||
# explicit_to_json: false
|
||||
field_rename: snake
|
||||
# generate_to_json_function: true
|
||||
# include_if_null: true
|
||||
# nullable: true
|
||||
# use_wrappers: false
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import '../common/event.dart';
|
||||
import '../components/event.dart';
|
||||
import '../utils.dart';
|
||||
import 'dart:async';
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import '../utils.dart';
|
||||
import '../models/event.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
|
@ -38,30 +39,92 @@ class EventItem extends StatelessWidget {
|
|||
final Event event;
|
||||
EventItem(this.event);
|
||||
|
||||
getEventItemByType() {
|
||||
Widget getEventItemByType(BuildContext context) {
|
||||
switch (event.type) {
|
||||
case 'IssuesEvent':
|
||||
return IssuesEvent(event);
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} issue '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(
|
||||
text: '#' + event.payload['issue']['number'].toString(),
|
||||
),
|
||||
TextSpan(
|
||||
text: event.payload['issue']['title'],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
case 'PushEvent':
|
||||
return PushEvent(event);
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' pushed to '),
|
||||
TextSpan(
|
||||
text: event.payload['ref'],
|
||||
style: TextStyle(color: CupertinoColors.activeBlue),
|
||||
),
|
||||
TextSpan(text: ' in '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(text: '')
|
||||
],
|
||||
),
|
||||
);
|
||||
case 'PullRequestEvent':
|
||||
return PullRequestEvent(event);
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} pull request '),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(text: '#' + event.payload['number'].toString()),
|
||||
TextSpan(text: event.payload['pull_request']['title'])
|
||||
],
|
||||
),
|
||||
);
|
||||
case 'WatchEvent':
|
||||
return WatchEvent(event);
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} '),
|
||||
_strong(event.repo.name),
|
||||
],
|
||||
),
|
||||
);
|
||||
default:
|
||||
return Text('Not implement yet');
|
||||
return Text(
|
||||
'Not implement yet',
|
||||
style: TextStyle(color: CupertinoColors.destructiveRed),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
// Padding(padding: EdgeInsets.only(top: 16.0)),
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
_Avatar(event.avatar),
|
||||
Expanded(child: getEventItemByType()),
|
||||
],
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 16.0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
|
||||
left: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
|
||||
right: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
|
||||
bottom: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
_Avatar(event.actor.avatarUrl),
|
||||
Expanded(child: getEventItemByType(context)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +142,7 @@ TextSpan _strong(String text, [GestureRecognizer recognizer]) {
|
|||
|
||||
TextSpan _user(Event event, context) {
|
||||
return _strong(
|
||||
event.actor,
|
||||
event.actor.login,
|
||||
// TapGestureRecognizer()
|
||||
// ..onTap = () {
|
||||
// Navigator.of(context).push(
|
||||
|
@ -93,31 +156,6 @@ TextSpan _user(Event event, context) {
|
|||
);
|
||||
}
|
||||
|
||||
class PushEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
PushEvent(this.event);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' pushed to '),
|
||||
TextSpan(
|
||||
text: event.payload['ref'],
|
||||
style: TextStyle(color: CupertinoColors.activeBlue),
|
||||
),
|
||||
TextSpan(text: ' in '),
|
||||
_strong(event.repo),
|
||||
TextSpan(text: '')
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class IssuesEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
IssuesEvent(this.event);
|
||||
|
@ -130,7 +168,7 @@ class IssuesEvent extends StatelessWidget {
|
|||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} issue '),
|
||||
_strong(event.repo),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(
|
||||
text: '#' + event.payload['issue']['number'].toString(),
|
||||
),
|
||||
|
@ -143,27 +181,6 @@ class IssuesEvent extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class PullRequestEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
PullRequestEvent(this.event);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} pull request '),
|
||||
_strong(event.repo),
|
||||
TextSpan(text: '#' + event.payload['number'].toString()),
|
||||
TextSpan(text: event.payload['pull_request']['title'])
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class IssueCommentEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
IssueCommentEvent(this.event);
|
||||
|
@ -176,7 +193,7 @@ class IssueCommentEvent extends StatelessWidget {
|
|||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' commented on issue '),
|
||||
_strong(event.repo),
|
||||
_strong(event.repo.name),
|
||||
TextSpan(text: '#' + event.payload['issue']['number'].toString()),
|
||||
TextSpan(text: event.payload['comment']['body'])
|
||||
],
|
||||
|
@ -184,22 +201,3 @@ class IssueCommentEvent extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WatchEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
WatchEvent(this.event);
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(color: CupertinoColors.black),
|
||||
children: [
|
||||
_user(event, context),
|
||||
TextSpan(text: ' ${event.payload['action']} '),
|
||||
_strong(event.repo),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,10 +2,12 @@
|
|||
// import 'dart:convert';
|
||||
import '../utils.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
// import 'package:graphql_flutter/graphql_flutter.dart';
|
||||
// import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../common/event.dart';
|
||||
import 'user.dart';
|
||||
import '../components/event.dart';
|
||||
// import 'user.dart';
|
||||
import '../models/event.dart';
|
||||
|
||||
class IosHomeTab extends StatefulWidget {
|
||||
@override
|
||||
|
@ -32,7 +34,7 @@ class IosHomeTabState extends State<IosHomeTab> {
|
|||
}
|
||||
|
||||
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
|
||||
GlobalKey<RefreshIndicatorState>();
|
||||
GlobalKey<RefreshIndicatorState>();
|
||||
|
||||
@override
|
||||
Widget build(context) {
|
||||
|
@ -60,7 +62,7 @@ class IosHomeTabState extends State<IosHomeTab> {
|
|||
try {
|
||||
return EventItem(events[index]);
|
||||
} catch (err) {
|
||||
return Text(err.toString());
|
||||
return Text(err.toString());
|
||||
// return null;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import '../models/user.dart';
|
||||
import '../utils.dart';
|
||||
|
||||
class IosUserPage extends StatelessWidget {
|
||||
|
@ -12,7 +13,7 @@ class IosUserPage extends StatelessWidget {
|
|||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
leading: CupertinoButton(
|
||||
child: Text('Cancel'),
|
||||
child: Text('Cancel'),
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(false);
|
||||
|
|
|
@ -1,9 +1,22 @@
|
|||
import 'package:flutter/material.dart';
|
||||
// import 'dart:io';
|
||||
// import 'package:graphql_flutter/graphql_flutter.dart';
|
||||
import 'android/main.dart';
|
||||
import 'ios/main.dart';
|
||||
// import 'token.dart';
|
||||
|
||||
class App extends StatelessWidget {
|
||||
final isIos = false;
|
||||
final isIos = true;
|
||||
|
||||
// final ValueNotifier<GraphQLClient> client = ValueNotifier(
|
||||
// GraphQLClient(
|
||||
// cache: InMemoryCache(),
|
||||
// link: HttpLink(
|
||||
// uri: 'https://api.github.com/graphql',
|
||||
// headers: {HttpHeaders.authorizationHeader: 'token $token'},
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
|
||||
@override
|
||||
build(context) {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'event.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class Actor {
|
||||
Actor(this.login, this.avatarUrl);
|
||||
|
||||
String login;
|
||||
String avatarUrl;
|
||||
|
||||
factory Actor.fromJson(Map<String, dynamic> json) => _$ActorFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$ActorToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class Repo {
|
||||
Repo(this.name);
|
||||
|
||||
String name;
|
||||
|
||||
factory Repo.fromJson(Map<String, dynamic> json) => _$RepoFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$RepoToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class Event {
|
||||
Event(this.id, this.type, this.actor, this.repo);
|
||||
|
||||
String id;
|
||||
String type;
|
||||
Actor actor;
|
||||
Repo repo;
|
||||
Map<String, dynamic> payload;
|
||||
|
||||
factory Event.fromJson(Map<String, dynamic> json) => _$EventFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$EventToJson(this);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'event.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Actor _$ActorFromJson(Map<String, dynamic> json) {
|
||||
return Actor(json['login'] as String, json['avatar_url'] as String);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ActorToJson(Actor instance) => <String, dynamic>{
|
||||
'login': instance.login,
|
||||
'avatar_url': instance.avatarUrl
|
||||
};
|
||||
|
||||
Repo _$RepoFromJson(Map<String, dynamic> json) {
|
||||
return Repo(json['name'] as String);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$RepoToJson(Repo instance) =>
|
||||
<String, dynamic>{'name': instance.name};
|
||||
|
||||
Event _$EventFromJson(Map<String, dynamic> json) {
|
||||
return Event(
|
||||
json['id'] as String,
|
||||
json['type'] as String,
|
||||
json['actor'] == null
|
||||
? null
|
||||
: Actor.fromJson(json['actor'] as Map<String, dynamic>),
|
||||
json['repo'] == null
|
||||
? null
|
||||
: Repo.fromJson(json['repo'] as Map<String, dynamic>))
|
||||
..payload = json['payload'] as Map<String, dynamic>;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$EventToJson(Event instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'type': instance.type,
|
||||
'actor': instance.actor,
|
||||
'repo': instance.repo,
|
||||
'payload': instance.payload
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
/// This allows the `User` class to access private members in
|
||||
/// the generated file. The value for this is *.g.dart, where
|
||||
/// the star denotes the source file name.
|
||||
part 'user.g.dart';
|
||||
|
||||
/// An annotation for the code generator to know that this class needs the
|
||||
/// JSON serialization logic to be generated.
|
||||
@JsonSerializable()
|
||||
class User {
|
||||
User(this.login, this.avatarUrl, this.name, this.publicRepos, this.followers,
|
||||
this.following);
|
||||
|
||||
String login;
|
||||
String avatarUrl;
|
||||
String name;
|
||||
int publicRepos;
|
||||
int followers;
|
||||
int following;
|
||||
|
||||
/// A necessary factory constructor for creating a new User instance
|
||||
/// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
|
||||
/// The constructor is named after the source class, in this case User.
|
||||
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
|
||||
|
||||
/// `toJson` is the convention for a class to declare support for serialization
|
||||
/// to JSON. The implementation simply calls the private, generated
|
||||
/// helper method `_$UserToJson`.
|
||||
Map<String, dynamic> toJson() => _$UserToJson(this);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'user.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
User _$UserFromJson(Map<String, dynamic> json) {
|
||||
return User(
|
||||
json['login'] as String,
|
||||
json['avatar_url'] as String,
|
||||
json['name'] as String,
|
||||
json['public_repos'] as int,
|
||||
json['followers'] as int,
|
||||
json['following'] as int);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
|
||||
'login': instance.login,
|
||||
'avatar_url': instance.avatarUrl,
|
||||
'name': instance.name,
|
||||
'public_repos': instance.publicRepos,
|
||||
'followers': instance.followers,
|
||||
'following': instance.following
|
||||
};
|
|
@ -3,50 +3,18 @@ import 'dart:async';
|
|||
import 'dart:io';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'token.dart';
|
||||
import 'models/event.dart';
|
||||
import 'models/user.dart';
|
||||
|
||||
final prefix = 'https://api.github.com';
|
||||
|
||||
class Event {
|
||||
String type;
|
||||
String actor;
|
||||
String id;
|
||||
String avatar;
|
||||
String repo;
|
||||
Map<String, dynamic> payload;
|
||||
|
||||
Event.fromJson(data) {
|
||||
id = data['id'];
|
||||
type = data['type'];
|
||||
actor = data['actor']['login'];
|
||||
avatar = data['actor']['avatar_url'];
|
||||
repo = data['repo']['name'];
|
||||
payload = data['payload'];
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
String login;
|
||||
String avatar;
|
||||
String name;
|
||||
int repos;
|
||||
int followers;
|
||||
int following;
|
||||
|
||||
User.fromJson(data) {
|
||||
login = data['login'];
|
||||
avatar = data['avatar_url'];
|
||||
name = data['name'];
|
||||
repos = data['public_repos'];
|
||||
followers = data['followers'];
|
||||
following = data['following'];
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Event>> fetchEvents([int page = 1]) async {
|
||||
final res = await http.get(
|
||||
prefix + '/users/pd4d10/received_events/public?page=$page',
|
||||
headers: {HttpHeaders.AUTHORIZATION: 'token $token'},
|
||||
headers: {HttpHeaders.authorizationHeader: 'token $token'},
|
||||
);
|
||||
|
||||
print(res.body);
|
||||
List<dynamic> data = json.decode(res.body);
|
||||
|
||||
return data.map((item) {
|
||||
|
@ -57,7 +25,7 @@ Future<List<Event>> fetchEvents([int page = 1]) async {
|
|||
Future<User> fetchUser(String login) async {
|
||||
final res = await http.get(
|
||||
prefix + '/users/$login',
|
||||
headers: {HttpHeaders.AUTHORIZATION: 'token $token'},
|
||||
headers: {HttpHeaders.authorizationHeader: 'token $token'},
|
||||
);
|
||||
Map<String, dynamic> data = json.decode(res.body);
|
||||
|
||||
|
|
|
@ -20,11 +20,15 @@ dependencies:
|
|||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^0.1.2
|
||||
http: ^0.11.3
|
||||
graphql_flutter: ^1.0.0-alpha
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
build_runner: ^1.1.3
|
||||
json_serializable: ^2.0.1
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||
|
||||
|
|
Loading…
Reference in New Issue