修改聊天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
- camera_avfoundation (0.0.1):
- Flutter
- device_info (0.0.1):
- Flutter
- device_info_plus (0.0.1):
- Flutter
- disk_space (0.0.1):
@ -129,10 +131,13 @@ PODS:
- Flutter
- wakelock (0.0.1):
- Flutter
- webview_flutter_wkwebview (0.0.1):
- Flutter
DEPENDENCIES:
- audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/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`)
- disk_space (from `.symlinks/plugins/disk_space/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`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
SPEC REPOS:
trunk:
@ -178,6 +184,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/audioplayers_darwin/ios"
camera_avfoundation:
:path: ".symlinks/plugins/camera_avfoundation/ios"
device_info:
:path: ".symlinks/plugins/device_info/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
disk_space:
@ -224,10 +232,13 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/video_player_avfoundation/ios"
wakelock:
:path: ".symlinks/plugins/wakelock/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40
camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
disk_space: e94d34bbdf77954adfb39e60bde9cc5c7233eda6
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
@ -264,6 +275,7 @@ SPEC CHECKSUMS:
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
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">
<plist version="1.0">
<dict>
<key>Microphone Usage Description</key>
<key>NSMicrophoneUsageDescription</key>
<string>应用想要访问您的麦克风,用于发送语音</string>
<key>NSCameraUsageDescription</key>
<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/base_widgets/tim_ui_kit_base.dart';
class SendSoundMessage extends StatefulWidget {
class TIMSendSoundMessage extends StatefulWidget {
/// conversation ID
final String conversationID;
@ -26,7 +26,7 @@ class SendSoundMessage extends StatefulWidget {
/// the conversation type
final ConvType conversationType;
const SendSoundMessage(
const TIMSendSoundMessage(
{required this.conversationID,
required this.conversationType,
Key? key,
@ -34,10 +34,10 @@ class SendSoundMessage extends StatefulWidget {
: super(key: key);
@override
State<StatefulWidget> createState() => _SendSoundMessageState();
State<StatefulWidget> createState() => _TIMSendSoundMessageState();
}
class _SendSoundMessageState extends TIMUIKitState<SendSoundMessage> {
class _TIMSendSoundMessageState extends TIMUIKitState<TIMSendSoundMessage> {
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
String soundTipsText = "";
bool isRecording = false;
@ -68,7 +68,8 @@ class _SendSoundMessageState extends TIMUIKitState<SendSoundMessage> {
width: 160,
height: 160,
decoration: const BoxDecoration(
color: Color(0xff77797A),
color: Colors.transparent,
// color: Color(0xff77797A),
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
child: Column(

View File

@ -1,5 +1,7 @@
import 'dart:async';
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:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.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 }
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.
double? width,
GlobalKey<_InputTextFieldState> myInputTextFieldState = GlobalKey();
/// If non-null, requires the child to have exactly this height.
double? height,
});
GlobalKey<_InputTextFieldState> inputTextFieldState = GlobalKey();
class TIMUIKitInputTextField extends StatefulWidget {
class TIMInputTextField extends StatefulWidget {
/// conversation id
final String conversationID;
@ -95,7 +83,7 @@ class TIMUIKitInputTextField extends StatefulWidget {
final String? groupType;
const TIMUIKitInputTextField(
const TIMInputTextField(
{Key? key,
required this.conversationID,
required this.conversationType,
@ -122,7 +110,7 @@ class TIMUIKitInputTextField extends StatefulWidget {
State<StatefulWidget> createState() => _InputTextFieldState();
}
class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
class _InputTextFieldState extends TIMUIKitState<TIMInputTextField> {
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
final TUISettingModel settingModel = serviceLocator<TUISettingModel>();
final RegExp atTextReg = RegExp(r'@([^@\s]*)');
@ -297,8 +285,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
goDownBottom();
_handleSendEditStatus("", false);
} else {
showToast('请输入消息内容');
}
}
}
void goDownBottom() {
if (globalModel.getMessageListPosition(widget.conversationID) ==
@ -647,7 +637,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
@override
void didUpdateWidget(TIMUIKitInputTextField oldWidget) {
void didUpdateWidget(TIMInputTextField oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.conversationID != oldWidget.conversationID) {
handleSetDraftText(oldWidget.conversationID, oldWidget.conversationType);
@ -763,7 +753,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
builder: (BuildContext context, BoxConstraints constraints) {
inputWidth = constraints.maxWidth;
return TUIKitScreenUtils.getDeviceWidget(
defaultWidget: TIMUIKitTextFieldLayoutNarrow(
defaultWidget: TIMTextFieldLayoutNarrow(
onEmojiSubmitted: onEmojiSubmitted,
onCustomEmojiFaceSubmitted: onCustomEmojiFaceSubmitted,
backSpaceText: backSpaceText,
@ -793,7 +783,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
handleSoftKeyBoardDelete: _handleSoftKeyBoardDelete,
onSubmitted: onSubmitted,
goDownBottom: goDownBottom,
showSendAudio: widget.showSendAudio,
showSendAudio: false,
showSendEmoji: widget.showSendEmoji,
showMorePanel: widget.showMorePanel,
customEmojiStickerList: widget.customEmojiStickerList),

View File

@ -1,8 +1,14 @@
import 'dart:async';
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_screenutil/flutter_screenutil.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_state.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_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
final CustomStickerPanel? customStickerPanel;
@ -93,7 +99,7 @@ class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget {
final List customEmojiStickerList;
const TIMUIKitTextFieldLayoutNarrow(
const TIMTextFieldLayoutNarrow(
{Key? key,
this.customStickerPanel,
required this.onEmojiSubmitted,
@ -129,13 +135,14 @@ class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget {
: super(key: key);
@override
State<TIMUIKitTextFieldLayoutNarrow> createState() =>
_TIMUIKitTextFieldLayoutNarrowState();
State<TIMTextFieldLayoutNarrow> createState() =>
_TIMTextFieldLayoutNarrowState();
}
class _TIMUIKitTextFieldLayoutNarrowState
extends TIMUIKitState<TIMUIKitTextFieldLayoutNarrow> {
class _TIMTextFieldLayoutNarrowState
extends TIMUIKitState<TIMTextFieldLayoutNarrow> {
final TUISettingModel settingModel = serviceLocator<TUISettingModel>();
final ImagePicker _picker = ImagePicker();
bool showMore = false;
bool showMoreButton = true;
@ -189,34 +196,34 @@ class _TIMUIKitTextFieldLayoutNarrowState
if (showEmojiPanel) {
return widget.customStickerPanel != null
? widget.customStickerPanel!(
sendTextMessage: () {
widget.onEmojiSubmitted();
setSendButton();
},
sendFaceMessage: widget.onCustomEmojiFaceSubmitted,
deleteText: () {
widget.backSpaceText();
setSendButton();
},
addText: (int unicode) {
final newText = String.fromCharCode(unicode);
widget.addStickerToText(newText);
// handleSetDraftText();
},
addCustomEmojiText: ((String singleEmojiName) {
String? emojiName = singleEmojiName.split('.png')[0];
if (widget.isUseDefaultEmoji &&
widget.languageType == 'zh' &&
ConstData.emojiMapList[emojiName] != null &&
ConstData.emojiMapList[emojiName] != '') {
emojiName = ConstData.emojiMapList[emojiName];
}
final newText = '[$emojiName]';
widget.addStickerToText(newText);
setSendButton();
}),
defaultCustomEmojiStickerList:
widget.isUseDefaultEmoji ? ConstData.emojiList : [])
sendTextMessage: () {
widget.onEmojiSubmitted();
setSendButton();
},
sendFaceMessage: widget.onCustomEmojiFaceSubmitted,
deleteText: () {
widget.backSpaceText();
setSendButton();
},
addText: (int unicode) {
final newText = String.fromCharCode(unicode);
widget.addStickerToText(newText);
// handleSetDraftText();
},
addCustomEmojiText: ((String singleEmojiName) {
String? emojiName = singleEmojiName.split('.png')[0];
if (widget.isUseDefaultEmoji &&
widget.languageType == 'zh' &&
ConstData.emojiMapList[emojiName] != null &&
ConstData.emojiMapList[emojiName] != '') {
emojiName = ConstData.emojiMapList[emojiName];
}
final newText = '[$emojiName]';
widget.addStickerToText(newText);
setSendButton();
}),
defaultCustomEmojiStickerList:
widget.isUseDefaultEmoji ? ConstData.emojiList : [])
: EmojiPanel(onTapEmoji: (unicode) {
final newText = String.fromCharCode(unicode);
widget.addStickerToText(newText);
@ -256,7 +263,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
final height = originHeight != 0 ? originHeight : currentKeyboardHeight;
return height;
} else if (showMore || showEmojiPanel) {
return 248.0 + (bottomPadding ?? 0.0);
return 268.0 + (bottomPadding ?? 0.0);
} else if (widget.textEditingController.text.length >= 46 &&
showKeyboard == false) {
return 25 + (bottomPadding ?? 0.0);
@ -388,190 +395,208 @@ class _TIMUIKitTextFieldLayoutNarrowState
return Column(
children: [
_buildRepliedMessage(widget.repliedMessage),
Container(
color: widget.backgroundColor ?? hexToColor("f5f5f6"),
child: Column(
children: [
Container(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
constraints: const BoxConstraints(minHeight: 50),
child: Row(
children: [
if (widget.forbiddenText != null)
Expanded(
child: Container(
height: 35,
color: theme.weakBackgroundColor,
alignment: Alignment.center,
child: Text(
TIM_t(widget.forbiddenText!),
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: theme.weakTextColor,
Stack(
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(
16.sp,
),
topRight: Radius.circular(16.sp)),
color: Color(0xFF423055),
// color: Colors.yellow,
),
child: Column(
children: [
Container(
padding:
EdgeInsets.symmetric(vertical: 8, horizontal: 12.sp),
constraints: const BoxConstraints(minHeight: 30),
child: Row(
children: [
if (widget.forbiddenText != null)
Expanded(
child: Container(
height: 35,
color: theme.weakBackgroundColor,
alignment: Alignment.center,
child: Text(
TIM_t(widget.forbiddenText!),
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: theme.weakTextColor,
),
),
)),
if (PlatformUtils().isMobile &&
widget.showSendAudio &&
widget.forbiddenText == null)
InkWell(
onTap: () async {
showKeyboard = showSendSoundText;
if (showSendSoundText) {
widget.focusNode.requestFocus();
}
if (await Permissions.checkPermission(
context,
Permission.microphone.value,
theme,
)) {
setState(() {
showEmojiPanel = false;
showMore = false;
showSendSoundText = !showSendSoundText;
});
}
},
child: SvgPicture.asset(
showSendSoundText
? 'images/keyboard.svg'
: 'images/voice.svg',
package: 'tencent_cloud_chat_uikit',
color: const Color.fromRGBO(68, 68, 68, 1),
height: 28,
width: 28,
),
),
),
)),
if (PlatformUtils().isMobile &&
widget.showSendAudio &&
widget.forbiddenText == null)
InkWell(
onTap: () async {
showKeyboard = showSendSoundText;
if (showSendSoundText) {
widget.focusNode.requestFocus();
}
if (await Permissions.checkPermission(
context,
Permission.microphone.value,
theme,
)) {
setState(() {
showEmojiPanel = false;
showMore = false;
showSendSoundText = !showSendSoundText;
});
}
},
child: SvgPicture.asset(
showSendSoundText
? 'images/keyboard.svg'
: 'images/voice.svg',
package: 'tencent_cloud_chat_uikit',
color: const Color.fromRGBO(68, 68, 68, 1),
height: 28,
width: 28,
),
),
if (widget.forbiddenText == null)
const SizedBox(
width: 10,
),
if (widget.forbiddenText == null)
Expanded(
child: showSendSoundText
? SendSoundMessage(
onDownBottom: widget.goDownBottom,
conversationID: widget.conversationID,
conversationType: widget.conversationType)
: KeyboardVisibility(
child: ExtendedTextField(
maxLines: 4,
minLines: 1,
focusNode: widget.focusNode,
onChanged: debounceFunc,
onTap: () {
showKeyboard = true;
widget.goDownBottom();
setState(() {
showEmojiPanel = false;
showMore = false;
});
},
keyboardType: TextInputType.multiline,
textInputAction: PlatformUtils().isAndroid
? TextInputAction.newline
: TextInputAction.send,
onEditingComplete: () {
widget.onSubmitted();
if (showKeyboard) {
widget.focusNode.requestFocus();
}
setState(() {
if (widget.textEditingController.text
.isEmpty) {
showMoreButton = true;
}
});
},
textAlignVertical: TextAlignVertical.top,
decoration: InputDecoration(
border: InputBorder.none,
hintStyle: const TextStyle(
// fontSize: 10,
color: Color(0xffAEA4A3),
if (widget.forbiddenText == null)
const SizedBox(
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)
Expanded(
child: showSendSoundText
? TIMSendSoundMessage(
onDownBottom:
widget.goDownBottom,
conversationID:
widget.conversationID,
conversationType:
widget.conversationType)
: KeyboardVisibility(
child: ExtendedTextField(
style: TextStyle(
color: Colors.white,
fontSize: 14.sp),
maxLines: 4,
minLines: 1,
focusNode: widget.focusNode,
onChanged: debounceFunc,
onTap: () {
showKeyboard = true;
widget.goDownBottom();
setState(() {
showEmojiPanel = false;
showMore = false;
});
},
keyboardType:
TextInputType.multiline,
textInputAction:
PlatformUtils()
.isAndroid
? TextInputAction
.newline
: TextInputAction
.send,
onEditingComplete: () {
widget.onSubmitted();
if (showKeyboard) {
widget.focusNode
.requestFocus();
}
setState(() {
if (widget
.textEditingController
.text
.isEmpty) {
showMoreButton = true;
}
});
},
textAlignVertical:
TextAlignVertical.top,
decoration: InputDecoration(
border: InputBorder.none,
hintStyle: TextStyle(
fontSize: 14.sp,
color:
Color(0xB3FFFFFF),
),
hintText: widget.hintText,
fillColor:
Colors.transparent,
filled: true,
isDense: true,
),
controller: widget
.textEditingController,
specialTextSpanBuilder:
PlatformUtils().isWeb
? null
: DefaultSpecialTextSpanBuilder(
isUseDefaultEmoji:
widget
.isUseDefaultEmoji,
customEmojiStickerList:
widget
.customEmojiStickerList,
showAtBackground:
true,
)),
onChanged: (bool visibility) {
if (showKeyboard !=
visibility) {
setState(() {
showKeyboard = visibility;
});
}
}),
),
if (widget.forbiddenText == null)
const SizedBox(
width: 10,
),
if (widget.showSendEmoji &&
widget.forbiddenText == null)
InkWell(
onTap: () {
_openEmojiPanel();
widget.goDownBottom();
},
child: Image.asset(
getMsgImage('emoji'),
height: 24.sp,
width: 24.sp,
),
fillColor: Colors.white,
filled: true,
isDense: true,
hintText: widget.hintText ?? ''),
controller: widget.textEditingController,
specialTextSpanBuilder: PlatformUtils()
.isWeb
? null
: DefaultSpecialTextSpanBuilder(
isUseDefaultEmoji:
widget.isUseDefaultEmoji,
customEmojiStickerList:
widget.customEmojiStickerList,
showAtBackground: true,
)),
onChanged: (bool visibility) {
if (showKeyboard != visibility) {
setState(() {
showKeyboard = visibility;
});
}
}),
),
if (widget.forbiddenText == null)
const SizedBox(
width: 10,
),
if (widget.showSendEmoji && widget.forbiddenText == null)
InkWell(
onTap: () {
_openEmojiPanel();
widget.goDownBottom();
},
child: PlatformUtils().isWeb
? Icon(
showEmojiPanel
? Icons.keyboard_alt_outlined
: 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)
const SizedBox(
width: 10,
),
if (widget.showMorePanel &&
widget.forbiddenText == null &&
showMoreButton)
InkWell(
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: () {
),
],
))
],
),
if (widget.forbiddenText == null)
const SizedBox(
width: 10,
),
InkWell(
onTap: () {
widget.onSubmitted();
if (showKeyboard) {
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(
duration: Duration(
milliseconds:
(showKeyboard && PlatformUtils().isAndroid)
? 200
: 340),
curve: Curves.fastOutSlowIn,
height: max(_getBottomHeight(), 0.0),
// child: ListView(
// physics: const NeverScrollableScrollPhysics(),
// children: [_getBottomContainer()],
// ),
),
],
),
AnimatedContainer(
),
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(
physics: const NeverScrollableScrollPhysics(),
children: [
_getBottomContainer()
],
children: [_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 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'TIMUIKitTextField/tim_uikit_text_field.dart';
class TIMChat extends StatefulWidget {
int startTime = 0;
int endTime = 0;
@ -465,7 +467,7 @@ class _TUIChatState extends TIMUIKitState<TIMChat> {
)
: (widget.textFieldBuilder != null
? widget.textFieldBuilder!(context)
: TIMUIKitInputTextField(
: TIMInputTextField(
key: inputTextFieldState,
atMemberPanelScroll:
atMemberPanelScroll,
@ -486,8 +488,7 @@ class _TUIChatState extends TIMUIKitState<TIMChat> {
scrollController: autoController,
conversationID: _getConvID(),
conversationType: _getConvType(),
initText: widget.draftText,
hintText: widget.textFieldHintText,
hintText: '最近心情怎么样?',
showMorePanel: widget.config
?.isAllowShowMorePanel ??
true,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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