From bd56d64972370e1079f7b7999ebc6dd84720fa67 Mon Sep 17 00:00:00 2001 From: Rongjian Zhang Date: Sat, 7 Dec 2019 16:39:56 +0800 Subject: [PATCH] refactor: object screen types --- build.yaml | 5 + lib/graphql/github_object.dart | 412 ++++++++++++++++++++++++++++++ lib/graphql/github_object.g.dart | 205 +++++++++++++++ lib/graphql/github_object.graphql | 16 ++ lib/screens/object.dart | 191 ++++++-------- 5 files changed, 723 insertions(+), 106 deletions(-) create mode 100644 lib/graphql/github_object.dart create mode 100644 lib/graphql/github_object.g.dart create mode 100644 lib/graphql/github_object.graphql diff --git a/build.yaml b/build.yaml index 46d85d3..f7cbb4b 100644 --- a/build.yaml +++ b/build.yaml @@ -34,6 +34,11 @@ targets: queries_glob: lib/graphql/github_repository.graphql resolve_type_field: __typename add_query_prefix: true + - schema: lib/github.schema.json + output: lib/graphql/github_object.dart + queries_glob: lib/graphql/github_object.graphql + resolve_type_field: __typename + add_query_prefix: true scalar_mapping: - graphql_type: URI dart_type: String diff --git a/lib/graphql/github_object.dart b/lib/graphql/github_object.dart new file mode 100644 index 0000000..37f68f2 --- /dev/null +++ b/lib/graphql/github_object.dart @@ -0,0 +1,412 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +import 'package:artemis/artemis.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:equatable/equatable.dart'; +import 'package:gql/ast.dart'; +part 'github_object.g.dart'; + +@JsonSerializable(explicitToJson: true) +class GithubObject with EquatableMixin { + GithubObject(); + + factory GithubObject.fromJson(Map json) => + _$GithubObjectFromJson(json); + + GithubObjectRepository repository; + + @override + List get props => [repository]; + Map toJson() => _$GithubObjectToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectRepository extends GithubObjectPinnableItem + with EquatableMixin + implements + GithubObjectNode, + GithubObjectProjectOwner, + GithubObjectRegistryPackageOwner, + GithubObjectRegistryPackageSearch, + GithubObjectSubscribable, + GithubObjectStarrable, + GithubObjectUniformResourceLocatable, + GithubObjectRepositoryInfo { + GithubObjectRepository(); + + factory GithubObjectRepository.fromJson(Map json) => + _$GithubObjectRepositoryFromJson(json); + + GithubObjectGitObject object; + + @override + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [object, resolveType]; + Map toJson() => _$GithubObjectRepositoryToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectGitObject with EquatableMixin { + GithubObjectGitObject(); + + factory GithubObjectGitObject.fromJson(Map json) { + switch (json['__typename'].toString()) { + case 'Tree': + return GithubObjectTree.fromJson(json); + case 'Blob': + return GithubObjectBlob.fromJson(json); + default: + } + return _$GithubObjectGitObjectFromJson(json); + } + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() { + switch (resolveType) { + case 'Tree': + return (this as GithubObjectTree).toJson(); + case 'Blob': + return (this as GithubObjectBlob).toJson(); + default: + } + return _$GithubObjectGitObjectToJson(this); + } +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectTree + with EquatableMixin + implements GithubObjectNode, GithubObjectGitObject { + GithubObjectTree(); + + factory GithubObjectTree.fromJson(Map json) => + _$GithubObjectTreeFromJson(json); + + List entries; + + @override + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [entries, resolveType]; + Map toJson() => _$GithubObjectTreeToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectTreeEntry with EquatableMixin { + GithubObjectTreeEntry(); + + factory GithubObjectTreeEntry.fromJson(Map json) => + _$GithubObjectTreeEntryFromJson(json); + + String type; + + String name; + + @override + List get props => [type, name]; + Map toJson() => _$GithubObjectTreeEntryToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectNode with EquatableMixin { + GithubObjectNode(); + + factory GithubObjectNode.fromJson(Map json) => + _$GithubObjectNodeFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => _$GithubObjectNodeToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectBlob + with EquatableMixin + implements GithubObjectNode, GithubObjectGitObject { + GithubObjectBlob(); + + factory GithubObjectBlob.fromJson(Map json) => + _$GithubObjectBlobFromJson(json); + + String text; + + @override + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [text, resolveType]; + Map toJson() => _$GithubObjectBlobToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectPinnableItem with EquatableMixin { + GithubObjectPinnableItem(); + + factory GithubObjectPinnableItem.fromJson(Map json) => + _$GithubObjectPinnableItemFromJson(json); + + @override + List get props => []; + Map toJson() => _$GithubObjectPinnableItemToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectProjectOwner with EquatableMixin { + GithubObjectProjectOwner(); + + factory GithubObjectProjectOwner.fromJson(Map json) => + _$GithubObjectProjectOwnerFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => _$GithubObjectProjectOwnerToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectRegistryPackageOwner with EquatableMixin { + GithubObjectRegistryPackageOwner(); + + factory GithubObjectRegistryPackageOwner.fromJson( + Map json) => + _$GithubObjectRegistryPackageOwnerFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => + _$GithubObjectRegistryPackageOwnerToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectRegistryPackageSearch with EquatableMixin { + GithubObjectRegistryPackageSearch(); + + factory GithubObjectRegistryPackageSearch.fromJson( + Map json) => + _$GithubObjectRegistryPackageSearchFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => + _$GithubObjectRegistryPackageSearchToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectSubscribable with EquatableMixin { + GithubObjectSubscribable(); + + factory GithubObjectSubscribable.fromJson(Map json) => + _$GithubObjectSubscribableFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => _$GithubObjectSubscribableToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectStarrable with EquatableMixin { + GithubObjectStarrable(); + + factory GithubObjectStarrable.fromJson(Map json) => + _$GithubObjectStarrableFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => _$GithubObjectStarrableToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectUniformResourceLocatable with EquatableMixin { + GithubObjectUniformResourceLocatable(); + + factory GithubObjectUniformResourceLocatable.fromJson( + Map json) => + _$GithubObjectUniformResourceLocatableFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => + _$GithubObjectUniformResourceLocatableToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectRepositoryInfo with EquatableMixin { + GithubObjectRepositoryInfo(); + + factory GithubObjectRepositoryInfo.fromJson(Map json) => + _$GithubObjectRepositoryInfoFromJson(json); + + @JsonKey(name: '__typename') + String resolveType; + + @override + List get props => [resolveType]; + Map toJson() => _$GithubObjectRepositoryInfoToJson(this); +} + +@JsonSerializable(explicitToJson: true) +class GithubObjectArguments extends JsonSerializable with EquatableMixin { + GithubObjectArguments({this.owner, this.name, this.expression}); + + factory GithubObjectArguments.fromJson(Map json) => + _$GithubObjectArgumentsFromJson(json); + + final String owner; + + final String name; + + final String expression; + + @override + List get props => [owner, name, expression]; + Map toJson() => _$GithubObjectArgumentsToJson(this); +} + +class GithubObjectQuery + extends GraphQLQuery { + GithubObjectQuery({this.variables}); + + @override + final DocumentNode document = DocumentNode(definitions: [ + OperationDefinitionNode( + type: OperationType.query, + name: null, + variableDefinitions: [ + VariableDefinitionNode( + variable: VariableNode(name: NameNode(value: 'owner')), + type: NamedTypeNode( + name: NameNode(value: 'String'), isNonNull: true), + defaultValue: DefaultValueNode(value: null), + directives: []), + VariableDefinitionNode( + variable: VariableNode(name: NameNode(value: 'name')), + type: NamedTypeNode( + name: NameNode(value: 'String'), isNonNull: true), + defaultValue: DefaultValueNode(value: null), + directives: []), + VariableDefinitionNode( + variable: VariableNode(name: NameNode(value: 'expression')), + type: NamedTypeNode( + name: NameNode(value: 'String'), isNonNull: true), + defaultValue: DefaultValueNode(value: null), + directives: []) + ], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'repository'), + alias: null, + arguments: [ + ArgumentNode( + name: NameNode(value: 'owner'), + value: VariableNode(name: NameNode(value: 'owner'))), + ArgumentNode( + name: NameNode(value: 'name'), + value: VariableNode(name: NameNode(value: 'name'))) + ], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'object'), + alias: null, + arguments: [ + ArgumentNode( + name: NameNode(value: 'expression'), + value: + VariableNode(name: NameNode(value: 'expression'))) + ], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: '__typename'), + alias: null, + arguments: [], + directives: [], + selectionSet: null), + InlineFragmentNode( + typeCondition: TypeConditionNode( + on: NamedTypeNode( + name: NameNode(value: 'Tree'), + isNonNull: false)), + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'entries'), + alias: null, + arguments: [], + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'type'), + alias: null, + arguments: [], + directives: [], + selectionSet: null), + FieldNode( + name: NameNode(value: 'name'), + alias: null, + arguments: [], + directives: [], + selectionSet: null) + ])) + ])), + InlineFragmentNode( + typeCondition: TypeConditionNode( + on: NamedTypeNode( + name: NameNode(value: 'Blob'), + isNonNull: false)), + directives: [], + selectionSet: SelectionSetNode(selections: [ + FieldNode( + name: NameNode(value: 'text'), + alias: null, + arguments: [], + directives: [], + selectionSet: null) + ])) + ])) + ])) + ])) + ]); + + @override + final String operationName = 'github_object'; + + @override + final GithubObjectArguments variables; + + @override + List get props => [document, operationName, variables]; + @override + GithubObject parse(Map json) => GithubObject.fromJson(json); +} diff --git a/lib/graphql/github_object.g.dart b/lib/graphql/github_object.g.dart new file mode 100644 index 0000000..e0fd993 --- /dev/null +++ b/lib/graphql/github_object.g.dart @@ -0,0 +1,205 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'github_object.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +GithubObject _$GithubObjectFromJson(Map json) { + return GithubObject() + ..repository = json['repository'] == null + ? null + : GithubObjectRepository.fromJson( + json['repository'] as Map); +} + +Map _$GithubObjectToJson(GithubObject instance) => + { + 'repository': instance.repository?.toJson(), + }; + +GithubObjectRepository _$GithubObjectRepositoryFromJson( + Map json) { + return GithubObjectRepository() + ..object = json['object'] == null + ? null + : GithubObjectGitObject.fromJson(json['object'] as Map) + ..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectRepositoryToJson( + GithubObjectRepository instance) => + { + 'object': instance.object?.toJson(), + '__typename': instance.resolveType, + }; + +GithubObjectGitObject _$GithubObjectGitObjectFromJson( + Map json) { + return GithubObjectGitObject()..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectGitObjectToJson( + GithubObjectGitObject instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectTree _$GithubObjectTreeFromJson(Map json) { + return GithubObjectTree() + ..entries = (json['entries'] as List) + ?.map((e) => e == null + ? null + : GithubObjectTreeEntry.fromJson(e as Map)) + ?.toList() + ..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectTreeToJson(GithubObjectTree instance) => + { + 'entries': instance.entries?.map((e) => e?.toJson())?.toList(), + '__typename': instance.resolveType, + }; + +GithubObjectTreeEntry _$GithubObjectTreeEntryFromJson( + Map json) { + return GithubObjectTreeEntry() + ..type = json['type'] as String + ..name = json['name'] as String; +} + +Map _$GithubObjectTreeEntryToJson( + GithubObjectTreeEntry instance) => + { + 'type': instance.type, + 'name': instance.name, + }; + +GithubObjectNode _$GithubObjectNodeFromJson(Map json) { + return GithubObjectNode()..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectNodeToJson(GithubObjectNode instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectBlob _$GithubObjectBlobFromJson(Map json) { + return GithubObjectBlob() + ..text = json['text'] as String + ..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectBlobToJson(GithubObjectBlob instance) => + { + 'text': instance.text, + '__typename': instance.resolveType, + }; + +GithubObjectPinnableItem _$GithubObjectPinnableItemFromJson( + Map json) { + return GithubObjectPinnableItem(); +} + +Map _$GithubObjectPinnableItemToJson( + GithubObjectPinnableItem instance) => + {}; + +GithubObjectProjectOwner _$GithubObjectProjectOwnerFromJson( + Map json) { + return GithubObjectProjectOwner()..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectProjectOwnerToJson( + GithubObjectProjectOwner instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectRegistryPackageOwner _$GithubObjectRegistryPackageOwnerFromJson( + Map json) { + return GithubObjectRegistryPackageOwner() + ..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectRegistryPackageOwnerToJson( + GithubObjectRegistryPackageOwner instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectRegistryPackageSearch _$GithubObjectRegistryPackageSearchFromJson( + Map json) { + return GithubObjectRegistryPackageSearch() + ..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectRegistryPackageSearchToJson( + GithubObjectRegistryPackageSearch instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectSubscribable _$GithubObjectSubscribableFromJson( + Map json) { + return GithubObjectSubscribable()..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectSubscribableToJson( + GithubObjectSubscribable instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectStarrable _$GithubObjectStarrableFromJson( + Map json) { + return GithubObjectStarrable()..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectStarrableToJson( + GithubObjectStarrable instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectUniformResourceLocatable + _$GithubObjectUniformResourceLocatableFromJson(Map json) { + return GithubObjectUniformResourceLocatable() + ..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectUniformResourceLocatableToJson( + GithubObjectUniformResourceLocatable instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectRepositoryInfo _$GithubObjectRepositoryInfoFromJson( + Map json) { + return GithubObjectRepositoryInfo() + ..resolveType = json['__typename'] as String; +} + +Map _$GithubObjectRepositoryInfoToJson( + GithubObjectRepositoryInfo instance) => + { + '__typename': instance.resolveType, + }; + +GithubObjectArguments _$GithubObjectArgumentsFromJson( + Map json) { + return GithubObjectArguments( + owner: json['owner'] as String, + name: json['name'] as String, + expression: json['expression'] as String, + ); +} + +Map _$GithubObjectArgumentsToJson( + GithubObjectArguments instance) => + { + 'owner': instance.owner, + 'name': instance.name, + 'expression': instance.expression, + }; diff --git a/lib/graphql/github_object.graphql b/lib/graphql/github_object.graphql new file mode 100644 index 0000000..15d754e --- /dev/null +++ b/lib/graphql/github_object.graphql @@ -0,0 +1,16 @@ +query($owner: String!, $name: String!, $expression: String!) { + repository(owner: $owner, name: $name) { + object(expression: $expression) { + __typename + ... on Tree { + entries { + type + name + } + } + ... on Blob { + text + } + } + } +} diff --git a/lib/screens/object.dart b/lib/screens/object.dart index 1f0ac3e..c718e7a 100644 --- a/lib/screens/object.dart +++ b/lib/screens/object.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter_highlight/theme_map.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:git_touch/graphql/github_object.dart'; import 'package:git_touch/models/code.dart'; import 'package:git_touch/models/theme.dart'; import 'package:git_touch/scaffolds/refresh_stateful.dart'; @@ -45,93 +46,21 @@ class ObjectScreen extends StatelessWidget { static const _iconDefaultColor = PrimerColors.blue300; - Widget _buildIcon(item) { - switch (item['type']) { + Widget _buildIcon(GithubObjectTreeEntry item) { + switch (item.type) { case 'blob': - return SetiIcon(item['name'], size: 36); + return SetiIcon(item.name, size: 36); case 'tree': case 'commit': return Icon( - item['type'] == 'tree' + item.type == 'tree' ? Octicons.file_directory : Octicons.file_submodule, color: _iconDefaultColor, size: 24, ); default: - throw 'Should not be here'; - } - } - - String get _subQuery { - switch (type) { - case 'tree': - return ''' -... on Tree { - entries { - type - name - } -} -'''; - case 'blob': - default: - return ''' -... on Blob { - text -} -'''; - } - } - - Widget _buildTree(payload) { - var entries = payload['entries'] as List; - return TableView( - hasIcon: true, - items: entries.map((item) { - return TableViewItem( - leftWidget: _buildIcon(item), - text: Text(item['name']), - screenBuilder: (_) { - if (item['type'] == 'commit') return null; - return ObjectScreen( - owner, - name, - branch, - paths: [...paths, item['name']], - type: item['type'], - ); - }, - ); - }), - ); - } - - Widget _buildBlob(BuildContext context, payload) { - var codeProvider = Provider.of(context); - switch (_extname) { - case 'md': - case 'markdown': - return Padding( - padding: CommonStyle.padding, - child: MarkdownView(payload['text'], - basePaths: [owner, name, branch, ...paths]), - ); - case 'svg': - return SvgPicture.network(rawUrl); - default: - return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: HighlightView( - payload['text'], - language: _language, - theme: themeMap[codeProvider.theme], - padding: CommonStyle.padding, - textStyle: TextStyle( - fontSize: codeProvider.fontSize.toDouble(), - fontFamily: codeProvider.fontFamilyUsed), - ), - ); + return null; } } @@ -143,41 +72,46 @@ class ObjectScreen extends StatelessWidget { return ImageViewScreen(rawUrl, title: Text(paths.last)); } - return RefreshStatefulScaffold( + return RefreshStatefulScaffold( title: AppBarTitle(_path.isEmpty ? 'Files' : _path), fetchData: () async { - var data = await Provider.of(context).query('''{ - repository(owner: "$owner", name: "$name") { - object(expression: "$_expression") { - $_subQuery - } - } -}'''); + final res = await Provider.of(context) + .gqlClient + .execute(GithubObjectQuery( + variables: GithubObjectArguments( + owner: owner, + name: name, + expression: _expression, + ), + )); + return res.data.repository.object; - if (type == 'tree') { - var entries = data['repository']['object']['entries'] as List; - entries.sort((a, b) { - if (a['type'] == 'tree' && b['type'] == 'blob') { - return -1; - } - if (a['type'] == 'blob' && b['type'] == 'tree') { - return 1; - } - return 0; - }); - } + // if (type == 'tree') { + // var entries = data['repository']['object']['entries'] as List; + // entries.sort((a, b) { + // if (a['type'] == 'tree' && b['type'] == 'blob') { + // return -1; + // } + // if (a['type'] == 'blob' && b['type'] == 'tree') { + // return 1; + // } + // return 0; + // }); + // } - return data['repository']['object']; + // return data['repository']['object']; }, actionBuilder: (data, _) { - switch (type) { - case 'blob': + if (data == null) return null; + switch (data.resolveType) { + case 'Blob': + final blob = data as GithubObjectBlob; return ActionEntry( iconData: Octicons.settings, onTap: () { if (data != null) { Provider.of(context).pushRoute( - context, (_) => CodeThemeScreen(data['text'], _language)); + context, (_) => CodeThemeScreen(blob.text, _language)); } }, ); @@ -186,11 +120,56 @@ class ObjectScreen extends StatelessWidget { } }, bodyBuilder: (data, _) { - switch (type) { - case 'tree': - return _buildTree(data); - case 'blob': - return _buildBlob(context, data); + switch (data.resolveType) { + case 'Tree': + final tree = data as GithubObjectTree; + return TableView( + hasIcon: true, + items: tree.entries.map((item) { + return TableViewItem( + leftWidget: _buildIcon(item), + text: Text(item.name), + screenBuilder: (_) { + if (item.type == 'commit') return null; + return ObjectScreen( + owner, + name, + branch, + paths: [...paths, item.name], + type: item.type, + ); + }, + ); + }), + ); + case 'Blob': + final codeProvider = Provider.of(context); + final text = (data as GithubObjectBlob).text; + switch (_extname) { + case 'md': + case 'markdown': + return Padding( + padding: CommonStyle.padding, + child: MarkdownView(text, + basePaths: [owner, name, branch, ...paths]), + ); + case 'svg': + return SvgPicture.network(rawUrl); + default: + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: HighlightView( + text, + language: _language, + theme: themeMap[codeProvider.theme], + padding: CommonStyle.padding, + textStyle: TextStyle( + fontSize: codeProvider.fontSize.toDouble(), + fontFamily: codeProvider.fontFamilyUsed), + ), + ); + } + break; default: return null; }