dart format
This commit is contained in:
@@ -1,15 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class BlocModule<TBloc extends StateStreamableSource<TState>, TState> extends StatelessWidget {
|
||||
class BlocModule<TBloc extends StateStreamableSource<TState>, TState>
|
||||
extends StatelessWidget {
|
||||
final TBloc Function(BuildContext context) create;
|
||||
final Widget Function(BuildContext context, TBloc bloc, TState state) child;
|
||||
final bool autoRebuild;
|
||||
final void Function(BuildContext context, TBloc bloc)? onInitialisation;
|
||||
const BlocModule({required this.create, required this.child, this.autoRebuild = false, this.onInitialisation, super.key});
|
||||
const BlocModule({
|
||||
required this.create,
|
||||
required this.child,
|
||||
this.autoRebuild = false,
|
||||
this.onInitialisation,
|
||||
super.key,
|
||||
});
|
||||
|
||||
Widget rebuildChild(BuildContext context) => child(context, context.watch<TBloc>(), context.watch<TBloc>().state);
|
||||
Widget staticChild(BuildContext context) => child(context, context.read<TBloc>(), context.read<TBloc>().state);
|
||||
Widget rebuildChild(BuildContext context) =>
|
||||
child(context, context.watch<TBloc>(), context.watch<TBloc>().state);
|
||||
Widget staticChild(BuildContext context) =>
|
||||
child(context, context.read<TBloc>(), context.read<TBloc>().state);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => BlocProvider<TBloc>(
|
||||
@@ -19,9 +28,8 @@ class BlocModule<TBloc extends StateStreamableSource<TState>, TState> extends St
|
||||
return bloc;
|
||||
},
|
||||
child: Builder(
|
||||
builder: (context) => autoRebuild
|
||||
? rebuildChild(context)
|
||||
: staticChild(context)
|
||||
)
|
||||
builder: (context) =>
|
||||
autoRebuild ? rebuildChild(context) : staticChild(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
+89
-66
@@ -13,60 +13,79 @@ abstract class LoadableHydratedBloc<
|
||||
TEvent extends LoadableHydratedBlocEvent<TState>,
|
||||
TState,
|
||||
TRepository extends Repository<TState>
|
||||
> extends HydratedBloc<
|
||||
LoadableHydratedBlocEvent<TState>,
|
||||
LoadableState<TState>
|
||||
> {
|
||||
>
|
||||
extends
|
||||
HydratedBloc<LoadableHydratedBlocEvent<TState>, LoadableState<TState>> {
|
||||
late TRepository _repository;
|
||||
LoadableHydratedBloc() : super(const LoadableState(
|
||||
error: null,
|
||||
data: null,
|
||||
isLoading: true,
|
||||
lastFetch: null,
|
||||
reFetch: null,
|
||||
)) {
|
||||
|
||||
LoadableHydratedBloc()
|
||||
: super(
|
||||
const LoadableState(
|
||||
error: null,
|
||||
data: null,
|
||||
isLoading: true,
|
||||
lastFetch: null,
|
||||
reFetch: null,
|
||||
),
|
||||
) {
|
||||
on<Emit<TState>>((event, emit) {
|
||||
emit(LoadableState(
|
||||
isLoading: state.isLoading,
|
||||
data: event.state(innerState ?? fromNothing()),
|
||||
lastFetch: state.lastFetch,
|
||||
reFetch: retry,
|
||||
error: state.error,
|
||||
));
|
||||
emit(
|
||||
LoadableState(
|
||||
isLoading: state.isLoading,
|
||||
data: event.state(innerState ?? fromNothing()),
|
||||
lastFetch: state.lastFetch,
|
||||
reFetch: retry,
|
||||
error: state.error,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
on<DataGathered<TState>>((event, emit) => emit(LoadableState(
|
||||
isLoading: false,
|
||||
data: event.state(innerState ?? fromNothing()),
|
||||
lastFetch: DateTime.now().millisecondsSinceEpoch,
|
||||
reFetch: retry,
|
||||
error: null,
|
||||
)));
|
||||
on<DataGathered<TState>>(
|
||||
(event, emit) => emit(
|
||||
LoadableState(
|
||||
isLoading: false,
|
||||
data: event.state(innerState ?? fromNothing()),
|
||||
lastFetch: DateTime.now().millisecondsSinceEpoch,
|
||||
reFetch: retry,
|
||||
error: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
on<RefetchStarted<TState>>((event, emit) => emit(LoadableState(
|
||||
isLoading: true,
|
||||
data: innerState,
|
||||
lastFetch: state.lastFetch,
|
||||
reFetch: null,
|
||||
error: null,
|
||||
)));
|
||||
on<RefetchStarted<TState>>(
|
||||
(event, emit) => emit(
|
||||
LoadableState(
|
||||
isLoading: true,
|
||||
data: innerState,
|
||||
lastFetch: state.lastFetch,
|
||||
reFetch: null,
|
||||
error: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
on<Error<TState>>((event, emit) => emit(LoadableState(
|
||||
isLoading: false,
|
||||
data: innerState,
|
||||
lastFetch: state.lastFetch,
|
||||
reFetch: retry,
|
||||
error: event.error
|
||||
)));
|
||||
on<Error<TState>>(
|
||||
(event, emit) => emit(
|
||||
LoadableState(
|
||||
isLoading: false,
|
||||
data: innerState,
|
||||
lastFetch: state.lastFetch,
|
||||
reFetch: retry,
|
||||
error: event.error,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
on<Reset<TState>>((event, emit) => emit(const LoadableState(
|
||||
isLoading: false,
|
||||
data: null,
|
||||
lastFetch: null,
|
||||
reFetch: null,
|
||||
error: null,
|
||||
)));
|
||||
on<Reset<TState>>(
|
||||
(event, emit) => emit(
|
||||
const LoadableState(
|
||||
isLoading: false,
|
||||
data: null,
|
||||
lastFetch: null,
|
||||
reFetch: null,
|
||||
error: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
_repository = repository();
|
||||
fetch();
|
||||
@@ -92,23 +111,27 @@ abstract class LoadableHydratedBloc<
|
||||
|
||||
void fetch() {
|
||||
log('Fetching data for ${TState.toString()}');
|
||||
gatherData().catchError(
|
||||
(e) {
|
||||
log('Error while fetching ${TState.toString()}: ${e.toString()}');
|
||||
// The bloc may have been closed before this async error landed (e.g.
|
||||
// when its scoping widget tree was disposed mid-fetch). Adding to a
|
||||
// closed bloc throws "Cannot add new events after calling close",
|
||||
// so swallow that case quietly.
|
||||
if (isClosed) return;
|
||||
add(Error(LoadingError(
|
||||
message: errorToUserMessage(e),
|
||||
technicalDetails: errorToTechnicalDetails(e),
|
||||
allowRetry: errorAllowsRetry(e),
|
||||
)));
|
||||
},
|
||||
).then((value) {
|
||||
log('Fetch for ${TState.toString()} completed!');
|
||||
});
|
||||
gatherData()
|
||||
.catchError((e) {
|
||||
log('Error while fetching ${TState.toString()}: ${e.toString()}');
|
||||
// The bloc may have been closed before this async error landed (e.g.
|
||||
// when its scoping widget tree was disposed mid-fetch). Adding to a
|
||||
// closed bloc throws "Cannot add new events after calling close",
|
||||
// so swallow that case quietly.
|
||||
if (isClosed) return;
|
||||
add(
|
||||
Error(
|
||||
LoadingError(
|
||||
message: errorToUserMessage(e),
|
||||
technicalDetails: errorToTechnicalDetails(e),
|
||||
allowRetry: errorAllowsRetry(e),
|
||||
),
|
||||
),
|
||||
);
|
||||
})
|
||||
.then((value) {
|
||||
log('Fetch for ${TState.toString()} completed!');
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -129,13 +152,13 @@ abstract class LoadableHydratedBloc<
|
||||
try {
|
||||
final stateData = state.data;
|
||||
data = stateData is TState ? toStorage(stateData) : null;
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
log('Failed to save state ${TState.toString()}: ${e.toString()}');
|
||||
}
|
||||
|
||||
return LoadableSaveContext.wrap(
|
||||
data,
|
||||
state.lastFetch ?? DateTime.now().millisecondsSinceEpoch
|
||||
state.lastFetch ?? DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -1,17 +1,22 @@
|
||||
import '../../loadable_state/loading_error.dart';
|
||||
|
||||
class LoadableHydratedBlocEvent<TState> {}
|
||||
|
||||
class Emit<TState> extends LoadableHydratedBlocEvent<TState> {
|
||||
final TState Function(TState state) state;
|
||||
Emit(this.state);
|
||||
}
|
||||
|
||||
class DataGathered<TState> extends LoadableHydratedBlocEvent<TState> {
|
||||
final TState Function(TState state) state;
|
||||
DataGathered(this.state);
|
||||
}
|
||||
|
||||
class Error<TState> extends LoadableHydratedBlocEvent<TState> {
|
||||
final LoadingError error;
|
||||
Error(this.error);
|
||||
}
|
||||
|
||||
class RefetchStarted<TState> extends LoadableHydratedBlocEvent<TState> {}
|
||||
|
||||
class Reset<TState> extends LoadableHydratedBlocEvent<TState> {}
|
||||
|
||||
+14
-7
@@ -6,18 +6,25 @@ part 'loadable_save_context.g.dart';
|
||||
@freezed
|
||||
abstract class LoadableSaveContext with _$LoadableSaveContext {
|
||||
const LoadableSaveContext._();
|
||||
const factory LoadableSaveContext({
|
||||
required int timestamp,
|
||||
}) = _LoadableSaveContext;
|
||||
const factory LoadableSaveContext({required int timestamp}) =
|
||||
_LoadableSaveContext;
|
||||
|
||||
factory LoadableSaveContext.fromJson(Map<String, dynamic> json) => _$LoadableSaveContextFromJson(json);
|
||||
factory LoadableSaveContext.fromJson(Map<String, dynamic> json) =>
|
||||
_$LoadableSaveContextFromJson(json);
|
||||
|
||||
static String dataKey = 'data';
|
||||
static String metaKey = 'meta';
|
||||
|
||||
static Map<String, dynamic> wrap(Map<String, dynamic>? data, int lastFetch) =>
|
||||
{dataKey: data, metaKey: LoadableSaveContext(timestamp: lastFetch).toJson()};
|
||||
{
|
||||
dataKey: data,
|
||||
metaKey: LoadableSaveContext(timestamp: lastFetch).toJson(),
|
||||
};
|
||||
|
||||
static ({Map<String, dynamic> data, LoadableSaveContext meta}) unwrap(Map<String, dynamic> data) =>
|
||||
(data: data[dataKey] as Map<String, dynamic>, meta: LoadableSaveContext.fromJson(data[metaKey] as Map<String, dynamic>));
|
||||
static ({Map<String, dynamic> data, LoadableSaveContext meta}) unwrap(
|
||||
Map<String, dynamic> data,
|
||||
) => (
|
||||
data: data[dataKey] as Map<String, dynamic>,
|
||||
meta: LoadableSaveContext.fromJson(data[metaKey] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user