添加 HTML 资源路径到 pubspec.yaml;更新 Auth 页面以使用新的 Webview 组件加载本地 HTML 文件;重构 WebviewPage 以支持加载本地资产和注入 JavaScript 通信桥接;清理不必要的导入和注释。
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:recording_tool/app/router/app_navigator.dart';
|
||||
import 'package:recording_tool/features/scan_qrcode/pages/page_scan_qrcode.dart';
|
||||
import 'package:recording_tool/shared/widgets/app_webview.dart';
|
||||
import 'package:recording_tool/shared/widgets/widgets.dart';
|
||||
|
||||
class AuthPageWidget extends StatefulWidget {
|
||||
@@ -35,7 +35,10 @@ class _AuthPageWidgetState extends State<AuthPageWidget> {
|
||||
child: AppButton(
|
||||
label: '确定',
|
||||
onPressed: () {
|
||||
AppNavigator.push(const ScanQrCodePage());
|
||||
// AppNavigator.push(const ScanQrCodePage());
|
||||
AppNavigator.push(
|
||||
const WebviewPage(assetPath: 'assets/html/index.html'),
|
||||
);
|
||||
},
|
||||
variant: AppButtonVariant.secondary,
|
||||
),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:apivideo_live_stream/apivideo_live_stream.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:recording_tool/shared/widgets/app_bar.dart';
|
||||
|
||||
class PushSteamTestWidget extends StatefulWidget {
|
||||
|
||||
@@ -11,6 +11,16 @@
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class $AssetsHtmlGen {
|
||||
const $AssetsHtmlGen();
|
||||
|
||||
/// File path: assets/html/index.html
|
||||
String get index => 'assets/html/index.html';
|
||||
|
||||
/// List of all assets
|
||||
List<String> get values => [index];
|
||||
}
|
||||
|
||||
class $AssetsImagesGen {
|
||||
const $AssetsImagesGen();
|
||||
|
||||
@@ -30,18 +40,24 @@ class $AssetsImagesGen {
|
||||
AssetGenImage get imageLogo =>
|
||||
const AssetGenImage('assets/images/image_logo.png');
|
||||
|
||||
/// File path: assets/images/image_vs.png
|
||||
AssetGenImage get imageVs =>
|
||||
const AssetGenImage('assets/images/image_vs.png');
|
||||
|
||||
/// List of all assets
|
||||
List<AssetGenImage> get values => [
|
||||
imageCopy,
|
||||
imageDelete,
|
||||
imageDialogBg,
|
||||
imageLogo,
|
||||
imageVs,
|
||||
];
|
||||
}
|
||||
|
||||
class Assets {
|
||||
const Assets._();
|
||||
|
||||
static const $AssetsHtmlGen html = $AssetsHtmlGen();
|
||||
static const $AssetsImagesGen images = $AssetsImagesGen();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,16 +5,19 @@ import 'package:webview_flutter_android/webview_flutter_android.dart';
|
||||
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
|
||||
|
||||
class WebviewPage extends StatefulWidget {
|
||||
final String url;
|
||||
final String? url;
|
||||
final String? title;
|
||||
final String? assetPath;
|
||||
|
||||
const WebviewPage({super.key, required this.url, this.title});
|
||||
const WebviewPage({super.key, this.url, this.title, this.assetPath});
|
||||
|
||||
@override
|
||||
State<WebviewPage> createState() => WebviewPageState();
|
||||
}
|
||||
|
||||
class WebviewPageState extends State<WebviewPage> {
|
||||
static const String _javaScriptChannelName = 'AppBridge';
|
||||
|
||||
WebViewController? _controller;
|
||||
bool _isLoading = true;
|
||||
String? _errorMessage;
|
||||
@@ -26,11 +29,12 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
}
|
||||
|
||||
Future<void> _initController() async {
|
||||
if (widget.url?.isEmpty ?? true) {
|
||||
if ((widget.url?.isEmpty ?? true) && widget.assetPath == null) {
|
||||
return;
|
||||
}
|
||||
final params = _createPlatformParams();
|
||||
final controller = WebViewController.fromPlatformCreationParams(params)
|
||||
late final WebViewController controller;
|
||||
controller = WebViewController.fromPlatformCreationParams(params)
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setBackgroundColor(Colors.transparent)
|
||||
..setNavigationDelegate(
|
||||
@@ -46,8 +50,9 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
_errorMessage = null;
|
||||
});
|
||||
},
|
||||
onPageFinished: (String url) {
|
||||
onPageFinished: (String url) async {
|
||||
debugPrint('webview - page finished: $url');
|
||||
await _injectPostMessageBridge(controller);
|
||||
if (!mounted) return;
|
||||
setState(() => _isLoading = false);
|
||||
},
|
||||
@@ -72,17 +77,28 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
),
|
||||
);
|
||||
|
||||
controller.addJavaScriptChannel(
|
||||
_javaScriptChannelName,
|
||||
onMessageReceived: (JavaScriptMessage message) {
|
||||
_onMessageReceived(message);
|
||||
},
|
||||
);
|
||||
|
||||
if (controller.platform is AndroidWebViewController) {
|
||||
AndroidWebViewController.enableDebugging(kDebugMode);
|
||||
await (controller.platform as AndroidWebViewController)
|
||||
.setMediaPlaybackRequiresUserGesture(false);
|
||||
}
|
||||
|
||||
final targetUrl = widget.url ?? '';
|
||||
try {
|
||||
await controller.loadRequest(Uri.parse(targetUrl));
|
||||
if (widget.assetPath != null) {
|
||||
await controller.loadFlutterAsset(widget.assetPath!);
|
||||
} else {
|
||||
final targetUrl = widget.url ?? '';
|
||||
await controller.loadRequest(Uri.parse(targetUrl));
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('webview - loadRequest failed: $e');
|
||||
debugPrint('webview - load failed: $e');
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
@@ -95,6 +111,81 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
setState(() => _controller = controller);
|
||||
}
|
||||
|
||||
void _onMessageReceived(JavaScriptMessage message) {
|
||||
debugPrint('收到来自 WebView 的消息: ${message.message}');
|
||||
}
|
||||
|
||||
/// 脚本注入传输给h5 数据
|
||||
Future<void> _injectH5NeedData(WebViewController controller) async {
|
||||
try {
|
||||
await controller.runJavaScript('''
|
||||
(function () {
|
||||
if (window.__appBridgePostMessageBridgeInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.__appBridgePostMessageBridgeInstalled = true;
|
||||
window.addEventListener('message', function (event) {
|
||||
if (!window.AppBridge || !window.AppBridge.postMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
var payload = event.data;
|
||||
if (typeof payload !== 'string') {
|
||||
try {
|
||||
payload = JSON.stringify(payload);
|
||||
if (typeof payload === 'undefined') {
|
||||
payload = String(event.data);
|
||||
}
|
||||
} catch (error) {
|
||||
payload = String(payload);
|
||||
}
|
||||
}
|
||||
|
||||
window.AppBridge.postMessage(payload);
|
||||
});
|
||||
})();
|
||||
''');
|
||||
} catch (e) {
|
||||
debugPrint('webview - inject postMessage bridge failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _injectPostMessageBridge(WebViewController controller) async {
|
||||
// try {
|
||||
// await controller.runJavaScript('''
|
||||
// (function () {
|
||||
// if (window.__appBridgePostMessageBridgeInstalled) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// window.__appBridgePostMessageBridgeInstalled = true;
|
||||
// window.addEventListener('message', function (event) {
|
||||
// if (!window.AppBridge || !window.AppBridge.postMessage) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var payload = event.data;
|
||||
// if (typeof payload !== 'string') {
|
||||
// try {
|
||||
// payload = JSON.stringify(payload);
|
||||
// if (typeof payload === 'undefined') {
|
||||
// payload = String(event.data);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// payload = String(payload);
|
||||
// }
|
||||
// }
|
||||
|
||||
// window.AppBridge.postMessage(payload);
|
||||
// });
|
||||
// })();
|
||||
// ''');
|
||||
// } catch (e) {
|
||||
// debugPrint('webview - inject postMessage bridge failed: $e');
|
||||
// }
|
||||
}
|
||||
|
||||
PlatformWebViewControllerCreationParams _createPlatformParams() {
|
||||
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
|
||||
return WebKitWebViewControllerCreationParams(
|
||||
@@ -110,27 +201,8 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
title: Text(
|
||||
widget.title ?? '',
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
onPressed: () async {
|
||||
final controller = _controller;
|
||||
if (controller != null && await controller.canGoBack()) {
|
||||
await controller.goBack();
|
||||
} else {
|
||||
if (context.mounted) Navigator.of(context).maybePop();
|
||||
}
|
||||
},
|
||||
),
|
||||
iconTheme: const IconThemeData(color: Colors.white),
|
||||
),
|
||||
|
||||
// appBar: myAppBar(context: context),
|
||||
body: _buildBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user