migrated timetable integration from WebUntis to the MarianumConnect API, implementing a Dio-based client with bearer token authentication, background session validation, and auto-refresh logic.

This commit is contained in:
2026-05-23 17:32:42 +02:00
parent 2858f910c9
commit 93b9929f8f
106 changed files with 2739 additions and 2624 deletions
+65
View File
@@ -1,19 +1,84 @@
import 'package:flutter/foundation.dart';
import 'package:json_annotation/json_annotation.dart';
part 'dev_tools_settings.g.dart';
enum MarianumConnectEndpoint { live, beta, custom }
@JsonSerializable()
class DevToolsSettings {
bool showPerformanceOverlay;
bool checkerboardOffscreenLayers;
bool checkerboardRasterCacheImages;
@JsonKey(defaultValue: MarianumConnectEndpoint.live)
MarianumConnectEndpoint marianumConnectEndpoint;
@JsonKey(defaultValue: '')
String marianumConnectCustomUrl;
DevToolsSettings({
required this.showPerformanceOverlay,
required this.checkerboardOffscreenLayers,
required this.checkerboardRasterCacheImages,
this.marianumConnectEndpoint = MarianumConnectEndpoint.live,
this.marianumConnectCustomUrl = '',
});
// Resolves the effective base URL for the Marianum-Connect mobile API.
// Falls back to live when the custom URL is empty or malformed. HTTP is
// accepted alongside HTTPS only in debug/profile builds (developers can
// point at `http://10.0.2.2:8080` without configuring TLS locally); release
// builds restrict the custom endpoint to HTTPS so a leaked debug URL never
// ships an unencrypted bearer token over the wire.
String resolveMarianumConnectBaseUrl() {
switch (marianumConnectEndpoint) {
case MarianumConnectEndpoint.live:
return liveUrl;
case MarianumConnectEndpoint.beta:
return betaUrl;
case MarianumConnectEndpoint.custom:
final sanitized = sanitizeCustomUrl(marianumConnectCustomUrl);
return sanitized ?? liveUrl;
}
}
static const String liveUrl = 'https://connect.marianum-fulda.de';
static const String betaUrl = 'https://connect-beta.marianum-fulda.de';
/// `true` in builds where plaintext HTTP custom endpoints are still allowed
/// (debug, profile). Release builds keep this `false` and the picker
/// rejects `http://` entirely.
static bool get allowsHttpCustomEndpoint => !kReleaseMode;
/// Returns the trimmed URL without a trailing slash, or null when the input
/// is not a usable HTTP/HTTPS URL. HTTP is only accepted when
/// [allowsHttpCustomEndpoint] is `true` — i.e. outside release builds.
static String? sanitizeCustomUrl(String raw) {
final trimmed = raw.trim();
if (trimmed.isEmpty) return null;
final uri = Uri.tryParse(trimmed);
if (uri == null || !uri.hasScheme) return null;
if (uri.scheme == 'https') {
// always fine
} else if (uri.scheme == 'http' && allowsHttpCustomEndpoint) {
// dev only
} else {
return null;
}
if (uri.host.isEmpty) return null;
return trimmed.endsWith('/')
? trimmed.substring(0, trimmed.length - 1)
: trimmed;
}
/// `true` when the configured custom URL is plain HTTP — the picker shows
/// this as a warning so developers don't accidentally ship a debug URL.
bool get marianumConnectCustomUrlIsInsecure {
final sanitized = sanitizeCustomUrl(marianumConnectCustomUrl);
return sanitized != null && Uri.parse(sanitized).scheme == 'http';
}
factory DevToolsSettings.fromJson(Map<String, dynamic> json) =>
_$DevToolsSettingsFromJson(json);
Map<String, dynamic> toJson() => _$DevToolsSettingsToJson(this);