wip basics for bloc based state management
This commit is contained in:
parent
19aca8f97f
commit
7129c0dee8
@ -9,6 +9,10 @@
|
|||||||
# packages, and plugins designed to encourage good coding practices.
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
errors:
|
||||||
|
invalid_annotation_target: ignore
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
# The lint rules applied to this project can be customized in the
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
6
build.yaml
Normal file
6
build.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
targets:
|
||||||
|
$default:
|
||||||
|
builders:
|
||||||
|
json_serializable:
|
||||||
|
options:
|
||||||
|
explicit_to_json: false
|
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
import '../../../infrastructure/controller.dart';
|
||||||
|
import 'grade_averages_state.dart';
|
||||||
|
|
||||||
|
class GradeAveragesController extends Controller<GradeAveragesState> {
|
||||||
|
GradeAveragesController(super.initialState);
|
||||||
|
|
||||||
|
void setGradeType(GradingSchemes scheme) => emit(state.copyWith(gradingScheme: scheme));
|
||||||
|
double average() => state.grades.reduce((a, b) => a + b) / state.grades.length;
|
||||||
|
}
|
@ -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<int> grades,
|
||||||
|
}) = _GradeAveragesState;
|
||||||
|
|
||||||
|
factory GradeAveragesState.fromJson(Map<String, dynamic> json) => _$GradeAveragesStateFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GradingSchemes {
|
||||||
|
middleSchool,
|
||||||
|
highSchool,
|
||||||
|
}
|
@ -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>(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<String, dynamic> json) {
|
||||||
|
return _GradeAveragesState.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$GradeAveragesState {
|
||||||
|
GradingSchemes get gradingScheme => throw _privateConstructorUsedError;
|
||||||
|
List<int> get grades => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$GradeAveragesStateCopyWith<GradeAveragesState> 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<int> 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<int>,
|
||||||
|
) 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<int> 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<int>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$GradeAveragesStateImpl implements _GradeAveragesState {
|
||||||
|
const _$GradeAveragesStateImpl(
|
||||||
|
{required this.gradingScheme, required final List<int> grades})
|
||||||
|
: _grades = grades;
|
||||||
|
|
||||||
|
factory _$GradeAveragesStateImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$GradeAveragesStateImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final GradingSchemes gradingScheme;
|
||||||
|
final List<int> _grades;
|
||||||
|
@override
|
||||||
|
List<int> 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<String, dynamic> toJson() {
|
||||||
|
return _$$GradeAveragesStateImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _GradeAveragesState implements GradeAveragesState {
|
||||||
|
const factory _GradeAveragesState(
|
||||||
|
{required final GradingSchemes gradingScheme,
|
||||||
|
required final List<int> grades}) = _$GradeAveragesStateImpl;
|
||||||
|
|
||||||
|
factory _GradeAveragesState.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$GradeAveragesStateImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
GradingSchemes get gradingScheme;
|
||||||
|
@override
|
||||||
|
List<int> get grades;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$GradeAveragesStateImplCopyWith<_$GradeAveragesStateImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'grade_averages_state.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$GradeAveragesStateImpl _$$GradeAveragesStateImplFromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$GradeAveragesStateImpl(
|
||||||
|
gradingScheme:
|
||||||
|
$enumDecode(_$GradingSchemesEnumMap, json['gradingScheme']),
|
||||||
|
grades: (json['grades'] as List<dynamic>).map((e) => e as int).toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$GradeAveragesStateImplToJson(
|
||||||
|
_$GradeAveragesStateImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'gradingScheme': _$GradingSchemesEnumMap[instance.gradingScheme]!,
|
||||||
|
'grades': instance.grades,
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$GradingSchemesEnumMap = {
|
||||||
|
GradingSchemes.middleSchool: 'middleSchool',
|
||||||
|
GradingSchemes.highSchool: 'highSchool',
|
||||||
|
};
|
@ -0,0 +1,24 @@
|
|||||||
|
import '../../../infrastructure/controller.dart';
|
||||||
|
import '../../../infrastructure/loadable_state.dart';
|
||||||
|
import 'marianum_message_state.dart';
|
||||||
|
|
||||||
|
class MarianumMessageController extends Controller<LoadableState<MarianumMessageState>> {
|
||||||
|
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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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<String> test
|
||||||
|
}) = _MarianumMessageState;
|
||||||
|
}
|
@ -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>(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<String> get test => 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({List<String> 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<String>,
|
||||||
|
) 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<String> 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<String>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$MarianumMessageStateImpl implements _MarianumMessageState {
|
||||||
|
const _$MarianumMessageStateImpl({required final List<String> test})
|
||||||
|
: _test = test;
|
||||||
|
|
||||||
|
final List<String> _test;
|
||||||
|
@override
|
||||||
|
List<String> 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<String> test}) =
|
||||||
|
_$MarianumMessageStateImpl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> get test;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$$MarianumMessageStateImplCopyWith<_$MarianumMessageStateImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
0
lib/state/app/base/account/account_controller.dart
Normal file
0
lib/state/app/base/account/account_controller.dart
Normal file
5
lib/state/infrastructure/controller.dart
Normal file
5
lib/state/infrastructure/controller.dart
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
abstract class Controller<TContentType> extends Cubit<TContentType> {
|
||||||
|
Controller(super.initialState);
|
||||||
|
}
|
31
lib/state/infrastructure/loadable_state.dart
Normal file
31
lib/state/infrastructure/loadable_state.dart
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
class LoadableState<TState> {
|
||||||
|
final LoadingState loadingState;
|
||||||
|
final TState? data;
|
||||||
|
|
||||||
|
const LoadableState({required this.loadingState, required this.data});
|
||||||
|
|
||||||
|
LoadableState<TState> loading() =>
|
||||||
|
LoadableState<TState>(loadingState: LoadingState.loading, data: null);
|
||||||
|
|
||||||
|
LoadableState<TState> cached(TState state) =>
|
||||||
|
LoadableState<TState>(loadingState: LoadingState.loading, data: state);
|
||||||
|
|
||||||
|
LoadableState<TState> done(TState state) =>
|
||||||
|
LoadableState<TState>(loadingState: LoadingState.none, data: state);
|
||||||
|
|
||||||
|
LoadableState<TState> error(TState state) =>
|
||||||
|
LoadableState<TState>(loadingState: LoadingState.none, data: state);
|
||||||
|
|
||||||
|
bool isBackgroundLoading() =>
|
||||||
|
loadingState == LoadingState.loading && data != null;
|
||||||
|
|
||||||
|
bool hasStateData() =>
|
||||||
|
data != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LoadingState {
|
||||||
|
loading,
|
||||||
|
failed,
|
||||||
|
none,
|
||||||
|
}
|
7
lib/state/infrastructure/state_extensions.dart
Normal file
7
lib/state/infrastructure/state_extensions.dart
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
extension StateExtensions on BuildContext {
|
||||||
|
TState readController<TState>() => read<TState>();
|
||||||
|
TState watchController<TState>() => watch<TState>();
|
||||||
|
}
|
12
lib/state/widgets/controller_consumer.dart
Normal file
12
lib/state/widgets/controller_consumer.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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);
|
||||||
|
}
|
21
lib/state/widgets/controller_provider.dart
Normal file
21
lib/state/widgets/controller_provider.dart
Normal file
@ -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<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,
|
||||||
|
);
|
||||||
|
}
|
17
lib/state/widgets/controllers_provider.dart
Normal file
17
lib/state/widgets/controllers_provider.dart
Normal file
@ -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<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)
|
||||||
|
);
|
||||||
|
}
|
39
lib/state/widgets/loadable_controller_consumer.dart
Normal file
39
lib/state/widgets/loadable_controller_consumer.dart
Normal file
@ -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<TController extends Controller<TState>, 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<TController>().state;
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
if(!state.hasStateData()) const Center(child: CircularProgressIndicator()),
|
||||||
|
|
||||||
|
AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 100),
|
||||||
|
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: 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()
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
11
lib/state/widgets/sub_selected_controller_consumer.dart
Normal file
11
lib/state/widgets/sub_selected_controller_consumer.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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);
|
||||||
|
}
|
44
lib/view/pages/more/test.dart
Normal file
44
lib/view/pages/more/test.dart
Normal file
@ -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<MarianumMessageController>(
|
||||||
|
create: (context) => MarianumMessageController(),
|
||||||
|
child: (context) => Scaffold(
|
||||||
|
appBar: AppBar(title: const Text("TEST")),
|
||||||
|
body: LoadableControllerConsumer<MarianumMessageController, LoadableState<MarianumMessageState>>(
|
||||||
|
child: (context, data) => Column(
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => context.readController<MarianumMessageController>().loading(),
|
||||||
|
child: Text(data.loadingState.toString())
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => context.readController<MarianumMessageController>().backgroundLoading(),
|
||||||
|
child: Text(context.watchController<MarianumMessageController>().state.loadingState.toString())
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => context.readController<MarianumMessageController>().done(),
|
||||||
|
child: Text(context.watchController<MarianumMessageController>().state.loadingState.toString())
|
||||||
|
),
|
||||||
|
ControllerConsumer<MarianumMessageController, LoadableState<MarianumMessageState>>(child: (context, state) => Text(state.data!.test.toString())),
|
||||||
|
SubSelectedControllerConsumer<MarianumMessageController, LoadableState<MarianumMessageState>, LoadingState>(
|
||||||
|
subselect: (state) => state.loadingState,
|
||||||
|
child: (context, state) => Text(state.toString()),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
@ -16,6 +16,7 @@ import 'more/holidays/holidays.dart';
|
|||||||
import 'more/message/message.dart';
|
import 'more/message/message.dart';
|
||||||
import 'more/roomplan/roomplan.dart';
|
import 'more/roomplan/roomplan.dart';
|
||||||
import 'more/share/selectShareTypeDialog.dart';
|
import 'more/share/selectShareTypeDialog.dart';
|
||||||
|
import 'more/test.dart';
|
||||||
|
|
||||||
class Overhang extends StatelessWidget {
|
class Overhang extends StatelessWidget {
|
||||||
const Overhang({super.key});
|
const Overhang({super.key});
|
||||||
@ -74,6 +75,10 @@ class Overhang extends StatelessWidget {
|
|||||||
trailing: const Icon(Icons.arrow_right),
|
trailing: const Icon(Icons.arrow_right),
|
||||||
onTap: () => pushScreen(context, withNavBar: false, screen: const FeedbackDialog()),
|
onTap: () => pushScreen(context, withNavBar: false, screen: const FeedbackDialog()),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.science_outlined),
|
||||||
|
onTap: () => pushScreen(context, withNavBar: false, screen: const Test()),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -52,7 +52,7 @@ class ChatMessage {
|
|||||||
fadeInDuration: Duration.zero,
|
fadeInDuration: Duration.zero,
|
||||||
fadeOutDuration: Duration.zero,
|
fadeOutDuration: Duration.zero,
|
||||||
errorListener: (value) {},
|
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',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
pubspec.yaml
10
pubspec.yaml
@ -49,7 +49,7 @@ dependencies:
|
|||||||
shared_preferences: ^2.0.15
|
shared_preferences: ^2.0.15
|
||||||
provider: ^6.0.4
|
provider: ^6.0.4
|
||||||
jiffy: ^6.1.0
|
jiffy: ^6.1.0
|
||||||
json_annotation: ^4.8.0
|
json_annotation: ^4.8.1
|
||||||
localstore: ^1.2.3
|
localstore: ^1.2.3
|
||||||
intl: ^0.18.0
|
intl: ^0.18.0
|
||||||
nextcloud:
|
nextcloud:
|
||||||
@ -98,12 +98,15 @@ dependencies:
|
|||||||
time_range_picker: ^2.2.0
|
time_range_picker: ^2.2.0
|
||||||
in_app_review: ^2.0.8
|
in_app_review: ^2.0.8
|
||||||
emoji_picker_flutter: ^2.1.1
|
emoji_picker_flutter: ^2.1.1
|
||||||
|
bloc: ^8.1.4
|
||||||
|
flutter_bloc: ^8.1.5
|
||||||
|
freezed_annotation: ^2.4.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
json_serializable: ^6.6.1
|
json_serializable: ^6.7.1
|
||||||
build_runner: ^2.3.3
|
build_runner: ^2.4.9
|
||||||
|
|
||||||
# The "flutter_lints" package below contains a set of recommended lints to
|
# The "flutter_lints" package below contains a set of recommended lints to
|
||||||
# encourage good coding practices. The lint set provided by the package is
|
# 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
|
# package. See that file for information about deactivating specific lint
|
||||||
# rules and activating additional ones.
|
# rules and activating additional ones.
|
||||||
flutter_lints: ^3.0.1
|
flutter_lints: ^3.0.1
|
||||||
|
freezed: ^2.5.2
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
Loading…
x
Reference in New Issue
Block a user