diff --git a/lib/models/github.dart b/lib/models/github.dart index df59706..7c9262f 100644 --- a/lib/models/github.dart +++ b/lib/models/github.dart @@ -235,3 +235,16 @@ class GithubTrendingUserRepo { factory GithubTrendingUserRepo.fromJson(Map json) => _$GithubTrendingUserRepoFromJson(json); } + +@JsonSerializable(fieldRename: FieldRename.snake) +class GithubTreeItem { + String name; + String path; + int size; + String type; + String downloadUrl; + String content; + GithubTreeItem(); + factory GithubTreeItem.fromJson(Map json) => + _$GithubTreeItemFromJson(json); +} diff --git a/lib/models/github.g.dart b/lib/models/github.g.dart index 1f81131..66c52a3 100644 --- a/lib/models/github.g.dart +++ b/lib/models/github.g.dart @@ -278,3 +278,23 @@ Map _$GithubTrendingUserRepoToJson( 'name': instance.name, 'description': instance.description, }; + +GithubTreeItem _$GithubTreeItemFromJson(Map json) { + return GithubTreeItem() + ..name = json['name'] as String + ..path = json['path'] as String + ..size = json['size'] as int + ..type = json['type'] as String + ..downloadUrl = json['download_url'] as String + ..content = json['content'] as String; +} + +Map _$GithubTreeItemToJson(GithubTreeItem instance) => + { + 'name': instance.name, + 'path': instance.path, + 'size': instance.size, + 'type': instance.type, + 'download_url': instance.downloadUrl, + 'content': instance.content, + }; diff --git a/lib/screens/object.dart b/lib/screens/object.dart index 463a66e..bab10b2 100644 --- a/lib/screens/object.dart +++ b/lib/screens/object.dart @@ -1,5 +1,5 @@ import 'package:flutter/cupertino.dart'; -import 'package:git_touch/graphql/gh.dart'; +import 'package:git_touch/models/github.dart'; import 'package:git_touch/models/theme.dart'; import 'package:git_touch/scaffolds/refresh_stateful.dart'; import 'package:git_touch/widgets/action_entry.dart'; @@ -28,86 +28,69 @@ class ObjectScreen extends StatelessWidget { final String path; ObjectScreen(this.owner, this.name, this.branch, {this.path}); - String get _pathNotNull => path ?? ''; - @override Widget build(BuildContext context) { - return RefreshStatefulScaffold( + return RefreshStatefulScaffold( // canRefresh: !_isImage, // TODO: title: AppBarTitle(path == null ? 'Files' : path), fetchData: () async { - final res = await Provider.of(context) - .gqlClient - .execute(GhObjectQuery( - variables: GhObjectArguments( - owner: owner, - name: name, - expression: '$branch:$_pathNotNull', - ), - )); - final data = res.data.repository.object; - if (data.resolveType == 'Tree') { - (data as GhObjectTree).entries.sort((a, b) { - return sortByKey('tree', a.type, b.type); - }); - } - return data; + final suffix = path == null ? '' : '/$path'; + final res = await Provider.of(context).getWithCredentials( + '/repos/$owner/$name/contents$suffix?ref=$branch'); + return res; }, actionBuilder: (data, _) { - switch (data.resolveType) { - case 'Blob': - final blob = data as GhObjectBlob; - final theme = Provider.of(context); - return ActionEntry( - iconData: Icons.settings, - onTap: () { - theme.push(context, '/choose-code-theme'); - }, - ); - default: - return null; + if (data is Map) { + final theme = Provider.of(context); + return ActionEntry( + iconData: Icons.settings, + onTap: () { + theme.push(context, '/choose-code-theme'); + }, + ); } }, bodyBuilder: (data, _) { - switch (data.resolveType) { - case 'Tree': - return ObjectTree( - items: (data as GhObjectTree).entries.map((v) { - // if (item.type == 'commit') return null; - String url; - var ext = p.extension(v.name); - if (ext.startsWith('.')) ext = ext.substring(1); - if (['pdf', 'docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls'] - .contains(ext)) { - // Let system browser handle these files - url = Uri.encodeFull( - 'https://raw.githubusercontent.com/$owner/$name/$branch/$path'); - } else { - url = - '/$owner/$name/blob/$branch?path=${p.join(_pathNotNull, v.name).urlencode}'; - } + if (data is List) { + final items = data.map((t) => GithubTreeItem.fromJson(t)).toList(); + items.sort((a, b) { + return sortByKey('dir', a.type, b.type); + }); + return ObjectTree( + items: items.map((v) { + // if (item.type == 'commit') return null; + String url; + var ext = p.extension(v.name); + if (ext.startsWith('.')) ext = ext.substring(1); + if (['pdf', 'docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls'] + .contains(ext)) { + // Let system browser handle these files + // + // TODO: + // Unhandled Exception: PlatformException(Error, Error while launching + // https://github.com/flutter/flutter/issues/49162 + url = v.downloadUrl; + } else { + url = '/$owner/$name/blob/$branch?path=${v.path.urlencode}'; + } - return ObjectTreeItem( - name: v.name, - type: v.type, - url: url, - size: v.object.resolveType == 'Blob' - ? (v.object as GhObjectBlob).byteSize - : null, - ); - }), - ); - case 'Blob': - // TODO: Markdown base path - // basePaths: [owner, name, branch, ...paths] - return BlobView( - path, - text: (data as GhObjectBlob).text, - networkUrl: Uri.encodeFull( - 'https://raw.githubusercontent.com/$owner/$name/$branch/$path'), // TODO: private - ); - default: - return null; + return ObjectTreeItem( + name: v.name, + type: v.type, + url: url, + size: v.type == 'file' ? v.size : null, + ); + }), + ); + } else { + // TODO: Markdown base path + // basePaths: [owner, name, branch, ...paths] + final v = GithubTreeItem.fromJson(data); + return BlobView( + path, + base64Text: v.content, + networkUrl: v.downloadUrl, + ); } }, ); diff --git a/lib/widgets/object_tree.dart b/lib/widgets/object_tree.dart index 949b59a..27e4cc6 100644 --- a/lib/widgets/object_tree.dart +++ b/lib/widgets/object_tree.dart @@ -24,11 +24,11 @@ class ObjectTree extends StatelessWidget { Widget _buildIcon(ObjectTreeItem item) { switch (item.type) { - case 'blob': - case 'file': // Gitea + case 'blob': // github gql + case 'file': // github rest, gitea return SetiIcon(item.name, size: 36); - case 'tree': - case 'dir': // Gitea + case 'tree': // github gql + case 'dir': // github rest, gitea return Icon( Octicons.file_directory, color: PrimerColors.blue300,