From d6fafe7f951a18d831900dca599b17482ee114db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BC=96=E7=A0=81=E5=B7=A5=E7=A8=8B=E5=B8=88?= Date: Fri, 21 Aug 2026 10:01:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(mobile-next):=20=E7=A7=BB=E9=99=A4=E6=82=AC?= =?UTF-8?q?=E6=B5=AE=E7=AA=97=E7=94=B3=E8=AF=B7=E4=B8=8E=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E5=8F=91=E9=80=81=EF=BC=8C=E9=80=9A=E8=AF=9D=E6=96=87=E6=A1=88?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E8=AF=AD=E9=9F=B3=E9=80=9A=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 同步完成后不再索取 SYSTEM_ALERT_WINDOW,去掉旧浮窗服务声明和定位权限/发送入口;历史位置消息仍只读展示。 Co-authored-by: Cursor Co-authored-by: multica-agent --- .../android/app/src/main/AndroidManifest.xml | 14 +- .../lib/core/controller/im_controller.dart | 5 - mobile-next/lib/pages/chat/chat_logic.dart | 23 -- mobile-next/lib/pages/chat/chat_view.dart | 1 - .../openim_common/lib/openim_common.dart | 1 - .../openim_common/lib/src/res/lang/en_US.dart | 12 +- .../openim_common/lib/src/res/lang/zh_CN.dart | 12 +- .../lib/src/utils/permissions.dart | 13 - .../openim_common/lib/src/utils/utils.dart | 19 +- .../openim_common/lib/src/widgets/button.dart | 2 +- .../lib/src/widgets/chat/chat_item_view.dart | 6 +- .../src/widgets/chat/chat_location_view.dart | 127 ++++++--- .../lib/src/widgets/chat/chat_toolbox.dart | 7 - .../src/widgets/chat/chat_webview_map.dart | 269 ------------------ .../lib/src/widgets/rich_text_input_box.dart | 13 +- .../openim_common/lib/src/widgets/views.dart | 11 - mobile-next/openim_common/pubspec.yaml | 1 - .../openim_live/lib/src/live_controller.dart | 8 - mobile-next/pubspec.lock | 48 ---- mobile-next/test/company/p1_cleanup_test.dart | 30 ++ 20 files changed, 143 insertions(+), 479 deletions(-) delete mode 100644 mobile-next/openim_common/lib/src/widgets/chat/chat_webview_map.dart create mode 100644 mobile-next/test/company/p1_cleanup_test.dart diff --git a/mobile-next/android/app/src/main/AndroidManifest.xml b/mobile-next/android/app/src/main/AndroidManifest.xml index 7420534..4ef292d 100644 --- a/mobile-next/android/app/src/main/AndroidManifest.xml +++ b/mobile-next/android/app/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ - + @@ -26,14 +26,14 @@ - - - + + + - + @@ -130,10 +130,6 @@ android:exported="false" android:stopWithTask="false" /> - - ? assets = await AssetPicker.pickAssets(Get.context!, pickerConfig: AssetPickerConfig( diff --git a/mobile-next/lib/pages/chat/chat_view.dart b/mobile-next/lib/pages/chat/chat_view.dart index 0cd84e2..fb1eaec 100644 --- a/mobile-next/lib/pages/chat/chat_view.dart +++ b/mobile-next/lib/pages/chat/chat_view.dart @@ -247,7 +247,6 @@ class ChatPage extends StatelessWidget { onTapCall: FeatureFlags.livekitCall && logic.isSingleChat ? logic.call : null, onTapCard: logic.onTapCarte, onTapFile: logic.onTapFile, - onTapLocation: logic.onTapLocation, ), voiceRecordBar: bar, emojiView: ChatEmojiView( diff --git a/mobile-next/openim_common/lib/openim_common.dart b/mobile-next/openim_common/lib/openim_common.dart index b10ba19..4ba0d20 100644 --- a/mobile-next/openim_common/lib/openim_common.dart +++ b/mobile-next/openim_common/lib/openim_common.dart @@ -76,7 +76,6 @@ export 'src/widgets/chat/chat_voice_record_bar.dart'; export 'src/widgets/chat/chat_voice_record_layout.dart'; export 'src/widgets/chat/chat_voice_record_view.dart'; export 'src/widgets/chat/chat_voice_view.dart'; -export 'src/widgets/chat/chat_webview_map.dart'; export 'src/widgets/chat/new_message_indicator.dart'; export 'src/widgets/chat/water_mark_view.dart'; export 'src/widgets/custom_pop_up_menu.dart'; diff --git a/mobile-next/openim_common/lib/src/res/lang/en_US.dart b/mobile-next/openim_common/lib/src/res/lang/en_US.dart index b7989a0..f5b8108 100644 --- a/mobile-next/openim_common/lib/src/res/lang/en_US.dart +++ b/mobile-next/openim_common/lib/src/res/lang/en_US.dart @@ -109,7 +109,7 @@ const Map en_US = { 'rejectCall': 'Reject', 'acceptCall': 'Accept', "callVoice": "Voice Call", - "callVideo": "Video Call", + "callVideo": "Voice Call", "sentSuccessfully": "Sent Successfully", "copySuccessfully": "Copied Successfully", "day": "day", @@ -120,7 +120,7 @@ const Map en_US = { "cancel": "Cancel", "determine": "OK", "toolboxAlbum": "Album", - "toolboxCall": "Video Call", + "toolboxCall": "Voice Call", "toolboxCamera": "Camera", "toolboxCard": "Card", "toolboxFile": "File", @@ -156,7 +156,7 @@ const Map en_US = { 'nMessage': '%s New Messages', 'plsSelectLocation': 'Please select a location', 'groupAudioCallHint': '%s people in a voice call', - 'groupVideoCallHint': '%s people in a video call', + 'groupVideoCallHint': '%s people in a voice call', 'reEdit': 'Re-edit', 'playSpeed': 'Playback Speed', 'download': 'Download', @@ -224,7 +224,7 @@ const Map en_US = { 'position': 'Position', 'personalInfo': 'Personal Info', 'viewDynamics': 'View Dynamics', - 'audioAndVideoCall': 'Call', + 'audioAndVideoCall': 'Voice Call', 'sendMessage': 'Message', 'avatar': 'Avatar', 'name': 'Name', @@ -436,7 +436,7 @@ const Map en_US = { "waitingVoiceCallHint": "Waiting for the other party to accept the invitation...", "invitedVoiceCallHint": "Inviting you to a voice call", "waitingVideoCallHint": "Waiting for the other party to accept the invitation", - "invitedVideoCallHint": "Inviting you for a video call...", + "invitedVideoCallHint": "Inviting you to a voice call", "waitingToAnswer": "Waiting to answer", "invitedYouToCall": "Invited you to a call", "calling": "Calling...", @@ -444,7 +444,7 @@ const Map en_US = { 'busyVideoCallHint': 'The other party is busy and cannot receive the invitation', 'inviterBusyVideoCallHint': 'You are in another call and cannot send an invitation', "whoInvitedVoiceCallHint": "%s invited you for a voice call", - "whoInvitedVideoCallHint": "%s invited you for a video call", + "whoInvitedVideoCallHint": "%s invited you for a voice call", 'plsInputMeetingSubject': 'Please enter meeting subject', 'meetingStartTime': 'Start Time', 'meetingDuration': 'Meeting Duration', diff --git a/mobile-next/openim_common/lib/src/res/lang/zh_CN.dart b/mobile-next/openim_common/lib/src/res/lang/zh_CN.dart index 011e3aa..69faafa 100644 --- a/mobile-next/openim_common/lib/src/res/lang/zh_CN.dart +++ b/mobile-next/openim_common/lib/src/res/lang/zh_CN.dart @@ -109,7 +109,7 @@ const Map zh_CN = { 'rejectCall': '拒绝', 'acceptCall': '同意', "callVoice": "语音通话", - "callVideo": "视频通话", + "callVideo": "语音通话", "sentSuccessfully": "发送成功", "copySuccessfully": "复制成功", "day": "天", @@ -120,7 +120,7 @@ const Map zh_CN = { "cancel": "取消", "determine": "确定", "toolboxAlbum": "相册", - "toolboxCall": "视频通话", + "toolboxCall": "语音通话", "toolboxCamera": "拍摄", "toolboxCard": "名片", "toolboxFile": "文件", @@ -156,7 +156,7 @@ const Map zh_CN = { 'nMessage': '%s条新消息', 'plsSelectLocation': '请选择一个位置', 'groupAudioCallHint': '%s人正在语音通话', - 'groupVideoCallHint': '%s人正在视频通话', + 'groupVideoCallHint': '%s人正在语音通话', 'reEdit': '重新编辑', 'playSpeed': '播放速度', 'download': '下载', @@ -224,7 +224,7 @@ const Map zh_CN = { 'position': '职位', 'personalInfo': '个人资料', 'viewDynamics': '查看动态', - 'audioAndVideoCall': '音视频通话', + 'audioAndVideoCall': '语音通话', 'sendMessage': '发消息', 'avatar': '头像', 'name': '姓名', @@ -438,7 +438,7 @@ const Map zh_CN = { "waitingVoiceCallHint": "正在等待对方接受邀请…", "invitedVoiceCallHint": "邀请你语音通话", "waitingVideoCallHint": "正在等待对方接受邀请", - "invitedVideoCallHint": "邀请你进行视频通话…", + "invitedVideoCallHint": "邀请你语音通话", "waitingToAnswer": "等待接听", "invitedYouToCall": "邀请你通话", "calling": "通话中", @@ -446,7 +446,7 @@ const Map zh_CN = { 'busyVideoCallHint': '对方正忙,无法接收邀请', 'inviterBusyVideoCallHint': '你在其它通话中,无法发起邀请', "whoInvitedVoiceCallHint": "%s邀请你进行语音通话", - "whoInvitedVideoCallHint": "%s邀请你进行视频通话", + "whoInvitedVideoCallHint": "%s邀请你进行语音通话", 'plsInputMeetingSubject': '请输入会议主题', 'meetingStartTime': '开始时间', 'meetingDuration': '会议时长', diff --git a/mobile-next/openim_common/lib/src/utils/permissions.dart b/mobile-next/openim_common/lib/src/utils/permissions.dart index 8f31cdc..86dd132 100644 --- a/mobile-next/openim_common/lib/src/utils/permissions.dart +++ b/mobile-next/openim_common/lib/src/utils/permissions.dart @@ -10,10 +10,6 @@ import 'package:sprintf/sprintf.dart'; class Permissions { Permissions._(); - static Future checkSystemAlertWindow() async { - return Permission.systemAlertWindow.isGranted; - } - static Future checkStorage() async { return await Permission.storage.isGranted; } @@ -66,15 +62,6 @@ class Permissions { } } - static void location(Function()? onGranted) async { - if (await Permission.location.request().isGranted) { - onGranted?.call(); - } - if (await Permission.location.isPermanentlyDenied || await Permission.location.isDenied) { - _showPermissionDeniedDialog(Permission.location.title); - } - } - static void speech(Function()? onGranted) async { if (await Permission.speech.request().isGranted) { onGranted?.call(); diff --git a/mobile-next/openim_common/lib/src/utils/utils.dart b/mobile-next/openim_common/lib/src/utils/utils.dart index ff87306..3ee524e 100644 --- a/mobile-next/openim_common/lib/src/utils/utils.dart +++ b/mobile-next/openim_common/lib/src/utils/utils.dart @@ -850,8 +850,7 @@ class IMUtils { var customData = map['data']; switch (customType) { case CustomMessageType.call: - var type = map['data']['type']; - content = '[${type == 'video' ? StrRes.callVideo : StrRes.callVoice}]'; + content = '[${StrRes.callVoice}]'; break; case CustomMessageType.emoji: content = '[${StrRes.emoji}]'; @@ -1326,15 +1325,19 @@ class IMUtils { } static void previewLocation(Message message) { - var location = message.locationElem; - Map detail = json.decode(location!.description!); + final location = message.locationElem; + if (location == null) { + IMViews.showToast(StrRes.location); + return; + } + final detail = LocationPreviewData.parse(location.description); Logger.print('previewLocation ${location.latitude} ${location.longitude}'); Get.to( () => MapView( - latitude: location.latitude!, - longitude: location.longitude!, - address1: detail['name'], - address2: detail['addr'], + latitude: location.latitude ?? 0, + longitude: location.longitude ?? 0, + address1: detail.name, + address2: detail.addr, ), transition: Transition.cupertino, popGesture: true, diff --git a/mobile-next/openim_common/lib/src/widgets/button.dart b/mobile-next/openim_common/lib/src/widgets/button.dart index 5a7f57b..3fce73d 100644 --- a/mobile-next/openim_common/lib/src/widgets/button.dart +++ b/mobile-next/openim_common/lib/src/widgets/button.dart @@ -78,7 +78,7 @@ class ImageTextButton extends StatelessWidget { final Function()? onTap; ImageTextButton.call({super.key, this.onTap}) - : icon = ImageRes.audioAndVideoCall, + : icon = ImageRes.callVoice, text = StrRes.audioAndVideoCall, color = Styles.c_FFFFFF, textStyle = null, diff --git a/mobile-next/openim_common/lib/src/widgets/chat/chat_item_view.dart b/mobile-next/openim_common/lib/src/widgets/chat/chat_item_view.dart index e3ebb94..a6c0b68 100644 --- a/mobile-next/openim_common/lib/src/widgets/chat/chat_item_view.dart +++ b/mobile-next/openim_common/lib/src/widgets/chat/chat_item_view.dart @@ -276,9 +276,9 @@ class _ChatItemViewState extends State { } else if (_message.isLocationType) { final location = _message.locationElem; child = ChatLocationView( - description: location!.description!, - latitude: location.latitude!, - longitude: location.longitude!, + description: location?.description ?? '', + latitude: location?.latitude ?? 0, + longitude: location?.longitude ?? 0, ); } else if (_message.isCardType) { child = ChatCarteView(cardElem: _message.cardElem!); diff --git a/mobile-next/openim_common/lib/src/widgets/chat/chat_location_view.dart b/mobile-next/openim_common/lib/src/widgets/chat/chat_location_view.dart index 8d5c7a0..f68b060 100644 --- a/mobile-next/openim_common/lib/src/widgets/chat/chat_location_view.dart +++ b/mobile-next/openim_common/lib/src/widgets/chat/chat_location_view.dart @@ -4,63 +4,96 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:openim_common/openim_common.dart'; +class LocationPreviewData { + const LocationPreviewData({ + required this.name, + required this.addr, + required this.url, + }); + + final String name; + final String addr; + final String url; + + static LocationPreviewData parse(String? description) { + var name = ''; + var addr = ''; + var url = ''; + try { + final raw = description?.trim() ?? ''; + if (raw.isNotEmpty) { + final decoded = json.decode(raw); + if (decoded is Map) { + url = '${decoded['url'] ?? ''}'; + name = '${decoded['name'] ?? ''}'; + addr = '${decoded['addr'] ?? ''}'; + } + } + } catch (_) {} + if (name.trim().isEmpty) { + name = StrRes.location; + } + return LocationPreviewData(name: name, addr: addr, url: url); + } +} + class ChatLocationView extends StatelessWidget { const ChatLocationView({ - Key? key, + super.key, required this.description, required this.latitude, required this.longitude, - }) : super(key: key); + }); final String description; final double latitude; final double longitude; - final _decoder = const JsonDecoder(); @override Widget build(BuildContext context) { - try { - final map = _decoder.convert(description); - String url = map['url'] ?? ''; - String name = map['name'] ?? ''; - String addr = map['addr'] ?? ''; - return Container( - width: locationWidth, - height: 130.h, - decoration: BoxDecoration( - color: Styles.c_FFFFFF, - border: Border.all(color: Styles.c_E8EAEF, width: 1), - borderRadius: BorderRadius.circular(6.r), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 4.verticalSpace, - Padding( - padding: EdgeInsets.symmetric(horizontal: 4.w), - child: name.toText - ..style = Styles.ts_0C1C33_14sp - ..maxLines = 1 - ..overflow = TextOverflow.ellipsis, - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 4.w), - child: addr.toText - ..style = Styles.ts_8E9AB0_12sp - ..maxLines = 1 - ..overflow = TextOverflow.ellipsis, - ), - 2.verticalSpace, - Expanded( - child: ImageUtil.networkImage( - url: url, - width: locationWidth, - fit: BoxFit.cover, - ), - ), - ], - ), - ); - } catch (e) {} - return Container(); + final data = LocationPreviewData.parse(description); + return Container( + width: locationWidth, + height: 130.h, + decoration: BoxDecoration( + color: Styles.c_FFFFFF, + border: Border.all(color: Styles.c_E8EAEF, width: 1), + borderRadius: BorderRadius.circular(6.r), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 4.verticalSpace, + Padding( + padding: EdgeInsets.symmetric(horizontal: 4.w), + child: data.name.toText + ..style = Styles.ts_0C1C33_14sp + ..maxLines = 1 + ..overflow = TextOverflow.ellipsis, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 4.w), + child: (data.addr.isEmpty ? StrRes.location : data.addr).toText + ..style = Styles.ts_8E9AB0_12sp + ..maxLines = 1 + ..overflow = TextOverflow.ellipsis, + ), + 2.verticalSpace, + Expanded( + child: data.url.isEmpty + ? ColoredBox( + color: Styles.c_F0F2F6, + child: Center( + child: StrRes.location.toText..style = Styles.ts_8E9AB0_12sp, + ), + ) + : ImageUtil.networkImage( + url: data.url, + width: locationWidth, + fit: BoxFit.cover, + ), + ), + ], + ), + ); } } diff --git a/mobile-next/openim_common/lib/src/widgets/chat/chat_toolbox.dart b/mobile-next/openim_common/lib/src/widgets/chat/chat_toolbox.dart index 8477f18..ff763ad 100644 --- a/mobile-next/openim_common/lib/src/widgets/chat/chat_toolbox.dart +++ b/mobile-next/openim_common/lib/src/widgets/chat/chat_toolbox.dart @@ -10,7 +10,6 @@ class ChatToolBox extends StatelessWidget { this.onTapCamera, this.onTapCard, this.onTapFile, - this.onTapLocation, this.onTapDirectionalMessage, }); final Function()? onTapAlbum; @@ -18,7 +17,6 @@ class ChatToolBox extends StatelessWidget { final Function()? onTapCall; final Function()? onTapFile; final Function()? onTapCard; - final Function()? onTapLocation; final VoidCallback? onTapDirectionalMessage; @override @@ -50,11 +48,6 @@ class ChatToolBox extends StatelessWidget { icon: ImageRes.toolboxCard, onTap: onTapCard, ), - ToolboxItemInfo( - text: StrRes.toolboxLocation, - icon: ImageRes.toolboxLocation, - onTap: () => Permissions.location(onTapLocation), - ), if (onTapDirectionalMessage != null) ToolboxItemInfo( text: StrRes.toolboxDirectionalMessage, diff --git a/mobile-next/openim_common/lib/src/widgets/chat/chat_webview_map.dart b/mobile-next/openim_common/lib/src/widgets/chat/chat_webview_map.dart deleted file mode 100644 index e441385..0000000 --- a/mobile-next/openim_common/lib/src/widgets/chat/chat_webview_map.dart +++ /dev/null @@ -1,269 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; -import 'package:openim_common/openim_common.dart'; -import 'package:geolocator/geolocator.dart'; -import 'package:webview_flutter/webview_flutter.dart'; - -import 'package:webview_flutter_android/webview_flutter_android.dart'; - -import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart'; - -class ChatWebViewMap extends StatefulWidget { - const ChatWebViewMap({ - super.key, - required this.host, - required this.webKey, - required this.webServerKey, - this.mapThumbnailSize = "1200*600", - this.mapBackUrl = "http://callback", - this.latitude, - this.longitude, - }); - - final String host; - final String webKey; - final String webServerKey; - final String mapThumbnailSize; - final String mapBackUrl; - final double? latitude; - final double? longitude; - - @override - State createState() => _ChatWebViewMapState(); -} - -class _ChatWebViewMapState extends State { - WebViewController? _controller; - - String url = ""; - double progress = 0; - double? latitude; - double? longitude; - String? description; - - late String locationUrl; - late String thumbnailUrl; - - late String previewLocationUrl; - - late String webKey; - late String webServerKey; - late String host; - - void _configUrl() { - locationUrl = "$host?key=$webKey&serverKey=$webServerKey#/"; - previewLocationUrl = "$host?key=$webKey&serverKey=$webServerKey&location=$longitude,$latitude#/"; - } - - String getStaticMapURL(double longitude, double latitude) { - final url = - 'https://restapi.amap.com/v3/staticmap?location=$longitude,$latitude&zoom=13&size=200*200&markers=mid,,A:$longitude,$latitude&key=$webServerKey'; - - return url; - } - - bool get isPreview => widget.longitude != null && widget.latitude != null; - - @override - void initState() { - super.initState(); - host = widget.host; - webKey = widget.webKey; - webServerKey = widget.webServerKey; - - longitude = widget.longitude; - latitude = widget.latitude; - - _determinePosition().then((position) { - longitude = position.longitude; - latitude = position.latitude; - - _configUrl(); - - late final PlatformWebViewControllerCreationParams params; - if (WebViewPlatform.instance is WebKitWebViewPlatform) { - params = WebKitWebViewControllerCreationParams( - allowsInlineMediaPlayback: true, - mediaTypesRequiringUserAction: const {}, - ); - } else { - params = const PlatformWebViewControllerCreationParams(); - } - - final WebViewController controller = WebViewController.fromPlatformCreationParams(params); - - controller - ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setNavigationDelegate( - NavigationDelegate( - onProgress: (int progress) { - debugPrint('WebView is loading (progress : $progress%)'); - setState(() { - this.progress = progress / 100; - }); - }, - onPageStarted: (String url) { - debugPrint('Page started loading: $url'); - }, - onPageFinished: (String url) { - debugPrint('Page finished loading: $url'); - }, - onWebResourceError: (WebResourceError error) { - debugPrint( - 'Page resource error: code: ${error.errorCode} description: ${error.description} errorType: ${error.errorType} isForMainFrame: ${error.isForMainFrame}'); - }, - onNavigationRequest: (NavigationRequest request) { - if (request.url.startsWith('https://www.youtube.com/')) { - debugPrint('blocking navigation to ${request.url}'); - return NavigationDecision.prevent; - } - debugPrint('allowing navigation to ${request.url}'); - return NavigationDecision.navigate; - }, - onHttpError: (HttpResponseError error) { - debugPrint('Error occurred on page: ${error.response?.statusCode}'); - }, - onUrlChange: (UrlChange change) { - debugPrint('url change to ${change.url}'); - }, - onHttpAuthRequest: (HttpAuthRequest request) {}, - ), - ) - ..addJavaScriptChannel( - 'getLocaltion', - onMessageReceived: (JavaScriptMessage message) { - final value = message.message; - final params = jsonDecode(value); - final locationStr = params['location'] as String; - final locations = locationStr.split(','); - longitude = double.parse(locations[0]); - latitude = double.parse(locations[1]); - final address = params['address']; - final url = getStaticMapURL(longitude!, latitude!); - - final result = { - 'longitude': longitude, - 'latitude': latitude, - 'url': url, - 'addr': address, - 'name': '', - }; - - description = jsonEncode(result); - Logger.print('$result'); - - _confirm(); - }, - ) - ..loadRequest(Uri.parse(previewLocationUrl)); - - print('previewLocationUrl: $previewLocationUrl'); - - if (!Platform.isMacOS) { - controller.setBackgroundColor(const Color(0x80000000)); - } - - if (controller.platform is AndroidWebViewController) { - AndroidWebViewController.enableDebugging(true); - - (controller.platform as AndroidWebViewController).setMediaPlaybackRequiresUserGesture(false); - } - - setState(() { - _controller = controller; - }); - }); - } - - Future _determinePosition() async { - bool serviceEnabled; - LocationPermission permission; - - serviceEnabled = await Geolocator.isLocationServiceEnabled(); - if (!serviceEnabled) { - return Future.error('Location services are disabled.'); - } - - permission = await Geolocator.checkPermission(); - if (permission == LocationPermission.denied) { - permission = await Geolocator.requestPermission(); - if (permission == LocationPermission.denied) { - return Future.error('Location permissions are denied'); - } - } - - if (permission == LocationPermission.deniedForever) { - return Future.error('Location permissions are permanently denied, we cannot request permissions.'); - } - - return await Geolocator.getCurrentPosition(); - } - - @override - void dispose() { - super.dispose(); - } - - void _confirm() async { - if (null == latitude || null == longitude) { - await showDialog( - context: context, - builder: (_) => AlertDialog( - title: StrRes.plsSelectLocation.toText..style = Styles.ts_0C1C33_17sp_semibold, - actions: [ - GestureDetector( - onTap: () => Navigator.pop(context), - behavior: HitTestBehavior.translucent, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 10.h), - child: StrRes.determine.toText..style = Styles.ts_0089FF_17sp_semibold, - ), - ), - ], - ), - ); - return; - } - Navigator.pop(context, { - 'latitude': latitude, - 'longitude': longitude, - 'description': description, - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - appBar: TitleBar.back( - onTap: () async { - Get.back(); - }, - title: StrRes.location, - ), - body: SafeArea( - child: Stack( - children: [ - _controller == null - ? const Align( - child: CupertinoActivityIndicator(), - ) - : WebViewWidget(controller: _controller!), - progress < 1.0 - ? LinearProgressIndicator( - value: progress, - color: Colors.blue, - ) - : const SizedBox(), - ], - ), - ), - ); - } -} diff --git a/mobile-next/openim_common/lib/src/widgets/rich_text_input_box.dart b/mobile-next/openim_common/lib/src/widgets/rich_text_input_box.dart index 41b6329..a9cac99 100644 --- a/mobile-next/openim_common/lib/src/widgets/rich_text_input_box.dart +++ b/mobile-next/openim_common/lib/src/widgets/rich_text_input_box.dart @@ -14,11 +14,9 @@ class RichTextInputBox extends StatefulWidget { this.showCameraIcon = true, this.showCardIcon = true, this.showFileIcon = true, - this.showLocationIcon = true, this.onTapAlbum, this.onTapCard, this.onTapFile, - this.onTapLocation, this.onSend, }) : super(key: key); final TextEditingController? controller; @@ -29,12 +27,10 @@ class RichTextInputBox extends StatefulWidget { final bool showCameraIcon; final bool showFileIcon; final bool showCardIcon; - final bool showLocationIcon; final Function()? onTapAlbum; final Function()? onTapCamera; final Function()? onTapFile; final Function()? onTapCard; - final Function()? onTapLocation; final Function()? onSend; @override @@ -113,19 +109,12 @@ class _RichTextInputBoxState extends State { ..height = 22.h ..opacity = _opacity ..onTap = widget.onTapCard, - if (widget.showLocationIcon) - ImageRes.toolboxLocation1.toImage - ..width = 16.w - ..height = 22.h - ..opacity = _opacity - ..onTap = widget.onTapLocation, ], ), if (widget.showAlbumIcon || widget.showCameraIcon || widget.showCardIcon || - widget.showFileIcon || - widget.showLocationIcon) + widget.showFileIcon) 15.verticalSpace, Row( children: [ diff --git a/mobile-next/openim_common/lib/src/widgets/views.dart b/mobile-next/openim_common/lib/src/widgets/views.dart index b799d31..6784b9a 100644 --- a/mobile-next/openim_common/lib/src/widgets/views.dart +++ b/mobile-next/openim_common/lib/src/widgets/views.dart @@ -72,12 +72,6 @@ class IMViews { alignment: MainAxisAlignment.start, onTap: () => onTapSheetItem.call(0), ), - SheetItem( - label: StrRes.callVideo, - icon: ImageRes.callVideo, - alignment: MainAxisAlignment.start, - onTap: () => onTapSheetItem.call(1), - ), ], ), ); @@ -96,11 +90,6 @@ class IMViews { icon: ImageRes.callVoice, onTap: () => onTapSheetItem.call(0), ), - SheetItem( - label: StrRes.callVideo, - icon: ImageRes.callVideo, - onTap: () => onTapSheetItem.call(1), - ), ], ), ); diff --git a/mobile-next/openim_common/pubspec.yaml b/mobile-next/openim_common/pubspec.yaml index f948224..39c1d7e 100644 --- a/mobile-next/openim_common/pubspec.yaml +++ b/mobile-next/openim_common/pubspec.yaml @@ -79,7 +79,6 @@ dependencies: flutter_map: ^6.0.1 ffmpeg_kit_flutter_full_gpl: 6.0.3 pull_to_refresh_new: ^2.0.5 - geolocator: ^12.0.0 fixnum: ^1.1.0 protobuf: ^3.0.0 intl: ^0.19.0 diff --git a/mobile-next/openim_live/lib/src/live_controller.dart b/mobile-next/openim_live/lib/src/live_controller.dart index 98dfc85..84362a8 100644 --- a/mobile-next/openim_live/lib/src/live_controller.dart +++ b/mobile-next/openim_live/lib/src/live_controller.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:io'; import 'package:collection/collection.dart'; import 'package:flutter/services.dart'; @@ -100,13 +99,6 @@ mixin OpenIMLive { final callType = mediaType == 'audio' ? CallType.audio : CallType.video; final callObj = sessionType == ConversationType.single ? CallObj.single : CallObj.group; - if (Platform.isAndroid && _isRunningBackground) { - _beCalledEvent = event; - if (await Permissions.checkSystemAlertWindow()) { - return; - } - } - _beCalledEvent = null; OpenIMLiveClient().start( Get.overlayContext!, callEventSubject: signalingSubject, diff --git a/mobile-next/pubspec.lock b/mobile-next/pubspec.lock index 19c072f..9c0526b 100644 --- a/mobile-next/pubspec.lock +++ b/mobile-next/pubspec.lock @@ -930,54 +930,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" - geolocator: - dependency: transitive - description: - name: geolocator - sha256: "149876cc5207a0f5daf4fdd3bfcf0a0f27258b3fe95108fa084f527ad0568f1b" - url: "https://pub.dev" - source: hosted - version: "12.0.0" - geolocator_android: - dependency: transitive - description: - name: geolocator_android - sha256: "7aefc530db47d90d0580b552df3242440a10fe60814496a979aa67aa98b1fd47" - url: "https://pub.dev" - source: hosted - version: "4.6.1" - geolocator_apple: - dependency: transitive - description: - name: geolocator_apple - sha256: c4ecead17985ede9634f21500072edfcb3dba0ef7b97f8d7bc556d2d722b3ba3 - url: "https://pub.dev" - source: hosted - version: "2.3.9" - geolocator_platform_interface: - dependency: transitive - description: - name: geolocator_platform_interface - sha256: "386ce3d9cce47838355000070b1d0b13efb5bc430f8ecda7e9238c8409ace012" - url: "https://pub.dev" - source: hosted - version: "4.2.4" - geolocator_web: - dependency: transitive - description: - name: geolocator_web - sha256: "2ed69328e05cd94e7eb48bb0535f5fc0c0c44d1c4fa1e9737267484d05c29b5e" - url: "https://pub.dev" - source: hosted - version: "4.1.1" - geolocator_windows: - dependency: transitive - description: - name: geolocator_windows - sha256: "53da08937d07c24b0d9952eb57a3b474e29aae2abf9dd717f7e1230995f13f0e" - url: "https://pub.dev" - source: hosted - version: "0.2.3" gesture_password_widget: dependency: "direct main" description: diff --git a/mobile-next/test/company/p1_cleanup_test.dart b/mobile-next/test/company/p1_cleanup_test.dart new file mode 100644 index 0000000..90c8356 --- /dev/null +++ b/mobile-next/test/company/p1_cleanup_test.dart @@ -0,0 +1,30 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:openim_common/src/res/lang/zh_CN.dart'; +import 'package:openim_common/src/widgets/chat/chat_location_view.dart'; + +void main() { + test('用户可见通话文案不再出现视频通话或音视频通话', () { + for (final entry in zh_CN.entries) { + expect(entry.value.contains('视频通话'), isFalse, reason: '${entry.key}=${entry.value}'); + expect(entry.value.contains('音视频通话'), isFalse, reason: '${entry.key}=${entry.value}'); + } + expect(zh_CN['toolboxCall'], '语音通话'); + expect(zh_CN['audioAndVideoCall'], '语音通话'); + expect(zh_CN['video'], '视频'); + }); + + test('历史位置描述损坏时仍能解析成只读占位,不抛异常', () { + final ok = LocationPreviewData.parse('{"url":"http://x","name":"公司门口","addr":"一楼大厅"}'); + expect(ok.name, '公司门口'); + expect(ok.addr, '一楼大厅'); + expect(ok.url, 'http://x'); + + expect(() => LocationPreviewData.parse('{not-json'), returnsNormally); + expect(() => LocationPreviewData.parse(null), returnsNormally); + expect(() => LocationPreviewData.parse(''), returnsNormally); + + final broken = LocationPreviewData.parse('{not-json'); + expect(broken.url, isEmpty); + expect(broken.name, isNotEmpty); + }); +}