mirror of
https://github.com/Linloir/Simple-TCP-Client.git
synced 2025-12-17 00:38:11 +08:00
Feature:
- Show pending contacts and requesting contacts in contact list
This commit is contained in:
parent
f9907c16fe
commit
5aa69d80f6
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:49:53
|
||||
* @LastEditTime : 2022-10-20 13:46:16
|
||||
* @LastEditTime : 2022-10-20 16:53:26
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -82,7 +82,7 @@ class UserAvatar extends StatelessWidget {
|
||||
alignment: Alignment.center,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.cover,
|
||||
child: Image.memory(base64.decode(state.userInfo.avatarEncoded!)),
|
||||
child: state.preCachedAvatar ?? Image.memory(base64.decode(state.userInfo.avatarEncoded!)),
|
||||
),
|
||||
),
|
||||
Material(
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:50:14
|
||||
* @LastEditTime : 2022-10-13 22:03:01
|
||||
* @LastEditTime : 2022-10-20 17:02:19
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tcp_client/common/avatar/cubit/avatar_state.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
@ -14,15 +17,25 @@ class AvatarCubit extends Cubit<AvatarState> {
|
||||
AvatarCubit({
|
||||
required int userid,
|
||||
required this.userRepository
|
||||
}): super(AvatarState(userInfo: userRepository.getUserInfo(userid: userid))) {
|
||||
}): super(AvatarState(userInfo: userRepository.getUserInfo(userid: userid)))
|
||||
{
|
||||
userRepository.userInfoStreamBroadcast.listen(onFetchedUserInfo);
|
||||
emit(AvatarState(
|
||||
userInfo: state.userInfo,
|
||||
preCachedAvatar: state.userInfo.avatarEncoded == null ? null :
|
||||
Image.memory(base64.decode(state.userInfo.avatarEncoded!))
|
||||
));
|
||||
}
|
||||
|
||||
final UserRepository userRepository;
|
||||
|
||||
void onFetchedUserInfo(UserInfo userInfo) {
|
||||
if(userInfo.userID == state.userInfo.userID) {
|
||||
emit(AvatarState(userInfo: userInfo));
|
||||
emit(AvatarState(
|
||||
userInfo: userInfo,
|
||||
preCachedAvatar: userInfo.avatarEncoded == null ? null :
|
||||
Image.memory(base64.decode(userInfo.avatarEncoded!))
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,23 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:50:07
|
||||
* @LastEditTime : 2022-10-13 22:02:11
|
||||
* @LastEditTime : 2022-10-20 16:51:11
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
|
||||
class AvatarState extends Equatable {
|
||||
const AvatarState({
|
||||
required this.userInfo,
|
||||
this.preCachedAvatar
|
||||
});
|
||||
|
||||
final UserInfo userInfo;
|
||||
final Image? preCachedAvatar;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [userInfo.userID, userInfo.avatarEncoded];
|
||||
List<Object?> get props => [userInfo.userID, userInfo.avatarEncoded, preCachedAvatar];
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 23:36:07
|
||||
* @LastEditTime : 2022-10-18 11:25:18
|
||||
* @LastEditTime : 2022-10-20 17:04:52
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -26,7 +26,7 @@ class ContactPage extends StatelessWidget {
|
||||
itemCount: indexedData.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ContactTile(
|
||||
userInfo: (indexedData[index] as ContactModel).userInfo,
|
||||
contactInfo: (indexedData[index] as ContactModel),
|
||||
);
|
||||
},
|
||||
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
|
||||
@ -38,7 +38,7 @@ class ContactPage extends StatelessWidget {
|
||||
color: Colors.grey[200],
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
indexedData[index].getSuspensionTag(),
|
||||
indexedData[index].getSuspensionTag() == '⨂' ? 'Pending for reply' : indexedData[index].getSuspensionTag() == '⊙' ? 'Requesting' : indexedData[index].getSuspensionTag(),
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:01:45
|
||||
* @LastEditTime : 2022-10-14 23:03:02
|
||||
* @LastEditTime : 2022-10-20 16:36:05
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -22,7 +22,7 @@ class ContactCubit extends Cubit<ContactState> {
|
||||
}): super(ContactState.empty()) {
|
||||
subscription = tcpRepository.responseStreamBroadcast.listen(_onResponse);
|
||||
updateContacts();
|
||||
timer = Timer.periodic(const Duration(seconds: 10), (timer) {updateContacts();});
|
||||
timer = Timer.periodic(const Duration(seconds: 20), (timer) {updateContacts();});
|
||||
}
|
||||
|
||||
final LocalServiceRepository localServiceRepository;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:01:39
|
||||
* @LastEditTime : 2022-10-17 17:28:33
|
||||
* @LastEditTime : 2022-10-20 16:09:50
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -24,13 +24,17 @@ class ContactState extends Equatable {
|
||||
static ContactState empty() => const ContactState(contacts: [], pending: [], requesting: []);
|
||||
|
||||
List<ISuspensionBean> get indexedData {
|
||||
var indexedList = contacts.map((e) => ContactModel(userInfo: e)).toList();
|
||||
var indexedList = contacts.map((e) => ContactModel(userInfo: e, status: ContactStatus.added)).toList();
|
||||
indexedList.sort((a, b) => a.getSuspensionTag().compareTo(b.getSuspensionTag()));
|
||||
//Add requesting contacts
|
||||
indexedList.insertAll(0, requesting.map((e) => ContactModel(userInfo: e, status: ContactStatus.requesting)).toList());
|
||||
//Add pending contacts
|
||||
indexedList.insertAll(0, pending.map((e) => ContactModel(userInfo: e, status: ContactStatus.pending)).toList());
|
||||
// SuspensionUtil.sortListBySuspensionTag(indexedList);
|
||||
SuspensionUtil.setShowSuspensionStatus(indexedList);
|
||||
return indexedList;
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => contacts;
|
||||
List<Object> get props => [...contacts, ...pending, ...requesting];
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 15:34:08
|
||||
* @LastEditTime : 2022-10-17 17:20:47
|
||||
* @LastEditTime : 2022-10-20 16:00:22
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -9,13 +9,22 @@ import 'package:azlistview/azlistview.dart';
|
||||
import 'package:lpinyin/lpinyin.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
|
||||
enum ContactStatus { added, pending, requesting }
|
||||
|
||||
class ContactModel extends ISuspensionBean {
|
||||
final UserInfo userInfo;
|
||||
final ContactStatus status;
|
||||
|
||||
ContactModel({required this.userInfo});
|
||||
ContactModel({required this.userInfo, required this.status});
|
||||
|
||||
@override
|
||||
String getSuspensionTag() {
|
||||
if(status == ContactStatus.pending) {
|
||||
return '⨂';
|
||||
}
|
||||
else if(status == ContactStatus.requesting) {
|
||||
return '⊙';
|
||||
}
|
||||
var pinyin = PinyinHelper.getPinyinE(userInfo.userName);
|
||||
var tag = pinyin.substring(0, 1).toUpperCase();
|
||||
if(!RegExp('[A-Z]').hasMatch(tag)) {
|
||||
|
||||
@ -1,30 +1,34 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:02:00
|
||||
* @LastEditTime : 2022-10-18 11:25:32
|
||||
* @LastEditTime : 2022-10-20 16:26:33
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:loading_indicator/loading_indicator.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tcp_client/chat/chat_page.dart';
|
||||
import 'package:tcp_client/common/avatar/avatar.dart';
|
||||
import 'package:tcp_client/common/username/username.dart';
|
||||
import 'package:tcp_client/home/cubit/home_cubit.dart';
|
||||
import 'package:tcp_client/home/cubit/home_state.dart';
|
||||
import 'package:tcp_client/home/view/contact_page/cubit/contact_cubit.dart';
|
||||
import 'package:tcp_client/home/view/contact_page/models/contact_model.dart';
|
||||
import 'package:tcp_client/home/view/message_page/cubit/msg_list_cubit.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
|
||||
class ContactTile extends StatelessWidget {
|
||||
const ContactTile({
|
||||
required this.userInfo,
|
||||
required this.contactInfo,
|
||||
super.key
|
||||
});
|
||||
|
||||
final UserInfo userInfo;
|
||||
final ContactModel contactInfo;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -33,16 +37,16 @@ class ContactTile extends StatelessWidget {
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
onTap: contactInfo.status == ContactStatus.added ? () {
|
||||
Navigator.of(context).push(ChatPage.route(
|
||||
userRepository: context.read<UserRepository>(),
|
||||
localServiceRepository: context.read<LocalServiceRepository>(),
|
||||
tcpRepository: context.read<TCPRepository>(),
|
||||
userID: userInfo.userID
|
||||
userID: contactInfo.userInfo.userID
|
||||
));
|
||||
context.read<MessageListCubit>().addEmptyMessageOf(targetUser: userInfo.userID);
|
||||
context.read<MessageListCubit>().addEmptyMessageOf(targetUser: contactInfo.userInfo.userID);
|
||||
context.read<HomeCubit>().switchPage(HomePagePosition.message);
|
||||
},
|
||||
} : (){},
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@ -52,7 +56,7 @@ class ContactTile extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
IgnorePointer(
|
||||
child: UserAvatar(userid: userInfo.userID),
|
||||
child: UserAvatar(userid: contactInfo.userInfo.userID),
|
||||
),
|
||||
const SizedBox(width: 12,),
|
||||
Expanded(
|
||||
@ -61,10 +65,32 @@ class ContactTile extends StatelessWidget {
|
||||
vertical: 12.0
|
||||
),
|
||||
child: IgnorePointer(
|
||||
child: UserNameText(userid: userInfo.userID,)
|
||||
child: UserNameText(userid: contactInfo.userInfo.userID,)
|
||||
),
|
||||
)
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: contactInfo.status == ContactStatus.added ? null :
|
||||
contactInfo.status == ContactStatus.pending ?
|
||||
SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: LoadingIndicator(
|
||||
indicatorType: Indicator.ballPulse,
|
||||
colors: [Colors.blue.withOpacity(0.5)],
|
||||
),
|
||||
) :
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
context.read<ContactCubit>().tcpRepository.pushRequest(AddContactRequest(
|
||||
userid: contactInfo.userInfo.userID,
|
||||
token: (await SharedPreferences.getInstance()).getInt('token')
|
||||
));
|
||||
},
|
||||
child: const Text('Confirm'),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 08:54:32
|
||||
* @LastEditTime : 2022-10-20 11:30:46
|
||||
* @LastEditTime : 2022-10-20 16:45:19
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -28,9 +28,8 @@ class UserProfileCubit extends Cubit<UserProfileState> {
|
||||
emit(const UserProfileState(status: ContactStatus.none));
|
||||
return;
|
||||
}
|
||||
var clonedTCPRepository = await tcpRepository.clone();
|
||||
clonedTCPRepository.pushRequest(FetchContactRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
||||
await for(var response in clonedTCPRepository.responseStreamBroadcast) {
|
||||
tcpRepository.pushRequest(FetchContactRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
||||
await for(var response in tcpRepository.responseStreamBroadcast) {
|
||||
if(response.type == TCPResponseType.fetchContact) {
|
||||
response as FetchContactResponse;
|
||||
if(response.addedContacts.any((element) => element.userID == userID)) {
|
||||
@ -45,7 +44,6 @@ class UserProfileCubit extends Cubit<UserProfileState> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
clonedTCPRepository.dispose();
|
||||
}
|
||||
|
||||
Future<void> addContact() async {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user