refactor: rename to tab scaffold
This commit is contained in:
parent
86e49d75cf
commit
d5363f613e
|
@ -8,16 +8,14 @@ import '../widgets/error_reload.dart';
|
|||
class RefreshScaffold<T> extends StatefulWidget {
|
||||
final Widget title;
|
||||
final Widget Function(T payload) bodyBuilder;
|
||||
final Future<T> Function(int activeTab) onRefresh;
|
||||
final Future<T> Function() onRefresh;
|
||||
final Widget Function(T payload) trailingBuilder;
|
||||
final List<String> tabs;
|
||||
|
||||
RefreshScaffold({
|
||||
@required this.title,
|
||||
@required this.bodyBuilder,
|
||||
@required this.onRefresh,
|
||||
this.trailingBuilder,
|
||||
this.tabs,
|
||||
});
|
||||
|
||||
@override
|
||||
|
@ -28,7 +26,6 @@ class _RefreshScaffoldState<T> extends State<RefreshScaffold<T>> {
|
|||
bool _loading;
|
||||
T _payload;
|
||||
String _error = '';
|
||||
int _activeTab = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -46,16 +43,13 @@ class _RefreshScaffoldState<T> extends State<RefreshScaffold<T>> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _refresh([int activeTab]) async {
|
||||
Future<void> _refresh() async {
|
||||
try {
|
||||
setState(() {
|
||||
_error = '';
|
||||
_loading = true;
|
||||
if (activeTab != null) {
|
||||
_activeTab = activeTab;
|
||||
}
|
||||
});
|
||||
_payload = await widget.onRefresh(activeTab);
|
||||
_payload = await widget.onRefresh();
|
||||
} catch (err) {
|
||||
_error = err.toString();
|
||||
throw err;
|
||||
|
@ -86,22 +80,8 @@ class _RefreshScaffoldState<T> extends State<RefreshScaffold<T>> {
|
|||
case AppThemeType.cupertino:
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: widget.tabs == null
|
||||
? widget.title
|
||||
: DefaultTextStyle(
|
||||
style: TextStyle(),
|
||||
child: CupertinoSegmentedControl(
|
||||
groupValue: _activeTab,
|
||||
onValueChanged: _refresh,
|
||||
children: widget.tabs.asMap().map((key, text) => MapEntry(
|
||||
key,
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Text(text),
|
||||
))),
|
||||
),
|
||||
),
|
||||
trailing: widget.tabs == null ? _buildTrailing() : null,
|
||||
middle: widget.title,
|
||||
trailing: _buildTrailing(),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: CustomScrollView(
|
||||
|
@ -113,28 +93,16 @@ class _RefreshScaffoldState<T> extends State<RefreshScaffold<T>> {
|
|||
),
|
||||
);
|
||||
default:
|
||||
var w = Scaffold(
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: widget.title,
|
||||
actions: _buildActions(),
|
||||
bottom: widget.tabs == null
|
||||
? null
|
||||
: TabBar(
|
||||
onTap: _refresh,
|
||||
tabs: widget.tabs
|
||||
.map((text) => Tab(text: text.toUpperCase()))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: _refresh,
|
||||
child: SingleChildScrollView(child: _buildBody()),
|
||||
),
|
||||
);
|
||||
if (widget.tabs == null) {
|
||||
return w;
|
||||
}
|
||||
return DefaultTabController(length: widget.tabs.length, child: w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/models/theme.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../widgets/loading.dart';
|
||||
import '../widgets/error_reload.dart';
|
||||
|
||||
class TabScaffold<T> extends StatefulWidget {
|
||||
final Widget title;
|
||||
final Widget Function(T payload) bodyBuilder;
|
||||
final Future<T> Function(int activeTab) onRefresh;
|
||||
final Widget Function(T payload) trailingBuilder;
|
||||
final List<String> tabs;
|
||||
|
||||
TabScaffold({
|
||||
@required this.title,
|
||||
@required this.bodyBuilder,
|
||||
@required this.onRefresh,
|
||||
this.trailingBuilder,
|
||||
this.tabs,
|
||||
});
|
||||
|
||||
@override
|
||||
_TabScaffoldState createState() => _TabScaffoldState();
|
||||
}
|
||||
|
||||
class _TabScaffoldState<T> extends State<TabScaffold<T>> {
|
||||
bool _loading;
|
||||
T _payload;
|
||||
String _error = '';
|
||||
int _activeTab = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_refresh();
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
if (_error.isNotEmpty) {
|
||||
return ErrorReload(text: _error, onTap: _refresh);
|
||||
} else if (_payload == null) {
|
||||
return Loading(more: false);
|
||||
} else {
|
||||
return widget.bodyBuilder(_payload);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _refresh([int activeTab]) async {
|
||||
try {
|
||||
setState(() {
|
||||
_error = '';
|
||||
_loading = true;
|
||||
if (activeTab != null) {
|
||||
_activeTab = activeTab;
|
||||
}
|
||||
});
|
||||
_payload = await widget.onRefresh(activeTab);
|
||||
} catch (err) {
|
||||
_error = err.toString();
|
||||
throw err;
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildTrailing() {
|
||||
if (_payload == null || widget.trailingBuilder == null) return null;
|
||||
|
||||
return widget.trailingBuilder(_payload);
|
||||
}
|
||||
|
||||
List<Widget> _buildActions() {
|
||||
if (_payload == null || widget.trailingBuilder == null) return null;
|
||||
var w = widget.trailingBuilder(_payload);
|
||||
return [if (w != null) w];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
switch (Provider.of<ThemeModel>(context).theme) {
|
||||
case AppThemeType.cupertino:
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: DefaultTextStyle(
|
||||
style: TextStyle(),
|
||||
child: CupertinoSegmentedControl(
|
||||
groupValue: _activeTab,
|
||||
onValueChanged: _refresh,
|
||||
children: widget.tabs.asMap().map((key, text) => MapEntry(
|
||||
key,
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Text(text),
|
||||
))),
|
||||
),
|
||||
),
|
||||
trailing: null, // TODO:
|
||||
),
|
||||
child: SafeArea(
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
CupertinoSliverRefreshControl(onRefresh: _refresh),
|
||||
SliverToBoxAdapter(child: _buildBody())
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
default:
|
||||
return DefaultTabController(
|
||||
length: widget.tabs.length,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: widget.title,
|
||||
actions: _buildActions(),
|
||||
bottom: TabBar(
|
||||
onTap: _refresh,
|
||||
tabs: widget.tabs
|
||||
.map((text) => Tab(text: text.toUpperCase()))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: _refresh,
|
||||
child: SingleChildScrollView(child: _buildBody()),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/scaffolds/refresh.dart';
|
||||
import 'package:git_touch/scaffolds/tab.dart';
|
||||
import 'package:git_touch/widgets/app_bar_title.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:git_touch/models/notification.dart';
|
||||
|
@ -142,7 +142,7 @@ $key: pullRequest(number: ${item.number}) {
|
|||
|
||||
@override
|
||||
Widget build(context) {
|
||||
return RefreshScaffold(
|
||||
return TabScaffold(
|
||||
title: AppBarTitle('Notifications'),
|
||||
tabs: ['Unread', 'Paticipating', 'All'],
|
||||
// trailing: GestureDetector(
|
||||
|
|
|
@ -145,7 +145,7 @@ class ObjectScreen extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return RefreshScaffold(
|
||||
title: AppBarTitle(paths.join('/')),
|
||||
onRefresh: (_) async {
|
||||
onRefresh: () async {
|
||||
var data = await Provider.of<SettingsModel>(context).query('''{
|
||||
repository(owner: "$owner", name: "$name") {
|
||||
object(expression: "$_expression") {
|
||||
|
|
|
@ -55,7 +55,7 @@ class OrganizationScreen extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshScaffold(
|
||||
onRefresh: (_) async {
|
||||
onRefresh: () async {
|
||||
// Use pinnableItems instead of organization here due to token permission
|
||||
var data = await Provider.of<SettingsModel>(context).query('''
|
||||
{
|
||||
|
|
|
@ -131,7 +131,7 @@ class RepositoryScreen extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return RefreshScaffold(
|
||||
title: AppBarTitle('Repository'),
|
||||
onRefresh: (_) => Future.wait([
|
||||
onRefresh: () => Future.wait([
|
||||
queryRepo(context),
|
||||
fetchReadme(context),
|
||||
]),
|
||||
|
|
|
@ -139,7 +139,7 @@ class UserScreen extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshScaffold(
|
||||
onRefresh: (_) {
|
||||
onRefresh: () {
|
||||
return Future.wait(
|
||||
[query(context), getContributions(login)],
|
||||
);
|
||||
|
|
|
@ -8,7 +8,8 @@ import 'package:git_touch/screens/user.dart';
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:primer/primer.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
export 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||
export 'package:flutter_vector_icons/flutter_vector_icons.dart' hide Octicons;
|
||||
export 'package:primer/primer.dart' show Octicons;
|
||||
|
||||
final monospaceFont = Platform.isIOS ? 'Menlo' : 'monospace'; // FIXME:
|
||||
|
||||
|
@ -55,7 +56,10 @@ TextSpan createLinkSpan(
|
|||
) {
|
||||
return TextSpan(
|
||||
text: text,
|
||||
style: TextStyle(color: PrimerColors.blue500, fontWeight: FontWeight.w600),
|
||||
style: TextStyle(
|
||||
color: PrimerColors.blue500,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Provider.of<ThemeModel>(context).pushRoute(context, builder);
|
||||
|
|
Loading…
Reference in New Issue