wip: bloc for files
This commit is contained in:
		| @@ -35,7 +35,7 @@ GetHolidaysResponseObject _$GetHolidaysResponseObjectFromJson( | ||||
|     GetHolidaysResponseObject( | ||||
|       start: json['start'] as String, | ||||
|       end: json['end'] as String, | ||||
|       year: json['year'] as int, | ||||
|       year: (json['year'] as num).toInt(), | ||||
|       stateCode: json['stateCode'] as String, | ||||
|       name: json['name'] as String, | ||||
|       slug: json['slug'] as String, | ||||
|   | ||||
| @@ -9,7 +9,7 @@ part of 'fileSharingApiParams.dart'; | ||||
| FileSharingApiParams _$FileSharingApiParamsFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     FileSharingApiParams( | ||||
|       shareType: json['shareType'] as int, | ||||
|       shareType: (json['shareType'] as num).toInt(), | ||||
|       shareWith: json['shareWith'] as String, | ||||
|       path: json['path'] as String, | ||||
|       referenceId: json['referenceId'] as String?, | ||||
|   | ||||
| @@ -10,10 +10,10 @@ GetChatParams _$GetChatParamsFromJson(Map<String, dynamic> json) => | ||||
|     GetChatParams( | ||||
|       lookIntoFuture: | ||||
|           $enumDecode(_$GetChatParamsSwitchEnumMap, json['lookIntoFuture']), | ||||
|       limit: json['limit'] as int?, | ||||
|       lastKnownMessageId: json['lastKnownMessageId'] as int?, | ||||
|       lastCommonReadId: json['lastCommonReadId'] as int?, | ||||
|       timeout: json['timeout'] as int?, | ||||
|       limit: (json['limit'] as num?)?.toInt(), | ||||
|       lastKnownMessageId: (json['lastKnownMessageId'] as num?)?.toInt(), | ||||
|       lastCommonReadId: (json['lastCommonReadId'] as num?)?.toInt(), | ||||
|       timeout: (json['timeout'] as num?)?.toInt(), | ||||
|       setReadMarker: $enumDecodeNullable( | ||||
|           _$GetChatParamsSwitchEnumMap, json['setReadMarker']), | ||||
|       includeLastKnown: $enumDecodeNullable( | ||||
|   | ||||
| @@ -32,13 +32,13 @@ Map<String, dynamic> _$GetChatResponseToJson(GetChatResponse instance) { | ||||
| GetChatResponseObject _$GetChatResponseObjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetChatResponseObject( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['token'] as String, | ||||
|       $enumDecode( | ||||
|           _$GetRoomResponseObjectMessageActorTypeEnumMap, json['actorType']), | ||||
|       json['actorId'] as String, | ||||
|       json['actorDisplayName'] as String, | ||||
|       json['timestamp'] as int, | ||||
|       (json['timestamp'] as num).toInt(), | ||||
|       json['systemMessage'] as String, | ||||
|       $enumDecode( | ||||
|           _$GetRoomResponseObjectMessageTypeEnumMap, json['messageType']), | ||||
| @@ -47,7 +47,7 @@ GetChatResponseObject _$GetChatResponseObjectFromJson( | ||||
|       json['message'] as String, | ||||
|       _fromJson(json['messageParameters']), | ||||
|       (json['reactions'] as Map<String, dynamic>?)?.map( | ||||
|         (k, e) => MapEntry(k, e as int), | ||||
|         (k, e) => MapEntry(k, (e as num).toInt()), | ||||
|       ), | ||||
|       (json['reactionsSelf'] as List<dynamic>?) | ||||
|           ?.map((e) => e as String) | ||||
|   | ||||
| @@ -8,7 +8,7 @@ part of 'createRoomParams.dart'; | ||||
|  | ||||
| CreateRoomParams _$CreateRoomParamsFromJson(Map<String, dynamic> json) => | ||||
|     CreateRoomParams( | ||||
|       roomType: json['roomType'] as int, | ||||
|       roomType: (json['roomType'] as num).toInt(), | ||||
|       invite: json['invite'] as String, | ||||
|       source: json['source'] as String?, | ||||
|       roomName: json['roomName'] as String?, | ||||
|   | ||||
| @@ -35,17 +35,17 @@ Map<String, dynamic> _$GetParticipantsResponseToJson( | ||||
| GetParticipantsResponseObject _$GetParticipantsResponseObjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetParticipantsResponseObject( | ||||
|       json['attendeeId'] as int, | ||||
|       (json['attendeeId'] as num).toInt(), | ||||
|       json['actorType'] as String, | ||||
|       json['actorId'] as String, | ||||
|       json['displayName'] as String, | ||||
|       $enumDecode(_$GetParticipantsResponseObjectParticipantTypeEnumMap, | ||||
|           json['participantType']), | ||||
|       json['lastPing'] as int, | ||||
|       (json['lastPing'] as num).toInt(), | ||||
|       $enumDecode(_$GetParticipantsResponseObjectParticipantsInCallFlagsEnumMap, | ||||
|           json['inCall']), | ||||
|       json['permissions'] as int, | ||||
|       json['attendeePermissions'] as int, | ||||
|       (json['permissions'] as num).toInt(), | ||||
|       (json['attendeePermissions'] as num).toInt(), | ||||
|       json['sessionId'] as String?, | ||||
|       (json['sessionIds'] as List<dynamic>).map((e) => e as String).toList(), | ||||
|       json['status'] as String?, | ||||
|   | ||||
| @@ -44,7 +44,7 @@ GetReactionsResponseObject _$GetReactionsResponseObjectFromJson( | ||||
|           _$GetReactionsResponseObjectActorTypeEnumMap, json['actorType']), | ||||
|       json['actorId'] as String, | ||||
|       json['actorDisplayName'] as String, | ||||
|       json['timestamp'] as int, | ||||
|       (json['timestamp'] as num).toInt(), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$GetReactionsResponseObjectToJson( | ||||
|   | ||||
| @@ -11,7 +11,7 @@ GetRoomParams _$GetRoomParamsFromJson(Map<String, dynamic> json) => | ||||
|       noStatusUpdate: $enumDecodeNullable( | ||||
|           _$GetRoomParamsStatusUpdateEnumMap, json['noStatusUpdate']), | ||||
|       includeStatus: json['includeStatus'] as bool?, | ||||
|       modifiedSince: json['modifiedSince'] as int?, | ||||
|       modifiedSince: (json['modifiedSince'] as num?)?.toInt(), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$GetRoomParamsToJson(GetRoomParams instance) => | ||||
|   | ||||
| @@ -32,33 +32,33 @@ Map<String, dynamic> _$GetRoomResponseToJson(GetRoomResponse instance) { | ||||
| GetRoomResponseObject _$GetRoomResponseObjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetRoomResponseObject( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['token'] as String, | ||||
|       $enumDecode(_$GetRoomResponseObjectConversationTypeEnumMap, json['type']), | ||||
|       json['name'] as String, | ||||
|       json['displayName'] as String, | ||||
|       json['description'] as String, | ||||
|       json['participantType'] as int, | ||||
|       json['participantFlags'] as int, | ||||
|       json['readOnly'] as int, | ||||
|       json['listable'] as int, | ||||
|       json['lastPing'] as int, | ||||
|       (json['participantType'] as num).toInt(), | ||||
|       (json['participantFlags'] as num).toInt(), | ||||
|       (json['readOnly'] as num).toInt(), | ||||
|       (json['listable'] as num).toInt(), | ||||
|       (json['lastPing'] as num).toInt(), | ||||
|       json['sessionId'] as String, | ||||
|       json['hasPassword'] as bool, | ||||
|       json['hasCall'] as bool, | ||||
|       json['callFlag'] as int, | ||||
|       (json['callFlag'] as num).toInt(), | ||||
|       json['canStartCall'] as bool, | ||||
|       json['canDeleteConversation'] as bool, | ||||
|       json['canLeaveConversation'] as bool, | ||||
|       json['lastActivity'] as int, | ||||
|       (json['lastActivity'] as num).toInt(), | ||||
|       json['isFavorite'] as bool, | ||||
|       $enumDecode(_$GetRoomResponseObjectParticipantNotificationLevelEnumMap, | ||||
|           json['notificationLevel']), | ||||
|       json['unreadMessages'] as int, | ||||
|       (json['unreadMessages'] as num).toInt(), | ||||
|       json['unreadMention'] as bool, | ||||
|       json['unreadMentionDirect'] as bool, | ||||
|       json['lastReadMessage'] as int, | ||||
|       json['lastCommonReadMessage'] as int, | ||||
|       (json['lastReadMessage'] as num).toInt(), | ||||
|       (json['lastCommonReadMessage'] as num).toInt(), | ||||
|       GetChatResponseObject.fromJson( | ||||
|           json['lastMessage'] as Map<String, dynamic>), | ||||
|       json['status'] as String?, | ||||
|   | ||||
| @@ -8,7 +8,7 @@ part of 'setReadMarkerParams.dart'; | ||||
|  | ||||
| SetReadMarkerParams _$SetReadMarkerParamsFromJson(Map<String, dynamic> json) => | ||||
|     SetReadMarkerParams( | ||||
|       lastReadMessage: json['lastReadMessage'] as int?, | ||||
|       lastReadMessage: (json['lastReadMessage'] as num?)?.toInt(), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$SetReadMarkerParamsToJson( | ||||
|   | ||||
| @@ -12,7 +12,7 @@ CacheableFile _$CacheableFileFromJson(Map<String, dynamic> json) => | ||||
|       isDirectory: json['isDirectory'] as bool, | ||||
|       name: json['name'] as String, | ||||
|       mimeType: json['mimeType'] as String?, | ||||
|       size: json['size'] as int?, | ||||
|       size: (json['size'] as num?)?.toInt(), | ||||
|       eTag: json['eTag'] as String?, | ||||
|       createdAt: json['createdAt'] == null | ||||
|           ? null | ||||
|   | ||||
| @@ -11,7 +11,7 @@ AddFeedbackParams _$AddFeedbackParamsFromJson(Map<String, dynamic> json) => | ||||
|       user: json['user'] as String, | ||||
|       feedback: json['feedback'] as String, | ||||
|       screenshot: json['screenshot'] as String?, | ||||
|       appVersion: json['appVersion'] as int, | ||||
|       appVersion: (json['appVersion'] as num).toInt(), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$AddFeedbackParamsToJson(AddFeedbackParams instance) => | ||||
|   | ||||
| @@ -12,7 +12,7 @@ UpdateUserIndexParams _$UpdateUserIndexParamsFromJson( | ||||
|       user: json['user'] as String, | ||||
|       username: json['username'] as String, | ||||
|       device: json['device'] as String, | ||||
|       appVersion: json['appVersion'] as int, | ||||
|       appVersion: (json['appVersion'] as num).toInt(), | ||||
|       deviceInfo: json['deviceInfo'] as String, | ||||
|     ); | ||||
|  | ||||
|   | ||||
| @@ -10,9 +10,9 @@ AuthenticateResponse _$AuthenticateResponseFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     AuthenticateResponse( | ||||
|       json['sessionId'] as String, | ||||
|       json['personType'] as int, | ||||
|       json['personId'] as int, | ||||
|       json['klasseId'] as int, | ||||
|       (json['personType'] as num).toInt(), | ||||
|       (json['personId'] as num).toInt(), | ||||
|       (json['klasseId'] as num).toInt(), | ||||
|     )..headers = (json['headers'] as Map<String, dynamic>?)?.map( | ||||
|         (k, e) => MapEntry(k, e as String), | ||||
|       ); | ||||
|   | ||||
| @@ -33,11 +33,11 @@ Map<String, dynamic> _$GetHolidaysResponseToJson(GetHolidaysResponse instance) { | ||||
| GetHolidaysResponseObject _$GetHolidaysResponseObjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetHolidaysResponseObject( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['name'] as String, | ||||
|       json['longName'] as String, | ||||
|       json['startDate'] as int, | ||||
|       json['endDate'] as int, | ||||
|       (json['startDate'] as num).toInt(), | ||||
|       (json['endDate'] as num).toInt(), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$GetHolidaysResponseObjectToJson( | ||||
|   | ||||
| @@ -33,7 +33,7 @@ Map<String, dynamic> _$GetRoomsResponseToJson(GetRoomsResponse instance) { | ||||
| GetRoomsResponseObject _$GetRoomsResponseObjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetRoomsResponseObject( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['name'] as String, | ||||
|       json['longName'] as String, | ||||
|       json['active'] as bool, | ||||
|   | ||||
| @@ -33,7 +33,7 @@ Map<String, dynamic> _$GetSubjectsResponseToJson(GetSubjectsResponse instance) { | ||||
| GetSubjectsResponseObject _$GetSubjectsResponseObjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetSubjectsResponseObject( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['name'] as String, | ||||
|       json['longName'] as String, | ||||
|       json['alternateName'] as String, | ||||
|   | ||||
| @@ -22,8 +22,8 @@ GetTimetableParamsOptions _$GetTimetableParamsOptionsFromJson( | ||||
|     GetTimetableParamsOptions( | ||||
|       element: GetTimetableParamsOptionsElement.fromJson( | ||||
|           json['element'] as Map<String, dynamic>), | ||||
|       startDate: json['startDate'] as int?, | ||||
|       endDate: json['endDate'] as int?, | ||||
|       startDate: (json['startDate'] as num?)?.toInt(), | ||||
|       endDate: (json['endDate'] as num?)?.toInt(), | ||||
|       onlyBaseTimetable: json['onlyBaseTimetable'] as bool?, | ||||
|       showBooking: json['showBooking'] as bool?, | ||||
|       showInfo: json['showInfo'] as bool?, | ||||
| @@ -99,8 +99,8 @@ const _$GetTimetableParamsOptionsFieldsEnumMap = { | ||||
| GetTimetableParamsOptionsElement _$GetTimetableParamsOptionsElementFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetTimetableParamsOptionsElement( | ||||
|       id: json['id'] as int, | ||||
|       type: json['type'] as int, | ||||
|       id: (json['id'] as num).toInt(), | ||||
|       type: (json['type'] as num).toInt(), | ||||
|       keyType: $enumDecodeNullable( | ||||
|           _$GetTimetableParamsOptionsElementKeyTypeEnumMap, json['keyType']), | ||||
|     ); | ||||
|   | ||||
| @@ -35,16 +35,16 @@ Map<String, dynamic> _$GetTimetableResponseToJson( | ||||
| GetTimetableResponseObject _$GetTimetableResponseObjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetTimetableResponseObject( | ||||
|       id: json['id'] as int, | ||||
|       date: json['date'] as int, | ||||
|       startTime: json['startTime'] as int, | ||||
|       endTime: json['endTime'] as int, | ||||
|       id: (json['id'] as num).toInt(), | ||||
|       date: (json['date'] as num).toInt(), | ||||
|       startTime: (json['startTime'] as num).toInt(), | ||||
|       endTime: (json['endTime'] as num).toInt(), | ||||
|       lstype: json['lstype'] as String?, | ||||
|       code: json['code'] as String?, | ||||
|       info: json['info'] as String?, | ||||
|       substText: json['substText'] as String?, | ||||
|       lstext: json['lstext'] as String?, | ||||
|       lsnumber: json['lsnumber'] as int?, | ||||
|       lsnumber: (json['lsnumber'] as num?)?.toInt(), | ||||
|       statflags: json['statflags'] as String?, | ||||
|       activityType: json['activityType'] as String?, | ||||
|       sg: json['sg'] as String?, | ||||
| @@ -110,7 +110,7 @@ GetTimetableResponseObjectFieldsObject | ||||
|     _$GetTimetableResponseObjectFieldsObjectFromJson( | ||||
|             Map<String, dynamic> json) => | ||||
|         GetTimetableResponseObjectFieldsObject( | ||||
|           id: json['id'] as int?, | ||||
|           id: (json['id'] as num?)?.toInt(), | ||||
|           name: json['name'] as String?, | ||||
|           longname: json['longname'] as String?, | ||||
|           externalkey: json['externalkey'] as String?, | ||||
| @@ -128,7 +128,7 @@ Map<String, dynamic> _$GetTimetableResponseObjectFieldsObjectToJson( | ||||
| GetTimetableResponseObjectClass _$GetTimetableResponseObjectClassFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetTimetableResponseObjectClass( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['name'] as String, | ||||
|       json['longname'] as String, | ||||
|       json['externalkey'] as String?, | ||||
| @@ -146,10 +146,10 @@ Map<String, dynamic> _$GetTimetableResponseObjectClassToJson( | ||||
| GetTimetableResponseObjectTeacher _$GetTimetableResponseObjectTeacherFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetTimetableResponseObjectTeacher( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['name'] as String, | ||||
|       json['longname'] as String, | ||||
|       json['orgid'] as int?, | ||||
|       (json['orgid'] as num?)?.toInt(), | ||||
|       json['orgname'] as String?, | ||||
|       json['externalkey'] as String?, | ||||
|     ); | ||||
| @@ -168,7 +168,7 @@ Map<String, dynamic> _$GetTimetableResponseObjectTeacherToJson( | ||||
| GetTimetableResponseObjectSubject _$GetTimetableResponseObjectSubjectFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetTimetableResponseObjectSubject( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['name'] as String, | ||||
|       json['longname'] as String, | ||||
|     ); | ||||
| @@ -184,7 +184,7 @@ Map<String, dynamic> _$GetTimetableResponseObjectSubjectToJson( | ||||
| GetTimetableResponseObjectRoom _$GetTimetableResponseObjectRoomFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     GetTimetableResponseObjectRoom( | ||||
|       json['id'] as int, | ||||
|       (json['id'] as num).toInt(), | ||||
|       json['name'] as String, | ||||
|       json['longname'] as String, | ||||
|     ); | ||||
|   | ||||
							
								
								
									
										93
									
								
								lib/app.dart
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								lib/app.dart
									
									
									
									
									
								
							| @@ -94,55 +94,56 @@ class _AppState extends State<App> with WidgetsBindingObserver { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) => PersistentTabView( | ||||
|       controller: Main.bottomNavigator, | ||||
|       navBarOverlap: const NavBarOverlap.none(), | ||||
|       backgroundColor: Theme.of(context).colorScheme.primary, | ||||
|       handleAndroidBackButtonPress: false, | ||||
|     controller: Main.bottomNavigator, | ||||
|     navBarOverlap: const NavBarOverlap.none(), | ||||
|     backgroundColor: Theme.of(context).colorScheme.primary, | ||||
|     handleAndroidBackButtonPress: false, | ||||
|  | ||||
|       screenTransitionAnimation: const ScreenTransitionAnimation(curve: Curves.easeOutQuad, duration: Duration(milliseconds: 200)), | ||||
|       tabs: [ | ||||
|         AppModule.getModule(Modules.timetable).toBottomTab(context), | ||||
|         AppModule.getModule(Modules.talk).toBottomTab( | ||||
|           context, | ||||
|           itemBuilder: (icon) => Consumer<ChatListProps>( | ||||
|             builder: (context, value, child) { | ||||
|               if(value.primaryLoading()) return Icon(icon); | ||||
|               var messages = value.getRoomsResponse.data.map((e) => e.unreadMessages).reduce((a, b) => a+b); | ||||
|               return badges.Badge( | ||||
|                 showBadge: messages > 0, | ||||
|                 position: badges.BadgePosition.topEnd(top: -3, end: -3), | ||||
|                 stackFit: StackFit.loose, | ||||
|                 badgeStyle: badges.BadgeStyle( | ||||
|                   padding: const EdgeInsets.all(3), | ||||
|                   badgeColor: Theme.of(context).primaryColor, | ||||
|                   elevation: 1, | ||||
|                 ), | ||||
|                 badgeContent: Text('$messages', style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)), | ||||
|                 child: Icon(icon), | ||||
|               ); | ||||
|             }, | ||||
|           ), | ||||
|         ), | ||||
|         AppModule.getModule(Modules.files).toBottomTab(context), | ||||
|  | ||||
|         PersistentTabConfig( | ||||
|           screen: const Breaker(breaker: BreakerArea.more, child: Overhang()), | ||||
|           item: ItemConfig( | ||||
|               activeForegroundColor: Theme.of(context).primaryColor, | ||||
|               inactiveForegroundColor: Theme.of(context).colorScheme.secondary, | ||||
|               icon: const Icon(Icons.apps), | ||||
|               title: 'Mehr' | ||||
|           ), | ||||
|         ), | ||||
|       ], | ||||
|       navBarBuilder: (config) => Style6BottomNavBar( | ||||
|         navBarConfig: config, | ||||
|         navBarDecoration: NavBarDecoration( | ||||
|           border: const Border(top: BorderSide(width: 1, color: Colors.grey)), | ||||
|           color: Theme.of(context).colorScheme.surface, | ||||
|     screenTransitionAnimation: const ScreenTransitionAnimation(curve: Curves.easeOutQuad, duration: Duration(milliseconds: 200)), | ||||
|     tabs: [ | ||||
|       AppModule.getModule(Modules.timetable).toBottomTab(context), | ||||
|       AppModule.getModule(Modules.talk).toBottomTab( | ||||
|         context, | ||||
|         itemBuilder: (icon) => Consumer<ChatListProps>( | ||||
|           builder: (context, value, child) { | ||||
|             if(value.primaryLoading()) return Icon(icon); | ||||
|             var messages = value.getRoomsResponse.data.map((e) => e.unreadMessages).reduce((a, b) => a+b); | ||||
|             return badges.Badge( | ||||
|               showBadge: messages > 0, | ||||
|               position: badges.BadgePosition.topEnd(top: -3, end: -3), | ||||
|               stackFit: StackFit.loose, | ||||
|               badgeStyle: badges.BadgeStyle( | ||||
|                 padding: const EdgeInsets.all(3), | ||||
|                 badgeColor: Theme.of(context).primaryColor, | ||||
|                 elevation: 1, | ||||
|               ), | ||||
|               badgeContent: Text('$messages', style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)), | ||||
|               child: Icon(icon), | ||||
|             ); | ||||
|           }, | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|       AppModule.getModule(Modules.blocFiles).toBottomTab(context), | ||||
|       AppModule.getModule(Modules.files).toBottomTab(context), | ||||
|  | ||||
|       PersistentTabConfig( | ||||
|         screen: const Breaker(breaker: BreakerArea.more, child: Overhang()), | ||||
|         item: ItemConfig( | ||||
|             activeForegroundColor: Theme.of(context).primaryColor, | ||||
|             inactiveForegroundColor: Theme.of(context).colorScheme.secondary, | ||||
|             icon: const Icon(Icons.apps), | ||||
|             title: 'Mehr' | ||||
|         ), | ||||
|       ), | ||||
|     ], | ||||
|     navBarBuilder: (config) => Style6BottomNavBar( | ||||
|       navBarConfig: config, | ||||
|       navBarDecoration: NavBarDecoration( | ||||
|         border: const Border(top: BorderSide(width: 1, color: Colors.grey)), | ||||
|         color: Theme.of(context).colorScheme.surface, | ||||
|       ), | ||||
|     ), | ||||
|   ); | ||||
|  | ||||
|   @override | ||||
|   void dispose() { | ||||
|   | ||||
| @@ -42,7 +42,7 @@ Future<void> main() async { | ||||
|   var initialisationTasks = [ | ||||
|     Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform) | ||||
|       .then((value) async => log("Firebase token: ${await FirebaseMessaging.instance.getToken() ?? "Error: no Firebase token!"}")) | ||||
|       .onError((error, stackTrace) => log('Error initializing Firebase: $error')), | ||||
|       .onError((error, stackTrace) => log('Error initializing Firebase: $error', stackTrace: stackTrace)), | ||||
|  | ||||
|     PlatformAssetBundle().load('assets/ca/lets-encrypt-r3.pem').then(addCertificateAsTrusted), | ||||
|     PlatformAssetBundle().load('assets/ca/lets-encrypt-r10.pem').then(addCertificateAsTrusted), | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import 'package:dio/dio.dart'; | ||||
|  | ||||
| import '../../infrastructure/dataLoader/data_loader.dart'; | ||||
| import '../../infrastructure/dataLoader/http_data_loader.dart'; | ||||
|  | ||||
| abstract class HolidayDataLoader<TResult> extends DataLoader<TResult> { | ||||
| abstract class HolidayDataLoader<TResult> extends HttpDataLoader<TResult> { | ||||
|   HolidayDataLoader() : super(Dio(BaseOptions( | ||||
|     baseUrl: 'https://ferien-api.de/api/v1/', | ||||
|   ))); | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import 'package:dio/dio.dart'; | ||||
|  | ||||
| import '../../infrastructure/dataLoader/data_loader.dart'; | ||||
| import '../../infrastructure/dataLoader/http_data_loader.dart'; | ||||
|  | ||||
| abstract class MhslDataLoader<TResult> extends DataLoader<TResult> { | ||||
| abstract class MhslDataLoader<TResult> extends HttpDataLoader<TResult> { | ||||
|   MhslDataLoader() : super(Dio(BaseOptions( | ||||
|     baseUrl: 'https://mhsl.eu/marianum/marianummobile/' | ||||
|   ))); | ||||
|   | ||||
| @@ -2,26 +2,21 @@ import 'dart:convert'; | ||||
| import 'dart:developer'; | ||||
| 
 | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| 
 | ||||
| abstract class DataLoader<TResult> { | ||||
| abstract class HttpDataLoader<TResult> { | ||||
|   final Dio dio; | ||||
|   DataLoader(this.dio) { | ||||
|   HttpDataLoader(this.dio) { | ||||
|     dio.options.connectTimeout = const Duration(seconds: 10).inMilliseconds; | ||||
|     dio.options.sendTimeout = const Duration(seconds: 30).inMilliseconds; | ||||
|     dio.options.receiveTimeout = const Duration(seconds: 30).inMilliseconds; | ||||
|   } | ||||
| 
 | ||||
|   Future<TResult> run() async { | ||||
|     var fetcher = fetch(); | ||||
|     await Future.wait([ | ||||
|       fetcher, | ||||
|       Future.delayed(const Duration(milliseconds: 500)) // TODO tune or remove | ||||
|     ]); | ||||
| 
 | ||||
|     var response = await fetcher; | ||||
|     var response = await fetch(); | ||||
|     try { | ||||
|       return assemble(DataLoaderResult( | ||||
|         json: jsonDecode(response.data!), | ||||
|         json: await compute(jsonDecode, response.data!), | ||||
|         headers: response.headers.map.map((key, value) => MapEntry(key, value.join(';'))), | ||||
|       )); | ||||
|     } catch(trace, e) { | ||||
| @@ -166,27 +166,22 @@ class __$$LoadableStateImplCopyWithImpl<TState, $Res> | ||||
|  | ||||
| class _$LoadableStateImpl<TState> extends _LoadableState<TState> { | ||||
|   const _$LoadableStateImpl( | ||||
|       {this.isLoading = true, | ||||
|       this.data = null, | ||||
|       this.lastFetch = null, | ||||
|       this.reFetch = null, | ||||
|       this.error = null}) | ||||
|       {required this.isLoading, | ||||
|       required this.data, | ||||
|       required this.lastFetch, | ||||
|       required this.reFetch, | ||||
|       required this.error}) | ||||
|       : super._(); | ||||
|  | ||||
|   @override | ||||
|   @JsonKey() | ||||
|   final bool isLoading; | ||||
|   @override | ||||
|   @JsonKey() | ||||
|   final TState? data; | ||||
|   @override | ||||
|   @JsonKey() | ||||
|   final int? lastFetch; | ||||
|   @override | ||||
|   @JsonKey() | ||||
|   final void Function()? reFetch; | ||||
|   @override | ||||
|   @JsonKey() | ||||
|   final LoadingError? error; | ||||
|  | ||||
|   @override | ||||
| @@ -222,11 +217,11 @@ class _$LoadableStateImpl<TState> extends _LoadableState<TState> { | ||||
|  | ||||
| abstract class _LoadableState<TState> extends LoadableState<TState> { | ||||
|   const factory _LoadableState( | ||||
|       {final bool isLoading, | ||||
|       final TState? data, | ||||
|       final int? lastFetch, | ||||
|       final void Function()? reFetch, | ||||
|       final LoadingError? error}) = _$LoadableStateImpl<TState>; | ||||
|       {required final bool isLoading, | ||||
|       required final TState? data, | ||||
|       required final int? lastFetch, | ||||
|       required final void Function()? reFetch, | ||||
|       required final LoadingError? error}) = _$LoadableStateImpl<TState>; | ||||
|   const _LoadableState._() : super._(); | ||||
|  | ||||
|   @override | ||||
|   | ||||
| @@ -30,16 +30,17 @@ abstract class LoadableHydratedBloc< | ||||
|         isLoading: state.isLoading, | ||||
|         data: event.state(innerState ?? fromNothing()), | ||||
|         lastFetch: state.lastFetch, | ||||
|         reFetch: retry, | ||||
|         reFetch: fetch, | ||||
|         error: state.error, | ||||
|       )); | ||||
|       if(event.fetch) fetch(); | ||||
|     }); | ||||
|  | ||||
|     on<DataGathered<TState>>((event, emit) => emit(LoadableState( | ||||
|       isLoading: false, | ||||
|       data: event.state(innerState ?? fromNothing()), | ||||
|       lastFetch: DateTime.now().millisecondsSinceEpoch, | ||||
|       reFetch: retry, | ||||
|       reFetch: fetch, | ||||
|       error: null, | ||||
|     ))); | ||||
|  | ||||
| @@ -55,7 +56,7 @@ abstract class LoadableHydratedBloc< | ||||
|         isLoading: false, | ||||
|         data: innerState, | ||||
|         lastFetch: state.lastFetch, | ||||
|         reFetch: retry, | ||||
|         reFetch: fetch, | ||||
|         error: event.error | ||||
|     ))); | ||||
|  | ||||
| @@ -66,19 +67,14 @@ abstract class LoadableHydratedBloc< | ||||
|   TState? get innerState => state.data; | ||||
|   TRepository get repo => _repository; | ||||
|  | ||||
|   void retry() { | ||||
|     log('Fetch retry triggered for ${TState.toString()}'); | ||||
|     add(RefetchStarted<TState>()); | ||||
|     fetch(); | ||||
|   } | ||||
|  | ||||
|   void fetch() { | ||||
|     log('Fetching data for ${TState.toString()}'); | ||||
|     add(RefetchStarted<TState>()); | ||||
|     gatherData().catchError( | ||||
|       (e) { | ||||
|         log('Error while fetching ${TState.toString()}: ${e.toString()}'); | ||||
|         add(Error(LoadingError( | ||||
|           message: e.message ?? e.toString(), | ||||
|           message: e.toString(), | ||||
|           allowRetry: true, | ||||
|         ))); | ||||
|       }, | ||||
| @@ -92,7 +88,7 @@ abstract class LoadableHydratedBloc< | ||||
|     var rawData = LoadableSaveContext.unwrap(json); | ||||
|     return LoadableState( | ||||
|       isLoading: true, | ||||
|       data: fromStorage(rawData.data), | ||||
|       data: fromStorage(rawData.data), // TODO fromStorage in isolate | ||||
|       lastFetch: rawData.meta.timestamp, | ||||
|       reFetch: null, | ||||
|       error: null, | ||||
| @@ -103,7 +99,7 @@ abstract class LoadableHydratedBloc< | ||||
|   Map<String, dynamic>? toJson(LoadableState<TState> state) { | ||||
|     Map<String, dynamic>? data; | ||||
|     try { | ||||
|       data = state.data == null ? null : toStorage(state.data); | ||||
|       data = state.data == null ? null : toStorage(state.data); // TODO toStorage in isolate | ||||
|     } catch(e) { | ||||
|       log('Failed to save state ${TState.toString()}: ${e.toString()}'); | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,8 @@ import '../../loadableState/loading_error.dart'; | ||||
| class LoadableHydratedBlocEvent<TState> {} | ||||
| class Emit<TState> extends LoadableHydratedBlocEvent<TState> { | ||||
|   final TState Function(TState state) state; | ||||
|   Emit(this.state); | ||||
|   final bool fetch; | ||||
|   Emit(this.state, {this.fetch = false}); | ||||
| } | ||||
| class DataGathered<TState> extends LoadableHydratedBlocEvent<TState> { | ||||
|   final TState Function(TState state) state; | ||||
|   | ||||
| @@ -9,7 +9,7 @@ part of 'loadable_save_context.dart'; | ||||
| _$LoadableSaveContextImpl _$$LoadableSaveContextImplFromJson( | ||||
|         Map<String, dynamic> json) => | ||||
|     _$LoadableSaveContextImpl( | ||||
|       timestamp: json['timestamp'] as int, | ||||
|       timestamp: (json['timestamp'] as num).toInt(), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$$LoadableSaveContextImplToJson( | ||||
|   | ||||
| @@ -0,0 +1,48 @@ | ||||
| import 'dart:async'; | ||||
|  | ||||
| import 'package:bloc/bloc.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| import 'bloc_module.dart'; | ||||
|  | ||||
| class SwappingBloc<TBloc> { | ||||
|   final TBloc initialBloc; | ||||
|   final StreamController<TBloc> updater = StreamController<TBloc>(); | ||||
|  | ||||
|   SwappingBloc(this.initialBloc); | ||||
|  | ||||
|   void swap(TBloc bloc) { | ||||
|     updater.add(bloc); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class SwappingBlocModule<TBloc extends StateStreamableSource<TState>, TState> extends StatefulWidget { | ||||
|   final SwappingBloc<TBloc> bloc; | ||||
|   final Widget Function(BuildContext context, TBloc bloc, TState state) child; | ||||
|   const SwappingBlocModule({super.key, required this.bloc, required this.child}); | ||||
|  | ||||
|   @override | ||||
|   State<SwappingBlocModule<TBloc, TState>> createState() => _SwappingBlocModuleState<TBloc, TState>(); | ||||
| } | ||||
|  | ||||
| class _SwappingBlocModuleState<TBloc extends StateStreamableSource<TState>, TState> extends State<SwappingBlocModule<TBloc, TState>> { | ||||
|   late TBloc bloc; | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     bloc = widget.bloc.initialBloc; | ||||
|     widget.bloc.updater.stream.listen((event) { | ||||
|       setState(() { | ||||
|         bloc = event; | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) => BlocModule<TBloc, TState>( | ||||
|     autoRebuild: true, | ||||
|     create: (context) => bloc, | ||||
|     child: (context, bloc, state) => widget.child(context, bloc, state), | ||||
|   ); | ||||
| } | ||||
| @@ -8,6 +8,7 @@ import '../../../view/pages/more/roomplan/roomplan.dart'; | ||||
| import '../../../view/pages/talk/chatList.dart'; | ||||
| import '../../../view/pages/timetable/timetable.dart'; | ||||
| import '../../../widget/centeredLeading.dart'; | ||||
| import 'files/view/files_view.dart'; | ||||
| import 'gradeAverages/view/grade_averages_view.dart'; | ||||
| import 'holidays/view/holidays_view.dart'; | ||||
| import 'marianumMessage/view/marianum_message_list_view.dart'; | ||||
| @@ -23,6 +24,7 @@ class AppModule { | ||||
|     Modules.timetable: AppModule('Vertretung', Icons.calendar_month, Timetable.new), | ||||
|     Modules.talk: AppModule('Talk', Icons.chat, ChatList.new), | ||||
|     Modules.files: AppModule('Files', Icons.folder, Files.new), | ||||
|     Modules.blocFiles: AppModule('BlocFiles', Icons.folder, FilesView.new), | ||||
|     Modules.marianumMessage: AppModule('Marianum Message', Icons.newspaper, MarianumMessageListView.new), | ||||
|     Modules.roomPlan: AppModule('Raumplan', Icons.location_pin, Roomplan.new), | ||||
|     Modules.gradeAveragesCalculator: AppModule('Notendurschnittsrechner', Icons.calculate, GradeAveragesView.new), | ||||
| @@ -53,6 +55,7 @@ enum Modules { | ||||
|   timetable, | ||||
|   talk, | ||||
|   files, | ||||
|   blocFiles, | ||||
|   marianumMessage, | ||||
|   roomPlan, | ||||
|   gradeAveragesCalculator, | ||||
|   | ||||
							
								
								
									
										65
									
								
								lib/state/app/modules/files/bloc/files_bloc.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								lib/state/app/modules/files/bloc/files_bloc.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
|  | ||||
| import 'dart:developer'; | ||||
|  | ||||
| import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc.dart'; | ||||
| import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc_event.dart'; | ||||
| import '../repository/files_repository.dart'; | ||||
| import 'files_event.dart'; | ||||
| import 'files_state.dart'; | ||||
|  | ||||
| class FilesBloc extends LoadableHydratedBloc<FilesEvent, FilesState, FilesRepository> { | ||||
|   static const String basePath = '/'; | ||||
|  | ||||
|   FilesBloc() { | ||||
|     add(Emit((state) => state.copyWith(currentFolder: basePath))); | ||||
|     on<EnterFolder>((event, emit) { | ||||
|       add(Emit((state) { | ||||
|         log('setFolder'); | ||||
|         return state.copyWith(currentFolder: event.absolutePath); | ||||
|       }, fetch: true)); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   List<File>? getVisibleFiles() => innerState?.files[innerState?.currentFolder]; | ||||
|   String getCurrentFolder() => innerState?.currentFolder ?? basePath; | ||||
|   String getCurrentFolderName() { | ||||
|     var folder = innerState?.currentFolder.split('/').reversed.elementAt(1); | ||||
|     return folder!.isEmpty ? 'Dateien' : folder; | ||||
|   } | ||||
|   bool canGoBack() => innerState?.currentFolder != basePath; | ||||
|   String goBackLocation() { | ||||
|     var pathSegments = innerState?.currentFolder.split(basePath) ?? []; | ||||
|     if (pathSegments.isNotEmpty) { | ||||
|       pathSegments.removeLast(); | ||||
|       pathSegments.removeLast(); | ||||
|     } | ||||
|     return pathSegments.join(basePath) + basePath; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   FilesState fromNothing() => const FilesState(currentFolder: basePath, files: {}); | ||||
|  | ||||
|   @override | ||||
|   FilesState fromStorage(Map<String, dynamic> json) => FilesState.fromJson(json); | ||||
|  | ||||
|   @override | ||||
|   Future<void> gatherData() async { | ||||
|     var fetchFolder = getCurrentFolder(); | ||||
|     log(fetchFolder); | ||||
|     var files = await repo.getFileList(fetchFolder); | ||||
|     var newFileMap = Map.of(innerState?.files ?? <String, List<File>>{}); | ||||
|     newFileMap[fetchFolder] = files; | ||||
|     if(fetchFolder != getCurrentFolder()) { | ||||
|       log('Fetch aborted due to folder change (expected "$fetchFolder" got "${getCurrentFolder()}")'); | ||||
|       return; | ||||
|     } | ||||
|     add(DataGathered((state) => state.copyWith(files: newFileMap))); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   FilesRepository repository() => FilesRepository(); | ||||
|  | ||||
|   @override | ||||
|   Map<String, dynamic>? toStorage(FilesState state) => state.toJson(); | ||||
|  | ||||
| } | ||||
							
								
								
									
										10
									
								
								lib/state/app/modules/files/bloc/files_event.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								lib/state/app/modules/files/bloc/files_event.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
|  | ||||
| import '../../../infrastructure/utilityWidgets/loadableHydratedBloc/loadable_hydrated_bloc_event.dart'; | ||||
| import 'files_state.dart'; | ||||
|  | ||||
| sealed class FilesEvent extends LoadableHydratedBlocEvent<FilesState> {} | ||||
| class EnterFolder extends FilesEvent { | ||||
|   String absolutePath; | ||||
|   EnterFolder(this.absolutePath); | ||||
| } | ||||
|  | ||||
							
								
								
									
										29
									
								
								lib/state/app/modules/files/bloc/files_state.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								lib/state/app/modules/files/bloc/files_state.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| import 'package:freezed_annotation/freezed_annotation.dart'; | ||||
|  | ||||
| part 'files_state.freezed.dart'; | ||||
| part 'files_state.g.dart'; | ||||
|  | ||||
| @freezed | ||||
| class FilesState with _$FilesState { | ||||
|   const factory FilesState({ | ||||
|     required String currentFolder, | ||||
|     required Map<String, List<File>> files, | ||||
|   }) = _FilesState; | ||||
|  | ||||
|   factory FilesState.fromJson(Map<String, Object?> json) => _$FilesStateFromJson(json); | ||||
| } | ||||
|  | ||||
| @freezed | ||||
| class File with _$File { | ||||
|   const factory File({ | ||||
|     required String path, | ||||
|     required bool isFolder, | ||||
|     required String name, | ||||
|     required DateTime? createdAt, | ||||
|     required DateTime? updatedAt, | ||||
|     required int? size, | ||||
|     required String? mimeType, | ||||
|   }) = _File; | ||||
|  | ||||
|   factory File.fromJson(Map<String, Object?> json) => _$FileFromJson(json); | ||||
| } | ||||
							
								
								
									
										439
									
								
								lib/state/app/modules/files/bloc/files_state.freezed.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										439
									
								
								lib/state/app/modules/files/bloc/files_state.freezed.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,439 @@ | ||||
| // 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 'files_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'); | ||||
|  | ||||
| FilesState _$FilesStateFromJson(Map<String, dynamic> json) { | ||||
|   return _FilesState.fromJson(json); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$FilesState { | ||||
|   String get currentFolder => throw _privateConstructorUsedError; | ||||
|   Map<String, List<File>> get files => throw _privateConstructorUsedError; | ||||
|  | ||||
|   Map<String, dynamic> toJson() => throw _privateConstructorUsedError; | ||||
|   @JsonKey(ignore: true) | ||||
|   $FilesStateCopyWith<FilesState> get copyWith => | ||||
|       throw _privateConstructorUsedError; | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract class $FilesStateCopyWith<$Res> { | ||||
|   factory $FilesStateCopyWith( | ||||
|           FilesState value, $Res Function(FilesState) then) = | ||||
|       _$FilesStateCopyWithImpl<$Res, FilesState>; | ||||
|   @useResult | ||||
|   $Res call({String currentFolder, Map<String, List<File>> files}); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| class _$FilesStateCopyWithImpl<$Res, $Val extends FilesState> | ||||
|     implements $FilesStateCopyWith<$Res> { | ||||
|   _$FilesStateCopyWithImpl(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? currentFolder = null, | ||||
|     Object? files = null, | ||||
|   }) { | ||||
|     return _then(_value.copyWith( | ||||
|       currentFolder: null == currentFolder | ||||
|           ? _value.currentFolder | ||||
|           : currentFolder // ignore: cast_nullable_to_non_nullable | ||||
|               as String, | ||||
|       files: null == files | ||||
|           ? _value.files | ||||
|           : files // ignore: cast_nullable_to_non_nullable | ||||
|               as Map<String, List<File>>, | ||||
|     ) as $Val); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract class _$$FilesStateImplCopyWith<$Res> | ||||
|     implements $FilesStateCopyWith<$Res> { | ||||
|   factory _$$FilesStateImplCopyWith( | ||||
|           _$FilesStateImpl value, $Res Function(_$FilesStateImpl) then) = | ||||
|       __$$FilesStateImplCopyWithImpl<$Res>; | ||||
|   @override | ||||
|   @useResult | ||||
|   $Res call({String currentFolder, Map<String, List<File>> files}); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| class __$$FilesStateImplCopyWithImpl<$Res> | ||||
|     extends _$FilesStateCopyWithImpl<$Res, _$FilesStateImpl> | ||||
|     implements _$$FilesStateImplCopyWith<$Res> { | ||||
|   __$$FilesStateImplCopyWithImpl( | ||||
|       _$FilesStateImpl _value, $Res Function(_$FilesStateImpl) _then) | ||||
|       : super(_value, _then); | ||||
|  | ||||
|   @pragma('vm:prefer-inline') | ||||
|   @override | ||||
|   $Res call({ | ||||
|     Object? currentFolder = null, | ||||
|     Object? files = null, | ||||
|   }) { | ||||
|     return _then(_$FilesStateImpl( | ||||
|       currentFolder: null == currentFolder | ||||
|           ? _value.currentFolder | ||||
|           : currentFolder // ignore: cast_nullable_to_non_nullable | ||||
|               as String, | ||||
|       files: null == files | ||||
|           ? _value._files | ||||
|           : files // ignore: cast_nullable_to_non_nullable | ||||
|               as Map<String, List<File>>, | ||||
|     )); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
| class _$FilesStateImpl implements _FilesState { | ||||
|   const _$FilesStateImpl( | ||||
|       {required this.currentFolder, | ||||
|       required final Map<String, List<File>> files}) | ||||
|       : _files = files; | ||||
|  | ||||
|   factory _$FilesStateImpl.fromJson(Map<String, dynamic> json) => | ||||
|       _$$FilesStateImplFromJson(json); | ||||
|  | ||||
|   @override | ||||
|   final String currentFolder; | ||||
|   final Map<String, List<File>> _files; | ||||
|   @override | ||||
|   Map<String, List<File>> get files { | ||||
|     if (_files is EqualUnmodifiableMapView) return _files; | ||||
|     // ignore: implicit_dynamic_type | ||||
|     return EqualUnmodifiableMapView(_files); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   String toString() { | ||||
|     return 'FilesState(currentFolder: $currentFolder, files: $files)'; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return identical(this, other) || | ||||
|         (other.runtimeType == runtimeType && | ||||
|             other is _$FilesStateImpl && | ||||
|             (identical(other.currentFolder, currentFolder) || | ||||
|                 other.currentFolder == currentFolder) && | ||||
|             const DeepCollectionEquality().equals(other._files, _files)); | ||||
|   } | ||||
|  | ||||
|   @JsonKey(ignore: true) | ||||
|   @override | ||||
|   int get hashCode => Object.hash( | ||||
|       runtimeType, currentFolder, const DeepCollectionEquality().hash(_files)); | ||||
|  | ||||
|   @JsonKey(ignore: true) | ||||
|   @override | ||||
|   @pragma('vm:prefer-inline') | ||||
|   _$$FilesStateImplCopyWith<_$FilesStateImpl> get copyWith => | ||||
|       __$$FilesStateImplCopyWithImpl<_$FilesStateImpl>(this, _$identity); | ||||
|  | ||||
|   @override | ||||
|   Map<String, dynamic> toJson() { | ||||
|     return _$$FilesStateImplToJson( | ||||
|       this, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| abstract class _FilesState implements FilesState { | ||||
|   const factory _FilesState( | ||||
|       {required final String currentFolder, | ||||
|       required final Map<String, List<File>> files}) = _$FilesStateImpl; | ||||
|  | ||||
|   factory _FilesState.fromJson(Map<String, dynamic> json) = | ||||
|       _$FilesStateImpl.fromJson; | ||||
|  | ||||
|   @override | ||||
|   String get currentFolder; | ||||
|   @override | ||||
|   Map<String, List<File>> get files; | ||||
|   @override | ||||
|   @JsonKey(ignore: true) | ||||
|   _$$FilesStateImplCopyWith<_$FilesStateImpl> get copyWith => | ||||
|       throw _privateConstructorUsedError; | ||||
| } | ||||
|  | ||||
| File _$FileFromJson(Map<String, dynamic> json) { | ||||
|   return _File.fromJson(json); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| mixin _$File { | ||||
|   String get path => throw _privateConstructorUsedError; | ||||
|   bool get isFolder => throw _privateConstructorUsedError; | ||||
|   String get name => throw _privateConstructorUsedError; | ||||
|   DateTime? get createdAt => throw _privateConstructorUsedError; | ||||
|   DateTime? get updatedAt => throw _privateConstructorUsedError; | ||||
|   int? get size => throw _privateConstructorUsedError; | ||||
|   String? get mimeType => throw _privateConstructorUsedError; | ||||
|  | ||||
|   Map<String, dynamic> toJson() => throw _privateConstructorUsedError; | ||||
|   @JsonKey(ignore: true) | ||||
|   $FileCopyWith<File> get copyWith => throw _privateConstructorUsedError; | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract class $FileCopyWith<$Res> { | ||||
|   factory $FileCopyWith(File value, $Res Function(File) then) = | ||||
|       _$FileCopyWithImpl<$Res, File>; | ||||
|   @useResult | ||||
|   $Res call( | ||||
|       {String path, | ||||
|       bool isFolder, | ||||
|       String name, | ||||
|       DateTime? createdAt, | ||||
|       DateTime? updatedAt, | ||||
|       int? size, | ||||
|       String? mimeType}); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| class _$FileCopyWithImpl<$Res, $Val extends File> | ||||
|     implements $FileCopyWith<$Res> { | ||||
|   _$FileCopyWithImpl(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? path = null, | ||||
|     Object? isFolder = null, | ||||
|     Object? name = null, | ||||
|     Object? createdAt = freezed, | ||||
|     Object? updatedAt = freezed, | ||||
|     Object? size = freezed, | ||||
|     Object? mimeType = freezed, | ||||
|   }) { | ||||
|     return _then(_value.copyWith( | ||||
|       path: null == path | ||||
|           ? _value.path | ||||
|           : path // ignore: cast_nullable_to_non_nullable | ||||
|               as String, | ||||
|       isFolder: null == isFolder | ||||
|           ? _value.isFolder | ||||
|           : isFolder // ignore: cast_nullable_to_non_nullable | ||||
|               as bool, | ||||
|       name: null == name | ||||
|           ? _value.name | ||||
|           : name // ignore: cast_nullable_to_non_nullable | ||||
|               as String, | ||||
|       createdAt: freezed == createdAt | ||||
|           ? _value.createdAt | ||||
|           : createdAt // ignore: cast_nullable_to_non_nullable | ||||
|               as DateTime?, | ||||
|       updatedAt: freezed == updatedAt | ||||
|           ? _value.updatedAt | ||||
|           : updatedAt // ignore: cast_nullable_to_non_nullable | ||||
|               as DateTime?, | ||||
|       size: freezed == size | ||||
|           ? _value.size | ||||
|           : size // ignore: cast_nullable_to_non_nullable | ||||
|               as int?, | ||||
|       mimeType: freezed == mimeType | ||||
|           ? _value.mimeType | ||||
|           : mimeType // ignore: cast_nullable_to_non_nullable | ||||
|               as String?, | ||||
|     ) as $Val); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| abstract class _$$FileImplCopyWith<$Res> implements $FileCopyWith<$Res> { | ||||
|   factory _$$FileImplCopyWith( | ||||
|           _$FileImpl value, $Res Function(_$FileImpl) then) = | ||||
|       __$$FileImplCopyWithImpl<$Res>; | ||||
|   @override | ||||
|   @useResult | ||||
|   $Res call( | ||||
|       {String path, | ||||
|       bool isFolder, | ||||
|       String name, | ||||
|       DateTime? createdAt, | ||||
|       DateTime? updatedAt, | ||||
|       int? size, | ||||
|       String? mimeType}); | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| class __$$FileImplCopyWithImpl<$Res> | ||||
|     extends _$FileCopyWithImpl<$Res, _$FileImpl> | ||||
|     implements _$$FileImplCopyWith<$Res> { | ||||
|   __$$FileImplCopyWithImpl(_$FileImpl _value, $Res Function(_$FileImpl) _then) | ||||
|       : super(_value, _then); | ||||
|  | ||||
|   @pragma('vm:prefer-inline') | ||||
|   @override | ||||
|   $Res call({ | ||||
|     Object? path = null, | ||||
|     Object? isFolder = null, | ||||
|     Object? name = null, | ||||
|     Object? createdAt = freezed, | ||||
|     Object? updatedAt = freezed, | ||||
|     Object? size = freezed, | ||||
|     Object? mimeType = freezed, | ||||
|   }) { | ||||
|     return _then(_$FileImpl( | ||||
|       path: null == path | ||||
|           ? _value.path | ||||
|           : path // ignore: cast_nullable_to_non_nullable | ||||
|               as String, | ||||
|       isFolder: null == isFolder | ||||
|           ? _value.isFolder | ||||
|           : isFolder // ignore: cast_nullable_to_non_nullable | ||||
|               as bool, | ||||
|       name: null == name | ||||
|           ? _value.name | ||||
|           : name // ignore: cast_nullable_to_non_nullable | ||||
|               as String, | ||||
|       createdAt: freezed == createdAt | ||||
|           ? _value.createdAt | ||||
|           : createdAt // ignore: cast_nullable_to_non_nullable | ||||
|               as DateTime?, | ||||
|       updatedAt: freezed == updatedAt | ||||
|           ? _value.updatedAt | ||||
|           : updatedAt // ignore: cast_nullable_to_non_nullable | ||||
|               as DateTime?, | ||||
|       size: freezed == size | ||||
|           ? _value.size | ||||
|           : size // ignore: cast_nullable_to_non_nullable | ||||
|               as int?, | ||||
|       mimeType: freezed == mimeType | ||||
|           ? _value.mimeType | ||||
|           : mimeType // ignore: cast_nullable_to_non_nullable | ||||
|               as String?, | ||||
|     )); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// @nodoc | ||||
| @JsonSerializable() | ||||
| class _$FileImpl implements _File { | ||||
|   const _$FileImpl( | ||||
|       {required this.path, | ||||
|       required this.isFolder, | ||||
|       required this.name, | ||||
|       required this.createdAt, | ||||
|       required this.updatedAt, | ||||
|       required this.size, | ||||
|       required this.mimeType}); | ||||
|  | ||||
|   factory _$FileImpl.fromJson(Map<String, dynamic> json) => | ||||
|       _$$FileImplFromJson(json); | ||||
|  | ||||
|   @override | ||||
|   final String path; | ||||
|   @override | ||||
|   final bool isFolder; | ||||
|   @override | ||||
|   final String name; | ||||
|   @override | ||||
|   final DateTime? createdAt; | ||||
|   @override | ||||
|   final DateTime? updatedAt; | ||||
|   @override | ||||
|   final int? size; | ||||
|   @override | ||||
|   final String? mimeType; | ||||
|  | ||||
|   @override | ||||
|   String toString() { | ||||
|     return 'File(path: $path, isFolder: $isFolder, name: $name, createdAt: $createdAt, updatedAt: $updatedAt, size: $size, mimeType: $mimeType)'; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return identical(this, other) || | ||||
|         (other.runtimeType == runtimeType && | ||||
|             other is _$FileImpl && | ||||
|             (identical(other.path, path) || other.path == path) && | ||||
|             (identical(other.isFolder, isFolder) || | ||||
|                 other.isFolder == isFolder) && | ||||
|             (identical(other.name, name) || other.name == name) && | ||||
|             (identical(other.createdAt, createdAt) || | ||||
|                 other.createdAt == createdAt) && | ||||
|             (identical(other.updatedAt, updatedAt) || | ||||
|                 other.updatedAt == updatedAt) && | ||||
|             (identical(other.size, size) || other.size == size) && | ||||
|             (identical(other.mimeType, mimeType) || | ||||
|                 other.mimeType == mimeType)); | ||||
|   } | ||||
|  | ||||
|   @JsonKey(ignore: true) | ||||
|   @override | ||||
|   int get hashCode => Object.hash( | ||||
|       runtimeType, path, isFolder, name, createdAt, updatedAt, size, mimeType); | ||||
|  | ||||
|   @JsonKey(ignore: true) | ||||
|   @override | ||||
|   @pragma('vm:prefer-inline') | ||||
|   _$$FileImplCopyWith<_$FileImpl> get copyWith => | ||||
|       __$$FileImplCopyWithImpl<_$FileImpl>(this, _$identity); | ||||
|  | ||||
|   @override | ||||
|   Map<String, dynamic> toJson() { | ||||
|     return _$$FileImplToJson( | ||||
|       this, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| abstract class _File implements File { | ||||
|   const factory _File( | ||||
|       {required final String path, | ||||
|       required final bool isFolder, | ||||
|       required final String name, | ||||
|       required final DateTime? createdAt, | ||||
|       required final DateTime? updatedAt, | ||||
|       required final int? size, | ||||
|       required final String? mimeType}) = _$FileImpl; | ||||
|  | ||||
|   factory _File.fromJson(Map<String, dynamic> json) = _$FileImpl.fromJson; | ||||
|  | ||||
|   @override | ||||
|   String get path; | ||||
|   @override | ||||
|   bool get isFolder; | ||||
|   @override | ||||
|   String get name; | ||||
|   @override | ||||
|   DateTime? get createdAt; | ||||
|   @override | ||||
|   DateTime? get updatedAt; | ||||
|   @override | ||||
|   int? get size; | ||||
|   @override | ||||
|   String? get mimeType; | ||||
|   @override | ||||
|   @JsonKey(ignore: true) | ||||
|   _$$FileImplCopyWith<_$FileImpl> get copyWith => | ||||
|       throw _privateConstructorUsedError; | ||||
| } | ||||
							
								
								
									
										50
									
								
								lib/state/app/modules/files/bloc/files_state.g.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/state/app/modules/files/bloc/files_state.g.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| // GENERATED CODE - DO NOT MODIFY BY HAND | ||||
|  | ||||
| part of 'files_state.dart'; | ||||
|  | ||||
| // ************************************************************************** | ||||
| // JsonSerializableGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| _$FilesStateImpl _$$FilesStateImplFromJson(Map<String, dynamic> json) => | ||||
|     _$FilesStateImpl( | ||||
|       currentFolder: json['currentFolder'] as String, | ||||
|       files: (json['files'] as Map<String, dynamic>).map( | ||||
|         (k, e) => MapEntry( | ||||
|             k, | ||||
|             (e as List<dynamic>) | ||||
|                 .map((e) => File.fromJson(e as Map<String, dynamic>)) | ||||
|                 .toList()), | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$$FilesStateImplToJson(_$FilesStateImpl instance) => | ||||
|     <String, dynamic>{ | ||||
|       'currentFolder': instance.currentFolder, | ||||
|       'files': instance.files, | ||||
|     }; | ||||
|  | ||||
| _$FileImpl _$$FileImplFromJson(Map<String, dynamic> json) => _$FileImpl( | ||||
|       path: json['path'] as String, | ||||
|       isFolder: json['isFolder'] as bool, | ||||
|       name: json['name'] as String, | ||||
|       createdAt: json['createdAt'] == null | ||||
|           ? null | ||||
|           : DateTime.parse(json['createdAt'] as String), | ||||
|       updatedAt: json['updatedAt'] == null | ||||
|           ? null | ||||
|           : DateTime.parse(json['updatedAt'] as String), | ||||
|       size: (json['size'] as num?)?.toInt(), | ||||
|       mimeType: json['mimeType'] as String?, | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$$FileImplToJson(_$FileImpl instance) => | ||||
|     <String, dynamic>{ | ||||
|       'path': instance.path, | ||||
|       'isFolder': instance.isFolder, | ||||
|       'name': instance.name, | ||||
|       'createdAt': instance.createdAt?.toIso8601String(), | ||||
|       'updatedAt': instance.updatedAt?.toIso8601String(), | ||||
|       'size': instance.size, | ||||
|       'mimeType': instance.mimeType, | ||||
|     }; | ||||
							
								
								
									
										31
									
								
								lib/state/app/modules/files/repository/files_repository.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/state/app/modules/files/repository/files_repository.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
|  | ||||
| import 'package:nextcloud/nextcloud.dart'; | ||||
|  | ||||
| import '../../../../../api/marianumcloud/webdav/webdavApi.dart'; | ||||
| import '../../../infrastructure/repository/repository.dart'; | ||||
| import '../bloc/files_state.dart'; | ||||
|  | ||||
| class FilesRepository extends Repository<FilesState> { | ||||
|   Future<List<File>> getFileList(String path) async { | ||||
|     var webdav = await WebdavApi.webdav; | ||||
|     var response = await webdav.propfind(PathUri.parse(path)); // TODO move to custom data loader | ||||
|     var davFiles = response.toWebDavFiles(); | ||||
|  | ||||
|     davFiles.removeWhere((file) { | ||||
|       var filePath = file.path.path; | ||||
|       return filePath.isEmpty || filePath == path; | ||||
|     }); | ||||
|  | ||||
|     var files = davFiles.map((davFile) => File( | ||||
|       path: davFile.path.path, | ||||
|       isFolder: davFile.isDirectory, | ||||
|       name: davFile.name, | ||||
|       createdAt: davFile.createdDate, | ||||
|       updatedAt: davFile.lastModified, | ||||
|       size: davFile.size, | ||||
|       mimeType: davFile.mimeType | ||||
|     )); | ||||
|  | ||||
|     return files.toList(); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										67
									
								
								lib/state/app/modules/files/view/files_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								lib/state/app/modules/files/view/files_view.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| import 'dart:developer'; | ||||
|  | ||||
| import 'package:filesize/filesize.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:jiffy/jiffy.dart'; | ||||
|  | ||||
| import '../../../../../widget/centeredLeading.dart'; | ||||
| import '../../../../../widget/list_view_util.dart'; | ||||
| import '../../../infrastructure/loadableState/loadable_state.dart'; | ||||
| import '../../../infrastructure/loadableState/view/loadable_state_consumer.dart'; | ||||
| import '../../../infrastructure/utilityWidgets/bloc_module.dart'; | ||||
| import '../bloc/files_bloc.dart'; | ||||
| import '../bloc/files_event.dart'; | ||||
| import '../bloc/files_state.dart'; | ||||
|  | ||||
| class FilesView extends StatelessWidget { | ||||
|   const FilesView({super.key}); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) => BlocModule<FilesBloc, LoadableState<FilesState>>( | ||||
|     create: (context) => FilesBloc(), | ||||
|     autoRebuild: true, | ||||
|     child: (context, bloc, state) { | ||||
|       var goBackButton = !bloc.canGoBack() ? null : IconButton( | ||||
|         icon: const Icon(Icons.arrow_back), | ||||
|         onPressed: () { | ||||
|           bloc.add(EnterFolder(bloc.goBackLocation())); | ||||
|         }, | ||||
|       ); | ||||
|       return PopScope( | ||||
|         canPop: false, | ||||
|         onPopInvoked: (didPop) => bloc.add(EnterFolder(bloc.goBackLocation())), | ||||
|         child: Scaffold( | ||||
|             appBar: AppBar( | ||||
|               leading: goBackButton, | ||||
|               title: Text(bloc.getCurrentFolderName()), | ||||
|  | ||||
|  | ||||
|               actions: [ | ||||
|                 IconButton(onPressed: () { | ||||
|                   log(bloc.innerState?.toJson().toString() ?? 'leer'); | ||||
|                 }, icon: const Icon(Icons.bug_report)), | ||||
|                 IconButton(onPressed: () { | ||||
|                   bloc.add(EnterFolder('/')); | ||||
|                 }, icon: const Icon(Icons.home)), | ||||
|               ], | ||||
|             ), | ||||
|             body: LoadableStateConsumer<FilesBloc, FilesState>( | ||||
|                 child: (state, loading) => ListViewUtil.fromList<File>(bloc.getVisibleFiles(), (file) => ListTile( | ||||
|                   leading: CenteredLeading(Icon(file.isFolder ? Icons.folder : Icons.description_outlined)), | ||||
|                   title: Text(file.name), | ||||
|                   subtitle: file.isFolder | ||||
|                       ? Text('geändert ${Jiffy.parseFromDateTime(file.updatedAt ?? DateTime.now()).fromNow()}') | ||||
|                       : Text('${filesize(file.size)}, ${Jiffy.parseFromDateTime(file.updatedAt ?? DateTime.now()).fromNow()}'), | ||||
|                   trailing: Icon(file.isFolder ? Icons.arrow_right : null), | ||||
|                   onTap: () { | ||||
|                     log(file.path); | ||||
|                     if(!file.isFolder) return; | ||||
|                     bloc.add(EnterFolder(file.path)); | ||||
|                   }, | ||||
|                 )) | ||||
|             ) | ||||
|         ), | ||||
|       ); | ||||
|     }, | ||||
|   ); | ||||
| } | ||||
| @@ -11,7 +11,9 @@ _$GradeAveragesStateImpl _$$GradeAveragesStateImplFromJson( | ||||
|     _$GradeAveragesStateImpl( | ||||
|       gradingSystem: $enumDecode( | ||||
|           _$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 num).toInt()) | ||||
|           .toList(), | ||||
|     ); | ||||
|  | ||||
| Map<String, dynamic> _$$GradeAveragesStateImplToJson( | ||||
|   | ||||
| @@ -26,7 +26,7 @@ _$HolidayImpl _$$HolidayImplFromJson(Map<String, dynamic> json) => | ||||
|     _$HolidayImpl( | ||||
|       start: json['start'] as String, | ||||
|       end: json['end'] as String, | ||||
|       year: json['year'] as int, | ||||
|       year: (json['year'] as num).toInt(), | ||||
|       stateCode: json['stateCode'] as String, | ||||
|       name: json['name'] as String, | ||||
|       slug: json['slug'] as String, | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import 'package:dio/dio.dart'; | ||||
|  | ||||
| import '../../../basis/dataloader/holiday_data_loader.dart'; | ||||
| import '../../../infrastructure/dataLoader/data_loader.dart'; | ||||
| import '../../../infrastructure/dataLoader/http_data_loader.dart'; | ||||
| import '../bloc/holidays_state.dart'; | ||||
|  | ||||
| class HolidaysGetHolidays extends HolidayDataLoader<List<Holiday>> { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import 'package:dio/dio.dart'; | ||||
|  | ||||
| import '../../../infrastructure/dataLoader/data_loader.dart'; | ||||
| import '../../../infrastructure/dataLoader/http_data_loader.dart'; | ||||
| import '../../../basis/dataloader/mhsl_data_loader.dart'; | ||||
| import '../bloc/marianum_message_state.dart'; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user