claude refactorings, flutter best practices, platform dependent changes, general cleanup

This commit is contained in:
2026-05-06 11:58:50 +02:00
parent 4b1d4379a0
commit 4e1272aba9
281 changed files with 1948 additions and 1041 deletions
@@ -2,9 +2,9 @@ import 'dart:async';
import 'dart:convert';
import '../../../../model/account_data.dart';
import '../../webuntisApi.dart';
import 'authenticateParams.dart';
import 'authenticateResponse.dart';
import '../../webuntis_api.dart';
import 'authenticate_params.dart';
import 'authenticate_response.dart';
class Authenticate extends WebuntisApi {
AuthenticateParams param;
@@ -15,18 +15,19 @@ class Authenticate extends WebuntisApi {
Future<AuthenticateResponse> run() async {
awaitingResponse = true;
try {
var rawAnswer = await query(this);
AuthenticateResponse response = finalize(AuthenticateResponse.fromJson(jsonDecode(rawAnswer)['result']));
final rawAnswer = await query(this);
final decoded = jsonDecode(rawAnswer) as Map<String, dynamic>;
final response = finalize(AuthenticateResponse.fromJson(decoded['result'] as Map<String, dynamic>));
_lastResponse = response;
if(!awaitedResponse.isCompleted) awaitedResponse.complete();
if (!awaitedResponse.isCompleted) awaitedResponse.complete();
return response;
} catch (e) {
// Surface the error to anyone waiting on the current completer, then
// install a fresh one so a future attempt can succeed. Without this,
// any later call to getSession() would hang forever on a completer
// that is already settled with no listeners (or never settles at all).
if(!awaitedResponse.isCompleted) awaitedResponse.completeError(e);
awaitedResponse = Completer();
if (!awaitedResponse.isCompleted) awaitedResponse.completeError(e);
awaitedResponse = Completer<void>();
rethrow;
} finally {
awaitingResponse = false;
@@ -34,7 +35,7 @@ class Authenticate extends WebuntisApi {
}
static bool awaitingResponse = false;
static Completer awaitedResponse = Completer();
static Completer<void> awaitedResponse = Completer<void>();
static AuthenticateResponse? _lastResponse;
static Future<void> createSession() async {
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiParams.dart';
import '../../../api_params.dart';
part 'authenticateParams.g.dart';
part 'authenticate_params.g.dart';
@JsonSerializable()
class AuthenticateParams extends ApiParams {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'authenticateParams.dart';
part of 'authenticate_params.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiResponse.dart';
import '../../../api_response.dart';
part 'authenticateResponse.g.dart';
part 'authenticate_response.g.dart';
@JsonSerializable()
class AuthenticateResponse extends ApiResponse {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'authenticateResponse.dart';
part of 'authenticate_response.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -1,15 +1,15 @@
import 'dart:convert';
import '../../webuntisApi.dart';
import 'getHolidaysResponse.dart';
import '../../webuntis_api.dart';
import 'get_holidays_response.dart';
class GetHolidays extends WebuntisApi {
GetHolidays() : super('getHolidays', null);
@override
Future<GetHolidaysResponse> run() async {
var rawAnswer = await query(this);
return finalize(GetHolidaysResponse.fromJson(jsonDecode(rawAnswer)));
final rawAnswer = await query(this);
return finalize(GetHolidaysResponse.fromJson(jsonDecode(rawAnswer) as Map<String, dynamic>));
}
static GetHolidaysResponseObject? find(GetHolidaysResponse holidaysResponse, {DateTime? time}) {
@@ -1,6 +1,6 @@
import '../../../requestCache.dart';
import 'getHolidays.dart';
import 'getHolidaysResponse.dart';
import '../../../request_cache.dart';
import 'get_holidays.dart';
import 'get_holidays_response.dart';
class GetHolidaysCache extends SimpleCache<GetHolidaysResponse> {
GetHolidaysCache({super.onUpdate, super.onError, super.renew})
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiResponse.dart';
import '../../../api_response.dart';
part 'getHolidaysResponse.g.dart';
part 'get_holidays_response.g.dart';
@JsonSerializable(explicitToJson: true)
class GetHolidaysResponse extends ApiResponse {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getHolidaysResponse.dart';
part of 'get_holidays_response.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -1,18 +1,18 @@
import 'dart:convert';
import 'dart:developer';
import '../../webuntisApi.dart';
import 'getRoomsResponse.dart';
import '../../webuntis_api.dart';
import 'get_rooms_response.dart';
class GetRooms extends WebuntisApi {
GetRooms() : super('getRooms', null);
@override
Future<GetRoomsResponse> run() async {
var rawAnswer = await query(this);
final rawAnswer = await query(this);
try {
return finalize(GetRoomsResponse.fromJson(jsonDecode(rawAnswer)));
} catch(e, trace) {
return finalize(GetRoomsResponse.fromJson(jsonDecode(rawAnswer) as Map<String, dynamic>));
} catch (e, trace) {
log(trace.toString());
log('Failed to parse getRoom data with server response: $rawAnswer');
}
@@ -1,6 +1,6 @@
import '../../../requestCache.dart';
import 'getRooms.dart';
import 'getRoomsResponse.dart';
import '../../../request_cache.dart';
import 'get_rooms.dart';
import 'get_rooms_response.dart';
class GetRoomsCache extends SimpleCache<GetRoomsResponse> {
GetRoomsCache({super.onUpdate, super.onError, super.renew})
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiResponse.dart';
import '../../../api_response.dart';
part 'getRoomsResponse.g.dart';
part 'get_rooms_response.g.dart';
@JsonSerializable(explicitToJson: true)
class GetRoomsResponse extends ApiResponse {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getRoomsResponse.dart';
part of 'get_rooms_response.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -1,14 +1,14 @@
import 'dart:convert';
import '../../webuntisApi.dart';
import 'getSubjectsResponse.dart';
import '../../webuntis_api.dart';
import 'get_subjects_response.dart';
class GetSubjects extends WebuntisApi {
GetSubjects() : super('getSubjects', null);
@override
Future<GetSubjectsResponse> run() async {
var rawAnswer = await query(this);
return finalize(GetSubjectsResponse.fromJson(jsonDecode(rawAnswer)));
final rawAnswer = await query(this);
return finalize(GetSubjectsResponse.fromJson(jsonDecode(rawAnswer) as Map<String, dynamic>));
}
}
@@ -1,6 +1,6 @@
import '../../../requestCache.dart';
import 'getSubjects.dart';
import 'getSubjectsResponse.dart';
import '../../../request_cache.dart';
import 'get_subjects.dart';
import 'get_subjects_response.dart';
class GetSubjectsCache extends SimpleCache<GetSubjectsResponse> {
GetSubjectsCache({super.onUpdate, super.onError, super.renew})
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiResponse.dart';
import '../../../api_response.dart';
part 'getSubjectsResponse.g.dart';
part 'get_subjects_response.g.dart';
@JsonSerializable(explicitToJson: true)
class GetSubjectsResponse extends ApiResponse {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getSubjectsResponse.dart';
part of 'get_subjects_response.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -1,17 +1,17 @@
import 'dart:convert';
import 'dart:developer';
import '../../webuntisApi.dart';
import 'getTimegridUnitsResponse.dart';
import '../../webuntis_api.dart';
import 'get_timegrid_units_response.dart';
class GetTimegridUnits extends WebuntisApi {
GetTimegridUnits() : super('getTimegridUnits', null);
@override
Future<GetTimegridUnitsResponse> run() async {
var rawAnswer = await query(this);
final rawAnswer = await query(this);
try {
return finalize(GetTimegridUnitsResponse.fromJson(jsonDecode(rawAnswer)));
return finalize(GetTimegridUnitsResponse.fromJson(jsonDecode(rawAnswer) as Map<String, dynamic>));
} catch (e, trace) {
log(trace.toString());
log('Failed to parse getTimegridUnits data with server response: $rawAnswer');
@@ -1,6 +1,6 @@
import '../../../requestCache.dart';
import 'getTimegridUnits.dart';
import 'getTimegridUnitsResponse.dart';
import '../../../request_cache.dart';
import 'get_timegrid_units.dart';
import 'get_timegrid_units_response.dart';
class GetTimegridUnitsCache extends SimpleCache<GetTimegridUnitsResponse> {
GetTimegridUnitsCache({super.onUpdate, super.renew})
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiResponse.dart';
import '../../../api_response.dart';
part 'getTimegridUnitsResponse.g.dart';
part 'get_timegrid_units_response.g.dart';
@JsonSerializable(explicitToJson: true)
class GetTimegridUnitsResponse extends ApiResponse {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getTimegridUnitsResponse.dart';
part of 'get_timegrid_units_response.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -1,8 +1,8 @@
import 'dart:convert';
import '../../webuntisApi.dart';
import 'getTimetableParams.dart';
import 'getTimetableResponse.dart';
import '../../webuntis_api.dart';
import 'get_timetable_params.dart';
import 'get_timetable_response.dart';
class GetTimetable extends WebuntisApi {
GetTimetableParams params;
@@ -11,8 +11,8 @@ class GetTimetable extends WebuntisApi {
@override
Future<GetTimetableResponse> run() async {
var rawAnswer = await query(this);
return finalize(GetTimetableResponse.fromJson(jsonDecode(rawAnswer)));
final rawAnswer = await query(this);
return finalize(GetTimetableResponse.fromJson(jsonDecode(rawAnswer) as Map<String, dynamic>));
}
}
@@ -1,8 +1,8 @@
import '../../../requestCache.dart';
import '../../../request_cache.dart';
import '../authenticate/authenticate.dart';
import 'getTimetable.dart';
import 'getTimetableParams.dart';
import 'getTimetableResponse.dart';
import 'get_timetable.dart';
import 'get_timetable_params.dart';
import 'get_timetable_response.dart';
class GetTimetableCache extends SimpleCache<GetTimetableResponse> {
GetTimetableCache({
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiParams.dart';
import '../../../api_params.dart';
part 'getTimetableParams.g.dart';
part 'get_timetable_params.g.dart';
@JsonSerializable(explicitToJson: true)
class GetTimetableParams extends ApiParams {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getTimetableParams.dart';
part of 'get_timetable_params.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -1,8 +1,8 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../apiResponse.dart';
import '../../../api_response.dart';
part 'getTimetableResponse.g.dart';
part 'get_timetable_response.g.dart';
@JsonSerializable(explicitToJson: true)
class GetTimetableResponse extends ApiResponse {
@@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getTimetableResponse.dart';
part of 'get_timetable_response.dart';
// **************************************************************************
// JsonSerializableGenerator
@@ -5,13 +5,13 @@ import 'dart:io';
import 'package:http/http.dart' as http;
import '../../model/endpoint_data.dart';
import '../apiParams.dart';
import '../apiRequest.dart';
import '../apiResponse.dart';
import '../api_params.dart';
import '../api_request.dart';
import '../api_response.dart';
import '../errors/network_exception.dart';
import '../errors/parse_exception.dart';
import 'queries/authenticate/authenticate.dart';
import 'webuntisError.dart';
import 'webuntis_error.dart';
abstract class WebuntisApi extends ApiRequest {
Uri endpoint = Uri.parse('https://${EndpointData().webuntis().full()}/WebUntis/jsonrpc.do?school=marianum-fulda');
@@ -25,34 +25,36 @@ abstract class WebuntisApi extends ApiRequest {
Future<String> query(WebuntisApi untis, {bool retry = false}) async {
var query = '{"id":"ID","method":"$method","params":${untis._body()},"jsonrpc":"2.0"}';
final body = '{"id":"ID","method":"$method","params":${untis._body()},"jsonrpc":"2.0"}';
var sessionId = '0';
if(authenticatedResponse) {
if (authenticatedResponse) {
sessionId = (await Authenticate.getSession()).sessionId;
}
var data = await post(query, {'Cookie': 'JSESSIONID=$sessionId'});
final data = await post(body, {'Cookie': 'JSESSIONID=$sessionId'});
response = data;
final dynamic jsonData;
final Map<String, dynamic> jsonData;
try {
jsonData = jsonDecode(data.body);
jsonData = jsonDecode(data.body) as Map<String, dynamic>;
} on FormatException catch (e) {
throw ParseException(technicalDetails: 'WebUntis JSON decode: ${e.message}');
}
if(jsonData['error'] != null) {
if(jsonData['error']['code'] == -8520) {
if(retry) throw WebuntisError('Authentication was tried (probably session timeout), but was not successful!', -8520);
final error = jsonData['error'] as Map<String, dynamic>?;
if (error != null) {
final code = error['code'] as int;
if (code == -8520) {
if (retry) throw WebuntisError('Authentication was tried (probably session timeout), but was not successful!', -8520);
await Authenticate.createSession();
return await this.query(untis, retry: true);
return query(untis, retry: true);
} else {
throw WebuntisError(jsonData['error']['message'], jsonData['error']['code']);
throw WebuntisError(error['message'] as String, code);
}
}
return data.body;
}
dynamic finalize(dynamic response) {
T finalize<T extends ApiResponse>(T response) {
response.rawResponse = this.response!;
return response;
}