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 json) => _$DevToolsSettingsFromJson(json); Map toJson() => _$DevToolsSettingsToJson(this); }