332 lines
11 KiB
Dart
332 lines
11 KiB
Dart
import 'dart:convert';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||
import 'package:aslan/chatvibe_core/utilities/at_pick_utils.dart';
|
||
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
|
||
import 'package:provider/provider.dart';
|
||
import 'package:tencent_cloud_chat_sdk/enum/conversation_type.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
||
import 'package:webview_flutter/webview_flutter.dart';
|
||
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
|
||
import 'package:aslan/chatvibe_core/constants/at_screen.dart';
|
||
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
|
||
import 'package:aslan/chatvibe_core/utilities/at_deviceId_utils.dart';
|
||
import 'package:aslan/chatvibe_core/utilities/at_room_utils.dart';
|
||
import 'package:aslan/main.dart';
|
||
import 'package:aslan/chatvibe_managers/rtm_manager.dart';
|
||
import 'package:aslan/chatvibe_ui/widgets/share/share_page.dart';
|
||
import 'package:aslan/chatvibe_features/chat/at_chat_route.dart';
|
||
import 'package:aslan/chatvibe_features/index/main_route.dart';
|
||
import 'package:aslan/chatvibe_features/webview/at_webview_navigation_handler.dart';
|
||
|
||
class WebViewPage extends StatefulWidget {
|
||
final String title;
|
||
final String url;
|
||
final String showTitle;
|
||
|
||
const WebViewPage({
|
||
Key? key,
|
||
this.title = "",
|
||
this.showTitle = "true",
|
||
required this.url,
|
||
}) : super(key: key);
|
||
|
||
@override
|
||
_WebViewPageState createState() => _WebViewPageState();
|
||
}
|
||
|
||
class _WebViewPageState extends State<WebViewPage> {
|
||
late WebViewController _controller;
|
||
String _title = "";
|
||
double _progress = 0.0;
|
||
bool _isLoading = true;
|
||
String urlLink = "";
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
if (widget.url.split("?").length > 1) {
|
||
urlLink = "${widget.url}&";
|
||
} else {
|
||
urlLink = "${widget.url}?";
|
||
}
|
||
urlLink = "${urlLink}lang=${ATGlobalConfig.lang}";
|
||
// 初始化 WebViewController
|
||
_controller =
|
||
WebViewController()
|
||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||
..addJavaScriptChannel(
|
||
"FlutterPageControl",
|
||
onMessageReceived: (sjMessage) async {
|
||
String msg = sjMessage.message;
|
||
if (sjMessage.message == "close_page") {
|
||
ATNavigatorUtils.goBack(context);
|
||
} else if (msg.startsWith("view_user_info")) {
|
||
//跳转个人信息
|
||
if (msg.contains(":")) {
|
||
var sli = msg.split(":");
|
||
if (sli.length > 1) {
|
||
String userId = sli[1];
|
||
ATNavigatorUtils.push(
|
||
context,
|
||
"${MainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == userId}&tageId=$userId",
|
||
);
|
||
}
|
||
}
|
||
} else if (msg.startsWith("go_to_room")) {
|
||
//跳转房间
|
||
if (msg.contains(":")) {
|
||
var sli = msg.split(":");
|
||
if (sli.length > 1) {
|
||
String roomId = sli[1];
|
||
ATRoomUtils.goRoom(
|
||
roomId,
|
||
navigatorKey.currentState!.context,
|
||
);
|
||
}
|
||
}
|
||
} else if (msg.startsWith("private_chat")) {
|
||
//打开私聊
|
||
if (msg.contains(":")) {
|
||
var sli = msg.split(":");
|
||
if (sli.length > 1) {
|
||
String userId = sli[1];
|
||
var conversation = V2TimConversation(
|
||
type: ConversationType.V2TIM_C2C,
|
||
userID: userId,
|
||
conversationID: '',
|
||
);
|
||
var bool = await Provider.of<RtmProvider>(
|
||
context,
|
||
listen: false,
|
||
).startConversation(conversation);
|
||
if (!bool) return;
|
||
var json = jsonEncode(conversation.toJson());
|
||
ATNavigatorUtils.push(
|
||
context,
|
||
"${ATChatRouter.chat}?conversation=${Uri.encodeComponent(json)}",
|
||
);
|
||
}
|
||
}
|
||
} else if (msg.startsWith("uploadImgFile")) {
|
||
picImage();
|
||
} else if (msg.startsWith("editingRoom")) {
|
||
ATNavigatorUtils.push(context, MainRoute.editRoomSearchAdmin);
|
||
} else if (msg.startsWith("editingUser")) {
|
||
ATNavigatorUtils.push(context, MainRoute.editUserSearchAdmin);
|
||
} else if (msg.startsWith("myCoupleList")) {
|
||
ATNavigatorUtils.push(context, MainRoute.cpList);
|
||
} else if (msg.startsWith("shareDrawer")) {
|
||
if (msg.contains(":")) {
|
||
var sli = msg.split(":");
|
||
if (sli.length > 1) {
|
||
String shareMsg = sli[1];
|
||
_showShareDialog(shareMsg);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
)
|
||
..setNavigationDelegate(
|
||
NavigationDelegate(
|
||
onProgress: (int progress) {
|
||
setState(() {
|
||
_progress = progress / 100.0;
|
||
});
|
||
},
|
||
onNavigationRequest:
|
||
ATWebViewNavigationHandler.handleNavigationRequest,
|
||
onPageStarted: (String url) {
|
||
setState(() {
|
||
_isLoading = true;
|
||
});
|
||
},
|
||
onPageFinished: (String url) {
|
||
// 延迟500毫秒注入,等待Vue3初始化
|
||
Future.delayed(Duration(milliseconds: 550), () {
|
||
_injectJavaScriptInterface();
|
||
});
|
||
setState(() {
|
||
_isLoading = false;
|
||
_getPageTitle();
|
||
});
|
||
},
|
||
onWebResourceError: (WebResourceError error) {
|
||
_onWebResourceError(error);
|
||
},
|
||
),
|
||
)
|
||
..loadRequest(Uri.parse(urlLink));
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_controller.loadRequest(Uri.parse('about:blank'));
|
||
super.dispose();
|
||
}
|
||
|
||
void _injectJavaScriptInterface() async {
|
||
String imei = await ATDeviceIdUtils.collectDeviceId();
|
||
// 注入JavaScript对象和方法
|
||
_controller.runJavaScript('''
|
||
window.app = window.app || {};
|
||
// 注入获取访问信息的方法
|
||
window.app.getAccessOrigin = function() {
|
||
// 获取认证信息(这里可以从Flutter传递)
|
||
return JSON.stringify({
|
||
'Authorization': 'Bearer ${AccountStorage().token}',
|
||
'Req-Lang': '${ATGlobalConfig.lang}',
|
||
'Req-App-Intel': 'build=${ATGlobalConfig.build};version=${ATGlobalConfig.version};model=${ATGlobalConfig.model};channel=${ATGlobalConfig.channel};Req-Imei=$imei',
|
||
'Req-Sys-Origin': 'origin=${ATGlobalConfig.origin};originChild=${ATGlobalConfig.originChild}'
|
||
});
|
||
};
|
||
|
||
// 注入其他可能需要的方法
|
||
window.app.getAuth = function() {
|
||
return window.app.getAccessOrigin();
|
||
};
|
||
|
||
// 可以通过这个方法向Flutter发送消息
|
||
window.app.sendToFlutter = function(data) {
|
||
FlutterApp.postMessage(data);
|
||
};
|
||
''');
|
||
}
|
||
|
||
void picImage() async {
|
||
ATPickUtils.pickImageProcess(context, (b, path) {
|
||
_controller.runJavaScript('''
|
||
window.app = window.app || {};
|
||
// 注入获取访问信息的方法
|
||
window.app.getImagePath = function() {
|
||
// 获取认证信息(这里可以从Flutter传递)
|
||
return JSON.stringify({
|
||
'path': '$path',
|
||
});
|
||
};
|
||
|
||
// 注入其他可能需要的方法
|
||
window.app.getAuth = function() {
|
||
return window.app.getImagePath();
|
||
};
|
||
|
||
// 可以通过这个方法向Flutter发送消息
|
||
window.app.sendToFlutter = function(data) {
|
||
FlutterApp.postMessage(data);
|
||
};
|
||
''');
|
||
}, neeCrop: false);
|
||
}
|
||
|
||
// 获取页面标题
|
||
Future<void> _getPageTitle() async {
|
||
try {
|
||
final title =
|
||
await _controller.runJavaScriptReturningResult("document.title")
|
||
as String?;
|
||
if (title != null) {
|
||
setState(() {
|
||
_title = title.replaceAll("\"", "");
|
||
});
|
||
}
|
||
} catch (e) {
|
||
print("获取标题失败: $e");
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar:
|
||
widget.showTitle == "true"
|
||
? AppBar(
|
||
elevation: 0,
|
||
backgroundColor:
|
||
ATGlobalConfig.businessLogicStrategy
|
||
.getWebViewPageAppBarBackgroundColor(),
|
||
centerTitle: true,
|
||
title: Text(
|
||
_title.isNotEmpty ? _title : widget.title,
|
||
style: TextStyle(
|
||
fontSize: sp(18),
|
||
color:
|
||
ATGlobalConfig.businessLogicStrategy
|
||
.getWebViewPageTitleTextColor(),
|
||
),
|
||
),
|
||
leading: GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
ATNavigatorUtils.goBack(context);
|
||
},
|
||
child: Container(
|
||
padding: EdgeInsets.only(left: width(15), right: width(15)),
|
||
child: Center(
|
||
child: Icon(
|
||
Icons.arrow_back_ios,
|
||
size: 20.w,
|
||
color:
|
||
ATGlobalConfig.businessLogicStrategy
|
||
.getWebViewPageBackArrowColor(),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
systemOverlayStyle: SystemUiOverlayStyle.dark,
|
||
)
|
||
: null,
|
||
body: SafeArea(
|
||
top: false,
|
||
child: Stack(
|
||
children: [
|
||
WebViewWidget(controller: _controller),
|
||
|
||
// 加载指示器
|
||
// if (_isLoading)
|
||
// Center(
|
||
// child: CircularProgressIndicator(
|
||
// valueColor: AlwaysStoppedAnimation<Color>(Color(0xffFF6000)),
|
||
// ),
|
||
// ),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _progressBar(double progress, BuildContext context) {
|
||
return progress < 1.0
|
||
? LinearProgressIndicator(
|
||
value: progress,
|
||
backgroundColor:
|
||
ATGlobalConfig.businessLogicStrategy
|
||
.getWebViewPageProgressBarBackgroundColor(),
|
||
minHeight: 1.0,
|
||
valueColor: AlwaysStoppedAnimation<Color>(
|
||
ATGlobalConfig.businessLogicStrategy
|
||
.getWebViewPageProgressBarActiveColor(),
|
||
),
|
||
)
|
||
: const SizedBox.shrink();
|
||
}
|
||
|
||
void _onWebResourceError(WebResourceError error) {
|
||
print('_onWebResourceError:${error.description}, url:${error.url}');
|
||
ATWebViewNavigationHandler.handleWebResourceError(error);
|
||
}
|
||
|
||
void _showShareDialog(String shareMsg) {
|
||
SmartDialog.show(
|
||
tag: "showShareDialog",
|
||
alignment: Alignment.bottomCenter,
|
||
debounce: true,
|
||
animationType: SmartAnimationType.fade,
|
||
builder: (_) {
|
||
return SharePage(shareMsg);
|
||
},
|
||
);
|
||
}
|
||
}
|