fix: 只有录像的时候才请求麦克风权限

This commit is contained in:
Max 2025-12-03 11:29:41 +08:00
parent 35bf666511
commit 4377369230
2 changed files with 133 additions and 60 deletions

View File

@ -72,7 +72,8 @@ class MorePanelItem {
final Widget icon; final Widget icon;
final Function(BuildContext context)? onTap; final Function(BuildContext context)? onTap;
MorePanelItem({this.onTap, required this.icon, required this.id, required this.title}); MorePanelItem(
{this.onTap, required this.icon, required this.id, required this.title});
} }
class MorePanel extends StatefulWidget { class MorePanel extends StatefulWidget {
@ -99,7 +100,8 @@ class MorePanel extends StatefulWidget {
class _MorePanelState extends TIMUIKitState<MorePanel> { class _MorePanelState extends TIMUIKitState<MorePanel> {
final ImagePicker _picker = ImagePicker(); final ImagePicker _picker = ImagePicker();
final TUISelfInfoViewModel _selfInfoViewModel = serviceLocator<TUISelfInfoViewModel>(); final TUISelfInfoViewModel _selfInfoViewModel =
serviceLocator<TUISelfInfoViewModel>();
Uint8List? fileContent; Uint8List? fileContent;
String? fileName; String? fileName;
File? tempFile; File? tempFile;
@ -120,7 +122,8 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
isInstallCallkit = value; isInstallCallkit = value;
}); });
}); });
_betterPlayerController = BetterPlayerController(const BetterPlayerConfiguration()); _betterPlayerController =
BetterPlayerController(const BetterPlayerConfiguration());
} }
} }
@ -205,12 +208,12 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
colorFilter: const ColorFilter.mode( colorFilter: const ColorFilter.mode(
Color(0xFF606060), BlendMode.srcIn), Color(0xFF606060), BlendMode.srcIn),
), ),
// Image.asset( // Image.asset(
// "images/take_video.png", // "images/take_video.png",
// package: 'tencent_cloud_chat_uikit', // package: 'tencent_cloud_chat_uikit',
// height: 64, // height: 64,
// width: 64, // width: 64,
// ), // ),
), ),
)), )),
if (PlatformUtils().isWeb) if (PlatformUtils().isWeb)
@ -387,9 +390,11 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
}).toList(); }).toList();
} }
_sendVideoMessage(String originFilePath, int duration, int size, TUIChatSeparateViewModel model) async { _sendVideoMessage(String originFilePath, int duration, int size,
TUIChatSeparateViewModel model) async {
if (size >= MorePanelConfig.VIDEO_MAX_SIZE) { if (size >= MorePanelConfig.VIDEO_MAX_SIZE) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制")));
return; return;
} }
@ -398,7 +403,9 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
final convID = widget.conversationID; final convID = widget.conversationID;
final convType = widget.conversationType; final convType = widget.conversationType;
String tempPath = (await getTemporaryDirectory()).path + p.basename(originFilePath) + ".jpeg"; String tempPath = (await getTemporaryDirectory()).path +
p.basename(originFilePath) +
".jpeg";
await plugin.getVideoThumbnail( await plugin.getVideoThumbnail(
srcFile: originFilePath, srcFile: originFilePath,
@ -410,7 +417,11 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
); );
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendVideoMessage( model.sendVideoMessage(
videoPath: originFilePath, duration: duration, snapshotPath: tempPath, convID: convID, convType: convType), videoPath: originFilePath,
duration: duration,
snapshotPath: tempPath,
convID: convID,
convType: convType),
context); context);
} }
@ -480,34 +491,47 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
if (filePath != null) { if (filePath != null) {
if (type == AssetType.image) { if (type == AssetType.image) {
if (size >= MorePanelConfig.IMAGE_MAX_SIZE) { if (size >= MorePanelConfig.IMAGE_MAX_SIZE) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("文件大小超出了限制")));
return; return;
} }
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendImageMessage(imagePath: filePath, convID: convID, convType: convType), context); model.sendImageMessage(
imagePath: filePath,
convID: convID,
convType: convType),
context);
} }
if (type == AssetType.video) { if (type == AssetType.video) {
_sendVideoMessage(originFile!.path, asset.videoDuration.inSeconds, size, model); _sendVideoMessage(originFile!.path,
asset.videoDuration.inSeconds, size, model);
} }
} }
} }
} }
} else { } else {
FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.media); FilePickerResult? result =
await FilePicker.platform.pickFiles(type: FileType.media);
if (result != null && result.files.isNotEmpty) { if (result != null && result.files.isNotEmpty) {
File file = File(result.files.single.path!); File file = File(result.files.single.path!);
final String savePath = file.path; final String savePath = file.path;
final String type = final String type = TencentUtils.getFileType(
TencentUtils.getFileType(savePath.split(".")[savePath.split(".").length - 1]).split("/")[0]; savePath.split(".")[savePath.split(".").length - 1])
.split("/")[0];
if (type == "image") { if (type == "image") {
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendImageMessage(imagePath: savePath, convID: convID, convType: convType), context); model.sendImageMessage(
imagePath: savePath, convID: convID, convType: convType),
context);
} else if (type == "video") { } else if (type == "video") {
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendVideoMessage(videoPath: savePath, convID: convID, convType: convType), context); model.sendVideoMessage(
videoPath: savePath, convID: convID, convType: convType),
context);
} }
} else { } else {
throw TypeError(); throw TypeError();
@ -518,7 +542,8 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
} }
} }
_sendImageFromCamera(TUIChatSeparateViewModel model, TUITheme theme, {required isVideo}) async { _sendImageFromCamera(TUIChatSeparateViewModel model, TUITheme theme,
{required isVideo}) async {
try { try {
if (!await Permissions.checkPermission( if (!await Permissions.checkPermission(
context, context,
@ -527,11 +552,17 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
)) { )) {
return; return;
} }
await Permissions.checkPermission(
context, //
Permission.microphone.value, if (isVideo) {
theme, if (!await Permissions.checkPermission(
); context,
Permission.microphone.value,
theme,
)) {
return;
}
}
final convID = widget.conversationID; final convID = widget.conversationID;
final convType = widget.conversationType; final convType = widget.conversationType;
@ -545,18 +576,25 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
final size = await originFile!.length(); final size = await originFile!.length();
if (!isVideo) { if (!isVideo) {
if (size >= MorePanelConfig.IMAGE_MAX_SIZE) { if (size >= MorePanelConfig.IMAGE_MAX_SIZE) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("文件大小超出了限制")));
return; return;
} }
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendImageMessage(imagePath: originFile.path, convID: convID, convType: convType), context); model.sendImageMessage(
imagePath: originFile.path, convID: convID, convType: convType),
context);
} else { } else {
// //
_betterPlayerController.addEventsListener((event) { _betterPlayerController.addEventsListener((event) {
if (event.betterPlayerEventType == BetterPlayerEventType.initialized) { if (event.betterPlayerEventType ==
BetterPlayerEventType.initialized) {
// //
int durationInSeconds = _betterPlayerController.videoPlayerController?.value.duration?.inSeconds ?? 0; int durationInSeconds = _betterPlayerController
.videoPlayerController?.value.duration?.inSeconds ??
0;
_sendVideoMessage(originFile!.path, durationInSeconds, size, model); _sendVideoMessage(originFile!.path, durationInSeconds, size, model);
} }
}); });
@ -583,12 +621,17 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
fileContent = imageContent; fileContent = imageContent;
html.Node? inputElem; html.Node? inputElem;
inputElem = html.document.getElementById("__image_picker_web-file-input")?.querySelector("input"); inputElem = html.document
.getElementById("__image_picker_web-file-input")
?.querySelector("input");
final convID = widget.conversationID; final convID = widget.conversationID;
final convType = widget.conversationType; final convType = widget.conversationType;
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendImageMessage( model.sendImageMessage(
inputElement: inputElem, imagePath: tempFile?.path, convID: convID, convType: convType), inputElement: inputElem,
imagePath: tempFile?.path,
convID: convID,
convType: convType),
context); context);
} catch (e) { } catch (e) {
outputLogger.i("_sendFileErr: ${e.toString()}"); outputLogger.i("_sendFileErr: ${e.toString()}");
@ -604,18 +647,25 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
fileContent = videoContent; fileContent = videoContent;
if (fileName!.split(".")[fileName!.split(".").length - 1] != "mp4") { if (fileName!.split(".")[fileName!.split(".").length - 1] != "mp4") {
onTIMCallback( onTIMCallback(TIMCallback(
TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频消息仅限 mp4 格式"), infoCode: 6660412)); type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频消息仅限 mp4 格式"),
infoCode: 6660412));
return; return;
} }
html.Node? inputElem; html.Node? inputElem;
inputElem = html.document.getElementById("__image_picker_web-file-input")?.querySelector("input"); inputElem = html.document
.getElementById("__image_picker_web-file-input")
?.querySelector("input");
final convID = widget.conversationID; final convID = widget.conversationID;
final convType = widget.conversationType; final convType = widget.conversationType;
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendVideoMessage( model.sendVideoMessage(
inputElement: inputElem, videoPath: tempFile?.path, convID: convID, convType: convType), inputElement: inputElem,
videoPath: tempFile?.path,
convID: convID,
convType: convType),
context); context);
} catch (e) { } catch (e) {
outputLogger.i("_sendFileErr: ${e.toString()}"); outputLogger.i("_sendFileErr: ${e.toString()}");
@ -633,29 +683,43 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
if (result != null && result.files.isNotEmpty) { if (result != null && result.files.isNotEmpty) {
if (PlatformUtils().isWeb) { if (PlatformUtils().isWeb) {
html.Node? inputElem; html.Node? inputElem;
inputElem = html.document.getElementById("__file_picker_web-file-input")?.querySelector("input"); inputElem = html.document
.getElementById("__file_picker_web-file-input")
?.querySelector("input");
fileName = result.files.single.name; fileName = result.files.single.name;
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendFileMessage(inputElement: inputElem, fileName: fileName, convID: convID, convType: convType), model.sendFileMessage(
inputElement: inputElem,
fileName: fileName,
convID: convID,
convType: convType),
context); context);
return; return;
} }
String? option2 = result.files.single.path ?? ""; String? option2 = result.files.single.path ?? "";
outputLogger.i(TIM_t_para("选择成功{{option2}}", "选择成功$option2")(option2: option2)); outputLogger
.i(TIM_t_para("选择成功{{option2}}", "选择成功$option2")(option2: option2));
File file = File(result.files.single.path!); File file = File(result.files.single.path!);
final int size = file.lengthSync(); final int size = file.lengthSync();
if (size >= MorePanelConfig.FILE_MAX_SIZE) { if (size >= MorePanelConfig.FILE_MAX_SIZE) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("文件大小超出了限制")));
return; return;
} }
final String savePath = file.path; final String savePath = file.path;
MessageUtils.handleMessageError( MessageUtils.handleMessageError(
model.sendFileMessage(filePath: savePath, size: size, convID: convID, convType: convType), context); model.sendFileMessage(
filePath: savePath,
size: size,
convID: convID,
convType: convType),
context);
} else { } else {
throw TypeError(); throw TypeError();
} }
@ -705,13 +769,16 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
bool hasCameraPermission = false; bool hasCameraPermission = false;
bool hasMicrophonePermission = false; bool hasMicrophonePermission = false;
if (type == TYPE_VIDEO) { if (type == TYPE_VIDEO) {
hasCameraPermission = await Permissions.checkPermission(context, Permission.camera.value); hasCameraPermission =
hasMicrophonePermission = await Permissions.checkPermission(context, Permission.microphone.value); await Permissions.checkPermission(context, Permission.camera.value);
hasMicrophonePermission = await Permissions.checkPermission(
context, Permission.microphone.value);
if (!hasCameraPermission || !hasMicrophonePermission) { if (!hasCameraPermission || !hasMicrophonePermission) {
return; return;
} }
} else { } else {
hasMicrophonePermission = await Permissions.checkPermission(context, Permission.microphone.value); hasMicrophonePermission = await Permissions.checkPermission(
context, Permission.microphone.value);
if (!hasMicrophonePermission) { if (!hasMicrophonePermission) {
return; return;
} }
@ -733,7 +800,9 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
_tUICore.callService(TUICALLKIT_SERVICE_NAME, METHOD_NAME_CALL, { _tUICore.callService(TUICALLKIT_SERVICE_NAME, METHOD_NAME_CALL, {
PARAM_NAME_TYPE: type, PARAM_NAME_TYPE: type,
PARAM_NAME_USERIDS: inviteMember, PARAM_NAME_USERIDS: inviteMember,
PARAM_NAME_GROUPID: widget.conversationType == ConvType.group ? widget.conversationID : "" PARAM_NAME_GROUPID: widget.conversationType == ConvType.group
? widget.conversationID
: ""
}); });
} }
} else { } else {
@ -754,7 +823,8 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
@override @override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final TUITheme theme = value.theme; final TUITheme theme = value.theme;
final TUIChatSeparateViewModel model = Provider.of<TUIChatSeparateViewModel>(context); final TUIChatSeparateViewModel model =
Provider.of<TUIChatSeparateViewModel>(context);
final screenWidth = MediaQuery.of(context).size.width; final screenWidth = MediaQuery.of(context).size.width;
final items = itemList(model, theme); final items = itemList(model, theme);
final double panelHeight = items.length > 4 ? 248.0 : 120; final double panelHeight = items.length > 4 ? 248.0 : 120;
@ -798,12 +868,15 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
height: 64, height: 64,
width: 64, width: 64,
margin: const EdgeInsets.only(bottom: 4), margin: const EdgeInsets.only(bottom: 4),
decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(5))), decoration: const BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(5))),
child: item.icon, child: item.icon,
), ),
Text( Text(
item.title, item.title,
style: TextStyle(fontSize: 12, color: theme.darkTextColor), style: TextStyle(
fontSize: 12, color: theme.darkTextColor),
) )
], ],
), ),

View File

@ -964,18 +964,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "8.3.0" version: "9.0.0"
package_info_plus_platform_interface: package_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: package_info_plus_platform_interface name: package_info_plus_platform_interface
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.2.0" version: "3.2.1"
pasteboard: pasteboard:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1577,10 +1577,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.4" version: "2.2.0"
video_player: video_player:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1633,18 +1633,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: wakelock_plus name: wakelock_plus
sha256: a474e314c3e8fb5adef1f9ae2d247e57467ad557fa7483a2b895bc1b421c5678 sha256: "9296d40c9adbedaba95d1e704f4e0b434be446e2792948d0e4aa977048104228"
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.3.2" version: "1.4.0"
wakelock_plus_platform_interface: wakelock_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: wakelock_plus_platform_interface name: wakelock_plus_platform_interface
sha256: e10444072e50dbc4999d7316fd303f7ea53d31c824aa5eb05d7ccbdd98985207 sha256: "036deb14cd62f558ca3b73006d52ce049fabcdcb2eddfe0bf0fe4e8a943b5cf2"
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.3" version: "1.3.0"
watcher: watcher:
dependency: transitive dependency: transitive
description: description: