refactor: ferry

This commit is contained in:
Rongjian Zhang 2021-01-17 22:08:32 +08:00
parent 4f1e0441d2
commit e41d235cde
50 changed files with 315165 additions and 112615 deletions

View File

@ -1,36 +1,56 @@
targets:
$default:
builders:
json_serializable:
gql_build|ast_builder:
enabled: true
gql_build|schema_builder:
enabled: true
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
artemis:
schema: git_touch|lib/graphql/schema.graphql
type_overrides:
DateTime:
name: DateTime
URI:
name: String
GitObjectID:
name: String
gql_build|data_builder:
enabled: true
options:
schema_mapping:
- schema: lib/github.schema.json
output: lib/graphql/gh.dart
queries_glob: lib/graphql/gh_*.graphql
resolve_type_field: __typename
add_query_prefix: true
scalar_mapping:
- graphql_type: URI
dart_type: String
- graphql_type: GitObjectID
dart_type: String
schema: git_touch|lib/graphql/schema.graphql
type_overrides:
DateTime:
name: DateTime
URI:
name: String
GitObjectID:
name: String
gql_build|var_builder:
enabled: true
options:
schema: git_touch|lib/graphql/schema.graphql
type_overrides:
DateTime:
name: DateTime
URI:
name: String
GitObjectID:
name: String
gql_build|serializer_builder:
enabled: true
options:
schema: git_touch|lib/graphql/schema.graphql
custom_serializers:
- import: package:git_touch/utils/date_time_serializer.dart
name: DateTimeSerializer
ferry_generator|req_builder:
enabled: true
options:
schema: git_touch|lib/graphql/schema.graphql
type_overrides:
DateTime:
name: DateTime
URI:
name: String
GitObjectID:
name: String

View File

@ -1,7 +1,5 @@
PODS:
- Flutter (1.0.0)
- in_app_review (0.2.0):
- Flutter
- launch_review (0.0.1):
- Flutter
- package_info (0.0.1):
@ -19,7 +17,6 @@ PODS:
DEPENDENCIES:
- Flutter (from `Flutter`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- launch_review (from `.symlinks/plugins/launch_review/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- share (from `.symlinks/plugins/share/ios`)
@ -31,8 +28,6 @@ DEPENDENCIES:
EXTERNAL SOURCES:
Flutter:
:path: Flutter
in_app_review:
:path: ".symlinks/plugins/in_app_review/ios"
launch_review:
:path: ".symlinks/plugins/launch_review/ios"
package_info:
@ -50,7 +45,6 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
in_app_review: 4a97249f7a2f539a0f294c2d9196b7fe35e49541
launch_review: 75d5a956ba8eaa493e9c9d4bf4c05e505e8d5ed0
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
@ -61,4 +55,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
COCOAPODS: 1.10.0
COCOAPODS: 1.10.1

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,60 +0,0 @@
fragment T on Ref {
target {
__typename
... on Commit {
oid
url
messageHeadline
committedDate
author {
name
avatarUrl
user {
login
}
}
status {
state
}
history(first: 30, after: $after) {
pageInfo {
hasNextPage
endCursor
}
nodes {
oid
url
messageHeadline
committedDate
author {
name
avatarUrl
user {
login
}
}
status {
state
}
}
}
}
}
}
query GhCommits(
$owner: String!
$name: String!
$ref: String!
$hasRef: Boolean!
$after: String
) {
repository(owner: $owner, name: $name) {
defaultBranchRef @skip(if: $hasRef) {
...T
}
ref(qualifiedName: $ref) @include(if: $hasRef) {
...T
}
}
}

View File

@ -1,43 +0,0 @@
query GhIssues($owner: String!, $name: String!, $cursor: String) {
repository(owner: $owner, name: $name) {
owner {
login
}
name
issues(
states: OPEN
orderBy: { field: CREATED_AT, direction: DESC }
first: 30
after: $cursor
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
repository {
owner {
login
}
name
}
number
title
updatedAt
author {
login
avatarUrl
}
labels(first: 10) {
nodes {
name
color
}
}
comments {
totalCount
}
}
}
}
}

View File

@ -1,12 +0,0 @@
mutation GhOpenIssue($id: ID!, $open: Boolean!) {
reopenIssue(input: { issueId: $id }) @include(if: $open) {
issue {
closed
}
}
closeIssue(input: { issueId: $id }) @skip(if: $open) {
issue {
closed
}
}
}

View File

@ -1,43 +0,0 @@
query GhPulls($owner: String!, $name: String!, $cursor: String) {
repository(owner: $owner, name: $name) {
owner {
login
}
name
pullRequests(
states: OPEN
orderBy: { field: CREATED_AT, direction: DESC }
first: 30
after: $cursor
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
repository {
owner {
login
}
name
}
number
title
updatedAt
author {
login
avatarUrl
}
labels(first: 10) {
nodes {
name
color
}
}
comments {
totalCount
}
}
}
}
}

View File

@ -1,101 +0,0 @@
query GhRepo(
$owner: String!
$name: String!
$branchSpecified: Boolean!
$branch: String!
) {
repository(owner: $owner, name: $name) {
owner {
__typename
login
avatarUrl
}
name
description
homepageUrl
isPrivate
isFork
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
id
diskUsage
hasIssuesEnabled
url
viewerHasStarred
viewerSubscription
projectsUrl
watchers {
totalCount
}
issues(states: OPEN) {
totalCount
}
pullRequests(states: OPEN) {
totalCount
}
projects {
totalCount
}
releases {
totalCount
}
languages(first: 10, orderBy: { field: SIZE, direction: DESC }) {
totalSize
edges {
size
node {
name
color
}
}
}
defaultBranchRef @skip(if: $branchSpecified) {
name
target {
__typename
... on Commit {
history {
totalCount
}
}
}
}
ref(qualifiedName: $branch) @include(if: $branchSpecified) {
name
target {
__typename
... on Commit {
history {
totalCount
}
}
}
}
refs(first: 100, refPrefix: "refs/heads/") {
totalCount
nodes {
name
}
}
licenseInfo {
name
spdxId
}
repositoryTopics(first: 10) {
nodes {
url
topic {
name
}
}
}
}
}

View File

@ -1,70 +0,0 @@
query GhRepos($owner: String!, $after: String, $isStar: Boolean!) {
user(login: $owner) {
__typename
login
avatarUrl
repositories(
first: 30
after: $after
orderBy: { field: UPDATED_AT, direction: DESC }
) @skip(if: $isStar) {
totalCount # TODO:
pageInfo {
hasNextPage
endCursor
}
nodes {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
updatedAt
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
starredRepositories(
first: 30
after: $after
orderBy: { field: STARRED_AT, direction: DESC }
) @include(if: $isStar) {
pageInfo {
hasNextPage
endCursor
}
nodes {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
updatedAt
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
}
}

View File

@ -1,239 +0,0 @@
query GhUser($login: String!, $isViewer: Boolean!) {
repositoryOwner(login: $login) @skip(if: $isViewer) {
__typename
id
login
avatarUrl
url
... on User {
name
bio
company
location
email
createdAt
websiteUrl
starredRepositories {
totalCount
}
followers {
totalCount
}
following {
totalCount
}
contributionsCollection {
contributionCalendar {
weeks {
contributionDays {
color
}
}
}
}
repositories(
first: 6
ownerAffiliations: OWNER
orderBy: { field: STARGAZERS, direction: DESC }
) {
totalCount
nodes {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
pinnedItems(first: 6) {
totalCount # TODO: Add this for correct generated code
nodes {
__typename
... on Repository {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
}
viewerCanFollow
viewerIsFollowing
}
... on Organization {
name
description
location
email
websiteUrl
createdAt
pinnedItems(first: 6) {
nodes {
__typename
... on Repository {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
}
pinnableItems(first: 6, types: [REPOSITORY]) {
totalCount
nodes {
__typename
... on Repository {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
}
membersWithRole {
totalCount
}
}
}
viewer @include(if: $isViewer) {
id
login
avatarUrl
url
name
bio
company
location
email
createdAt
websiteUrl
starredRepositories {
totalCount
}
followers {
totalCount
}
following {
totalCount
}
contributionsCollection {
contributionCalendar {
weeks {
contributionDays {
color
}
}
}
}
repositories(
first: 6
ownerAffiliations: OWNER
orderBy: { field: STARGAZERS, direction: DESC }
) {
totalCount
nodes {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
pinnedItems(first: 6) {
totalCount # TODO: Add this for correct generated code
nodes {
__typename
... on Repository {
owner {
login
avatarUrl
}
name
description
isPrivate
isFork
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
}
}
}
viewerCanFollow
viewerIsFollowing
}
}

View File

@ -1,101 +0,0 @@
query GhUsers(
$login: String!
$repoName: String!
$after: String
$isFollowers: Boolean!
$isFollowing: Boolean!
$isMember: Boolean!
$isStar: Boolean!
$isWatch: Boolean!
) {
user(login: $login) @skip(if: $isMember) {
login
name
avatarUrl
company
location
createdAt
followers(first: 30, after: $after) @include(if: $isFollowers) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
company
location
createdAt
}
}
following(first: 30, after: $after) @include(if: $isFollowing) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
company
location
createdAt
}
}
}
organization(login: $login) @include(if: $isMember) {
login
name
avatarUrl
location
membersWithRole(first: 30, after: $after) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
company
location
createdAt
}
}
}
repository(owner: $login, name: $repoName) {
watchers(first: 30, after: $after) @include(if: $isWatch) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
company
location
createdAt
}
}
stargazers(
first: 30
after: $after
orderBy: { field: STARRED_AT, direction: DESC }
) @include(if: $isStar) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
company
location
createdAt
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1020
lib/graphql/github.graphql Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,939 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:git_touch/graphql/serializers.gql.dart' as _i1;
part 'github.var.gql.g.dart';
abstract class GFollowersVars
implements Built<GFollowersVars, GFollowersVarsBuilder> {
GFollowersVars._();
factory GFollowersVars([Function(GFollowersVarsBuilder b) updates]) =
_$GFollowersVars;
String get login;
@nullable
String get after;
static Serializer<GFollowersVars> get serializer =>
_$gFollowersVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GFollowersVars.serializer, this);
static GFollowersVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GFollowersVars.serializer, json);
}
abstract class GFollowingVars
implements Built<GFollowingVars, GFollowingVarsBuilder> {
GFollowingVars._();
factory GFollowingVars([Function(GFollowingVarsBuilder b) updates]) =
_$GFollowingVars;
String get login;
@nullable
String get after;
static Serializer<GFollowingVars> get serializer =>
_$gFollowingVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GFollowingVars.serializer, this);
static GFollowingVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GFollowingVars.serializer, json);
}
abstract class GMembersVars
implements Built<GMembersVars, GMembersVarsBuilder> {
GMembersVars._();
factory GMembersVars([Function(GMembersVarsBuilder b) updates]) =
_$GMembersVars;
String get login;
@nullable
String get after;
static Serializer<GMembersVars> get serializer => _$gMembersVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GMembersVars.serializer, this);
static GMembersVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GMembersVars.serializer, json);
}
abstract class GWatchersVars
implements Built<GWatchersVars, GWatchersVarsBuilder> {
GWatchersVars._();
factory GWatchersVars([Function(GWatchersVarsBuilder b) updates]) =
_$GWatchersVars;
String get owner;
String get name;
@nullable
String get after;
static Serializer<GWatchersVars> get serializer => _$gWatchersVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GWatchersVars.serializer, this);
static GWatchersVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GWatchersVars.serializer, json);
}
abstract class GStargazersVars
implements Built<GStargazersVars, GStargazersVarsBuilder> {
GStargazersVars._();
factory GStargazersVars([Function(GStargazersVarsBuilder b) updates]) =
_$GStargazersVars;
String get owner;
String get name;
@nullable
String get after;
static Serializer<GStargazersVars> get serializer =>
_$gStargazersVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GStargazersVars.serializer, this);
static GStargazersVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GStargazersVars.serializer, json);
}
abstract class GReposVars implements Built<GReposVars, GReposVarsBuilder> {
GReposVars._();
factory GReposVars([Function(GReposVarsBuilder b) updates]) = _$GReposVars;
String get login;
@nullable
String get after;
static Serializer<GReposVars> get serializer => _$gReposVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GReposVars.serializer, this);
static GReposVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GReposVars.serializer, json);
}
abstract class GStarsVars implements Built<GStarsVars, GStarsVarsBuilder> {
GStarsVars._();
factory GStarsVars([Function(GStarsVarsBuilder b) updates]) = _$GStarsVars;
String get login;
@nullable
String get after;
static Serializer<GStarsVars> get serializer => _$gStarsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GStarsVars.serializer, this);
static GStarsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GStarsVars.serializer, json);
}
abstract class GViewerVars implements Built<GViewerVars, GViewerVarsBuilder> {
GViewerVars._();
factory GViewerVars([Function(GViewerVarsBuilder b) updates]) = _$GViewerVars;
static Serializer<GViewerVars> get serializer => _$gViewerVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GViewerVars.serializer, this);
static GViewerVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GViewerVars.serializer, json);
}
abstract class GUserVars implements Built<GUserVars, GUserVarsBuilder> {
GUserVars._();
factory GUserVars([Function(GUserVarsBuilder b) updates]) = _$GUserVars;
String get login;
static Serializer<GUserVars> get serializer => _$gUserVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GUserVars.serializer, this);
static GUserVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GUserVars.serializer, json);
}
abstract class GRepoVars implements Built<GRepoVars, GRepoVarsBuilder> {
GRepoVars._();
factory GRepoVars([Function(GRepoVarsBuilder b) updates]) = _$GRepoVars;
String get owner;
String get name;
bool get branchSpecified;
String get branch;
static Serializer<GRepoVars> get serializer => _$gRepoVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GRepoVars.serializer, this);
static GRepoVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GRepoVars.serializer, json);
}
abstract class GCommitsVars
implements Built<GCommitsVars, GCommitsVarsBuilder> {
GCommitsVars._();
factory GCommitsVars([Function(GCommitsVarsBuilder b) updates]) =
_$GCommitsVars;
String get owner;
String get name;
String get ref;
bool get hasRef;
@nullable
String get after;
static Serializer<GCommitsVars> get serializer => _$gCommitsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GCommitsVars.serializer, this);
static GCommitsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GCommitsVars.serializer, json);
}
abstract class GIssuesVars implements Built<GIssuesVars, GIssuesVarsBuilder> {
GIssuesVars._();
factory GIssuesVars([Function(GIssuesVarsBuilder b) updates]) = _$GIssuesVars;
String get owner;
String get name;
@nullable
String get cursor;
static Serializer<GIssuesVars> get serializer => _$gIssuesVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GIssuesVars.serializer, this);
static GIssuesVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GIssuesVars.serializer, json);
}
abstract class GPullsVars implements Built<GPullsVars, GPullsVarsBuilder> {
GPullsVars._();
factory GPullsVars([Function(GPullsVarsBuilder b) updates]) = _$GPullsVars;
String get owner;
String get name;
@nullable
String get cursor;
static Serializer<GPullsVars> get serializer => _$gPullsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GPullsVars.serializer, this);
static GPullsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GPullsVars.serializer, json);
}
abstract class GIssueVars implements Built<GIssueVars, GIssueVarsBuilder> {
GIssueVars._();
factory GIssueVars([Function(GIssueVarsBuilder b) updates]) = _$GIssueVars;
String get owner;
String get name;
int get number;
@nullable
String get cursor;
static Serializer<GIssueVars> get serializer => _$gIssueVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GIssueVars.serializer, this);
static GIssueVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GIssueVars.serializer, json);
}
abstract class GPageInfoPartsVars
implements Built<GPageInfoPartsVars, GPageInfoPartsVarsBuilder> {
GPageInfoPartsVars._();
factory GPageInfoPartsVars([Function(GPageInfoPartsVarsBuilder b) updates]) =
_$GPageInfoPartsVars;
static Serializer<GPageInfoPartsVars> get serializer =>
_$gPageInfoPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GPageInfoPartsVars.serializer, this);
static GPageInfoPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GPageInfoPartsVars.serializer, json);
}
abstract class GRepoItemVars
implements Built<GRepoItemVars, GRepoItemVarsBuilder> {
GRepoItemVars._();
factory GRepoItemVars([Function(GRepoItemVarsBuilder b) updates]) =
_$GRepoItemVars;
static Serializer<GRepoItemVars> get serializer => _$gRepoItemVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GRepoItemVars.serializer, this);
static GRepoItemVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GRepoItemVars.serializer, json);
}
abstract class GUserItemVars
implements Built<GUserItemVars, GUserItemVarsBuilder> {
GUserItemVars._();
factory GUserItemVars([Function(GUserItemVarsBuilder b) updates]) =
_$GUserItemVars;
static Serializer<GUserItemVars> get serializer => _$gUserItemVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GUserItemVars.serializer, this);
static GUserItemVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GUserItemVars.serializer, json);
}
abstract class GReposRepoItemVars
implements Built<GReposRepoItemVars, GReposRepoItemVarsBuilder> {
GReposRepoItemVars._();
factory GReposRepoItemVars([Function(GReposRepoItemVarsBuilder b) updates]) =
_$GReposRepoItemVars;
static Serializer<GReposRepoItemVars> get serializer =>
_$gReposRepoItemVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GReposRepoItemVars.serializer, this);
static GReposRepoItemVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GReposRepoItemVars.serializer, json);
}
abstract class GUserPartsVars
implements Built<GUserPartsVars, GUserPartsVarsBuilder> {
GUserPartsVars._();
factory GUserPartsVars([Function(GUserPartsVarsBuilder b) updates]) =
_$GUserPartsVars;
static Serializer<GUserPartsVars> get serializer =>
_$gUserPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GUserPartsVars.serializer, this);
static GUserPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GUserPartsVars.serializer, json);
}
abstract class GRepoCommitVars
implements Built<GRepoCommitVars, GRepoCommitVarsBuilder> {
GRepoCommitVars._();
factory GRepoCommitVars([Function(GRepoCommitVarsBuilder b) updates]) =
_$GRepoCommitVars;
static Serializer<GRepoCommitVars> get serializer =>
_$gRepoCommitVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GRepoCommitVars.serializer, this);
static GRepoCommitVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GRepoCommitVars.serializer, json);
}
abstract class GRepoRefVars
implements Built<GRepoRefVars, GRepoRefVarsBuilder> {
GRepoRefVars._();
factory GRepoRefVars([Function(GRepoRefVarsBuilder b) updates]) =
_$GRepoRefVars;
static Serializer<GRepoRefVars> get serializer => _$gRepoRefVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GRepoRefVars.serializer, this);
static GRepoRefVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GRepoRefVars.serializer, json);
}
abstract class GCommitsRefCommitVars
implements Built<GCommitsRefCommitVars, GCommitsRefCommitVarsBuilder> {
GCommitsRefCommitVars._();
factory GCommitsRefCommitVars(
[Function(GCommitsRefCommitVarsBuilder b) updates]) =
_$GCommitsRefCommitVars;
@nullable
String get after;
static Serializer<GCommitsRefCommitVars> get serializer =>
_$gCommitsRefCommitVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GCommitsRefCommitVars.serializer, this);
static GCommitsRefCommitVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GCommitsRefCommitVars.serializer, json);
}
abstract class GCommitsRefVars
implements Built<GCommitsRefVars, GCommitsRefVarsBuilder> {
GCommitsRefVars._();
factory GCommitsRefVars([Function(GCommitsRefVarsBuilder b) updates]) =
_$GCommitsRefVars;
@nullable
String get after;
static Serializer<GCommitsRefVars> get serializer =>
_$gCommitsRefVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GCommitsRefVars.serializer, this);
static GCommitsRefVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GCommitsRefVars.serializer, json);
}
abstract class GCommentPartsVars
implements Built<GCommentPartsVars, GCommentPartsVarsBuilder> {
GCommentPartsVars._();
factory GCommentPartsVars([Function(GCommentPartsVarsBuilder b) updates]) =
_$GCommentPartsVars;
static Serializer<GCommentPartsVars> get serializer =>
_$gCommentPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GCommentPartsVars.serializer, this);
static GCommentPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GCommentPartsVars.serializer, json);
}
abstract class GReactablePartsVars
implements Built<GReactablePartsVars, GReactablePartsVarsBuilder> {
GReactablePartsVars._();
factory GReactablePartsVars(
[Function(GReactablePartsVarsBuilder b) updates]) = _$GReactablePartsVars;
static Serializer<GReactablePartsVars> get serializer =>
_$gReactablePartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GReactablePartsVars.serializer, this);
static GReactablePartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GReactablePartsVars.serializer, json);
}
abstract class GReferencedEventPartsVars
implements
Built<GReferencedEventPartsVars, GReferencedEventPartsVarsBuilder> {
GReferencedEventPartsVars._();
factory GReferencedEventPartsVars(
[Function(GReferencedEventPartsVarsBuilder b) updates]) =
_$GReferencedEventPartsVars;
static Serializer<GReferencedEventPartsVars> get serializer =>
_$gReferencedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GReferencedEventPartsVars.serializer, this);
static GReferencedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GReferencedEventPartsVars.serializer, json);
}
abstract class GRenamedTitleEventPartsVars
implements
Built<GRenamedTitleEventPartsVars, GRenamedTitleEventPartsVarsBuilder> {
GRenamedTitleEventPartsVars._();
factory GRenamedTitleEventPartsVars(
[Function(GRenamedTitleEventPartsVarsBuilder b) updates]) =
_$GRenamedTitleEventPartsVars;
static Serializer<GRenamedTitleEventPartsVars> get serializer =>
_$gRenamedTitleEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GRenamedTitleEventPartsVars.serializer, this);
static GRenamedTitleEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GRenamedTitleEventPartsVars.serializer, json);
}
abstract class GClosedEventPartsVars
implements Built<GClosedEventPartsVars, GClosedEventPartsVarsBuilder> {
GClosedEventPartsVars._();
factory GClosedEventPartsVars(
[Function(GClosedEventPartsVarsBuilder b) updates]) =
_$GClosedEventPartsVars;
static Serializer<GClosedEventPartsVars> get serializer =>
_$gClosedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GClosedEventPartsVars.serializer, this);
static GClosedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GClosedEventPartsVars.serializer, json);
}
abstract class GReopenedEventPartsVars
implements Built<GReopenedEventPartsVars, GReopenedEventPartsVarsBuilder> {
GReopenedEventPartsVars._();
factory GReopenedEventPartsVars(
[Function(GReopenedEventPartsVarsBuilder b) updates]) =
_$GReopenedEventPartsVars;
static Serializer<GReopenedEventPartsVars> get serializer =>
_$gReopenedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GReopenedEventPartsVars.serializer, this);
static GReopenedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GReopenedEventPartsVars.serializer, json);
}
abstract class GCrossReferencedEventPartsVars
implements
Built<GCrossReferencedEventPartsVars,
GCrossReferencedEventPartsVarsBuilder> {
GCrossReferencedEventPartsVars._();
factory GCrossReferencedEventPartsVars(
[Function(GCrossReferencedEventPartsVarsBuilder b) updates]) =
_$GCrossReferencedEventPartsVars;
static Serializer<GCrossReferencedEventPartsVars> get serializer =>
_$gCrossReferencedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GCrossReferencedEventPartsVars.serializer, this);
static GCrossReferencedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GCrossReferencedEventPartsVars.serializer, json);
}
abstract class GLabeledEventPartsVars
implements Built<GLabeledEventPartsVars, GLabeledEventPartsVarsBuilder> {
GLabeledEventPartsVars._();
factory GLabeledEventPartsVars(
[Function(GLabeledEventPartsVarsBuilder b) updates]) =
_$GLabeledEventPartsVars;
static Serializer<GLabeledEventPartsVars> get serializer =>
_$gLabeledEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GLabeledEventPartsVars.serializer, this);
static GLabeledEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GLabeledEventPartsVars.serializer, json);
}
abstract class GUnlabeledEventPartsVars
implements
Built<GUnlabeledEventPartsVars, GUnlabeledEventPartsVarsBuilder> {
GUnlabeledEventPartsVars._();
factory GUnlabeledEventPartsVars(
[Function(GUnlabeledEventPartsVarsBuilder b) updates]) =
_$GUnlabeledEventPartsVars;
static Serializer<GUnlabeledEventPartsVars> get serializer =>
_$gUnlabeledEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GUnlabeledEventPartsVars.serializer, this);
static GUnlabeledEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GUnlabeledEventPartsVars.serializer, json);
}
abstract class GMilestonedEventPartsVars
implements
Built<GMilestonedEventPartsVars, GMilestonedEventPartsVarsBuilder> {
GMilestonedEventPartsVars._();
factory GMilestonedEventPartsVars(
[Function(GMilestonedEventPartsVarsBuilder b) updates]) =
_$GMilestonedEventPartsVars;
static Serializer<GMilestonedEventPartsVars> get serializer =>
_$gMilestonedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GMilestonedEventPartsVars.serializer, this);
static GMilestonedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GMilestonedEventPartsVars.serializer, json);
}
abstract class GDemilestonedEventPartsVars
implements
Built<GDemilestonedEventPartsVars, GDemilestonedEventPartsVarsBuilder> {
GDemilestonedEventPartsVars._();
factory GDemilestonedEventPartsVars(
[Function(GDemilestonedEventPartsVarsBuilder b) updates]) =
_$GDemilestonedEventPartsVars;
static Serializer<GDemilestonedEventPartsVars> get serializer =>
_$gDemilestonedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GDemilestonedEventPartsVars.serializer, this);
static GDemilestonedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GDemilestonedEventPartsVars.serializer, json);
}
abstract class GLockedEventPartsVars
implements Built<GLockedEventPartsVars, GLockedEventPartsVarsBuilder> {
GLockedEventPartsVars._();
factory GLockedEventPartsVars(
[Function(GLockedEventPartsVarsBuilder b) updates]) =
_$GLockedEventPartsVars;
static Serializer<GLockedEventPartsVars> get serializer =>
_$gLockedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GLockedEventPartsVars.serializer, this);
static GLockedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GLockedEventPartsVars.serializer, json);
}
abstract class GUnlockedEventPartsVars
implements Built<GUnlockedEventPartsVars, GUnlockedEventPartsVarsBuilder> {
GUnlockedEventPartsVars._();
factory GUnlockedEventPartsVars(
[Function(GUnlockedEventPartsVarsBuilder b) updates]) =
_$GUnlockedEventPartsVars;
static Serializer<GUnlockedEventPartsVars> get serializer =>
_$gUnlockedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GUnlockedEventPartsVars.serializer, this);
static GUnlockedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GUnlockedEventPartsVars.serializer, json);
}
abstract class GAssignedEventPartsVars
implements Built<GAssignedEventPartsVars, GAssignedEventPartsVarsBuilder> {
GAssignedEventPartsVars._();
factory GAssignedEventPartsVars(
[Function(GAssignedEventPartsVarsBuilder b) updates]) =
_$GAssignedEventPartsVars;
static Serializer<GAssignedEventPartsVars> get serializer =>
_$gAssignedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GAssignedEventPartsVars.serializer, this);
static GAssignedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GAssignedEventPartsVars.serializer, json);
}
abstract class GUnassignedEventPartsVars
implements
Built<GUnassignedEventPartsVars, GUnassignedEventPartsVarsBuilder> {
GUnassignedEventPartsVars._();
factory GUnassignedEventPartsVars(
[Function(GUnassignedEventPartsVarsBuilder b) updates]) =
_$GUnassignedEventPartsVars;
static Serializer<GUnassignedEventPartsVars> get serializer =>
_$gUnassignedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GUnassignedEventPartsVars.serializer, this);
static GUnassignedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GUnassignedEventPartsVars.serializer, json);
}
abstract class GSubscribedEventPartsVars
implements
Built<GSubscribedEventPartsVars, GSubscribedEventPartsVarsBuilder> {
GSubscribedEventPartsVars._();
factory GSubscribedEventPartsVars(
[Function(GSubscribedEventPartsVarsBuilder b) updates]) =
_$GSubscribedEventPartsVars;
static Serializer<GSubscribedEventPartsVars> get serializer =>
_$gSubscribedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GSubscribedEventPartsVars.serializer, this);
static GSubscribedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GSubscribedEventPartsVars.serializer, json);
}
abstract class GUnsubscribedEventPartsVars
implements
Built<GUnsubscribedEventPartsVars, GUnsubscribedEventPartsVarsBuilder> {
GUnsubscribedEventPartsVars._();
factory GUnsubscribedEventPartsVars(
[Function(GUnsubscribedEventPartsVarsBuilder b) updates]) =
_$GUnsubscribedEventPartsVars;
static Serializer<GUnsubscribedEventPartsVars> get serializer =>
_$gUnsubscribedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GUnsubscribedEventPartsVars.serializer, this);
static GUnsubscribedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GUnsubscribedEventPartsVars.serializer, json);
}
abstract class GMentionedEventPartsVars
implements
Built<GMentionedEventPartsVars, GMentionedEventPartsVarsBuilder> {
GMentionedEventPartsVars._();
factory GMentionedEventPartsVars(
[Function(GMentionedEventPartsVarsBuilder b) updates]) =
_$GMentionedEventPartsVars;
static Serializer<GMentionedEventPartsVars> get serializer =>
_$gMentionedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GMentionedEventPartsVars.serializer, this);
static GMentionedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GMentionedEventPartsVars.serializer, json);
}
abstract class GPinnedEventPartsVars
implements Built<GPinnedEventPartsVars, GPinnedEventPartsVarsBuilder> {
GPinnedEventPartsVars._();
factory GPinnedEventPartsVars(
[Function(GPinnedEventPartsVarsBuilder b) updates]) =
_$GPinnedEventPartsVars;
static Serializer<GPinnedEventPartsVars> get serializer =>
_$gPinnedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GPinnedEventPartsVars.serializer, this);
static GPinnedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GPinnedEventPartsVars.serializer, json);
}
abstract class GTransferredEventPartsVars
implements
Built<GTransferredEventPartsVars, GTransferredEventPartsVarsBuilder> {
GTransferredEventPartsVars._();
factory GTransferredEventPartsVars(
[Function(GTransferredEventPartsVarsBuilder b) updates]) =
_$GTransferredEventPartsVars;
static Serializer<GTransferredEventPartsVars> get serializer =>
_$gTransferredEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GTransferredEventPartsVars.serializer, this);
static GTransferredEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GTransferredEventPartsVars.serializer, json);
}
abstract class GPullRequestCommitPartsVars
implements
Built<GPullRequestCommitPartsVars, GPullRequestCommitPartsVarsBuilder> {
GPullRequestCommitPartsVars._();
factory GPullRequestCommitPartsVars(
[Function(GPullRequestCommitPartsVarsBuilder b) updates]) =
_$GPullRequestCommitPartsVars;
static Serializer<GPullRequestCommitPartsVars> get serializer =>
_$gPullRequestCommitPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GPullRequestCommitPartsVars.serializer, this);
static GPullRequestCommitPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GPullRequestCommitPartsVars.serializer, json);
}
abstract class GDeployedEventPartsVars
implements Built<GDeployedEventPartsVars, GDeployedEventPartsVarsBuilder> {
GDeployedEventPartsVars._();
factory GDeployedEventPartsVars(
[Function(GDeployedEventPartsVarsBuilder b) updates]) =
_$GDeployedEventPartsVars;
static Serializer<GDeployedEventPartsVars> get serializer =>
_$gDeployedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GDeployedEventPartsVars.serializer, this);
static GDeployedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GDeployedEventPartsVars.serializer, json);
}
abstract class GDeploymentEnvironmentChangedEventPartsVars
implements
Built<GDeploymentEnvironmentChangedEventPartsVars,
GDeploymentEnvironmentChangedEventPartsVarsBuilder> {
GDeploymentEnvironmentChangedEventPartsVars._();
factory GDeploymentEnvironmentChangedEventPartsVars(
[Function(GDeploymentEnvironmentChangedEventPartsVarsBuilder b)
updates]) = _$GDeploymentEnvironmentChangedEventPartsVars;
static Serializer<GDeploymentEnvironmentChangedEventPartsVars>
get serializer => _$gDeploymentEnvironmentChangedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers.serializeWith(
GDeploymentEnvironmentChangedEventPartsVars.serializer, this);
static GDeploymentEnvironmentChangedEventPartsVars fromJson(
Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(
GDeploymentEnvironmentChangedEventPartsVars.serializer, json);
}
abstract class GHeadRefRestoredEventPartsVars
implements
Built<GHeadRefRestoredEventPartsVars,
GHeadRefRestoredEventPartsVarsBuilder> {
GHeadRefRestoredEventPartsVars._();
factory GHeadRefRestoredEventPartsVars(
[Function(GHeadRefRestoredEventPartsVarsBuilder b) updates]) =
_$GHeadRefRestoredEventPartsVars;
static Serializer<GHeadRefRestoredEventPartsVars> get serializer =>
_$gHeadRefRestoredEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GHeadRefRestoredEventPartsVars.serializer, this);
static GHeadRefRestoredEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GHeadRefRestoredEventPartsVars.serializer, json);
}
abstract class GBaseRefForcePushedEventPartsVars
implements
Built<GBaseRefForcePushedEventPartsVars,
GBaseRefForcePushedEventPartsVarsBuilder> {
GBaseRefForcePushedEventPartsVars._();
factory GBaseRefForcePushedEventPartsVars(
[Function(GBaseRefForcePushedEventPartsVarsBuilder b) updates]) =
_$GBaseRefForcePushedEventPartsVars;
static Serializer<GBaseRefForcePushedEventPartsVars> get serializer =>
_$gBaseRefForcePushedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GBaseRefForcePushedEventPartsVars.serializer, this);
static GBaseRefForcePushedEventPartsVars fromJson(
Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GBaseRefForcePushedEventPartsVars.serializer, json);
}
abstract class GHeadRefForcePushedEventPartsVars
implements
Built<GHeadRefForcePushedEventPartsVars,
GHeadRefForcePushedEventPartsVarsBuilder> {
GHeadRefForcePushedEventPartsVars._();
factory GHeadRefForcePushedEventPartsVars(
[Function(GHeadRefForcePushedEventPartsVarsBuilder b) updates]) =
_$GHeadRefForcePushedEventPartsVars;
static Serializer<GHeadRefForcePushedEventPartsVars> get serializer =>
_$gHeadRefForcePushedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GHeadRefForcePushedEventPartsVars.serializer, this);
static GHeadRefForcePushedEventPartsVars fromJson(
Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GHeadRefForcePushedEventPartsVars.serializer, json);
}
abstract class GReviewRequestedEventPartsVars
implements
Built<GReviewRequestedEventPartsVars,
GReviewRequestedEventPartsVarsBuilder> {
GReviewRequestedEventPartsVars._();
factory GReviewRequestedEventPartsVars(
[Function(GReviewRequestedEventPartsVarsBuilder b) updates]) =
_$GReviewRequestedEventPartsVars;
static Serializer<GReviewRequestedEventPartsVars> get serializer =>
_$gReviewRequestedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GReviewRequestedEventPartsVars.serializer, this);
static GReviewRequestedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GReviewRequestedEventPartsVars.serializer, json);
}
abstract class GReviewRequestRemovedEventPartsVars
implements
Built<GReviewRequestRemovedEventPartsVars,
GReviewRequestRemovedEventPartsVarsBuilder> {
GReviewRequestRemovedEventPartsVars._();
factory GReviewRequestRemovedEventPartsVars(
[Function(GReviewRequestRemovedEventPartsVarsBuilder b) updates]) =
_$GReviewRequestRemovedEventPartsVars;
static Serializer<GReviewRequestRemovedEventPartsVars> get serializer =>
_$gReviewRequestRemovedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GReviewRequestRemovedEventPartsVars.serializer, this);
static GReviewRequestRemovedEventPartsVars fromJson(
Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(
GReviewRequestRemovedEventPartsVars.serializer, json);
}
abstract class GReviewDismissedEventPartsVars
implements
Built<GReviewDismissedEventPartsVars,
GReviewDismissedEventPartsVarsBuilder> {
GReviewDismissedEventPartsVars._();
factory GReviewDismissedEventPartsVars(
[Function(GReviewDismissedEventPartsVarsBuilder b) updates]) =
_$GReviewDismissedEventPartsVars;
static Serializer<GReviewDismissedEventPartsVars> get serializer =>
_$gReviewDismissedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GReviewDismissedEventPartsVars.serializer, this);
static GReviewDismissedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GReviewDismissedEventPartsVars.serializer, json);
}
abstract class GPullRequestReviewPartsVars
implements
Built<GPullRequestReviewPartsVars, GPullRequestReviewPartsVarsBuilder> {
GPullRequestReviewPartsVars._();
factory GPullRequestReviewPartsVars(
[Function(GPullRequestReviewPartsVarsBuilder b) updates]) =
_$GPullRequestReviewPartsVars;
static Serializer<GPullRequestReviewPartsVars> get serializer =>
_$gPullRequestReviewPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GPullRequestReviewPartsVars.serializer, this);
static GPullRequestReviewPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GPullRequestReviewPartsVars.serializer, json);
}
abstract class GMergedEventPartsVars
implements Built<GMergedEventPartsVars, GMergedEventPartsVarsBuilder> {
GMergedEventPartsVars._();
factory GMergedEventPartsVars(
[Function(GMergedEventPartsVarsBuilder b) updates]) =
_$GMergedEventPartsVars;
static Serializer<GMergedEventPartsVars> get serializer =>
_$gMergedEventPartsVarsSerializer;
Map<String, dynamic> toJson() =>
_i1.serializers.serializeWith(GMergedEventPartsVars.serializer, this);
static GMergedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers.deserializeWith(GMergedEventPartsVars.serializer, json);
}
abstract class GHeadRefDeletedEventPartsVars
implements
Built<GHeadRefDeletedEventPartsVars,
GHeadRefDeletedEventPartsVarsBuilder> {
GHeadRefDeletedEventPartsVars._();
factory GHeadRefDeletedEventPartsVars(
[Function(GHeadRefDeletedEventPartsVarsBuilder b) updates]) =
_$GHeadRefDeletedEventPartsVars;
static Serializer<GHeadRefDeletedEventPartsVars> get serializer =>
_$gHeadRefDeletedEventPartsVarsSerializer;
Map<String, dynamic> toJson() => _i1.serializers
.serializeWith(GHeadRefDeletedEventPartsVars.serializer, this);
static GHeadRefDeletedEventPartsVars fromJson(Map<String, dynamic> json) =>
_i1.serializers
.deserializeWith(GHeadRefDeletedEventPartsVars.serializer, json);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

38155
lib/graphql/schema.graphql Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -41,9 +41,9 @@ class _HomeState extends State<Home> {
_buildScreen(int index) {
// return GlProjectScreen(32221);
// return IssuesScreen('flutter', 'flutter', isPullRequest: true);
// return IssueScreen('reactjs', 'rfcs', 29);
// return IssueScreen('reactjs', 'rfcs', 68, isPullRequest: true);
// return GhIssuesScreen('flutter', 'flutter', isPullRequest: true);
// return GhIssueScreen('reactjs', 'rfcs', 29);
// return GhIssueScreen('reactjs', 'rfcs', 68);
// return Image.asset('images/spinner.webp', width: 32, height: 32);
// return GhRepoScreen('shreyas1599', 'test');
final auth = Provider.of<AuthModel>(context);
@ -59,7 +59,7 @@ class _HomeState extends State<Home> {
case 3:
return GhSearchScreen();
case 4:
return GhUserScreen(null);
return GhViewer();
}
break;
case PlatformType.gitlab:

View File

@ -1,14 +1,14 @@
import 'dart:convert';
import 'dart:async';
import 'package:ferry/ferry.dart';
import 'package:git_touch/utils/nil_store.dart';
// import 'package:in_app_review/in_app_review.dart';
import 'package:universal_io/io.dart';
import 'package:git_touch/models/bitbucket.dart';
import 'package:git_touch/models/gitea.dart';
import 'package:git_touch/models/gitee.dart';
import 'package:git_touch/utils/request_serilizer.dart';
import 'package:github/github.dart';
import 'package:gql_http_link/gql_http_link.dart';
import 'package:artemis/artemis.dart';
import 'package:fimber/fimber.dart';
import 'package:http/http.dart' as http;
import 'package:uni_links/uni_links.dart';
@ -683,17 +683,17 @@ class AuthModel with ChangeNotifier {
return _ghClient;
}
ArtemisClient _gqlClient;
ArtemisClient get gqlClient {
Client _gqlClient;
Client get gqlClient {
if (token == null) return null;
if (_gqlClient == null) {
_gqlClient = ArtemisClient.fromLink(
HttpLink(
_gqlClient = Client(
link: HttpLink(
_apiPrefix + '/graphql',
defaultHeaders: {HttpHeaders.authorizationHeader: 'token $token'},
serializer: GithubRequestSerializer(),
),
cache: Cache(store: NilStore()),
);
}

View File

@ -129,15 +129,15 @@ class GithubRouter {
final tab = parameters['tab']?.first;
switch (tab) {
case 'followers':
return GhUsersScreen(login, UsersScreenType.follower);
return GhFollowers(login);
case 'following':
return GhUsersScreen(login, UsersScreenType.following);
return GhFollowing(login);
case 'people':
return GhUsersScreen(login, UsersScreenType.member);
return GhMembers(login);
case 'stars':
return GhReposScreen.stars(login);
return GhStars(login);
case 'repositories':
return GhReposScreen(login);
return GhRepos(login);
case 'orgrepo':
return GhOrgReposScreen(login);
case 'organizations':
@ -147,7 +147,7 @@ class GithubRouter {
case 'events':
return GhEventsScreen(login);
default:
return GhUserScreen(login);
return GhUser(login);
}
});
static final repo = RouterScreen('/:owner/:name', (context, parameters) {
@ -193,8 +193,7 @@ class GithubRouter {
static final pull = RouterScreen(
'/:owner/:name/pull/:number',
(context, parameters) => GhIssueScreen(parameters['owner'].first,
parameters['name'].first, int.parse(parameters['number'].first),
isPullRequest: true));
parameters['name'].first, int.parse(parameters['number'].first)));
static final files = RouterScreen(
'/:owner/:name/pull/:number/files',
(context, parameters) => GhFilesScreen(
@ -212,7 +211,7 @@ class GithubRouter {
static final commits = RouterScreen(
'/:owner/:name/commits',
(context, parameters) =>
GhCommitsScreen(parameters['owner'].first, parameters['name'].first));
GhCommits(parameters['owner'].first, parameters['name'].first));
static final object =
RouterScreen('/:owner/:name/blob/:ref', (context, parameters) {
return GhObjectScreen(
@ -225,13 +224,11 @@ class GithubRouter {
});
static final stargazers =
RouterScreen('/:owner/:name/stargazers', (context, parameters) {
return GhUsersScreen(parameters['owner'].first, UsersScreenType.star,
repoName: parameters['name'].first);
return GhStargazers(parameters['owner'].first, parameters['name'].first);
});
static final watchers =
RouterScreen('/:owner/:name/watchers', (context, parameters) {
return GhUsersScreen(parameters['owner'].first, UsersScreenType.watch,
repoName: parameters['name'].first);
return GhWachers(parameters['owner'].first, parameters['name'].first);
});
static final contributors =
RouterScreen('/:owner/:name/contributors', (context, parameters) {

View File

@ -11,7 +11,7 @@ import '../widgets/empty.dart';
class ListPayload<T, K> {
K cursor;
List<T> items;
Iterable<T> items;
bool hasMore;
ListPayload({
@ -95,8 +95,8 @@ class _ListStatefulScaffoldState<T, K>
}
});
try {
var _payload = await widget.fetch(null);
items = _payload.items;
final _payload = await widget.fetch(null);
items = _payload.items.toList();
cursor = _payload.cursor;
hasMore = _payload.hasMore;
} catch (err) {

View File

@ -30,10 +30,9 @@ class LongListPayload<T, K> {
// e.g. https://github.com/reactjs/rfcs/pull/68
class LongListStatefulScaffold<T, K> extends StatefulWidget {
final Widget title;
final Widget Function(
T headerPayload, void Function(VoidCallback fn) setState) trailingBuilder;
final Widget Function(T headerPayload) headerBuilder;
final Widget Function(K itemPayload) itemBuilder;
final Widget Function(T t) trailingBuilder;
final Widget Function(T t) headerBuilder;
final Widget Function(K k) itemBuilder;
final Future<LongListPayload<T, K>> Function() onRefresh;
final Future<LongListPayload<T, K>> Function(String cursor) onLoadMore;
@ -194,9 +193,8 @@ class _LongListStatefulScaffoldState<T, K>
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: widget.title,
trailing: payload == null
? null
: widget.trailingBuilder(payload.header, setState),
trailing:
payload == null ? null : widget.trailingBuilder(payload.header),
),
child: SafeArea(
child: CupertinoScrollbar(
@ -210,7 +208,7 @@ class _LongListStatefulScaffoldState<T, K>
title: widget.title,
actions: payload == null
? null
: [widget.trailingBuilder(payload.header, setState)],
: [widget.trailingBuilder(payload.header)],
),
body: RefreshIndicator(
onRefresh: _refresh,

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.dart';
import 'package:git_touch/graphql/schema.schema.gql.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/utils/utils.dart';
@ -8,18 +10,18 @@ import 'package:git_touch/widgets/commit_item.dart';
import 'package:provider/provider.dart';
import '../generated/l10n.dart';
class GhCommitsScreen extends StatelessWidget {
class GhCommits extends StatelessWidget {
final String owner;
final String name;
final String branch;
GhCommitsScreen(this.owner, this.name, {this.branch});
GhCommits(this.owner, this.name, {this.branch});
Widget _buildStatus(GhCommitsStatusState state) {
Widget _buildStatus(GStatusState state) {
const size = 18.0;
switch (state) {
case GhCommitsStatusState.SUCCESS:
case GStatusState.SUCCESS:
return Icon(Octicons.check, color: GithubPalette.open, size: size);
case GhCommitsStatusState.FAILURE:
case GStatusState.FAILURE:
return Icon(Octicons.x, color: GithubPalette.closed, size: size);
default:
return Container();
@ -28,40 +30,41 @@ class GhCommitsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GhCommitsCommit, String>(
return ListStatefulScaffold<GCommitsRefCommit_history_nodes, String>(
title: AppBarTitle(S.of(context).commits),
fetch: (cursor) async {
final res = await context.read<AuthModel>().gqlClient.execute(
GhCommitsQuery(
variables: GhCommitsArguments(
owner: owner,
name: name,
hasRef: branch != null,
ref: branch ?? '',
after: cursor)));
final req = GCommitsReq((b) {
b.vars.owner = owner;
b.vars.name = name;
b.vars.hasRef = branch != null;
b.vars.ref = branch ?? '';
b.vars.after = cursor;
});
final res =
await context.read<AuthModel>().gqlClient.request(req).first;
final ref =
res.data.repository.defaultBranchRef ?? res.data.repository.ref;
final history = (ref.target as GhCommitsCommit).history;
final history = (ref.target as GCommitsRefCommit).history;
return ListPayload(
cursor: history.pageInfo.endCursor,
hasMore: history.pageInfo.hasNextPage,
items: history.nodes,
);
},
itemBuilder: (payload) {
final login = payload.author?.user?.login;
itemBuilder: (p) {
final login = p.author?.user?.login;
return CommitItem(
url: payload.url,
avatarUrl: payload.author?.avatarUrl,
url: p.url,
avatarUrl: p.author?.avatarUrl,
avatarLink: login == null ? null : '/github/$login',
message: payload.messageHeadline,
author: login ?? payload.author.name,
createdAt: payload.committedDate,
widgets: payload.status == null
message: p.messageHeadline,
author: login ?? p.author.name,
createdAt: p.committedDate,
widgets: p.status == null
? null
: [
SizedBox(width: 4),
_buildStatus(payload.status.state),
_buildStatus(p.status.state),
],
);
},

View File

@ -1,664 +1,249 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/action_button.dart';
import 'package:git_touch/widgets/avatar.dart';
import 'package:git_touch/widgets/link.dart';
import 'package:git_touch/widgets/timeline_item.dart';
import 'package:primer/primer.dart';
import 'package:provider/provider.dart';
import 'package:github/github.dart' as github;
import '../scaffolds/long_list.dart';
import '../widgets/timeline_item.dart';
import '../widgets/comment_item.dart';
final reactionChunk = emojiMap.entries.map((entry) {
var key = entry.key;
return '''
$key: reactions(content: $key) {
totalCount
viewerHasReacted
}''';
}).join('\n');
/// Screen for issue and pull request
class GhIssueScreen extends StatefulWidget {
class GhIssueScreen extends StatelessWidget {
final String owner;
final String name;
final int number;
final bool isPullRequest;
GhIssueScreen(this.owner, this.name, this.number);
GhIssueScreen(this.owner, this.name, this.number,
{this.isPullRequest = false});
@override
_GhIssueScreenState createState() => _GhIssueScreenState();
}
class _GhIssueScreenState extends State<GhIssueScreen> {
String get owner => widget.owner;
String get name => widget.name;
int get number => widget.number;
bool get isPullRequest => widget.isPullRequest;
String get resource => isPullRequest ? 'pullRequest' : 'issue';
String get issueChunk {
var base = '''
repository {
owner {
avatarUrl
}
}
title
closed
url
viewerCanReact
viewerCanUpdate
...CommentParts
...ReactableParts
''';
if (isPullRequest) {
base += '''
merged
additions
deletions
changedFiles
commits {
totalCount
}
''';
}
return base;
Widget _buildHeader(
BuildContext context, {
@required String avatarUrl,
@required String title,
@required StateLabelStatus status,
@required GCommentParts comment,
Iterable<Widget> extraWidgets = const [],
}) {
final theme = Provider.of<ThemeModel>(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
padding: CommonStyle.padding,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Link(
url: '/github/$owner/$name',
child: Row(
children: <Widget>[
Avatar(url: avatarUrl, size: AvatarSize.extraSmall),
SizedBox(width: 4),
Text(
'$owner / $name',
style: TextStyle(
fontSize: 17,
color: theme.palette.secondaryText,
),
),
SizedBox(width: 4),
Text(
'#$number',
style: TextStyle(
fontSize: 17,
color: theme.palette.tertiaryText,
),
),
],
),
),
SizedBox(height: 8),
Text(
title,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 8),
StateLabel(status, small: true),
SizedBox(height: 8),
CommonStyle.border,
...extraWidgets,
SizedBox(height: 8),
CommentItem.gql(comment),
],
),
),
CommonStyle.border,
],
);
}
String get timelineChunk {
var base = '''
__typename
... on IssueComment {
...CommentParts
...ReactableParts
}
... on ReferencedEvent {
createdAt
isCrossRepository
actor {
login
}
commit {
oid
url
}
commitRepository {
owner {
login
}
name
}
}
... on RenamedTitleEvent {
createdAt
previousTitle
currentTitle
actor {
login
}
}
... on ClosedEvent {
createdAt
actor {
login
}
}
... on ReopenedEvent {
createdAt
actor {
login
}
}
... on CrossReferencedEvent {
createdAt
actor {
login
}
source {
__typename
... on Issue {
number
repository {
owner {
login
}
name
}
}
... on PullRequest {
number
repository {
owner {
login
}
name
}
}
}
}
... on LabeledEvent {
createdAt
actor {
login
}
label {
name
color
}
}
... on UnlabeledEvent {
createdAt
actor {
login
}
label {
name
color
}
}
... on MilestonedEvent {
createdAt
actor {
login
}
milestoneTitle
}
... on DemilestonedEvent {
createdAt
actor {
login
}
milestoneTitle
}
... on LockedEvent {
createdAt
actor {
login
}
lockReason
}
... on UnlockedEvent {
createdAt
actor {
login
}
}
... on AssignedEvent {
createdAt
actor {
login
}
assignee {
__typename
... on User {
login
}
... on Bot {
login
}
... on Organization {
login
}
... on Mannequin {
login
}
}
}
... on UnassignedEvent {
createdAt
actor {
login
}
assignee {
__typename
... on User {
login
}
... on Bot {
login
}
... on Organization {
login
}
... on Mannequin {
login
}
}
}
... on SubscribedEvent {
createdAt
actor {
login
}
}
... on UnsubscribedEvent {
createdAt
actor {
login
}
}
... on MentionedEvent {
createdAt
actor {
login
}
}
... on PinnedEvent {
createdAt
actor {
login
}
}
... on TransferredEvent {
createdAt
actor {
login
}
fromRepository {
owner {
login
}
name
}
}
''';
if (isPullRequest) {
base += '''
... on PullRequestCommit {
prCommit: commit {
committedDate
oid
author {
user {
login
}
}
}
}
... on DeployedEvent {
createdAt
actor {
login
}
pullRequest {
headRef {
name
}
}
}
... on DeploymentEnvironmentChangedEvent {
createdAt
actor {
login
}
deploymentStatus {
deployment {
environment
}
description
}
}
... on HeadRefRestoredEvent {
createdAt
actor {
login
}
pullRequest {
headRefName
}
}
... on BaseRefForcePushedEvent {
createdAt
actor {
login
}
pullRequest {
baseRef {
name
}
}
beforeCommit {
oid
}
afterCommit {
oid
}
}
... on HeadRefForcePushedEvent {
createdAt
actor {
login
}
pullRequest {
headRefName
}
beforeCommit {
oid
}
afterCommit {
oid
}
}
... on ReviewRequestedEvent {
createdAt
actor {
login
}
requestedReviewer {
... on User {
login
}
}
}
... on ReviewRequestRemovedEvent {
createdAt
actor {
login
}
requestedReviewer {
... on User {
login
}
}
}
... on ReviewDismissedEvent {
createdAt
actor {
login
}
dismissalMessage
pullRequest {
author {
login
}
}
}
... on PullRequestReview {
createdAt
state
author {
login
}
comments(first: 10) {
nodes {
...CommentParts
...ReactableParts
}
}
}
... on MergedEvent {
createdAt
mergeRefName
actor {
login
}
commit {
oid
url
}
}
... on HeadRefDeletedEvent {
createdAt
actor {
login
}
headRefName
}
''';
}
return base;
}
Future _queryIssue({String cursor, bool trailing = false}) async {
String timelineParams;
if (trailing) {
timelineParams = 'last: $pageSize';
} else {
timelineParams = 'first: $pageSize';
if (cursor != null) {
timelineParams += ', after: "$cursor"';
}
}
var data = await context.read<AuthModel>().query('''
fragment CommentParts on Comment {
id
createdAt
body
author {
login
avatarUrl
}
}
fragment ReactableParts on Reactable {
$reactionChunk
}
{
repository(owner: "$owner", name: "$name") {
$resource(number: $number) {
$issueChunk
timelineItems($timelineParams) {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
$timelineChunk
}
}
}
}
}
''');
return data['repository'][resource];
}
StateLabelStatus _getLabelStatus(payload) {
StateLabelStatus status;
if (isPullRequest) {
if (payload['merged']) {
status = StateLabelStatus.pullMerged;
} else if (payload['closed']) {
status = StateLabelStatus.pullClosed;
} else {
status = StateLabelStatus.pullOpened;
}
} else {
if (payload['closed']) {
status = StateLabelStatus.issueClosed;
} else {
status = StateLabelStatus.issueOpened;
}
}
return status;
Future<GIssueData_repository> _queryIssue(BuildContext context,
{String cursor}) async {
final req = GIssueReq((b) {
b.vars.owner = owner;
b.vars.name = name;
b.vars.number = number;
});
var res = await context.read<AuthModel>().gqlClient.request(req).first;
return res.data.repository;
}
@override
Widget build(BuildContext context) {
return LongListStatefulScaffold(
title: Text(isPullRequest ? 'Pull Request' : 'Issue'),
trailingBuilder: (payload, setState) {
return ActionButton(
title: (isPullRequest ? 'Pull Request' : 'Issue') + ' Actions',
items: [
if (payload != null) ...[
if (!isPullRequest && payload['viewerCanUpdate'])
return LongListStatefulScaffold<GIssueData_repository, dynamic>(
title: Text('$owner/$name #$number'),
trailingBuilder: (p) {
if (p.issueOrPullRequest.G__typename == 'Issue') {
final d = p.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asIssue;
return ActionButton(
title: 'Actions',
items: [
if (!d.viewerCanUpdate)
ActionItem(
text: payload['closed'] ? 'Reopen issue' : 'Close issue',
text: d.closed ? 'Reopen issue' : 'Close issue',
onTap: (_) async {
final res = await context
.read<AuthModel>()
.gqlClient
.execute(GhOpenIssueQuery(
variables: GhOpenIssueArguments(
id: payload['id'],
open: payload['closed'],
),
));
setState(() {
payload['closed'] = res.data.reopenIssue?.issue?.closed ??
res.data.closeIssue.issue.closed;
});
await context.read<AuthModel>().ghClient.issues.edit(
github.RepositorySlug(owner, name),
number,
github.IssueRequest(
state: d.closed ? 'open' : 'closed'));
},
),
...ActionItem.getUrlActions(payload['url'] as String),
...ActionItem.getUrlActions(d.url),
],
],
);
);
} else {
final d = p.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asPullRequest;
return ActionButton(
title: 'Actions',
items: [
...ActionItem.getUrlActions(d.url),
],
);
}
},
headerBuilder: (p) {
final theme = Provider.of<ThemeModel>(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
padding: CommonStyle.padding,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Link(
url: '/github/$owner/$name',
child: Row(
children: <Widget>[
Avatar(
url: p['repository']['owner']['avatarUrl'],
size: AvatarSize.extraSmall,
),
SizedBox(width: 4),
Text(
'$owner / $name',
if (p.issueOrPullRequest.G__typename == 'Issue') {
final issue = p.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asIssue;
return _buildHeader(
context,
avatarUrl: issue.author.avatarUrl,
title: issue.title,
status: issue.closed
? StateLabelStatus.issueClosed
: StateLabelStatus.issueOpened,
comment: issue,
);
} else {
final pr = p.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asPullRequest;
return _buildHeader(
context,
avatarUrl: pr.author.avatarUrl,
title: pr.title,
status: pr.merged
? StateLabelStatus.pullMerged
: pr.closed
? StateLabelStatus.pullClosed
: StateLabelStatus.pullOpened,
comment: pr,
extraWidgets: [
Link(
child: Container(
padding: EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('${pr.changedFiles} files changed',
style: TextStyle(
fontSize: 17,
color: theme.palette.secondaryText,
),
),
SizedBox(width: 4),
Text(
'#$number',
style: TextStyle(
fontSize: 17,
color: theme.palette.tertiaryText,
),
),
],
),
),
SizedBox(height: 8),
Text(
p['title'],
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 8),
StateLabel(_getLabelStatus(p), small: true),
SizedBox(height: 8),
CommonStyle.border,
if (isPullRequest) ...[
Link(
child: Container(
padding: EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'${p['changedFiles']} files changed',
)),
Row(
children: <Widget>[
Text('+${pr.additions}',
style: TextStyle(
color: theme.palette.secondaryText,
fontSize: 17,
),
),
Row(
children: <Widget>[
Text(
'+${p['additions']}',
style: TextStyle(
color: Colors.green,
fontSize: 15,
),
),
SizedBox(width: 2),
Text(
'-${p['deletions']}',
style: TextStyle(
color: Colors.red,
fontSize: 15,
),
),
Icon(
Icons.chevron_right,
color: theme.palette.border,
),
],
)
],
),
),
url: '/github/$owner/$name/pull/$number/files',
),
CommonStyle.border,
],
SizedBox(height: 8),
CommentItem.gh(p),
],
color: Colors.green,
fontSize: 15,
)),
SizedBox(width: 2),
Text('-${pr.deletions}',
style: TextStyle(
color: Colors.red,
fontSize: 15,
)),
Icon(Icons.chevron_right,
color: theme.palette.border),
],
)
],
),
),
url: '/github/$owner/$name/pull/$number/files',
),
),
CommonStyle.border,
],
);
},
itemBuilder: (itemPayload) => TimelineItem(itemPayload),
onRefresh: () async {
var res = await _queryIssue();
int totalCount = res['timelineItems']['totalCount'];
String cursor = res['timelineItems']['pageInfo']['endCursor'];
List leadingItems = res['timelineItems']['nodes'];
var payload = LongListPayload(
header: res,
totalCount: totalCount,
cursor: cursor,
leadingItems: leadingItems,
trailingItems: [],
);
if (totalCount > 2 * pageSize) {
var res = await _queryIssue(trailing: true);
payload.trailingItems = res['timelineItems']['nodes'];
CommonStyle.border,
],
);
}
return payload;
},
onLoadMore: (String _cursor) async {
var res = await _queryIssue(cursor: _cursor);
int totalCount = res['timelineItems']['totalCount'];
String cursor = res['timelineItems']['pageInfo']['endCursor'];
List leadingItems = res['timelineItems']['nodes'];
var payload = LongListPayload(
totalCount: totalCount,
cursor: cursor,
leadingItems: leadingItems,
);
return payload;
itemBuilder: (p) => TimelineItem(p),
onRefresh: () async {
final res = await _queryIssue(context);
if (res.issueOrPullRequest.G__typename == 'Issue') {
final issue = res.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asIssue;
return LongListPayload(
header: res,
totalCount: issue.timelineItems.totalCount,
cursor: issue.timelineItems.pageInfo.endCursor,
leadingItems: issue.timelineItems.nodes.toList(),
trailingItems: [],
);
} else {
final pr = res.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asPullRequest;
return LongListPayload(
header: res,
totalCount: pr.timelineItems.totalCount,
cursor: pr.timelineItems.pageInfo.endCursor,
leadingItems: pr.timelineItems.nodes.toList(),
trailingItems: [],
);
}
},
onLoadMore: (_cursor) async {
final res = await _queryIssue(context, cursor: _cursor);
if (res.issueOrPullRequest.G__typename == 'Issue') {
final issue = res.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asIssue;
return LongListPayload(
header: res,
totalCount: issue.timelineItems.totalCount,
cursor: issue.timelineItems.pageInfo.endCursor,
leadingItems: issue.timelineItems.nodes.toList(),
);
} else {
final pr = res.issueOrPullRequest
as GIssueData_repository_issueOrPullRequest__asPullRequest;
return LongListPayload(
header: res,
totalCount: pr.timelineItems.totalCount,
cursor: pr.timelineItems.pageInfo.endCursor,
leadingItems: pr.timelineItems.nodes.toList(),
);
}
},
);
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/utils/utils.dart';
@ -17,43 +18,44 @@ class GhIssuesScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GhIssuesIssue, String>(
return ListStatefulScaffold<GIssuesData_repository_issues_nodes, String>(
title: AppBarTitle(S.of(context).issues),
actionBuilder: () => ActionEntry(
iconData: Octicons.plus,
url: '/github/$owner/$name/issues/new',
),
fetch: (cursor) async {
final req = GIssuesReq((b) {
b.vars.owner = owner;
b.vars.name = name;
b.vars.cursor = cursor;
});
final res =
await context.read<AuthModel>().gqlClient.execute(GhIssuesQuery(
variables: GhIssuesArguments(
owner: owner,
name: name,
cursor: cursor,
)));
await context.read<AuthModel>().gqlClient.request(req).first;
final issues = res.data.repository.issues;
return ListPayload(
cursor: issues.pageInfo.endCursor,
hasMore: issues.pageInfo.hasNextPage,
items: issues.nodes,
items: issues.nodes.toList(),
);
},
itemBuilder: (p) {
return IssueItem(
author: p.author?.login,
avatarUrl: p.author?.avatarUrl,
commentCount: p.comments.totalCount,
subtitle: '#' + p.number.toString(),
title: p.title,
updatedAt: p.updatedAt,
labels: p.labels.nodes.isEmpty
? null
: Wrap(spacing: 4, runSpacing: 4, children: [
for (var label in p.labels.nodes)
MyLabel(name: label.name, cssColor: label.color)
]),
url: '/github/$owner/$name/issues/${p.number}',
);
},
itemBuilder: (p) => IssueItem(
author: p.author?.login,
avatarUrl: p.author?.avatarUrl,
commentCount: p.comments.totalCount,
subtitle: '#' + p.number.toString(),
title: p.title,
updatedAt: p.updatedAt,
labels: p.labels.nodes.isEmpty
? null
: Wrap(spacing: 4, runSpacing: 4, children: [
for (var label in p.labels.nodes)
MyLabel(name: label.name, cssColor: label.color)
]),
url:
'/github/${p.repository.owner.login}/${p.repository.name}/issues/${p.number}',
),
);
}
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
@ -15,21 +16,22 @@ class GhPullsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GhPullsPullRequest, String>(
return ListStatefulScaffold<GPullsData_repository_pullRequests_nodes,
String>(
title: AppBarTitle(S.of(context).pullRequests),
fetch: (cursor) async {
final req = GPullsReq((b) {
b.vars.owner = owner;
b.vars.name = name;
b.vars.cursor = cursor;
});
final res =
await context.read<AuthModel>().gqlClient.execute(GhPullsQuery(
variables: GhPullsArguments(
owner: owner,
name: name,
cursor: cursor,
)));
await context.read<AuthModel>().gqlClient.request(req).first;
final pulls = res.data.repository.pullRequests;
return ListPayload(
cursor: pulls.pageInfo.endCursor,
hasMore: pulls.pageInfo.hasNextPage,
items: pulls.nodes,
items: pulls.nodes.toList(),
);
},
itemBuilder: (p) => IssueItem(
@ -46,8 +48,7 @@ class GhPullsScreen extends StatelessWidget {
for (var label in p.labels.nodes)
MyLabel(name: label.name, cssColor: label.color)
]),
url:
'/github/${p.repository.owner.login}/${p.repository.name}/pull/${p.number}',
url: '/github/$owner/$name/pull/${p.number}',
),
);
}

View File

@ -1,7 +1,9 @@
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.dart';
import 'package:git_touch/graphql/schema.schema.gql.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/utils/utils.dart';
@ -27,23 +29,13 @@ class GhRepoScreen extends StatelessWidget {
final String branch;
GhRepoScreen(this.owner, this.name, {this.branch});
Future<GhRepoRepository> _query(BuildContext context) async {
var res = await context.read<AuthModel>().gqlClient.execute(GhRepoQuery(
variables: GhRepoArguments(
owner: owner,
name: name,
branchSpecified: branch != null,
branch: branch ?? '')));
return res.data.repository;
}
String _buildWatchState(GhRepoSubscriptionState state) {
String _buildWatchState(GSubscriptionState state) {
switch (state) {
case GhRepoSubscriptionState.IGNORED:
case GSubscriptionState.IGNORED:
return 'Ignoring';
case GhRepoSubscriptionState.SUBSCRIBED:
case GSubscriptionState.SUBSCRIBED:
return 'Watching';
case GhRepoSubscriptionState.UNSUBSCRIBED:
case GSubscriptionState.UNSUBSCRIBED:
return 'Not watching';
default:
return 'Unknown';
@ -54,13 +46,19 @@ class GhRepoScreen extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
return RefreshStatefulScaffold<
Tuple3<GhRepoRepository, Future<int>, MarkdownViewData>>(
Tuple3<GRepoData_repository, Future<int>, MarkdownViewData>>(
title: AppBarTitle(S.of(context).repository),
fetch: () async {
final req = GRepoReq((b) => b
..vars.owner = owner
..vars.name = name
..vars.branchSpecified = branch != null
..vars.branch = branch ?? '');
final res =
await context.read<AuthModel>().gqlClient.request(req).first;
final repo = res.data.repository;
final ghClient = context.read<AuthModel>().ghClient;
final repo = await _query(context);
final countFuture = ghClient
.getJSON('/repos/$owner/$name/stats/contributors')
.then((v) => (v as List).length);
@ -127,19 +125,17 @@ class GhRepoScreen extends StatelessWidget {
children: <Widget>[
MutationButton(
active: repo.viewerSubscription ==
GhRepoSubscriptionState.SUBSCRIBED,
GSubscriptionState.SUBSCRIBED,
text: _buildWatchState(repo.viewerSubscription),
onTap: () async {
final vs = GhRepoSubscriptionState.values.where((v) =>
v != GhRepoSubscriptionState.ARTEMIS_UNKNOWN);
theme.showActions(context, [
for (var v in vs)
for (var v in GSubscriptionState.values)
ActionItem(
text: _buildWatchState(v),
onTap: (_) async {
switch (v) {
case GhRepoSubscriptionState.SUBSCRIBED:
case GhRepoSubscriptionState.IGNORED:
case GSubscriptionState.SUBSCRIBED:
case GSubscriptionState.IGNORED:
final res = await context
.read<AuthModel>()
.ghClient
@ -148,22 +144,21 @@ class GhRepoScreen extends StatelessWidget {
RepositorySlug(
repo.owner.login, repo.name),
subscribed: v ==
GhRepoSubscriptionState
.SUBSCRIBED,
ignored: v ==
GhRepoSubscriptionState.IGNORED,
GSubscriptionState.SUBSCRIBED,
ignored:
v == GSubscriptionState.IGNORED,
);
setState(() {
if (res.subscribed) {
repo.viewerSubscription =
GhRepoSubscriptionState.SUBSCRIBED;
} else if (res.ignored) {
repo.viewerSubscription =
GhRepoSubscriptionState.IGNORED;
}
// if (res.subscribed) {
// repo.viewerSubscription =
// GSubscriptionState.SUBSCRIBED;
// } else if (res.ignored) {
// repo.viewerSubscription =
// GSubscriptionState.IGNORED;
// }
});
break;
case GhRepoSubscriptionState.UNSUBSCRIBED:
case GSubscriptionState.UNSUBSCRIBED:
await context
.read<AuthModel>()
.ghClient
@ -175,8 +170,8 @@ class GhRepoScreen extends StatelessWidget {
),
);
setState(() {
repo.viewerSubscription =
GhRepoSubscriptionState.UNSUBSCRIBED;
// repo.viewerSubscription =
// GSubscriptionState.UNSUBSCRIBED;
});
break;
default:
@ -207,7 +202,7 @@ class GhRepoScreen extends StatelessWidget {
RepositorySlug(repo.owner.login, repo.name));
}
setState(() {
repo.viewerHasStarred = !repo.viewerHasStarred;
// repo.viewerHasStarred = !repo.viewerHasStarred;
});
},
),
@ -295,7 +290,7 @@ class GhRepoScreen extends StatelessWidget {
leftIconData: Octicons.history,
text: Text(S.of(context).commits),
rightWidget: Text(
((ref.target as GhRepoCommit).history?.totalCount ?? 0)
((ref.target as GRepoCommit).history?.totalCount ?? 0)
.toString()),
url: '/github/$owner/$name/commits',
),

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/models/auth.dart';
@ -7,57 +8,62 @@ import 'package:provider/provider.dart';
import 'package:git_touch/widgets/repository_item.dart';
import 'package:timeago/timeago.dart' as timeago;
class GhReposScreen extends StatelessWidget {
final String owner;
final String title;
final bool isStar;
GhReposScreen(this.owner)
: title = 'Repositories',
isStar = false;
GhReposScreen.stars(this.owner)
: title = 'Stars',
isStar = true;
class GhRepos extends StatelessWidget {
final String login;
GhRepos(this.login);
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GhReposRepository, String>(
title: AppBarTitle(title),
return ListStatefulScaffold<GReposRepoItem, String>(
title: AppBarTitle('Repositories'),
fetch: (cursor) async {
final auth = context.read<AuthModel>();
final res = await auth.gqlClient.execute(GhReposQuery(
variables:
GhReposArguments(owner: owner, isStar: isStar, after: cursor)));
final data = res.data.user;
if (isStar) {
return ListPayload(
cursor: data.starredRepositories.pageInfo.endCursor,
items: data.starredRepositories.nodes,
hasMore: data.starredRepositories.pageInfo.hasNextPage,
);
} else {
return ListPayload(
cursor: data.repositories.pageInfo.endCursor,
items: data.repositories.nodes,
hasMore: data.repositories.pageInfo.hasNextPage,
);
}
},
itemBuilder: (v) {
return RepositoryItem.gh(
owner: v.owner.login,
avatarUrl: v.owner.avatarUrl,
name: v.name,
description: v.description,
starCount: v.stargazers.totalCount,
forkCount: v.forks.totalCount,
primaryLanguageName: v.primaryLanguage?.name,
primaryLanguageColor: v.primaryLanguage?.color,
note: 'Updated ${timeago.format(v.updatedAt)}',
isPrivate: v.isPrivate,
isFork: v.isFork,
final req = GReposReq((b) {
b.vars.login = login;
b.vars.after = cursor;
});
final res = await auth.gqlClient.request(req).first;
final p = res.data.user.repositories;
return ListPayload(
cursor: p.pageInfo.endCursor,
hasMore: p.pageInfo.hasNextPage,
items: p.nodes,
);
},
itemBuilder: (p) {
return RepositoryItem.gql(p,
note: 'Updated ${timeago.format(p.updatedAt)}');
},
);
}
}
class GhStars extends StatelessWidget {
final String login;
GhStars(this.login);
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GReposRepoItem, String>(
title: AppBarTitle('Stars'),
fetch: (cursor) async {
final auth = context.read<AuthModel>();
final req = GStarsReq((b) {
b.vars.login = login;
b.vars.after = cursor;
});
final res = await auth.gqlClient.request(req).first;
final p = res.data.user.starredRepositories;
return ListPayload(
cursor: p.pageInfo.endCursor,
hasMore: p.pageInfo.hasNextPage,
items: p.nodes,
);
},
itemBuilder: (p) {
return RepositoryItem.gql(p,
note: 'Updated ${timeago.format(p.updatedAt)}');
},
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/utils/utils.dart';
@ -18,52 +19,54 @@ import 'package:provider/provider.dart';
import 'package:git_touch/widgets/action_button.dart';
import '../generated/l10n.dart';
class GhUserScreen extends StatelessWidget {
final String login;
GhUserScreen(this.login);
bool get isViewer => login == null;
class _Repos extends StatelessWidget {
final String title;
final Iterable<GRepoItem> repos;
Iterable<Widget> _buildPinnedItems(Iterable<GhUserRepository> pinnedItems,
Iterable<GhUserRepository> repositories) {
String title;
Iterable<GhUserRepository> items = [];
_Repos(final Iterable<GRepoItem> pinned, final Iterable<GRepoItem> repos)
: title =
pinned.isNotEmpty ? 'pinned repositories' : 'popular repositories',
repos = pinned.isNotEmpty ? pinned : repos;
if (pinnedItems.isNotEmpty) {
title = 'pinned repositories';
items = pinnedItems;
} else if (repositories.isNotEmpty) {
title = 'popular repositories';
items = repositories;
}
if (items.isEmpty) return [];
return [
if (title != null) TableViewHeader(title),
...join(
CommonStyle.border,
items.map((v) {
return RepositoryItem.gh(
owner: v.owner.login,
avatarUrl: v.owner.avatarUrl,
name: v.name,
description: v.description,
starCount: v.stargazers.totalCount,
forkCount: v.forks.totalCount,
primaryLanguageName: v.primaryLanguage?.name,
primaryLanguageColor: v.primaryLanguage?.color,
isPrivate: v.isPrivate,
isFork: v.isFork,
);
}).toList(),
),
];
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TableViewHeader(title),
...join(
CommonStyle.border,
repos.map((v) {
return RepositoryItem.gh(
owner: v.owner.login,
avatarUrl: v.owner.avatarUrl,
name: v.name,
description: v.description,
starCount: v.stargazers.totalCount,
forkCount: v.forks.totalCount,
primaryLanguageName: v.primaryLanguage?.name,
primaryLanguageColor: v.primaryLanguage?.color,
isPrivate: v.isPrivate,
isFork: v.isFork,
);
}).toList(),
),
],
);
}
}
Widget _buildUser(BuildContext context, GhUserUser p,
void Function(void Function()) setState) {
class _User extends StatelessWidget {
final GUserParts p;
final bool isViewer;
const _User(this.p, {this.isViewer = false});
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
final auth = Provider.of<AuthModel>(context);
final login = p.login;
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
@ -87,9 +90,9 @@ class GhUserScreen extends StatelessWidget {
} else {
await auth.ghClient.users.followUser(p.login);
}
setState(() {
p.viewerIsFollowing = !p.viewerIsFollowing;
});
// setState(() {
// // p.viewerIsFollowing = !p.viewerIsFollowing;
// });
},
)
],
@ -190,34 +193,22 @@ class GhUserScreen extends StatelessWidget {
],
),
CommonStyle.verticalGap,
// if (isViewer)
// TableView(
// hasIcon: true,
// items: [
// TableViewItem(
// leftIconData: Icons.settings,
// text: Text('Settings'),
// url: '/settings',
// ),
// TableViewItem(
// leftIconData: Icons.info_outline,
// text: Text('About'),
// url: '/about',
// ),
// ],
// )
// else
..._buildPinnedItems(
p.pinnedItems.nodes
.where((n) => n is GhUserRepository)
.cast<GhUserRepository>(),
p.repositories.nodes),
_Repos(
p.pinnedItems.nodes.whereType<GRepoItem>(),
p.repositories.nodes,
),
CommonStyle.verticalGap,
],
);
}
}
Widget _buildOrganization(BuildContext context, GhUserOrganization p) {
class _Org extends StatelessWidget {
final GUserData_repositoryOwner__asOrganization p;
_Org(this.p);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
@ -247,7 +238,7 @@ class GhUserScreen extends StatelessWidget {
TableViewItem(
leftIconData: Icons.rss_feed,
text: Text(S.of(context).events),
url: '/github/$login?tab=events',
url: '/github/${p.login}?tab=events',
),
if (isNotNullOrEmpty(p.location))
TableViewItem(
@ -281,69 +272,64 @@ class GhUserScreen extends StatelessWidget {
],
),
CommonStyle.verticalGap,
..._buildPinnedItems(
p.pinnedItems.nodes
.where((n) => n is GhUserRepository)
.cast<GhUserRepository>(),
p.pinnableItems.nodes
.where((n) => n is GhUserRepository)
.cast<GhUserRepository>(),
_Repos(
p.pinnedItems.nodes.whereType<GRepoItem>(),
p.pinnableItems.nodes.whereType<GRepoItem>(),
),
CommonStyle.verticalGap,
],
);
}
}
class GhViewer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final auth = Provider.of<AuthModel>(context);
return RefreshStatefulScaffold<GUserParts>(
fetch: () async {
final req = GViewerReq();
final res = await auth.gqlClient.request(req).first;
return res.data.viewer;
},
title: AppBarTitle(S.of(context).me),
action: ActionEntry(
iconData: Icons.settings,
url: '/settings',
),
bodyBuilder: (p, setState) {
return _User(p, isViewer: true);
},
);
}
}
class GhUser extends StatelessWidget {
final String login;
GhUser(this.login);
@override
Widget build(BuildContext context) {
final auth = Provider.of<AuthModel>(context);
return RefreshStatefulScaffold<GhUserRepositoryOwner>(
return RefreshStatefulScaffold<GUserData>(
fetch: () async {
final data = await auth.gqlClient.execute(GhUserQuery(
variables:
GhUserArguments(login: login ?? '', isViewer: isViewer)));
return isViewer ? data.data.viewer : data.data.repositoryOwner;
final req = GUserReq((b) => b..vars.login = login);
final res = await auth.gqlClient.request(req).first;
return res.data;
},
title: AppBarTitle(isViewer ? S.of(context).me : login),
action: isViewer
? ActionEntry(
iconData: Icons.settings,
url: '/settings',
)
: null,
actionBuilder: isViewer
? null
: (payload, setState) {
switch (payload.resolveType) {
case 'User':
final user = payload as GhUserUser;
return ActionButton(
title: 'User Actions',
items: [...ActionItem.getUrlActions(user.url)],
);
case 'Organization':
final organization = payload as GhUserOrganization;
return ActionButton(
title: 'Organization Actions',
items: [
...ActionItem.getUrlActions(organization.url),
],
);
default:
return null;
}
},
bodyBuilder: (payload, setState) {
if (isViewer) {
return _buildUser(context, payload as GhUserUser, setState);
}
switch (payload.resolveType) {
case 'User':
return _buildUser(context, payload as GhUserUser, setState);
case 'Organization':
return _buildOrganization(context, payload as GhUserOrganization);
default:
return null;
title: AppBarTitle(login),
actionBuilder: (payload, setState) {
return ActionButton(
title: 'User Actions',
items: ActionItem.getUrlActions(payload.repositoryOwner.url),
);
},
bodyBuilder: (p, setState) {
if (p.repositoryOwner.G__typename == 'User') {
return _User(p.repositoryOwner as GUserData_repositoryOwner__asUser);
} else {
return _Org(
p.repositoryOwner as GUserData_repositoryOwner__asOrganization);
}
},
);

View File

@ -1,155 +1,157 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/gh.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/github.req.gql.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/user_item.dart';
import 'package:git_touch/models/auth.dart';
import 'package:provider/provider.dart';
enum UsersScreenType {
follower,
following,
member,
watch,
star,
}
class GhUsersScreen extends StatelessWidget {
class GhFollowers extends StatelessWidget {
final String login;
final String repoName;
final UsersScreenType type;
GhUsersScreen(this.login, this.type, {this.repoName = ''});
String get _title {
switch (type) {
case UsersScreenType.follower:
return 'Followers';
case UsersScreenType.following:
return 'Following';
case UsersScreenType.member:
return 'Members';
case UsersScreenType.watch:
return 'Watchers';
case UsersScreenType.star:
return 'Stargazers';
default:
return null;
}
}
Widget _buildBio(BuildContext context, String company, String location,
DateTime createdAt) {
final theme = Provider.of<ThemeModel>(context);
if (company != null && company.isNotEmpty) {
return Row(
children: <Widget>[
Icon(
Octicons.organization,
size: 15,
color: theme.palette.secondaryText,
),
SizedBox(width: 4),
Expanded(child: Text(company, overflow: TextOverflow.ellipsis)),
],
);
}
if (location != null && location.isNotEmpty) {
return Row(
children: <Widget>[
Icon(
Octicons.location,
size: 15,
color: theme.palette.secondaryText,
),
SizedBox(width: 4),
Expanded(child: Text(location, overflow: TextOverflow.ellipsis)),
],
);
}
return Row(
children: <Widget>[
Icon(
Octicons.clock,
size: 15,
color: theme.palette.secondaryText,
),
SizedBox(width: 4),
Expanded(
child: Text('Joined on ${dateFormat.format(createdAt)}',
overflow: TextOverflow.ellipsis)),
],
);
}
GhFollowers(this.login);
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GhUsersUser, String>(
title: AppBarTitle(_title),
return ListStatefulScaffold<GUserItem, String>(
title: AppBarTitle('Followers'),
fetch: (cursor) async {
final auth = context.read<AuthModel>();
final res = await auth.gqlClient.execute(GhUsersQuery(
variables: GhUsersArguments(
login: login,
repoName: repoName,
isFollowers: type == UsersScreenType.follower,
isFollowing: type == UsersScreenType.following,
isStar: type == UsersScreenType.star,
isWatch: type == UsersScreenType.watch,
isMember: type == UsersScreenType.member,
after: cursor)));
switch (type) {
case UsersScreenType.follower:
final payload = res.data.user.followers;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.following:
final payload = res.data.user.following;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.member:
final payload = res.data.organization.membersWithRole;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.watch:
final payload = res.data.repository.watchers;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.star:
final payload = res.data.repository.stargazers;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
default:
return null;
}
},
itemBuilder: (payload) {
return UserItem.github(
login: payload.login,
name: payload.name,
avatarUrl: payload.avatarUrl,
bio: _buildBio(
context, payload.company, payload.location, payload.createdAt),
final req = GFollowersReq((b) {
b.vars.login = login;
b.vars.after = cursor;
});
final res = await auth.gqlClient.request(req).first;
final p = res.data.user.followers;
return ListPayload(
cursor: p.pageInfo.endCursor,
hasMore: p.pageInfo.hasNextPage,
items: p.nodes,
);
},
itemBuilder: (p) {
return UserItem.gql(p);
},
);
}
}
class GhFollowing extends StatelessWidget {
final String login;
GhFollowing(this.login);
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GUserItem, String>(
title: AppBarTitle('Following'),
fetch: (cursor) async {
final auth = context.read<AuthModel>();
final req = GFollowingReq((b) {
b.vars.login = login;
b.vars.after = cursor;
});
final res = await auth.gqlClient.request(req).first;
final p = res.data.user.following;
return ListPayload(
cursor: p.pageInfo.endCursor,
hasMore: p.pageInfo.hasNextPage,
items: p.nodes,
);
},
itemBuilder: (p) {
return UserItem.gql(p);
},
);
}
}
class GhMembers extends StatelessWidget {
final String login;
GhMembers(this.login);
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GUserItem, String>(
title: AppBarTitle('Members'),
fetch: (cursor) async {
final auth = context.read<AuthModel>();
final req = GMembersReq((b) {
b.vars.login = login;
b.vars.after = cursor;
});
final res = await auth.gqlClient.request(req).first;
final p = res.data.organization.membersWithRole;
return ListPayload(
cursor: p.pageInfo.endCursor,
hasMore: p.pageInfo.hasNextPage,
items: p.nodes,
);
},
itemBuilder: (p) {
return UserItem.gql(p);
},
);
}
}
class GhWachers extends StatelessWidget {
final String owner;
final String name;
GhWachers(this.owner, this.name);
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GUserItem, String>(
title: AppBarTitle('Wachers'),
fetch: (cursor) async {
final auth = context.read<AuthModel>();
final req = GWatchersReq((b) {
b.vars.owner = owner;
b.vars.name = name;
b.vars.after = cursor;
});
final res = await auth.gqlClient.request(req).first;
final p = res.data.repository.watchers;
return ListPayload(
cursor: p.pageInfo.endCursor,
hasMore: p.pageInfo.hasNextPage,
items: p.nodes,
);
},
itemBuilder: (p) {
return UserItem.gql(p);
},
);
}
}
class GhStargazers extends StatelessWidget {
final String owner;
final String name;
GhStargazers(this.owner, this.name);
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GUserItem, String>(
title: AppBarTitle('Stargazers'),
fetch: (cursor) async {
final auth = context.read<AuthModel>();
final req = GStargazersReq((b) {
b.vars.owner = owner;
b.vars.name = name;
b.vars.after = cursor;
});
final res = await auth.gqlClient.request(req).first;
final p = res.data.repository.stargazers;
return ListPayload(
cursor: p.pageInfo.endCursor,
hasMore: p.pageInfo.hasNextPage,
items: p.nodes,
);
},
itemBuilder: (p) {
return UserItem.gql(p);
},
);
}
}

View File

@ -0,0 +1,28 @@
import 'package:built_value/serializer.dart';
class DateTimeSerializer implements PrimitiveSerializer<DateTime> {
@override
DateTime deserialize(
Serializers serializers,
Object serialized, {
FullType specifiedType = FullType.unspecified,
}) {
assert(serialized is String,
"DateTimeSerializer expected 'String' but got ${serialized.runtimeType}");
return DateTime.parse(serialized);
}
@override
Object serialize(
Serializers serializers,
DateTime dt, {
FullType specifiedType = FullType.unspecified,
}) =>
dt.toString();
@override
Iterable<Type> get types => [DateTime];
@override
String get wireName => "DateTime";
}

33
lib/utils/nil_store.dart Normal file
View File

@ -0,0 +1,33 @@
import 'dart:async';
import 'package:ferry_store/ferry_store.dart';
// This is a cache store to disable cache
class NilStore extends Store {
@override
void clear() {}
@override
void delete(String dataId) {}
@override
void deleteAll(Iterable<String> dataIds) {}
@override
Map<String, dynamic> get(String dataId) {
return {};
}
@override
Iterable<String> get keys => [];
@override
void put(String dataId, Map<String, dynamic> value) {}
@override
void putAll(Map<String, Map<String, dynamic>> data) {}
@override
Stream<Map<String, dynamic>> watch(String dataId) {
return Stream.empty();
}
}

View File

@ -1,20 +0,0 @@
import "package:gql_exec/gql_exec.dart";
import "package:gql/language.dart";
import 'package:gql_link/gql_link.dart';
class GithubRequestSerializer extends RequestSerializer {
const GithubRequestSerializer();
@override
Map<String, dynamic> serializeRequest(Request request) {
final RequestExtensionsThunk thunk = request.context.entry();
return <String, dynamic>{
// Remove operationName here for GitHub API compatibility
// "operationName": request.operation.operationName,
"variables": request.variables,
"query": printNode(request.operation.document),
if (thunk != null) "extensions": thunk.getRequestExtensions(request),
};
}
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/widgets/action_button.dart';
@ -141,6 +142,18 @@ class CommentItem extends StatelessWidget {
final List<Widget> widgets;
final List<ActionItem> commentActionItemList;
CommentItem.gql(GCommentParts p)
: avatar = Avatar(
url: p.author.avatarUrl, // TODO: deleted user
linkUrl: '/github/' + p.author.login,
),
login = p.author.login,
createdAt = p.createdAt,
body = p.body,
widgets = [], // [GhEmojiAction(payload)], // TODO:
prefix = 'github',
commentActionItemList = []; // TODO
CommentItem.gh(Map<String, dynamic> payload)
: avatar = Avatar(
url: payload['author']['avatarUrl'], // TODO: deleted user

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/models/bitbucket.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/models/gogs.dart';
@ -103,6 +104,22 @@ class RepositoryItem extends StatelessWidget {
avatarLink = '/github/$owner',
url = '/github/$owner/$name';
factory RepositoryItem.gql(GRepoItem v, {@required note}) {
return RepositoryItem.gh(
owner: v.owner.login,
avatarUrl: v.owner.avatarUrl,
name: v.name,
description: v.description,
starCount: v.stargazers.totalCount,
forkCount: v.forks.totalCount,
primaryLanguageName: v.primaryLanguage?.name,
primaryLanguageColor: v.primaryLanguage?.color,
note: note,
isPrivate: v.isPrivate,
isFork: v.isFork,
);
}
static IconData _buildIconData(bool isPrivate, bool isFork) {
if (isPrivate == true) return Octicons.lock;
if (isFork == true) return Octicons.repo_forked;

View File

@ -1,6 +1,8 @@
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/graphql/schema.schema.gql.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/widgets/label.dart';
import 'package:provider/provider.dart';
@ -16,14 +18,12 @@ class TimelineEventItem extends StatelessWidget {
final IconData iconData;
final Color iconColor;
final TextSpan textSpan;
final p;
TimelineEventItem({
this.actor,
this.iconData = Octicons.octoface,
this.iconColor = Colors.grey,
this.textSpan,
this.p,
});
@override
@ -54,64 +54,45 @@ class TimelineEventItem extends StatelessWidget {
}
class TimelineItem extends StatelessWidget {
final Map<String, dynamic> p;
TimelineItem(this.p);
final dynamic node;
TimelineItem(this.node);
TextSpan _buildReviewText(BuildContext context, item) {
switch (item['state']) {
case 'APPROVED':
return TextSpan(text: ' approved these changes');
case 'COMMENTED':
return TextSpan(text: ' reviewed ');
default:
return warningSpan;
}
}
InlineSpan _buildLabel(p) {
return WidgetSpan(
child: MyLabel(
name: p['label']['name'],
cssColor: p['label']['color'],
),
Widget _buildFallback(String type) {
return TimelineEventItem(
actor: '',
iconData: Octicons.octoface,
textSpan: TextSpan(children: [
TextSpan(text: 'Woops, $type type not implemented yet'),
]),
);
}
Widget _buildByType(BuildContext context, String type) {
final theme = Provider.of<ThemeModel>(context);
var defaultItem = TimelineEventItem(
actor: '',
iconData: Octicons.octoface,
textSpan: TextSpan(children: [
TextSpan(text: 'Woops, $type type not implemented yet'),
]),
p: p,
);
switch (type) {
// common types
case 'PullRequestCommit':
final p = node as GPullRequestCommitParts;
return TimelineEventItem(
actor: p['prCommit']['author']['user'] == null
? null
: p['prCommit']['author']['user']['login'],
actor: p.commit.author.user?.login,
iconData: Octicons.git_commit,
textSpan: TextSpan(children: [
TextSpan(text: ' added commit '),
TextSpan(text: p['prCommit']['oid'].substring(0, 8))
TextSpan(text: p.commit.oid.substring(0, 8))
]),
p: p,
);
case 'IssueComment':
return CommentItem.gh(p);
return CommentItem.gql(node as GCommentParts);
case 'CrossReferencedEvent':
final number = p['source']['number'] as int;
final owner = p['source']['repository']['owner']['login'] as String;
final name = p['source']['repository']['name'] as String;
final prefix = p['source']['__typename'] == 'Issue' ? 'issues' : 'pull';
final p = node as GCrossReferencedEventParts;
final source = p.source as dynamic;
final number = source.number;
final owner = source.repository.owner.login;
final name = source.repository.name;
final prefix = p.source.G__typename == 'Issue' ? 'issues' : 'pull';
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.primitive_dot,
iconColor: GithubPalette.open,
textSpan: TextSpan(children: [
@ -119,361 +100,359 @@ class TimelineItem extends StatelessWidget {
createLinkSpan(context, '$owner/$name#$number',
'/github/$owner/$name/$prefix/$number'),
]),
p: p,
);
case 'ClosedEvent':
final p = node as GClosedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.circle_slash,
iconColor: GithubPalette.closed,
textSpan: TextSpan(text: ' closed this '),
p: p,
);
case 'ReopenedEvent':
final p = node as GReopenedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.primitive_dot,
iconColor: GithubPalette.open,
textSpan: TextSpan(text: ' reopened this '),
p: p,
);
case 'SubscribedEvent':
final p = node as GSubscribedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
textSpan: TextSpan(text: ' subscribed to this issue '),
p: p,
);
case 'UnsubscribedEvent':
final p = node as GUnsubscribedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
textSpan: TextSpan(text: ' unsubscribed from this issue '),
p: p,
);
case 'ReferencedEvent':
final p = node as GReferencedEventParts;
// TODO: isCrossRepository
if (p['commit'] == null) {
if (p.commit == null) {
return Container();
}
if (p['isCrossRepository']) {
if (p.isCrossRepository) {
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.bookmark,
textSpan: TextSpan(children: [
TextSpan(text: ' referenced this pull request from commit '),
TextSpan(text: p['commit']['oid'].substring(0, 8)),
TextSpan(text: ' from ' + p['commitRepository']['name']),
TextSpan(text: p.commit.oid.substring(0, 8)),
TextSpan(text: ' from ' + p.commitRepository.name),
]),
p: p,
);
}
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.bookmark,
textSpan: TextSpan(children: [
TextSpan(text: ' referenced this pull request from commit '),
TextSpan(text: p['commit']['oid'].substring(0, 8)),
TextSpan(text: p.commit.oid.substring(0, 8)),
]),
p: p,
);
case 'AssignedEvent':
final p = node as GAssignedEventParts;
final assignee = (p.assignee as dynamic).login;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.key,
textSpan: TextSpan(children: [
TextSpan(text: ' assigned this to '),
createLinkSpan(context, p['assignee']['login'],
'/github/' + p['assignee']['login']),
createLinkSpan(context, assignee, '/github/$assignee'),
]),
p: p,
);
case 'UnassignedEvent':
final p = node as GUnassignedEventParts;
final assignee = (p.assignee as dynamic).login;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.key,
textSpan: TextSpan(children: [
TextSpan(text: ' unassigned this from '),
createLinkSpan(context, p['assignee']['login'],
'/github/' + p['assignee']['login']),
createLinkSpan(context, assignee, '/github/$assignee')
]),
p: p,
);
case 'LabeledEvent':
final p = node as GLabeledEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.tag,
textSpan: TextSpan(children: [
TextSpan(text: ' added '),
_buildLabel(p),
WidgetSpan(
child: MyLabel(name: p.label.name, cssColor: p.label.color)),
TextSpan(text: ' label'),
]),
p: p,
);
case 'UnlabeledEvent':
final p = node as GUnlabeledEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.tag,
textSpan: TextSpan(children: [
TextSpan(text: ' removed '),
_buildLabel(p),
WidgetSpan(
child: MyLabel(name: p.label.name, cssColor: p.label.color)),
TextSpan(text: ' label'),
]),
p: p,
);
case 'MilestonedEvent':
final p = node as GMilestonedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.milestone,
textSpan: TextSpan(children: [
TextSpan(text: ' added this to '),
TextSpan(text: p['milestoneTitle']),
TextSpan(text: p.milestoneTitle),
TextSpan(text: ' milestone'),
]),
p: p,
);
case 'DemilestonedEvent':
final p = node as GDemilestonedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.milestone,
textSpan: TextSpan(children: [
TextSpan(text: ' removed this from '),
TextSpan(text: p['milestoneTitle']),
TextSpan(text: p.milestoneTitle),
TextSpan(text: ' milestone'),
]),
p: p,
);
case 'RenamedTitleEvent':
final p = node as GRenamedTitleEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.pencil,
textSpan: TextSpan(children: [
TextSpan(text: ' changed the title '),
TextSpan(
text: p['previousTitle'],
text: p.previousTitle,
style: TextStyle(decoration: TextDecoration.lineThrough),
),
TextSpan(text: ' to '),
TextSpan(text: p['currentTitle'])
TextSpan(text: p.currentTitle)
]),
p: p,
);
case 'LockedEvent':
final p = node as GLockedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.lock,
textSpan: TextSpan(children: [
TextSpan(text: ' locked this conversation '),
]),
p: p,
);
case 'UnlockedEvent':
final p = node as GUnlockedEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
iconData: Octicons.key,
textSpan: TextSpan(children: [
TextSpan(text: ' unlocked this conversation '),
]),
p: p,
);
// issue only types
case 'TransferredEvent':
final p = node as GTransferredEventParts;
return TimelineEventItem(
actor: p['actor']['login'],
actor: p.actor.login,
textSpan: TextSpan(
children: [
TextSpan(
text: ' transferred this issue from ' +
p['fromRepository']['name'])
text: ' transferred this issue from ' + p.fromRepository.name)
],
),
);
// pull request only types
case 'CommitCommentThread':
return defaultItem; // TODO:
return _buildFallback(type); // TODO:
case 'PullRequestReview':
return TimelineEventItem(
actor: p['author']['login'],
iconColor: GithubPalette.open,
iconData: Octicons.check,
textSpan: _buildReviewText(context, p),
p: p,
);
case 'PullRequestReviewThread':
case 'PullRequestReviewComment':
return defaultItem; // TODO:
case 'MergedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.git_merge,
iconColor: GithubPalette.merged,
textSpan: TextSpan(children: [
TextSpan(text: ' merged commit '),
TextSpan(text: p['commit']['oid'].substring(0, 8)),
TextSpan(text: ' into '),
TextSpan(text: p['mergeRefName']),
]),
p: p,
);
case 'MentionedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.bookmark,
textSpan: TextSpan(text: ' was mentioned '),
);
case 'PinnedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.pin,
textSpan: TextSpan(text: ' pinned this issue '),
);
case 'DeployedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
textSpan: TextSpan(
text: ' deployed the pull request ' + p['pullRequest']['name']),
);
case 'DeploymentEnvironmentChangedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
textSpan: TextSpan(
text: ' changed the deployment environment to ' +
p['deploymentStatus']['deployment']['environment']),
);
case 'HeadRefDeletedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.git_branch,
textSpan: TextSpan(children: [
TextSpan(text: ' deleted the '),
TextSpan(text: p['headRefName']),
TextSpan(text: ' branch'),
]),
p: p,
);
case 'HeadRefRestoredEvent':
return TimelineEventItem(
actor: p['actor']['login'],
textSpan: TextSpan(children: [
TextSpan(text: ' restored the '),
WidgetSpan(
child: PrimerBranchName(p['pullRequest']['headRefName'])),
TextSpan(text: ' branch')
]),
);
case 'HeadRefForcePushedEvent':
return TimelineEventItem(
iconData: Octicons.repo_force_push,
actor: p['actor']['login'],
textSpan: TextSpan(
children: [
TextSpan(text: ' force-pushed the '),
WidgetSpan(
child: PrimerBranchName(p['pullRequest']['headRefName'])),
TextSpan(text: ' branch from '),
TextSpan(
text: (p['beforeCommit']['oid'] as String).substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
TextSpan(text: ' to '),
TextSpan(
text: (p['afterCommit']['oid'] as String).substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
],
),
p: p,
);
case 'BaseRefForcePushedEvent':
return TimelineEventItem(
iconData: Octicons.repo_force_push,
actor: p['actor']['login'],
textSpan: TextSpan(
children: [
TextSpan(text: ' force-pushed the '),
WidgetSpan(
child: PrimerBranchName(p['pullRequest']['baseRef']['name'])),
TextSpan(text: ' branch from '),
TextSpan(
text: (p['beforeCommit']['oid'] as String).substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
TextSpan(text: ' to '),
TextSpan(
text: (p['afterCommit']['oid'] as String).substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
],
),
p: p,
);
case 'ReviewRequestedEvent':
return TimelineEventItem(
iconData: Octicons.eye,
actor: p['actor']['login'],
textSpan: TextSpan(children: [
TextSpan(text: ' requested a review from '),
createUserSpan(context, p['requestedReviewer']['login']),
]),
p: p,
);
case 'ReviewRequestRemovedEvent':
return TimelineEventItem(
iconData: Octicons.eye,
actor: p['actor']['login'],
textSpan: TextSpan(children: [
TextSpan(text: ' removed '),
createUserSpan(context, p['requestedReviewer']['login']),
TextSpan(text: ' from the review request '),
]),
p: p,
);
case 'ReviewDismissedEvent':
return TimelineEventItem(
iconData: Octicons.eye,
actor: p['actor']['login'],
textSpan: TextSpan(children: [
TextSpan(text: ' dismissed the pull request review requested by '),
createUserSpan(context, p['pullRequest']['author']['login'])
]),
);
default:
return defaultItem;
}
}
@override
Widget build(BuildContext context) {
final type = p['__typename'] as String;
Widget widget = Container(
padding: CommonStyle.padding,
child: _buildByType(context, type),
);
if (type == 'PullRequestReview') {
final comments = p['comments']['nodes'] as List;
if (comments.isNotEmpty) {
widget = Column(
final p = node as GPullRequestReviewParts;
return Column(
children: <Widget>[
widget,
TimelineEventItem(
actor: p.author.login,
iconColor: GithubPalette.open,
iconData: Octicons.check,
textSpan: p.state == GPullRequestReviewState.APPROVED
? TextSpan(text: ' approved these changes')
: p.state == GPullRequestReviewState.COMMENTED
? TextSpan(text: ' reviewed ')
: warningSpan),
Container(
padding: CommonStyle.padding.copyWith(left: 50),
child: Column(
children: <Widget>[
for (var v in comments) CommentItem.gh(v),
for (var v in p.comments.nodes) CommentItem.gql(v),
],
),
),
],
);
}
case 'PullRequestReviewThread':
case 'PullRequestReviewComment':
return _buildFallback(type); // TODO:
case 'MergedEvent':
final p = node as GMergedEventParts;
return TimelineEventItem(
actor: p.actor.login,
iconData: Octicons.git_merge,
iconColor: GithubPalette.merged,
textSpan: TextSpan(children: [
TextSpan(text: ' merged commit '),
TextSpan(text: p.commit.oid.substring(0, 8)),
TextSpan(text: ' into '),
TextSpan(text: p.mergeRefName),
]),
);
case 'MentionedEvent':
final p = node as GMentionedEventParts;
return TimelineEventItem(
actor: p.actor.login,
iconData: Octicons.bookmark,
textSpan: TextSpan(text: ' was mentioned '),
);
case 'PinnedEvent':
final p = node as GPinnedEventParts;
return TimelineEventItem(
actor: p.actor.login,
iconData: Octicons.pin,
textSpan: TextSpan(text: ' pinned this issue '),
);
case 'DeployedEvent':
final p = node as GDeployedEventParts;
return TimelineEventItem(
actor: p.actor.login,
textSpan: TextSpan(
text: ' deployed the pull request ' + p.pullRequest.headRef.name),
);
case 'DeploymentEnvironmentChangedEvent':
final p = node as GDeploymentEnvironmentChangedEventParts;
return TimelineEventItem(
actor: p.actor.login,
textSpan: TextSpan(
text: ' changed the deployment environment to ' +
p.deploymentStatus.deployment.environment),
);
case 'HeadRefDeletedEvent':
final p = node as GHeadRefDeletedEventParts;
return TimelineEventItem(
actor: p.actor.login,
iconData: Octicons.git_branch,
textSpan: TextSpan(children: [
TextSpan(text: ' deleted the '),
TextSpan(text: p.headRefName),
TextSpan(text: ' branch'),
]),
);
case 'HeadRefRestoredEvent':
final p = node as GHeadRefRestoredEventParts;
return TimelineEventItem(
actor: p.actor.login,
textSpan: TextSpan(children: [
TextSpan(text: ' restored the '),
WidgetSpan(child: PrimerBranchName(p.pullRequest.headRefName)),
TextSpan(text: ' branch')
]),
);
case 'HeadRefForcePushedEvent':
final p = node as GHeadRefForcePushedEventParts;
return TimelineEventItem(
iconData: Octicons.repo_force_push,
actor: p.actor.login,
textSpan: TextSpan(
children: [
TextSpan(text: ' force-pushed the '),
WidgetSpan(child: PrimerBranchName(p.pullRequest.headRefName)),
TextSpan(text: ' branch from '),
TextSpan(
text: p.beforeCommit.oid.substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
TextSpan(text: ' to '),
TextSpan(
text: p.afterCommit.oid.substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
],
),
);
case 'BaseRefForcePushedEvent':
final p = node as GBaseRefForcePushedEventParts;
return TimelineEventItem(
iconData: Octicons.repo_force_push,
actor: p.actor.login,
textSpan: TextSpan(
children: [
TextSpan(text: ' force-pushed the '),
WidgetSpan(child: PrimerBranchName(p.pullRequest.baseRef.name)),
TextSpan(text: ' branch from '),
TextSpan(
text: p.beforeCommit.oid.substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
TextSpan(text: ' to '),
TextSpan(
text: p.afterCommit.oid.substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
],
),
);
case 'ReviewRequestedEvent':
final p = node as GReviewRequestedEventParts;
return TimelineEventItem(
iconData: Octicons.eye,
actor: p.actor.login,
textSpan: TextSpan(children: [
TextSpan(text: ' requested a review from '),
createUserSpan(
context,
(p.requestedReviewer
as GReviewRequestedEventParts_requestedReviewer__asUser)
.login),
]),
);
case 'ReviewRequestRemovedEvent':
final p = node as GReviewRequestRemovedEventParts;
return TimelineEventItem(
iconData: Octicons.eye,
actor: p.actor.login,
textSpan: TextSpan(children: [
TextSpan(text: ' removed '),
createUserSpan(
context,
(p.requestedReviewer
as GReviewRequestRemovedEventParts_requestedReviewer__asUser)
.login),
TextSpan(text: ' from the review request '),
]),
);
case 'ReviewDismissedEvent':
final p = node as GReviewDismissedEventParts;
return TimelineEventItem(
iconData: Octicons.eye,
actor: p.actor.login,
textSpan: TextSpan(children: [
TextSpan(text: ' dismissed the pull request review requested by '),
createUserSpan(context, p.pullRequest.author.login),
]),
);
default:
return _buildFallback(type);
}
}
return widget;
@override
Widget build(BuildContext context) {
return Container(
padding: CommonStyle.padding,
child: _buildByType(context, node.G__typename),
);
}
}

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/github.data.gql.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/avatar.dart';
@ -12,6 +13,56 @@ const userGqlChunk = '''
bio
''';
class GhBioWidget extends StatelessWidget {
final GUserItem p;
const GhBioWidget(this.p);
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
if (isNotNullOrEmpty(p.company)) {
return Row(
children: <Widget>[
Icon(
Octicons.organization,
size: 15,
color: theme.palette.secondaryText,
),
SizedBox(width: 4),
Expanded(child: Text(p.company, overflow: TextOverflow.ellipsis)),
],
);
}
if (isNotNullOrEmpty(p.location)) {
return Row(
children: <Widget>[
Icon(
Octicons.location,
size: 15,
color: theme.palette.secondaryText,
),
SizedBox(width: 4),
Expanded(child: Text(p.location, overflow: TextOverflow.ellipsis)),
],
);
}
return Row(
children: <Widget>[
Icon(
Octicons.clock,
size: 15,
color: theme.palette.secondaryText,
),
SizedBox(width: 4),
Expanded(
child: Text('Joined on ${dateFormat.format(p.createdAt)}',
overflow: TextOverflow.ellipsis)),
],
);
}
}
class UserItem extends StatelessWidget {
final String login;
final String name;
@ -26,6 +77,13 @@ class UserItem extends StatelessWidget {
@required this.bio,
}) : url = '/github/$login';
UserItem.gql(GUserItem p)
: login = p.login,
name = p.name,
avatarUrl = p.avatarUrl,
url = '/github/' + p.login,
bio = GhBioWidget(p);
UserItem.gitlab({
@required this.login,
@required this.name,

View File

@ -7,14 +7,14 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "14.0.0"
version: "7.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.41.1"
version: "0.39.17"
args:
dependency: transitive
description:
@ -22,13 +22,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.0"
artemis:
dependency: "direct main"
description:
name: artemis
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.1"
async:
dependency: transitive
description:
@ -49,14 +42,14 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.0"
version: "1.3.0"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.5"
version: "0.4.2"
build_daemon:
dependency: transitive
description:
@ -70,21 +63,21 @@ packages:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.1"
version: "1.3.11"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.11"
version: "1.10.2"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.5"
version: "6.0.1"
built_collection:
dependency: transitive
description:
@ -99,6 +92,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "7.1.0"
built_value_generator:
dependency: transitive
description:
name: built_value_generator
url: "https://pub.dartlang.org"
source: hosted
version: "7.1.0"
characters:
dependency: transitive
description:
@ -162,6 +162,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
csslib:
dependency: transitive
description:
name: csslib
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.2"
cupertino_icons:
dependency: "direct main"
description:
@ -175,14 +182,7 @@ packages:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.10"
equatable:
dependency: transitive
description:
name: equatable
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.5"
version: "1.3.6"
fake_async:
dependency: transitive
description:
@ -190,6 +190,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0-nullsafety.1"
ferry:
dependency: "direct main"
description:
name: ferry
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.2"
ferry_cache:
dependency: transitive
description:
name: ferry_cache
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
ferry_exec:
dependency: transitive
description:
name: ferry_exec
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2"
ferry_flutter:
dependency: "direct main"
description:
name: ferry_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.2"
ferry_generator:
dependency: "direct dev"
description:
name: ferry_generator
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.3"
ferry_store:
dependency: transitive
description:
name: ferry_store
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.2"
ffi:
dependency: transitive
description:
@ -315,20 +357,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.4"
gql_code_gen:
gql_build:
dependency: transitive
description:
name: gql_code_gen
name: gql_build
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
gql_dedupe_link:
version: "0.1.4+2"
gql_code_builder:
dependency: transitive
description:
name: gql_dedupe_link
name: gql_code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.9"
version: "0.1.4+1"
gql_exec:
dependency: transitive
description:
@ -337,19 +379,19 @@ packages:
source: hosted
version: "0.2.5"
gql_http_link:
dependency: transitive
dependency: "direct main"
description:
name: gql_http_link
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.7"
version: "0.3.2"
gql_link:
dependency: transitive
description:
name: gql_link
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.3"
version: "0.3.1"
graphs:
dependency: transitive
description:
@ -364,6 +406,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.0"
hive:
dependency: transitive
description:
name: hive
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.4+1"
html:
dependency: transitive
description:
name: html
url: "https://pub.dartlang.org"
source: hosted
version: "0.14.0+4"
http:
dependency: "direct main"
description:
@ -490,6 +546,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
normalize:
dependency: transitive
description:
name: normalize
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.6"
package_config:
dependency: transitive
description:
@ -629,7 +692,14 @@ packages:
name: recase
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "3.0.1"
rxdart:
dependency: transitive
description:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
version: "0.25.0"
share:
dependency: "direct main"
description:
@ -704,7 +774,7 @@ packages:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.10+1"
version: "0.9.7+1"
source_span:
dependency: transitive
description:

View File

@ -16,8 +16,9 @@ environment:
dependencies:
flutter:
sdk: flutter
artemis: ^3.2.1
cupertino_icons: ^1.0.0
ferry: ^0.9.2
ferry_flutter: ^0.3.2
file_icon: ^0.3.0
filesize: ^1.0.4
fimber: ^0.4.4
@ -26,8 +27,9 @@ dependencies:
flutter_markdown: ^0.4.4
flutter_svg: ^0.19.0
flutter_vector_icons: ^0.2.1
github: ^7.0.3
github: ^7.0.4
github_trending: ^1.0.0
gql_http_link: ^0.3.2
http: ^0.12.0
# in_app_review: ^1.0.4
intl: ^0.16.0
@ -52,7 +54,8 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.10.3
build_runner: ^1.10.0
ferry_generator: ^0.3.3
json_serializable: ^3.5.1
# dependencies_overrides: