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:
parent
c79f7abdba
commit
1226e8ff8d
@ -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(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
@ -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()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
79
lib/scaffolds/refresh_stateful.dart
Normal file
79
lib/scaffolds/refresh_stateful.dart
Normal 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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
23
lib/scaffolds/single.dart
Normal 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
126
lib/scaffolds/tab_stateful.dart
Normal file
126
lib/scaffolds/tab_stateful.dart
Normal 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
69
lib/scaffolds/utils.dart
Normal 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),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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(
|
||||||
|
@ -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),
|
||||||
|
@ -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),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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),
|
||||||
|
@ -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(
|
||||||
|
@ -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)),
|
||||||
|
@ -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,
|
||||||
|
@ -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'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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('''{
|
||||||
|
@ -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('''
|
||||||
|
@ -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),
|
||||||
|
@ -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),
|
||||||
|
@ -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
|
||||||
|
@ -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: [
|
||||||
|
@ -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 {
|
||||||
|
@ -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)],
|
||||||
|
@ -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),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user