refactor: table view

This commit is contained in:
Rongjian Zhang 2019-09-14 23:48:01 +08:00
parent 8cd1d9f1a5
commit 124ec611ad
10 changed files with 140 additions and 162 deletions

View File

@ -139,7 +139,7 @@ class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
} }
if (index % 2 == 1) { if (index % 2 == 1) {
return BorderView(height: 1); return borderView;
} }
return widget.itemBuilder(items[index ~/ 2]); return widget.itemBuilder(items[index ~/ 2]);

View File

@ -103,7 +103,7 @@ class _LongListScaffoldState<T, K> extends State<LongListScaffold<T, K>> {
Widget _buildItem(BuildContext context, int index) { Widget _buildItem(BuildContext context, int index) {
if (index % 2 == 1) { if (index % 2 == 1) {
return BorderView(); return borderView;
} }
int realIndex = index ~/ 2; int realIndex = index ~/ 2;

View File

@ -393,7 +393,7 @@ mutation {
], ],
), ),
), ),
BorderView(), borderView,
], ],
); );
}, },

View File

@ -94,7 +94,7 @@ class ObjectScreen extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: join( children: join(
BorderView(), borderView,
entries.map((item) { entries.map((item) {
return Link( return Link(
screenBuilder: item['type'] == 'commit' screenBuilder: item['type'] == 'commit'

View File

@ -174,7 +174,7 @@ class RepoScreen extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
RepoItem(payload, inRepoScreen: true), RepoItem(payload, inRepoScreen: true),
BorderView(), borderView,
Row( Row(
children: <Widget>[ children: <Widget>[
EntryItem( EntryItem(
@ -202,7 +202,7 @@ class RepoScreen extends StatelessWidget {
), ),
], ],
), ),
BorderView(height: 10), borderView10,
Padding( Padding(
padding: const EdgeInsets.all(_languageBarPadding), padding: const EdgeInsets.all(_languageBarPadding),
child: ClipRRect( child: ClipRRect(
@ -224,16 +224,8 @@ class RepoScreen extends StatelessWidget {
TableViewItem( TableViewItem(
leftWidget: Icon(Octicons.code, size: 20), leftWidget: Icon(Octicons.code, size: 20),
text: Text('Code'), text: Text('Code'),
rightWidget: Row( rightWidget:
children: <Widget>[
Text(filesize(payload['languages']['totalSize'] as int)), Text(filesize(payload['languages']['totalSize'] as int)),
Icon(
CupertinoIcons.right_chevron,
size: 18,
color: PrimerColors.gray300,
),
],
),
screenBuilder: (_) => ObjectScreen( screenBuilder: (_) => ObjectScreen(
owner: owner, owner: owner,
name: name, name: name,
@ -243,52 +235,27 @@ class RepoScreen extends StatelessWidget {
TableViewItem( TableViewItem(
leftWidget: Icon(Octicons.issue_opened, size: 20), leftWidget: Icon(Octicons.issue_opened, size: 20),
text: Text('Issues'), text: Text('Issues'),
rightWidget: Row( rightWidget:
children: <Widget>[
Text(numberFormat.format(payload['issues']['totalCount'])), Text(numberFormat.format(payload['issues']['totalCount'])),
Icon(
CupertinoIcons.right_chevron,
size: 18,
color: PrimerColors.gray300,
),
],
),
screenBuilder: (_) => IssuesScreen(owner: owner, name: name), screenBuilder: (_) => IssuesScreen(owner: owner, name: name),
), ),
TableViewItem( TableViewItem(
leftWidget: Icon(Octicons.git_pull_request, size: 20), leftWidget: Icon(Octicons.git_pull_request, size: 20),
text: Text('Pull requests'), text: Text('Pull requests'),
rightWidget: Row( rightWidget: Text(
children: <Widget>[ numberFormat.format(payload['pullRequests']['totalCount'])),
Text(numberFormat
.format(payload['pullRequests']['totalCount'])),
Icon(
CupertinoIcons.right_chevron,
size: 18,
color: PrimerColors.gray300,
),
],
),
screenBuilder: (_) => screenBuilder: (_) =>
IssuesScreen(owner: owner, name: name, isPullRequest: true), IssuesScreen(owner: owner, name: name, isPullRequest: true),
), ),
]), ]),
BorderView(height: 10), borderView10,
TableView(items: [ TableView(items: [
TableViewItem( TableViewItem(
leftWidget: Icon(Octicons.history, size: 20), leftWidget: Icon(Octicons.history, size: 20),
text: Text('Commits'), text: Text('Commits'),
rightWidget: Row( rightWidget: Text(numberFormat.format(
children: <Widget>[ payload['defaultBranchRef']['target']['history']
Text(numberFormat.format(payload['defaultBranchRef'] ['totalCount'])),
['target']['history']['totalCount'])),
Icon(
CupertinoIcons.right_chevron,
size: 18,
color: PrimerColors.gray300,
),
],
),
screenBuilder: (_) => CommitsScreen(owner, name), screenBuilder: (_) => CommitsScreen(owner, name),
), ),
TableViewItem( TableViewItem(
@ -300,7 +267,7 @@ class RepoScreen extends StatelessWidget {
payload['licenseInfo']['name'])), payload['licenseInfo']['name'])),
), ),
]), ]),
BorderView(height: 10), borderView10,
if (payload['object'] != null) if (payload['object'] != null)
Container( Container(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),

View File

@ -11,15 +11,10 @@ import '../widgets/table_view.dart';
import '../screens/repo.dart'; import '../screens/repo.dart';
import '../screens/login.dart'; import '../screens/login.dart';
class SettingsScreen extends StatefulWidget { class SettingsScreen extends StatelessWidget {
@override
_SettingsScreenState createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
Widget _buildRightWidget(bool checked) { Widget _buildRightWidget(bool checked) {
if (!checked) return null; if (!checked) return null;
return Icon(Octicons.check, color: CupertinoColors.activeBlue, size: 20); return Icon(Octicons.check, color: CupertinoColors.activeBlue, size: 24);
} }
@override @override
@ -41,7 +36,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
TableViewSeperator(), TableViewSeperator(),
TableView(headerText: 'THEME', items: [ TableView(headerText: 'THEME', items: [
TableViewItem( TableViewItem(
text: Text('material'), leftIconData: MaterialCommunityIcons.material_design,
text: Text('Material'),
rightWidget: rightWidget:
_buildRightWidget(themeProvider.theme == ThemeMap.material), _buildRightWidget(themeProvider.theme == ThemeMap.material),
onTap: () { onTap: () {
@ -49,9 +45,11 @@ class _SettingsScreenState extends State<SettingsScreen> {
themeProvider.setTheme(ThemeMap.material); themeProvider.setTheme(ThemeMap.material);
} }
}, },
hideRightChevron: true,
), ),
TableViewItem( TableViewItem(
text: Text('cupertino'), leftIconData: MaterialCommunityIcons.apple,
text: Text('Cupertino'),
rightWidget: _buildRightWidget( rightWidget: _buildRightWidget(
themeProvider.theme == ThemeMap.cupertino), themeProvider.theme == ThemeMap.cupertino),
onTap: () { onTap: () {
@ -59,38 +57,36 @@ class _SettingsScreenState extends State<SettingsScreen> {
themeProvider.setTheme(ThemeMap.cupertino); themeProvider.setTheme(ThemeMap.cupertino);
} }
}, },
hideRightChevron: true,
), ),
]), ]),
TableViewSeperator(), TableViewSeperator(),
TableView(headerText: 'REVIEW', items: [ TableView(headerText: 'ABOUT', items: [
TableViewItem( TableViewItem(
text: Text('Review'), leftIconData: Octicons.repo,
text: Text('pd4d10/git-touch'),
screenBuilder: (_) => RepoScreen('pd4d10', 'git-touch'),
),
TableViewItem(
leftIconData: Octicons.star,
text: Text('Rate this App'),
onTap: () { onTap: () {
LaunchReview.launch( LaunchReview.launch(
androidAppId: 'io.github.pd4d10.gittouch', androidAppId: 'io.github.pd4d10.gittouch',
iOSAppId: '1452042346', iOSAppId: '1452042346',
); );
}, },
) ),
]),
TableViewSeperator(),
TableView(headerText: 'SOURCE CODE', items: [
TableViewItem( TableViewItem(
text: Text('pd4d10/git-touch'), leftIconData: Octicons.law,
screenBuilder: (_) => RepoScreen('pd4d10', 'git-touch'), text: Text('License'),
) rightWidget: Text('MIT'),
]),
TableViewSeperator(),
TableView(headerText: 'LICENSE', items: [
TableViewItem(
text: Text('MIT'),
onTap: () { onTap: () {
launch( launch(
'https://github.com/pd4d10/git-touch/blob/master/LICENSE'); 'https://github.com/pd4d10/git-touch/blob/master/LICENSE');
}, },
) )
]), ]),
TableViewSeperator(),
], ],
); );
}, },

View File

@ -48,7 +48,7 @@ class _TrendingScreenState extends State<TrendingScreen> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: join( children: join(
BorderView(), borderView,
payload.map<Widget>((item) => RepoItem(item)).toList(), payload.map<Widget>((item) => RepoItem(item)).toList(),
), ),
); );

View File

@ -85,10 +85,10 @@ class UserScreen extends StatelessWidget {
if (items.isEmpty) return []; if (items.isEmpty) return [];
return [ return [
BorderView(height: 10), borderView10,
// Text('Pinned repositories'), // Text('Pinned repositories'),
...join( ...join(
BorderView(), borderView,
items.map((item) { items.map((item) {
return RepoItem(item); return RepoItem(item);
}).toList(), }).toList(),
@ -96,25 +96,6 @@ class UserScreen extends StatelessWidget {
]; ];
} }
TableViewItem _buildTableViewItem({
IconData iconData,
String text,
Function onTap,
}) {
if (text == null || text.isEmpty) return null;
var leftWidget = Icon(iconData, size: 20, color: PrimerColors.blue500);
return TableViewItem(
leftWidget: leftWidget,
text: Text(text),
rightWidget: onTap == null
? null
: Icon(CupertinoIcons.right_chevron,
size: 18, color: PrimerColors.gray300),
onTap: onTap,
);
}
Widget _buildContributions(List<ContributionsInfo> contributions) { Widget _buildContributions(List<ContributionsInfo> contributions) {
var row = Row( var row = Row(
children: <Widget>[], children: <Widget>[],
@ -224,7 +205,7 @@ class UserScreen extends StatelessWidget {
bio: payload['bio'], bio: payload['bio'],
), ),
), ),
BorderView(), borderView,
Row(children: <Widget>[ Row(children: <Widget>[
EntryItem( EntryItem(
count: payload['repositories']['totalCount'], count: payload['repositories']['totalCount'],
@ -250,46 +231,45 @@ class UserScreen extends StatelessWidget {
login: login, type: UsersScreenType.userFollowing), login: login, type: UsersScreenType.userFollowing),
), ),
]), ]),
BorderView(height: 10), borderView10,
_buildContributions(contributions), _buildContributions(contributions),
BorderView(height: 10), borderView10,
TableView(items: [ TableView(items: [
_buildTableViewItem( if (isNotNullOrEmpty(payload['company']))
iconData: Octicons.organization, TableViewItem(
text: payload['company'], leftIconData: Octicons.organization,
), text: Text(payload['company']),
_buildTableViewItem( ),
iconData: Octicons.location, if (isNotNullOrEmpty(payload['location']))
text: payload['location'], TableViewItem(
onTap: payload['location'] == null leftIconData: Octicons.location,
? null text: Text(payload['location']),
: () { onTap: () {
launch('https://www.google.com/maps/place/' + launch('https://www.google.com/maps/place/' +
(payload['location'] as String) (payload['location'] as String)
.replaceAll(RegExp(r'\s+'), '')); .replaceAll(RegExp(r'\s+'), ''));
}), },
_buildTableViewItem( ),
iconData: Octicons.mail, if (isNotNullOrEmpty(payload['email']))
text: payload['email'], TableViewItem(
onTap: (payload['email'] as String).isEmpty leftIconData: Octicons.mail,
? null text: Text(payload['email']),
: () { onTap: () {
launch('mailto:' + payload['email']); launch('mailto:' + payload['email']);
}, },
), ),
_buildTableViewItem( if (isNotNullOrEmpty(payload['websiteUrl']))
iconData: Octicons.link, TableViewItem(
text: payload['websiteUrl'], leftIconData: Octicons.link,
onTap: payload['websiteUrl'] == null text: Text(payload['websiteUrl']),
? null onTap: () {
: () { var url = payload['websiteUrl'] as String;
var url = payload['websiteUrl'] as String; if (!url.startsWith('http')) {
if (!url.startsWith('http')) { url = 'http://$url';
url = 'http://$url'; }
} launch(url);
launch(url); },
}, ),
),
]), ]),
..._buildRepos(payload), ..._buildRepos(payload),
], ],

View File

@ -136,18 +136,38 @@ List<T> joinAll<T>(T seperator, List<List<T>> xss) {
final numberFormat = NumberFormat(); final numberFormat = NumberFormat();
bool isNotNullOrEmpty(String text) {
return text != null && text.isNotEmpty;
}
class BorderView extends StatelessWidget { class BorderView extends StatelessWidget {
final double height; final double height;
final Color color;
final double leftPadding;
BorderView({this.height = 1}); const BorderView({
this.height = 1,
this.color = PrimerColors.gray200,
this.leftPadding = 0,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return Row(
height: height, children: <Widget>[
child: const DecoratedBox( SizedBox(width: leftPadding),
decoration: const BoxDecoration(color: PrimerColors.gray100), Expanded(
), child: SizedBox(
height: height,
child: DecoratedBox(
decoration: BoxDecoration(color: color),
),
),
),
],
); );
} }
} }
const borderView = BorderView();
const borderView10 = BorderView(height: 20, color: PrimerColors.gray100);

View File

@ -16,18 +16,22 @@ class TableViewSeperator extends StatelessWidget {
class TableViewItem { class TableViewItem {
final Widget text; final Widget text;
final IconData leftIconData;
final Widget leftWidget; final Widget leftWidget;
final Widget rightWidget; final Widget rightWidget;
final void Function() onTap; final void Function() onTap;
final WidgetBuilder screenBuilder; final WidgetBuilder screenBuilder;
final bool hideRightChevron;
TableViewItem({ TableViewItem({
this.text, this.text,
this.leftIconData,
this.leftWidget, this.leftWidget,
this.rightWidget, this.rightWidget,
this.onTap, this.onTap,
this.screenBuilder, this.screenBuilder,
}); this.hideRightChevron = false,
}) : assert(leftIconData == null || leftWidget == null);
} }
class TableView extends StatelessWidget { class TableView extends StatelessWidget {
@ -36,29 +40,40 @@ class TableView extends StatelessWidget {
TableView({this.headerText, @required this.items}); TableView({this.headerText, @required this.items});
static final _border = BorderView();
static final _seperator = BorderView();
Widget _buildItem(TableViewItem item) { Widget _buildItem(TableViewItem item) {
if (item == null) return null; if (item == null) return null;
var widget = Container( var widget = DefaultTextStyle(
height: 44, style: TextStyle(fontSize: 16, color: PrimerColors.gray900),
child: Row(children: [ overflow: TextOverflow.ellipsis,
if (item.leftWidget != null) ...[ child: Container(
height: 44,
child: Row(children: [
if (item.leftIconData != null) ...[
SizedBox(width: 12),
Icon(item.leftIconData),
// Container(
// width: 24,
// height: 24,
// // decoration: BoxDecoration(
// // borderRadius: BorderRadius.circular(4), color: PrimerColors.blue400),
// child: Icon(iconData, size: 24, color: PrimerColors.gray600),
// )
],
if (item.leftWidget != null) ...[
SizedBox(width: 12),
item.leftWidget,
],
SizedBox(width: 12), SizedBox(width: 12),
item.leftWidget, Expanded(child: item.text),
], if (item.rightWidget != null) item.rightWidget,
SizedBox(width: 12), if ((item.onTap != null || item.screenBuilder != null) &
Expanded( !item.hideRightChevron)
child: DefaultTextStyle( Icon(CupertinoIcons.right_chevron,
child: item.text, size: 24, color: PrimerColors.gray400),
style: TextStyle(fontSize: 16, color: PrimerColors.gray900), SizedBox(width: 4),
), ]),
), ),
if (item.rightWidget != null) item.rightWidget,
SizedBox(width: 12),
]),
); );
if (item.onTap == null && item.screenBuilder == null) { if (item.onTap == null && item.screenBuilder == null) {
@ -85,9 +100,9 @@ class TableView extends StatelessWidget {
style: TextStyle(color: PrimerColors.gray600, fontSize: 13), style: TextStyle(color: PrimerColors.gray600, fontSize: 13),
), ),
), ),
_border, borderView,
...join(_seperator, items.map(_buildItem).toList()), ...join(BorderView(leftPadding: 44), items.map(_buildItem).toList()),
_border, borderView,
], ],
); );
} }