diff --git a/lib/state/app/infrastructure/dataLoader/data_loader.dart b/lib/state/app/infrastructure/dataLoader/data_loader.dart new file mode 100644 index 0000000..6f84cb1 --- /dev/null +++ b/lib/state/app/infrastructure/dataLoader/data_loader.dart @@ -0,0 +1,4 @@ +abstract class DataLoader { + + Future fetch(); +} diff --git a/lib/state/app/base/infrastructure/errorBar/error_bar_controller.dart b/lib/state/app/infrastructure/loadableState/bloc/loadable_state_bloc.dart similarity index 73% rename from lib/state/app/base/infrastructure/errorBar/error_bar_controller.dart rename to lib/state/app/infrastructure/loadableState/bloc/loadable_state_bloc.dart index b5a7858..a2cb062 100644 --- a/lib/state/app/base/infrastructure/errorBar/error_bar_controller.dart +++ b/lib/state/app/infrastructure/loadableState/bloc/loadable_state_bloc.dart @@ -1,16 +1,16 @@ 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 { +class LoadableStateBloc extends Bloc { late StreamSubscription> _updateStream; - ErrorBarController() : super(const ErrorBarState(connections: null)) { + LoadableStateBloc() : super(const LoadableStateState(connections: null)) { emitState(List v) => emit(state.copyWith(connections: v)); - + Connectivity().checkConnectivity().then(emitState); _updateStream = Connectivity().onConnectivityChanged.listen(emitState); } diff --git a/lib/state/app/base/infrastructure/errorBar/error_bar_state.dart b/lib/state/app/infrastructure/loadableState/bloc/loadable_state_state.dart similarity index 53% rename from lib/state/app/base/infrastructure/errorBar/error_bar_state.dart rename to lib/state/app/infrastructure/loadableState/bloc/loadable_state_state.dart index 59a8b22..712c9fd 100644 --- a/lib/state/app/base/infrastructure/errorBar/error_bar_state.dart +++ b/lib/state/app/infrastructure/loadableState/bloc/loadable_state_state.dart @@ -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? connections, - }) = _ErrorBarState; + }) = _LoadableStateState; } diff --git a/lib/state/app/base/infrastructure/errorBar/error_bar_state.freezed.dart b/lib/state/app/infrastructure/loadableState/bloc/loadable_state_state.freezed.dart similarity index 64% rename from lib/state/app/base/infrastructure/errorBar/error_bar_state.freezed.dart rename to lib/state/app/infrastructure/loadableState/bloc/loadable_state_state.freezed.dart index 2e60c16..66011f9 100644 --- a/lib/state/app/base/infrastructure/errorBar/error_bar_state.freezed.dart +++ b/lib/state/app/infrastructure/loadableState/bloc/loadable_state_state.freezed.dart @@ -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? get connections => throw _privateConstructorUsedError; @JsonKey(ignore: true) - $ErrorBarStateCopyWith get copyWith => + $LoadableStateStateCopyWith 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? 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? 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? 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? connections}) = - _$ErrorBarStateImpl; + _$LoadableStateStateImpl; @override List? get connections; @override @JsonKey(ignore: true) - _$$ErrorBarStateImplCopyWith<_$ErrorBarStateImpl> get copyWith => + _$$LoadableStateStateImplCopyWith<_$LoadableStateStateImpl> get copyWith => throw _privateConstructorUsedError; } diff --git a/lib/state/app/infrastructure/loadableState/loadable_hydrated_bloc.dart b/lib/state/app/infrastructure/loadableState/loadable_hydrated_bloc.dart new file mode 100644 index 0000000..5694249 --- /dev/null +++ b/lib/state/app/infrastructure/loadableState/loadable_hydrated_bloc.dart @@ -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 extends HydratedBloc> { + LoadableHydratedBloc() : super(const LoadableState()) { + repository().load(); + + } + + Repository repository(); + + + @override + fromJson(Map json) => LoadableState(isLoading: true, data: fromStorage(json)); + @override + Map? toJson(state) => state.data.toJson(); + + TState fromStorage(Map json); + Map? toStorage(TState state); +} diff --git a/lib/state/app/infrastructure/loadableState/loadable_state.dart b/lib/state/app/infrastructure/loadableState/loadable_state.dart new file mode 100644 index 0000000..6c25efc --- /dev/null +++ b/lib/state/app/infrastructure/loadableState/loadable_state.dart @@ -0,0 +1,18 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'loadable_state.freezed.dart'; + +@freezed +class LoadableState 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; +} diff --git a/lib/state/app/infrastructure/loadableState/loadable_state.freezed.dart b/lib/state/app/infrastructure/loadableState/loadable_state.freezed.dart new file mode 100644 index 0000000..3bfb969 --- /dev/null +++ b/lib/state/app/infrastructure/loadableState/loadable_state.freezed.dart @@ -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 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 { + bool get isLoading => throw _privateConstructorUsedError; + TState? get data => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $LoadableStateCopyWith> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LoadableStateCopyWith { + factory $LoadableStateCopyWith(LoadableState value, + $Res Function(LoadableState) then) = + _$LoadableStateCopyWithImpl>; + @useResult + $Res call({bool isLoading, TState? data}); +} + +/// @nodoc +class _$LoadableStateCopyWithImpl> + implements $LoadableStateCopyWith { + _$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 + implements $LoadableStateCopyWith { + factory _$$LoadableStateImplCopyWith(_$LoadableStateImpl value, + $Res Function(_$LoadableStateImpl) then) = + __$$LoadableStateImplCopyWithImpl; + @override + @useResult + $Res call({bool isLoading, TState? data}); +} + +/// @nodoc +class __$$LoadableStateImplCopyWithImpl + extends _$LoadableStateCopyWithImpl> + implements _$$LoadableStateImplCopyWith { + __$$LoadableStateImplCopyWithImpl(_$LoadableStateImpl _value, + $Res Function(_$LoadableStateImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? isLoading = null, + Object? data = freezed, + }) { + return _then(_$LoadableStateImpl( + 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 extends _LoadableState { + 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 && + (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> + get copyWith => __$$LoadableStateImplCopyWithImpl>(this, _$identity); +} + +abstract class _LoadableState extends LoadableState { + const factory _LoadableState({final bool isLoading, final TState? data}) = + _$LoadableStateImpl; + const _LoadableState._() : super._(); + + @override + bool get isLoading; + @override + TState? get data; + @override + @JsonKey(ignore: true) + _$$LoadableStateImplCopyWith> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/state/widgets/components/background_loading_indicator.dart b/lib/state/app/infrastructure/loadableState/view/loadable_state_background_loading.dart similarity index 80% rename from lib/state/widgets/components/background_loading_indicator.dart rename to lib/state/app/infrastructure/loadableState/view/loadable_state_background_loading.dart index a7c4048..1c10bb0 100644 --- a/lib/state/widgets/components/background_loading_indicator.dart +++ b/lib/state/app/infrastructure/loadableState/view/loadable_state_background_loading.dart @@ -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); diff --git a/lib/state/app/infrastructure/loadableState/view/loadable_state_consumer.dart b/lib/state/app/infrastructure/loadableState/view/loadable_state_consumer.dart new file mode 100644 index 0000000..c3d3c75 --- /dev/null +++ b/lib/state/app/infrastructure/loadableState/view/loadable_state_consumer.dart @@ -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, TWrappedState extends LoadableState, 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().state as LoadableState; + + 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() + ), + ], + ), + ) + ], + ); + } +} diff --git a/lib/state/app/infrastructure/loadableState/view/loadable_state_error_bar.dart b/lib/state/app/infrastructure/loadableState/view/loadable_state_error_bar.dart new file mode 100644 index 0000000..4e21c72 --- /dev/null +++ b/lib/state/app/infrastructure/loadableState/view/loadable_state_error_bar.dart @@ -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( + create: (context) => LoadableStateBloc(), + child: (context, state) => AnimatedSize( + duration: animationDuration, + child: AnimatedSwitcher( + duration: animationDuration, + transitionBuilder: (Widget child, Animation animation) => SlideTransition( + position: Tween( + 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(); + 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)) + ], + ), + ); + }, + ) + ) + ), + ), + ); +} diff --git a/lib/state/widgets/components/primary_loading_indicator.dart b/lib/state/app/infrastructure/loadableState/view/loadable_state_primary_loading.dart similarity index 74% rename from lib/state/widgets/components/primary_loading_indicator.dart rename to lib/state/app/infrastructure/loadableState/view/loadable_state_primary_loading.dart index 4f21fc1..a01ba28 100644 --- a/lib/state/widgets/components/primary_loading_indicator.dart +++ b/lib/state/app/infrastructure/loadableState/view/loadable_state_primary_loading.dart @@ -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); diff --git a/lib/state/app/infrastructure/repository/repository.dart b/lib/state/app/infrastructure/repository/repository.dart new file mode 100644 index 0000000..4a6caae --- /dev/null +++ b/lib/state/app/infrastructure/repository/repository.dart @@ -0,0 +1,13 @@ +import '../dataLoader/data_loader.dart'; + +abstract class Repository { + final List dataLoaders; + + Repository(this.dataLoaders); + + Future load() async { + dataLoaders.forEach((element) { + element.fetch(); + }); + } +} diff --git a/lib/state/app/infrastructure/utilityWidgets/bloc_providing_builder.dart b/lib/state/app/infrastructure/utilityWidgets/bloc_providing_builder.dart new file mode 100644 index 0000000..4c98579 --- /dev/null +++ b/lib/state/app/infrastructure/utilityWidgets/bloc_providing_builder.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class BlocProvidingBuilder, 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(create: create, child: BlocBuilder(builder: child)); +} diff --git a/lib/state/app/modules/gradeAverages/screens/grade_averages_list_view.dart b/lib/state/app/modules/gradeAverages/view/grade_averages_list_view.dart similarity index 100% rename from lib/state/app/modules/gradeAverages/screens/grade_averages_list_view.dart rename to lib/state/app/modules/gradeAverages/view/grade_averages_list_view.dart diff --git a/lib/state/app/modules/gradeAverages/screens/grade_averages_view.dart b/lib/state/app/modules/gradeAverages/view/grade_averages_view.dart similarity index 97% rename from lib/state/app/modules/gradeAverages/screens/grade_averages_view.dart rename to lib/state/app/modules/gradeAverages/view/grade_averages_view.dart index ccda360..c0734ef 100644 --- a/lib/state/app/modules/gradeAverages/screens/grade_averages_view.dart +++ b/lib/state/app/modules/gradeAverages/view/grade_averages_view.dart @@ -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( diff --git a/lib/state/app/modules/marianumMessage/bloc/marianum_message_bloc.dart b/lib/state/app/modules/marianumMessage/bloc/marianum_message_bloc.dart new file mode 100644 index 0000000..0563ae3 --- /dev/null +++ b/lib/state/app/modules/marianumMessage/bloc/marianum_message_bloc.dart @@ -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 { + MarianumMessageBloc(); + + + @override + MarianumMessageState fromStorage(Map json) => MarianumMessageState.fromJson(json); + @override + Map? toStorage(MarianumMessageState state) => state.toJson(); + + @override + Repository repository() => MarianumMessageRepository(emit); +} diff --git a/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.dart b/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.dart new file mode 100644 index 0000000..4f2d7c9 --- /dev/null +++ b/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.dart @@ -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 json) => _$MarianumMessageStateFromJson(json); +} + +@freezed +class MarianumMessageList with _$MarianumMessageList { + const factory MarianumMessageList({ + required String base, + required List messages, + }) = _MarianumMessageList; + + factory MarianumMessageList.fromJson(Map 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 json) => _$MarianumMessageFromJson(json); +} + + +enum GradeAveragesGradingSystem { + highSchool, + middleSchool, +} diff --git a/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.freezed.dart b/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.freezed.dart new file mode 100644 index 0000000..35105e1 --- /dev/null +++ b/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.freezed.dart @@ -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 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 json) { + return _MarianumMessageState.fromJson(json); +} + +/// @nodoc +mixin _$MarianumMessageState { + MarianumMessageList get messageList => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $MarianumMessageStateCopyWith 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 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 toJson() { + return _$$MarianumMessageStateImplToJson( + this, + ); + } +} + +abstract class _MarianumMessageState implements MarianumMessageState { + const factory _MarianumMessageState( + {required final MarianumMessageList messageList}) = + _$MarianumMessageStateImpl; + + factory _MarianumMessageState.fromJson(Map json) = + _$MarianumMessageStateImpl.fromJson; + + @override + MarianumMessageList get messageList; + @override + @JsonKey(ignore: true) + _$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl> + get copyWith => throw _privateConstructorUsedError; +} + +MarianumMessageList _$MarianumMessageListFromJson(Map json) { + return _MarianumMessageList.fromJson(json); +} + +/// @nodoc +mixin _$MarianumMessageList { + String get base => throw _privateConstructorUsedError; + List get messages => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $MarianumMessageListCopyWith 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 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, + ) 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 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, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$MarianumMessageListImpl implements _MarianumMessageList { + const _$MarianumMessageListImpl( + {required this.base, required final List messages}) + : _messages = messages; + + factory _$MarianumMessageListImpl.fromJson(Map json) => + _$$MarianumMessageListImplFromJson(json); + + @override + final String base; + final List _messages; + @override + List 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 toJson() { + return _$$MarianumMessageListImplToJson( + this, + ); + } +} + +abstract class _MarianumMessageList implements MarianumMessageList { + const factory _MarianumMessageList( + {required final String base, + required final List messages}) = + _$MarianumMessageListImpl; + + factory _MarianumMessageList.fromJson(Map json) = + _$MarianumMessageListImpl.fromJson; + + @override + String get base; + @override + List get messages; + @override + @JsonKey(ignore: true) + _$$MarianumMessageListImplCopyWith<_$MarianumMessageListImpl> get copyWith => + throw _privateConstructorUsedError; +} + +MarianumMessage _$MarianumMessageFromJson(Map json) { + return _MarianumMessage.fromJson(json); +} + +/// @nodoc +mixin _$MarianumMessage { + String get name => throw _privateConstructorUsedError; + String get date => throw _privateConstructorUsedError; + String get url => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $MarianumMessageCopyWith 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 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 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 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; +} diff --git a/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.g.dart b/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.g.dart new file mode 100644 index 0000000..80dc1a2 --- /dev/null +++ b/lib/state/app/modules/marianumMessage/bloc/marianum_message_state.g.dart @@ -0,0 +1,52 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'marianum_message_state.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$MarianumMessageStateImpl _$$MarianumMessageStateImplFromJson( + Map json) => + _$MarianumMessageStateImpl( + messageList: MarianumMessageList.fromJson( + json['messageList'] as Map), + ); + +Map _$$MarianumMessageStateImplToJson( + _$MarianumMessageStateImpl instance) => + { + 'messageList': instance.messageList, + }; + +_$MarianumMessageListImpl _$$MarianumMessageListImplFromJson( + Map json) => + _$MarianumMessageListImpl( + base: json['base'] as String, + messages: (json['messages'] as List) + .map((e) => MarianumMessage.fromJson(e as Map)) + .toList(), + ); + +Map _$$MarianumMessageListImplToJson( + _$MarianumMessageListImpl instance) => + { + 'base': instance.base, + 'messages': instance.messages, + }; + +_$MarianumMessageImpl _$$MarianumMessageImplFromJson( + Map json) => + _$MarianumMessageImpl( + name: json['name'] as String, + date: json['date'] as String, + url: json['url'] as String, + ); + +Map _$$MarianumMessageImplToJson( + _$MarianumMessageImpl instance) => + { + 'name': instance.name, + 'date': instance.date, + 'url': instance.url, + }; diff --git a/lib/state/app/modules/marianumMessage/dataProvider/marianum_message_get_messages.dart b/lib/state/app/modules/marianumMessage/dataProvider/marianum_message_get_messages.dart new file mode 100644 index 0000000..694b304 --- /dev/null +++ b/lib/state/app/modules/marianumMessage/dataProvider/marianum_message_get_messages.dart @@ -0,0 +1,6 @@ +import '../../../infrastructure/dataLoader/data_loader.dart'; + +class MarianumMessageGetMessages extends DataLoader { + @override + Future fetch() => Future(() => 'Test'); +} diff --git a/lib/state/app/modules/marianumMessage/repository/marianum_message_repository.dart b/lib/state/app/modules/marianumMessage/repository/marianum_message_repository.dart new file mode 100644 index 0000000..9679f44 --- /dev/null +++ b/lib/state/app/modules/marianumMessage/repository/marianum_message_repository.dart @@ -0,0 +1,9 @@ +import '../../../infrastructure/loadableState/loadable_state.dart'; +import '../../../infrastructure/repository/repository.dart'; +import '../dataProvider/marianum_message_get_messages.dart'; + +class MarianumMessageRepository extends Repository { + MarianumMessageRepository(void Function(LoadableState content) emit) : super([ + MarianumMessageGetMessages(), + ]); +} diff --git a/lib/state/app/modules/marianumMessage/view/marianum_message_list_view.dart b/lib/state/app/modules/marianumMessage/view/marianum_message_list_view.dart new file mode 100644 index 0000000..fa323c7 --- /dev/null +++ b/lib/state/app/modules/marianumMessage/view/marianum_message_list_view.dart @@ -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>( + create: (context) => MarianumMessageBloc(), + child: (context, state) { + // if(value.primaryLoading()) return const LoadingSpinner(); + log(state.toString()); + return LoadableStateConsumer, 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))); + }, + ); + } + ), + ); + } + ), + ); +} diff --git a/lib/state/widgets/components/error_bar.dart b/lib/state/widgets/components/error_bar.dart deleted file mode 100644 index 0d1c8bf..0000000 --- a/lib/state/widgets/components/error_bar.dart +++ /dev/null @@ -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( -// create: (context) => ErrorBarController(), -// child: (context) => AnimatedSize( -// duration: animationDuration, -// child: AnimatedSwitcher( -// duration: animationDuration, -// transitionBuilder: (Widget child, Animation animation) => SlideTransition( -// position: Tween( -// 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(); -// 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)) -// ], -// ), -// ); -// }, -// ) -// ) -// ), -// ), -// ); -// } diff --git a/lib/state/widgets/controller_consumer.dart b/lib/state/widgets/controller_consumer.dart deleted file mode 100644 index c814d94..0000000 --- a/lib/state/widgets/controller_consumer.dart +++ /dev/null @@ -1,12 +0,0 @@ -// import 'package:flutter/material.dart'; -// import 'package:flutter_bloc/flutter_bloc.dart'; -// -// import '../infrastructure/controller.dart'; -// -// class ControllerConsumer, TState> extends StatelessWidget { -// final Widget Function(BuildContext context, TState state) child; -// const ControllerConsumer({required this.child, super.key}); -// -// @override -// Widget build(BuildContext context) => BlocBuilder(builder: child); -// } diff --git a/lib/state/widgets/controller_provider.dart b/lib/state/widgets/controller_provider.dart deleted file mode 100644 index e232ac3..0000000 --- a/lib/state/widgets/controller_provider.dart +++ /dev/null @@ -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 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, -// ); -// } diff --git a/lib/state/widgets/controllers_provider.dart b/lib/state/widgets/controllers_provider.dart deleted file mode 100644 index 1b5417b..0000000 --- a/lib/state/widgets/controllers_provider.dart +++ /dev/null @@ -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 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) -// ); -// } diff --git a/lib/state/widgets/loadable_controller_consumer.dart b/lib/state/widgets/loadable_controller_consumer.dart deleted file mode 100644 index 5fa8b48..0000000 --- a/lib/state/widgets/loadable_controller_consumer.dart +++ /dev/null @@ -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, 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().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() -// // ), -// // ], -// // ), -// // ) -// ], -// ); -// } -// } diff --git a/lib/state/widgets/sub_selected_controller_consumer.dart b/lib/state/widgets/sub_selected_controller_consumer.dart deleted file mode 100644 index fdbe68f..0000000 --- a/lib/state/widgets/sub_selected_controller_consumer.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -class SubSelectedControllerConsumer, 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(selector: subSelect, builder: child); -} diff --git a/lib/view/pages/more/test.dart b/lib/view/pages/more/test.dart index 36ec438..5f68993 100644 --- a/lib/view/pages/more/test.dart +++ b/lib/view/pages/more/test.dart @@ -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'; // diff --git a/lib/view/pages/overhang.dart b/lib/view/pages/overhang.dart index 184953b..599c8f6 100644 --- a/lib/view/pages/overhang.dart +++ b/lib/view/pages/overhang.dart @@ -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()), ) ], ), diff --git a/lib/view/settings/devToolsSettingsDialog.dart b/lib/view/settings/devToolsSettingsDialog.dart index c62cdde..e1fb660 100644 --- a/lib/view/settings/devToolsSettingsDialog.dart +++ b/lib/view/settings/devToolsSettingsDialog.dart @@ -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 { }, 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), + ), ], ); }