修改会话列表UI,完善资料UI,跳转逻辑

This commit is contained in:
CYH 2023-06-20 12:31:47 +08:00
parent 8bfb1814ae
commit a74025c4c4
11 changed files with 964 additions and 47 deletions

View File

@ -67,6 +67,7 @@ class Complete_materialLogic extends GetxController {
_setImageFileListFromFile(pickedFile!);
// });
} catch (e) {
print(e);
// setState(() {
// _pickImageError = e;
// });
@ -141,7 +142,7 @@ class Complete_materialLogic extends GetxController {
});
var bean = BaseResponse<String>.fromJson(data, (data) => data);
if (bean.code == 200) {
Get.toNamed(AppRoutes.Home);
Get.offAllNamed(AppRoutes.Home);
}
}

View File

@ -73,7 +73,7 @@ class Complete_materialPage extends StatelessWidget {
height: 15.sp,
),
Text(
'数据表明95%的人对完整的兽设更感兴趣',
'数据表明95%的人对真实的头像更感兴趣',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
@ -148,13 +148,18 @@ class Complete_materialPage extends StatelessWidget {
funcWidget(
'兴趣',
Row(
children: [interestWdiget('JK圈',controller)],
),
() async {
controller.numbers = await Get.toNamed(AppRoutes.SelectCircleActivity,arguments: controller.configBean.interestMap);
controller.update();
}),
children: controller.numbers.isNotEmpty
? [interestWdiget('JK圈', controller)]
: [],
), () async {
var data = await Get.toNamed(
AppRoutes.SelectCircleActivity,
arguments: controller.configBean.interestMap);
if (data != null) {
controller.numbers = data;
controller.update();
}
}),
Container(
margin: EdgeInsets.only(
top: 24.sp,
@ -194,7 +199,7 @@ class Complete_materialPage extends StatelessWidget {
GestureDetector(
onTap: () {
if (controller.type == "user") {
// Navigator.pop(context);
// Navigator.pop(context);
controller.editInfo();
} else {
controller.checkInfo();
@ -285,7 +290,7 @@ class Complete_materialPage extends StatelessWidget {
);
}
interestWdiget(String interest,Complete_materialLogic controller) {
interestWdiget(String interest, Complete_materialLogic controller) {
return Container(
height: 59.sp,
width: 240.sp,
@ -300,35 +305,18 @@ class Complete_materialPage extends StatelessWidget {
return Container(
margin: EdgeInsets.only(right: 11.sp), // item
child: Container(
height: 34.sp,
padding: EdgeInsets.only(left: 15.sp, right: 15.sp),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(17.0), //
gradient: LinearGradient(
colors: [
Color(0xFFffffff),
Color(0xFFffffff),
],
),
borderRadius: BorderRadius.circular(17.0.sp), //
border: Border.all(color: Colors.white, width: 1.sp),
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(
controller.numbers[index].name,
style: TextStyle(
fontSize: 12.0,
color: Colors.white,
),
),
),
child: Text(
controller.numbers[index].name,
style: TextStyle(
fontSize: 12.0.sp,
color: Colors.white,
),
),
), //
@ -362,7 +350,8 @@ class Complete_materialPage extends StatelessWidget {
? controller.state.sex
: '', onConfirm: (p, position) {
controller.state.sex = p;
controller.state.genderId = controller.configBean.genderMap.keys.toList()[position];
controller.state.genderId =
controller.configBean.genderMap.keys.toList()[position];
controller.update();
});
}
@ -408,7 +397,8 @@ class Complete_materialPage extends StatelessWidget {
? controller.state.role
: 'Sado', onConfirm: (p, position) {
controller.state.role = p;
controller.state.roleId = controller.configBean.roleMap.keys.toList()[position];
controller.state.roleId =
controller.configBean.roleMap.keys.toList()[position];
controller.update();
});
}
@ -422,11 +412,9 @@ class Complete_materialPage extends StatelessWidget {
? controller.state.orientation
: '异性恋', onConfirm: (p, position) {
controller.state.orientation = p;
controller.state.orientationId = controller.configBean.orientationMap.keys.toList()[position];
controller.state.orientationId =
controller.configBean.orientationMap.keys.toList()[position];
controller.update();
});
}
}

View File

@ -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);
},
),
);
}
}

View File

@ -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()));
});
}
}

View File

@ -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),
)),
]);
}
}

View File

@ -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,
),
)
],
),
],
),
))
],
),
);
}
}

View File

@ -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),
)),
]);
}
}

View File

@ -5,6 +5,8 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'TIMUIKitConversation/tim_uikit_conversation.dart';
import 'logic.dart';
class MsgPage extends StatelessWidget {
@ -210,10 +212,14 @@ class MsgPage extends StatelessWidget {
}
msgWdiget(context) {
return TIMUIKitConversation(
return TIMConversation(
onTapItem: (selectedConv) {
Get.toNamed(AppRoutes.Chat);
}
},
);
}
Widget msgItem(conv,status){
return Container();
}
}

View File

@ -15,7 +15,7 @@ class SplashLogic extends GetxController {
@override
void onInit() async{
super.onInit();
if(getAuthorization()==''){
if((await getAuthorization()).isEmpty){
Get.toNamed(AppRoutes.Login);
}else{
var data =

View File

@ -171,7 +171,6 @@ class DioManager {
// json转model
String jsonStr = json.encode(response.data);
Map<String, dynamic> responseMap = json.decode(jsonStr);
return responseMap;
} on DioException catch (e) {
// // DioError是指返回值不为200的情况

View File

@ -10,6 +10,7 @@ import desktop_drop
import device_info_plus_macos
import fc_native_video_thumbnail_for_us
import file_selector_macos
import geolocator_apple
import package_info_plus_macos
import pasteboard
import path_provider_foundation
@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FcNativeVideoThumbnailPlugin.register(with: registry.registrar(forPlugin: "FcNativeVideoThumbnailPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))