refactor: table view

This commit is contained in:
Rongjian Zhang 2022-09-13 23:52:35 +08:00
parent 08f70164f4
commit aac5fb866b
10 changed files with 133 additions and 135 deletions

View File

@ -1,15 +1,17 @@
import 'dart:convert';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:universal_io/io.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/bitbucket.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/action_entry.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/blob_view.dart';
import 'package:git_touch/widgets/object_tree.dart';
import 'package:git_touch/widgets/table_view.dart';
import 'package:path/path.dart';
import 'package:provider/provider.dart';
import 'package:path/path.dart' as p;
import 'package:universal_io/io.dart';
class BbObjectScreen extends StatelessWidget {
final String owner;
@ -52,13 +54,15 @@ class BbObjectScreen extends StatelessWidget {
if (pl is String) {
return BlobView(path, text: pl);
} else if (pl is BbTree) {
return ObjectTreeItem(
name: p.basename(pl.path),
type: pl.type,
// size: v.type == 'commit_file' ? v.size : null,
size: pl.size,
url: '/bitbucket/$owner/$name/src/$ref?path=${pl.path.urlencode}',
downloadUrl: pl.links!['self']['href'] as String?,
return TableViewItemWidget(
createObjectTreeItem(
name: basename(pl.path),
type: pl.type,
// size: v.type == 'commit_file' ? v.size : null,
size: pl.size,
url: '/bitbucket/$owner/$name/src/$ref?path=${pl.path.urlencode}',
downloadUrl: pl.links!['self']['href'] as String?,
),
);
} else {
return Container();

View File

@ -1,14 +1,14 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/S.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/gitee.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/object_tree.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/widgets/table_view.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/S.dart';
class GeTreeScreen extends StatelessWidget {
final String owner;
@ -34,21 +34,16 @@ class GeTreeScreen extends StatelessWidget {
return TableView(
items: [
for (var item in data)
ObjectTreeItem(
createObjectTreeItem(
type: item.type,
name: item.path,
size: item.size,
downloadUrl: '', // TODO:
url: (() {
switch (item.type) {
case 'tree':
return '/gitee/$owner/$name/tree/${item.sha}?path=${item.path.urlencode}';
case 'blob':
return '/gitee/$owner/$name/blob/${item.sha}?path=${item.path.urlencode}';
default:
return null;
}
})(),
url: item.type == 'tree'
? '/gitee/$owner/$name/tree/${item.sha}?path=${item.path.urlencode}'
: item.type == 'blob'
? '/gitee/$owner/$name/blob/${item.sha}?path=${item.path.urlencode}'
: '',
)
],
);

View File

@ -39,7 +39,7 @@ class GhGistsFilesScreen extends StatelessWidget {
'content': v.text,
},
).toString();
return ObjectTreeItem(
return createObjectTreeItem(
url: uri,
type: 'file',
name: v.name ?? '',

View File

@ -1,12 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/action_entry.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/blob_view.dart';
import 'package:git_touch/widgets/object_tree.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/widgets/table_view.dart';
import 'package:github/github.dart';
import 'package:provider/provider.dart';
@ -69,7 +69,7 @@ class GhObjectScreen extends StatelessWidget {
...(v.downloadUrl == null ? {} : {'raw': v.downloadUrl}),
},
).toString();
return ObjectTreeItem(
return createObjectTreeItem(
name: v.name ?? '',
type: v.type ?? '',
url: uri.toString(),

View File

@ -1,12 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/S.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/gitlab.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/object_tree.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/widgets/table_view.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/S.dart';
class GlTreeScreen extends StatelessWidget {
final int id;
@ -37,21 +38,18 @@ class GlTreeScreen extends StatelessWidget {
);
},
itemBuilder: (item) {
return ObjectTreeItem(
type: item.type,
name: item.name,
downloadUrl:
'${auth.activeAccount!.domain}/api/v4/projects/$id/repository/files/${item.path.urlencode}/raw?ref=master', // TODO:
url: (() {
switch (item.type) {
case 'tree':
return '/gitlab/projects/$id/tree/$ref?path=${item.path.urlencode}';
case 'blob':
return '/gitlab/projects/$id/blob/$ref?path=${item.path.urlencode}';
default:
return null;
}
})(),
return TableViewItemWidget(
createObjectTreeItem(
type: item.type,
name: item.name,
downloadUrl:
'${auth.activeAccount!.domain}/api/v4/projects/$id/repository/files/${item.path.urlencode}/raw?ref=master', // TODO:
url: item.type == 'tree'
? '/gitlab/projects/$id/tree/$ref?path=${item.path.urlencode}'
: item.type == 'blob'
? '/gitlab/projects/$id/blob/$ref?path=${item.path.urlencode}'
: '',
),
);
},
);

View File

@ -47,7 +47,7 @@ class GoObjectScreen extends StatelessWidget {
});
return TableView(items: [
for (var v in items)
ObjectTreeItem(
createObjectTreeItem(
name: v.name,
type: v.type,
size: v.type == 'file' ? v.size : null,

View File

@ -46,7 +46,7 @@ class GtObjectScreen extends StatelessWidget {
});
return TableView(items: [
for (var v in items)
ObjectTreeItem(
createObjectTreeItem(
name: v.name,
type: v.type,
size: v.type == 'file' ? v.size : null,

View File

@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/S.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/code.dart';
import 'package:git_touch/models/theme.dart';
@ -13,7 +14,6 @@ import 'package:launch_review/launch_review.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart';
import 'package:flutter_gen/gen_l10n/S.dart';
class SettingsScreen extends StatelessWidget {
@override
@ -203,9 +203,8 @@ class SettingsScreen extends StatelessWidget {
TableViewItem(
text: Text(AppLocalizations.of(context)!.submitAnIssue),
rightWidget: const Text('git-touch/git-touch'),
url: '${auth.activeAccount!.platform == PlatformType.github
? '/github'
: 'https://github.com'}/git-touch/git-touch/issues/new',
url:
'${auth.activeAccount!.platform == PlatformType.github ? '/github' : 'https://github.com'}/git-touch/git-touch/issues/new',
),
TableViewItem(
text: Text(AppLocalizations.of(context)!.rateThisApp),
@ -241,9 +240,8 @@ class SettingsScreen extends StatelessWidget {
TableViewItem(
text: Text(AppLocalizations.of(context)!.sourceCode),
rightWidget: const Text('git-touch/git-touch'),
url: '${auth.activeAccount!.platform == PlatformType.github
? '/github'
: 'https://github.com'}/git-touch/git-touch',
url:
'${auth.activeAccount!.platform == PlatformType.github ? '/github' : 'https://github.com'}/git-touch/git-touch',
),
],
),

View File

@ -1,72 +1,61 @@
import 'package:file_icon/file_icon.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/table_view.dart';
import 'package:primer/primer.dart';
import 'package:file_icon/file_icon.dart';
class ObjectTreeItem extends StatelessWidget {
final String type;
final String name;
final int? size;
final String? url;
final String? downloadUrl;
const ObjectTreeItem({
required this.type,
required this.name,
this.size,
this.url,
this.downloadUrl,
});
Widget _buildIcon() {
switch (type) {
case 'blob': // github gql, gitlab
case 'file': // github rest, gitea
case 'commit_file': // bitbucket
return FileIcon(name, size: 36);
case 'tree': // github gql, gitlab
case 'dir': // github rest, gitea
case 'commit_directory': // bitbucket
return const Icon(
Octicons.file_directory,
color: PrimerColors.blue300,
size: 24,
);
case 'commit':
return const Icon(
Octicons.file_submodule,
color: PrimerColors.blue300,
size: 24,
);
default:
throw 'object type error';
}
}
@override
Widget build(BuildContext context) {
return TableViewItem(
leftWidget: _buildIcon(),
text: Text(name),
rightWidget: size == null ? null : Text(filesize(size)),
url: [
// Let system browser handle these files
//
// TODO:
// Unhandled Exception: PlatformException(Error, Error while launching
// https://github.com/flutter/flutter/issues/49162
// Docs
'pdf', 'docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls',
// Fonts
'ttf', 'otf', 'eot', 'woff', 'woff2',
'svg',
].contains(name.ext)
? downloadUrl
: url,
hideRightChevron: size != null,
);
Widget _buildIcon(String type, String name) {
switch (type) {
case 'blob': // github gql, gitlab
case 'file': // github rest, gitea
case 'commit_file': // bitbucket
return FileIcon(name, size: 36);
case 'tree': // github gql, gitlab
case 'dir': // github rest, gitea
case 'commit_directory': // bitbucket
return const Icon(
Octicons.file_directory,
color: PrimerColors.blue300,
size: 24,
);
case 'commit':
return const Icon(
Octicons.file_submodule,
color: PrimerColors.blue300,
size: 24,
);
default:
throw 'object type error';
}
}
TableViewItem createObjectTreeItem({
required String name,
required String type,
required String url,
String? downloadUrl,
int? size,
}) {
return TableViewItem(
leftWidget: _buildIcon(type, name),
text: Text(name),
rightWidget: size == null ? null : Text(filesize(size)),
url: [
// Let system browser handle these files
//
// TODO:
// Unhandled Exception: PlatformException(Error, Error while launching
// https://github.com/flutter/flutter/issues/49162
// Docs
'pdf', 'docx', 'doc', 'pptx', 'ppt', 'xlsx', 'xls',
// Fonts
'ttf', 'otf', 'eot', 'woff', 'woff2',
'svg',
].contains(name.ext)
? downloadUrl
: url,
hideRightChevron: size != null,
);
}

View File

@ -1,15 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/border_view.dart';
import 'package:git_touch/widgets/link.dart';
import 'package:provider/provider.dart';
import 'link.dart';
class TableViewHeader extends StatelessWidget {
final String? title;
const TableViewHeader(this.title);
const TableViewHeader(this.title, {super.key});
@override
Widget build(BuildContext context) {
@ -24,7 +24,7 @@ class TableViewHeader extends StatelessWidget {
}
}
class TableViewItem extends StatelessWidget {
class TableViewItem {
final Widget text;
final IconData? leftIconData;
final Widget? leftWidget;
@ -42,14 +42,20 @@ class TableViewItem extends StatelessWidget {
this.url,
this.hideRightChevron = false,
}) : assert(leftIconData == null || leftWidget == null);
}
class TableViewItemWidget extends StatelessWidget {
const TableViewItemWidget(this.item, {super.key});
final TableViewItem item;
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
return LinkWidget(
onTap: onTap,
url: url,
onTap: item.onTap,
url: item.url,
child: DefaultTextStyle(
style: TextStyle(fontSize: 17, color: theme.palette.text),
overflow: TextOverflow.ellipsis,
@ -58,27 +64,30 @@ class TableViewItem extends StatelessWidget {
child: Row(
children: [
SizedBox(
width: (leftWidget == null && leftIconData == null) ? 12 : 44,
width: (item.leftWidget == null && item.leftIconData == null)
? 12
: 44,
child: Center(
child: leftWidget ??
child: item.leftWidget ??
Icon(
leftIconData,
item.leftIconData,
color: theme.palette.primary,
size: 20,
)),
),
Expanded(child: text),
if (rightWidget != null) ...[
Expanded(child: item.text),
if (item.rightWidget != null) ...[
DefaultTextStyle(
style: TextStyle(
fontSize: 17,
color: theme.palette.tertiaryText,
),
child: rightWidget!,
child: item.rightWidget!,
),
const SizedBox(width: 6)
],
if ((onTap != null || url != null) && !hideRightChevron)
if ((item.onTap != null || item.url != null) &&
!item.hideRightChevron)
Icon(Ionicons.chevron_forward,
size: 20, color: theme.palette.tertiaryText)
else
@ -94,10 +103,15 @@ class TableViewItem extends StatelessWidget {
class TableView extends StatelessWidget {
final String? headerText;
final Iterable<Widget> items;
final Iterable<TableViewItem> items;
final bool? hasIcon;
const TableView({this.headerText, required this.items, this.hasIcon = true});
const TableView({
super.key,
this.headerText,
required this.items,
this.hasIcon = true,
});
double get _leftPadding => hasIcon == true ? 44 : 12;
@ -109,7 +123,7 @@ class TableView extends StatelessWidget {
if (headerText != null) TableViewHeader(headerText),
...join(
BorderView(leftPadding: _leftPadding),
items.toList(),
[for (final item in items) TableViewItemWidget(item)],
),
CommonStyle.border,
],