revamp on bloc approach
This commit is contained in:
parent
ee6af2bc07
commit
f58a2ec8cd
@ -4,3 +4,4 @@ targets:
|
|||||||
json_serializable:
|
json_serializable:
|
||||||
options:
|
options:
|
||||||
explicit_to_json: false
|
explicit_to_json: false
|
||||||
|
generic_argument_factories: true
|
@ -137,7 +137,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PersistentTabConfig(
|
PersistentTabConfig(
|
||||||
screen: const Breaker(breaker: BreakerArea.files, child: Files([])),
|
screen: Breaker(breaker: BreakerArea.files, child: Files()),
|
||||||
item: ItemConfig(
|
item: ItemConfig(
|
||||||
activeForegroundColor: Theme.of(context).primaryColor,
|
activeForegroundColor: Theme.of(context).primaryColor,
|
||||||
inactiveForegroundColor: Theme.of(context).colorScheme.secondary,
|
inactiveForegroundColor: Theme.of(context).colorScheme.secondary,
|
||||||
|
@ -7,8 +7,10 @@ import 'package:firebase_messaging/firebase_messaging.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:jiffy/jiffy.dart';
|
import 'package:jiffy/jiffy.dart';
|
||||||
import 'package:loader_overlay/loader_overlay.dart';
|
import 'package:loader_overlay/loader_overlay.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
@ -34,21 +36,26 @@ import 'widget/placeholderView.dart';
|
|||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
try {
|
var initialisationTasks = [
|
||||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform)
|
||||||
log("Firebase token: ${await FirebaseMessaging.instance.getToken() ?? "Error: no Firebase token!"}");
|
.then((value) async => log("Firebase token: ${await FirebaseMessaging.instance.getToken() ?? "Error: no Firebase token!"}"))
|
||||||
} catch (e) {
|
.onError((error, stackTrace) => log('Error initializing Firebase: $error')),
|
||||||
log('Error initializing Firebase app!');
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = await PlatformAssetBundle().load('assets/ca/lets-encrypt-r3.pem');
|
PlatformAssetBundle().load('assets/ca/lets-encrypt-r3.pem')
|
||||||
SecurityContext.defaultContext.setTrustedCertificatesBytes(data.buffer.asUint8List());
|
.then((certificate) => SecurityContext.defaultContext.setTrustedCertificatesBytes(certificate.buffer.asUint8List())),
|
||||||
|
|
||||||
|
Future(() async {
|
||||||
|
await HydratedStorage.build(storageDirectory: await getTemporaryDirectory()).then((storage) => HydratedBloc.storage = storage);
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
await Future.wait(initialisationTasks);
|
||||||
|
|
||||||
if(kReleaseMode) {
|
if(kReleaseMode) {
|
||||||
ErrorWidget.builder = (error) => PlaceholderView(
|
ErrorWidget.builder = (error) => PlaceholderView(
|
||||||
icon: Icons.phonelink_erase_rounded,
|
icon: Icons.phonelink_erase_rounded,
|
||||||
text: error.toStringShort(),
|
text: error.toStringShort(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
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() {
|
|
||||||
emit(state.error(state: const MarianumMessageState(test: [])));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
// 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;
|
|
||||||
}
|
|
29
lib/state/app/modules/app_modules.dart
Normal file
29
lib/state/app/modules/app_modules.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../view/pages/files/files.dart';
|
||||||
|
import '../../../view/pages/talk/chatList.dart';
|
||||||
|
import '../../../view/pages/timetable/timetable.dart';
|
||||||
|
|
||||||
|
class AppModule {
|
||||||
|
String name;
|
||||||
|
IconData icon;
|
||||||
|
Widget Function() create;
|
||||||
|
|
||||||
|
AppModule(this.name, this.icon, this.create);
|
||||||
|
|
||||||
|
static Map<Module, AppModule> modules() => {
|
||||||
|
Module.timetable: AppModule('Vertretung', Icons.calendar_month, Timetable.new),
|
||||||
|
Module.talk: AppModule('Talk', Icons.chat, ChatList.new),
|
||||||
|
Module.files: AppModule('Files', Icons.folder, Files.new),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Module {
|
||||||
|
timetable,
|
||||||
|
talk,
|
||||||
|
files,
|
||||||
|
marianumMessage,
|
||||||
|
roomPlan,
|
||||||
|
gradeAveragesCalculator,
|
||||||
|
holidays,
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
|
|
||||||
|
import 'grade_averages_event.dart';
|
||||||
|
import 'grade_averages_state.dart';
|
||||||
|
|
||||||
|
class GradeAveragesBloc extends HydratedBloc<GradeAveragesEvent, GradeAveragesState> {
|
||||||
|
GradeAveragesBloc() : super(const GradeAveragesState(gradingSystem: GradeAveragesGradingSystem.middleSchool, grades: [])) {
|
||||||
|
|
||||||
|
on<GradingSystemChanged>((event, emit) {
|
||||||
|
add(ResetAll());
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
gradingSystem: event.isMiddleSchool
|
||||||
|
? GradeAveragesGradingSystem.middleSchool
|
||||||
|
: GradeAveragesGradingSystem.highSchool
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
on<ResetAll>((event, emit) {
|
||||||
|
emit(state.copyWith(grades: []));
|
||||||
|
});
|
||||||
|
|
||||||
|
on<ResetGrade>((event, emit) {
|
||||||
|
emit(state.copyWith(grades: [...state.grades]..removeWhere((grade) => grade == event.grade)));
|
||||||
|
});
|
||||||
|
|
||||||
|
on<IncrementGrade>((event, emit) {
|
||||||
|
emit(state.copyWith(grades: [...state.grades, event.grade]));
|
||||||
|
});
|
||||||
|
|
||||||
|
on<DecrementGrade>((event, emit) {
|
||||||
|
emit(state.copyWith(grades: List.from(state.grades)..remove(event.grade)));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double average() => state.grades.isEmpty ? 0 : state.grades.reduce((a, b) => a + b) / state.grades.length;
|
||||||
|
bool isMiddleSchool() => state.gradingSystem == GradeAveragesGradingSystem.middleSchool;
|
||||||
|
bool canDecrementOrDelete(int grade) => state.grades.contains(grade);
|
||||||
|
int countOfGrade(int grade) => state.grades.where((g) => g == grade).length;
|
||||||
|
int gradesInGradingSystem() => state.gradingSystem == GradeAveragesGradingSystem.middleSchool ? 6 : 16;
|
||||||
|
int getGradeFromIndex(int index) => isMiddleSchool() ? index + 1 : 15 - index;
|
||||||
|
|
||||||
|
@override
|
||||||
|
GradeAveragesState? fromJson(Map<String, dynamic> json) => GradeAveragesState.fromJson(json);
|
||||||
|
@override
|
||||||
|
Map<String, dynamic>? toJson(GradeAveragesState state) => state.toJson();
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
sealed class GradeAveragesEvent {}
|
||||||
|
|
||||||
|
final class GradingSystemChanged extends GradeAveragesEvent {
|
||||||
|
final bool isMiddleSchool;
|
||||||
|
GradingSystemChanged(this.isMiddleSchool);
|
||||||
|
}
|
||||||
|
final class ResetAll extends GradeAveragesEvent {}
|
||||||
|
final class ResetGrade extends GradeAveragesEvent {
|
||||||
|
final int grade;
|
||||||
|
ResetGrade(this.grade);
|
||||||
|
}
|
||||||
|
final class IncrementGrade extends GradeAveragesEvent {
|
||||||
|
final int grade;
|
||||||
|
IncrementGrade(this.grade);
|
||||||
|
}
|
||||||
|
final class DecrementGrade extends GradeAveragesEvent {
|
||||||
|
final int grade;
|
||||||
|
DecrementGrade(this.grade);
|
||||||
|
}
|
@ -6,14 +6,14 @@ part 'grade_averages_state.g.dart';
|
|||||||
@freezed
|
@freezed
|
||||||
class GradeAveragesState with _$GradeAveragesState {
|
class GradeAveragesState with _$GradeAveragesState {
|
||||||
const factory GradeAveragesState({
|
const factory GradeAveragesState({
|
||||||
required GradingSchemes gradingScheme,
|
required GradeAveragesGradingSystem gradingSystem,
|
||||||
required List<int> grades,
|
required List<int> grades,
|
||||||
}) = _GradeAveragesState;
|
}) = _GradeAveragesState;
|
||||||
|
|
||||||
factory GradeAveragesState.fromJson(Map<String, dynamic> json) => _$GradeAveragesStateFromJson(json);
|
factory GradeAveragesState.fromJson(Map<String, dynamic> json) => _$GradeAveragesStateFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GradingSchemes {
|
enum GradeAveragesGradingSystem {
|
||||||
middleSchool,
|
|
||||||
highSchool,
|
highSchool,
|
||||||
|
middleSchool,
|
||||||
}
|
}
|
@ -20,7 +20,8 @@ GradeAveragesState _$GradeAveragesStateFromJson(Map<String, dynamic> json) {
|
|||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$GradeAveragesState {
|
mixin _$GradeAveragesState {
|
||||||
GradingSchemes get gradingScheme => throw _privateConstructorUsedError;
|
GradeAveragesGradingSystem get gradingSystem =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
List<int> get grades => throw _privateConstructorUsedError;
|
List<int> get grades => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@ -35,7 +36,7 @@ abstract class $GradeAveragesStateCopyWith<$Res> {
|
|||||||
GradeAveragesState value, $Res Function(GradeAveragesState) then) =
|
GradeAveragesState value, $Res Function(GradeAveragesState) then) =
|
||||||
_$GradeAveragesStateCopyWithImpl<$Res, GradeAveragesState>;
|
_$GradeAveragesStateCopyWithImpl<$Res, GradeAveragesState>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({GradingSchemes gradingScheme, List<int> grades});
|
$Res call({GradeAveragesGradingSystem gradingSystem, List<int> grades});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -51,14 +52,14 @@ class _$GradeAveragesStateCopyWithImpl<$Res, $Val extends GradeAveragesState>
|
|||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
Object? gradingScheme = null,
|
Object? gradingSystem = null,
|
||||||
Object? grades = null,
|
Object? grades = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
gradingScheme: null == gradingScheme
|
gradingSystem: null == gradingSystem
|
||||||
? _value.gradingScheme
|
? _value.gradingSystem
|
||||||
: gradingScheme // ignore: cast_nullable_to_non_nullable
|
: gradingSystem // ignore: cast_nullable_to_non_nullable
|
||||||
as GradingSchemes,
|
as GradeAveragesGradingSystem,
|
||||||
grades: null == grades
|
grades: null == grades
|
||||||
? _value.grades
|
? _value.grades
|
||||||
: grades // ignore: cast_nullable_to_non_nullable
|
: grades // ignore: cast_nullable_to_non_nullable
|
||||||
@ -75,7 +76,7 @@ abstract class _$$GradeAveragesStateImplCopyWith<$Res>
|
|||||||
__$$GradeAveragesStateImplCopyWithImpl<$Res>;
|
__$$GradeAveragesStateImplCopyWithImpl<$Res>;
|
||||||
@override
|
@override
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({GradingSchemes gradingScheme, List<int> grades});
|
$Res call({GradeAveragesGradingSystem gradingSystem, List<int> grades});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -89,14 +90,14 @@ class __$$GradeAveragesStateImplCopyWithImpl<$Res>
|
|||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
Object? gradingScheme = null,
|
Object? gradingSystem = null,
|
||||||
Object? grades = null,
|
Object? grades = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$GradeAveragesStateImpl(
|
return _then(_$GradeAveragesStateImpl(
|
||||||
gradingScheme: null == gradingScheme
|
gradingSystem: null == gradingSystem
|
||||||
? _value.gradingScheme
|
? _value.gradingSystem
|
||||||
: gradingScheme // ignore: cast_nullable_to_non_nullable
|
: gradingSystem // ignore: cast_nullable_to_non_nullable
|
||||||
as GradingSchemes,
|
as GradeAveragesGradingSystem,
|
||||||
grades: null == grades
|
grades: null == grades
|
||||||
? _value._grades
|
? _value._grades
|
||||||
: grades // ignore: cast_nullable_to_non_nullable
|
: grades // ignore: cast_nullable_to_non_nullable
|
||||||
@ -109,14 +110,14 @@ class __$$GradeAveragesStateImplCopyWithImpl<$Res>
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$GradeAveragesStateImpl implements _GradeAveragesState {
|
class _$GradeAveragesStateImpl implements _GradeAveragesState {
|
||||||
const _$GradeAveragesStateImpl(
|
const _$GradeAveragesStateImpl(
|
||||||
{required this.gradingScheme, required final List<int> grades})
|
{required this.gradingSystem, required final List<int> grades})
|
||||||
: _grades = grades;
|
: _grades = grades;
|
||||||
|
|
||||||
factory _$GradeAveragesStateImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$GradeAveragesStateImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$GradeAveragesStateImplFromJson(json);
|
_$$GradeAveragesStateImplFromJson(json);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final GradingSchemes gradingScheme;
|
final GradeAveragesGradingSystem gradingSystem;
|
||||||
final List<int> _grades;
|
final List<int> _grades;
|
||||||
@override
|
@override
|
||||||
List<int> get grades {
|
List<int> get grades {
|
||||||
@ -127,7 +128,7 @@ class _$GradeAveragesStateImpl implements _GradeAveragesState {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'GradeAveragesState(gradingScheme: $gradingScheme, grades: $grades)';
|
return 'GradeAveragesState(gradingSystem: $gradingSystem, grades: $grades)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -135,15 +136,15 @@ class _$GradeAveragesStateImpl implements _GradeAveragesState {
|
|||||||
return identical(this, other) ||
|
return identical(this, other) ||
|
||||||
(other.runtimeType == runtimeType &&
|
(other.runtimeType == runtimeType &&
|
||||||
other is _$GradeAveragesStateImpl &&
|
other is _$GradeAveragesStateImpl &&
|
||||||
(identical(other.gradingScheme, gradingScheme) ||
|
(identical(other.gradingSystem, gradingSystem) ||
|
||||||
other.gradingScheme == gradingScheme) &&
|
other.gradingSystem == gradingSystem) &&
|
||||||
const DeepCollectionEquality().equals(other._grades, _grades));
|
const DeepCollectionEquality().equals(other._grades, _grades));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(
|
int get hashCode => Object.hash(
|
||||||
runtimeType, gradingScheme, const DeepCollectionEquality().hash(_grades));
|
runtimeType, gradingSystem, const DeepCollectionEquality().hash(_grades));
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
@ -162,14 +163,14 @@ class _$GradeAveragesStateImpl implements _GradeAveragesState {
|
|||||||
|
|
||||||
abstract class _GradeAveragesState implements GradeAveragesState {
|
abstract class _GradeAveragesState implements GradeAveragesState {
|
||||||
const factory _GradeAveragesState(
|
const factory _GradeAveragesState(
|
||||||
{required final GradingSchemes gradingScheme,
|
{required final GradeAveragesGradingSystem gradingSystem,
|
||||||
required final List<int> grades}) = _$GradeAveragesStateImpl;
|
required final List<int> grades}) = _$GradeAveragesStateImpl;
|
||||||
|
|
||||||
factory _GradeAveragesState.fromJson(Map<String, dynamic> json) =
|
factory _GradeAveragesState.fromJson(Map<String, dynamic> json) =
|
||||||
_$GradeAveragesStateImpl.fromJson;
|
_$GradeAveragesStateImpl.fromJson;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
GradingSchemes get gradingScheme;
|
GradeAveragesGradingSystem get gradingSystem;
|
||||||
@override
|
@override
|
||||||
List<int> get grades;
|
List<int> get grades;
|
||||||
@override
|
@override
|
@ -9,19 +9,20 @@ part of 'grade_averages_state.dart';
|
|||||||
_$GradeAveragesStateImpl _$$GradeAveragesStateImplFromJson(
|
_$GradeAveragesStateImpl _$$GradeAveragesStateImplFromJson(
|
||||||
Map<String, dynamic> json) =>
|
Map<String, dynamic> json) =>
|
||||||
_$GradeAveragesStateImpl(
|
_$GradeAveragesStateImpl(
|
||||||
gradingScheme:
|
gradingSystem: $enumDecode(
|
||||||
$enumDecode(_$GradingSchemesEnumMap, json['gradingScheme']),
|
_$GradeAveragesGradingSystemEnumMap, json['gradingSystem']),
|
||||||
grades: (json['grades'] as List<dynamic>).map((e) => e as int).toList(),
|
grades: (json['grades'] as List<dynamic>).map((e) => e as int).toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$GradeAveragesStateImplToJson(
|
Map<String, dynamic> _$$GradeAveragesStateImplToJson(
|
||||||
_$GradeAveragesStateImpl instance) =>
|
_$GradeAveragesStateImpl instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'gradingScheme': _$GradingSchemesEnumMap[instance.gradingScheme]!,
|
'gradingSystem':
|
||||||
|
_$GradeAveragesGradingSystemEnumMap[instance.gradingSystem]!,
|
||||||
'grades': instance.grades,
|
'grades': instance.grades,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$GradingSchemesEnumMap = {
|
const _$GradeAveragesGradingSystemEnumMap = {
|
||||||
GradingSchemes.middleSchool: 'middleSchool',
|
GradeAveragesGradingSystem.highSchool: 'highSchool',
|
||||||
GradingSchemes.highSchool: 'highSchool',
|
GradeAveragesGradingSystem.middleSchool: 'middleSchool',
|
||||||
};
|
};
|
@ -0,0 +1,70 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../bloc/grade_averages_bloc.dart';
|
||||||
|
import '../bloc/grade_averages_event.dart';
|
||||||
|
|
||||||
|
class GradeAveragesListView extends StatelessWidget {
|
||||||
|
const GradeAveragesListView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var bloc = context.watch<GradeAveragesBloc>();
|
||||||
|
|
||||||
|
String getGradeDisplay(int grade) {
|
||||||
|
if(bloc.isMiddleSchool()) {
|
||||||
|
return 'Note $grade';
|
||||||
|
} else {
|
||||||
|
return "$grade Punkt${grade > 1 ? "e" : ""}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: bloc.gradesInGradingSystem(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var grade = bloc.getGradeFromIndex(index);
|
||||||
|
return Material(
|
||||||
|
child: ListTile(
|
||||||
|
tileColor: grade.isEven ? Colors.transparent : Colors.transparent.withAlpha(50),
|
||||||
|
title: Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(getGradeDisplay(grade)),
|
||||||
|
const SizedBox(width: 30),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
bloc.add(DecrementGrade(grade));
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.remove),
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
Text('${bloc.countOfGrade(grade)}', style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold)),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
bloc.add(IncrementGrade(grade));
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: Visibility(
|
||||||
|
maintainState: true,
|
||||||
|
maintainAnimation: true,
|
||||||
|
maintainSize: true,
|
||||||
|
visible: bloc.canDecrementOrDelete(grade),
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(Icons.delete),
|
||||||
|
onPressed: () {
|
||||||
|
bloc.add(ResetGrade(grade));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import '../../../../../widget/confirmDialog.dart';
|
||||||
|
import '../bloc/grade_averages_bloc.dart';
|
||||||
|
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});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => BlocProvider<GradeAveragesBloc>(
|
||||||
|
create: (context) => GradeAveragesBloc(),
|
||||||
|
child: BlocBuilder<GradeAveragesBloc, GradeAveragesState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
var bloc = context.watch<GradeAveragesBloc>();
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Notendurschnittsrechner'),
|
||||||
|
actions: [
|
||||||
|
Visibility(
|
||||||
|
visible: bloc.state.grades.isNotEmpty,
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => ConfirmDialog(
|
||||||
|
title: 'Zurücksetzen?',
|
||||||
|
content: 'Alle Einträge werden entfernt.',
|
||||||
|
confirmButton: 'Zurücksetzen',
|
||||||
|
onConfirm: () {
|
||||||
|
bloc.add(ResetAll());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.delete_forever)),
|
||||||
|
),
|
||||||
|
PopupMenuButton<bool>(
|
||||||
|
initialValue: bloc.isMiddleSchool(),
|
||||||
|
icon: const Icon(Icons.more_horiz),
|
||||||
|
itemBuilder: (context) => [true, false].map((isMiddleSchool) => PopupMenuItem<bool>(
|
||||||
|
value: isMiddleSchool,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
isMiddleSchool ? Icons.calculate_outlined : Icons.school_outlined,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface
|
||||||
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Text(isMiddleSchool ? 'Notensystem' : 'Punktesystem'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)).toList(),
|
||||||
|
onSelected: (isMiddleSchool) {
|
||||||
|
if (bloc.state.grades.isNotEmpty) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => ConfirmDialog(
|
||||||
|
title: 'Notensystem wechseln',
|
||||||
|
content:
|
||||||
|
'Beim wechsel des Notensystems werden alle Einträge zurückgesetzt.',
|
||||||
|
confirmButton: 'Fortfahren',
|
||||||
|
onConfirm: () => bloc.add(GradingSystemChanged(isMiddleSchool)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
bloc.add(GradingSystemChanged(isMiddleSchool));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
Text(bloc.average().toStringAsFixed(2), style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold)),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const Divider(),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Text(bloc.isMiddleSchool() ? 'Wähle unten die Anzahl deiner jewiligen Noten aus' : 'Wähle unten die Anzahl deiner jeweiligen Punkte aus'),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const Expanded(
|
||||||
|
child: GradeAveragesListView()
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
|
|
||||||
abstract class Controller<TContentType> extends Cubit<TContentType> {
|
|
||||||
Controller(super.initialState);
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
|
|
||||||
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.failed, data: state);
|
|
||||||
|
|
||||||
bool isBackgroundLoading() =>
|
|
||||||
loadingState == LoadingState.loading && data != null;
|
|
||||||
|
|
||||||
bool hasError() =>
|
|
||||||
loadingState == LoadingState.failed;
|
|
||||||
|
|
||||||
bool hasStateData() =>
|
|
||||||
data != null;
|
|
||||||
|
|
||||||
bool errorBarVisible() =>
|
|
||||||
hasError() && hasStateData();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LoadingState {
|
|
||||||
loading,
|
|
||||||
failed,
|
|
||||||
none,
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
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>();
|
|
||||||
}
|
|
@ -1,58 +1,58 @@
|
|||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
|
//
|
||||||
import '../../app/base/infrastructure/errorBar/error_bar_controller.dart';
|
// import '../../app/base/infrastructure/errorBar/error_bar_controller.dart';
|
||||||
import '../../infrastructure/state_extensions.dart';
|
// import '../../infrastructure/state_extensions.dart';
|
||||||
import '../controller_provider.dart';
|
// import '../controller_provider.dart';
|
||||||
|
//
|
||||||
class ErrorBar extends StatelessWidget {
|
// class ErrorBar extends StatelessWidget {
|
||||||
final bool visible;
|
// final bool visible;
|
||||||
const ErrorBar({required this.visible, super.key});
|
// const ErrorBar({required this.visible, super.key});
|
||||||
|
//
|
||||||
final Duration animationDuration = const Duration(milliseconds: 200);
|
// final Duration animationDuration = const Duration(milliseconds: 200);
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) => ControllerProvider<ErrorBarController>(
|
// Widget build(BuildContext context) => ControllerProvider<ErrorBarController>(
|
||||||
create: (context) => ErrorBarController(),
|
// create: (context) => ErrorBarController(),
|
||||||
child: (context) => AnimatedSize(
|
// child: (context) => AnimatedSize(
|
||||||
duration: animationDuration,
|
// duration: animationDuration,
|
||||||
child: AnimatedSwitcher(
|
// child: AnimatedSwitcher(
|
||||||
duration: animationDuration,
|
// duration: animationDuration,
|
||||||
transitionBuilder: (Widget child, Animation<double> animation) => SlideTransition(
|
// transitionBuilder: (Widget child, Animation<double> animation) => SlideTransition(
|
||||||
position: Tween<Offset>(
|
// position: Tween<Offset>(
|
||||||
begin: const Offset(0.0, -1.0),
|
// begin: const Offset(0.0, -1.0),
|
||||||
end: Offset.zero,
|
// end: Offset.zero,
|
||||||
).animate(animation),
|
// ).animate(animation),
|
||||||
child: child,
|
// child: child,
|
||||||
),
|
// ),
|
||||||
child: Visibility(
|
// child: Visibility(
|
||||||
key: Key(visible.hashCode.toString()),
|
// key: Key(visible.hashCode.toString()),
|
||||||
visible: visible,
|
// visible: visible,
|
||||||
replacement: const SizedBox(width: double.infinity),
|
// replacement: const SizedBox(width: double.infinity),
|
||||||
child: Builder(
|
// child: Builder(
|
||||||
builder: (context) {
|
// builder: (context) {
|
||||||
var controller = context.watchController<ErrorBarController>();
|
// var controller = context.watchController<ErrorBarController>();
|
||||||
var status = controller.connectivityStatusKnown() && !controller.isConnected()
|
// var status = controller.connectivityStatusKnown() && !controller.isConnected()
|
||||||
? (icon: Icons.wifi_off_outlined, text: 'Offline', color: Colors.grey.shade600)
|
// ? (icon: Icons.wifi_off_outlined, text: 'Offline', color: Colors.grey.shade600)
|
||||||
: (icon: Icons.wifi_find_outlined, text: 'Verbindung fehlgeschlagen', color: Theme.of(context).primaryColor);
|
// : (icon: Icons.wifi_find_outlined, text: 'Verbindung fehlgeschlagen', color: Theme.of(context).primaryColor);
|
||||||
|
//
|
||||||
return Container(
|
// return Container(
|
||||||
height: 20,
|
// height: 20,
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: status.color,
|
// color: status.color,
|
||||||
),
|
// ),
|
||||||
child: Row(
|
// child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
// children: [
|
||||||
Icon(status.icon, size: 14),
|
// Icon(status.icon, size: 14),
|
||||||
const SizedBox(width: 10),
|
// const SizedBox(width: 10),
|
||||||
Text(status.text, style: const TextStyle(fontSize: 12))
|
// Text(status.text, style: const TextStyle(fontSize: 12))
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
)
|
// )
|
||||||
)
|
// )
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
// import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
//
|
||||||
import '../infrastructure/controller.dart';
|
// import '../infrastructure/controller.dart';
|
||||||
|
//
|
||||||
class ControllerConsumer<TController extends Controller<TState>, TState> extends StatelessWidget {
|
// class ControllerConsumer<TController extends Controller<TState>, TState> extends StatelessWidget {
|
||||||
final Widget Function(BuildContext context, TState state) child;
|
// final Widget Function(BuildContext context, TState state) child;
|
||||||
const ControllerConsumer({required this.child, super.key});
|
// const ControllerConsumer({required this.child, super.key});
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) => BlocBuilder<TController, TState>(builder: child);
|
// Widget build(BuildContext context) => BlocBuilder<TController, TState>(builder: child);
|
||||||
}
|
// }
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
// import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:provider/single_child_widget.dart';
|
// import 'package:provider/single_child_widget.dart';
|
||||||
|
//
|
||||||
import '../infrastructure/controller.dart';
|
// import '../infrastructure/controller.dart';
|
||||||
|
//
|
||||||
|
//
|
||||||
class ControllerProvider<TState extends Controller> extends SingleChildStatelessWidget {
|
// class ControllerProvider<TState extends Controller> extends SingleChildStatelessWidget {
|
||||||
final TState Function(BuildContext context) create;
|
// final TState Function(BuildContext context) create;
|
||||||
final bool lazy;
|
// final bool lazy;
|
||||||
final Widget Function(BuildContext context) child;
|
// final Widget Function(BuildContext context) child;
|
||||||
ControllerProvider({required this.create, this.lazy = true, required this.child, super.key})
|
// ControllerProvider({required this.create, this.lazy = true, required this.child, super.key})
|
||||||
: super(child: Builder(builder: child));
|
// : super(child: Builder(builder: child));
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
Widget buildWithChild(BuildContext context, Widget? child) => BlocProvider(
|
// Widget buildWithChild(BuildContext context, Widget? child) => BlocProvider(
|
||||||
create: create,
|
// create: create,
|
||||||
lazy: lazy,
|
// lazy: lazy,
|
||||||
child: child,
|
// child: child,
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
|
//
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
// import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
//
|
||||||
import 'controller_provider.dart';
|
// import 'controller_provider.dart';
|
||||||
|
//
|
||||||
class ControllersProvider extends StatelessWidget {
|
// class ControllersProvider extends StatelessWidget {
|
||||||
final List<ControllerProvider> controllers;
|
// final List<ControllerProvider> controllers;
|
||||||
final Widget Function(BuildContext context) child;
|
// final Widget Function(BuildContext context) child;
|
||||||
const ControllersProvider({required this.controllers, required this.child, super.key});
|
// const ControllersProvider({required this.controllers, required this.child, super.key});
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) => MultiBlocProvider(
|
// Widget build(BuildContext context) => MultiBlocProvider(
|
||||||
providers: controllers,
|
// providers: controllers,
|
||||||
child: Builder(builder: child)
|
// child: Builder(builder: child)
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
@ -1,40 +1,42 @@
|
|||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
|
// import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import '../infrastructure/controller.dart';
|
//
|
||||||
import '../infrastructure/loadable_state.dart';
|
// import '../infrastructure/controller.dart';
|
||||||
import '../infrastructure/state_extensions.dart';
|
// import '../infrastructure/loadable_state.dart';
|
||||||
import 'components/background_loading_indicator.dart';
|
// import '../infrastructure/state_extensions.dart';
|
||||||
import 'components/error_bar.dart';
|
// import 'components/background_loading_indicator.dart';
|
||||||
import 'components/primary_loading_indicator.dart';
|
// import 'components/error_bar.dart';
|
||||||
|
// import 'components/primary_loading_indicator.dart';
|
||||||
class LoadableControllerConsumer<TController extends Controller<TState>, TState extends LoadableState> extends StatelessWidget {
|
//
|
||||||
final Widget child;
|
// class LoadableControllerConsumer<TController extends Controller<TState>, TState extends LoadableState> extends StatelessWidget {
|
||||||
const LoadableControllerConsumer({required this.child, super.key});
|
// final Widget child;
|
||||||
|
// const LoadableControllerConsumer({required this.child, super.key});
|
||||||
final Duration animationDuration = const Duration(milliseconds: 200);
|
//
|
||||||
|
// final Duration animationDuration = const Duration(milliseconds: 200);
|
||||||
@override
|
//
|
||||||
Widget build(BuildContext context) {
|
// @override
|
||||||
var state = context.readController<TController>().state;
|
// Widget build(BuildContext context) {
|
||||||
return Column(
|
// var state = context.readController<TController>().state;
|
||||||
children: [
|
//
|
||||||
ErrorBar(visible: state.errorBarVisible()),
|
// return Column(
|
||||||
Expanded(
|
// children: [
|
||||||
child: Stack(
|
// // ErrorBar(visible: state.errorBarVisible()),
|
||||||
children: [
|
// // Expanded(
|
||||||
PrimaryLoadingIndicator(visible: !state.hasStateData()),
|
// // child: Stack(
|
||||||
BackgroundLoadingIndicator(visible: state.isBackgroundLoading() && !state.errorBarVisible()),
|
// // children: [
|
||||||
|
// // PrimaryLoadingIndicator(visible: !state.hasStateData()),
|
||||||
AnimatedOpacity(
|
// // BackgroundLoadingIndicator(visible: state.isBackgroundLoading() && !state.errorBarVisible()),
|
||||||
opacity: state.hasStateData() ? 1.0 : 0.0,
|
// //
|
||||||
duration: animationDuration,
|
// // AnimatedOpacity(
|
||||||
curve: Curves.easeInOut,
|
// // opacity: state.hasStateData() ? 1.0 : 0.0,
|
||||||
child: state.hasStateData() ? child : const SizedBox.shrink()
|
// // duration: animationDuration,
|
||||||
),
|
// // curve: Curves.easeInOut,
|
||||||
],
|
// // child: state.hasStateData() ? child : const SizedBox.shrink()
|
||||||
),
|
// // ),
|
||||||
)
|
// // ],
|
||||||
],
|
// // ),
|
||||||
);
|
// // )
|
||||||
}
|
// ],
|
||||||
}
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@ -99,7 +99,7 @@ class _FileElementState extends State<FileElement> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
if(widget.file.isDirectory) {
|
if(widget.file.isDirectory) {
|
||||||
Navigator.of(context).push(MaterialPageRoute(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
builder: (context) => Files(widget.path.toList()..add(widget.file.name)),
|
builder: (context) => Files(path: widget.path.toList()..add(widget.file.name)),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
if(EndpointData().getEndpointMode() == EndpointMode.stage) {
|
if(EndpointData().getEndpointMode() == EndpointMode.stage) {
|
||||||
|
@ -21,7 +21,7 @@ import 'filesUploadDialog.dart';
|
|||||||
|
|
||||||
class Files extends StatefulWidget {
|
class Files extends StatefulWidget {
|
||||||
final List<String> path;
|
final List<String> path;
|
||||||
const Files(this.path, {super.key});
|
Files({List<String>? path, super.key}) : path = path ?? [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<Files> createState() => _FilesState();
|
State<Files> createState() => _FilesState();
|
||||||
|
@ -1,48 +1,48 @@
|
|||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import '../../../state/app/application/marianumMessage/marianum_message_controller.dart';
|
// import '../../../state/app/application/marianumMessage/marianum_message_controller.dart';
|
||||||
import '../../../state/app/application/marianumMessage/marianum_message_state.dart';
|
// import '../../../state/app/application/marianumMessage/marianum_message_state.dart';
|
||||||
import '../../../state/infrastructure/loadable_state.dart';
|
// import '../../../state/infrastructure/loadable_state.dart';
|
||||||
import '../../../state/infrastructure/state_extensions.dart';
|
// import '../../../state/infrastructure/state_extensions.dart';
|
||||||
import '../../../state/widgets/controller_consumer.dart';
|
// import '../../../state/widgets/controller_consumer.dart';
|
||||||
import '../../../state/widgets/loadable_controller_consumer.dart';
|
// import '../../../state/widgets/loadable_controller_consumer.dart';
|
||||||
import '../../../state/widgets/sub_selected_controller_consumer.dart';
|
// import '../../../state/widgets/sub_selected_controller_consumer.dart';
|
||||||
import '../../../state/widgets/controller_provider.dart';
|
// import '../../../state/widgets/controller_provider.dart';
|
||||||
|
//
|
||||||
class Test extends StatelessWidget {
|
// class Test extends StatelessWidget {
|
||||||
const Test({super.key});
|
// const Test({super.key});
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) => ControllerProvider<MarianumMessageController>(
|
// Widget build(BuildContext context) => ControllerProvider<MarianumMessageController>(
|
||||||
create: (context) => MarianumMessageController(),
|
// create: (context) => MarianumMessageController(),
|
||||||
child: (context) => Scaffold(
|
// child: (context) => Scaffold(
|
||||||
appBar: AppBar(title: const Text('TEST')),
|
// appBar: AppBar(title: const Text('TEST')),
|
||||||
body: LoadableControllerConsumer<MarianumMessageController, LoadableState<MarianumMessageState>>(
|
// body: ControllerConsumer<MarianumMessageController, MarianumMessageState>(
|
||||||
child: Column(
|
// child: (context, state) => Column(
|
||||||
children: [
|
// children: [
|
||||||
TextButton(
|
// TextButton(
|
||||||
onPressed: () => context.readController<MarianumMessageController>().loading(),
|
// onPressed: () => context.readController<MarianumMessageController>().someaction(),
|
||||||
child: Text(context.watchController<MarianumMessageController>().state.loadingState.toString())
|
// child: Text(context.watchController<MarianumMessageController>().state.toString())
|
||||||
),
|
// ),
|
||||||
TextButton(
|
// TextButton(
|
||||||
onPressed: () => context.readController<MarianumMessageController>().backgroundLoading(),
|
// onPressed: () => context.readController<MarianumMessageController>().backgroundLoading(),
|
||||||
child: Text(context.watchController<MarianumMessageController>().state.loadingState.toString())
|
// child: Text(context.watchController<MarianumMessageController>().state.toString())
|
||||||
),
|
// ),
|
||||||
TextButton(
|
// TextButton(
|
||||||
onPressed: () => context.readController<MarianumMessageController>().done(),
|
// onPressed: () => context.readController<MarianumMessageController>().done(),
|
||||||
child: Text(context.watchController<MarianumMessageController>().state.loadingState.toString())
|
// child: Text(context.watchController<MarianumMessageController>().state.toString())
|
||||||
),
|
// ),
|
||||||
TextButton(
|
// TextButton(
|
||||||
onPressed: () => context.readController<MarianumMessageController>().error(),
|
// onPressed: () => context.readController<MarianumMessageController>().error(),
|
||||||
child: Text(context.watchController<MarianumMessageController>().state.loadingState.toString())
|
// child: Text(context.watchController<MarianumMessageController>().state.toString())
|
||||||
),
|
// ),
|
||||||
ControllerConsumer<MarianumMessageController, LoadableState<MarianumMessageState>>(child: (context, state) => Text(state.data!.test.toString())),
|
// ControllerConsumer<MarianumMessageController, MarianumMessageState>(child: (context, state) => Text(state.base.toString())),
|
||||||
SubSelectedControllerConsumer<MarianumMessageController, LoadableState<MarianumMessageState>, LoadingState>(
|
// SubSelectedControllerConsumer<MarianumMessageController, MarianumMessageState, List>(
|
||||||
subSelect: (state) => state.loadingState,
|
// subSelect: (state) => state.messages,
|
||||||
child: (context, state) => Text(state.toString()),
|
// child: (context, state) => Text(state.toString()),
|
||||||
)
|
// )
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
@ -6,6 +6,7 @@ import 'package:in_app_review/in_app_review.dart';
|
|||||||
import '../../extensions/renderNotNull.dart';
|
import '../../extensions/renderNotNull.dart';
|
||||||
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.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 '../../widget/ListItem.dart';
|
import '../../widget/ListItem.dart';
|
||||||
import '../../widget/centeredLeading.dart';
|
import '../../widget/centeredLeading.dart';
|
||||||
import '../../widget/infoDialog.dart';
|
import '../../widget/infoDialog.dart';
|
||||||
@ -16,7 +17,6 @@ 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});
|
||||||
@ -77,7 +77,7 @@ class Overhang extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.science_outlined),
|
leading: const Icon(Icons.science_outlined),
|
||||||
onTap: () => pushScreen(context, withNavBar: false, screen: const Test()),
|
onTap: () => pushScreen(context, withNavBar: false, screen: const GradeAveragesScreen()),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -102,6 +102,7 @@ dependencies:
|
|||||||
flutter_bloc: ^8.1.5
|
flutter_bloc: ^8.1.5
|
||||||
freezed_annotation: ^2.4.1
|
freezed_annotation: ^2.4.1
|
||||||
connectivity_plus: ^6.0.3
|
connectivity_plus: ^6.0.3
|
||||||
|
hydrated_bloc: ^9.1.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user