From d91ae0a21325330c5dd3de15aeb6ee72a1adaa85 Mon Sep 17 00:00:00 2001 From: Rongjian Zhang Date: Wed, 11 Dec 2019 23:58:25 +0800 Subject: [PATCH] feat(gitlab): blob screen --- lib/models/gitlab.dart | 10 ++++++ lib/models/gitlab.g.dart | 9 +++++ lib/screens/gitlab_blob.dart | 31 +++++++++++++++++ lib/screens/gitlab_tree.dart | 16 ++++++--- lib/widgets/blob_view.dart | 67 ++++++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 lib/screens/gitlab_blob.dart create mode 100644 lib/widgets/blob_view.dart diff --git a/lib/models/gitlab.dart b/lib/models/gitlab.dart index 17b755d..930b9ec 100644 --- a/lib/models/gitlab.dart +++ b/lib/models/gitlab.dart @@ -132,3 +132,13 @@ class GitlabTreeItem { factory GitlabTreeItem.fromJson(Map json) => _$GitlabTreeItemFromJson(json); } + +@JsonSerializable(fieldRename: FieldRename.snake) +class GitlabBlob { + String content; + + GitlabBlob(); + + factory GitlabBlob.fromJson(Map json) => + _$GitlabBlobFromJson(json); +} diff --git a/lib/models/gitlab.g.dart b/lib/models/gitlab.g.dart index 7beb8f7..d9fc58a 100644 --- a/lib/models/gitlab.g.dart +++ b/lib/models/gitlab.g.dart @@ -178,3 +178,12 @@ Map _$GitlabTreeItemToJson(GitlabTreeItem instance) => 'type': instance.type, 'path': instance.path, }; + +GitlabBlob _$GitlabBlobFromJson(Map json) { + return GitlabBlob()..content = json['content'] as String; +} + +Map _$GitlabBlobToJson(GitlabBlob instance) => + { + 'content': instance.content, + }; diff --git a/lib/screens/gitlab_blob.dart b/lib/screens/gitlab_blob.dart new file mode 100644 index 0000000..595a331 --- /dev/null +++ b/lib/screens/gitlab_blob.dart @@ -0,0 +1,31 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:git_touch/models/auth.dart'; +import 'package:git_touch/models/gitlab.dart'; +import 'package:git_touch/scaffolds/refresh_stateful.dart'; +import 'package:git_touch/widgets/app_bar_title.dart'; +import 'package:git_touch/widgets/blob_view.dart'; +import 'package:provider/provider.dart'; + +class GitlabBlobScreen extends StatelessWidget { + final int id; + final String path; + + GitlabBlobScreen(this.id, this.path); + + @override + Widget build(BuildContext context) { + return RefreshStatefulScaffold( + title: AppBarTitle(path), + fetchData: () async { + final res = await Provider.of(context).fetchGitlab( + '/projects/$id/repository/files/$path?ref=master'); // TODO: + return GitlabBlob.fromJson(res); + }, + bodyBuilder: (data, _) { + return BlobView(path, utf8.decode(base64.decode(data.content))); + }, + ); + } +} diff --git a/lib/screens/gitlab_tree.dart b/lib/screens/gitlab_tree.dart index 5de2137..6e36359 100644 --- a/lib/screens/gitlab_tree.dart +++ b/lib/screens/gitlab_tree.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:git_touch/models/gitlab.dart'; import 'package:git_touch/scaffolds/refresh_stateful.dart'; +import 'package:git_touch/screens/gitlab_blob.dart'; import 'package:git_touch/widgets/app_bar_title.dart'; import 'package:git_touch/widgets/table_view.dart'; import 'package:flutter/material.dart'; @@ -58,11 +59,16 @@ class GitlabTreeScreen extends StatelessWidget { leftWidget: _buildIcon(item), text: Text(item.path), screenBuilder: (_) { - if (item.type == 'commit') return null; - return GitlabTreeScreen( - id, - paths: [...paths, item.path], - ); + switch (item.type) { + case 'tree': + return GitlabTreeScreen( + id, + paths: [...paths, item.path], + ); + case 'blob': + return GitlabBlobScreen( + id, [...paths, item.path].join('/')); + } }, ); }), diff --git a/lib/widgets/blob_view.dart b/lib/widgets/blob_view.dart new file mode 100644 index 0000000..e1c45fc --- /dev/null +++ b/lib/widgets/blob_view.dart @@ -0,0 +1,67 @@ +import 'package:path/path.dart' as p; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_highlight/theme_map.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:git_touch/models/code.dart'; +import 'package:git_touch/models/theme.dart'; +import 'package:git_touch/widgets/markdown_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_highlight/flutter_highlight.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:provider/provider.dart'; +import 'package:git_touch/utils/utils.dart'; + +class BlobView extends StatelessWidget { + final String path; + final String payload; + + BlobView(this.path, this.payload); + + String get _extname { + var dotext = p.extension(path); + if (dotext.isEmpty) return ''; + return dotext.substring(1); + } + + String get _language => _extname.isEmpty ? 'plaintext' : _extname; + + @override + Widget build(BuildContext context) { + final codeProvider = Provider.of(context); + final theme = Provider.of(context); + + switch (_extname) { + // TODO: All image types + case 'png': + case 'jpg': + case 'jpeg': + case 'gif': + case 'webp': + return PhotoView( + imageProvider: NetworkImage(payload), + backgroundDecoration: BoxDecoration(color: theme.palette.background), + ); + case 'md': + case 'markdown': + return Padding( + padding: CommonStyle.padding, + child: MarkdownView(payload), // TODO: basePath + ); + case 'svg': + return SvgPicture.network(payload); + default: + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: HighlightView( + payload, + language: _language, + theme: themeMap[codeProvider.theme], + padding: CommonStyle.padding, + textStyle: TextStyle( + fontSize: codeProvider.fontSize.toDouble(), + fontFamily: codeProvider.fontFamilyUsed), + ), + ); + } + } +}