1
0
mirror of https://github.com/git-touch/git-touch synced 2025-03-05 19:57:42 +01:00

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/cupertino.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:git_touch/models/theme.dart'; import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/utils.dart';
import 'package:git_touch/utils/utils.dart'; import 'package:git_touch/utils/utils.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../widgets/error_reload.dart'; import '../widgets/error_reload.dart';
@ -17,14 +18,14 @@ class ListPayload<T, K> {
} }
// This is a scaffold for infinite scroll screens // 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 title;
final Widget Function({Function({bool force}) refresh}) trailingBuiler; final Widget Function() trailingBuiler;
final Widget Function(T payload) itemBuilder; final Widget Function(T payload) itemBuilder;
final Future<ListPayload<T, K>> Function() onRefresh; final Future<ListPayload<T, K>> Function() onRefresh;
final Future<ListPayload<T, K>> Function(K cursor) onLoadMore; final Future<ListPayload<T, K>> Function(K cursor) onLoadMore;
ListScaffold({ ListStatefulScaffold({
@required this.title, @required this.title,
@required this.itemBuilder, @required this.itemBuilder,
@required this.onRefresh, @required this.onRefresh,
@ -33,10 +34,12 @@ class ListScaffold<T, K> extends StatefulWidget {
}); });
@override @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 loading = false;
bool loadingMore = false; bool loadingMore = false;
String error = ''; String error = '';
@ -145,7 +148,7 @@ class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
return widget.itemBuilder(items[index ~/ 2]); return widget.itemBuilder(items[index ~/ 2]);
} }
Widget _buildSliver(BuildContext context) { Widget _buildCupertinoSliver() {
if (error.isNotEmpty) { if (error.isNotEmpty) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: ErrorReload(text: error, onTap: _refresh), 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) { if (error.isNotEmpty) {
return ErrorReload(text: error, onTap: _refresh); return ErrorReload(text: error, onTap: _refresh);
} else if (loading && items.isEmpty) { } else if (loading && items.isEmpty) {
@ -181,45 +184,30 @@ class _ListScaffoldState<T, K> extends State<ListScaffold<T, K>> {
} }
} }
@override Widget _buildBody() {
Widget build(BuildContext context) {
switch (Provider.of<ThemeModel>(context).theme) { switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino: case AppThemeType.cupertino:
List<Widget> slivers = [ return CustomScrollView(
CupertinoSliverRefreshControl(onRefresh: _refresh) controller: _controller,
]; slivers: [
// if (widget.header != null) { CupertinoSliverRefreshControl(onRefresh: _refresh),
// slivers.add(SliverToBoxAdapter(child: widget.header)); _buildCupertinoSliver(),
// } ],
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,
),
),
); );
default: default:
return Scaffold( return RefreshIndicator(
appBar: AppBar( onRefresh: _refresh,
title: widget.title, child: _buildMaterial(),
actions: widget.trailingBuiler == null
? null
: [widget.trailingBuiler(refresh: _refresh)],
),
body: RefreshIndicator(
onRefresh: _refresh,
child: _buildBody(context),
),
); );
} }
} }
@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/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:git_touch/models/theme.dart'; import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/utils.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../widgets/loading.dart';
import '../widgets/error_reload.dart';
class TabScaffold<T> extends StatefulWidget { class CommonTabPayload {
final Widget title;
final Widget Function(T payload, int activeTab) bodyBuilder;
final Future<T> Function(int activeTab) onRefresh;
final List<String> tabs; 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({ TabScaffold({
@required this.title, @required this.title,
@required this.bodyBuilder, @required this.body,
this.trailing,
@required this.onRefresh, @required this.onRefresh,
@required this.tabs, @required this.tabPayload,
this.trailingBuilder,
}); });
@override Widget _buildTitle(BuildContext context) {
_TabScaffoldState createState() => _TabScaffoldState(); switch (Provider.of<ThemeModel>(context).theme) {
} case AppThemeType.cupertino:
return DefaultTextStyle(
class _TabScaffoldState<T> extends State<TabScaffold<T>> { style: TextStyle(fontSize: 16),
bool _loading; child: CupertinoSegmentedControl(
T _payload0; groupValue: tabPayload.activeTab,
T _payload1; onValueChanged: tabPayload.onTabSwitch,
T _payload2; children: tabPayload.tabs.asMap().map((key, text) => MapEntry(
String _error = ''; key,
int _activeTab = 0; Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
T _getPayload(int selected) { child: Text(text),
switch (selected) { ))),
case 0: ),
return _payload0; );
case 1:
return _payload1;
case 2:
return _payload2;
default: 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 @override
Widget build(BuildContext context) { 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) { switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino: case AppThemeType.cupertino:
return CupertinoPageScaffold( return scaffold;
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())
],
),
),
);
default: default:
return DefaultTabController( return DefaultTabController(
length: widget.tabs.length, length: tabPayload.tabs.length,
child: Scaffold( 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()),
),
),
); );
} }
} }

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:git_touch/scaffolds/single.dart';
import 'package:git_touch/widgets/app_bar_title.dart'; import 'package:git_touch/widgets/app_bar_title.dart';
import '../scaffolds/simple.dart';
class NotFoundScreen extends StatelessWidget { class NotFoundScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SimpleScaffold( return SingleScaffold(
title: AppBarTitle('Not Found'), 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/material.dart';
import 'package:flutter/cupertino.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:git_touch/widgets/app_bar_title.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:git_touch/models/notification.dart'; import 'package:git_touch/models/notification.dart';
@ -142,7 +142,7 @@ $key: pullRequest(number: ${item.number}) {
@override @override
Widget build(context) { Widget build(context) {
return TabScaffold( return TabStatefulScaffold(
title: AppBarTitle('Notifications'), title: AppBarTitle('Notifications'),
tabs: ['Unread', 'Paticipating', 'All'], tabs: ['Unread', 'Paticipating', 'All'],
// trailing: GestureDetector( // trailing: GestureDetector(
@ -167,19 +167,19 @@ $key: pullRequest(number: ${item.number}) {
// _onSwitchTab(value); // _onSwitchTab(value);
// }, // },
// ), // ),
trailingBuilder: (_) => IconButton( // trailingBuilder: (_) => IconButton(
icon: Icon(Icons.done_all), // icon: Icon(Icons.done_all),
onPressed: () async { // onPressed: () async {
// TODO: // // TODO:
// var value = await Provider.of<ThemeModel>(context) // // var value = await Provider.of<ThemeModel>(context)
// .showConfirm(context, 'Mark all as read?'); // // .showConfirm(context, 'Mark all as read?');
// if (value) { // // if (value) {
// await Provider.of<SettingsModel>(context) // // await Provider.of<SettingsModel>(context)
// .putWithCredentials('/notifications'); // // .putWithCredentials('/notifications');
// await fetchNotifications(0); // // await fetchNotifications(0);
// } // // }
}, // },
), // ),
onRefresh: fetchNotifications, onRefresh: fetchNotifications,
bodyBuilder: (groupMap, activeTab) { bodyBuilder: (groupMap, activeTab) {
if (groupMap.isEmpty) return EmptyWidget(); if (groupMap.isEmpty) return EmptyWidget();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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