refactored data providers with centralized cache resolution, unified UI using custom dialogs and bottom sheets, and enhanced network error handling for Dio and TLS errors

This commit is contained in:
2026-05-08 20:01:45 +02:00
parent c62a14645a
commit 9e139b5704
37 changed files with 595 additions and 753 deletions
@@ -10,6 +10,7 @@ import '../../../../../api/mhsl/custom_timetable_event/remove/remove_custom_time
import '../../../../../api/mhsl/custom_timetable_event/remove/remove_custom_timetable_event_params.dart';
import '../../../../../api/mhsl/custom_timetable_event/update/update_custom_timetable_event.dart';
import '../../../../../api/mhsl/custom_timetable_event/update/update_custom_timetable_event_params.dart';
import '../../../../../api/request_cache.dart';
import '../../../../../api/webuntis/queries/get_holidays/get_holidays_cache.dart';
import '../../../../../api/webuntis/queries/get_holidays/get_holidays_response.dart';
import '../../../../../api/webuntis/queries/get_rooms/get_rooms_cache.dart';
@@ -30,112 +31,84 @@ class TimetableDataProvider {
DateTime endDate, {
void Function(Object)? onError,
bool renew = false,
}) async {
GetTimetableResponse? latest;
Object? capturedError;
final cache = GetTimetableCache(
startdate: int.parse(_dateFormat.format(startDate)),
enddate: int.parse(_dateFormat.format(endDate)),
renew: renew,
onUpdate: (data) => latest = data,
onError: (e) {
capturedError = e;
onError?.call(e);
},
);
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getWeek');
}
}) =>
resolveFromCache<GetTimetableResponse>(
(onUpdate, onError) => GetTimetableCache(
startdate: int.parse(_dateFormat.format(startDate)),
enddate: int.parse(_dateFormat.format(endDate)),
renew: renew,
onUpdate: onUpdate,
onError: onError,
),
onError: onError,
operationName: 'getWeek',
);
Future<GetRoomsResponse> getRooms({
void Function(Object)? onError,
bool renew = false,
}) async {
GetRoomsResponse? latest;
Object? capturedError;
final cache = GetRoomsCache(
renew: renew,
onUpdate: (data) => latest = data,
onError: (e) {
capturedError = e;
onError?.call(e);
},
);
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getRooms');
}
}) =>
resolveFromCache<GetRoomsResponse>(
(onUpdate, onError) => GetRoomsCache(
renew: renew,
onUpdate: onUpdate,
onError: onError,
),
onError: onError,
operationName: 'getRooms',
);
Future<GetSubjectsResponse> getSubjects({
void Function(Object)? onError,
bool renew = false,
}) async {
GetSubjectsResponse? latest;
Object? capturedError;
final cache = GetSubjectsCache(
renew: renew,
onUpdate: (data) => latest = data,
onError: (e) {
capturedError = e;
onError?.call(e);
},
);
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getSubjects');
}
}) =>
resolveFromCache<GetSubjectsResponse>(
(onUpdate, onError) => GetSubjectsCache(
renew: renew,
onUpdate: onUpdate,
onError: onError,
),
onError: onError,
operationName: 'getSubjects',
);
Future<GetHolidaysResponse> getSchoolHolidays({
void Function(Object)? onError,
bool renew = false,
}) async {
GetHolidaysResponse? latest;
Object? capturedError;
final cache = GetHolidaysCache(
renew: renew,
onUpdate: (data) => latest = data,
onError: (e) {
capturedError = e;
onError?.call(e);
},
);
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getSchoolHolidays');
}
}) =>
resolveFromCache<GetHolidaysResponse>(
(onUpdate, onError) => GetHolidaysCache(
renew: renew,
onUpdate: onUpdate,
onError: onError,
),
onError: onError,
operationName: 'getSchoolHolidays',
);
Future<GetTimegridUnitsResponse> getTimegrid({bool renew = false}) async {
GetTimegridUnitsResponse? latest;
Object? capturedError;
final cache = GetTimegridUnitsCache(
renew: renew,
onUpdate: (data) => latest = data,
);
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getTimegrid');
}
Future<GetTimegridUnitsResponse> getTimegrid({bool renew = false}) =>
resolveFromCache<GetTimegridUnitsResponse>(
(onUpdate, _) => GetTimegridUnitsCache(
renew: renew,
onUpdate: onUpdate,
),
operationName: 'getTimegrid',
);
Future<GetCustomTimetableEventResponse> getCustomEvents({
bool renew = false,
void Function(Object)? onError,
}) async {
GetCustomTimetableEventResponse? latest;
Object? capturedError;
final cache = GetCustomTimetableEventCache(
GetCustomTimetableEventParams(AccountData().getUserSecret()),
renew: renew,
onUpdate: (data) => latest = data,
onError: (e) {
capturedError = e;
onError?.call(e);
},
);
await cache.ready;
if (latest != null) return latest!;
throw capturedError ?? Exception('No data and no error from getCustomEvents');
}
}) =>
resolveFromCache<GetCustomTimetableEventResponse>(
(onUpdate, onError) => GetCustomTimetableEventCache(
GetCustomTimetableEventParams(AccountData().getUserSecret()),
renew: renew,
onUpdate: onUpdate,
onError: onError,
),
onError: onError,
operationName: 'getCustomEvents',
);
Future<void> addCustomEvent(CustomTimetableEvent event) =>
AddCustomTimetableEvent(AddCustomTimetableEventParams(AccountData().getUserSecret(), event)).run();