implemented new loadable state concept

This commit is contained in:
Elias Müller 2024-05-05 22:58:40 +02:00
parent f58a2ec8cd
commit 6ad8203b6a
31 changed files with 1085 additions and 214 deletions

View File

@ -0,0 +1,4 @@
abstract class DataLoader<TResult> {
Future<TResult> fetch();
}

View File

@ -1,14 +1,14 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import '../../../../infrastructure/controller.dart';
import 'error_bar_state.dart';
import 'loadable_state_state.dart';
class ErrorBarController extends Controller<ErrorBarState> {
class LoadableStateBloc extends Bloc<void, LoadableStateState> {
late StreamSubscription<List<ConnectivityResult>> _updateStream;
ErrorBarController() : super(const ErrorBarState(connections: null)) {
LoadableStateBloc() : super(const LoadableStateState(connections: null)) {
emitState(List<ConnectivityResult> v) => emit(state.copyWith(connections: v));
Connectivity().checkConnectivity().then(emitState);

View File

@ -1,11 +1,11 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'error_bar_state.freezed.dart';
part 'loadable_state_state.freezed.dart';
@freezed
class ErrorBarState with _$ErrorBarState {
const factory ErrorBarState({
class LoadableStateState with _$LoadableStateState {
const factory LoadableStateState({
required List<ConnectivityResult>? connections,
}) = _ErrorBarState;
}) = _LoadableStateState;
}

View File

@ -3,7 +3,7 @@
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'error_bar_state.dart';
part of 'loadable_state_state.dart';
// **************************************************************************
// FreezedGenerator
@ -15,28 +15,28 @@ final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$ErrorBarState {
mixin _$LoadableStateState {
List<ConnectivityResult>? get connections =>
throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ErrorBarStateCopyWith<ErrorBarState> get copyWith =>
$LoadableStateStateCopyWith<LoadableStateState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ErrorBarStateCopyWith<$Res> {
factory $ErrorBarStateCopyWith(
ErrorBarState value, $Res Function(ErrorBarState) then) =
_$ErrorBarStateCopyWithImpl<$Res, ErrorBarState>;
abstract class $LoadableStateStateCopyWith<$Res> {
factory $LoadableStateStateCopyWith(
LoadableStateState value, $Res Function(LoadableStateState) then) =
_$LoadableStateStateCopyWithImpl<$Res, LoadableStateState>;
@useResult
$Res call({List<ConnectivityResult>? connections});
}
/// @nodoc
class _$ErrorBarStateCopyWithImpl<$Res, $Val extends ErrorBarState>
implements $ErrorBarStateCopyWith<$Res> {
_$ErrorBarStateCopyWithImpl(this._value, this._then);
class _$LoadableStateStateCopyWithImpl<$Res, $Val extends LoadableStateState>
implements $LoadableStateStateCopyWith<$Res> {
_$LoadableStateStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
@ -58,22 +58,22 @@ class _$ErrorBarStateCopyWithImpl<$Res, $Val extends ErrorBarState>
}
/// @nodoc
abstract class _$$ErrorBarStateImplCopyWith<$Res>
implements $ErrorBarStateCopyWith<$Res> {
factory _$$ErrorBarStateImplCopyWith(
_$ErrorBarStateImpl value, $Res Function(_$ErrorBarStateImpl) then) =
__$$ErrorBarStateImplCopyWithImpl<$Res>;
abstract class _$$LoadableStateStateImplCopyWith<$Res>
implements $LoadableStateStateCopyWith<$Res> {
factory _$$LoadableStateStateImplCopyWith(_$LoadableStateStateImpl value,
$Res Function(_$LoadableStateStateImpl) then) =
__$$LoadableStateStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({List<ConnectivityResult>? connections});
}
/// @nodoc
class __$$ErrorBarStateImplCopyWithImpl<$Res>
extends _$ErrorBarStateCopyWithImpl<$Res, _$ErrorBarStateImpl>
implements _$$ErrorBarStateImplCopyWith<$Res> {
__$$ErrorBarStateImplCopyWithImpl(
_$ErrorBarStateImpl _value, $Res Function(_$ErrorBarStateImpl) _then)
class __$$LoadableStateStateImplCopyWithImpl<$Res>
extends _$LoadableStateStateCopyWithImpl<$Res, _$LoadableStateStateImpl>
implements _$$LoadableStateStateImplCopyWith<$Res> {
__$$LoadableStateStateImplCopyWithImpl(_$LoadableStateStateImpl _value,
$Res Function(_$LoadableStateStateImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@ -81,7 +81,7 @@ class __$$ErrorBarStateImplCopyWithImpl<$Res>
$Res call({
Object? connections = freezed,
}) {
return _then(_$ErrorBarStateImpl(
return _then(_$LoadableStateStateImpl(
connections: freezed == connections
? _value._connections
: connections // ignore: cast_nullable_to_non_nullable
@ -92,8 +92,8 @@ class __$$ErrorBarStateImplCopyWithImpl<$Res>
/// @nodoc
class _$ErrorBarStateImpl implements _ErrorBarState {
const _$ErrorBarStateImpl(
class _$LoadableStateStateImpl implements _LoadableStateState {
const _$LoadableStateStateImpl(
{required final List<ConnectivityResult>? connections})
: _connections = connections;
@ -109,14 +109,14 @@ class _$ErrorBarStateImpl implements _ErrorBarState {
@override
String toString() {
return 'ErrorBarState(connections: $connections)';
return 'LoadableStateState(connections: $connections)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ErrorBarStateImpl &&
other is _$LoadableStateStateImpl &&
const DeepCollectionEquality()
.equals(other._connections, _connections));
}
@ -128,19 +128,20 @@ class _$ErrorBarStateImpl implements _ErrorBarState {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ErrorBarStateImplCopyWith<_$ErrorBarStateImpl> get copyWith =>
__$$ErrorBarStateImplCopyWithImpl<_$ErrorBarStateImpl>(this, _$identity);
_$$LoadableStateStateImplCopyWith<_$LoadableStateStateImpl> get copyWith =>
__$$LoadableStateStateImplCopyWithImpl<_$LoadableStateStateImpl>(
this, _$identity);
}
abstract class _ErrorBarState implements ErrorBarState {
const factory _ErrorBarState(
abstract class _LoadableStateState implements LoadableStateState {
const factory _LoadableStateState(
{required final List<ConnectivityResult>? connections}) =
_$ErrorBarStateImpl;
_$LoadableStateStateImpl;
@override
List<ConnectivityResult>? get connections;
@override
@JsonKey(ignore: true)
_$$ErrorBarStateImplCopyWith<_$ErrorBarStateImpl> get copyWith =>
_$$LoadableStateStateImplCopyWith<_$LoadableStateStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -0,0 +1,25 @@
import 'package:hydrated_bloc/hydrated_bloc.dart';
import '../repository/repository.dart';
import 'loadable_state.dart';
sealed class LoadableHydratedBlocEvent {}
class DataRecieved extends LoadableHydratedBlocEvent {}
abstract class LoadableHydratedBloc<TEvent, TState> extends HydratedBloc<TEvent, LoadableState<TState>> {
LoadableHydratedBloc() : super(const LoadableState()) {
repository().load();
}
Repository repository();
@override
fromJson(Map<String, dynamic> json) => LoadableState(isLoading: true, data: fromStorage(json));
@override
Map<String, dynamic>? toJson(state) => state.data.toJson();
TState fromStorage(Map<String, dynamic> json);
Map<String, dynamic>? toStorage(TState state);
}

View File

@ -0,0 +1,18 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'loadable_state.freezed.dart';
@freezed
class LoadableState<TState> with _$LoadableState {
const LoadableState._();
const factory LoadableState({
@Default(true) bool isLoading,
@Default(null) TState? data,
}) = _LoadableState;
bool showPrimaryLoading() => isLoading && data == null;
bool showBackgroundLoading() => isLoading && data != null;
bool showError() => !isLoading && data == null;
bool showContent() => data != null;
}

View File

@ -0,0 +1,158 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'loadable_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$LoadableState<TState> {
bool get isLoading => throw _privateConstructorUsedError;
TState? get data => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$LoadableStateCopyWith<TState, LoadableState<TState>> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $LoadableStateCopyWith<TState, $Res> {
factory $LoadableStateCopyWith(LoadableState<TState> value,
$Res Function(LoadableState<TState>) then) =
_$LoadableStateCopyWithImpl<TState, $Res, LoadableState<TState>>;
@useResult
$Res call({bool isLoading, TState? data});
}
/// @nodoc
class _$LoadableStateCopyWithImpl<TState, $Res,
$Val extends LoadableState<TState>>
implements $LoadableStateCopyWith<TState, $Res> {
_$LoadableStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isLoading = null,
Object? data = freezed,
}) {
return _then(_value.copyWith(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
data: freezed == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as TState?,
) as $Val);
}
}
/// @nodoc
abstract class _$$LoadableStateImplCopyWith<TState, $Res>
implements $LoadableStateCopyWith<TState, $Res> {
factory _$$LoadableStateImplCopyWith(_$LoadableStateImpl<TState> value,
$Res Function(_$LoadableStateImpl<TState>) then) =
__$$LoadableStateImplCopyWithImpl<TState, $Res>;
@override
@useResult
$Res call({bool isLoading, TState? data});
}
/// @nodoc
class __$$LoadableStateImplCopyWithImpl<TState, $Res>
extends _$LoadableStateCopyWithImpl<TState, $Res,
_$LoadableStateImpl<TState>>
implements _$$LoadableStateImplCopyWith<TState, $Res> {
__$$LoadableStateImplCopyWithImpl(_$LoadableStateImpl<TState> _value,
$Res Function(_$LoadableStateImpl<TState>) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isLoading = null,
Object? data = freezed,
}) {
return _then(_$LoadableStateImpl<TState>(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
data: freezed == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as TState?,
));
}
}
/// @nodoc
class _$LoadableStateImpl<TState> extends _LoadableState<TState> {
const _$LoadableStateImpl({this.isLoading = true, this.data = null})
: super._();
@override
@JsonKey()
final bool isLoading;
@override
@JsonKey()
final TState? data;
@override
String toString() {
return 'LoadableState<$TState>(isLoading: $isLoading, data: $data)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$LoadableStateImpl<TState> &&
(identical(other.isLoading, isLoading) ||
other.isLoading == isLoading) &&
const DeepCollectionEquality().equals(other.data, data));
}
@override
int get hashCode => Object.hash(
runtimeType, isLoading, const DeepCollectionEquality().hash(data));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$LoadableStateImplCopyWith<TState, _$LoadableStateImpl<TState>>
get copyWith => __$$LoadableStateImplCopyWithImpl<TState,
_$LoadableStateImpl<TState>>(this, _$identity);
}
abstract class _LoadableState<TState> extends LoadableState<TState> {
const factory _LoadableState({final bool isLoading, final TState? data}) =
_$LoadableStateImpl<TState>;
const _LoadableState._() : super._();
@override
bool get isLoading;
@override
TState? get data;
@override
@JsonKey(ignore: true)
_$$LoadableStateImplCopyWith<TState, _$LoadableStateImpl<TState>>
get copyWith => throw _privateConstructorUsedError;
}

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
class BackgroundLoadingIndicator extends StatelessWidget {
class LoadableStateBackgroundLoading extends StatelessWidget {
final bool visible;
const BackgroundLoadingIndicator({required this.visible, super.key});
const LoadableStateBackgroundLoading({required this.visible, super.key});
final Duration animationDuration = const Duration(milliseconds: 200);

View File

@ -0,0 +1,42 @@
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../loadable_state.dart';
import 'loadable_state_background_loading.dart';
import 'loadable_state_error_bar.dart';
import 'loadable_state_primary_loading.dart';
// TODO might be a simpler way
class LoadableStateConsumer<TController extends Bloc<dynamic, TWrappedState>, TWrappedState extends LoadableState<TState>, TState> extends StatelessWidget {
final Widget Function(TState state) child;
const LoadableStateConsumer({required this.child, super.key});
static Duration animationDuration = const Duration(milliseconds: 200);
@override
Widget build(BuildContext context) {
var state = context.read<TController>().state as LoadableState<TState>;
return Column(
children: [
LoadableStateErrorBar(visible: state.showError()),
Expanded(
child: Stack(
children: [
LoadableStatePrimaryLoading(visible: state.showPrimaryLoading()),
LoadableStateBackgroundLoading(visible: state.showBackgroundLoading()),
AnimatedOpacity(
opacity: state.showContent() ? 1.0 : 0.0,
duration: animationDuration,
curve: Curves.easeInOut,
child: state.showContent() ? child(state.data) : const SizedBox.shrink()
),
],
),
)
],
);
}
}

View File

@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../utilityWidgets/bloc_providing_builder.dart';
import '../bloc/loadable_state_bloc.dart';
import '../bloc/loadable_state_state.dart';
class LoadableStateErrorBar extends StatelessWidget {
final bool visible;
const LoadableStateErrorBar({required this.visible, super.key});
final Duration animationDuration = const Duration(milliseconds: 200);
@override
Widget build(BuildContext context) => BlocProvidingBuilder<LoadableStateBloc, LoadableStateState>(
create: (context) => LoadableStateBloc(),
child: (context, state) => AnimatedSize(
duration: animationDuration,
child: AnimatedSwitcher(
duration: animationDuration,
transitionBuilder: (Widget child, Animation<double> animation) => SlideTransition(
position: Tween<Offset>(
begin: const Offset(0.0, -1.0),
end: Offset.zero,
).animate(animation),
child: child,
),
child: Visibility(
key: Key(visible.hashCode.toString()),
visible: visible,
replacement: const SizedBox(width: double.infinity),
child: Builder(
builder: (context) {
var controller = context.watch<LoadableStateBloc>();
var status = controller.connectivityStatusKnown() && !controller.isConnected()
? (icon: Icons.wifi_off_outlined, text: 'Offline', color: Colors.grey.shade600)
: (icon: Icons.wifi_find_outlined, text: 'Verbindung fehlgeschlagen', color: Theme.of(context).primaryColor);
return Container(
height: 20,
decoration: BoxDecoration(
color: status.color,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(status.icon, size: 14),
const SizedBox(width: 10),
Text(status.text, style: const TextStyle(fontSize: 12))
],
),
);
},
)
)
),
),
);
}

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
class PrimaryLoadingIndicator extends StatelessWidget {
class LoadableStatePrimaryLoading extends StatelessWidget {
final bool visible;
const PrimaryLoadingIndicator({required this.visible, super.key});
const LoadableStatePrimaryLoading({required this.visible, super.key});
final Duration animationDuration = const Duration(milliseconds: 200);

View File

@ -0,0 +1,13 @@
import '../dataLoader/data_loader.dart';
abstract class Repository {
final List<DataLoader> dataLoaders;
Repository(this.dataLoaders);
Future<void> load() async {
dataLoaders.forEach((element) {
element.fetch();
});
}
}

View File

@ -0,0 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class BlocProvidingBuilder<TBloc extends StateStreamableSource<TState>, TState> extends StatelessWidget {
final TBloc Function(BuildContext context) create;
final Widget Function(BuildContext context, TState state) child;
const BlocProvidingBuilder({required this.create, required this.child, super.key});
@override
Widget build(BuildContext context) => BlocProvider<TBloc>(create: create, child: BlocBuilder<TBloc, TState>(builder: child));
}

View File

@ -7,8 +7,8 @@ import '../bloc/grade_averages_event.dart';
import '../bloc/grade_averages_state.dart';
import 'grade_averages_list_view.dart';
class GradeAveragesScreen extends StatelessWidget {
const GradeAveragesScreen({super.key});
class GradeAveragesView extends StatelessWidget {
const GradeAveragesView({super.key});
@override
Widget build(BuildContext context) => BlocProvider<GradeAveragesBloc>(

View File

@ -0,0 +1,17 @@
import '../../../infrastructure/loadableState/loadable_hydrated_bloc.dart';
import '../../../infrastructure/repository/repository.dart';
import '../repository/marianum_message_repository.dart';
import 'marianum_message_state.dart';
class MarianumMessageBloc extends LoadableHydratedBloc<void, MarianumMessageState> {
MarianumMessageBloc();
@override
MarianumMessageState fromStorage(Map<String, dynamic> json) => MarianumMessageState.fromJson(json);
@override
Map<String, dynamic>? toStorage(MarianumMessageState state) => state.toJson();
@override
Repository repository() => MarianumMessageRepository(emit);
}

View File

@ -0,0 +1,41 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'marianum_message_state.freezed.dart';
part 'marianum_message_state.g.dart';
@freezed
class MarianumMessageState with _$MarianumMessageState {
const factory MarianumMessageState({
required MarianumMessageList messageList,
}) = _MarianumMessageState;
factory MarianumMessageState.fromJson(Map<String, dynamic> json) => _$MarianumMessageStateFromJson(json);
}
@freezed
class MarianumMessageList with _$MarianumMessageList {
const factory MarianumMessageList({
required String base,
required List<MarianumMessage> messages,
}) = _MarianumMessageList;
factory MarianumMessageList.fromJson(Map<String, dynamic> json) => _$MarianumMessageListFromJson(json);
}
@freezed
class MarianumMessage with _$MarianumMessage {
const factory MarianumMessage({
required String name,
required String date,
required String url,
}) = _MarianumMessage;
factory MarianumMessage.fromJson(Map<String, dynamic> json) => _$MarianumMessageFromJson(json);
}
enum GradeAveragesGradingSystem {
highSchool,
middleSchool,
}

View File

@ -0,0 +1,507 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'marianum_message_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
MarianumMessageState _$MarianumMessageStateFromJson(Map<String, dynamic> json) {
return _MarianumMessageState.fromJson(json);
}
/// @nodoc
mixin _$MarianumMessageState {
MarianumMessageList get messageList => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$MarianumMessageStateCopyWith<MarianumMessageState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $MarianumMessageStateCopyWith<$Res> {
factory $MarianumMessageStateCopyWith(MarianumMessageState value,
$Res Function(MarianumMessageState) then) =
_$MarianumMessageStateCopyWithImpl<$Res, MarianumMessageState>;
@useResult
$Res call({MarianumMessageList messageList});
$MarianumMessageListCopyWith<$Res> get messageList;
}
/// @nodoc
class _$MarianumMessageStateCopyWithImpl<$Res,
$Val extends MarianumMessageState>
implements $MarianumMessageStateCopyWith<$Res> {
_$MarianumMessageStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? messageList = null,
}) {
return _then(_value.copyWith(
messageList: null == messageList
? _value.messageList
: messageList // ignore: cast_nullable_to_non_nullable
as MarianumMessageList,
) as $Val);
}
@override
@pragma('vm:prefer-inline')
$MarianumMessageListCopyWith<$Res> get messageList {
return $MarianumMessageListCopyWith<$Res>(_value.messageList, (value) {
return _then(_value.copyWith(messageList: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$MarianumMessageStateImplCopyWith<$Res>
implements $MarianumMessageStateCopyWith<$Res> {
factory _$$MarianumMessageStateImplCopyWith(_$MarianumMessageStateImpl value,
$Res Function(_$MarianumMessageStateImpl) then) =
__$$MarianumMessageStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({MarianumMessageList messageList});
@override
$MarianumMessageListCopyWith<$Res> get messageList;
}
/// @nodoc
class __$$MarianumMessageStateImplCopyWithImpl<$Res>
extends _$MarianumMessageStateCopyWithImpl<$Res, _$MarianumMessageStateImpl>
implements _$$MarianumMessageStateImplCopyWith<$Res> {
__$$MarianumMessageStateImplCopyWithImpl(_$MarianumMessageStateImpl _value,
$Res Function(_$MarianumMessageStateImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? messageList = null,
}) {
return _then(_$MarianumMessageStateImpl(
messageList: null == messageList
? _value.messageList
: messageList // ignore: cast_nullable_to_non_nullable
as MarianumMessageList,
));
}
}
/// @nodoc
@JsonSerializable()
class _$MarianumMessageStateImpl implements _MarianumMessageState {
const _$MarianumMessageStateImpl({required this.messageList});
factory _$MarianumMessageStateImpl.fromJson(Map<String, dynamic> json) =>
_$$MarianumMessageStateImplFromJson(json);
@override
final MarianumMessageList messageList;
@override
String toString() {
return 'MarianumMessageState(messageList: $messageList)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarianumMessageStateImpl &&
(identical(other.messageList, messageList) ||
other.messageList == messageList));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, messageList);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl>
get copyWith =>
__$$MarianumMessageStateImplCopyWithImpl<_$MarianumMessageStateImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$MarianumMessageStateImplToJson(
this,
);
}
}
abstract class _MarianumMessageState implements MarianumMessageState {
const factory _MarianumMessageState(
{required final MarianumMessageList messageList}) =
_$MarianumMessageStateImpl;
factory _MarianumMessageState.fromJson(Map<String, dynamic> json) =
_$MarianumMessageStateImpl.fromJson;
@override
MarianumMessageList get messageList;
@override
@JsonKey(ignore: true)
_$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl>
get copyWith => throw _privateConstructorUsedError;
}
MarianumMessageList _$MarianumMessageListFromJson(Map<String, dynamic> json) {
return _MarianumMessageList.fromJson(json);
}
/// @nodoc
mixin _$MarianumMessageList {
String get base => throw _privateConstructorUsedError;
List<MarianumMessage> get messages => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$MarianumMessageListCopyWith<MarianumMessageList> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $MarianumMessageListCopyWith<$Res> {
factory $MarianumMessageListCopyWith(
MarianumMessageList value, $Res Function(MarianumMessageList) then) =
_$MarianumMessageListCopyWithImpl<$Res, MarianumMessageList>;
@useResult
$Res call({String base, List<MarianumMessage> messages});
}
/// @nodoc
class _$MarianumMessageListCopyWithImpl<$Res, $Val extends MarianumMessageList>
implements $MarianumMessageListCopyWith<$Res> {
_$MarianumMessageListCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? base = null,
Object? messages = null,
}) {
return _then(_value.copyWith(
base: null == base
? _value.base
: base // ignore: cast_nullable_to_non_nullable
as String,
messages: null == messages
? _value.messages
: messages // ignore: cast_nullable_to_non_nullable
as List<MarianumMessage>,
) as $Val);
}
}
/// @nodoc
abstract class _$$MarianumMessageListImplCopyWith<$Res>
implements $MarianumMessageListCopyWith<$Res> {
factory _$$MarianumMessageListImplCopyWith(_$MarianumMessageListImpl value,
$Res Function(_$MarianumMessageListImpl) then) =
__$$MarianumMessageListImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String base, List<MarianumMessage> messages});
}
/// @nodoc
class __$$MarianumMessageListImplCopyWithImpl<$Res>
extends _$MarianumMessageListCopyWithImpl<$Res, _$MarianumMessageListImpl>
implements _$$MarianumMessageListImplCopyWith<$Res> {
__$$MarianumMessageListImplCopyWithImpl(_$MarianumMessageListImpl _value,
$Res Function(_$MarianumMessageListImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? base = null,
Object? messages = null,
}) {
return _then(_$MarianumMessageListImpl(
base: null == base
? _value.base
: base // ignore: cast_nullable_to_non_nullable
as String,
messages: null == messages
? _value._messages
: messages // ignore: cast_nullable_to_non_nullable
as List<MarianumMessage>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$MarianumMessageListImpl implements _MarianumMessageList {
const _$MarianumMessageListImpl(
{required this.base, required final List<MarianumMessage> messages})
: _messages = messages;
factory _$MarianumMessageListImpl.fromJson(Map<String, dynamic> json) =>
_$$MarianumMessageListImplFromJson(json);
@override
final String base;
final List<MarianumMessage> _messages;
@override
List<MarianumMessage> get messages {
if (_messages is EqualUnmodifiableListView) return _messages;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_messages);
}
@override
String toString() {
return 'MarianumMessageList(base: $base, messages: $messages)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarianumMessageListImpl &&
(identical(other.base, base) || other.base == base) &&
const DeepCollectionEquality().equals(other._messages, _messages));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType, base, const DeepCollectionEquality().hash(_messages));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$MarianumMessageListImplCopyWith<_$MarianumMessageListImpl> get copyWith =>
__$$MarianumMessageListImplCopyWithImpl<_$MarianumMessageListImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$MarianumMessageListImplToJson(
this,
);
}
}
abstract class _MarianumMessageList implements MarianumMessageList {
const factory _MarianumMessageList(
{required final String base,
required final List<MarianumMessage> messages}) =
_$MarianumMessageListImpl;
factory _MarianumMessageList.fromJson(Map<String, dynamic> json) =
_$MarianumMessageListImpl.fromJson;
@override
String get base;
@override
List<MarianumMessage> get messages;
@override
@JsonKey(ignore: true)
_$$MarianumMessageListImplCopyWith<_$MarianumMessageListImpl> get copyWith =>
throw _privateConstructorUsedError;
}
MarianumMessage _$MarianumMessageFromJson(Map<String, dynamic> json) {
return _MarianumMessage.fromJson(json);
}
/// @nodoc
mixin _$MarianumMessage {
String get name => throw _privateConstructorUsedError;
String get date => throw _privateConstructorUsedError;
String get url => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$MarianumMessageCopyWith<MarianumMessage> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $MarianumMessageCopyWith<$Res> {
factory $MarianumMessageCopyWith(
MarianumMessage value, $Res Function(MarianumMessage) then) =
_$MarianumMessageCopyWithImpl<$Res, MarianumMessage>;
@useResult
$Res call({String name, String date, String url});
}
/// @nodoc
class _$MarianumMessageCopyWithImpl<$Res, $Val extends MarianumMessage>
implements $MarianumMessageCopyWith<$Res> {
_$MarianumMessageCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? date = null,
Object? url = null,
}) {
return _then(_value.copyWith(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
date: null == date
? _value.date
: date // ignore: cast_nullable_to_non_nullable
as String,
url: null == url
? _value.url
: url // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$MarianumMessageImplCopyWith<$Res>
implements $MarianumMessageCopyWith<$Res> {
factory _$$MarianumMessageImplCopyWith(_$MarianumMessageImpl value,
$Res Function(_$MarianumMessageImpl) then) =
__$$MarianumMessageImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String name, String date, String url});
}
/// @nodoc
class __$$MarianumMessageImplCopyWithImpl<$Res>
extends _$MarianumMessageCopyWithImpl<$Res, _$MarianumMessageImpl>
implements _$$MarianumMessageImplCopyWith<$Res> {
__$$MarianumMessageImplCopyWithImpl(
_$MarianumMessageImpl _value, $Res Function(_$MarianumMessageImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? date = null,
Object? url = null,
}) {
return _then(_$MarianumMessageImpl(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
date: null == date
? _value.date
: date // ignore: cast_nullable_to_non_nullable
as String,
url: null == url
? _value.url
: url // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
@JsonSerializable()
class _$MarianumMessageImpl implements _MarianumMessage {
const _$MarianumMessageImpl(
{required this.name, required this.date, required this.url});
factory _$MarianumMessageImpl.fromJson(Map<String, dynamic> json) =>
_$$MarianumMessageImplFromJson(json);
@override
final String name;
@override
final String date;
@override
final String url;
@override
String toString() {
return 'MarianumMessage(name: $name, date: $date, url: $url)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarianumMessageImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.date, date) || other.date == date) &&
(identical(other.url, url) || other.url == url));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, name, date, url);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$MarianumMessageImplCopyWith<_$MarianumMessageImpl> get copyWith =>
__$$MarianumMessageImplCopyWithImpl<_$MarianumMessageImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$MarianumMessageImplToJson(
this,
);
}
}
abstract class _MarianumMessage implements MarianumMessage {
const factory _MarianumMessage(
{required final String name,
required final String date,
required final String url}) = _$MarianumMessageImpl;
factory _MarianumMessage.fromJson(Map<String, dynamic> json) =
_$MarianumMessageImpl.fromJson;
@override
String get name;
@override
String get date;
@override
String get url;
@override
@JsonKey(ignore: true)
_$$MarianumMessageImplCopyWith<_$MarianumMessageImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -0,0 +1,52 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'marianum_message_state.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$MarianumMessageStateImpl _$$MarianumMessageStateImplFromJson(
Map<String, dynamic> json) =>
_$MarianumMessageStateImpl(
messageList: MarianumMessageList.fromJson(
json['messageList'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$MarianumMessageStateImplToJson(
_$MarianumMessageStateImpl instance) =>
<String, dynamic>{
'messageList': instance.messageList,
};
_$MarianumMessageListImpl _$$MarianumMessageListImplFromJson(
Map<String, dynamic> json) =>
_$MarianumMessageListImpl(
base: json['base'] as String,
messages: (json['messages'] as List<dynamic>)
.map((e) => MarianumMessage.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$MarianumMessageListImplToJson(
_$MarianumMessageListImpl instance) =>
<String, dynamic>{
'base': instance.base,
'messages': instance.messages,
};
_$MarianumMessageImpl _$$MarianumMessageImplFromJson(
Map<String, dynamic> json) =>
_$MarianumMessageImpl(
name: json['name'] as String,
date: json['date'] as String,
url: json['url'] as String,
);
Map<String, dynamic> _$$MarianumMessageImplToJson(
_$MarianumMessageImpl instance) =>
<String, dynamic>{
'name': instance.name,
'date': instance.date,
'url': instance.url,
};

View File

@ -0,0 +1,6 @@
import '../../../infrastructure/dataLoader/data_loader.dart';
class MarianumMessageGetMessages extends DataLoader {
@override
Future fetch() => Future(() => 'Test');
}

View File

@ -0,0 +1,9 @@
import '../../../infrastructure/loadableState/loadable_state.dart';
import '../../../infrastructure/repository/repository.dart';
import '../dataProvider/marianum_message_get_messages.dart';
class MarianumMessageRepository<TState> extends Repository {
MarianumMessageRepository(void Function(LoadableState<TState> content) emit) : super([
MarianumMessageGetMessages(),
]);
}

View File

@ -0,0 +1,49 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import '../../../../../api/mhsl/message/getMessages/getMessagesResponse.dart';
import '../../../../../view/pages/more/message/messageView.dart';
import '../../../infrastructure/loadableState/loadable_state.dart';
import '../../../infrastructure/loadableState/view/loadable_state_consumer.dart';
import '../../../infrastructure/utilityWidgets/bloc_providing_builder.dart';
import '../bloc/marianum_message_bloc.dart';
import '../bloc/marianum_message_state.dart';
class MarianumMessageListView extends StatelessWidget {
const MarianumMessageListView({super.key});
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Marianum Message'),
),
body: BlocProvidingBuilder<MarianumMessageBloc, LoadableState<MarianumMessageState>>(
create: (context) => MarianumMessageBloc(),
child: (context, state) {
// if(value.primaryLoading()) return const LoadingSpinner();
log(state.toString());
return LoadableStateConsumer<MarianumMessageBloc, LoadableState<MarianumMessageState>, MarianumMessageState>(
child: (state) => ListView.builder(
itemCount: state.messageList.messages.length,
itemBuilder: (context, index) {
var message = state.messageList.messages.toList()[index];
return ListTile(
leading: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Icon(Icons.newspaper)],
),
title: Text(message.name, overflow: TextOverflow.ellipsis),
subtitle: Text('vom ${message.date}'),
trailing: const Icon(Icons.arrow_right),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => MessageView(basePath: state.messageList.base, message: message as GetMessagesResponseObject)));
},
);
}
),
);
}
),
);
}

View File

@ -1,58 +0,0 @@
// import 'package:flutter/material.dart';
//
// import '../../app/base/infrastructure/errorBar/error_bar_controller.dart';
// import '../../infrastructure/state_extensions.dart';
// import '../controller_provider.dart';
//
// class ErrorBar extends StatelessWidget {
// final bool visible;
// const ErrorBar({required this.visible, super.key});
//
// final Duration animationDuration = const Duration(milliseconds: 200);
//
// @override
// Widget build(BuildContext context) => ControllerProvider<ErrorBarController>(
// create: (context) => ErrorBarController(),
// child: (context) => AnimatedSize(
// duration: animationDuration,
// child: AnimatedSwitcher(
// duration: animationDuration,
// transitionBuilder: (Widget child, Animation<double> animation) => SlideTransition(
// position: Tween<Offset>(
// begin: const Offset(0.0, -1.0),
// end: Offset.zero,
// ).animate(animation),
// child: child,
// ),
// child: Visibility(
// key: Key(visible.hashCode.toString()),
// visible: visible,
// replacement: const SizedBox(width: double.infinity),
// child: Builder(
// builder: (context) {
// var controller = context.watchController<ErrorBarController>();
// var status = controller.connectivityStatusKnown() && !controller.isConnected()
// ? (icon: Icons.wifi_off_outlined, text: 'Offline', color: Colors.grey.shade600)
// : (icon: Icons.wifi_find_outlined, text: 'Verbindung fehlgeschlagen', color: Theme.of(context).primaryColor);
//
// return Container(
// height: 20,
// decoration: BoxDecoration(
// color: status.color,
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Icon(status.icon, size: 14),
// const SizedBox(width: 10),
// Text(status.text, style: const TextStyle(fontSize: 12))
// ],
// ),
// );
// },
// )
// )
// ),
// ),
// );
// }

View File

@ -1,12 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_bloc/flutter_bloc.dart';
//
// import '../infrastructure/controller.dart';
//
// class ControllerConsumer<TController extends Controller<TState>, TState> extends StatelessWidget {
// final Widget Function(BuildContext context, TState state) child;
// const ControllerConsumer({required this.child, super.key});
//
// @override
// Widget build(BuildContext context) => BlocBuilder<TController, TState>(builder: child);
// }

View File

@ -1,21 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_bloc/flutter_bloc.dart';
// import 'package:provider/single_child_widget.dart';
//
// import '../infrastructure/controller.dart';
//
//
// class ControllerProvider<TState extends Controller> extends SingleChildStatelessWidget {
// final TState Function(BuildContext context) create;
// final bool lazy;
// final Widget Function(BuildContext context) child;
// ControllerProvider({required this.create, this.lazy = true, required this.child, super.key})
// : super(child: Builder(builder: child));
//
// @override
// Widget buildWithChild(BuildContext context, Widget? child) => BlocProvider(
// create: create,
// lazy: lazy,
// child: child,
// );
// }

View File

@ -1,17 +0,0 @@
//
// import 'package:flutter/material.dart';
// import 'package:flutter_bloc/flutter_bloc.dart';
//
// import 'controller_provider.dart';
//
// class ControllersProvider extends StatelessWidget {
// final List<ControllerProvider> controllers;
// final Widget Function(BuildContext context) child;
// const ControllersProvider({required this.controllers, required this.child, super.key});
//
// @override
// Widget build(BuildContext context) => MultiBlocProvider(
// providers: controllers,
// child: Builder(builder: child)
// );
// }

View File

@ -1,42 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_bloc/flutter_bloc.dart';
//
// import '../infrastructure/controller.dart';
// import '../infrastructure/loadable_state.dart';
// import '../infrastructure/state_extensions.dart';
// import 'components/background_loading_indicator.dart';
// import 'components/error_bar.dart';
// import 'components/primary_loading_indicator.dart';
//
// class LoadableControllerConsumer<TController extends Controller<TState>, TState extends LoadableState> extends StatelessWidget {
// final Widget child;
// const LoadableControllerConsumer({required this.child, super.key});
//
// final Duration animationDuration = const Duration(milliseconds: 200);
//
// @override
// Widget build(BuildContext context) {
// var state = context.readController<TController>().state;
//
// return Column(
// children: [
// // ErrorBar(visible: state.errorBarVisible()),
// // Expanded(
// // child: Stack(
// // children: [
// // PrimaryLoadingIndicator(visible: !state.hasStateData()),
// // BackgroundLoadingIndicator(visible: state.isBackgroundLoading() && !state.errorBarVisible()),
// //
// // AnimatedOpacity(
// // opacity: state.hasStateData() ? 1.0 : 0.0,
// // duration: animationDuration,
// // curve: Curves.easeInOut,
// // child: state.hasStateData() ? child : const SizedBox.shrink()
// // ),
// // ],
// // ),
// // )
// ],
// );
// }
// }

View File

@ -1,11 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SubSelectedControllerConsumer<TController extends Cubit<TFullState>, TFullState, TFilteredState> extends StatelessWidget {
final Widget Function(BuildContext context, TFilteredState state) child;
final TFilteredState Function(TFullState state) subSelect;
const SubSelectedControllerConsumer({required this.subSelect, required this.child, super.key});
@override
Widget build(BuildContext context) => BlocSelector<TController, TFullState, TFilteredState>(selector: subSelect, builder: child);
}

View File

@ -4,7 +4,7 @@
// import '../../../state/infrastructure/loadable_state.dart';
// import '../../../state/infrastructure/state_extensions.dart';
// import '../../../state/widgets/controller_consumer.dart';
// import '../../../state/widgets/loadable_controller_consumer.dart';
// import '../../../state/widgets/loadable_state_consumer.dart';
// import '../../../state/widgets/sub_selected_controller_consumer.dart';
// import '../../../state/widgets/controller_provider.dart';
//

View File

@ -6,15 +6,14 @@ import 'package:in_app_review/in_app_review.dart';
import '../../extensions/renderNotNull.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart';
import '../../state/app/modules/gradeAverages/screens/grade_averages_view.dart';
import '../../state/app/modules/gradeAverages/view/grade_averages_view.dart';
import '../../state/app/modules/marianumMessage/view/marianum_message_list_view.dart';
import '../../widget/ListItem.dart';
import '../../widget/centeredLeading.dart';
import '../../widget/infoDialog.dart';
import '../settings/settings.dart';
import 'more/feedback/feedbackDialog.dart';
import 'more/gradeAverages/gradeAverage.dart';
import 'more/holidays/holidays.dart';
import 'more/message/message.dart';
import 'more/roomplan/roomplan.dart';
import 'more/share/selectShareTypeDialog.dart';
@ -31,9 +30,9 @@ class Overhang extends StatelessWidget {
),
body: ListView(
children: [
const ListItemNavigator(icon: Icons.newspaper, text: 'Marianum Message', target: Message()),
const ListItemNavigator(icon: Icons.newspaper, text: 'Marianum Message', target: MarianumMessageListView()),
const ListItemNavigator(icon: Icons.room, text: 'Raumplan', target: Roomplan()),
const ListItemNavigator(icon: Icons.calculate, text: 'Notendurschnittsrechner', target: GradeAverage()),
const ListItemNavigator(icon: Icons.calculate, text: 'Notendurschnittsrechner', target: GradeAveragesView()),
const ListItemNavigator(icon: Icons.calendar_month, text: 'Schulferien', target: Holidays()),
const Divider(),
ListTile(
@ -77,7 +76,7 @@ class Overhang extends StatelessWidget {
),
ListTile(
leading: const Icon(Icons.science_outlined),
onTap: () => pushScreen(context, withNavBar: false, screen: const GradeAveragesScreen()),
// onTap: () => pushScreen(context, withNavBar: false, screen: const GradeAveragesScreen()),
)
],
),

View File

@ -1,6 +1,7 @@
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:provider/provider.dart';
import '../../storage/base/settingsProvider.dart';
@ -109,6 +110,26 @@ class _DevToolsSettingsDialogState extends State<DevToolsSettingsDialog> {
},
trailing: const Icon(Icons.arrow_right),
),
ListTile(
leading: const CenteredLeading(Icon(Icons.data_object)),
title: const Text('BLOC State cache'),
subtitle: FutureBuilder(
future: const CacheView().totalSize(),
builder: (context, snapshot) => Text("etwa ${snapshot.hasError ? "?" : snapshot.hasData ? filesize(snapshot.data) : "..."}\nLange tippen um zu löschen"),
),
onTap: () {
// Navigator.push(context, MaterialPageRoute(builder: (context) => const CacheView()));
},
onLongPress: () {
ConfirmDialog(
title: 'BLOC-Cache löschen',
content: 'Alle cache Einträge werden gelöscht. Der Cache wird bei Nutzung der App automatisch erneut aufgebaut',
confirmButton: 'Unwiederruflich löschen',
onConfirm: () => HydratedBloc.storage.clear(),
).asDialog(context);
},
trailing: const Icon(Icons.arrow_right),
),
],
);
}