ui backbone
This commit is contained in:
parent
3e374d24f6
commit
b7045fc242
24 changed files with 918 additions and 73 deletions
|
@ -1,5 +1,4 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
@ -9,7 +8,7 @@ import '../services/connection_service.dart';
|
|||
class McgScaffold extends StatelessWidget {
|
||||
const McgScaffold({
|
||||
this.appBar,
|
||||
this.bodyBuilderCompleter,
|
||||
this.bodyBuilderWaiter,
|
||||
this.body,
|
||||
this.waitingWidget,
|
||||
this.forceInternetCheck = false,
|
||||
|
@ -19,10 +18,10 @@ class McgScaffold extends StatelessWidget {
|
|||
final AppBar? appBar;
|
||||
|
||||
/// Awaits an external signal (complete) before building the body.
|
||||
final Completer? bodyBuilderCompleter;
|
||||
final ValueListenable<bool>? bodyBuilderWaiter;
|
||||
final Widget? body;
|
||||
|
||||
/// Custom widget to be used while awaiting [bodyBuilderCompleter].
|
||||
/// Custom widget to be used while awaiting [bodyBuilderWaiter].
|
||||
///
|
||||
/// Defaults to using [PlatformCircularProgressIndicator].
|
||||
final Widget? waitingWidget;
|
||||
|
@ -32,19 +31,12 @@ class McgScaffold extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Widget loginOptionsBody = bodyBuilderCompleter != null
|
||||
? FutureBuilder(
|
||||
future: bodyBuilderCompleter!.future,
|
||||
builder: (context, snapshot) {
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
case ConnectionState.active:
|
||||
return Center(child: waitingWidget ?? const CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
return body ?? const SizedBox.shrink();
|
||||
}
|
||||
},
|
||||
final Widget loginOptionsBody = bodyBuilderWaiter != null
|
||||
? ValueListenableBuilder<bool>(
|
||||
valueListenable: bodyBuilderWaiter!,
|
||||
builder: (context, final isReady, child) => !isReady
|
||||
? Center(child: waitingWidget ?? const CircularProgressIndicator())
|
||||
: body ?? const SizedBox.shrink(),
|
||||
)
|
||||
: body ?? const SizedBox.shrink();
|
||||
|
||||
|
|
47
lib/features/core/widgets/view_model_builder.dart
Normal file
47
lib/features/core/widgets/view_model_builder.dart
Normal file
|
@ -0,0 +1,47 @@
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../abstracts/base_view_model.dart';
|
||||
|
||||
class ViewModelBuilder<T extends BaseViewModel> extends StatefulWidget {
|
||||
const ViewModelBuilder({
|
||||
required Widget Function(BuildContext context, T model) builder,
|
||||
required T Function() viewModelBuilder,
|
||||
dynamic Function()? argumentBuilder,
|
||||
super.key,
|
||||
}) : _builder = builder,
|
||||
_viewModelBuilder = viewModelBuilder,
|
||||
_argumentBuilder = argumentBuilder;
|
||||
|
||||
final Widget Function(BuildContext context, T model) _builder;
|
||||
final T Function() _viewModelBuilder;
|
||||
final dynamic Function()? _argumentBuilder;
|
||||
|
||||
@override
|
||||
_ViewModelBuilderState<T> createState() => _ViewModelBuilderState<T>();
|
||||
}
|
||||
|
||||
class _ViewModelBuilderState<T extends BaseViewModel> extends State<ViewModelBuilder<T>> {
|
||||
late final T _viewModel;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_viewModel = widget._viewModelBuilder();
|
||||
_viewModel.initialise(() => mounted, widget._argumentBuilder?.call());
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_viewModel.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext _) => ChangeNotifierProvider.value(
|
||||
value: _viewModel,
|
||||
child: Consumer<T>(
|
||||
builder: (context, model, _) => widget._builder(context, model),
|
||||
),
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue