refactor: scaffolds

This commit is contained in:
Rongjian Zhang 2019-09-25 17:06:36 +08:00
parent c79f7abdba
commit 1226e8ff8d
26 changed files with 435 additions and 392 deletions

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/utils.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:provider/provider.dart';
import '../widgets/error_reload.dart';
@ -17,14 +18,14 @@ class ListPayload<T, K> {
}
// This is a scaffold for infinite scroll screens
class ListScaffold<T, K> extends StatefulWidget {
class ListStatefulScaffold<T, K> extends StatefulWidget {
final Widget title;
final Widget Function({Function({bool force}) refresh}) trailingBuiler;
final Widget Function() trailingBuiler;
final Widget Function(T payload) itemBuilder;
final Future<ListPayload<T, K>> Function() onRefresh;
final Future<ListPayload<T, K>> Function(K cursor) onLoadMore;
ListScaffold({
ListStatefulScaffold({
@required this.title,
@required this.itemBuilder,
@required this.onRefresh,
@ -33,10 +34,12 @@ class ListScaffold<T, K> extends StatefulWidget {
});
@override
_ListScaffoldState<T, K> createState() => _ListScaffoldState();
_ListStatefulScaffoldState<T, K> createState() =>
_ListStatefulScaffoldState();
}
class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
class _ListStatefulScaffoldState<T, K>
extends State<ListStatefulScaffold<T, K>> {
bool loading = false;
bool loadingMore = false;
String error = '';
@ -145,7 +148,7 @@ class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
return widget.itemBuilder(items[index ~/ 2]);
}
Widget _buildSliver(BuildContext context) {
Widget _buildCupertinoSliver() {
if (error.isNotEmpty) {
return SliverToBoxAdapter(
child: ErrorReload(text: error, onTap: _refresh),
@ -164,7 +167,7 @@ class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
}
}
Widget _buildBody(BuildContext context) {
Widget _buildMaterial() {
if (error.isNotEmpty) {
return ErrorReload(text: error, onTap: _refresh);
} else if (loading && items.isEmpty) {
@ -181,45 +184,30 @@ class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
}
}
@override
Widget build(BuildContext context) {
Widget _buildBody() {
switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino:
List<Widget> slivers = [
CupertinoSliverRefreshControl(onRefresh: _refresh)
];
// if (widget.header != null) {
// slivers.add(SliverToBoxAdapter(child: widget.header));
// }
slivers.add(_buildSliver(context));
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: widget.title,
trailing: widget.trailingBuiler == null
? null
: widget.trailingBuiler(refresh: _refresh),
),
child: SafeArea(
child: CustomScrollView(
controller: _controller,
slivers: slivers,
),
),
return CustomScrollView(
controller: _controller,
slivers: [
CupertinoSliverRefreshControl(onRefresh: _refresh),
_buildCupertinoSliver(),
],
);
default:
return Scaffold(
appBar: AppBar(
title: widget.title,
actions: widget.trailingBuiler == null
? null
: [widget.trailingBuiler(refresh: _refresh)],
),
body: RefreshIndicator(
onRefresh: _refresh,
child: _buildBody(context),
),
return RefreshIndicator(
onRefresh: _refresh,
child: _buildMaterial(),
);
}
}
@override
Widget build(BuildContext context) {
return CommonScaffold(
title: widget.title,
body: _buildBody(),
trailing: widget.trailingBuiler == null ? null : widget.trailingBuiler(),
);
}
}

View File

@ -1,108 +0,0 @@
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 RefreshScaffold<T> extends StatefulWidget {
final Widget title;
final Widget Function(T payload) bodyBuilder;
final Future<T> Function() onRefresh;
final Widget Function(T payload) trailingBuilder;
RefreshScaffold({
@required this.title,
@required this.bodyBuilder,
@required this.onRefresh,
this.trailingBuilder,
});
@override
_RefreshScaffoldState createState() => _RefreshScaffoldState();
}
class _RefreshScaffoldState<T> extends State<RefreshScaffold<T>> {
bool _loading;
T _payload;
String _error = '';
@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() async {
try {
setState(() {
_error = '';
_loading = true;
});
_payload = await widget.onRefresh();
} 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: widget.title,
trailing: _buildTrailing(),
),
child: SafeArea(
child: CustomScrollView(
slivers: <Widget>[
CupertinoSliverRefreshControl(onRefresh: _refresh),
SliverToBoxAdapter(child: _buildBody())
],
),
),
);
default:
return Scaffold(
appBar: AppBar(
title: widget.title,
actions: _buildActions(),
),
body: RefreshIndicator(
onRefresh: _refresh,
child: SingleChildScrollView(child: _buildBody()),
),
);
}
}
}

View File

@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/scaffolds/utils.dart';
import '../widgets/loading.dart';
import '../widgets/error_reload.dart';
class RefreshStatefulScaffold<T> extends StatefulWidget {
final Widget title;
final Widget Function(T payload) bodyBuilder;
final Future<T> Function() onRefresh;
final Widget Function(T payload) trailingBuilder;
RefreshStatefulScaffold({
@required this.title,
@required this.bodyBuilder,
@required this.onRefresh,
this.trailingBuilder,
});
@override
_RefreshStatefulScaffoldState createState() =>
_RefreshStatefulScaffoldState();
}
class _RefreshStatefulScaffoldState<T>
extends State<RefreshStatefulScaffold<T>> {
bool _loading;
T _payload;
String _error = '';
@override
void initState() {
super.initState();
_refresh();
}
Future<void> _refresh() async {
try {
setState(() {
_error = '';
_loading = true;
});
_payload = await widget.onRefresh();
} catch (err) {
_error = err.toString();
throw err;
} finally {
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
Widget get _trailing {
if (_payload == null || widget.trailingBuilder == null) return null;
return widget.trailingBuilder(_payload);
}
Widget get _body {
if (_error.isNotEmpty) {
return ErrorReload(text: _error, onTap: _refresh);
} else if (_payload == null) {
return Loading(more: false);
} else {
return widget.bodyBuilder(_payload);
}
}
@override
Widget build(BuildContext context) {
return CommonScaffold(
title: widget.title,
body: RefreshWrapper(onRefresh: _refresh, body: _body),
trailing: _trailing,
);
}
}

View File

@ -1,40 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
class SimpleScaffold extends StatelessWidget {
final Widget title;
final Widget child;
final Widget trailing;
final List<Widget> actions;
final PreferredSizeWidget bottom;
SimpleScaffold({
@required this.title,
@required this.child,
this.trailing,
this.actions,
this.bottom,
});
@override
Widget build(BuildContext context) {
switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino:
return CupertinoPageScaffold(
navigationBar:
CupertinoNavigationBar(middle: title, trailing: trailing),
child: SafeArea(
child: SingleChildScrollView(child: child),
),
);
default:
return Scaffold(
appBar: AppBar(title: title, actions: actions, bottom: bottom),
body: SingleChildScrollView(child: child),
);
}
}
}

23
lib/scaffolds/single.dart Normal file
View File

@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'package:git_touch/scaffolds/utils.dart';
class SingleScaffold extends StatelessWidget {
final Widget title;
final Widget body;
final Widget trailing;
SingleScaffold({
@required this.title,
@required this.body,
this.trailing,
});
@override
Widget build(BuildContext context) {
return CommonScaffold(
title: title,
body: SingleChildScrollView(child: body),
trailing: trailing,
);
}
}

View File

@ -1,171 +1,77 @@
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/scaffolds/utils.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, int activeTab) bodyBuilder;
final Future<T> Function(int activeTab) onRefresh;
class CommonTabPayload {
final List<String> tabs;
final Widget Function(T payload) trailingBuilder;
final int activeTab;
final Function(int active) onTabSwitch;
CommonTabPayload({
@required this.tabs,
@required this.activeTab,
@required this.onTabSwitch,
});
}
class TabScaffold extends StatelessWidget {
final Widget title;
final Widget body;
final Widget trailing;
final void Function() onRefresh;
final CommonTabPayload tabPayload;
TabScaffold({
@required this.title,
@required this.bodyBuilder,
@required this.body,
this.trailing,
@required this.onRefresh,
@required this.tabs,
this.trailingBuilder,
@required this.tabPayload,
});
@override
_TabScaffoldState createState() => _TabScaffoldState();
}
class _TabScaffoldState<T> extends State<TabScaffold<T>> {
bool _loading;
T _payload0;
T _payload1;
T _payload2;
String _error = '';
int _activeTab = 0;
T _getPayload(int selected) {
switch (selected) {
case 0:
return _payload0;
case 1:
return _payload1;
case 2:
return _payload2;
Widget _buildTitle(BuildContext context) {
switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino:
return DefaultTextStyle(
style: TextStyle(fontSize: 16),
child: CupertinoSegmentedControl(
groupValue: tabPayload.activeTab,
onValueChanged: tabPayload.onTabSwitch,
children: tabPayload.tabs.asMap().map((key, text) => MapEntry(
key,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(text),
))),
),
);
default:
throw '';
return title;
}
}
T get _payload => _getPayload(_activeTab);
set _payload(T v) {
switch (_activeTab) {
case 0:
_payload0 = v;
break;
case 1:
_payload1 = v;
break;
case 2:
_payload2 = v;
break;
}
}
@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, _activeTab);
}
}
Future<void> _refresh() async {
try {
setState(() {
_error = '';
_loading = true;
});
_payload = await widget.onRefresh(_activeTab);
} catch (err) {
_error = err.toString();
throw err;
} finally {
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
Future<void> _switch(int selected) async {
setState(() {
_activeTab = selected;
});
if (_getPayload(selected) == null) {
await _refresh();
}
}
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) {
final scaffold = CommonScaffold(
title: _buildTitle(context),
body: RefreshWrapper(body: body, onRefresh: onRefresh),
trailing: trailing,
bottom: TabBar(
onTap: tabPayload.onTabSwitch,
tabs: tabPayload.tabs
.map((text) => Tab(text: text.toUpperCase()))
.toList(),
),
);
switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino:
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: DefaultTextStyle(
style: TextStyle(fontSize: 16),
child: CupertinoSegmentedControl(
groupValue: _activeTab,
onValueChanged: _switch,
children: widget.tabs.asMap().map((key, text) => MapEntry(
key,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(text),
))),
),
),
trailing: null, // TODO:
),
child: SafeArea(
child: CustomScrollView(
slivers: <Widget>[
CupertinoSliverRefreshControl(onRefresh: _refresh),
SliverToBoxAdapter(child: _buildBody())
],
),
),
);
return scaffold;
default:
return DefaultTabController(
length: widget.tabs.length,
child: Scaffold(
appBar: AppBar(
title: widget.title,
actions: _buildActions(),
bottom: TabBar(
onTap: _switch,
tabs: widget.tabs
.map((text) => Tab(text: text.toUpperCase()))
.toList(),
),
),
body: RefreshIndicator(
onRefresh: _refresh,
child: SingleChildScrollView(child: _buildBody()),
),
),
length: tabPayload.tabs.length,
child: scaffold,
);
}
}

View File

@ -0,0 +1,126 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/scaffolds/tab.dart';
import '../widgets/loading.dart';
import '../widgets/error_reload.dart';
class TabStatefulScaffold<T> extends StatefulWidget {
final Widget title;
final Widget Function(T payload, int activeTab) bodyBuilder;
final Future<T> Function(int activeTab) onRefresh;
final List<String> tabs;
final Widget Function(T payload) trailingBuilder;
TabStatefulScaffold({
@required this.title,
@required this.bodyBuilder,
@required this.onRefresh,
@required this.tabs,
this.trailingBuilder,
});
@override
_TabStatefulScaffoldState createState() => _TabStatefulScaffoldState();
}
class _TabStatefulScaffoldState<T> extends State<TabStatefulScaffold<T>> {
bool _loading;
T _payload0;
T _payload1;
T _payload2;
String _error = '';
int _activeTab = 0;
T _getPayload(int selected) {
switch (selected) {
case 0:
return _payload0;
case 1:
return _payload1;
case 2:
return _payload2;
default:
throw '';
}
}
T get _payload => _getPayload(_activeTab);
set _payload(T v) {
switch (_activeTab) {
case 0:
_payload0 = v;
break;
case 1:
_payload1 = v;
break;
case 2:
_payload2 = v;
break;
}
}
@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, _activeTab);
}
}
Future<void> _refresh() async {
try {
setState(() {
_error = '';
_loading = true;
});
_payload = await widget.onRefresh(_activeTab);
} catch (err) {
_error = err.toString();
throw err;
} finally {
if (mounted) {
setState(() {
_loading = false;
});
}
}
}
Future<void> _switch(int selected) async {
setState(() {
_activeTab = selected;
});
if (_getPayload(selected) == null) {
await _refresh();
}
}
Widget _buildTrailing() {
if (_payload == null || widget.trailingBuilder == null) return null;
return widget.trailingBuilder(_payload);
}
@override
Widget build(BuildContext context) {
return TabScaffold(
title: widget.title,
trailing: _buildTrailing(),
tabPayload: CommonTabPayload(
tabs: widget.tabs,
activeTab: _activeTab,
onTabSwitch: _switch,
),
onRefresh: _refresh,
body: _buildBody(),
);
}
}

69
lib/scaffolds/utils.dart Normal file
View File

@ -0,0 +1,69 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/theme.dart';
import 'package:provider/provider.dart';
class CommonScaffold extends StatelessWidget {
final Widget title;
final Widget body;
final Widget trailing;
final PreferredSizeWidget bottom;
CommonScaffold({
@required this.title,
@required this.body,
this.trailing,
this.bottom,
});
@override
Widget build(BuildContext context) {
switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino:
return CupertinoPageScaffold(
navigationBar:
CupertinoNavigationBar(middle: title, trailing: trailing),
child: SafeArea(child: body),
);
default:
return Scaffold(
appBar: AppBar(
title: title,
actions: [
if (trailing != null) trailing,
],
bottom: bottom,
),
body: body,
);
}
}
}
class RefreshWrapper extends StatelessWidget {
final Widget body;
final void Function() onRefresh;
RefreshWrapper({
@required this.onRefresh,
@required this.body,
});
@override
Widget build(BuildContext context) {
switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino:
return CustomScrollView(
slivers: <Widget>[
CupertinoSliverRefreshControl(onRefresh: onRefresh),
SliverToBoxAdapter(child: body),
],
);
default:
return RefreshIndicator(
onRefresh: onRefresh,
child: SingleChildScrollView(child: body),
);
}
}
}

View File

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_highlight/flutter_highlight.dart';
import 'package:flutter_highlight/theme_map.dart';
import 'package:git_touch/models/code.dart';
import 'package:git_touch/scaffolds/simple.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/picker.dart';
import 'package:provider/provider.dart';
@ -18,9 +18,9 @@ class CodeSettingsScreen extends StatelessWidget {
Widget build(BuildContext context) {
var codeProvider = Provider.of<CodeModel>(context);
return SimpleScaffold(
return SingleScaffold(
title: AppBarTitle('Code theme'),
child: Column(
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
PickerGroup(

View File

@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
import 'package:git_touch/models/settings.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/link.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
import 'package:git_touch/scaffolds/list.dart';
import 'package:git_touch/widgets/avatar.dart';
import 'package:primer/primer.dart';
@ -82,7 +82,7 @@ class CommitsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListScaffold(
return ListStatefulScaffold(
title: AppBarTitle('Commits'),
onRefresh: () => _query(context),
onLoadMore: (cursor) => _query(context, cursor),

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:git_touch/scaffolds/simple.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
class ImageView extends StatelessWidget {
@ -9,9 +9,9 @@ class ImageView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SimpleScaffold(
return SingleScaffold(
title: AppBarTitle('Image preview'),
child: Container(
body: Container(
child: Image(image: imageProvider),
),
);

View File

@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
import 'package:git_touch/models/settings.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/avatar.dart';
import 'package:primer/primer.dart';
import 'package:provider/provider.dart';
import 'package:timeago/timeago.dart' as timeago;
import '../scaffolds/list.dart';
import '../utils/utils.dart';
import '../widgets/link.dart';
import '../screens/issue.dart';
@ -191,7 +191,7 @@ class IssuesScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListScaffold(
return ListStatefulScaffold(
title: AppBarTitle(
(isPullRequest ? 'Pull requests' : 'Issues') + ' of $owner/$name'),
onRefresh: () => _query(context),

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:git_touch/models/settings.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:provider/provider.dart';
import '../scaffolds/simple.dart';
import '../widgets/link.dart';
import '../widgets/loading.dart';
import '../models/account.dart';
@ -90,9 +90,9 @@ class _LoginScreenState extends State<LoginScreen> {
});
});
return SimpleScaffold(
return SingleScaffold(
title: AppBarTitle('Select account'),
child: settings.loading
body: settings.loading
? Center(child: Loading())
: Container(
child: Column(

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:git_touch/models/settings.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:provider/provider.dart';
import '../scaffolds/simple.dart';
class LoginGitlabScreen extends StatefulWidget {
@override
@ -15,9 +15,9 @@ class _LoginGitlabScreenState extends State<LoginGitlabScreen> {
@override
Widget build(BuildContext context) {
return SimpleScaffold(
return SingleScaffold(
title: AppBarTitle('Login to GitLab'),
child: Column(
body: Column(
children: <Widget>[
TextField(
// decoration: InputDecoration(icon: Icon(Icons.more_vert)),

View File

@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/notification.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:provider/provider.dart';
import '../scaffolds/list.dart';
import '../widgets/event_item.dart';
import 'package:git_touch/models/settings.dart';
@ -67,7 +67,7 @@ class NewsScreenState extends State<NewsScreen> {
@override
Widget build(context) {
return ListScaffold<EventPayload, int>(
return ListStatefulScaffold<EventPayload, int>(
title: AppBarTitle('News'),
itemBuilder: (payload) => EventItem(payload),
onRefresh: fetchEvents,

View File

@ -1,13 +1,13 @@
import 'package:flutter/material.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import '../scaffolds/simple.dart';
class NotFoundScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SimpleScaffold(
return SingleScaffold(
title: AppBarTitle('Not Found'),
child: Text('Woops, This page is not implemented yet'),
body: Text('Woops, This page is not implemented yet'),
);
}
}

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/scaffolds/tab.dart';
import 'package:git_touch/scaffolds/tab_stateful.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 TabScaffold(
return TabStatefulScaffold(
title: AppBarTitle('Notifications'),
tabs: ['Unread', 'Paticipating', 'All'],
// trailing: GestureDetector(
@ -167,19 +167,19 @@ $key: pullRequest(number: ${item.number}) {
// _onSwitchTab(value);
// },
// ),
trailingBuilder: (_) => IconButton(
icon: Icon(Icons.done_all),
onPressed: () async {
// TODO:
// var value = await Provider.of<ThemeModel>(context)
// .showConfirm(context, 'Mark all as read?');
// if (value) {
// await Provider.of<SettingsModel>(context)
// .putWithCredentials('/notifications');
// await fetchNotifications(0);
// }
},
),
// trailingBuilder: (_) => IconButton(
// icon: Icon(Icons.done_all),
// onPressed: () async {
// // TODO:
// // var value = await Provider.of<ThemeModel>(context)
// // .showConfirm(context, 'Mark all as read?');
// // if (value) {
// // await Provider.of<SettingsModel>(context)
// // .putWithCredentials('/notifications');
// // await fetchNotifications(0);
// // }
// },
// ),
onRefresh: fetchNotifications,
bodyBuilder: (groupMap, activeTab) {
if (groupMap.isEmpty) return EmptyWidget();

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_highlight/theme_map.dart';
import 'package:git_touch/models/code.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/screens/code_settings.dart';
import 'package:git_touch/screens/image_view.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
@ -12,7 +13,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_highlight/flutter_highlight.dart';
import 'package:git_touch/models/settings.dart';
import 'package:provider/provider.dart';
import 'package:git_touch/scaffolds/refresh.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:primer/primer.dart';
import 'package:seti/seti.dart';
@ -143,7 +143,7 @@ class ObjectScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RefreshScaffold(
return RefreshStatefulScaffold(
title: AppBarTitle(paths.join('/')),
onRefresh: () async {
var data = await Provider.of<SettingsModel>(context).query('''{

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/screens/repositories.dart';
import 'package:git_touch/screens/users.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
@ -11,7 +12,6 @@ import 'package:url_launcher/url_launcher.dart';
import 'package:share/share.dart';
import 'package:git_touch/models/settings.dart';
import 'package:provider/provider.dart';
import '../scaffolds/refresh.dart';
import '../widgets/action.dart';
import '../utils/utils.dart';
@ -54,7 +54,7 @@ class OrganizationScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RefreshScaffold(
return RefreshStatefulScaffold(
onRefresh: () async {
// Use pinnableItems instead of organization here due to token permission
var data = await Provider.of<SettingsModel>(context).query('''

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import '../scaffolds/list.dart';
import 'package:git_touch/models/settings.dart';
import 'package:provider/provider.dart';
import '../utils/utils.dart';
@ -67,7 +67,7 @@ class RepositoriesScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListScaffold(
return ListStatefulScaffold(
title: AppBarTitle(title),
onRefresh: () => _queryRepos(context),
onLoadMore: (cursor) => _queryRepos(context, cursor),

View File

@ -3,6 +3,7 @@ import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/settings.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/screens/users.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
@ -14,7 +15,6 @@ import 'package:git_touch/screens/commits.dart';
import 'package:git_touch/screens/object.dart';
import 'package:share/share.dart';
import 'package:url_launcher/url_launcher.dart';
import '../scaffolds/refresh.dart';
import 'package:git_touch/widgets/repository_item.dart';
import '../widgets/entry_item.dart';
import '../screens/issues.dart';
@ -129,7 +129,7 @@ class RepositoryScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RefreshScaffold(
return RefreshStatefulScaffold(
title: AppBarTitle('Repository'),
onRefresh: () => Future.wait([
queryRepo(context),

View File

@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:provider/provider.dart';
import 'package:git_touch/models/settings.dart';
import '../scaffolds/simple.dart';
import '../utils/utils.dart';
import 'package:git_touch/widgets/repository_item.dart';
import '../widgets/loading.dart';
@ -60,9 +60,9 @@ class _SearchScreenState extends State<SearchScreen> {
@override
Widget build(BuildContext context) {
return SimpleScaffold(
return SingleScaffold(
title: AppBarTitle('Search GitHub Repositories'),
child: Column(
body: Column(
children: <Widget>[
Container(padding: EdgeInsets.all(8), child: _buildInput()),
loading

View File

@ -1,13 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/screens/object.dart';
import 'package:git_touch/screens/repository.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:provider/provider.dart';
import 'package:launch_review/launch_review.dart';
import '../scaffolds/simple.dart';
import '../widgets/table_view.dart';
import '../screens/login.dart';
@ -21,9 +21,9 @@ class SettingsScreen extends StatelessWidget {
Widget build(BuildContext context) {
var themeProvider = Provider.of<ThemeModel>(context);
return SimpleScaffold(
return SingleScaffold(
title: AppBarTitle('Settings'),
child: Column(
body: Column(
children: <Widget>[
borderView1,
TableView(headerText: 'ACCOUNTS', items: [

View File

@ -1,6 +1,6 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:git_touch/scaffolds/tab.dart';
import 'package:git_touch/scaffolds/tab_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/user_item.dart';
@ -9,7 +9,7 @@ import 'package:git_touch/widgets/repository_item.dart';
class TrendingScreen extends StatelessWidget {
Widget build(BuildContext context) {
return TabScaffold(
return TabStatefulScaffold(
title: AppBarTitle('Trending'),
tabs: ['Repositories', 'Users'],
onRefresh: (tabIndex) async {

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/screens/repositories.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/table_view.dart';
@ -9,7 +10,6 @@ import 'package:share/share.dart';
import 'package:github_contributions/github_contributions.dart';
import 'package:git_touch/models/settings.dart';
import 'package:provider/provider.dart';
import '../scaffolds/refresh.dart';
import '../widgets/entry_item.dart';
import 'package:git_touch/widgets/repository_item.dart';
import '../widgets/link.dart';
@ -138,7 +138,7 @@ class UserScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RefreshScaffold(
return RefreshStatefulScaffold(
onRefresh: () {
return Future.wait(
[query(context), getContributions(login)],

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/user_item.dart';
import '../scaffolds/list.dart';
import 'package:git_touch/models/settings.dart';
import 'package:provider/provider.dart';
import '../utils/utils.dart';
@ -69,7 +69,7 @@ class UsersScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListScaffold(
return ListStatefulScaffold(
title: AppBarTitle(title),
onRefresh: () => _queryUsers(context),
onLoadMore: (cursor) => _queryUsers(context, cursor),