From 0a2ff5c3fb5e1262cce97509e2fe89ad2b2e04d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sun, 12 Jul 2026 23:24:21 +0200 Subject: [PATCH] add MarianumConnectQuery base and adopt it in list queries --- .../marianumconnect_query.dart | 29 +++++++++++++++ .../queries/get_holidays/get_holidays.dart | 30 +++++---------- .../timetable_get_classes.dart | 34 ++++++----------- .../timetable_get_holidays.dart | 34 ++++++----------- .../timetable_get_rooms.dart | 32 +++++----------- .../timetable_get_students.dart | 34 ++++++----------- .../timetable_get_subjects.dart | 34 ++++++----------- .../timetable_get_teachers.dart | 37 ++++++------------- .../timetable_get_timegrid.dart | 34 ++++++----------- .../queries/user_search/user_search.dart | 36 +++++++----------- 10 files changed, 133 insertions(+), 201 deletions(-) create mode 100644 lib/api/marianumconnect/marianumconnect_query.dart diff --git a/lib/api/marianumconnect/marianumconnect_query.dart b/lib/api/marianumconnect/marianumconnect_query.dart new file mode 100644 index 0000000..9de04f8 --- /dev/null +++ b/lib/api/marianumconnect/marianumconnect_query.dart @@ -0,0 +1,29 @@ +import 'package:dio/dio.dart'; + +import 'errors/marianumconnect_error.dart'; +import 'marianumconnect_api.dart'; +import 'marianumconnect_endpoint.dart'; + +/// Shared base for MarianumConnect API queries. Owns the [dio] client (the +/// shared authenticated singleton by default) and routes calls through [guard] +/// so every query maps a DioException to the app's typed AppExceptions the same +/// way instead of repeating the try/catch. Subclasses with bespoke error or +/// lifecycle handling (own dio, silent failure, custom status mapping) may skip +/// [guard] and still reuse [dio]/[endpoint]. +abstract class MarianumConnectQuery { + final Dio dio; + + MarianumConnectQuery({Dio? dio}) : dio = dio ?? MarianumConnectApi.dio(); + + /// Resolves [path] against the active mobile-API base URL. + String endpoint(String path) => MarianumConnectEndpoint.resolve(path); + + /// Runs [body], converting any DioException into the matching AppException. + Future guard(Future Function() body) async { + try { + return await body(); + } on DioException catch (e) { + throw mapMarianumConnectError(e); + } + } +} diff --git a/lib/api/marianumconnect/queries/get_holidays/get_holidays.dart b/lib/api/marianumconnect/queries/get_holidays/get_holidays.dart index f896f22..51896dd 100644 --- a/lib/api/marianumconnect/queries/get_holidays/get_holidays.dart +++ b/lib/api/marianumconnect/queries/get_holidays/get_holidays.dart @@ -1,25 +1,13 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import '../../models/mc_holiday.dart'; -class GetHolidays { - final Dio _dio; +class GetHolidays extends MarianumConnectQuery { + GetHolidays({super.dio}); - GetHolidays({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future> run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('holidays'), - ); - return response.data! - .map((e) => McHoliday.fromJson(e as Map)) - .toList(); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future> run() => guard(() async { + final response = await dio.get>(endpoint('holidays')); + return response.data! + .map((e) => McHoliday.fromJson(e as Map)) + .toList(); + }); } diff --git a/lib/api/marianumconnect/queries/timetable_get_classes/timetable_get_classes.dart b/lib/api/marianumconnect/queries/timetable_get_classes/timetable_get_classes.dart index e067779..0528772 100644 --- a/lib/api/marianumconnect/queries/timetable_get_classes/timetable_get_classes.dart +++ b/lib/api/marianumconnect/queries/timetable_get_classes/timetable_get_classes.dart @@ -1,26 +1,16 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'timetable_get_classes_response.dart'; -class TimetableGetClasses { - final Dio _dio; +class TimetableGetClasses extends MarianumConnectQuery { + TimetableGetClasses({super.dio}); - TimetableGetClasses({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('timetable/elements/classes'), - ); - final list = response.data! - .map((e) => McTimetableClass.fromJson(e as Map)) - .toList(); - return TimetableGetClassesResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run() => guard(() async { + final response = await dio.get>( + endpoint('timetable/elements/classes'), + ); + final list = response.data! + .map((e) => McTimetableClass.fromJson(e as Map)) + .toList(); + return TimetableGetClassesResponse(result: list); + }); } diff --git a/lib/api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays.dart b/lib/api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays.dart index d120820..5cd1892 100644 --- a/lib/api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays.dart +++ b/lib/api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays.dart @@ -1,26 +1,16 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'timetable_get_holidays_response.dart'; -class TimetableGetHolidays { - final Dio _dio; +class TimetableGetHolidays extends MarianumConnectQuery { + TimetableGetHolidays({super.dio}); - TimetableGetHolidays({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('timetable/holidays'), - ); - final list = response.data! - .map((e) => McHoliday.fromJson(e as Map)) - .toList(); - return TimetableGetHolidaysResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run() => guard(() async { + final response = await dio.get>( + endpoint('timetable/holidays'), + ); + final list = response.data! + .map((e) => McHoliday.fromJson(e as Map)) + .toList(); + return TimetableGetHolidaysResponse(result: list); + }); } diff --git a/lib/api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms.dart b/lib/api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms.dart index ff28f5c..ac52846 100644 --- a/lib/api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms.dart +++ b/lib/api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms.dart @@ -1,26 +1,14 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'timetable_get_rooms_response.dart'; -class TimetableGetRooms { - final Dio _dio; +class TimetableGetRooms extends MarianumConnectQuery { + TimetableGetRooms({super.dio}); - TimetableGetRooms({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('timetable/rooms'), - ); - final list = response.data! - .map((e) => McRoom.fromJson(e as Map)) - .toList(); - return TimetableGetRoomsResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run() => guard(() async { + final response = await dio.get>(endpoint('timetable/rooms')); + final list = response.data! + .map((e) => McRoom.fromJson(e as Map)) + .toList(); + return TimetableGetRoomsResponse(result: list); + }); } diff --git a/lib/api/marianumconnect/queries/timetable_get_students/timetable_get_students.dart b/lib/api/marianumconnect/queries/timetable_get_students/timetable_get_students.dart index ab28251..c173627 100644 --- a/lib/api/marianumconnect/queries/timetable_get_students/timetable_get_students.dart +++ b/lib/api/marianumconnect/queries/timetable_get_students/timetable_get_students.dart @@ -1,26 +1,16 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'timetable_get_students_response.dart'; -class TimetableGetStudents { - final Dio _dio; +class TimetableGetStudents extends MarianumConnectQuery { + TimetableGetStudents({super.dio}); - TimetableGetStudents({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('timetable/elements/students'), - ); - final list = response.data! - .map((e) => McTimetableStudent.fromJson(e as Map)) - .toList(); - return TimetableGetStudentsResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run() => guard(() async { + final response = await dio.get>( + endpoint('timetable/elements/students'), + ); + final list = response.data! + .map((e) => McTimetableStudent.fromJson(e as Map)) + .toList(); + return TimetableGetStudentsResponse(result: list); + }); } diff --git a/lib/api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects.dart b/lib/api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects.dart index d126326..98967fe 100644 --- a/lib/api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects.dart +++ b/lib/api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects.dart @@ -1,26 +1,16 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'timetable_get_subjects_response.dart'; -class TimetableGetSubjects { - final Dio _dio; +class TimetableGetSubjects extends MarianumConnectQuery { + TimetableGetSubjects({super.dio}); - TimetableGetSubjects({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('timetable/subjects'), - ); - final list = response.data! - .map((e) => McSubject.fromJson(e as Map)) - .toList(); - return TimetableGetSubjectsResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run() => guard(() async { + final response = await dio.get>( + endpoint('timetable/subjects'), + ); + final list = response.data! + .map((e) => McSubject.fromJson(e as Map)) + .toList(); + return TimetableGetSubjectsResponse(result: list); + }); } diff --git a/lib/api/marianumconnect/queries/timetable_get_teachers/timetable_get_teachers.dart b/lib/api/marianumconnect/queries/timetable_get_teachers/timetable_get_teachers.dart index 4027808..4fb281f 100644 --- a/lib/api/marianumconnect/queries/timetable_get_teachers/timetable_get_teachers.dart +++ b/lib/api/marianumconnect/queries/timetable_get_teachers/timetable_get_teachers.dart @@ -1,29 +1,16 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'timetable_get_teachers_response.dart'; -class TimetableGetTeachers { - final Dio _dio; +class TimetableGetTeachers extends MarianumConnectQuery { + TimetableGetTeachers({super.dio}); - TimetableGetTeachers({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('timetable/elements/teachers'), - ); - final list = response.data! - .map( - (e) => - McTimetableTeacherElement.fromJson(e as Map), - ) - .toList(); - return TimetableGetTeachersResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run() => guard(() async { + final response = await dio.get>( + endpoint('timetable/elements/teachers'), + ); + final list = response.data! + .map((e) => McTimetableTeacherElement.fromJson(e as Map)) + .toList(); + return TimetableGetTeachersResponse(result: list); + }); } diff --git a/lib/api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid.dart b/lib/api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid.dart index 282dbcb..c719385 100644 --- a/lib/api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid.dart +++ b/lib/api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid.dart @@ -1,26 +1,16 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'timetable_get_timegrid_response.dart'; -class TimetableGetTimegrid { - final Dio _dio; +class TimetableGetTimegrid extends MarianumConnectQuery { + TimetableGetTimegrid({super.dio}); - TimetableGetTimegrid({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run() async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('timetable/timegrid'), - ); - final list = response.data! - .map((e) => McTimegridUnit.fromJson(e as Map)) - .toList(); - return TimetableGetTimegridResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run() => guard(() async { + final response = await dio.get>( + endpoint('timetable/timegrid'), + ); + final list = response.data! + .map((e) => McTimegridUnit.fromJson(e as Map)) + .toList(); + return TimetableGetTimegridResponse(result: list); + }); } diff --git a/lib/api/marianumconnect/queries/user_search/user_search.dart b/lib/api/marianumconnect/queries/user_search/user_search.dart index 5951b36..28ffbbe 100644 --- a/lib/api/marianumconnect/queries/user_search/user_search.dart +++ b/lib/api/marianumconnect/queries/user_search/user_search.dart @@ -1,30 +1,20 @@ -import 'package:dio/dio.dart'; - -import '../../errors/marianumconnect_error.dart'; -import '../../marianumconnect_api.dart'; -import '../../marianumconnect_endpoint.dart'; +import '../../marianumconnect_query.dart'; import 'user_search_response.dart'; /// Searches active users (students, teachers, staff) via the MarianumConnect /// mobile API. Returns each match's Nextcloud username plus role, so the Talk /// search can start a direct chat and label results without hitting Nextcloud. -class UserSearch { - final Dio _dio; +class UserSearch extends MarianumConnectQuery { + UserSearch({super.dio}); - UserSearch({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); - - Future run(String query) async { - try { - final response = await _dio.get>( - MarianumConnectEndpoint.resolve('users/search'), - queryParameters: {'q': query}, - ); - final list = response.data! - .map((e) => McUserSearchResult.fromJson(e as Map)) - .toList(); - return UserSearchResponse(result: list); - } on DioException catch (e) { - throw mapMarianumConnectError(e); - } - } + Future run(String query) => guard(() async { + final response = await dio.get>( + endpoint('users/search'), + queryParameters: {'q': query}, + ); + final list = response.data! + .map((e) => McUserSearchResult.fromJson(e as Map)) + .toList(); + return UserSearchResponse(result: list); + }); }