import 'dart:math'; class H5Line { const H5Line({ required this.label, required this.url, }); final String label; final String url; Uri get uri => Uri.parse(url); } enum Environment { development, staging, production, } class AppConfig { static const String appName = '本地打包'; static const String appLogo = ''; static const String flutterShellMarkerQueryKey = 'flutter_shell'; static const String flutterShellUrlQueryKey = 'flutter_shell_url'; static const List wildcardH5DomainTemplates = [ '*.albzyuxq.vip', '*.zdyswvnt.vip', '*.gxifpxcr.vip', ]; static const Environment currentEnvironment = Environment.production; // Kept for the packaging service's legacy domain rewrite step. static final Map> _environmentHosts = { Environment.production: [ '*.albzyuxq.vip', '*.zdyswvnt.vip', '*.gxifpxcr.vip', ], }; static final Random _random = Random.secure(); static H5Line get h5Line => createRandomH5Line(); static H5Line createRandomH5Line({ int attempt = 0, String Function()? wildcardFactory, }) { final templates = _h5DomainTemplatesForCurrentEnvironment; final template = templates[attempt.abs() % templates.length]; return h5LineFromUrl( _buildFlutterShellHomeUrl( _replaceWildcardHost(template, wildcardFactory: wildcardFactory), ), ); } static List get _h5DomainTemplatesForCurrentEnvironment { final environmentHosts = _environmentHosts[currentEnvironment]; if (environmentHosts == null || environmentHosts.isEmpty) { return wildcardH5DomainTemplates; } return environmentHosts; } static H5Line h5LineFromUrl(String value) { return H5Line(label: '线路1', url: _normalizeHomeUrl(value)); } static String originForUrl(String value) { final uri = Uri.parse(value); return '${uri.scheme}://${uri.authority}'; } static String _buildFlutterShellHomeUrl(String host) { final normalized = _normalizeHomeUrl(host); final uri = Uri.parse(normalized); final origin = originForUrl(normalized); final queryParameters = Map.from(uri.queryParameters) ..[flutterShellMarkerQueryKey] = '1' ..[flutterShellUrlQueryKey] = origin; return uri.replace(queryParameters: queryParameters).toString(); } static String _normalizeHomeUrl(String host) { final value = host.trim(); if (value.isEmpty) { throw const FormatException('Empty H5 line URL'); } final normalized = value.startsWith('http://') || value.startsWith('https://') ? value : 'https://$value'; final uri = Uri.parse(normalized); final path = uri.path.isEmpty ? '/' : uri.path; return uri.replace(path: path).toString(); } static String _replaceWildcardHost( String value, { String Function()? wildcardFactory, }) { if (!value.contains('*.')) { return value; } return value.replaceAllMapped( '*.', (_) => '${(wildcardFactory ?? _randomWildcardLabel)()}.', ); } static String _randomWildcardLabel() { const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'; final label = StringBuffer(); for (var index = 0; index < 6; index += 1) { label.write(alphabet[_random.nextInt(alphabet.length)]); } return label.toString(); } }