Compare commits
No commits in common. "b076e4318077ac3fc805eda5d5d8a8e76a445cdf" and "bd9c9c34992a65c814e1a4559b998617fd7479a5" have entirely different histories.
b076e43180
...
bd9c9c3499
@ -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>
|
||||||
|
|||||||
@ -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';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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: () {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user