init
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import 'package:flutter/material.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_statelesswidget.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
|
||||
class TIMUIKitSearchFolder extends TIMUIKitStatelessWidget {
|
||||
final String folderName;
|
||||
final List<Widget> children;
|
||||
|
||||
TIMUIKitSearchFolder(
|
||||
{Key? key, required this.folderName, required this.children})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final TUITheme theme = value.theme;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom:
|
||||
BorderSide(color: hexToColor("DBDBDB"), width: 0.5))),
|
||||
padding: const EdgeInsets.fromLTRB(0, 6, 0, 6),
|
||||
child: Text(
|
||||
folderName,
|
||||
style: TextStyle(
|
||||
color: theme.weakTextColor, height: 1.5, fontSize: 14),
|
||||
),
|
||||
),
|
||||
...children
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.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_statelesswidget.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
|
||||
|
||||
enum SearchType { contact, group, history }
|
||||
|
||||
class TIMUIKitSearchIndicator extends TIMUIKitStatelessWidget {
|
||||
final List<SearchType> typeList;
|
||||
final ValueChanged<List<SearchType>> onChange;
|
||||
|
||||
TIMUIKitSearchIndicator(
|
||||
{required this.typeList, required this.onChange, Key? key})
|
||||
: super(key: key);
|
||||
|
||||
final titleMap = {
|
||||
SearchType.contact: "联系人",
|
||||
SearchType.group: "群聊",
|
||||
SearchType.history: "聊天记录"
|
||||
};
|
||||
|
||||
Widget renderItemBox(
|
||||
IconData icon, SearchType item, bool isSelect, TUITheme theme) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
if (isSelect) {
|
||||
typeList.remove(item);
|
||||
} else {
|
||||
typeList.add(item);
|
||||
}
|
||||
onChange(typeList);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: theme.weakTextColor,
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
if (isSelect)
|
||||
Positioned(
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 16,
|
||||
width: 16,
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: theme.primaryColor),
|
||||
child: const Icon(
|
||||
Icons.check,
|
||||
size: 8,
|
||||
color: Colors.white,
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
TIM_t(titleMap[item]!),
|
||||
style: TextStyle(color: theme.textColor, fontSize: 13),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final theme = value.theme;
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(TIM_t("搜索指定内容"),
|
||||
style: TextStyle(color: theme.weakTextColor, fontSize: 12)),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 1),
|
||||
Divider(thickness: 0.8, color: theme.weakDividerColor),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
renderItemBox(Icons.person, SearchType.contact,
|
||||
typeList.contains(SearchType.contact), theme),
|
||||
renderItemBox(Icons.people, SearchType.group,
|
||||
typeList.contains(SearchType.group), theme),
|
||||
renderItemBox(Icons.message, SearchType.history,
|
||||
typeList.contains(SearchType.history), theme),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
|
||||
|
||||
class TIMUIKitSearchInput extends StatefulWidget {
|
||||
final ValueChanged<String> onChange;
|
||||
final String? initValue;
|
||||
final TextEditingController? controller;
|
||||
final Widget? prefixIcon;
|
||||
final Widget? prefixText;
|
||||
final bool? isAutoFocus;
|
||||
final FocusNode focusNode;
|
||||
|
||||
const TIMUIKitSearchInput({
|
||||
required this.onChange,
|
||||
this.initValue,
|
||||
this.controller,
|
||||
Key? key,
|
||||
this.prefixIcon,
|
||||
this.isAutoFocus = true,
|
||||
this.prefixText,
|
||||
required this.focusNode,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => TIMUIKitSearchInputState();
|
||||
}
|
||||
|
||||
class TIMUIKitSearchInputState extends TIMUIKitState<TIMUIKitSearchInput> {
|
||||
late TextEditingController textEditingController =
|
||||
widget.controller ?? TextEditingController();
|
||||
bool isEmptyInput = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
textEditingController.text = widget.initValue ?? "";
|
||||
isEmptyInput = textEditingController.text.isEmpty;
|
||||
}
|
||||
|
||||
hideAllPanel() {
|
||||
widget.focusNode.unfocus();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final TUITheme theme = value.theme;
|
||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
return Container(
|
||||
// height: 64,
|
||||
padding: EdgeInsets.fromLTRB(16, isDesktopScreen ? 16 : 8, 16, 16),
|
||||
margin: isDesktopScreen ? const EdgeInsets.only(bottom: 2) : null,
|
||||
decoration: BoxDecoration(
|
||||
color: isDesktopScreen
|
||||
? theme.wideBackgroundColor
|
||||
: theme.primaryColor,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: theme.weakBackgroundColor ?? hexToColor("E6E9EB"),
|
||||
offset: const Offset(0.0, 2.0),
|
||||
)
|
||||
]
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxHeight: isDesktopScreen ? 30 : 36),
|
||||
child: TextField(
|
||||
autofocus: widget.isAutoFocus ?? true,
|
||||
onChanged: (value) async {
|
||||
final trimValue = value.trim();
|
||||
final isEmpty = trimValue.isEmpty;
|
||||
if(isEmpty != isEmptyInput){
|
||||
setState(() {
|
||||
isEmptyInput = isEmpty ? true : false;
|
||||
});
|
||||
}
|
||||
widget.onChange(trimValue);
|
||||
},
|
||||
keyboardType: TextInputType.text,
|
||||
textInputAction: TextInputAction.search,
|
||||
maxLines: 4,
|
||||
minLines: 1,
|
||||
focusNode: widget.focusNode,
|
||||
controller: textEditingController,
|
||||
textAlignVertical: TextAlignVertical.center,
|
||||
textAlign: TextAlign.start,
|
||||
style: isDesktopScreen ? const TextStyle(
|
||||
fontSize: 12
|
||||
) : null,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
border: const OutlineInputBorder(borderSide: BorderSide.none),
|
||||
hintStyle: TextStyle(
|
||||
fontSize: isDesktopScreen ? 12 : 14,
|
||||
color: hexToColor("CCCCCC"),
|
||||
),
|
||||
fillColor: isDesktopScreen ? hexToColor("f3f3f4") : Colors.white,
|
||||
filled: true,
|
||||
isDense: true,
|
||||
hintText: TIM_t("搜索"),
|
||||
prefix: widget.prefixText != null
|
||||
? Container(
|
||||
margin: const EdgeInsets.only(right: 8),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth:
|
||||
MediaQuery.of(context).size.width * 0.2),
|
||||
child: widget.prefixText,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
prefixIcon: widget.prefixIcon,
|
||||
suffixIcon: isEmptyInput
|
||||
? null
|
||||
: IconButton(
|
||||
onPressed: () {
|
||||
textEditingController.clear();
|
||||
setState(() {
|
||||
isEmptyInput = true;
|
||||
});
|
||||
widget.onChange("");
|
||||
},
|
||||
icon: Icon(Icons.cancel, color: hexToColor("979797")),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
if(!isDesktopScreen) Container(
|
||||
margin: const EdgeInsets.fromLTRB(10, 0, 0, 0),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(TIM_t("取消"),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
)),
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_item_wide.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
|
||||
|
||||
class TIMUIKitSearchItem extends TIMUIKitStatelessWidget {
|
||||
final String faceUrl;
|
||||
final String showName;
|
||||
final String lineOne;
|
||||
final String? lineOneRight;
|
||||
final String? lineTwo;
|
||||
final VoidCallback? onClick;
|
||||
|
||||
TIMUIKitSearchItem(
|
||||
{Key? key,
|
||||
required this.faceUrl,
|
||||
required this.showName,
|
||||
required this.lineOne,
|
||||
this.lineTwo,
|
||||
this.lineOneRight,
|
||||
this.onClick})
|
||||
: super(key: key);
|
||||
|
||||
_renderLineOneRight(String? text, TUITheme theme) {
|
||||
if (text != null) {
|
||||
return Text(text,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.weakTextColor,
|
||||
));
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
|
||||
_renderLineTwo(String? text, TUITheme theme) {
|
||||
return (text != null)
|
||||
? Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
color: theme.weakTextColor, height: 1.5, fontSize: 14),
|
||||
)
|
||||
: Container(
|
||||
height: 0,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final TUITheme theme = value.theme;
|
||||
|
||||
return TUIKitScreenUtils.getDeviceWidget(
|
||||
context: context,
|
||||
defaultWidget: GestureDetector(
|
||||
onTap: onClick,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(color: hexToColor("DBDBDB"), width: 0.5))),
|
||||
padding: const EdgeInsets.fromLTRB(0, 12, 0, 12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
clipBehavior: Clip.none,
|
||||
children: [Avatar(faceUrl: faceUrl, showName: showName)],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(left: 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
// height: 24,
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
lineOne,
|
||||
style: TextStyle(
|
||||
color: theme.darkTextColor,
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
_renderLineOneRight(lineOneRight, theme),
|
||||
],
|
||||
),
|
||||
),
|
||||
_renderLineTwo(lineTwo, theme),
|
||||
],
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
desktopWidget: TIMUIKitSearchWideItem(
|
||||
lineOneRight: lineOneRight,
|
||||
key: key,
|
||||
lineTwo: lineTwo,
|
||||
onClick: onClick,
|
||||
faceUrl: faceUrl,
|
||||
showName: showName,
|
||||
lineOne: lineOne),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// ignore_for_file: file_names
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
|
||||
class TIMUIKitSearchShowALl extends TIMUIKitStatelessWidget {
|
||||
final String textShow;
|
||||
final VoidCallback? onClick;
|
||||
final bool isNeedMoreBottom;
|
||||
|
||||
TIMUIKitSearchShowALl(
|
||||
{Key? key,
|
||||
this.onClick,
|
||||
required this.textShow,
|
||||
this.isNeedMoreBottom = false})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
return InkWell(
|
||||
onTap: onClick,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
bottom: BorderSide(color: hexToColor("DBDBDB"), width: 0.5))),
|
||||
padding: EdgeInsets.fromLTRB(0, 8, 0, (isNeedMoreBottom ? 24 : 8)),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.search,
|
||||
color: hexToColor("979797"),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(left: 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
// height: 24,
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Text(
|
||||
textShow,
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: isDesktopScreen ? 14 : 16.0,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)),
|
||||
Icon(
|
||||
Icons.expand_more,
|
||||
color: hexToColor("979797"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info_result.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_result_item.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message_search_result_item.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_search_view_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_indicator.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_friend.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_input.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_group.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_msg.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_not_support.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
|
||||
class TIMUIKitSearch extends StatefulWidget {
|
||||
/// the callback after clicking the conversation item
|
||||
final Function(V2TimConversation, V2TimMessage?) onTapConversation;
|
||||
|
||||
/// [Deprecated] : You are supposed to use [TIMUIKitSearchMsgDetail],
|
||||
/// if you tend to search inside a specific conversation, includes c2c and group.
|
||||
final V2TimConversation? conversation;
|
||||
|
||||
/// [Deprecated] : You are supposed to use [onEnterSearchInConversation],
|
||||
/// though the effects are the same.
|
||||
final Function(V2TimConversation conversation, String initKeyword)? onEnterConversation;
|
||||
|
||||
/// On click each conversation from 'Chat history' and searching for historical message in it.
|
||||
final Function(V2TimConversation conversation, String initKeyword)? onEnterSearchInConversation;
|
||||
|
||||
final VoidCallback? onBack;
|
||||
|
||||
final bool? isAutoFocus;
|
||||
|
||||
const TIMUIKitSearch(
|
||||
{required this.onTapConversation,
|
||||
Key? key,
|
||||
@Deprecated(
|
||||
"You are supposed to use [TIMUIKitSearchMsgDetail], if you tend to search inside a specific conversation, includes c2c and group")
|
||||
this.conversation,
|
||||
@Deprecated("You are supposed to use [onEnterSearchInConversation], though the effects are the same.")
|
||||
this.onEnterConversation,
|
||||
this.isAutoFocus = true,
|
||||
this.onEnterSearchInConversation,
|
||||
this.onBack})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => TIMUIKitSearchState();
|
||||
}
|
||||
|
||||
class TIMUIKitSearchState extends TIMUIKitState<TIMUIKitSearch> {
|
||||
late TextEditingController textEditingController = TextEditingController();
|
||||
final model = serviceLocator<TUISearchViewModel>();
|
||||
final FocusNode focusNode = FocusNode();
|
||||
GlobalKey<dynamic> inputTextField = GlobalKey();
|
||||
List<SearchType> searchTypes = [SearchType.group, SearchType.contact, SearchType.history];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
model.initSearch();
|
||||
model.initConversationMsg();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
if (PlatformUtils().isWeb) {
|
||||
return TIMUIKitSearchNotSupport();
|
||||
}
|
||||
return MultiProvider(
|
||||
providers: [ChangeNotifierProvider.value(value: serviceLocator<TUISearchViewModel>())],
|
||||
builder: (context, w) {
|
||||
List<V2TimFriendInfoResult> friendResultList = Provider.of<TUISearchViewModel>(context).friendList ?? [];
|
||||
List<V2TimMessageSearchResultItem> msgList = Provider.of<TUISearchViewModel>(context).msgList ?? [];
|
||||
List<V2TimGroupInfo> groupList = Provider.of<TUISearchViewModel>(context).groupList ?? [];
|
||||
int totalMsgCount = Provider.of<TUISearchViewModel>(context).totalMsgCount;
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.unfocus();
|
||||
}
|
||||
},
|
||||
child: Scaffold(
|
||||
body: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
TIMUIKitSearchInput(
|
||||
focusNode: focusNode,
|
||||
key: inputTextField,
|
||||
isAutoFocus: widget.isAutoFocus,
|
||||
onChange: (String value) {
|
||||
model.searchByKey(value);
|
||||
},
|
||||
controller: textEditingController,
|
||||
prefixIcon: Icon(
|
||||
Icons.search,
|
||||
size: 16,
|
||||
color: hexToColor("979797"),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
if ((friendResultList.isEmpty || !(searchTypes.contains(SearchType.contact))) &&
|
||||
(groupList.isEmpty || !(searchTypes.contains(SearchType.group))) &&
|
||||
(totalMsgCount == 0 || !(searchTypes.contains(SearchType.history))))
|
||||
TIMUIKitSearchIndicator(
|
||||
typeList: searchTypes,
|
||||
onChange: (list) {
|
||||
setState(() {
|
||||
searchTypes = list;
|
||||
});
|
||||
},
|
||||
),
|
||||
if (searchTypes.contains(SearchType.contact))
|
||||
TIMUIKitSearchFriend(
|
||||
onTapConversation: (conversation, message) {
|
||||
focusNode.unfocus();
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
widget.onTapConversation(conversation, message);
|
||||
});
|
||||
},
|
||||
friendResultList: friendResultList),
|
||||
if (searchTypes.contains(SearchType.group))
|
||||
TIMUIKitSearchGroup(
|
||||
groupList: groupList,
|
||||
onTapConversation: (conversation, message) {
|
||||
focusNode.unfocus();
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
widget.onTapConversation(conversation, message);
|
||||
});
|
||||
},
|
||||
),
|
||||
if (searchTypes.contains(SearchType.history))
|
||||
TIMUIKitSearchMsg(
|
||||
onTapConversation: widget.onTapConversation,
|
||||
keyword: textEditingController.text,
|
||||
totalMsgCount: totalMsgCount,
|
||||
msgList: msgList,
|
||||
onEnterConversation: (V2TimConversation conversation, String keyword) {
|
||||
if (widget.onEnterSearchInConversation != null) {
|
||||
widget.onEnterSearchInConversation!(conversation, keyword);
|
||||
} else if (widget.onEnterConversation != null) {
|
||||
widget.onEnterConversation!(conversation, keyword);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
if (widget.onBack != null) {
|
||||
widget.onBack!();
|
||||
}
|
||||
},
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// ignore_for_file: must_be_immutable
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info_result.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_item.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_folder.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_search_view_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_showAll.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
|
||||
class TIMUIKitSearchFriend extends StatefulWidget {
|
||||
List<V2TimFriendInfoResult> friendResultList;
|
||||
final Function(V2TimConversation, V2TimMessage?) onTapConversation;
|
||||
|
||||
TIMUIKitSearchFriend({required this.friendResultList, Key? key, required this.onTapConversation}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => TIMUIKitSearchFriendState();
|
||||
}
|
||||
|
||||
class TIMUIKitSearchFriendState extends TIMUIKitState<TIMUIKitSearchFriend> {
|
||||
bool isShowAll = false;
|
||||
int defaultShowLines = 3;
|
||||
|
||||
Widget _renderShowALl(int currentLines) {
|
||||
return (isShowAll == false && currentLines > defaultShowLines)
|
||||
? TIMUIKitSearchShowALl(
|
||||
textShow: TIM_t("全部联系人"),
|
||||
onClick: () => setState(() {
|
||||
isShowAll = true;
|
||||
}),
|
||||
)
|
||||
: Container();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
List<V2TimConversation?> _conversationList = Provider.of<TUISearchViewModel>(context).conversationList;
|
||||
|
||||
List<V2TimFriendInfoResult> filteredFriendResultList = widget.friendResultList.where((friend) {
|
||||
int index = _conversationList.indexWhere((conv) => friend.friendInfo?.userID == conv?.userID);
|
||||
return index == -1 ? false : true;
|
||||
}).toList();
|
||||
|
||||
List<V2TimFriendInfoResult> halfFilteredFriendResultList = isShowAll
|
||||
? filteredFriendResultList
|
||||
: filteredFriendResultList.sublist(0, min(defaultShowLines, filteredFriendResultList.length));
|
||||
|
||||
if (filteredFriendResultList.isNotEmpty) {
|
||||
return TIMUIKitSearchFolder(folderName: TIM_t("联系人"), children: [
|
||||
...halfFilteredFriendResultList.map((conv) {
|
||||
int convIndex = _conversationList.indexWhere((item) => conv.friendInfo?.userID == item?.userID);
|
||||
V2TimConversation conversation = _conversationList[convIndex]!;
|
||||
late String? showNickName;
|
||||
if (conv.friendInfo?.friendRemark != null && conv.friendInfo?.friendRemark != "") {
|
||||
showNickName = conv.friendInfo?.friendRemark;
|
||||
} else if (conv.friendInfo?.userProfile?.nickName != null && conv.friendInfo?.userProfile?.nickName != "") {
|
||||
showNickName = conv.friendInfo?.userProfile?.nickName;
|
||||
} else {
|
||||
showNickName = conv.friendInfo?.userID;
|
||||
}
|
||||
|
||||
return TIMUIKitSearchItem(
|
||||
onClick: () {
|
||||
widget.onTapConversation(conversation, null);
|
||||
},
|
||||
faceUrl: conv.friendInfo?.userProfile?.faceUrl ?? "",
|
||||
showName: "",
|
||||
lineOne: conversation.userID!,
|
||||
lineTwo: TIM_t("昵称") + ":" + showNickName!,
|
||||
);
|
||||
}).toList(),
|
||||
_renderShowALl(filteredFriendResultList.length),
|
||||
]);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// ignore_for_file: must_be_immutable
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_item.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_folder.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_search_view_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_showAll.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
|
||||
class TIMUIKitSearchGroup extends StatefulWidget {
|
||||
List<V2TimGroupInfo> groupList;
|
||||
final Function(V2TimConversation, V2TimMessage?) onTapConversation;
|
||||
|
||||
TIMUIKitSearchGroup({required this.groupList, Key? key, required this.onTapConversation}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => TIMUIKitSearchGroupState();
|
||||
}
|
||||
|
||||
class TIMUIKitSearchGroupState extends TIMUIKitState<TIMUIKitSearchGroup> {
|
||||
bool isShowAll = false;
|
||||
int defaultShowLines = 3;
|
||||
|
||||
Widget _renderShowALl(int currentLines) {
|
||||
return (isShowAll == false && currentLines > defaultShowLines)
|
||||
? TIMUIKitSearchShowALl(
|
||||
textShow: TIM_t("全部群聊"),
|
||||
onClick: () => setState(() {
|
||||
isShowAll = true;
|
||||
}),
|
||||
)
|
||||
: Container();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
List<V2TimConversation?> _conversationList = Provider.of<TUISearchViewModel>(context).conversationList;
|
||||
|
||||
List<V2TimGroupInfo> filteredGroupResultList = widget.groupList.where((group) {
|
||||
int index = _conversationList.indexWhere((conv) => group.groupID == conv?.groupID);
|
||||
return index == -1 ? false : true;
|
||||
}).toList();
|
||||
|
||||
List<V2TimGroupInfo> halfFilteredGroupResultList = isShowAll
|
||||
? filteredGroupResultList
|
||||
: filteredGroupResultList.sublist(0, min(defaultShowLines, filteredGroupResultList.length));
|
||||
|
||||
if (filteredGroupResultList.isNotEmpty) {
|
||||
return TIMUIKitSearchFolder(folderName: TIM_t("群聊"), children: [
|
||||
...halfFilteredGroupResultList.map((group) {
|
||||
int convIndex = _conversationList.indexWhere((item) => group.groupID == item?.groupID);
|
||||
V2TimConversation conversation = _conversationList[convIndex]!;
|
||||
return TIMUIKitSearchItem(
|
||||
onClick: () {
|
||||
widget.onTapConversation(conversation, null);
|
||||
},
|
||||
faceUrl: conversation.faceUrl ?? group.faceUrl ?? "",
|
||||
showName: "",
|
||||
lineOne: conversation.showName ?? group.groupName ?? conversation.groupID ?? "",
|
||||
);
|
||||
}).toList(),
|
||||
_renderShowALl(filteredGroupResultList.length),
|
||||
]);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
|
||||
|
||||
class TIMUIKitSearchWideItem extends TIMUIKitStatelessWidget {
|
||||
final String faceUrl;
|
||||
final String showName;
|
||||
final String lineOne;
|
||||
final String? lineOneRight;
|
||||
final String? lineTwo;
|
||||
final VoidCallback? onClick;
|
||||
|
||||
TIMUIKitSearchWideItem(
|
||||
{Key? key,
|
||||
required this.faceUrl,
|
||||
required this.showName,
|
||||
required this.lineOne,
|
||||
this.lineTwo,
|
||||
this.lineOneRight,
|
||||
this.onClick})
|
||||
: super(key: key);
|
||||
|
||||
_renderLineOneRight(String? text, TUITheme theme) {
|
||||
if (text != null) {
|
||||
return Text(text,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: theme.weakTextColor,
|
||||
));
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
|
||||
_renderLineTwo(String? text, TUITheme theme) {
|
||||
return (text != null)
|
||||
? Container(
|
||||
margin: const EdgeInsets.only(top: 0),
|
||||
child: SelectableText(
|
||||
text,
|
||||
style: TextStyle(
|
||||
color: theme.weakTextColor, height: 1.5, fontSize: 12),
|
||||
),
|
||||
)
|
||||
: Container(
|
||||
height: 0,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final TUITheme theme = value.theme;
|
||||
|
||||
return Material(
|
||||
color: Colors.white,
|
||||
child: InkWell(
|
||||
onTap: onClick,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(color: hexToColor("DBDBDB"), width: 0.5))),
|
||||
padding: const EdgeInsets.fromLTRB(0, 12, 0, 12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: Avatar(faceUrl: faceUrl, showName: showName, isShowBigWhenClick: false,),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(left: 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
// height: 24,
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(child: Text(
|
||||
lineOne,
|
||||
style: TextStyle(
|
||||
color: theme.darkTextColor,
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w400),
|
||||
)),
|
||||
_renderLineOneRight(lineOneRight, theme),
|
||||
],
|
||||
),
|
||||
),
|
||||
_renderLineTwo(lineTwo, theme),
|
||||
],
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// ignore_for_file: must_be_immutable, unused_import
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_result_item.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message_search_result_item.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_search_view_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_item.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_folder.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_msg_detail.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_showAll.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
||||
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
|
||||
class TIMUIKitSearchMsg extends TIMUIKitStatelessWidget {
|
||||
List<V2TimMessageSearchResultItem?> msgList;
|
||||
int totalMsgCount;
|
||||
String keyword;
|
||||
final Function(V2TimConversation, V2TimMessage?) onTapConversation;
|
||||
final model = serviceLocator<TUISearchViewModel>();
|
||||
final Function(V2TimConversation, String) onEnterConversation;
|
||||
|
||||
TIMUIKitSearchMsg(
|
||||
{required this.msgList,
|
||||
required this.keyword,
|
||||
required this.totalMsgCount,
|
||||
Key? key,
|
||||
required this.onTapConversation,
|
||||
required this.onEnterConversation})
|
||||
: super(key: key);
|
||||
|
||||
Widget _renderShowALl(bool isShowMore) {
|
||||
return (isShowMore == true)
|
||||
? TIMUIKitSearchShowALl(
|
||||
textShow: TIM_t("更多聊天记录"),
|
||||
onClick: () => {model.searchMsgByKey(keyword, false)},
|
||||
)
|
||||
: Container();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
List<V2TimConversation?> _conversationList = Provider.of<TUISearchViewModel>(context).conversationList;
|
||||
|
||||
if (msgList.isNotEmpty) {
|
||||
return TIMUIKitSearchFolder(folderName: TIM_t("聊天记录"), children: [
|
||||
...msgList.map((conv) {
|
||||
V2TimConversation? conversation;
|
||||
final index = _conversationList.indexWhere((item) => item!.conversationID == conv?.conversationID);
|
||||
if (index > -1) {
|
||||
conversation = _conversationList[index]!;
|
||||
}
|
||||
if (conversation == null) {
|
||||
return Container();
|
||||
}
|
||||
final option1 = conv?.messageCount;
|
||||
return TIMUIKitSearchItem(
|
||||
onClick: () async {
|
||||
onEnterConversation(conversation!, keyword);
|
||||
},
|
||||
faceUrl: conversation.faceUrl ?? "",
|
||||
showName: conversation.showName ?? "",
|
||||
lineOne: conversation.showName ?? "",
|
||||
lineTwo: TIM_t_para("{{option1}}条相关聊天记录", "$option1条相关聊天记录")(option1: option1),
|
||||
);
|
||||
}).toList(),
|
||||
_renderShowALl(totalMsgCount > msgList.length)
|
||||
]);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/utils/time_ago.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_input.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_item.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_search_view_model.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/pureUI/tim_uikit_search_showAll.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitSearch/tim_uikit_search_not_support.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
|
||||
class TIMUIKitSearchMsgDetail extends StatefulWidget {
|
||||
/// Conversation need search
|
||||
final V2TimConversation currentConversation;
|
||||
|
||||
/// initial keyword
|
||||
final String keyword;
|
||||
|
||||
final List<V2TimMessage>? initMessageList;
|
||||
|
||||
/// the callback after clicking each conversation message item
|
||||
final Function(V2TimConversation, V2TimMessage?) onTapConversation;
|
||||
|
||||
final bool? isAutoFocus;
|
||||
|
||||
const TIMUIKitSearchMsgDetail(
|
||||
{Key? key,
|
||||
this.isAutoFocus = true,
|
||||
required this.currentConversation,
|
||||
required this.keyword,
|
||||
required this.onTapConversation,
|
||||
this.initMessageList})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => TIMUIKitSearchMsgDetailState();
|
||||
}
|
||||
|
||||
class TIMUIKitSearchMsgDetailState extends TIMUIKitState<TIMUIKitSearchMsgDetail> {
|
||||
final model = serviceLocator<TUISearchViewModel>();
|
||||
String keywordState = "";
|
||||
int currentPage = 0;
|
||||
final FocusNode focusNode = FocusNode();
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
keywordState = widget.keyword;
|
||||
updateMsgResult(widget.keyword, true);
|
||||
}
|
||||
|
||||
(bool isRevoke, bool isRevokeByAdmin) isRevokeMessage(V2TimMessage? message) {
|
||||
if (message == null) {
|
||||
return (false, false);
|
||||
}
|
||||
if (message.status == 6) {
|
||||
return (true, false);
|
||||
} else {
|
||||
try {
|
||||
final customData = jsonDecode(message.cloudCustomData ?? "{}");
|
||||
final isRevoke = customData["isRevoke"] ?? false;
|
||||
final revokeByAdmin = customData["revokeByAdmin"] ?? false;
|
||||
return (isRevoke, revokeByAdmin);
|
||||
} catch (e) {
|
||||
return (false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String _getMsgElem(V2TimMessage message) {
|
||||
final msgType = message.elemType;
|
||||
final revokeStatus = isRevokeMessage(message);
|
||||
final isRevokedMessage = revokeStatus.$1;
|
||||
final isAdminRevoke = revokeStatus.$2;
|
||||
if (isRevokedMessage) {
|
||||
final isSelf = message.isSelf ?? true;
|
||||
final option2 = isAdminRevoke ? TIM_t("管理员") : (isSelf ? TIM_t("您") : message.nickName ?? message.sender);
|
||||
return TIM_t_para("{{option2}}撤回了一条消息", "$option2撤回了一条消息")(option2: option2);
|
||||
}
|
||||
switch (msgType) {
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
|
||||
return TIM_t("[自定义]");
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_SOUND:
|
||||
return TIM_t("[语音]");
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
|
||||
return message.textElem!.text as String;
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_FACE:
|
||||
return TIM_t("[表情]");
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_FILE:
|
||||
final option1 = message.fileElem!.fileName;
|
||||
return TIM_t_para("[文件] {{option1}}", "[文件] $option1")(option1: option1);
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_IMAGE:
|
||||
return TIM_t("[图片]");
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
|
||||
return TIM_t("[视频]");
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_LOCATION:
|
||||
return TIM_t("[位置]");
|
||||
case MessageElemType.V2TIM_ELEM_TYPE_MERGER:
|
||||
return TIM_t("[聊天记录]");
|
||||
default:
|
||||
return TIM_t("未知消息");
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> _renderListMessage(List<V2TimMessage> msgList, BuildContext context, bool isDesktopScreen) {
|
||||
List<Widget> listWidget = [];
|
||||
|
||||
listWidget = msgList.map((message) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 0),
|
||||
child: TIMUIKitSearchItem(
|
||||
faceUrl: message.faceUrl ?? "",
|
||||
showName: TencentUtils.checkString(message.nickName) ??
|
||||
TencentUtils.checkString(message.userID) ??
|
||||
message.sender ??
|
||||
"",
|
||||
lineOne: TencentUtils.checkString(message.nickName) ??
|
||||
TencentUtils.checkString(message.userID) ??
|
||||
message.sender ??
|
||||
"",
|
||||
lineOneRight:
|
||||
(isDesktopScreen && message.timestamp != null) ? TimeAgo().getTimeForMessage(message.timestamp!) : null,
|
||||
lineTwo: _getMsgElem(message),
|
||||
onClick: () {
|
||||
focusNode.unfocus();
|
||||
widget.onTapConversation(widget.currentConversation, message);
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList();
|
||||
return listWidget;
|
||||
}
|
||||
|
||||
updateMsgResult(String? keyword, bool isNewSearch) {
|
||||
if (isNewSearch) {
|
||||
setState(() {
|
||||
currentPage = 0;
|
||||
keywordState = keyword!;
|
||||
});
|
||||
}
|
||||
model.getMsgForConversation(keyword ?? keywordState, widget.currentConversation.conversationID, currentPage);
|
||||
setState(() {
|
||||
currentPage = currentPage + 1;
|
||||
});
|
||||
}
|
||||
|
||||
Widget _renderShowALl(bool isShowMore) {
|
||||
return (isShowMore == true)
|
||||
? Container(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 0),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
child: TIMUIKitSearchShowALl(
|
||||
textShow: TIM_t("更多聊天记录"),
|
||||
onClick: () => {updateMsgResult(null, false)},
|
||||
),
|
||||
)
|
||||
: Container();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final theme = value.theme;
|
||||
if (PlatformUtils().isWeb) {
|
||||
return TIMUIKitSearchNotSupport();
|
||||
}
|
||||
return MultiProvider(
|
||||
providers: [ChangeNotifierProvider.value(value: serviceLocator<TUISearchViewModel>())],
|
||||
builder: (context, w) {
|
||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||
|
||||
List<V2TimMessage> currentMsgListForConversation =
|
||||
Provider.of<TUISearchViewModel>(context).currentMsgListForConversation;
|
||||
final currentText = _controller.text;
|
||||
if (currentMsgListForConversation.isEmpty &&
|
||||
widget.initMessageList != null &&
|
||||
widget.initMessageList!.isNotEmpty &&
|
||||
currentText.isEmpty) {
|
||||
currentMsgListForConversation = widget.initMessageList!;
|
||||
}
|
||||
|
||||
final int totalMsgInConversationCount = Provider.of<TUISearchViewModel>(context).totalMsgInConversationCount;
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.unfocus();
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (isDesktopScreen)
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
child: Avatar(faceUrl: widget.currentConversation.faceUrl ?? "", showName: ""),
|
||||
width: 30,
|
||||
height: 30,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
widget.currentConversation.showName ?? widget.currentConversation.userID ?? "",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: theme.darkTextColor,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TIMUIKitSearchInput(
|
||||
focusNode: focusNode,
|
||||
controller: _controller,
|
||||
isAutoFocus: widget.isAutoFocus,
|
||||
onChange: (String value) {
|
||||
updateMsgResult(value, true);
|
||||
},
|
||||
initValue: widget.keyword,
|
||||
prefixIcon: Icon(
|
||||
Icons.search,
|
||||
size: 16,
|
||||
color: hexToColor("979797"),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Scrollbar(
|
||||
controller: _scrollController,
|
||||
child: ListView(
|
||||
controller: _scrollController,
|
||||
children: [
|
||||
..._renderListMessage(currentMsgListForConversation, context, isDesktopScreen),
|
||||
_renderShowALl(
|
||||
keywordState.isNotEmpty && totalMsgInConversationCount > currentMsgListForConversation.length)
|
||||
],
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.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_statelesswidget.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
|
||||
|
||||
class TIMUIKitSearchNotSupport extends TIMUIKitStatelessWidget {
|
||||
TIMUIKitSearchNotSupport({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final theme = value.theme;
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: BoxDecoration(
|
||||
color: hexToColor("ecf3fe"),
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
// 因为底部有波浪图, icon向上一点,感觉视觉上更协调
|
||||
margin: const EdgeInsets.only(bottom: 40),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
TIM_t("Web网页端不支持搜索"),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: theme.darkTextColor,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
TIM_t("暂时仅限 Android/iOS 端"),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: theme.darkTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
child: Image.asset(
|
||||
"images/logo_bottom.png",
|
||||
package: 'tencent_cloud_chat_uikit',
|
||||
fit: BoxFit.fitWidth,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user