From 7129c0dee8bc402a4fd34072afef445e0cb875c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Mon, 22 Apr 2024 23:02:03 +0200 Subject: [PATCH] wip basics for bloc based state management --- analysis_options.yaml | 4 + build.yaml | 6 + .../grade_averages_controller.dart | 10 + .../gradeAverages/grade_averages_state.dart | 19 ++ .../grade_averages_state.freezed.dart | 179 ++++++++++++++++++ .../gradeAverages/grade_averages_state.g.dart | 27 +++ .../marianum_message_controller.dart | 24 +++ .../marianum_message_state.dart | 10 + .../marianum_message_state.freezed.dart | 143 ++++++++++++++ .../app/base/account/account_controller.dart | 0 lib/state/infrastructure/controller.dart | 5 + lib/state/infrastructure/loadable_state.dart | 31 +++ .../infrastructure/state_extensions.dart | 7 + lib/state/widgets/controller_consumer.dart | 12 ++ lib/state/widgets/controller_provider.dart | 21 ++ lib/state/widgets/controllers_provider.dart | 17 ++ .../widgets/loadable_controller_consumer.dart | 39 ++++ .../sub_selected_controller_consumer.dart | 11 ++ lib/view/pages/more/test.dart | 44 +++++ lib/view/pages/overhang.dart | 5 + .../pages/talk/components/chatMessage.dart | 2 +- pubspec.yaml | 10 +- 22 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 build.yaml create mode 100644 lib/state/app/application/gradeAverages/grade_averages_controller.dart create mode 100644 lib/state/app/application/gradeAverages/grade_averages_state.dart create mode 100644 lib/state/app/application/gradeAverages/grade_averages_state.freezed.dart create mode 100644 lib/state/app/application/gradeAverages/grade_averages_state.g.dart create mode 100644 lib/state/app/application/marianumMessage/marianum_message_controller.dart create mode 100644 lib/state/app/application/marianumMessage/marianum_message_state.dart create mode 100644 lib/state/app/application/marianumMessage/marianum_message_state.freezed.dart create mode 100644 lib/state/app/base/account/account_controller.dart create mode 100644 lib/state/infrastructure/controller.dart create mode 100644 lib/state/infrastructure/loadable_state.dart create mode 100644 lib/state/infrastructure/state_extensions.dart create mode 100644 lib/state/widgets/controller_consumer.dart create mode 100644 lib/state/widgets/controller_provider.dart create mode 100644 lib/state/widgets/controllers_provider.dart create mode 100644 lib/state/widgets/loadable_controller_consumer.dart create mode 100644 lib/state/widgets/sub_selected_controller_consumer.dart create mode 100644 lib/view/pages/more/test.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index ebc4a78..a40338c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -9,6 +9,10 @@ # packages, and plugins designed to encourage good coding practices. include: package:flutter_lints/flutter.yaml +analyzer: + errors: + invalid_annotation_target: ignore + linter: # The lint rules applied to this project can be customized in the # section below to disable rules from the `package:flutter_lints/flutter.yaml` diff --git a/build.yaml b/build.yaml new file mode 100644 index 0000000..24cf608 --- /dev/null +++ b/build.yaml @@ -0,0 +1,6 @@ +targets: + $default: + builders: + json_serializable: + options: + explicit_to_json: false \ No newline at end of file diff --git a/lib/state/app/application/gradeAverages/grade_averages_controller.dart b/lib/state/app/application/gradeAverages/grade_averages_controller.dart new file mode 100644 index 0000000..6e0f829 --- /dev/null +++ b/lib/state/app/application/gradeAverages/grade_averages_controller.dart @@ -0,0 +1,10 @@ + +import '../../../infrastructure/controller.dart'; +import 'grade_averages_state.dart'; + +class GradeAveragesController extends Controller { + GradeAveragesController(super.initialState); + + void setGradeType(GradingSchemes scheme) => emit(state.copyWith(gradingScheme: scheme)); + double average() => state.grades.reduce((a, b) => a + b) / state.grades.length; +} diff --git a/lib/state/app/application/gradeAverages/grade_averages_state.dart b/lib/state/app/application/gradeAverages/grade_averages_state.dart new file mode 100644 index 0000000..c9df18e --- /dev/null +++ b/lib/state/app/application/gradeAverages/grade_averages_state.dart @@ -0,0 +1,19 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'grade_averages_state.freezed.dart'; +part 'grade_averages_state.g.dart'; + +@freezed +class GradeAveragesState with _$GradeAveragesState { + const factory GradeAveragesState({ + required GradingSchemes gradingScheme, + required List grades, + }) = _GradeAveragesState; + + factory GradeAveragesState.fromJson(Map json) => _$GradeAveragesStateFromJson(json); +} + +enum GradingSchemes { + middleSchool, + highSchool, +} diff --git a/lib/state/app/application/gradeAverages/grade_averages_state.freezed.dart b/lib/state/app/application/gradeAverages/grade_averages_state.freezed.dart new file mode 100644 index 0000000..9985e09 --- /dev/null +++ b/lib/state/app/application/gradeAverages/grade_averages_state.freezed.dart @@ -0,0 +1,179 @@ +// 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 'grade_averages_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'); + +GradeAveragesState _$GradeAveragesStateFromJson(Map json) { + return _GradeAveragesState.fromJson(json); +} + +/// @nodoc +mixin _$GradeAveragesState { + GradingSchemes get gradingScheme => throw _privateConstructorUsedError; + List get grades => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $GradeAveragesStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $GradeAveragesStateCopyWith<$Res> { + factory $GradeAveragesStateCopyWith( + GradeAveragesState value, $Res Function(GradeAveragesState) then) = + _$GradeAveragesStateCopyWithImpl<$Res, GradeAveragesState>; + @useResult + $Res call({GradingSchemes gradingScheme, List grades}); +} + +/// @nodoc +class _$GradeAveragesStateCopyWithImpl<$Res, $Val extends GradeAveragesState> + implements $GradeAveragesStateCopyWith<$Res> { + _$GradeAveragesStateCopyWithImpl(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? gradingScheme = null, + Object? grades = null, + }) { + return _then(_value.copyWith( + gradingScheme: null == gradingScheme + ? _value.gradingScheme + : gradingScheme // ignore: cast_nullable_to_non_nullable + as GradingSchemes, + grades: null == grades + ? _value.grades + : grades // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$GradeAveragesStateImplCopyWith<$Res> + implements $GradeAveragesStateCopyWith<$Res> { + factory _$$GradeAveragesStateImplCopyWith(_$GradeAveragesStateImpl value, + $Res Function(_$GradeAveragesStateImpl) then) = + __$$GradeAveragesStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({GradingSchemes gradingScheme, List grades}); +} + +/// @nodoc +class __$$GradeAveragesStateImplCopyWithImpl<$Res> + extends _$GradeAveragesStateCopyWithImpl<$Res, _$GradeAveragesStateImpl> + implements _$$GradeAveragesStateImplCopyWith<$Res> { + __$$GradeAveragesStateImplCopyWithImpl(_$GradeAveragesStateImpl _value, + $Res Function(_$GradeAveragesStateImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? gradingScheme = null, + Object? grades = null, + }) { + return _then(_$GradeAveragesStateImpl( + gradingScheme: null == gradingScheme + ? _value.gradingScheme + : gradingScheme // ignore: cast_nullable_to_non_nullable + as GradingSchemes, + grades: null == grades + ? _value._grades + : grades // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$GradeAveragesStateImpl implements _GradeAveragesState { + const _$GradeAveragesStateImpl( + {required this.gradingScheme, required final List grades}) + : _grades = grades; + + factory _$GradeAveragesStateImpl.fromJson(Map json) => + _$$GradeAveragesStateImplFromJson(json); + + @override + final GradingSchemes gradingScheme; + final List _grades; + @override + List get grades { + if (_grades is EqualUnmodifiableListView) return _grades; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_grades); + } + + @override + String toString() { + return 'GradeAveragesState(gradingScheme: $gradingScheme, grades: $grades)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$GradeAveragesStateImpl && + (identical(other.gradingScheme, gradingScheme) || + other.gradingScheme == gradingScheme) && + const DeepCollectionEquality().equals(other._grades, _grades)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, gradingScheme, const DeepCollectionEquality().hash(_grades)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$GradeAveragesStateImplCopyWith<_$GradeAveragesStateImpl> get copyWith => + __$$GradeAveragesStateImplCopyWithImpl<_$GradeAveragesStateImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$GradeAveragesStateImplToJson( + this, + ); + } +} + +abstract class _GradeAveragesState implements GradeAveragesState { + const factory _GradeAveragesState( + {required final GradingSchemes gradingScheme, + required final List grades}) = _$GradeAveragesStateImpl; + + factory _GradeAveragesState.fromJson(Map json) = + _$GradeAveragesStateImpl.fromJson; + + @override + GradingSchemes get gradingScheme; + @override + List get grades; + @override + @JsonKey(ignore: true) + _$$GradeAveragesStateImplCopyWith<_$GradeAveragesStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/state/app/application/gradeAverages/grade_averages_state.g.dart b/lib/state/app/application/gradeAverages/grade_averages_state.g.dart new file mode 100644 index 0000000..056d665 --- /dev/null +++ b/lib/state/app/application/gradeAverages/grade_averages_state.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'grade_averages_state.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$GradeAveragesStateImpl _$$GradeAveragesStateImplFromJson( + Map json) => + _$GradeAveragesStateImpl( + gradingScheme: + $enumDecode(_$GradingSchemesEnumMap, json['gradingScheme']), + grades: (json['grades'] as List).map((e) => e as int).toList(), + ); + +Map _$$GradeAveragesStateImplToJson( + _$GradeAveragesStateImpl instance) => + { + 'gradingScheme': _$GradingSchemesEnumMap[instance.gradingScheme]!, + 'grades': instance.grades, + }; + +const _$GradingSchemesEnumMap = { + GradingSchemes.middleSchool: 'middleSchool', + GradingSchemes.highSchool: 'highSchool', +}; diff --git a/lib/state/app/application/marianumMessage/marianum_message_controller.dart b/lib/state/app/application/marianumMessage/marianum_message_controller.dart new file mode 100644 index 0000000..47e7881 --- /dev/null +++ b/lib/state/app/application/marianumMessage/marianum_message_controller.dart @@ -0,0 +1,24 @@ +import '../../../infrastructure/controller.dart'; +import '../../../infrastructure/loadable_state.dart'; +import 'marianum_message_state.dart'; + +class MarianumMessageController extends Controller> { + MarianumMessageController() : super(const LoadableState(loadingState: LoadingState.none, data: MarianumMessageState(test: []))); + + void loading() { + emit(state.loading()); + Future.delayed(const Duration(seconds: 3)).then((value) => emit(state.done(const MarianumMessageState(test: [])))); + } + + void backgroundLoading() { + emit(state.cached(const MarianumMessageState(test: []))); + } + + void done() { + emit(state.done(const MarianumMessageState(test: []))); + } + + void error() { + + } +} diff --git a/lib/state/app/application/marianumMessage/marianum_message_state.dart b/lib/state/app/application/marianumMessage/marianum_message_state.dart new file mode 100644 index 0000000..9d893f0 --- /dev/null +++ b/lib/state/app/application/marianumMessage/marianum_message_state.dart @@ -0,0 +1,10 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'marianum_message_state.freezed.dart'; + +@freezed +class MarianumMessageState with _$MarianumMessageState { + const factory MarianumMessageState({ + required List test + }) = _MarianumMessageState; +} diff --git a/lib/state/app/application/marianumMessage/marianum_message_state.freezed.dart b/lib/state/app/application/marianumMessage/marianum_message_state.freezed.dart new file mode 100644 index 0000000..49a75a1 --- /dev/null +++ b/lib/state/app/application/marianumMessage/marianum_message_state.freezed.dart @@ -0,0 +1,143 @@ +// 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'); + +/// @nodoc +mixin _$MarianumMessageState { + List get test => 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({List test}); +} + +/// @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? test = null, + }) { + return _then(_value.copyWith( + test: null == test + ? _value.test + : test // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$MarianumMessageStateImplCopyWith<$Res> + implements $MarianumMessageStateCopyWith<$Res> { + factory _$$MarianumMessageStateImplCopyWith(_$MarianumMessageStateImpl value, + $Res Function(_$MarianumMessageStateImpl) then) = + __$$MarianumMessageStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({List test}); +} + +/// @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? test = null, + }) { + return _then(_$MarianumMessageStateImpl( + test: null == test + ? _value._test + : test // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc + +class _$MarianumMessageStateImpl implements _MarianumMessageState { + const _$MarianumMessageStateImpl({required final List test}) + : _test = test; + + final List _test; + @override + List get test { + if (_test is EqualUnmodifiableListView) return _test; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_test); + } + + @override + String toString() { + return 'MarianumMessageState(test: $test)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$MarianumMessageStateImpl && + const DeepCollectionEquality().equals(other._test, _test)); + } + + @override + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(_test)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl> + get copyWith => + __$$MarianumMessageStateImplCopyWithImpl<_$MarianumMessageStateImpl>( + this, _$identity); +} + +abstract class _MarianumMessageState implements MarianumMessageState { + const factory _MarianumMessageState({required final List test}) = + _$MarianumMessageStateImpl; + + @override + List get test; + @override + @JsonKey(ignore: true) + _$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/state/app/base/account/account_controller.dart b/lib/state/app/base/account/account_controller.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/state/infrastructure/controller.dart b/lib/state/infrastructure/controller.dart new file mode 100644 index 0000000..2ceca86 --- /dev/null +++ b/lib/state/infrastructure/controller.dart @@ -0,0 +1,5 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; + +abstract class Controller extends Cubit { + Controller(super.initialState); +} diff --git a/lib/state/infrastructure/loadable_state.dart b/lib/state/infrastructure/loadable_state.dart new file mode 100644 index 0000000..c3b0b12 --- /dev/null +++ b/lib/state/infrastructure/loadable_state.dart @@ -0,0 +1,31 @@ + +class LoadableState { + final LoadingState loadingState; + final TState? data; + + const LoadableState({required this.loadingState, required this.data}); + + LoadableState loading() => + LoadableState(loadingState: LoadingState.loading, data: null); + + LoadableState cached(TState state) => + LoadableState(loadingState: LoadingState.loading, data: state); + + LoadableState done(TState state) => + LoadableState(loadingState: LoadingState.none, data: state); + + LoadableState error(TState state) => + LoadableState(loadingState: LoadingState.none, data: state); + + bool isBackgroundLoading() => + loadingState == LoadingState.loading && data != null; + + bool hasStateData() => + data != null; +} + +enum LoadingState { + loading, + failed, + none, +} diff --git a/lib/state/infrastructure/state_extensions.dart b/lib/state/infrastructure/state_extensions.dart new file mode 100644 index 0000000..1a828e1 --- /dev/null +++ b/lib/state/infrastructure/state_extensions.dart @@ -0,0 +1,7 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +extension StateExtensions on BuildContext { + TState readController() => read(); + TState watchController() => watch(); +} diff --git a/lib/state/widgets/controller_consumer.dart b/lib/state/widgets/controller_consumer.dart new file mode 100644 index 0000000..70b5302 --- /dev/null +++ b/lib/state/widgets/controller_consumer.dart @@ -0,0 +1,12 @@ +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 new file mode 100644 index 0000000..af9d9d7 --- /dev/null +++ b/lib/state/widgets/controller_provider.dart @@ -0,0 +1,21 @@ +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 new file mode 100644 index 0000000..0474581 --- /dev/null +++ b/lib/state/widgets/controllers_provider.dart @@ -0,0 +1,17 @@ + +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 new file mode 100644 index 0000000..3f82187 --- /dev/null +++ b/lib/state/widgets/loadable_controller_consumer.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; + +import '../infrastructure/controller.dart'; +import '../infrastructure/loadable_state.dart'; +import '../infrastructure/state_extensions.dart'; + +class LoadableControllerConsumer, TState extends LoadableState> extends StatelessWidget { + final Widget Function(BuildContext context, TState state) child; + const LoadableControllerConsumer({required this.child, super.key}); + + @override + Widget build(BuildContext context) { + var state = context.readController().state; + return Stack( + children: [ + if(!state.hasStateData()) const Center(child: CircularProgressIndicator()), + + AnimatedSwitcher( + duration: const Duration(milliseconds: 100), + transitionBuilder: (Widget child, Animation animation) => SlideTransition( + position: Tween( + begin: const Offset(0.0, -1.0), + end: Offset.zero, + ).animate(animation), + child: child, + ), + child: state.isBackgroundLoading() ? const LinearProgressIndicator() : const SizedBox.shrink(), + ), + + AnimatedOpacity( + opacity: state.hasStateData() ? 1.0 : 0.0, + duration: const Duration(milliseconds: 100), + curve: Curves.easeInOut, + child: state.hasStateData() ? child(context, state) : const SizedBox.shrink() + ), + ], + ); + } +} diff --git a/lib/state/widgets/sub_selected_controller_consumer.dart b/lib/state/widgets/sub_selected_controller_consumer.dart new file mode 100644 index 0000000..d57730b --- /dev/null +++ b/lib/state/widgets/sub_selected_controller_consumer.dart @@ -0,0 +1,11 @@ +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 new file mode 100644 index 0000000..dcac21a --- /dev/null +++ b/lib/view/pages/more/test.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import '../../../state/app/application/marianumMessage/marianum_message_controller.dart'; +import '../../../state/app/application/marianumMessage/marianum_message_state.dart'; +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/sub_selected_controller_consumer.dart'; +import '../../../state/widgets/controller_provider.dart'; + +class Test extends StatelessWidget { + const Test({super.key}); + + @override + Widget build(BuildContext context) => ControllerProvider( + create: (context) => MarianumMessageController(), + child: (context) => Scaffold( + appBar: AppBar(title: const Text("TEST")), + body: LoadableControllerConsumer>( + child: (context, data) => Column( + children: [ + TextButton( + onPressed: () => context.readController().loading(), + child: Text(data.loadingState.toString()) + ), + TextButton( + onPressed: () => context.readController().backgroundLoading(), + child: Text(context.watchController().state.loadingState.toString()) + ), + TextButton( + onPressed: () => context.readController().done(), + child: Text(context.watchController().state.loadingState.toString()) + ), + ControllerConsumer>(child: (context, state) => Text(state.data!.test.toString())), + SubSelectedControllerConsumer, LoadingState>( + subselect: (state) => state.loadingState, + child: (context, state) => Text(state.toString()), + ) + ], + ), + ), + ), + ); +} diff --git a/lib/view/pages/overhang.dart b/lib/view/pages/overhang.dart index 0fbe65a..79f59bf 100644 --- a/lib/view/pages/overhang.dart +++ b/lib/view/pages/overhang.dart @@ -16,6 +16,7 @@ import 'more/holidays/holidays.dart'; import 'more/message/message.dart'; import 'more/roomplan/roomplan.dart'; import 'more/share/selectShareTypeDialog.dart'; +import 'more/test.dart'; class Overhang extends StatelessWidget { const Overhang({super.key}); @@ -74,6 +75,10 @@ class Overhang extends StatelessWidget { trailing: const Icon(Icons.arrow_right), onTap: () => pushScreen(context, withNavBar: false, screen: const FeedbackDialog()), ), + ListTile( + leading: const Icon(Icons.science_outlined), + onTap: () => pushScreen(context, withNavBar: false, screen: const Test()), + ) ], ), ); diff --git a/lib/view/pages/talk/components/chatMessage.dart b/lib/view/pages/talk/components/chatMessage.dart index 48bcaf9..7767874 100644 --- a/lib/view/pages/talk/components/chatMessage.dart +++ b/lib/view/pages/talk/components/chatMessage.dart @@ -52,7 +52,7 @@ class ChatMessage { fadeInDuration: Duration.zero, fadeOutDuration: Duration.zero, errorListener: (value) {}, - imageUrl: 'https://${AccountData().buildHttpAuthString()}@${EndpointData().nextcloud().full()}/index.php/core/preview?fileId=${file!.id}&x=100&y=-1&a=1', + imageUrl: 'https://${AccountData().buildHttpAuthString()}@${EndpointData().nextcloud().full()}/index.php/core/preview?fileId=${file!.id}&x=100&sub_selected_controller_consumer.dart=-1&a=1', ); } diff --git a/pubspec.yaml b/pubspec.yaml index 5f44576..a97a3c9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,7 +49,7 @@ dependencies: shared_preferences: ^2.0.15 provider: ^6.0.4 jiffy: ^6.1.0 - json_annotation: ^4.8.0 + json_annotation: ^4.8.1 localstore: ^1.2.3 intl: ^0.18.0 nextcloud: @@ -98,12 +98,15 @@ dependencies: time_range_picker: ^2.2.0 in_app_review: ^2.0.8 emoji_picker_flutter: ^2.1.1 + bloc: ^8.1.4 + flutter_bloc: ^8.1.5 + freezed_annotation: ^2.4.1 dev_dependencies: flutter_test: sdk: flutter - json_serializable: ^6.6.1 - build_runner: ^2.3.3 + json_serializable: ^6.7.1 + build_runner: ^2.4.9 # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is @@ -111,6 +114,7 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^3.0.1 + freezed: ^2.5.2 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec