修改会话列表UI,完善资料UI,跳转逻辑
This commit is contained in:
parent
8bfb1814ae
commit
a74025c4c4
@ -67,6 +67,7 @@ class Complete_materialLogic extends GetxController {
|
|||||||
_setImageFileListFromFile(pickedFile!);
|
_setImageFileListFromFile(pickedFile!);
|
||||||
// });
|
// });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// _pickImageError = e;
|
// _pickImageError = e;
|
||||||
// });
|
// });
|
||||||
@ -141,7 +142,7 @@ class Complete_materialLogic extends GetxController {
|
|||||||
});
|
});
|
||||||
var bean = BaseResponse<String>.fromJson(data, (data) => data);
|
var bean = BaseResponse<String>.fromJson(data, (data) => data);
|
||||||
if (bean.code == 200) {
|
if (bean.code == 200) {
|
||||||
Get.toNamed(AppRoutes.Home);
|
Get.offAllNamed(AppRoutes.Home);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,7 +73,7 @@ class Complete_materialPage extends StatelessWidget {
|
|||||||
height: 15.sp,
|
height: 15.sp,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'数据表明95%的人对完整的兽设更感兴趣',
|
'数据表明95%的人对真实的头像更感兴趣',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -148,13 +148,18 @@ class Complete_materialPage extends StatelessWidget {
|
|||||||
funcWidget(
|
funcWidget(
|
||||||
'兴趣',
|
'兴趣',
|
||||||
Row(
|
Row(
|
||||||
children: [interestWdiget('JK圈',controller)],
|
children: controller.numbers.isNotEmpty
|
||||||
),
|
? [interestWdiget('JK圈', controller)]
|
||||||
() async {
|
: [],
|
||||||
controller.numbers = await Get.toNamed(AppRoutes.SelectCircleActivity,arguments: controller.configBean.interestMap);
|
), () async {
|
||||||
|
var data = await Get.toNamed(
|
||||||
|
AppRoutes.SelectCircleActivity,
|
||||||
|
arguments: controller.configBean.interestMap);
|
||||||
|
if (data != null) {
|
||||||
|
controller.numbers = data;
|
||||||
controller.update();
|
controller.update();
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.only(
|
margin: EdgeInsets.only(
|
||||||
top: 24.sp,
|
top: 24.sp,
|
||||||
@ -285,7 +290,7 @@ class Complete_materialPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interestWdiget(String interest,Complete_materialLogic controller) {
|
interestWdiget(String interest, Complete_materialLogic controller) {
|
||||||
return Container(
|
return Container(
|
||||||
height: 59.sp,
|
height: 59.sp,
|
||||||
width: 240.sp,
|
width: 240.sp,
|
||||||
@ -300,37 +305,20 @@ class Complete_materialPage extends StatelessWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.only(right: 11.sp), // 替换为实际的 item 间距
|
margin: EdgeInsets.only(right: 11.sp), // 替换为实际的 item 间距
|
||||||
child: Container(
|
child: Container(
|
||||||
|
height: 34.sp,
|
||||||
|
padding: EdgeInsets.only(left: 15.sp, right: 15.sp),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(17.0), // 设置圆角半径
|
borderRadius: BorderRadius.circular(17.0.sp), // 设置圆角半径
|
||||||
gradient: LinearGradient(
|
border: Border.all(color: Colors.white, width: 1.sp),
|
||||||
colors: [
|
|
||||||
Color(0xFFffffff),
|
|
||||||
Color(0xFFffffff),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
color: Color(0xFF392D53),
|
color: Color(0xFF392D53),
|
||||||
),
|
),
|
||||||
child: Container(
|
|
||||||
margin: EdgeInsets.all(0.2.sp),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(17.0),
|
|
||||||
// shape: BoxShape.circle,
|
|
||||||
color: Color(0xFF392D53),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
top: 2.sp, bottom: 2.sp, left: 15.sp, right: 15.sp),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
child: Text(
|
||||||
controller.numbers[index].name,
|
controller.numbers[index].name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12.0,
|
fontSize: 12.0.sp,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
), // 替换为实际的列表项小部件
|
), // 替换为实际的列表项小部件
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -362,7 +350,8 @@ class Complete_materialPage extends StatelessWidget {
|
|||||||
? controller.state.sex
|
? controller.state.sex
|
||||||
: '男', onConfirm: (p, position) {
|
: '男', onConfirm: (p, position) {
|
||||||
controller.state.sex = p;
|
controller.state.sex = p;
|
||||||
controller.state.genderId = controller.configBean.genderMap.keys.toList()[position];
|
controller.state.genderId =
|
||||||
|
controller.configBean.genderMap.keys.toList()[position];
|
||||||
controller.update();
|
controller.update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -408,7 +397,8 @@ class Complete_materialPage extends StatelessWidget {
|
|||||||
? controller.state.role
|
? controller.state.role
|
||||||
: 'Sado', onConfirm: (p, position) {
|
: 'Sado', onConfirm: (p, position) {
|
||||||
controller.state.role = p;
|
controller.state.role = p;
|
||||||
controller.state.roleId = controller.configBean.roleMap.keys.toList()[position];
|
controller.state.roleId =
|
||||||
|
controller.configBean.roleMap.keys.toList()[position];
|
||||||
controller.update();
|
controller.update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -422,11 +412,9 @@ class Complete_materialPage extends StatelessWidget {
|
|||||||
? controller.state.orientation
|
? controller.state.orientation
|
||||||
: '异性恋', onConfirm: (p, position) {
|
: '异性恋', onConfirm: (p, position) {
|
||||||
controller.state.orientation = p;
|
controller.state.orientation = p;
|
||||||
controller.state.orientationId = controller.configBean.orientationMap.keys.toList()[position];
|
controller.state.orientationId =
|
||||||
|
controller.configBean.orientationMap.keys.toList()[position];
|
||||||
controller.update();
|
controller.update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
// ignore_for_file: camel_case_types
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:provider/provider.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/business_logic/view_models/tui_conversation_view_model.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/unread_message.dart';
|
||||||
|
|
||||||
|
typedef unreadCountBuilder = Widget Function(int unreadCount);
|
||||||
|
|
||||||
|
class TIMUIKitConversationTotalUnread extends TIMUIKitStatelessWidget {
|
||||||
|
final TUIConversationViewModel model =
|
||||||
|
serviceLocator<TUIConversationViewModel>();
|
||||||
|
final int? unreadCount;
|
||||||
|
final unreadCountBuilder? builder;
|
||||||
|
final double? width;
|
||||||
|
final double? height;
|
||||||
|
|
||||||
|
TIMUIKitConversationTotalUnread(
|
||||||
|
{this.width = 22.0,
|
||||||
|
this.height = 22.0,
|
||||||
|
this.unreadCount,
|
||||||
|
this.builder,
|
||||||
|
Key? key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
|
return MultiProvider(
|
||||||
|
providers: [
|
||||||
|
ChangeNotifierProvider.value(value: model),
|
||||||
|
],
|
||||||
|
child: Consumer<TUIConversationViewModel>(
|
||||||
|
builder: (context, value, child) {
|
||||||
|
if (value.totalUnReadCount == 0) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builder != null) {
|
||||||
|
return builder!(value.totalUnReadCount);
|
||||||
|
}
|
||||||
|
return UnreadMessage(
|
||||||
|
unreadCount: unreadCount ?? value.totalUnReadCount,
|
||||||
|
width: width,
|
||||||
|
height: height);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,465 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
||||||
|
import 'package:flutter_slidable_for_tencent_im/flutter_slidable.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:scroll_to_index/scroll_to_index.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_statelesswidget.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/conversation_life_cycle.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_conversation_view_model.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_friendship_view_model.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_wide_modal_operation_key.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/controller/tim_uikit_conversation_controller.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/views/TIMUIKitConversation/tim_uikit_conversation_item.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/customize_ball_pulse_header.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
|
||||||
|
|
||||||
|
import 'tim_uikit_conversation_item.dart';
|
||||||
|
|
||||||
|
typedef TIMConversationItemBuilder = Widget Function(
|
||||||
|
V2TimConversation conversationItem,
|
||||||
|
[V2TimUserStatus? onlineStatus]);
|
||||||
|
|
||||||
|
typedef ConversationItemSlideBuilder = List<ConversationItemSlidePanel>
|
||||||
|
Function(V2TimConversation conversationItem);
|
||||||
|
|
||||||
|
typedef ConversationItemSecondaryMenuBuilder = Widget Function(
|
||||||
|
V2TimConversation conversationItem, VoidCallback onClose);
|
||||||
|
|
||||||
|
class TIMConversation extends StatefulWidget {
|
||||||
|
/// the callback after clicking conversation item
|
||||||
|
final ValueChanged<V2TimConversation>? onTapItem;
|
||||||
|
|
||||||
|
/// conversation controller
|
||||||
|
final TIMUIKitConversationController? controller;
|
||||||
|
|
||||||
|
/// the builder for conversation item
|
||||||
|
final TIMConversationItemBuilder? itemBuilder;
|
||||||
|
|
||||||
|
/// the builder for Slidable item for each conversation item, shows on narrow screens.
|
||||||
|
final ConversationItemSlideBuilder? itemSlideBuilder;
|
||||||
|
|
||||||
|
/// the widget of secondary tap menu for each conversation item, shows on wide screens.
|
||||||
|
final ConversationItemSecondaryMenuBuilder? itemSecondaryMenuBuilder;
|
||||||
|
|
||||||
|
/// the widget shows when no conversation exists
|
||||||
|
final Widget Function()? emptyBuilder;
|
||||||
|
|
||||||
|
/// the filter for conversation
|
||||||
|
final bool Function(V2TimConversation? conversation)? conversationCollector;
|
||||||
|
|
||||||
|
/// the builder for the second line in each conservation item,
|
||||||
|
/// usually shows the summary of the last message
|
||||||
|
final LastMessageBuilder? lastMessageBuilder;
|
||||||
|
|
||||||
|
/// The life cycle hooks for `TIMUIKitConversation`
|
||||||
|
final ConversationLifeCycle? lifeCycle;
|
||||||
|
|
||||||
|
/// Control if shows the online status for each user on its avatar.
|
||||||
|
final bool isShowOnlineStatus;
|
||||||
|
|
||||||
|
/// Control if shows the identifier that the conversation has a draft text, inputted in previous.
|
||||||
|
/// Also, you have better specifying the `draftText` field for `TIMUIKitChat`, from the `draftText` in `V2TimConversation`,
|
||||||
|
/// to meet the identifier shows here.
|
||||||
|
final bool isShowDraft;
|
||||||
|
|
||||||
|
const TIMConversation(
|
||||||
|
{Key? key,
|
||||||
|
this.lifeCycle,
|
||||||
|
this.onTapItem,
|
||||||
|
this.controller,
|
||||||
|
this.itemSecondaryMenuBuilder,
|
||||||
|
this.itemBuilder,
|
||||||
|
this.isShowDraft = true,
|
||||||
|
this.itemSlideBuilder,
|
||||||
|
this.conversationCollector,
|
||||||
|
this.emptyBuilder,
|
||||||
|
this.lastMessageBuilder,
|
||||||
|
this.isShowOnlineStatus = true})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() {
|
||||||
|
return _TIMConversationState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConversationItemSlidePanel extends TIMUIKitStatelessWidget {
|
||||||
|
ConversationItemSlidePanel({
|
||||||
|
Key? key,
|
||||||
|
this.flex = 1,
|
||||||
|
this.backgroundColor = Colors.white,
|
||||||
|
this.foregroundColor,
|
||||||
|
this.autoClose = true,
|
||||||
|
required this.onPressed,
|
||||||
|
this.icon,
|
||||||
|
this.spacing = 4,
|
||||||
|
this.label,
|
||||||
|
}) : assert(flex > 0),
|
||||||
|
assert(icon != null || label != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
/// {@macro slidable.actions.flex}
|
||||||
|
final int flex;
|
||||||
|
|
||||||
|
/// {@macro slidable.actions.backgroundColor}
|
||||||
|
final Color backgroundColor;
|
||||||
|
|
||||||
|
/// {@macro slidable.actions.foregroundColor}
|
||||||
|
final Color? foregroundColor;
|
||||||
|
|
||||||
|
/// {@macro slidable.actions.autoClose}
|
||||||
|
final bool autoClose;
|
||||||
|
|
||||||
|
/// {@macro slidable.actions.onPressed}
|
||||||
|
final SlidableActionCallback? onPressed;
|
||||||
|
|
||||||
|
/// An icon to display above the [label].
|
||||||
|
final IconData? icon;
|
||||||
|
|
||||||
|
/// The space between [icon] and [label] if both set.
|
||||||
|
///
|
||||||
|
/// Defaults to 4.
|
||||||
|
final double spacing;
|
||||||
|
|
||||||
|
/// A label to display below the [icon].
|
||||||
|
final String? label;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
|
return SlidableAction(
|
||||||
|
onPressed: onPressed,
|
||||||
|
flex: flex,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
foregroundColor: foregroundColor,
|
||||||
|
autoClose: autoClose,
|
||||||
|
label: label,
|
||||||
|
spacing: spacing,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TIMConversationState extends TIMUIKitState<TIMConversation> {
|
||||||
|
final TUIConversationViewModel model =
|
||||||
|
serviceLocator<TUIConversationViewModel>();
|
||||||
|
late TIMUIKitConversationController _timuiKitConversationController;
|
||||||
|
final TUIThemeViewModel themeViewModel = serviceLocator<TUIThemeViewModel>();
|
||||||
|
final TUIFriendShipViewModel friendShipViewModel =
|
||||||
|
serviceLocator<TUIFriendShipViewModel>();
|
||||||
|
late AutoScrollController _autoScrollController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
final controller = getController();
|
||||||
|
_timuiKitConversationController = controller;
|
||||||
|
_timuiKitConversationController.model = model;
|
||||||
|
_autoScrollController = AutoScrollController();
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMUIKitConversationController getController() {
|
||||||
|
return widget.controller ?? TIMUIKitConversationController();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onTapConvItem(V2TimConversation conversation) {
|
||||||
|
if (widget.onTapItem != null) {
|
||||||
|
widget.onTapItem!(conversation);
|
||||||
|
}
|
||||||
|
model.setSelectedConversation(conversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
_clearHistory(V2TimConversation conversationItem) {
|
||||||
|
_timuiKitConversationController.clearHistoryMessage(
|
||||||
|
conversation: conversationItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pinConversation(V2TimConversation conversation) {
|
||||||
|
_timuiKitConversationController.pinConversation(
|
||||||
|
conversationID: conversation.conversationID,
|
||||||
|
isPinned: !conversation.isPinned!);
|
||||||
|
}
|
||||||
|
|
||||||
|
_deleteConversation(V2TimConversation conversation) {
|
||||||
|
_timuiKitConversationController.deleteConversation(
|
||||||
|
conversationID: conversation.conversationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<V2TimConversation?> getFilteredConversation() {
|
||||||
|
List<V2TimConversation?> filteredConversationList = model.conversationList
|
||||||
|
.where(
|
||||||
|
(element) => (element?.groupID != null || element?.userID != null))
|
||||||
|
.toList();
|
||||||
|
if (widget.conversationCollector != null) {
|
||||||
|
filteredConversationList = filteredConversationList
|
||||||
|
.where(widget.conversationCollector!)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
return filteredConversationList;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onScrollToConversation(String conversationID) {
|
||||||
|
final msgList = getFilteredConversation();
|
||||||
|
bool isFound = false;
|
||||||
|
int targetIndex = 1;
|
||||||
|
for (int i = msgList.length - 1; i >= 0; i--) {
|
||||||
|
final currentConversation = msgList[i];
|
||||||
|
if (currentConversation?.conversationID == conversationID) {
|
||||||
|
isFound = true;
|
||||||
|
targetIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFound) {
|
||||||
|
_autoScrollController.scrollToIndex(
|
||||||
|
targetIndex,
|
||||||
|
preferPosition: AutoScrollPosition.begin,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _defaultSecondaryMenu(
|
||||||
|
V2TimConversation conversationItem, VoidCallback onClose) {
|
||||||
|
return TUIKitColumnMenu(data: [
|
||||||
|
if (!PlatformUtils().isWeb)
|
||||||
|
ColumnMenuItem(
|
||||||
|
label: TIM_t("清除消息"),
|
||||||
|
icon: const Icon(Icons.clear_all, size: 16),
|
||||||
|
onClick: () {
|
||||||
|
onClose();
|
||||||
|
_clearHistory(conversationItem);
|
||||||
|
}),
|
||||||
|
ColumnMenuItem(
|
||||||
|
label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"),
|
||||||
|
icon: Icon(
|
||||||
|
conversationItem.isPinned!
|
||||||
|
? Icons.vertical_align_bottom
|
||||||
|
: Icons.vertical_align_top,
|
||||||
|
size: 16),
|
||||||
|
onClick: () {
|
||||||
|
onClose();
|
||||||
|
_pinConversation(conversationItem);
|
||||||
|
}),
|
||||||
|
ColumnMenuItem(
|
||||||
|
label: TIM_t("删除会话"),
|
||||||
|
icon: const Icon(Icons.delete_outline, size: 16),
|
||||||
|
onClick: () {
|
||||||
|
onClose();
|
||||||
|
_deleteConversation(conversationItem);
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ConversationItemSlidePanel> _defaultSlideBuilder(
|
||||||
|
V2TimConversation conversationItem,
|
||||||
|
) {
|
||||||
|
final theme = themeViewModel.theme;
|
||||||
|
return [
|
||||||
|
if (!PlatformUtils().isWeb)
|
||||||
|
ConversationItemSlidePanel(
|
||||||
|
onPressed: (context) {
|
||||||
|
_clearHistory(conversationItem);
|
||||||
|
},
|
||||||
|
backgroundColor: theme.conversationItemSliderClearBgColor ??
|
||||||
|
CommonColor.primaryColor,
|
||||||
|
foregroundColor: theme.conversationItemSliderTextColor,
|
||||||
|
label: TIM_t("清除聊天"),
|
||||||
|
spacing: 0,
|
||||||
|
autoClose: true,
|
||||||
|
),
|
||||||
|
ConversationItemSlidePanel(
|
||||||
|
onPressed: (context) {
|
||||||
|
_pinConversation(conversationItem);
|
||||||
|
},
|
||||||
|
backgroundColor:
|
||||||
|
theme.conversationItemSliderPinBgColor ?? CommonColor.infoColor,
|
||||||
|
foregroundColor: theme.conversationItemSliderTextColor,
|
||||||
|
label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"),
|
||||||
|
),
|
||||||
|
ConversationItemSlidePanel(
|
||||||
|
onPressed: (context) {
|
||||||
|
_deleteConversation(conversationItem);
|
||||||
|
},
|
||||||
|
backgroundColor:
|
||||||
|
theme.conversationItemSliderDeleteBgColor ?? Colors.red,
|
||||||
|
foregroundColor: theme.conversationItemSliderTextColor,
|
||||||
|
label: TIM_t("删除"),
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _getSecondaryMenu(
|
||||||
|
V2TimConversation conversation, VoidCallback onClose) {
|
||||||
|
if (widget.itemSecondaryMenuBuilder != null) {
|
||||||
|
return widget.itemSecondaryMenuBuilder!(conversation, onClose);
|
||||||
|
}
|
||||||
|
return _defaultSecondaryMenu(conversation, onClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConversationItemSlideBuilder _getSlideBuilder() {
|
||||||
|
return widget.itemSlideBuilder ?? _defaultSlideBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
|
final theme = value.theme;
|
||||||
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
|
return MultiProvider(
|
||||||
|
providers: [
|
||||||
|
ChangeNotifierProvider.value(value: model),
|
||||||
|
ChangeNotifierProvider.value(value: friendShipViewModel)
|
||||||
|
],
|
||||||
|
builder: (BuildContext context, Widget? w) {
|
||||||
|
final _model = Provider.of<TUIConversationViewModel>(context);
|
||||||
|
bool haveMoreData = _model.haveMoreData;
|
||||||
|
final _friendShipViewModel =
|
||||||
|
Provider.of<TUIFriendShipViewModel>(context);
|
||||||
|
_model.lifeCycle = widget.lifeCycle;
|
||||||
|
|
||||||
|
List<V2TimConversation?> filteredConversationList =
|
||||||
|
getFilteredConversation();
|
||||||
|
|
||||||
|
if (TencentUtils.checkString(_model.scrollToConversation) != null) {
|
||||||
|
_onScrollToConversation(_model.scrollToConversation!);
|
||||||
|
_model.clearScrollToConversation();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget conversationList() {
|
||||||
|
return filteredConversationList.isNotEmpty
|
||||||
|
? ListView.builder(
|
||||||
|
controller: _autoScrollController,
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: filteredConversationList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == filteredConversationList.length - 1) {
|
||||||
|
if (haveMoreData) {
|
||||||
|
_timuiKitConversationController.loadData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final conversationItem = filteredConversationList[index];
|
||||||
|
|
||||||
|
final V2TimUserStatus? onlineStatus =
|
||||||
|
_friendShipViewModel.userStatusList.firstWhere(
|
||||||
|
(item) => item.userID == conversationItem?.userID,
|
||||||
|
orElse: () => V2TimUserStatus(statusType: 0));
|
||||||
|
|
||||||
|
if (widget.itemBuilder != null) {
|
||||||
|
return widget.itemBuilder!(
|
||||||
|
conversationItem!, onlineStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
final slideChildren =
|
||||||
|
_getSlideBuilder()(conversationItem!);
|
||||||
|
|
||||||
|
final isCurrent = conversationItem.conversationID ==
|
||||||
|
model.selectedConversation?.conversationID;
|
||||||
|
|
||||||
|
final isPined = conversationItem.isPinned ?? false;
|
||||||
|
|
||||||
|
Widget conversationLineItem() {
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
child: TIMConversationItem(
|
||||||
|
isCurrent: isCurrent,
|
||||||
|
isShowDraft: widget.isShowDraft,
|
||||||
|
lastMessageBuilder: widget.lastMessageBuilder,
|
||||||
|
faceUrl: conversationItem.faceUrl ?? "",
|
||||||
|
nickName: conversationItem.showName ?? "",
|
||||||
|
isDisturb: conversationItem.recvOpt != 0,
|
||||||
|
lastMsg: conversationItem.lastMessage,
|
||||||
|
isPined: isPined,
|
||||||
|
groupAtInfoList:
|
||||||
|
conversationItem.groupAtInfoList ?? [],
|
||||||
|
unreadCount: conversationItem.unreadCount ?? 0,
|
||||||
|
draftText: conversationItem.draftText,
|
||||||
|
onlineStatus: (widget.isShowOnlineStatus &&
|
||||||
|
conversationItem.userID != null &&
|
||||||
|
conversationItem.userID!.isNotEmpty)
|
||||||
|
? onlineStatus
|
||||||
|
: null,
|
||||||
|
draftTimestamp: conversationItem.draftTimestamp,
|
||||||
|
convType: conversationItem.type),
|
||||||
|
onTap: () => onTapConvItem(conversationItem),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TUIKitScreenUtils.getDeviceWidget(
|
||||||
|
desktopWidget: AutoScrollTag(
|
||||||
|
key: ValueKey(conversationItem.conversationID),
|
||||||
|
controller: _autoScrollController,
|
||||||
|
index: index,
|
||||||
|
child: GestureDetector(
|
||||||
|
onSecondaryTapDown: (details) {
|
||||||
|
TUIKitWidePopup.showPopupWindow(
|
||||||
|
operationKey: TUIKitWideModalOperationKey
|
||||||
|
.conversationSecondaryMenu,
|
||||||
|
isDarkBackground: false,
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(4)),
|
||||||
|
context: context,
|
||||||
|
offset: Offset(
|
||||||
|
min(
|
||||||
|
details.globalPosition.dx,
|
||||||
|
MediaQuery.of(context).size.width -
|
||||||
|
80),
|
||||||
|
min(
|
||||||
|
details.globalPosition.dy,
|
||||||
|
MediaQuery.of(context).size.height -
|
||||||
|
130)),
|
||||||
|
child: (onClose) => _getSecondaryMenu(
|
||||||
|
conversationItem, onClose));
|
||||||
|
},
|
||||||
|
child: conversationLineItem(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
defaultWidget: AutoScrollTag(
|
||||||
|
key: ValueKey(conversationItem.conversationID),
|
||||||
|
controller: _autoScrollController,
|
||||||
|
index: index,
|
||||||
|
child: Slidable(
|
||||||
|
groupTag: 'conversation-list',
|
||||||
|
child: conversationLineItem(),
|
||||||
|
endActionPane: ActionPane(
|
||||||
|
extentRatio:
|
||||||
|
slideChildren.length > 2 ? 0.77 : 0.5,
|
||||||
|
motion: const DrawerMotion(),
|
||||||
|
children: slideChildren)),
|
||||||
|
));
|
||||||
|
})
|
||||||
|
: (widget.emptyBuilder != null
|
||||||
|
? widget.emptyBuilder!()
|
||||||
|
: Container());
|
||||||
|
}
|
||||||
|
|
||||||
|
return TUIKitScreenUtils.getDeviceWidget(
|
||||||
|
defaultWidget: SlidableAutoCloseBehavior(
|
||||||
|
child: EasyRefresh(
|
||||||
|
header: CustomizeBallPulseHeader(color: theme.primaryColor),
|
||||||
|
onRefresh: () async {
|
||||||
|
model.refresh();
|
||||||
|
},
|
||||||
|
child: conversationList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
desktopWidget: Scrollbar(
|
||||||
|
controller: _autoScrollController,
|
||||||
|
child: conversationList()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
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_im_base/tencent_im_base.dart';
|
||||||
|
|
||||||
|
class TIMUIKitDraftText extends TIMUIKitStatelessWidget {
|
||||||
|
final BuildContext context;
|
||||||
|
final String draftText;
|
||||||
|
final double fontSize;
|
||||||
|
|
||||||
|
TIMUIKitDraftText({
|
||||||
|
Key? key,
|
||||||
|
this.fontSize = 14.0,
|
||||||
|
required this.context,
|
||||||
|
required this.draftText,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
String _getDraftShowText() {
|
||||||
|
final draftShowText = TIM_t("草稿");
|
||||||
|
|
||||||
|
return '[$draftShowText] ';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
|
final TUITheme theme = value.theme;
|
||||||
|
return Row(children: [
|
||||||
|
Text(_getDraftShowText(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme.conversationItemDraftTextColor,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
draftText,
|
||||||
|
softWrap: true,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(
|
||||||
|
height: 1.5,
|
||||||
|
color: theme.conversationItemLastMessageTextColor,
|
||||||
|
fontSize: fontSize),
|
||||||
|
)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,206 @@
|
|||||||
|
// ignore_for_file: empty_catches
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitConversation/tim_uikit_conversation_item.dart';
|
||||||
|
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
|
||||||
|
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/utils/time_ago.dart';
|
||||||
|
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitConversation/tim_uikit_conversation_draft_text.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitConversation/tim_uikit_conversation_last_msg.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/unread_message.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class TIMConversationItem extends TIMUIKitStatelessWidget {
|
||||||
|
final String faceUrl;
|
||||||
|
final String nickName;
|
||||||
|
final V2TimMessage? lastMsg;
|
||||||
|
final int unreadCount;
|
||||||
|
final bool isPined;
|
||||||
|
final List<V2TimGroupAtInfo?> groupAtInfoList;
|
||||||
|
final String? draftText;
|
||||||
|
final int? draftTimestamp;
|
||||||
|
final bool isDisturb;
|
||||||
|
final LastMessageBuilder? lastMessageBuilder;
|
||||||
|
final V2TimUserStatus? onlineStatus;
|
||||||
|
final int? convType;
|
||||||
|
final bool isCurrent;
|
||||||
|
|
||||||
|
/// Control if shows the identifier that the conversation has a draft text, inputted in previous.
|
||||||
|
/// Also, you'd better specifying the `draftText` field for `TIMUIKitChat`, from the `draftText` in `V2TimConversation`,
|
||||||
|
/// to meet the identifier shows here.
|
||||||
|
final bool isShowDraft;
|
||||||
|
|
||||||
|
TIMConversationItem({
|
||||||
|
Key? key,
|
||||||
|
required this.isShowDraft,
|
||||||
|
required this.faceUrl,
|
||||||
|
required this.nickName,
|
||||||
|
required this.lastMsg,
|
||||||
|
this.onlineStatus,
|
||||||
|
required this.isPined,
|
||||||
|
this.isCurrent = false,
|
||||||
|
required this.unreadCount,
|
||||||
|
required this.groupAtInfoList,
|
||||||
|
required this.isDisturb,
|
||||||
|
this.draftText,
|
||||||
|
this.draftTimestamp,
|
||||||
|
this.lastMessageBuilder,
|
||||||
|
this.convType,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
Widget _getShowMsgWidget(BuildContext context) {
|
||||||
|
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
|
if (isShowDraft && draftText != null && draftText != "") {
|
||||||
|
return TIMUIKitDraftText(
|
||||||
|
context: context,
|
||||||
|
draftText: draftText ?? "",
|
||||||
|
fontSize: isDesktopScreen ? 12 : 14,
|
||||||
|
);
|
||||||
|
} else if (lastMsg != null) {
|
||||||
|
if (lastMessageBuilder != null &&
|
||||||
|
lastMessageBuilder!(lastMsg, groupAtInfoList) != null) {
|
||||||
|
return lastMessageBuilder!(lastMsg, groupAtInfoList)!;
|
||||||
|
}
|
||||||
|
return TIMUIKitLastMsg(
|
||||||
|
fontSize: isDesktopScreen ? 12 : 14,
|
||||||
|
groupAtInfoList: groupAtInfoList,
|
||||||
|
lastMsg: lastMsg,
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
height: 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHaveSecondLine() {
|
||||||
|
return (isShowDraft && draftText != null && draftText != "") ||
|
||||||
|
(lastMsg != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _getTimeStringForChatWidget(BuildContext context, TUITheme theme) {
|
||||||
|
try {
|
||||||
|
if (draftTimestamp != null && draftTimestamp != 0) {
|
||||||
|
return Text(TimeAgo().getTimeStringForChat(draftTimestamp as int),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: theme.conversationItemTitmeTextColor,
|
||||||
|
));
|
||||||
|
} else if (lastMsg != null) {
|
||||||
|
return Text(TimeAgo().getTimeStringForChat(lastMsg!.timestamp as int),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: theme.conversationItemTitmeTextColor,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
|
final TUITheme theme = value.theme;
|
||||||
|
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.only(top: 6, bottom: 6, left: 16, right: 16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
|
|
||||||
|
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(top: 0, bottom: 2, right: 0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: isDesktopScreen ? 40 : 44,
|
||||||
|
height: isDesktopScreen ? 40 : 44,
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
clipBehavior: Clip.none,
|
||||||
|
children: [
|
||||||
|
ClipOval(
|
||||||
|
child: Avatar(
|
||||||
|
onlineStatus: onlineStatus,
|
||||||
|
faceUrl: faceUrl,
|
||||||
|
showName: nickName,
|
||||||
|
type: convType),
|
||||||
|
),
|
||||||
|
if (unreadCount != 0)
|
||||||
|
Positioned(
|
||||||
|
top: isDisturb ? -2.5 : -4.5,
|
||||||
|
right: isDisturb ? -2.5 : -4.5,
|
||||||
|
child: UnconstrainedBox(
|
||||||
|
child: UnreadMessage(
|
||||||
|
width: isDisturb ? 10 : 18,
|
||||||
|
height: isDisturb ? 10 : 18,
|
||||||
|
unreadCount: isDisturb ? 0 : unreadCount),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
height: 60,
|
||||||
|
margin: EdgeInsets.only(left: isDesktopScreen ? 10 : 12),
|
||||||
|
padding: const EdgeInsets.only(top: 0, bottom: 0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
nickName,
|
||||||
|
softWrap: true,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(
|
||||||
|
height: 1,
|
||||||
|
color: Color(0xFFF7FAFA),
|
||||||
|
fontSize: isDesktopScreen ? 14 : 18,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
_getTimeStringForChatWidget(context, theme),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (isHaveSecondLine())
|
||||||
|
const SizedBox(
|
||||||
|
height: 6,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: _getShowMsgWidget(context)),
|
||||||
|
if (isDisturb)
|
||||||
|
SizedBox(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
child: Icon(
|
||||||
|
Icons.notifications_off,
|
||||||
|
color: theme.conversationItemNoNotificationIconColor,
|
||||||
|
size: isDesktopScreen ? 14 : 16.0,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,152 @@
|
|||||||
|
// ignore_for_file: unrelated_type_equality_checks
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||||
|
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';
|
||||||
|
|
||||||
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||||
|
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||||
|
|
||||||
|
class TIMUIKitLastMsg extends StatefulWidget {
|
||||||
|
final V2TimMessage? lastMsg;
|
||||||
|
final List<V2TimGroupAtInfo?> groupAtInfoList;
|
||||||
|
final BuildContext context;
|
||||||
|
final double fontSize;
|
||||||
|
|
||||||
|
const TIMUIKitLastMsg(
|
||||||
|
{Key? key,
|
||||||
|
this.lastMsg,
|
||||||
|
required this.groupAtInfoList,
|
||||||
|
required this.context,
|
||||||
|
this.fontSize = 14.0})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<TIMUIKitLastMsg> createState() => _TIMUIKitLastMsgState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TIMUIKitLastMsgState extends TIMUIKitState<TIMUIKitLastMsg> {
|
||||||
|
String groupTipsAbstractText = "";
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_getMsgElem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant TIMUIKitLastMsg oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if ((oldWidget.lastMsg?.msgID != widget.lastMsg?.msgID) ||
|
||||||
|
(oldWidget.lastMsg?.id != widget.lastMsg?.id)) {
|
||||||
|
_getMsgElem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getMsgElem() async {
|
||||||
|
final isRevokedMessage = widget.lastMsg!.status == 6;
|
||||||
|
if (isRevokedMessage) {
|
||||||
|
final isSelf = widget.lastMsg!.isSelf ?? true;
|
||||||
|
final option1 = isSelf
|
||||||
|
? TIM_t("您")
|
||||||
|
: widget.lastMsg!.nickName ?? widget.lastMsg?.sender;
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
groupTipsAbstractText = TIM_t_para(
|
||||||
|
"{{option1}}撤回了一条消息", "$option1撤回了一条消息")(option1: option1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final newText = await _getLastMsgShowText(widget.lastMsg, widget.context);
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
groupTipsAbstractText = newText;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> _getLastMsgShowText(
|
||||||
|
V2TimMessage? message, BuildContext context) async {
|
||||||
|
final msgType = message!.elemType;
|
||||||
|
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 (widget.lastMsg?.textElem?.text)?.trim() ?? "";
|
||||||
|
case MessageElemType.V2TIM_ELEM_TYPE_FACE:
|
||||||
|
return TIM_t("[表情]");
|
||||||
|
case MessageElemType.V2TIM_ELEM_TYPE_FILE:
|
||||||
|
final option1 = widget.lastMsg!.fileElem!.fileName;
|
||||||
|
return TIM_t_para("[文件] {{option1}}", "[文件] $option1")(
|
||||||
|
option1: option1);
|
||||||
|
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
|
||||||
|
return await MessageUtils.groupTipsMessageAbstract(
|
||||||
|
widget.lastMsg!.groupTipsElem!, []);
|
||||||
|
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("未知消息");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Icon? _getIconByMsgStatus(BuildContext context) {
|
||||||
|
final msgStatus = widget.lastMsg!.status;
|
||||||
|
final theme = Provider.of<TUIThemeViewModel>(context).theme;
|
||||||
|
if (msgStatus == MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL) {
|
||||||
|
return Icon(Icons.error, color: theme.cautionColor, size: 16);
|
||||||
|
}
|
||||||
|
if (msgStatus == MessageStatus.V2TIM_MSG_STATUS_SENDING) {
|
||||||
|
return Icon(Icons.arrow_back, color: theme.weakTextColor, size: 16);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getAtMessage() {
|
||||||
|
String msg = "";
|
||||||
|
for (var item in widget.groupAtInfoList) {
|
||||||
|
if (item!.atType == 1) {
|
||||||
|
msg = TIM_t("[有人@我] ");
|
||||||
|
} else {
|
||||||
|
msg = TIM_t("[@所有人] ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
|
final TUITheme theme = value.theme;
|
||||||
|
final icon = _getIconByMsgStatus(context);
|
||||||
|
return Row(children: [
|
||||||
|
if (icon != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(right: 2),
|
||||||
|
child: icon,
|
||||||
|
),
|
||||||
|
if (widget.groupAtInfoList.isNotEmpty)
|
||||||
|
Text(_getAtMessage(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme.cautionColor, fontSize: widget.fontSize)),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
groupTipsAbstractText,
|
||||||
|
softWrap: true,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
height: 1, color: theme.weakTextColor, fontSize: widget.fontSize),
|
||||||
|
)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,8 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
||||||
|
|
||||||
|
|
||||||
|
import 'TIMUIKitConversation/tim_uikit_conversation.dart';
|
||||||
import 'logic.dart';
|
import 'logic.dart';
|
||||||
|
|
||||||
class MsgPage extends StatelessWidget {
|
class MsgPage extends StatelessWidget {
|
||||||
@ -210,10 +212,14 @@ class MsgPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
msgWdiget(context) {
|
msgWdiget(context) {
|
||||||
return TIMUIKitConversation(
|
return TIMConversation(
|
||||||
onTapItem: (selectedConv) {
|
onTapItem: (selectedConv) {
|
||||||
Get.toNamed(AppRoutes.Chat);
|
Get.toNamed(AppRoutes.Chat);
|
||||||
}
|
},
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Widget msgItem(conv,status){
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class SplashLogic extends GetxController {
|
|||||||
@override
|
@override
|
||||||
void onInit() async{
|
void onInit() async{
|
||||||
super.onInit();
|
super.onInit();
|
||||||
if(getAuthorization()==''){
|
if((await getAuthorization()).isEmpty){
|
||||||
Get.toNamed(AppRoutes.Login);
|
Get.toNamed(AppRoutes.Login);
|
||||||
}else{
|
}else{
|
||||||
var data =
|
var data =
|
||||||
|
|||||||
@ -171,7 +171,6 @@ class DioManager {
|
|||||||
// json转model
|
// json转model
|
||||||
String jsonStr = json.encode(response.data);
|
String jsonStr = json.encode(response.data);
|
||||||
Map<String, dynamic> responseMap = json.decode(jsonStr);
|
Map<String, dynamic> responseMap = json.decode(jsonStr);
|
||||||
|
|
||||||
return responseMap;
|
return responseMap;
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
// // DioError是指返回值不为200的情况
|
// // DioError是指返回值不为200的情况
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import desktop_drop
|
|||||||
import device_info_plus_macos
|
import device_info_plus_macos
|
||||||
import fc_native_video_thumbnail_for_us
|
import fc_native_video_thumbnail_for_us
|
||||||
import file_selector_macos
|
import file_selector_macos
|
||||||
|
import geolocator_apple
|
||||||
import package_info_plus_macos
|
import package_info_plus_macos
|
||||||
import pasteboard
|
import pasteboard
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||||
FcNativeVideoThumbnailPlugin.register(with: registry.registrar(forPlugin: "FcNativeVideoThumbnailPlugin"))
|
FcNativeVideoThumbnailPlugin.register(with: registry.registrar(forPlugin: "FcNativeVideoThumbnailPlugin"))
|
||||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||||
|
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
|
||||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||||
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin"))
|
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user