修改聊天UI

This commit is contained in:
CYH 2023-06-19 18:20:14 +08:00
parent 78088f2682
commit c5b1140d1a
17 changed files with 479 additions and 292 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -3,6 +3,8 @@ PODS:
- Flutter - Flutter
- camera_avfoundation (0.0.1): - camera_avfoundation (0.0.1):
- Flutter - Flutter
- device_info (0.0.1):
- Flutter
- device_info_plus (0.0.1): - device_info_plus (0.0.1):
- Flutter - Flutter
- disk_space (0.0.1): - disk_space (0.0.1):
@ -129,10 +131,13 @@ PODS:
- Flutter - Flutter
- wakelock (0.0.1): - wakelock (0.0.1):
- Flutter - Flutter
- webview_flutter_wkwebview (0.0.1):
- Flutter
DEPENDENCIES: DEPENDENCIES:
- audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`)
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`) - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
- device_info (from `.symlinks/plugins/device_info/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- disk_space (from `.symlinks/plugins/disk_space/ios`) - disk_space (from `.symlinks/plugins/disk_space/ios`)
- fc_native_video_thumbnail_for_us (from `.symlinks/plugins/fc_native_video_thumbnail_for_us/ios`) - fc_native_video_thumbnail_for_us (from `.symlinks/plugins/fc_native_video_thumbnail_for_us/ios`)
@ -156,6 +161,7 @@ DEPENDENCIES:
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`) - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`) - wakelock (from `.symlinks/plugins/wakelock/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
@ -178,6 +184,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/audioplayers_darwin/ios" :path: ".symlinks/plugins/audioplayers_darwin/ios"
camera_avfoundation: camera_avfoundation:
:path: ".symlinks/plugins/camera_avfoundation/ios" :path: ".symlinks/plugins/camera_avfoundation/ios"
device_info:
:path: ".symlinks/plugins/device_info/ios"
device_info_plus: device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios" :path: ".symlinks/plugins/device_info_plus/ios"
disk_space: disk_space:
@ -224,10 +232,13 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/video_player_avfoundation/ios" :path: ".symlinks/plugins/video_player_avfoundation/ios"
wakelock: wakelock:
:path: ".symlinks/plugins/wakelock/ios" :path: ".symlinks/plugins/wakelock/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS: SPEC CHECKSUMS:
audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40
camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
disk_space: e94d34bbdf77954adfb39e60bde9cc5c7233eda6 disk_space: e94d34bbdf77954adfb39e60bde9cc5c7233eda6
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
@ -264,6 +275,7 @@ SPEC CHECKSUMS:
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126 video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
PODFILE CHECKSUM: 9f3fe3e871b4a811f0f2f55cc60906d65b3d629e PODFILE CHECKSUM: 9f3fe3e871b4a811f0f2f55cc60906d65b3d629e

View File

@ -2,7 +2,7 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>Microphone Usage Description</key> <key>NSMicrophoneUsageDescription</key>
<string>应用想要访问您的麦克风,用于发送语音</string> <string>应用想要访问您的麦克风,用于发送语音</string>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>应用想要访问您的相机,用于设置头像/动态发布</string> <string>应用想要访问您的相机,用于设置头像/动态发布</string>

View File

@ -16,7 +16,7 @@ import 'package:tencent_cloud_chat_uikit/ui/utils/permission.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/sound_record.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/sound_record.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
class SendSoundMessage extends StatefulWidget { class TIMSendSoundMessage extends StatefulWidget {
/// conversation ID /// conversation ID
final String conversationID; final String conversationID;
@ -26,7 +26,7 @@ class SendSoundMessage extends StatefulWidget {
/// the conversation type /// the conversation type
final ConvType conversationType; final ConvType conversationType;
const SendSoundMessage( const TIMSendSoundMessage(
{required this.conversationID, {required this.conversationID,
required this.conversationType, required this.conversationType,
Key? key, Key? key,
@ -34,10 +34,10 @@ class SendSoundMessage extends StatefulWidget {
: super(key: key); : super(key: key);
@override @override
State<StatefulWidget> createState() => _SendSoundMessageState(); State<StatefulWidget> createState() => _TIMSendSoundMessageState();
} }
class _SendSoundMessageState extends TIMUIKitState<SendSoundMessage> { class _TIMSendSoundMessageState extends TIMUIKitState<TIMSendSoundMessage> {
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>(); final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
String soundTipsText = ""; String soundTipsText = "";
bool isRecording = false; bool isRecording = false;
@ -68,7 +68,8 @@ class _SendSoundMessageState extends TIMUIKitState<SendSoundMessage> {
width: 160, width: 160,
height: 160, height: 160,
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Color(0xff77797A), color: Colors.transparent,
// color: Color(0xff77797A),
borderRadius: BorderRadius.all(Radius.circular(20.0)), borderRadius: BorderRadius.all(Radius.circular(20.0)),
), ),
child: Column( child: Column(

View File

@ -1,5 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:circle_app/app/chat/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart';
import 'package:circle_app/util/util.dart';
import 'package:diff_match_patch/diff_match_patch.dart'; import 'package:diff_match_patch/diff_match_patch.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
@ -23,24 +25,10 @@ import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField
enum MuteStatus { none, me, all } enum MuteStatus { none, me, all }
typedef CustomStickerPanel = Widget Function({
void Function() sendTextMessage,
void Function(int index, String data) sendFaceMessage,
void Function() deleteText,
void Function(int unicode) addText,
void Function(String singleEmojiName) addCustomEmojiText,
List<CustomEmojiFaceData> defaultCustomEmojiStickerList,
/// If non-null, requires the child to have exactly this width. GlobalKey<_InputTextFieldState> myInputTextFieldState = GlobalKey();
double? width,
/// If non-null, requires the child to have exactly this height. class TIMInputTextField extends StatefulWidget {
double? height,
});
GlobalKey<_InputTextFieldState> inputTextFieldState = GlobalKey();
class TIMUIKitInputTextField extends StatefulWidget {
/// conversation id /// conversation id
final String conversationID; final String conversationID;
@ -95,7 +83,7 @@ class TIMUIKitInputTextField extends StatefulWidget {
final String? groupType; final String? groupType;
const TIMUIKitInputTextField( const TIMInputTextField(
{Key? key, {Key? key,
required this.conversationID, required this.conversationID,
required this.conversationType, required this.conversationType,
@ -122,7 +110,7 @@ class TIMUIKitInputTextField extends StatefulWidget {
State<StatefulWidget> createState() => _InputTextFieldState(); State<StatefulWidget> createState() => _InputTextFieldState();
} }
class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> { class _InputTextFieldState extends TIMUIKitState<TIMInputTextField> {
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>(); final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
final TUISettingModel settingModel = serviceLocator<TUISettingModel>(); final TUISettingModel settingModel = serviceLocator<TUISettingModel>();
final RegExp atTextReg = RegExp(r'@([^@\s]*)'); final RegExp atTextReg = RegExp(r'@([^@\s]*)');
@ -297,8 +285,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
goDownBottom(); goDownBottom();
_handleSendEditStatus("", false); _handleSendEditStatus("", false);
} else {
showToast('请输入消息内容');
} }
} }
void goDownBottom() { void goDownBottom() {
if (globalModel.getMessageListPosition(widget.conversationID) == if (globalModel.getMessageListPosition(widget.conversationID) ==
@ -647,7 +637,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
} }
@override @override
void didUpdateWidget(TIMUIKitInputTextField oldWidget) { void didUpdateWidget(TIMInputTextField oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (widget.conversationID != oldWidget.conversationID) { if (widget.conversationID != oldWidget.conversationID) {
handleSetDraftText(oldWidget.conversationID, oldWidget.conversationType); handleSetDraftText(oldWidget.conversationID, oldWidget.conversationType);
@ -763,7 +753,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
builder: (BuildContext context, BoxConstraints constraints) { builder: (BuildContext context, BoxConstraints constraints) {
inputWidth = constraints.maxWidth; inputWidth = constraints.maxWidth;
return TUIKitScreenUtils.getDeviceWidget( return TUIKitScreenUtils.getDeviceWidget(
defaultWidget: TIMUIKitTextFieldLayoutNarrow( defaultWidget: TIMTextFieldLayoutNarrow(
onEmojiSubmitted: onEmojiSubmitted, onEmojiSubmitted: onEmojiSubmitted,
onCustomEmojiFaceSubmitted: onCustomEmojiFaceSubmitted, onCustomEmojiFaceSubmitted: onCustomEmojiFaceSubmitted,
backSpaceText: backSpaceText, backSpaceText: backSpaceText,
@ -793,7 +783,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
handleSoftKeyBoardDelete: _handleSoftKeyBoardDelete, handleSoftKeyBoardDelete: _handleSoftKeyBoardDelete,
onSubmitted: onSubmitted, onSubmitted: onSubmitted,
goDownBottom: goDownBottom, goDownBottom: goDownBottom,
showSendAudio: widget.showSendAudio, showSendAudio: false,
showSendEmoji: widget.showSendEmoji, showSendEmoji: widget.showSendEmoji,
showMorePanel: widget.showMorePanel, showMorePanel: widget.showMorePanel,
customEmojiStickerList: widget.customEmojiStickerList), customEmojiStickerList: widget.customEmojiStickerList),

View File

@ -1,8 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:circle_app/app/chat/TIMUIKitChat/TIMUIKitTextField/tim_uikit_send_sound_message.dart';
import 'package:circle_app/util/util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:image_picker/image_picker.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';
@ -20,9 +26,9 @@ import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField
import 'package:tencent_extended_text_field/extended_text_field.dart'; import 'package:tencent_extended_text_field/extended_text_field.dart';
import 'package:tencent_keyboard_visibility/tencent_keyboard_visibility.dart'; import 'package:tencent_keyboard_visibility/tencent_keyboard_visibility.dart';
GlobalKey<_TIMUIKitTextFieldLayoutNarrowState> narrowTextFieldKey = GlobalKey(); GlobalKey<_TIMTextFieldLayoutNarrowState> TIMnarrowTextFieldKey = GlobalKey();
class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget { class TIMTextFieldLayoutNarrow extends StatefulWidget {
/// sticker panel customization /// sticker panel customization
final CustomStickerPanel? customStickerPanel; final CustomStickerPanel? customStickerPanel;
@ -93,7 +99,7 @@ class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget {
final List customEmojiStickerList; final List customEmojiStickerList;
const TIMUIKitTextFieldLayoutNarrow( const TIMTextFieldLayoutNarrow(
{Key? key, {Key? key,
this.customStickerPanel, this.customStickerPanel,
required this.onEmojiSubmitted, required this.onEmojiSubmitted,
@ -129,13 +135,14 @@ class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget {
: super(key: key); : super(key: key);
@override @override
State<TIMUIKitTextFieldLayoutNarrow> createState() => State<TIMTextFieldLayoutNarrow> createState() =>
_TIMUIKitTextFieldLayoutNarrowState(); _TIMTextFieldLayoutNarrowState();
} }
class _TIMUIKitTextFieldLayoutNarrowState class _TIMTextFieldLayoutNarrowState
extends TIMUIKitState<TIMUIKitTextFieldLayoutNarrow> { extends TIMUIKitState<TIMTextFieldLayoutNarrow> {
final TUISettingModel settingModel = serviceLocator<TUISettingModel>(); final TUISettingModel settingModel = serviceLocator<TUISettingModel>();
final ImagePicker _picker = ImagePicker();
bool showMore = false; bool showMore = false;
bool showMoreButton = true; bool showMoreButton = true;
@ -256,7 +263,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
final height = originHeight != 0 ? originHeight : currentKeyboardHeight; final height = originHeight != 0 ? originHeight : currentKeyboardHeight;
return height; return height;
} else if (showMore || showEmojiPanel) { } else if (showMore || showEmojiPanel) {
return 248.0 + (bottomPadding ?? 0.0); return 268.0 + (bottomPadding ?? 0.0);
} else if (widget.textEditingController.text.length >= 46 && } else if (widget.textEditingController.text.length >= 46 &&
showKeyboard == false) { showKeyboard == false) {
return 25 + (bottomPadding ?? 0.0); return 25 + (bottomPadding ?? 0.0);
@ -388,14 +395,24 @@ class _TIMUIKitTextFieldLayoutNarrowState
return Column( return Column(
children: [ children: [
_buildRepliedMessage(widget.repliedMessage), _buildRepliedMessage(widget.repliedMessage),
Stack(
children: [
Container( Container(
color: widget.backgroundColor ?? hexToColor("f5f5f6"), decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(
16.sp,
),
topRight: Radius.circular(16.sp)),
color: Color(0xFF423055),
// color: Colors.yellow,
),
child: Column( child: Column(
children: [ children: [
Container( Container(
padding: padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 16), EdgeInsets.symmetric(vertical: 8, horizontal: 12.sp),
constraints: const BoxConstraints(minHeight: 50), constraints: const BoxConstraints(minHeight: 30),
child: Row( child: Row(
children: [ children: [
if (widget.forbiddenText != null) if (widget.forbiddenText != null)
@ -449,15 +466,35 @@ class _TIMUIKitTextFieldLayoutNarrowState
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),
Stack(
children: [
Container(
width: 296.sp,
padding: EdgeInsets.symmetric(
vertical: 8, horizontal: 12.sp),
constraints:
const BoxConstraints(minHeight: 30),
decoration: BoxDecoration(
color: Color(0x1AFFFFFF),
borderRadius: BorderRadius.circular(26.sp),
),
child: Row(
children: [
if (widget.forbiddenText == null) if (widget.forbiddenText == null)
Expanded( Expanded(
child: showSendSoundText child: showSendSoundText
? SendSoundMessage( ? TIMSendSoundMessage(
onDownBottom: widget.goDownBottom, onDownBottom:
conversationID: widget.conversationID, widget.goDownBottom,
conversationType: widget.conversationType) conversationID:
widget.conversationID,
conversationType:
widget.conversationType)
: KeyboardVisibility( : KeyboardVisibility(
child: ExtendedTextField( child: ExtendedTextField(
style: TextStyle(
color: Colors.white,
fontSize: 14.sp),
maxLines: 4, maxLines: 4,
minLines: 1, minLines: 1,
focusNode: widget.focusNode, focusNode: widget.focusNode,
@ -470,46 +507,63 @@ class _TIMUIKitTextFieldLayoutNarrowState
showMore = false; showMore = false;
}); });
}, },
keyboardType: TextInputType.multiline, keyboardType:
textInputAction: PlatformUtils().isAndroid TextInputType.multiline,
? TextInputAction.newline textInputAction:
: TextInputAction.send, PlatformUtils()
.isAndroid
? TextInputAction
.newline
: TextInputAction
.send,
onEditingComplete: () { onEditingComplete: () {
widget.onSubmitted(); widget.onSubmitted();
if (showKeyboard) { if (showKeyboard) {
widget.focusNode.requestFocus(); widget.focusNode
.requestFocus();
} }
setState(() { setState(() {
if (widget.textEditingController.text if (widget
.textEditingController
.text
.isEmpty) { .isEmpty) {
showMoreButton = true; showMoreButton = true;
} }
}); });
}, },
textAlignVertical: TextAlignVertical.top, textAlignVertical:
TextAlignVertical.top,
decoration: InputDecoration( decoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
hintStyle: const TextStyle( hintStyle: TextStyle(
// fontSize: 10, fontSize: 14.sp,
color: Color(0xffAEA4A3), color:
Color(0xB3FFFFFF),
), ),
fillColor: Colors.white, hintText: widget.hintText,
fillColor:
Colors.transparent,
filled: true, filled: true,
isDense: true, isDense: true,
hintText: widget.hintText ?? ''), ),
controller: widget.textEditingController, controller: widget
specialTextSpanBuilder: PlatformUtils() .textEditingController,
.isWeb specialTextSpanBuilder:
PlatformUtils().isWeb
? null ? null
: DefaultSpecialTextSpanBuilder( : DefaultSpecialTextSpanBuilder(
isUseDefaultEmoji: isUseDefaultEmoji:
widget.isUseDefaultEmoji, widget
.isUseDefaultEmoji,
customEmojiStickerList: customEmojiStickerList:
widget.customEmojiStickerList, widget
showAtBackground: true, .customEmojiStickerList,
showAtBackground:
true,
)), )),
onChanged: (bool visibility) { onChanged: (bool visibility) {
if (showKeyboard != visibility) { if (showKeyboard !=
visibility) {
setState(() { setState(() {
showKeyboard = visibility; showKeyboard = visibility;
}); });
@ -520,58 +574,29 @@ class _TIMUIKitTextFieldLayoutNarrowState
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),
if (widget.showSendEmoji && widget.forbiddenText == null) if (widget.showSendEmoji &&
widget.forbiddenText == null)
InkWell( InkWell(
onTap: () { onTap: () {
_openEmojiPanel(); _openEmojiPanel();
widget.goDownBottom(); widget.goDownBottom();
}, },
child: PlatformUtils().isWeb child: Image.asset(
? Icon( getMsgImage('emoji'),
showEmojiPanel height: 24.sp,
? Icons.keyboard_alt_outlined width: 24.sp,
: Icons.mood_outlined,
color: hexToColor("5c6168"),
size: 32)
: SvgPicture.asset(
showEmojiPanel
? 'images/keyboard.svg'
: 'images/face.svg',
package: 'tencent_cloud_chat_uikit',
color: const Color.fromRGBO(68, 68, 68, 1),
height: 28,
width: 28,
), ),
), ),
],
))
],
),
if (widget.forbiddenText == null) if (widget.forbiddenText == null)
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),
if (widget.showMorePanel &&
widget.forbiddenText == null &&
showMoreButton)
InkWell( InkWell(
onTap: () { onTap: () {
// model.sendCustomMessage(data: "a", convID: model.currentSelectedConv, convType: model.currentSelectedConvType == 1 ? ConvType.c2c : ConvType.group);
_openMore();
widget.goDownBottom();
},
child: PlatformUtils().isWeb
? Icon(Icons.add_circle_outline_outlined,
color: hexToColor("5c6168"), size: 32)
: SvgPicture.asset(
'images/add.svg',
package: 'tencent_cloud_chat_uikit',
color: const Color.fromRGBO(68, 68, 68, 1),
height: 28,
width: 28,
),
),
if ((isAndroidDevice() || isWebDevice()) && !showMoreButton)
SizedBox(
height: 32.0,
child: ElevatedButton(
onPressed: () {
widget.onSubmitted(); widget.onSubmitted();
if (showKeyboard) { if (showKeyboard) {
widget.focusNode.requestFocus(); widget.focusNode.requestFocus();
@ -582,30 +607,167 @@ class _TIMUIKitTextFieldLayoutNarrowState
} }
}); });
}, },
child: Text(TIM_t("发送")), child: Image.asset(
getMsgImage('send'),
height: 24.sp,
width: 24.sp,
), ),
), ),
], ],
), ),
), ),
Container(
height: 40.sp,
width: Get.width,
// color: Colors.red,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
GestureDetector(
onTap: () async {
showKeyboard = showSendSoundText;
if (showSendSoundText) {
widget.focusNode.requestFocus();
}
try {
var data = await Permission.microphone.status;
if (data.isGranted) {
setState(() {
showEmojiPanel = false;
showMore = false;
showSendSoundText = !showSendSoundText;
});
} else {
var data = await Permission.microphone.request();
if (data.isGranted) {
setState(() {
showEmojiPanel = false;
showMore = false;
showSendSoundText = !showSendSoundText;
});
} else {
Permissions.showPermissionConfirmDialog(context, Permission.microphone.value);
}
}
} catch (e) {
print(e);
}
},
child: Image.asset(
getMsgImage('voice'),
width: 40.sp,
),
),
GestureDetector(
onTap: () {
getImageFile();
},
child:
Image.asset(getMsgImage('photo'), width: 40.sp),
),
GestureDetector(
onTap: () {
getTakeImageFile();
},
child: Image.asset(getMsgImage('take_photo'),
width: 40.sp),
),
],
),
),
AnimatedContainer( AnimatedContainer(
duration: Duration( duration: Duration(
milliseconds: (showKeyboard && PlatformUtils().isAndroid) milliseconds:
(showKeyboard && PlatformUtils().isAndroid)
? 200 ? 200
: 340), : 340),
curve: Curves.fastOutSlowIn, curve: Curves.fastOutSlowIn,
height: max(_getBottomHeight(), 0.0), height: max(_getBottomHeight(), 0.0),
// child: ListView(
// physics: const NeverScrollableScrollPhysics(),
// children: [_getBottomContainer()],
// ),
),
],
),
),
Positioned(
bottom: MediaQuery.of(context).padding.bottom + 20,
child: AnimatedContainer(
duration: Duration(
milliseconds: (showKeyboard && PlatformUtils().isAndroid)
? 200
: 340),
curve: Curves.fastOutSlowIn,
width: Get.width,
height: max(_getBottomHeight(), 0.0),
child: ListView( child: ListView(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
children: [ children: [_getBottomContainer()],
_getBottomContainer() ),
),
)
], ],
),
),
],
),
) )
], ],
); );
} }
Future getImageFile() async {
try {
final XFile? pickedFile = await _picker.pickImage(
source: ImageSource.gallery,
);
await widget.model.sendImageMessage(
imagePath: pickedFile!.path,
convID: widget.conversationID,
convType: widget.conversationType,
inputElement: context);
} catch (e) {
print(e);
// setState(() {
// _pickImageError = e;
// });
}
}
Future getTakeImageFile() async {
try {
final XFile? pickedFile = await _picker.pickImage(
source: ImageSource.camera,
);
widget.model.sendImageMessage(
imagePath: pickedFile!.path,
convID: widget.conversationID,
convType: widget.conversationType,
inputElement: context);
} catch (e) {}
}
_handleCameraAndMic() async {
// //
// Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions(
// [PermissionGroup.camera, PermissionGroup.microphone],
// );
//
// //
// if (permissions[PermissionGroup.camera] != PermissionStatus.granted) {
// print("无照相权限");
// return false;
// }
// if (permissions[PermissionGroup.microphone] != PermissionStatus.granted) {
// print("无麦克风权限");
// return false;
// }
// return true;
// }
//
// void _onVoiceCall() async {
// // await for camera and mic permissions before pushing video page
// if (await _handleCameraAndMic()) {
// navigatePushPage(this.context,
// new PageAVChatCallerStatefulWidget(Int64(this.sessionInfo.sessionId), this.sessionInfo.sessionName));
// }
// }
}
} }

View File

@ -27,6 +27,8 @@ import 'TIMUIKItMessageList/tim_uikit_chat_history_message_list_config.dart';
import 'TIMUIKItMessageList/tim_uikit_history_message_list_container.dart'; import 'TIMUIKItMessageList/tim_uikit_history_message_list_container.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'TIMUIKitTextField/tim_uikit_text_field.dart';
class TIMChat extends StatefulWidget { class TIMChat extends StatefulWidget {
int startTime = 0; int startTime = 0;
int endTime = 0; int endTime = 0;
@ -465,7 +467,7 @@ class _TUIChatState extends TIMUIKitState<TIMChat> {
) )
: (widget.textFieldBuilder != null : (widget.textFieldBuilder != null
? widget.textFieldBuilder!(context) ? widget.textFieldBuilder!(context)
: TIMUIKitInputTextField( : TIMInputTextField(
key: inputTextFieldState, key: inputTextFieldState,
atMemberPanelScroll: atMemberPanelScroll:
atMemberPanelScroll, atMemberPanelScroll,
@ -486,8 +488,7 @@ class _TUIChatState extends TIMUIKitState<TIMChat> {
scrollController: autoController, scrollController: autoController,
conversationID: _getConvID(), conversationID: _getConvID(),
conversationType: _getConvType(), conversationType: _getConvType(),
initText: widget.draftText, hintText: '最近心情怎么样?',
hintText: widget.textFieldHintText,
showMorePanel: widget.config showMorePanel: widget.config
?.isAllowShowMorePanel ?? ?.isAllowShowMorePanel ??
true, true,

View File

@ -44,6 +44,8 @@ class ChatPage extends StatelessWidget {
)); ));
}).toList(); }).toList();
return StickerPanel( return StickerPanel(
backgroundColor:Colors.transparent,
showBottomContainer: false,
sendTextMsg: sendTextMessage, sendTextMsg: sendTextMessage,
sendFaceMsg: (index, data) => sendFaceMsg: (index, data) =>
sendFaceMessage(index + 1, (data.split("/")[3]).split("@")[0]), sendFaceMessage(index + 1, (data.split("/")[3]).split("@")[0]),
@ -69,7 +71,7 @@ class ChatPage extends StatelessWidget {
// 使 // 使
isAllowClickAvatar: true, isAllowClickAvatar: true,
isUseDefaultEmoji: true, isUseDefaultEmoji: true,
isAllowLongPressMessage: true, isAllowLongPressMessage: false,
isShowReadingStatus: true, isShowReadingStatus: true,
isShowGroupReadingStatus: true, isShowGroupReadingStatus: true,
notificationTitle: "", notificationTitle: "",

View File

@ -17,9 +17,11 @@ class CirclePage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.height,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color(0xFF423055),
image: DecorationImage( image: DecorationImage(
fit: BoxFit.fill, fit: BoxFit.fill,
image: AssetImage(getBaseImage('home_back')))), image: AssetImage(getBaseImage('home_back')))),

View File

@ -39,6 +39,7 @@ class HomePage extends StatelessWidget {
// color: Colors.red, // color: Colors.red,
padding: EdgeInsets.only(left: 50.sp, right: 50.sp, top: 8.sp), padding: EdgeInsets.only(left: 50.sp, right: 50.sp, top: 8.sp),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color(0xFF423055),
image: DecorationImage( image: DecorationImage(
fit: BoxFit.fill, fit: BoxFit.fill,
image: AssetImage( image: AssetImage(

View File

@ -21,11 +21,11 @@ class MsgPage extends StatelessWidget {
fit: BoxFit.fill, fit: BoxFit.fill,
image: AssetImage(getBaseImage('home_back')))), image: AssetImage(getBaseImage('home_back')))),
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset:false,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
body: SafeArea( body: SafeArea(
child: GetBuilder(builder: (MsgLogic controller) { child: GetBuilder(builder: (MsgLogic controller) {
return Container( return Column(
child: Column(
children: [ children: [
navigatorItem(), navigatorItem(),
tipWidget(), tipWidget(),
@ -33,7 +33,6 @@ class MsgPage extends StatelessWidget {
Text(controller.state.msg), Text(controller.state.msg),
Expanded(child: msgWdiget(context)) Expanded(child: msgWdiget(context))
], ],
),
); );
}), }),
), ),

View File

@ -24,56 +24,71 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> { class _MyAppState extends State<MyApp> {
// This widget is the root of your application. // This widget is the root of your application.
final List<String> _guideList = ['bg', 'home_back'];
final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance(); final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance();
@override @override
void initState() { void initState() {
initIM(); initIM();
loadBgImage();
super.initState(); super.initState();
} }
initIM() { initIM() {
_coreInstance.init( _coreInstance.init(
sdkAppID: 1400793496, // Replace 0 with the SDKAppID of your IM application when integrating sdkAppID:
1400793496, // Replace 0 with the SDKAppID of your IM application when integrating
// language: LanguageEnum.en, // // language: LanguageEnum.en, //
loglevel: LogLevelEnum.V2TIM_LOG_DEBUG, loglevel: LogLevelEnum.V2TIM_LOG_DEBUG,
onTUIKitCallbackListener: (TIMCallback callbackValue){ onTUIKitCallbackListener: (TIMCallback callbackValue) {
switch(callbackValue.type) { switch (callbackValue.type) {
case TIMCallbackType.INFO: case TIMCallbackType.INFO:
// Shows the recommend text for info callback directly // Shows the recommend text for info callback directly
showToast(callbackValue.infoRecommendText!); showToast(callbackValue.infoRecommendText!);
break; break;
case TIMCallbackType.API_ERROR: case TIMCallbackType.API_ERROR:
//Prints the API error to console, and shows the error message. //Prints the API error to console, and shows the error message.
print("Error from TUIKit: ${callbackValue.errorMsg}, Code: ${callbackValue.errorCode}"); print(
if (callbackValue.errorCode == 10004 && callbackValue.errorMsg!.contains("not support @all")) { "Error from TUIKit: ${callbackValue.errorMsg}, Code: ${callbackValue.errorCode}");
if (callbackValue.errorCode == 10004 &&
callbackValue.errorMsg!.contains("not support @all")) {
showToast("当前群组不支持@全体成员"); showToast("当前群组不支持@全体成员");
}else{ } else {
showToast(callbackValue.errorMsg ?? callbackValue.errorCode.toString()); showToast(callbackValue.errorMsg ??
callbackValue.errorCode.toString());
} }
break; break;
case TIMCallbackType.FLUTTER_ERROR: case TIMCallbackType.FLUTTER_ERROR:
default: default:
// prints the stack trace to console or shows the catch error // prints the stack trace to console or shows the catch error
if(callbackValue.catchError != null){ if (callbackValue.catchError != null) {
showToast(callbackValue.catchError.toString()); showToast(callbackValue.catchError.toString());
} else {
}else{
print(callbackValue.stackTrace); print(callbackValue.stackTrace);
// loginIM(); // loginIM();
} }
} }
}, // [](https://cloud.tencent.com/document/product/269/70746#callback) }, // [](https://cloud.tencent.com/document/product/269/70746#callback)
listener: V2TimSDKListener( listener: V2TimSDKListener(onConnectSuccess: () {
onConnectSuccess: () {
loginIM(); loginIM();
}));
} }
));
loadBgImage() async {
await precacheImage(precacheImages(_guideList.first),context);
await precacheImage(precacheImages(_guideList.last),context);
}
precacheImages(String image) {
return AssetImage(getBaseImage(image));
} }
loginIM() async { loginIM() async {
var info = await _coreInstance.login(userID: '123456', userSig: 'eJwtzEELgjAYxvHvsmshc25rCl40OlRIYaVX0RUvrTFsDFn03TP1*Pwe*H-Q5VgGTvYoQSTAaD1t6KS2cIeJQxJRxpfn3T0bY6BDSUgx3sQRjfn8yMFAL0dnjBGM8awWXn-jggtBY0qXCjzGcJ7tT4eVrHa6aG9FWfsms*rqK3cW2hulHKkHtzU2L9sUfX-YTTG5'); var info = await _coreInstance.login(
userID: '123456',
userSig:
'eJwtzEELgjAYxvHvsmshc25rCl40OlRIYaVX0RUvrTFsDFn03TP1*Pwe*H-Q5VgGTvYoQSTAaD1t6KS2cIeJQxJRxpfn3T0bY6BDSUgx3sQRjfn8yMFAL0dnjBGM8awWXn-jggtBY0qXCjzGcJ7tT4eVrHa6aG9FWfsms*rqK3cW2hulHKkHtzU2L9sUfX-YTTG5');
print(info); print(info);
} }
@override @override

View File

@ -60,10 +60,12 @@ dependencies:
dio: ^5.0.0 dio: ^5.0.0
#获取设备信息 #获取设备信息
device_info: ^2.0.3 device_info: ^2.0.3
#本地数据缓存
shared_preferences: ^2.1.2 shared_preferences: ^2.1.2
#集成腾讯IM包含UIKIT库
tencent_cloud_chat_uikit: ^2.0.0 tencent_cloud_chat_uikit: ^2.0.0
#权限申请
permission_handler: ^10.3.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: