通讯录部分页面
This commit is contained in:
@@ -14,6 +14,8 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- path_provider_ios (0.0.1):
|
- path_provider_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- permission_handler_apple (9.0.4):
|
||||||
|
- Flutter
|
||||||
- photo_manager (2.0.0):
|
- photo_manager (2.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -35,6 +37,8 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- video_player_avfoundation (0.0.1):
|
- video_player_avfoundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- wakelock (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
@@ -42,6 +46,7 @@ DEPENDENCIES:
|
|||||||
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
|
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
|
||||||
- open_file (from `.symlinks/plugins/open_file/ios`)
|
- open_file (from `.symlinks/plugins/open_file/ios`)
|
||||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
||||||
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
|
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
|
||||||
- scan (from `.symlinks/plugins/scan/ios`)
|
- scan (from `.symlinks/plugins/scan/ios`)
|
||||||
- smart_auth (from `.symlinks/plugins/smart_auth/ios`)
|
- smart_auth (from `.symlinks/plugins/smart_auth/ios`)
|
||||||
@@ -49,6 +54,7 @@ DEPENDENCIES:
|
|||||||
- tencent_im_sdk_plugin (from `.symlinks/plugins/tencent_im_sdk_plugin/ios`)
|
- tencent_im_sdk_plugin (from `.symlinks/plugins/tencent_im_sdk_plugin/ios`)
|
||||||
- vibration (from `.symlinks/plugins/vibration/ios`)
|
- vibration (from `.symlinks/plugins/vibration/ios`)
|
||||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
|
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
|
||||||
|
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
@@ -69,6 +75,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/open_file/ios"
|
:path: ".symlinks/plugins/open_file/ios"
|
||||||
path_provider_ios:
|
path_provider_ios:
|
||||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
:path: ".symlinks/plugins/path_provider_ios/ios"
|
||||||
|
permission_handler_apple:
|
||||||
|
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||||
photo_manager:
|
photo_manager:
|
||||||
:path: ".symlinks/plugins/photo_manager/ios"
|
:path: ".symlinks/plugins/photo_manager/ios"
|
||||||
scan:
|
scan:
|
||||||
@@ -83,6 +91,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/vibration/ios"
|
:path: ".symlinks/plugins/vibration/ios"
|
||||||
video_player_avfoundation:
|
video_player_avfoundation:
|
||||||
:path: ".symlinks/plugins/video_player_avfoundation/ios"
|
:path: ".symlinks/plugins/video_player_avfoundation/ios"
|
||||||
|
wakelock:
|
||||||
|
:path: ".symlinks/plugins/wakelock/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
@@ -92,6 +102,7 @@ SPEC CHECKSUMS:
|
|||||||
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
|
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
|
||||||
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
|
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||||
|
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
||||||
photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604
|
photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604
|
||||||
scan: aea35bb4aa59ccc8839c576a18cd57c7d492cc86
|
scan: aea35bb4aa59ccc8839c576a18cd57c7d492cc86
|
||||||
smart_auth: 4bedbc118723912d0e45a07e8ab34039c19e04f2
|
smart_auth: 4bedbc118723912d0e45a07e8ab34039c19e04f2
|
||||||
@@ -102,6 +113,7 @@ SPEC CHECKSUMS:
|
|||||||
TXIMSDK_Plus_iOS: 5412f55a77f058b2b5a8575900334daccbae3b08
|
TXIMSDK_Plus_iOS: 5412f55a77f058b2b5a8575900334daccbae3b08
|
||||||
vibration: 7d883d141656a1c1a6d8d238616b2042a51a1241
|
vibration: 7d883d141656a1c1a6d8d238616b2042a51a1241
|
||||||
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
|
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
|
||||||
|
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||||
|
|
||||||
PODFILE CHECKSUM: a75497545d4391e2d394c3668e20cfb1c2bbd4aa
|
PODFILE CHECKSUM: a75497545d4391e2d394c3668e20cfb1c2bbd4aa
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ abstract class ContactRoutes {
|
|||||||
static const String friend = '/contact/friend';
|
static const String friend = '/contact/friend';
|
||||||
static const String friendSearch = '/contact/friend/search';
|
static const String friendSearch = '/contact/friend/search';
|
||||||
static const String friendProfile = '/contact/friend/profile';
|
static const String friendProfile = '/contact/friend/profile';
|
||||||
|
static const String friendProfileMore = '/contact/friend/profile';
|
||||||
|
static const String friendRemark = '/contact/friend/profile';
|
||||||
|
static const String friendApply = '/contact/friend/profile';
|
||||||
|
static const String friendRecommend = '/contact/friend/profile';
|
||||||
|
|
||||||
static const String group = '/contact/group';
|
static const String group = '/contact/group';
|
||||||
static const String groupQrCode = '/contact/group/qrCode';
|
static const String groupQrCode = '/contact/group/qrCode';
|
||||||
|
|||||||
147
lib/views/contact/firend/profile/index_page.dart
Normal file
147
lib/views/contact/firend/profile/index_page.dart
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/routes/contact_routes.dart';
|
||||||
|
import 'package:chat/routes/conversation_routes.dart';
|
||||||
|
import 'package:chat/routes/moments_routes.dart';
|
||||||
|
import 'package:chat/services/tim/conversation_service.dart';
|
||||||
|
import 'package:chat/utils/im_tools.dart';
|
||||||
|
import 'package:chat/views/home/widgets/action_button.dart';
|
||||||
|
import 'package:chat/views/home/widgets/action_item.dart';
|
||||||
|
import 'package:chat/widgets/custom_avatar.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class ImFriendProfilePage extends StatelessWidget {
|
||||||
|
const ImFriendProfilePage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GetX<PrivateController>(builder: (_) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: AppColors.white,
|
||||||
|
actions: [
|
||||||
|
Visibility(
|
||||||
|
visible: _.currentFriend.value.isFriend,
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendProfileMore,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.more_horiz,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
color: AppColors.white,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
CustomAvatar(
|
||||||
|
_.currentFriend.value.userProfile?.faceUrl,
|
||||||
|
size: 54,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
_.currentFriend.value.conversation!.showName!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('昵称:${_.currentFriend.value.userProfile?.nickName}'),
|
||||||
|
// Text('区块链地址:$friendId'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 0),
|
||||||
|
ActionItem(
|
||||||
|
'设置备注',
|
||||||
|
extend: _.currentFriend.value.friendRemark,
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendRemark,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
ActionItem(
|
||||||
|
'他的动态',
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(
|
||||||
|
MomentsRoutes.user,
|
||||||
|
arguments: {
|
||||||
|
'userId': _.currentFriend.value.userID,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Visibility(
|
||||||
|
visible: !_.currentFriend.value.isFriend,
|
||||||
|
child: ActionButton(
|
||||||
|
'添加到通讯录',
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendApply,
|
||||||
|
arguments: {
|
||||||
|
'userID': _.currentFriend.value.userID,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: _.currentFriend.value.isFriend,
|
||||||
|
child: ActionButton(
|
||||||
|
'发消息',
|
||||||
|
color: AppColors.primary,
|
||||||
|
onTap: () async {
|
||||||
|
var result = await TimConversationService
|
||||||
|
.to.conversationManager
|
||||||
|
.getConversation(
|
||||||
|
conversationID: 'c2c_' + _.currentFriend.value.userID,
|
||||||
|
);
|
||||||
|
if (result.code == 0) {
|
||||||
|
Get.toNamed(
|
||||||
|
ConversationRoutes.index,
|
||||||
|
arguments: {
|
||||||
|
'conversation': result.data,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: _.currentFriend.value.isFriend,
|
||||||
|
child: const Divider(height: 0),
|
||||||
|
),
|
||||||
|
Visibility(
|
||||||
|
visible: _.currentFriend.value.isFriend,
|
||||||
|
child: ActionButton(
|
||||||
|
'音视频通话',
|
||||||
|
color: AppColors.primary,
|
||||||
|
onTap: () {
|
||||||
|
ImTools.showTrtcMessage(_.currentFriend.value.userID);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
105
lib/views/contact/firend/profile/more_page.dart
Normal file
105
lib/views/contact/firend/profile/more_page.dart
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/routes/contact_routes.dart';
|
||||||
|
import 'package:chat/services/tim/friend_service.dart';
|
||||||
|
import 'package:chat/utils/ui_tools.dart';
|
||||||
|
import 'package:chat/views/home/widgets/action_button.dart';
|
||||||
|
import 'package:chat/views/home/widgets/action_item.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class ImFriendProfileMorePage extends StatelessWidget {
|
||||||
|
const ImFriendProfileMorePage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GetX<PrivateController>(builder: (_) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('资料设置'),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
ActionItem(
|
||||||
|
'设置备注',
|
||||||
|
extend: _.currentFriend.value.friendRemark,
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendRemark,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
ActionItem(
|
||||||
|
'把他推荐给朋友',
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendRecommend,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
ActionItem(
|
||||||
|
'加入黑名单',
|
||||||
|
rightWidget: SizedBox(
|
||||||
|
height: 24,
|
||||||
|
child: Switch(
|
||||||
|
value: false,
|
||||||
|
onChanged: (e) async {
|
||||||
|
OkCancelResult result = await showOkCancelAlertDialog(
|
||||||
|
style: AdaptiveStyle.iOS,
|
||||||
|
context: Get.context!,
|
||||||
|
title: '加入黑名单',
|
||||||
|
message: '加入黑名单将会解除好友关系,不再接收他的消息',
|
||||||
|
okLabel: '确定',
|
||||||
|
cancelLabel: '取消',
|
||||||
|
defaultType: OkCancelAlertDefaultType.ok,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == OkCancelResult.ok) {
|
||||||
|
var res = await TimBlockService.to.add(
|
||||||
|
_.currentFriend.value.userID,
|
||||||
|
);
|
||||||
|
if (res) {
|
||||||
|
UiTools.toast('加入黑名单成功');
|
||||||
|
Navigator.popUntil(context, (route) => route.isFirst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
ActionButton(
|
||||||
|
'删除',
|
||||||
|
onTap: () async {
|
||||||
|
OkCancelResult result = await showOkCancelAlertDialog(
|
||||||
|
style: AdaptiveStyle.iOS,
|
||||||
|
context: Get.context!,
|
||||||
|
title: '删除好友',
|
||||||
|
message: '确定要删除该好友么?',
|
||||||
|
okLabel: '确定',
|
||||||
|
cancelLabel: '取消',
|
||||||
|
defaultType: OkCancelAlertDefaultType.ok,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == OkCancelResult.ok) {
|
||||||
|
var res = await TimFriendService.to.delete(
|
||||||
|
_.currentFriend.value.userID,
|
||||||
|
);
|
||||||
|
if (res) {
|
||||||
|
UiTools.toast('好友删除成功');
|
||||||
|
|
||||||
|
/// 关闭所有页面
|
||||||
|
Navigator.popUntil(context, (route) => route.isFirst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
164
lib/views/contact/firend/recommend/friends_page.dart
Normal file
164
lib/views/contact/firend/recommend/friends_page.dart
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:azlistview/azlistview.dart';
|
||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/models/im/contact_info_model.dart';
|
||||||
|
import 'package:chat/models/im/name_card_model.dart';
|
||||||
|
import 'package:chat/models/im/private_conversation_model.dart';
|
||||||
|
import 'package:chat/services/tim/conversation_service.dart';
|
||||||
|
import 'package:chat/services/tim/friend_service.dart';
|
||||||
|
import 'package:chat/utils/im_tools.dart';
|
||||||
|
import 'package:chat/widgets/custom_avatar.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import 'package:tencent_im_sdk_plugin/models/v2_tim_conversation.dart';
|
||||||
|
|
||||||
|
class ImFriendRecommendFriendsPage extends StatelessWidget {
|
||||||
|
const ImFriendRecommendFriendsPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
PrivateConversationModel card = PrivateController.to.currentFriend.value;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('选择联系人'),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
color: AppColors.page,
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: 8,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxHeight: 32,
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(32),
|
||||||
|
child: TextField(
|
||||||
|
onChanged: (e) async {},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: '搜索',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
fillColor: AppColors.white,
|
||||||
|
filled: true,
|
||||||
|
contentPadding: EdgeInsets.only(
|
||||||
|
bottom: 14,
|
||||||
|
left: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cursorColor: AppColors.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
FocusScope.of(Get.context!).requestFocus(FocusNode());
|
||||||
|
// Get.offNamed(ImRoutes.friendRecommendGroups);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: AppColors.white,
|
||||||
|
),
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
top: 12,
|
||||||
|
bottom: 12,
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'选择一个群',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: GetX<TimFriendService>(builder: (_) {
|
||||||
|
return AzListView(
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
data: _.contacts,
|
||||||
|
itemCount: _.contacts.length,
|
||||||
|
itemBuilder: (__, index) {
|
||||||
|
ContactInfoModel info = _.contacts[index];
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
onTap: () async {
|
||||||
|
FocusScope.of(Get.context!).requestFocus(FocusNode());
|
||||||
|
|
||||||
|
V2TimConversation conversation =
|
||||||
|
await TimConversationService.to.getById(
|
||||||
|
'c2c_' + info.userID,
|
||||||
|
);
|
||||||
|
|
||||||
|
OkCancelResult result = await showOkCancelAlertDialog(
|
||||||
|
style: AdaptiveStyle.iOS,
|
||||||
|
context: context,
|
||||||
|
title: '发送名片',
|
||||||
|
message: '确定要发送【个人名片】至${conversation.showName}?',
|
||||||
|
okLabel: '确定',
|
||||||
|
cancelLabel: '取消',
|
||||||
|
defaultType: OkCancelAlertDefaultType.cancel,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == OkCancelResult.ok) {
|
||||||
|
var model = NameCardModel(
|
||||||
|
avatar: card.userProfile?.faceUrl ?? '',
|
||||||
|
userID: card.userID,
|
||||||
|
userName: card.userProfile?.nickName ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
|
TimConversationService.to.sendCustomMessage(
|
||||||
|
conversation,
|
||||||
|
model,
|
||||||
|
'NAME_CARD',
|
||||||
|
);
|
||||||
|
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tileColor: AppColors.white,
|
||||||
|
leading: CustomAvatar(
|
||||||
|
info.friendInfo!.userProfile!.faceUrl,
|
||||||
|
size: 40,
|
||||||
|
),
|
||||||
|
title: Text(info.name),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
height: 0,
|
||||||
|
indent: 72,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
susItemBuilder: (__, index) {
|
||||||
|
ContactInfoModel model = _.contacts[index];
|
||||||
|
if ('↑' == model.getSuspensionTag()) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
return ImTools.susItem(context, model.getSuspensionTag());
|
||||||
|
},
|
||||||
|
indexBarData:
|
||||||
|
SuspensionUtil.getTagIndexList(_.contacts).toList(),
|
||||||
|
indexBarOptions: ImTools.indexBarOptions,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
126
lib/views/contact/firend/recommend/groups_page.dart
Normal file
126
lib/views/contact/firend/recommend/groups_page.dart
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/models/im/name_card_model.dart';
|
||||||
|
import 'package:chat/models/im/private_conversation_model.dart';
|
||||||
|
import 'package:chat/services/tim/conversation_service.dart';
|
||||||
|
import 'package:chat/services/tim/group_service.dart';
|
||||||
|
import 'package:chat/views/home/widgets/group_avatar.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:tencent_im_sdk_plugin/models/v2_tim_conversation.dart';
|
||||||
|
import 'package:tencent_im_sdk_plugin/models/v2_tim_group_info.dart';
|
||||||
|
|
||||||
|
class ImFriendRecommendGroupsPage extends StatelessWidget {
|
||||||
|
const ImFriendRecommendGroupsPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
PrivateConversationModel card = PrivateController.to.currentFriend.value;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('选择一个群'),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
color: AppColors.page,
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: 8,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxHeight: 32,
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(32),
|
||||||
|
child: TextField(
|
||||||
|
onChanged: (e) async {},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: '搜索',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
fillColor: AppColors.white,
|
||||||
|
filled: true,
|
||||||
|
contentPadding: EdgeInsets.only(
|
||||||
|
bottom: 14,
|
||||||
|
left: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cursorColor: AppColors.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: GetX<TimGroupService>(
|
||||||
|
builder: (_) {
|
||||||
|
return ListView.separated(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
V2TimGroupInfo group = _.groups[index];
|
||||||
|
return ListTile(
|
||||||
|
onTap: () async {
|
||||||
|
FocusScope.of(Get.context!).requestFocus(FocusNode());
|
||||||
|
|
||||||
|
V2TimConversation conversation =
|
||||||
|
await TimConversationService.to.getById(
|
||||||
|
'group_' + group.groupID,
|
||||||
|
);
|
||||||
|
|
||||||
|
OkCancelResult result = await showOkCancelAlertDialog(
|
||||||
|
style: AdaptiveStyle.iOS,
|
||||||
|
context: context,
|
||||||
|
title: '发送名片',
|
||||||
|
message: '确定要发送【个人名片】至${conversation.showName}?',
|
||||||
|
okLabel: '确定',
|
||||||
|
cancelLabel: '取消',
|
||||||
|
defaultType: OkCancelAlertDefaultType.cancel,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == OkCancelResult.ok) {
|
||||||
|
var model = NameCardModel(
|
||||||
|
avatar: card.userProfile?.faceUrl ?? '',
|
||||||
|
userID: card.userID,
|
||||||
|
userName: card.userProfile?.nickName ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
|
TimConversationService.to.sendCustomMessage(
|
||||||
|
conversation,
|
||||||
|
model,
|
||||||
|
'NAME_CARD',
|
||||||
|
);
|
||||||
|
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leading: GroupAvatar(group.groupID),
|
||||||
|
tileColor: AppColors.white,
|
||||||
|
title: Text(group.groupName!),
|
||||||
|
subtitle: Text('成员数: ${group.memberCount}'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) {
|
||||||
|
return const Divider(
|
||||||
|
height: 0,
|
||||||
|
indent: 72,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount: _.groups.length,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
179
lib/views/contact/firend/recommend/index_page.dart
Normal file
179
lib/views/contact/firend/recommend/index_page.dart
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/configs/app_size.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/models/im/name_card_model.dart';
|
||||||
|
import 'package:chat/models/im/private_conversation_model.dart';
|
||||||
|
import 'package:chat/services/tim/conversation_service.dart';
|
||||||
|
import 'package:chat/views/home/widgets/group_avatar.dart';
|
||||||
|
import 'package:chat/widgets/custom_avatar.dart';
|
||||||
|
import 'package:chat/widgets/custom_easy_refresh.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:tencent_im_sdk_plugin/enum/conversation_type.dart';
|
||||||
|
|
||||||
|
class ImFriendRecommendPage extends StatelessWidget {
|
||||||
|
const ImFriendRecommendPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
PrivateConversationModel info = PrivateController.to.currentFriend.value;
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
FocusScope.of(Get.context!).requestFocus(FocusNode());
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text(
|
||||||
|
'选择一个聊天',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: 8,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxHeight: 32,
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(32),
|
||||||
|
child: TextField(
|
||||||
|
onChanged: (e) async {},
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: '搜索',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
fillColor: AppColors.white,
|
||||||
|
filled: true,
|
||||||
|
contentPadding: EdgeInsets.only(
|
||||||
|
bottom: 14,
|
||||||
|
left: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cursorColor: AppColors.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
FocusScope.of(Get.context!).requestFocus(FocusNode());
|
||||||
|
// Get.offNamed(ImRoutes.friendRecommendFriends);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: AppColors.white,
|
||||||
|
),
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
top: 12,
|
||||||
|
bottom: 12,
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'更多联系人',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
top: 6,
|
||||||
|
bottom: 6,
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'最近联系人',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.unactive,
|
||||||
|
fontSize: AppSize.smallFontSize,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: GetX<TimConversationService>(
|
||||||
|
builder: (_) {
|
||||||
|
return _.conversationList.isEmpty
|
||||||
|
? CustomEasyRefresh.empty()
|
||||||
|
: ListView.separated(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
itemCount: _.conversationList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var conversation = _.conversationList[index]!;
|
||||||
|
return ListTile(
|
||||||
|
tileColor: AppColors.white,
|
||||||
|
onTap: () async {
|
||||||
|
FocusScope.of(Get.context!)
|
||||||
|
.requestFocus(FocusNode());
|
||||||
|
|
||||||
|
OkCancelResult result =
|
||||||
|
await showOkCancelAlertDialog(
|
||||||
|
style: AdaptiveStyle.iOS,
|
||||||
|
context: context,
|
||||||
|
title: '发送名片',
|
||||||
|
message:
|
||||||
|
'确定要发送【个人名片】至${conversation.showName}?',
|
||||||
|
okLabel: '确定',
|
||||||
|
cancelLabel: '取消',
|
||||||
|
defaultType: OkCancelAlertDefaultType.cancel,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == OkCancelResult.ok) {
|
||||||
|
var model = NameCardModel(
|
||||||
|
avatar: info.userProfile?.faceUrl ?? '',
|
||||||
|
userID: info.userID,
|
||||||
|
userName: info.userProfile?.nickName ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
|
TimConversationService.to.sendCustomMessage(
|
||||||
|
conversation,
|
||||||
|
model,
|
||||||
|
'NAME_CARD',
|
||||||
|
);
|
||||||
|
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leading: conversation.type ==
|
||||||
|
ConversationType.V2TIM_C2C
|
||||||
|
? CustomAvatar(
|
||||||
|
conversation.faceUrl,
|
||||||
|
)
|
||||||
|
: GroupAvatar(conversation.groupID!),
|
||||||
|
title: Text(
|
||||||
|
conversation.showName!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) {
|
||||||
|
return const Divider(
|
||||||
|
height: 0,
|
||||||
|
indent: 72,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
82
lib/views/contact/firend/remark/index_page.dart
Normal file
82
lib/views/contact/firend/remark/index_page.dart
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class ImFriendRemarkPage extends StatefulWidget {
|
||||||
|
const ImFriendRemarkPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ImFriendRemarkPage> createState() => _ImFriendRemarkPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ImFriendRemarkPageState extends State<ImFriendRemarkPage> {
|
||||||
|
final TextEditingController _controller = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GetX<PrivateController>(builder: (_) {
|
||||||
|
_controller.text = _.currentFriend.value.friendRemark;
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
FocusScope.of(Get.context!).requestFocus(FocusNode());
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: const Text('保存'),
|
||||||
|
onPressed: () async {
|
||||||
|
_.setRemark(_controller.text);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'设置备注',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: TextField(
|
||||||
|
controller: _controller,
|
||||||
|
autofocus: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: '好友备注',
|
||||||
|
hintText: '',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
fillColor: AppColors.white,
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
cursorColor: AppColors.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
118
lib/views/contact/firend/request/apply_page.dart
Normal file
118
lib/views/contact/firend/request/apply_page.dart
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/services/tim/friend_service.dart';
|
||||||
|
import 'package:chat/utils/ui_tools.dart';
|
||||||
|
import 'package:chat/widgets/custom_primary_button.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class ImFriendRequestApplyPage extends StatefulWidget {
|
||||||
|
const ImFriendRequestApplyPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ImFriendRequestApplyPage> createState() =>
|
||||||
|
_ImFriendRequestApplyPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ImFriendRequestApplyPageState extends State<ImFriendRequestApplyPage> {
|
||||||
|
late final String userID;
|
||||||
|
String _remark = '';
|
||||||
|
String _wording = '';
|
||||||
|
final TextEditingController _wordingController = TextEditingController();
|
||||||
|
final TextEditingController _remarkController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
userID = Get.arguments['userID'];
|
||||||
|
|
||||||
|
_wordingController.text = '我是 ';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_wordingController.dispose();
|
||||||
|
_remarkController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('好友申请'),
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'发送添加朋友申请',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
TextField(
|
||||||
|
controller: _wordingController,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: AppColors.unactive.withOpacity(0.1),
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
onChanged: (e) {
|
||||||
|
setState(() {
|
||||||
|
_wording = e;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
const Text(
|
||||||
|
'设置备注',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
TextField(
|
||||||
|
controller: _remarkController,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: '',
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: AppColors.unactive.withOpacity(0.1),
|
||||||
|
filled: true,
|
||||||
|
),
|
||||||
|
onChanged: (e) {
|
||||||
|
setState(() {
|
||||||
|
_remark = e;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
CustomPrimaryButton(
|
||||||
|
text: '发送',
|
||||||
|
onPressed: () async {
|
||||||
|
var res = await TimFriendService.to.add(
|
||||||
|
userID,
|
||||||
|
remark: _remark,
|
||||||
|
addWording: _wording,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
UiTools.toast('申请成功');
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
293
lib/views/contact/firend/request/index_page.dart
Normal file
293
lib/views/contact/firend/request/index_page.dart
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/models/im/search_user_model.dart';
|
||||||
|
import 'package:chat/routes/contact_routes.dart';
|
||||||
|
import 'package:chat/services/tim/apply_service.dart';
|
||||||
|
import 'package:chat/services/tim/friend_service.dart';
|
||||||
|
import 'package:chat/widgets/custom_avatar.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:tencent_im_sdk_plugin/enum/friend_type.dart';
|
||||||
|
import 'package:tencent_im_sdk_plugin/models/v2_tim_friend_application.dart';
|
||||||
|
import 'package:tencent_im_sdk_plugin/models/v2_tim_friend_check_result.dart';
|
||||||
|
|
||||||
|
class ImFriendRequestPage extends StatefulWidget {
|
||||||
|
const ImFriendRequestPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ImFriendRequestPage> createState() => _ImFriendRequestState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ImFriendRequestState extends State<ImFriendRequestPage> {
|
||||||
|
List<SearchUserModel>? searchList;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('新的朋友'),
|
||||||
|
bottom: _Search(
|
||||||
|
onChanged: (String e) async {
|
||||||
|
if (e.length < 3) {
|
||||||
|
setState(() {
|
||||||
|
searchList = null;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var result = await TimFriendService.to.searchUser(e);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
searchList = result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
FocusScope.of(context).requestFocus(FocusNode());
|
||||||
|
},
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ListView.separated(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
itemCount: searchList?.length ?? 0,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var user = searchList![index];
|
||||||
|
return FutureBuilder<V2TimFriendCheckResult?>(
|
||||||
|
future: TimFriendService.to.check(user.userID),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
V2TimFriendCheckResult? result = snapshot.data;
|
||||||
|
return ListTile(
|
||||||
|
leading: CustomAvatar(user.avatar),
|
||||||
|
title: Text(user.nickname),
|
||||||
|
onTap: () {
|
||||||
|
if (result?.resultType == 3) {
|
||||||
|
PrivateController.to.setCurrentFriend(user.userID);
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendProfile,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendApply,
|
||||||
|
arguments: {
|
||||||
|
'userID': user.userID,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
trailing: _buildTrailing(result),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) {
|
||||||
|
return const Divider(
|
||||||
|
height: 0,
|
||||||
|
indent: 72,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Divider(height: 0),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
top: 4,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'好友申请',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GetX<TimApplyService>(
|
||||||
|
builder: (_) {
|
||||||
|
return ListView.separated(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
V2TimFriendApplication apply = _.applies[index]!;
|
||||||
|
return ListTile(
|
||||||
|
leading: CustomAvatar(apply.faceUrl),
|
||||||
|
title: Text(apply.nickname!),
|
||||||
|
subtitle: Text(apply.addWording ?? ''),
|
||||||
|
trailing: apply.type ==
|
||||||
|
FriendApplicationType
|
||||||
|
.V2TIM_FRIEND_APPLICATION_COME_IN
|
||||||
|
? InkWell(
|
||||||
|
onTap: () {
|
||||||
|
TimApplyService.to.accept(apply.userID);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 4,
|
||||||
|
horizontal: 12,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColors.primary,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'通过请求',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.white,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const Text('已发送'),
|
||||||
|
onTap: () {
|
||||||
|
PrivateController.to.setCurrentFriend(apply.userID);
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendProfile,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) {
|
||||||
|
return const Divider(
|
||||||
|
height: 0,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount: _.applies.length,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTrailing(V2TimFriendCheckResult? result) {
|
||||||
|
if (result == null) {
|
||||||
|
return const Text('');
|
||||||
|
}
|
||||||
|
if (result.resultType == 0) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 4,
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColors.primary,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'添加好友',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.white,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (result.resultType == 2) {
|
||||||
|
return const Text(
|
||||||
|
'已申请',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (result.resultType == 3) {
|
||||||
|
return const Text('已是好友');
|
||||||
|
}
|
||||||
|
return Text(result.resultType.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Search extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
final Function(String e) onChanged;
|
||||||
|
|
||||||
|
const _Search({
|
||||||
|
Key? key,
|
||||||
|
required this.onChanged,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size get preferredSize => const Size.fromHeight(64);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxHeight: 32,
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
child: TextField(
|
||||||
|
keyboardType: TextInputType.phone,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: '请输入对方手机号',
|
||||||
|
hintStyle: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
fillColor: AppColors.unactive.withOpacity(0.1),
|
||||||
|
filled: true,
|
||||||
|
prefixIcon: const Icon(
|
||||||
|
Icons.search,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.only(
|
||||||
|
bottom: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cursorColor: AppColors.primary,
|
||||||
|
onChanged: (e) async {
|
||||||
|
onChanged.call(e);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 8,
|
||||||
|
bottom: 16,
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(ContactRoutes.friendProfile);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: const [
|
||||||
|
Text(
|
||||||
|
'我的二维码: ',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Icon(
|
||||||
|
Icons.qr_code,
|
||||||
|
size: 18,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 0),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
lib/views/contact/firend/search/index_page.dart
Normal file
57
lib/views/contact/firend/search/index_page.dart
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ImFriendSearchPage extends StatefulWidget {
|
||||||
|
const ImFriendSearchPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ImFriendSearchPage> createState() => _ImFriendSearchPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ImFriendSearchPageState extends State<ImFriendSearchPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: AppColors.white,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Container(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxHeight: 32,
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(32),
|
||||||
|
child: TextField(
|
||||||
|
onChanged: (e) async {},
|
||||||
|
autofocus: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: '请输入搜索内容',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: AppColors.unactive,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
focusedBorder: InputBorder.none,
|
||||||
|
fillColor: AppColors.white,
|
||||||
|
filled: true,
|
||||||
|
contentPadding: EdgeInsets.only(
|
||||||
|
bottom: 14,
|
||||||
|
left: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cursorColor: AppColors.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.search,
|
||||||
|
color: AppColors.black,
|
||||||
|
),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,87 @@
|
|||||||
|
import 'package:azlistview/azlistview.dart';
|
||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/models/im/contact_info_model.dart';
|
||||||
|
import 'package:chat/routes/contact_routes.dart';
|
||||||
|
import 'package:chat/services/tim/friend_service.dart';
|
||||||
|
import 'package:chat/utils/im_tools.dart';
|
||||||
|
import 'package:chat/widgets/custom_avatar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class ContactPage extends StatefulWidget {
|
class ContactPage extends StatefulWidget {
|
||||||
const ContactPage({Key? key}) : super(key: key);
|
const ContactPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ContactPageState createState() => _ContactPageState();
|
State<ContactPage> createState() => _ContactPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ContactPageState extends State<ContactPage> {
|
class _ContactPageState extends State<ContactPage> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
TimFriendService.to.fetchList();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return GetX<TimFriendService>(
|
||||||
appBar: AppBar(
|
builder: (_) {
|
||||||
title: const Text('通讯录'),
|
return Scaffold(
|
||||||
),
|
appBar: AppBar(
|
||||||
|
title: Text('我的好友(${_.friends.length})'),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
// Get.toNamed(ImRoutes.friendSearch);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.search_outlined),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: AzListView(
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
data: _.contacts,
|
||||||
|
itemCount: _.contacts.length,
|
||||||
|
itemBuilder: (__, index) {
|
||||||
|
ContactInfoModel info = _.contacts[index];
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
onTap: () async {
|
||||||
|
await PrivateController.to.setCurrentFriend(
|
||||||
|
info.userID,
|
||||||
|
);
|
||||||
|
Get.toNamed(
|
||||||
|
ContactRoutes.friendProfile,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
tileColor: AppColors.white,
|
||||||
|
leading: CustomAvatar(
|
||||||
|
info.friendInfo!.userProfile!.faceUrl,
|
||||||
|
size: 40,
|
||||||
|
),
|
||||||
|
title: Text(info.name),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
height: 0,
|
||||||
|
indent: 72,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
susItemBuilder: (__, index) {
|
||||||
|
ContactInfoModel model = _.contacts[index];
|
||||||
|
if ('↑' == model.getSuspensionTag()) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
return ImTools.susItem(context, model.getSuspensionTag());
|
||||||
|
},
|
||||||
|
indexBarData: SuspensionUtil.getTagIndexList(_.contacts).toList(),
|
||||||
|
indexBarOptions: ImTools.indexBarOptions,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user