Compare commits

..

No commits in common. "b076e4318077ac3fc805eda5d5d8a8e76a445cdf" and "bd9c9c34992a65c814e1a4559b998617fd7479a5" have entirely different histories.

3 changed files with 18 additions and 117 deletions

View File

@ -88,8 +88,6 @@
logEl.textContent = line + logEl.textContent; logEl.textContent = line + logEl.textContent;
} }
let hasLoadedGame = false;
function requestConfig() { function requestConfig() {
if (!window.NativeBridge || typeof window.NativeBridge.getConfig !== "function") { if (!window.NativeBridge || typeof window.NativeBridge.getConfig !== "function") {
writeLog("getConfig", { error: "NativeBridge not ready" }); writeLog("getConfig", { error: "NativeBridge not ready" });
@ -97,14 +95,10 @@
} }
window.NativeBridge.getConfig(function (config) { window.NativeBridge.getConfig(function (config) {
writeLog("getConfig callback", config); writeLog("getConfig callback", config);
if (!hasLoadedGame) {
setTimeout(notifyLoaded, 300);
}
}); });
} }
function notifyLoaded() { function notifyLoaded() {
hasLoadedGame = true;
window.NativeBridge && window.NativeBridge &&
window.NativeBridge.gameLoaded && window.NativeBridge.gameLoaded &&
window.NativeBridge.gameLoaded({ status: "loaded" }); window.NativeBridge.gameLoaded({ status: "loaded" });
@ -132,23 +126,6 @@
window.addEventListener("walletUpdate", function (event) { window.addEventListener("walletUpdate", function (event) {
writeLog("walletUpdate event", event.detail || {}); writeLog("walletUpdate event", event.detail || {});
}); });
window.addEventListener("baishunBridgeReady", function () {
writeLog("baishunBridgeReady", { status: "received" });
requestConfig();
});
window.addEventListener("baishunConfig", function (event) {
writeLog("baishunConfig event", event.detail || {});
});
window.addEventListener("load", function () {
setTimeout(function () {
if (!hasLoadedGame) {
requestConfig();
}
}, 150);
});
</script> </script>
</body> </body>
</html> </html>

View File

@ -76,12 +76,6 @@ class BaishunJsBridge {
window.dispatchEvent(new CustomEvent('walletUpdate', { detail: payload || {} })); window.dispatchEvent(new CustomEvent('walletUpdate', { detail: payload || {} }));
} }
}; };
if (typeof window.onBaishunBridgeReady === 'function') {
window.onBaishunBridgeReady(window.NativeBridge);
}
if (typeof window.dispatchEvent === 'function') {
window.dispatchEvent(new CustomEvent('baishunBridgeReady', { detail: { nativeBridge: true } }));
}
})(); })();
'''; ''';
} }
@ -94,13 +88,11 @@ class BaishunJsBridge {
window.__baishunLastConfig = config; window.__baishunLastConfig = config;
if (typeof window.__baishunGetConfigCallback === 'function') { if (typeof window.__baishunGetConfigCallback === 'function') {
window.__baishunGetConfigCallback(config); window.__baishunGetConfigCallback(config);
return;
} }
if (typeof window.onBaishunConfig === 'function') { if (typeof window.onBaishunConfig === 'function') {
window.onBaishunConfig(config); window.onBaishunConfig(config);
} }
if (typeof window.dispatchEvent === 'function') {
window.dispatchEvent(new CustomEvent('baishunConfig', { detail: config }));
}
})(); })();
'''; ''';
} }
@ -108,7 +100,9 @@ class BaishunJsBridge {
static String buildWalletUpdateScript({Map<String, dynamic>? payload}) { static String buildWalletUpdateScript({Map<String, dynamic>? payload}) {
final safePayload = jsonEncode( final safePayload = jsonEncode(
payload ?? payload ??
<String, dynamic>{'timestamp': DateTime.now().millisecondsSinceEpoch}, <String, dynamic>{
'timestamp': DateTime.now().millisecondsSinceEpoch,
},
); );
return ''' return '''
(function() { (function() {
@ -119,26 +113,4 @@ class BaishunJsBridge {
})(); })();
'''; ''';
} }
static String injectBootstrapHtml({
required String html,
required Uri entryUri,
required BaishunBridgeConfigModel config,
}) {
final baseHref = htmlEscape.convert(entryUri.toString());
final injection = '''
<base href="$baseHref" />
<script>
${bootstrapScript()}
${buildConfigScript(config)}
</script>
''';
final headPattern = RegExp(r'<head[^>]*>', caseSensitive: false);
final headMatch = headPattern.firstMatch(html);
if (headMatch != null) {
return html.replaceRange(headMatch.end, headMatch.end, injection);
}
return '$injection$html';
}
} }

View File

@ -1,7 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
@ -52,7 +49,7 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
..setNavigationDelegate( ..setNavigationDelegate(
NavigationDelegate( NavigationDelegate(
onPageFinished: (String _) async { onPageFinished: (String _) async {
await _primeBridgeHandshake(); await _injectBridge();
}, },
onWebResourceError: (WebResourceError error) { onWebResourceError: (WebResourceError error) {
if (!mounted) { if (!mounted) {
@ -86,13 +83,7 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
if (uri == null) { if (uri == null) {
throw Exception('Invalid game entry url: $entryUrl'); throw Exception('Invalid game entry url: $entryUrl');
} }
final html = await _fetchRemoteEntryHtml(uri); await _controller.loadRequest(uri);
final injectedHtml = BaishunJsBridge.injectBootstrapHtml(
html: html,
entryUri: uri,
config: widget.launchModel.bridgeConfig,
);
await _controller.loadHtmlString(injectedHtml, baseUrl: uri.toString());
} catch (error) { } catch (error) {
if (!mounted) { if (!mounted) {
return; return;
@ -104,24 +95,6 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
} }
} }
Future<String> _fetchRemoteEntryHtml(Uri uri) async {
final client = HttpClient();
client.userAgent = 'YumiBaishunBridge/1.0';
try {
final request = await client.getUrl(uri);
final response = await request.close();
if (response.statusCode < 200 || response.statusCode >= 300) {
throw HttpException(
'Failed to load remote entry html (${response.statusCode})',
uri: uri,
);
}
return response.transform(utf8.decoder).join();
} finally {
client.close(force: true);
}
}
Future<void> _injectBridge() async { Future<void> _injectBridge() async {
try { try {
await _controller.runJavaScript(BaishunJsBridge.bootstrapScript()); await _controller.runJavaScript(BaishunJsBridge.bootstrapScript());
@ -131,21 +104,6 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
} catch (_) {} } catch (_) {}
} }
Future<void> _primeBridgeHandshake() async {
await _injectBridge();
for (final delay in <Duration>[
const Duration(milliseconds: 400),
const Duration(milliseconds: 1200),
]) {
Future<void>.delayed(delay, () async {
if (!mounted || !_isLoading || _errorMessage != null) {
return;
}
await _injectBridge();
});
}
}
Future<void> _handleBridgeMessage(JavaScriptMessage message) async { Future<void> _handleBridgeMessage(JavaScriptMessage message) async {
final bridgeMessage = BaishunBridgeMessage.parse(message.message); final bridgeMessage = BaishunBridgeMessage.parse(message.message);
switch (bridgeMessage.action) { switch (bridgeMessage.action) {
@ -177,9 +135,7 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
Future<void> _notifyWalletUpdate() async { Future<void> _notifyWalletUpdate() async {
try { try {
await _controller.runJavaScript( await _controller.runJavaScript(BaishunJsBridge.buildWalletUpdateScript());
BaishunJsBridge.buildWalletUpdateScript(),
);
} catch (_) {} } catch (_) {}
} }
@ -250,10 +206,7 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
children: [ children: [
IconButton( IconButton(
onPressed: _closeAndExit, onPressed: _closeAndExit,
icon: const Icon( icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
Icons.arrow_back_ios,
color: Colors.white,
),
), ),
Expanded( Expanded(
child: Text( child: Text(
@ -276,17 +229,10 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
Expanded( Expanded(
child: Stack( child: Stack(
children: [ children: [
Positioned.fill( Positioned.fill(child: WebViewWidget(controller: _controller)),
child: WebViewWidget(controller: _controller),
),
if (_errorMessage != null) _buildErrorState(), if (_errorMessage != null) _buildErrorState(),
if (_isLoading && _errorMessage == null) if (_isLoading && _errorMessage == null)
const IgnorePointer( const BaishunLoadingView(message: 'Waiting for gameLoaded...'),
ignoring: true,
child: BaishunLoadingView(
message: 'Waiting for gameLoaded...',
),
),
], ],
), ),
), ),
@ -320,13 +266,19 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
Text( Text(
_errorMessage ?? '', _errorMessage ?? '',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(color: Colors.white70, fontSize: 12.sp), style: TextStyle(
color: Colors.white70,
fontSize: 12.sp,
),
), ),
SizedBox(height: 16.w), SizedBox(height: 16.w),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
TextButton(onPressed: _reload, child: const Text('Retry')), TextButton(
onPressed: _reload,
child: const Text('Retry'),
),
SizedBox(width: 10.w), SizedBox(width: 10.w),
TextButton( TextButton(
onPressed: () { onPressed: () {