Compare commits

..

2 Commits

Author SHA1 Message Date
admin
c0d5021f8c change 2026-06-11 11:12:46 +08:00
admin
fb207d667e change 2026-06-11 11:05:19 +08:00
2 changed files with 209 additions and 153 deletions

View File

@@ -28,6 +28,23 @@ Future launchURL(
}
}
String _externalUrlForScheme(String url, String scheme) {
final prefix = '$scheme:';
if (!url.toLowerCase().startsWith(prefix)) return url;
final stripped = url
.substring(prefix.length)
.replaceFirst(RegExp(r'^/+'), '');
final uri = Uri.tryParse(stripped);
if (uri != null &&
(uri.scheme == 'http' || uri.scheme == 'https') &&
uri.host.isNotEmpty) {
return stripped;
}
return url;
}
class BootstrapProgress {
final String phase;
final double percent;
@@ -492,6 +509,7 @@ class _LoadingScreenState extends State<LoadingScreen>
Positioned.fill(
child: Material(
color: Colors.black,
child: SafeArea(
child: Stack(
children: [
Positioned.fill(
@@ -532,7 +550,7 @@ class _LoadingScreenState extends State<LoadingScreen>
_showWebViewProgress(progress: 0);
});
}
debugPrint('onLoadStart: $url');
debugPrint('WebView onLoadStart: $url');
},
onProgressChanged: (controller, progress) {
if (!mounted) return;
@@ -550,7 +568,7 @@ class _LoadingScreenState extends State<LoadingScreen>
if (progress >= 100) {
_hideWebViewProgressSoon();
}
debugPrint('onProgressChanged: $progress');
debugPrint('WebView onProgressChanged: $progress');
},
onLoadStop: (controller, url) async {
final loadedUrl = url?.toString();
@@ -572,7 +590,7 @@ class _LoadingScreenState extends State<LoadingScreen>
_hideWebViewProgressSoon();
}
_reportWebViewEvent('load_success', {
'rs': _safeReportUrl(loadedUrl),
'url': _safeReportUrl(loadedUrl),
});
debugPrint('WebView onLoadStop: $url');
},
@@ -617,9 +635,30 @@ class _LoadingScreenState extends State<LoadingScreen>
(controller, navigationAction) async {
final requestUrl = navigationAction.request.url
?.toString();
if (requestUrl != null && requestUrl.isNotEmpty) {
if (requestUrl != null &&
requestUrl.isNotEmpty) {
_currentWebViewUrl = requestUrl;
}
final requestScheme = navigationAction
.request
.url
?.scheme
.trim()
.toLowerCase();
if (requestUrl != null &&
requestUrl.isNotEmpty &&
requestScheme != null &&
NextStep.I.openWindows.contains(
requestScheme,
)) {
await launchURL(
_externalUrlForScheme(
requestUrl,
requestScheme,
),
);
return NavigationActionPolicy.CANCEL;
}
final isRedirect =
navigationAction.isRedirect == true;
if (isRedirect && mounted) {
@@ -658,6 +697,7 @@ class _LoadingScreenState extends State<LoadingScreen>
),
),
),
),
],
),
);

View File

@@ -107,6 +107,8 @@ class NextStep {
bool _j = false;
bool get j => _j;
Set<String> openWindows = {};
NextStep._();
static final NextStep I = NextStep._();
@@ -142,6 +144,7 @@ class NextStep {
if (rs is! Map<String, dynamic>) return;
_applyEventMap(rs['f']);
openWindows = _parseOpenWindowSchemes(rs['o']);
} catch (e) {
debugPrint("loadAppInfo error $e");
}
@@ -261,6 +264,19 @@ void _applyEventMap(dynamic value) {
}
}
Set<String> _parseOpenWindowSchemes(dynamic value) {
if (value is! List) return {};
return value
.map((item) => item?.toString().trim().toLowerCase() ?? '')
.map(
(item) =>
item.endsWith(':') ? item.substring(0, item.length - 1) : item,
)
.where((item) => item.isNotEmpty)
.toSet();
}
bool _isValidToken(String? token) {
return token != null && token.trim().length > 5;
}