import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import '../providers/settings.dart'; import '../widgets/loading.dart'; import '../widgets/error_reload.dart'; import '../utils/utils.dart'; // This is a scaffold for pull to refresh class RefreshScaffold<T> extends StatefulWidget { final Widget title; final Widget Function(T payload) bodyBuilder; final Future<T> Function() onRefresh; final Widget trailing; final List<Widget> actions; final PreferredSizeWidget bottom; RefreshScaffold({ @required this.title, @required this.bodyBuilder, @required this.onRefresh, this.trailing, this.actions, this.bottom, }); @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, reload: _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(); } finally { if (mounted) { setState(() { loading = false; }); } } } @override Widget build(BuildContext context) { switch (SettingsProvider.of(context).theme) { case ThemeMap.cupertino: return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: widget.title, trailing: widget.trailing), child: SafeArea( child: CustomScrollView( slivers: <Widget>[ CupertinoSliverRefreshControl(onRefresh: _refresh), SliverToBoxAdapter(child: _buildBody()) ], ), ), ); default: return Scaffold( appBar: AppBar( title: widget.title, actions: widget.actions, bottom: widget.bottom, ), body: RefreshIndicator( onRefresh: _refresh, child: SingleChildScrollView(child: _buildBody()), ), ); } } }