mirror of
https://github.com/Linloir/Simple-TCP-Client.git
synced 2025-12-17 00:38:11 +08:00
More Functions
- User Profile page available - Search user avavilable - Tested Message page - Tested Contact page
This commit is contained in:
parent
f93a95d141
commit
0bb71791da
@ -1,34 +1,54 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:03:16
|
||||
* @LastEditTime : 2022-10-13 16:29:57
|
||||
* @LastEditTime : 2022-10-14 11:58:34
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/common/username/username.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
|
||||
class ChatPage extends StatelessWidget {
|
||||
const ChatPage({
|
||||
required this.userInfo,
|
||||
required this.userRepository,
|
||||
required this.localServiceRepository,
|
||||
required this.tcpRepository,
|
||||
required this.userID,
|
||||
super.key
|
||||
});
|
||||
|
||||
final UserInfo userInfo;
|
||||
final int userID;
|
||||
final UserRepository userRepository;
|
||||
final LocalServiceRepository localServiceRepository;
|
||||
final TCPRepository tcpRepository;
|
||||
|
||||
static Route<void> route({required UserInfo userInfo}) => MaterialPageRoute<void>(builder: (context) => ChatPage(userInfo: userInfo,));
|
||||
static Route<void> route({
|
||||
required UserRepository userRepository,
|
||||
required LocalServiceRepository localServiceRepository,
|
||||
required TCPRepository tcpRepository,
|
||||
required int userID
|
||||
}) => MaterialPageRoute<void>(builder: (context) => ChatPage(
|
||||
userID: userID,
|
||||
userRepository: userRepository,
|
||||
localServiceRepository: localServiceRepository,
|
||||
tcpRepository: tcpRepository,
|
||||
));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
userInfo.userName,
|
||||
style: const TextStyle(
|
||||
return RepositoryProvider<UserRepository>.value(
|
||||
value: userRepository,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: UserNameText(
|
||||
userid: userID,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:49:53
|
||||
* @LastEditTime : 2022-10-13 22:17:17
|
||||
* @LastEditTime : 2022-10-14 10:32:50
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -14,9 +14,14 @@ import 'package:tcp_client/common/avatar/cubit/avatar_state.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
|
||||
class UserAvatar extends StatelessWidget {
|
||||
const UserAvatar({required this.userid, super.key});
|
||||
const UserAvatar({
|
||||
required this.userid,
|
||||
this.size = 48,
|
||||
super.key
|
||||
});
|
||||
|
||||
final int userid;
|
||||
final double size;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -28,16 +33,18 @@ class UserAvatar extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
if(state.userInfo.avatarEncoded == null) {
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[800],
|
||||
color: Colors.grey[600],
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
boxShadow: [BoxShadow(blurRadius: 10.0, color: Colors.grey[850]!.withOpacity(0.15))]
|
||||
),
|
||||
child: Text(
|
||||
state.userInfo.userName[0],
|
||||
state.userInfo.userName[0].toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontSize: 24 * (size / 48),
|
||||
fontWeight: FontWeight.w300,
|
||||
color: Colors.white,
|
||||
shadows: [Shadow(blurRadius: 5.0, color: Colors.white.withOpacity(0.15))]
|
||||
@ -47,6 +54,8 @@ class UserAvatar extends StatelessWidget {
|
||||
}
|
||||
else {
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
boxShadow: [BoxShadow(blurRadius: 10.0, color: Colors.grey[850]!.withOpacity(0.15))]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 22:05:12
|
||||
* @LastEditTime : 2022-10-13 22:21:42
|
||||
* @LastEditTime : 2022-10-14 12:10:46
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -15,11 +15,15 @@ class UserNameText extends StatelessWidget {
|
||||
const UserNameText({
|
||||
required this.userid,
|
||||
this.fontWeight = FontWeight.normal,
|
||||
this.fontSize = 18,
|
||||
this.alignment = Alignment.centerLeft,
|
||||
super.key
|
||||
});
|
||||
|
||||
final int userid;
|
||||
final FontWeight fontWeight;
|
||||
final double fontSize;
|
||||
final Alignment alignment;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -29,11 +33,14 @@ class UserNameText extends StatelessWidget {
|
||||
userRepository: context.read<UserRepository>()
|
||||
),
|
||||
builder: (context, state) {
|
||||
return Text(
|
||||
state.userInfo.userName,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: fontWeight
|
||||
return Align(
|
||||
alignment: alignment,
|
||||
child: Text(
|
||||
state.userInfo.userName,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: fontWeight
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-11 11:05:08
|
||||
* @LastEditTime : 2022-10-13 23:02:55
|
||||
* @LastEditTime : 2022-10-14 10:52:26
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -13,6 +13,7 @@ import 'package:tcp_client/home/view/contact_page/contact_page.dart';
|
||||
import 'package:tcp_client/home/view/contact_page/cubit/contact_cubit.dart';
|
||||
import 'package:tcp_client/home/view/message_page/cubit/msg_list_cubit.dart';
|
||||
import 'package:tcp_client/home/view/message_page/mesage_page.dart';
|
||||
import 'package:tcp_client/home/view/profile_page/profile_page.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
@ -20,18 +21,22 @@ import 'package:tcp_client/search/search_page.dart';
|
||||
|
||||
class HomePage extends StatelessWidget {
|
||||
const HomePage({
|
||||
required this.userID,
|
||||
required this.localServiceRepository,
|
||||
required this.tcpRepository,
|
||||
super.key
|
||||
});
|
||||
|
||||
final int userID;
|
||||
final LocalServiceRepository localServiceRepository;
|
||||
final TCPRepository tcpRepository;
|
||||
|
||||
static Route<void> route({
|
||||
required int userID,
|
||||
required LocalServiceRepository localServiceRepository,
|
||||
required TCPRepository tcpRepository
|
||||
}) => MaterialPageRoute<void>(builder: (context) => HomePage(
|
||||
userID: userID,
|
||||
localServiceRepository: localServiceRepository,
|
||||
tcpRepository: tcpRepository,
|
||||
));
|
||||
@ -70,16 +75,20 @@ class HomePage extends StatelessWidget {
|
||||
),
|
||||
)
|
||||
],
|
||||
child: HomePageView(),
|
||||
child: HomePageView(userID: userID,),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomePageView extends StatelessWidget {
|
||||
HomePageView({super.key});
|
||||
HomePageView({
|
||||
required this.userID,
|
||||
super.key
|
||||
});
|
||||
|
||||
final PageController _controller = PageController();
|
||||
final int userID;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -122,9 +131,10 @@ class HomePageView extends StatelessWidget {
|
||||
builder:(context, state) => PageView(
|
||||
controller: _controller,
|
||||
onPageChanged: (value) => context.read<HomeCubit>().switchPage(HomePagePosition.fromValue(value)),
|
||||
children: const [
|
||||
MessagePage(),
|
||||
ContactPage()
|
||||
children: [
|
||||
const MessagePage(),
|
||||
const ContactPage(),
|
||||
MyProfilePage(userID: userID)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 23:36:07
|
||||
* @LastEditTime : 2022-10-13 22:59:25
|
||||
* @LastEditTime : 2022-10-14 11:45:35
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -19,7 +19,6 @@ class ContactPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.green,
|
||||
child: BlocBuilder<ContactCubit, ContactState>(
|
||||
builder: (context, state) {
|
||||
return AzListView(
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:01:45
|
||||
* @LastEditTime : 2022-10-13 14:50:34
|
||||
* @LastEditTime : 2022-10-14 11:49:50
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tcp_client/home/view/contact_page/cubit/contact_state.dart';
|
||||
@ -18,11 +20,15 @@ class ContactCubit extends Cubit<ContactState> {
|
||||
required this.localServiceRepository,
|
||||
required this.tcpRepository
|
||||
}): super(ContactState.empty()) {
|
||||
tcpRepository.responseStreamBroadcast.listen(_onResponse);
|
||||
subscription = tcpRepository.responseStreamBroadcast.listen(_onResponse);
|
||||
updateContacts();
|
||||
timer = Timer.periodic(const Duration(seconds: 5), (timer) {updateContacts();});
|
||||
}
|
||||
|
||||
LocalServiceRepository localServiceRepository;
|
||||
TCPRepository tcpRepository;
|
||||
final LocalServiceRepository localServiceRepository;
|
||||
final TCPRepository tcpRepository;
|
||||
late final StreamSubscription subscription;
|
||||
late final Timer timer;
|
||||
|
||||
void _onResponse(TCPResponse response) {
|
||||
switch(response.type) {
|
||||
@ -42,4 +48,12 @@ class ContactCubit extends Cubit<ContactState> {
|
||||
Future<void> updateContacts() async {
|
||||
tcpRepository.pushRequest(FetchContactRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
||||
}
|
||||
|
||||
//Override dispose to cancel the subscription
|
||||
@override
|
||||
Future<void> close() {
|
||||
subscription.cancel();
|
||||
timer.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:02:00
|
||||
* @LastEditTime : 2022-10-13 22:26:07
|
||||
* @LastEditTime : 2022-10-14 11:59:48
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -10,10 +10,15 @@ import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.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/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/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
|
||||
class ContactTile extends StatelessWidget {
|
||||
const ContactTile({
|
||||
@ -31,59 +36,35 @@ class ContactTile extends StatelessWidget {
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(ChatPage.route(userInfo: userInfo));
|
||||
Navigator.of(context).push(ChatPage.route(
|
||||
userRepository: context.read<UserRepository>(),
|
||||
localServiceRepository: context.read<LocalServiceRepository>(),
|
||||
tcpRepository: context.read<TCPRepository>(),
|
||||
userID: userInfo.userID
|
||||
));
|
||||
context.read<MessageListCubit>().addEmptyMessageOf(targetUser: userInfo.userID);
|
||||
context.read<HomeCubit>().switchPage(HomePagePosition.message);
|
||||
},
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
border: Border.all(
|
||||
color: Colors.grey[700]!,
|
||||
width: 1.0
|
||||
)
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
child: OverflowBox(
|
||||
alignment: Alignment.center,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
child: Image.memory(base64Decode(userInfo.avatarEncoded!)),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
if(userInfo.avatarEncoded == null || userInfo.avatarEncoded!.isEmpty)
|
||||
Container(
|
||||
color: Colors.grey,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
border: Border.all(
|
||||
color: Colors.grey[700]!,
|
||||
width: 1.0
|
||||
)
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12,),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12.0
|
||||
),
|
||||
child: Text(
|
||||
userInfo.userName,
|
||||
style: const TextStyle(
|
||||
fontSize: 18.0
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 24,
|
||||
vertical: 16,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
UserAvatar(userid: userInfo.userID),
|
||||
const SizedBox(width: 12,),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12.0
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
child: UserNameText(userid: userInfo.userID,)
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-11 11:05:18
|
||||
* @LastEditTime : 2022-10-13 22:59:10
|
||||
* @LastEditTime : 2022-10-14 11:45:45
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -19,7 +19,6 @@ class MessagePage extends StatelessWidget {
|
||||
return BlocBuilder<MessageListCubit, MessageListState>(
|
||||
builder: (context, state) {
|
||||
return Container(
|
||||
color: Colors.blue,
|
||||
child: ListView.separated(
|
||||
itemBuilder: (context, index) {
|
||||
return MessageTile(
|
||||
|
||||
@ -1,17 +1,22 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 13:17:52
|
||||
* @LastEditTime : 2022-10-13 22:23:31
|
||||
* @LastEditTime : 2022-10-14 12:07:32
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.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/repositories/common_models/message.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/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
|
||||
class MessageTile extends StatelessWidget {
|
||||
const MessageTile({
|
||||
@ -25,90 +30,105 @@ class MessageTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16.0,
|
||||
horizontal: 24.0
|
||||
),
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
UserAvatar(userid: userID),
|
||||
// if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
||||
// Container(
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(5.0),
|
||||
// border: Border.all(
|
||||
// color: Colors.grey[700]!,
|
||||
// width: 1.0
|
||||
// )
|
||||
// ),
|
||||
// child: ClipRRect(
|
||||
// borderRadius: BorderRadius.circular(5.0),
|
||||
// child: OverflowBox(
|
||||
// alignment: Alignment.center,
|
||||
// child: FittedBox(
|
||||
// fit: BoxFit.fitWidth,
|
||||
// child: Image.memory(base64Decode(userInfo.avatarEncoded!)),
|
||||
// ),
|
||||
// )
|
||||
// ),
|
||||
// ),
|
||||
// if(userInfo.avatarEncoded == null || userInfo.avatarEncoded!.isEmpty)
|
||||
// Container(
|
||||
// color: Colors.grey,
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(5.0),
|
||||
// border: Border.all(
|
||||
// color: Colors.grey[700]!,
|
||||
// width: 1.0
|
||||
// )
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(width: 12,),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
return IntrinsicHeight(
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(ChatPage.route(
|
||||
userRepository: context.read<UserRepository>(),
|
||||
localServiceRepository: context.read<LocalServiceRepository>(),
|
||||
tcpRepository: context.read<TCPRepository>(),
|
||||
userID: userID
|
||||
));
|
||||
},
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 24.0
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
UserAvatar(userid: userID),
|
||||
// if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
||||
// Container(
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(5.0),
|
||||
// border: Border.all(
|
||||
// color: Colors.grey[700]!,
|
||||
// width: 1.0
|
||||
// )
|
||||
// ),
|
||||
// child: ClipRRect(
|
||||
// borderRadius: BorderRadius.circular(5.0),
|
||||
// child: OverflowBox(
|
||||
// alignment: Alignment.center,
|
||||
// child: FittedBox(
|
||||
// fit: BoxFit.fitWidth,
|
||||
// child: Image.memory(base64Decode(userInfo.avatarEncoded!)),
|
||||
// ),
|
||||
// )
|
||||
// ),
|
||||
// ),
|
||||
// if(userInfo.avatarEncoded == null || userInfo.avatarEncoded!.isEmpty)
|
||||
// Container(
|
||||
// color: Colors.grey,
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(5.0),
|
||||
// border: Border.all(
|
||||
// color: Colors.grey[700]!,
|
||||
// width: 1.0
|
||||
// )
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(width: 16,),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 0
|
||||
),
|
||||
child: UserNameText(userid: userID, fontWeight: FontWeight.bold,)
|
||||
),
|
||||
const Spacer(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4.0
|
||||
),
|
||||
child: Text(
|
||||
message?.contentDecoded ?? '',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if(message != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 0
|
||||
),
|
||||
child: UserNameText(userid: userID, fontWeight: FontWeight.bold,)
|
||||
),
|
||||
const Spacer(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4.0
|
||||
),
|
||||
child: Text(
|
||||
message?.contentDecoded ?? '',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Text(
|
||||
getTimeStamp(message!.timeStamp)
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if(message != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 0
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Text(
|
||||
getTimeStamp(message!.timeStamp)
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
48
lib/home/view/profile_page/cubit/log_out_cubit.dart
Normal file
48
lib/home/view/profile_page/cubit/log_out_cubit.dart
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 10:54:57
|
||||
* @LastEditTime : 2022-10-14 11:44:12
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tcp_client/home/view/profile_page/cubit/log_out_state.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_response.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
|
||||
class LogOutCubit extends Cubit<LogOutStatus> {
|
||||
LogOutCubit({
|
||||
required this.tcpRepository
|
||||
}): super(LogOutStatus.none) {
|
||||
subscription = tcpRepository.responseStreamBroadcast.listen(_onResponse);
|
||||
}
|
||||
|
||||
final TCPRepository tcpRepository;
|
||||
late final StreamSubscription subscription;
|
||||
|
||||
void _onResponse(TCPResponse response) {
|
||||
if(response.type == TCPResponseType.logout) {
|
||||
if(response.status == TCPResponseStatus.ok) {
|
||||
emit(LogOutStatus.done);
|
||||
}
|
||||
else {
|
||||
emit(LogOutStatus.none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onLogout() async {
|
||||
tcpRepository.pushRequest(LogoutRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
||||
}
|
||||
|
||||
//Override dispose to cancel the subscription
|
||||
@override
|
||||
Future<void> close() {
|
||||
subscription.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
8
lib/home/view/profile_page/cubit/log_out_state.dart
Normal file
8
lib/home/view/profile_page/cubit/log_out_state.dart
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 10:54:38
|
||||
* @LastEditTime : 2022-10-14 10:56:04
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
enum LogOutStatus { none, processing, done }
|
||||
@ -1,6 +1,84 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 23:36:12
|
||||
* @LastEditTime : 2022-10-12 23:36:57
|
||||
* @LastEditTime : 2022-10-14 12:10:34
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/common/avatar/avatar.dart';
|
||||
import 'package:tcp_client/common/username/username.dart';
|
||||
import 'package:tcp_client/home/view/profile_page/cubit/log_out_cubit.dart';
|
||||
import 'package:tcp_client/home/view/profile_page/cubit/log_out_state.dart';
|
||||
import 'package:tcp_client/home/view/profile_page/view/log_out_button.dart';
|
||||
import 'package:tcp_client/login/login_page.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
|
||||
class MyProfilePage extends StatelessWidget {
|
||||
const MyProfilePage({
|
||||
required this.userID,
|
||||
super.key
|
||||
});
|
||||
|
||||
static Route<void> route({
|
||||
required int userID,
|
||||
}) => MaterialPageRoute<void>(builder: (context) => MyProfilePage(
|
||||
userID: userID,
|
||||
));
|
||||
|
||||
final int userID;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<LogOutCubit>(
|
||||
create: (context) => LogOutCubit(tcpRepository: context.read<TCPRepository>()),
|
||||
child: BlocListener<LogOutCubit, LogOutStatus>(
|
||||
listenWhen: (previous, current) => current == LogOutStatus.done || (previous == LogOutStatus.processing && current == LogOutStatus.none),
|
||||
listener: (context, state) {
|
||||
if(state == LogOutStatus.none) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Log out failed'))
|
||||
);
|
||||
}
|
||||
else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Logged out'))
|
||||
);
|
||||
Future.delayed(const Duration(seconds: 1)).then((_) {
|
||||
Navigator.of(context).pushAndRemoveUntil(LoginPage.route(
|
||||
localServiceRepository: context.read<LocalServiceRepository>(),
|
||||
tcpRepository: context.read<TCPRepository>()
|
||||
), (route) => false);
|
||||
});
|
||||
}
|
||||
},
|
||||
child: BlocBuilder<LogOutCubit, LogOutStatus>(
|
||||
builder: (context, state) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(60),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
UserAvatar(userid: userID, size: 96,),
|
||||
const SizedBox(height: 48,),
|
||||
UserNameText(
|
||||
userid: userID,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22,
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
const SizedBox(height: 48,),
|
||||
const LogoutButton(),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
43
lib/home/view/profile_page/view/log_out_button.dart
Normal file
43
lib/home/view/profile_page/view/log_out_button.dart
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 10:53:24
|
||||
* @LastEditTime : 2022-10-14 11:12:22
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/home/view/profile_page/cubit/log_out_cubit.dart';
|
||||
|
||||
class LogoutButton extends StatelessWidget {
|
||||
const LogoutButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
context.read<LogOutCubit>().onLogout();
|
||||
},
|
||||
style: ButtonStyle(
|
||||
elevation: MaterialStateProperty.all(0),
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))),
|
||||
minimumSize: MaterialStateProperty.all(const Size(300, 0)),
|
||||
backgroundColor: MaterialStateProperty.all(Colors.red[700]),
|
||||
overlayColor: MaterialStateProperty.all(Colors.red[900]!.withOpacity(0.2)),
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12
|
||||
),
|
||||
child: Text(
|
||||
'Log Out',
|
||||
style: TextStyle(
|
||||
fontSize: 20
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,14 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 15:06:30
|
||||
* @LastEditTime : 2022-10-13 16:46:06
|
||||
* @LastEditTime : 2022-10-14 10:47:08
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:formz/formz.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tcp_client/home/home_page.dart';
|
||||
import 'package:tcp_client/login/cubit/login_cubit.dart';
|
||||
import 'package:tcp_client/login/cubit/login_state.dart';
|
||||
@ -53,8 +54,13 @@ class LoginPage extends StatelessWidget {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Login Successed'))
|
||||
);
|
||||
Future.delayed(const Duration(seconds: 1)).then((_) {
|
||||
Future<int>(() async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
var pref = await SharedPreferences.getInstance();
|
||||
return pref.getInt('userid')!;
|
||||
}).then((userID) {
|
||||
Navigator.of(context).pushReplacement(HomePage.route(
|
||||
userID: userID,
|
||||
localServiceRepository: localServiceRepository,
|
||||
tcpRepository: tcpRepository
|
||||
));
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-10 08:04:53
|
||||
* @LastEditTime : 2022-10-13 16:46:33
|
||||
* @LastEditTime : 2022-10-14 11:45:01
|
||||
* @Description :
|
||||
*/
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@ -30,6 +31,9 @@ class MyApp extends StatelessWidget {
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
||||
dragDevices: {PointerDeviceKind.mouse, PointerDeviceKind.touch, PointerDeviceKind.stylus, PointerDeviceKind.unknown},
|
||||
),
|
||||
home: const SplashPage(),
|
||||
);
|
||||
}
|
||||
@ -50,9 +54,14 @@ class SplashPage extends StatelessWidget {
|
||||
child: BlocListener<InitializationCubit, InitializationState>(
|
||||
listener: (context, state) {
|
||||
if(state.isDone) {
|
||||
Future.delayed(const Duration(seconds: 1)).then((_) async {
|
||||
if((await SharedPreferences.getInstance()).getInt('userid') != null) {
|
||||
Future<int?>(() async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
var pref = await SharedPreferences.getInstance();
|
||||
return pref.getInt('userid');
|
||||
}).then((userID) {
|
||||
if(userID != null) {
|
||||
Navigator.of(context).pushReplacement(HomePage.route(
|
||||
userID: userID,
|
||||
localServiceRepository: state.localServiceRepository!,
|
||||
tcpRepository: state.tcpRepository!
|
||||
));
|
||||
|
||||
65
lib/profile/cubit/user_profile_cubit.dart
Normal file
65
lib/profile/cubit/user_profile_cubit.dart
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 08:54:32
|
||||
* @LastEditTime : 2022-10-14 11:30:59
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tcp_client/profile/cubit/user_profile_state.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_response.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
|
||||
class UserProfileCubit extends Cubit<UserProfileState> {
|
||||
UserProfileCubit({
|
||||
required this.userID,
|
||||
required this.tcpRepository
|
||||
}): super(const UserProfileState(status: ContactStatus.none)) {
|
||||
updateContactStatus();
|
||||
}
|
||||
|
||||
final int userID;
|
||||
final TCPRepository tcpRepository;
|
||||
|
||||
Future<void> updateContactStatus() async {
|
||||
if(userID == (await SharedPreferences.getInstance()).getInt('userid')) {
|
||||
emit(const UserProfileState(status: ContactStatus.none));
|
||||
}
|
||||
var clonedTCPRepository = await tcpRepository.clone();
|
||||
clonedTCPRepository.pushRequest(FetchContactRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
||||
await for(var response in clonedTCPRepository.responseStreamBroadcast) {
|
||||
if(response.type == TCPResponseType.fetchContact) {
|
||||
response as FetchContactResponse;
|
||||
if(response.addedContacts.any((element) => element.userID == userID)) {
|
||||
emit(const UserProfileState(status: ContactStatus.isContact));
|
||||
}
|
||||
else if(response.pendingContacts.any((element) => element.userID == userID)) {
|
||||
emit(const UserProfileState(status: ContactStatus.pendingReply));
|
||||
}
|
||||
else {
|
||||
emit(const UserProfileState(status: ContactStatus.notContact));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
clonedTCPRepository.dispose();
|
||||
}
|
||||
|
||||
Future<void> addContact() async {
|
||||
emit(const UserProfileState(status: ContactStatus.consulting));
|
||||
var clonedTCPRepository = await tcpRepository.clone();
|
||||
clonedTCPRepository.pushRequest(AddContactRequest(
|
||||
userid: userID,
|
||||
token: (await SharedPreferences.getInstance()).getInt('token')
|
||||
));
|
||||
await for(var response in clonedTCPRepository.responseStreamBroadcast) {
|
||||
if(response.type == TCPResponseType.addContact) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
clonedTCPRepository.dispose();
|
||||
updateContactStatus();
|
||||
}
|
||||
}
|
||||
19
lib/profile/cubit/user_profile_state.dart
Normal file
19
lib/profile/cubit/user_profile_state.dart
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 08:54:25
|
||||
* @LastEditTime : 2022-10-14 09:11:04
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
enum ContactStatus { isContact, pendingReply, notContact, consulting, none }
|
||||
|
||||
class UserProfileState extends Equatable {
|
||||
final ContactStatus status;
|
||||
|
||||
const UserProfileState({required this.status});
|
||||
|
||||
@override
|
||||
List<Object> get props => [status];
|
||||
}
|
||||
@ -1,6 +1,89 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 17:04:44
|
||||
* @LastEditTime : 2022-10-13 17:04:44
|
||||
* @LastEditTime : 2022-10-14 12:11:26
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/common/avatar/avatar.dart';
|
||||
import 'package:tcp_client/common/username/username.dart';
|
||||
import 'package:tcp_client/profile/cubit/user_profile_cubit.dart';
|
||||
import 'package:tcp_client/profile/view/add_contact_button.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
|
||||
class ProfilePage extends StatelessWidget {
|
||||
const ProfilePage({
|
||||
required this.userID,
|
||||
required this.localServiceRepository,
|
||||
required this.tcpRepository,
|
||||
required this.userRepository,
|
||||
super.key
|
||||
});
|
||||
|
||||
static Route<void> route({
|
||||
required int userID,
|
||||
required LocalServiceRepository localServiceRepository,
|
||||
required TCPRepository tcpRepository,
|
||||
required UserRepository userRepository
|
||||
}) => MaterialPageRoute<void>(builder: (context) => ProfilePage(
|
||||
userID: userID,
|
||||
localServiceRepository: localServiceRepository,
|
||||
tcpRepository: tcpRepository,
|
||||
userRepository: userRepository,
|
||||
));
|
||||
|
||||
final int userID;
|
||||
final LocalServiceRepository localServiceRepository;
|
||||
final TCPRepository tcpRepository;
|
||||
final UserRepository userRepository;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiRepositoryProvider(
|
||||
providers: [
|
||||
RepositoryProvider<UserRepository>.value(
|
||||
value: userRepository,
|
||||
),
|
||||
RepositoryProvider<LocalServiceRepository>.value(
|
||||
value: localServiceRepository,
|
||||
),
|
||||
RepositoryProvider<TCPRepository>.value(
|
||||
value: tcpRepository,
|
||||
)
|
||||
],
|
||||
child: BlocProvider<UserProfileCubit>(
|
||||
create: (context) => UserProfileCubit(
|
||||
userID: userID,
|
||||
tcpRepository: tcpRepository,
|
||||
),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: Container(
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.all(60),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
UserAvatar(userid: userID, size: 96,),
|
||||
const SizedBox(height: 48,),
|
||||
UserNameText(
|
||||
userid: userID,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22,
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
const SizedBox(height: 48,),
|
||||
AddContactButton(userID: userID)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
142
lib/profile/view/add_contact_button.dart
Normal file
142
lib/profile/view/add_contact_button.dart
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 09:34:53
|
||||
* @LastEditTime : 2022-10-14 12:00:52
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/chat/chat_page.dart';
|
||||
import 'package:tcp_client/profile/cubit/user_profile_cubit.dart';
|
||||
import 'package:tcp_client/profile/cubit/user_profile_state.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
|
||||
class AddContactButton extends StatelessWidget {
|
||||
const AddContactButton({
|
||||
required this.userID,
|
||||
super.key
|
||||
});
|
||||
|
||||
final int userID;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<UserProfileCubit, UserProfileState>(
|
||||
builder: (context, state) {
|
||||
if(state.status == ContactStatus.isContact) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(ChatPage.route(
|
||||
userRepository: context.read<UserRepository>(),
|
||||
localServiceRepository: context.read<LocalServiceRepository>(),
|
||||
tcpRepository: context.read<TCPRepository>(),
|
||||
userID: userID
|
||||
));
|
||||
},
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))),
|
||||
minimumSize: MaterialStateProperty.all(const Size(300, 0)),
|
||||
backgroundColor: MaterialStateProperty.all(Colors.blue),
|
||||
overlayColor: MaterialStateProperty.all(Colors.blue[800]!.withOpacity(0.2)),
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12
|
||||
),
|
||||
child: Text(
|
||||
'Chat',
|
||||
style: TextStyle(
|
||||
fontSize: 20
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
if(state.status == ContactStatus.pendingReply) {
|
||||
return TextButton(
|
||||
onPressed: null,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))),
|
||||
minimumSize: MaterialStateProperty.all(const Size(300, 0)),
|
||||
backgroundColor: MaterialStateProperty.all(Colors.grey[400]),
|
||||
overlayColor: MaterialStateProperty.all(Colors.grey[800]!.withOpacity(0.2)),
|
||||
foregroundColor: MaterialStateProperty.all(Colors.grey[800]),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12
|
||||
),
|
||||
child: Text(
|
||||
'Pending for Reply',
|
||||
style: TextStyle(
|
||||
fontSize: 20
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
else if(state.status == ContactStatus.notContact) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
context.read<UserProfileCubit>().addContact();
|
||||
},
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))),
|
||||
minimumSize: MaterialStateProperty.all(const Size(300, 0)),
|
||||
backgroundColor: MaterialStateProperty.all(Colors.blue),
|
||||
overlayColor: MaterialStateProperty.all(Colors.blue[800]!.withOpacity(0.2)),
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12
|
||||
),
|
||||
child: Text(
|
||||
'Add Contact',
|
||||
style: TextStyle(
|
||||
fontSize: 20
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
else if(state.status == ContactStatus.consulting) {
|
||||
return TextButton(
|
||||
onPressed: null,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))),
|
||||
minimumSize: MaterialStateProperty.all(const Size(300, 0)),
|
||||
backgroundColor: MaterialStateProperty.all(Colors.blue),
|
||||
overlayColor: MaterialStateProperty.all(Colors.blue[800]!.withOpacity(0.2)),
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12
|
||||
),
|
||||
child: SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
strokeWidth: 2.0,
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 17:36:38
|
||||
* @LastEditTime : 2022-10-13 16:45:44
|
||||
* @LastEditTime : 2022-10-14 11:22:38
|
||||
* @Description :
|
||||
*/
|
||||
/*
|
||||
@ -14,6 +14,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:formz/formz.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tcp_client/home/home_page.dart';
|
||||
import 'package:tcp_client/register/cubit/register_cubit.dart';
|
||||
import 'package:tcp_client/register/cubit/register_state.dart';
|
||||
@ -63,11 +64,16 @@ class RegisterPage extends StatelessWidget {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Register Successed'))
|
||||
);
|
||||
Future.delayed(const Duration(seconds: 1)).then((_) {
|
||||
Navigator.of(context).pushReplacement(HomePage.route(
|
||||
Future<int>(() async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
var pref = await SharedPreferences.getInstance();
|
||||
return pref.getInt('userid')!;
|
||||
}).then((userID) {
|
||||
Navigator.of(context).pushAndRemoveUntil(HomePage.route(
|
||||
userID: userID,
|
||||
localServiceRepository: localServiceRepository,
|
||||
tcpRepository: tcpRepository
|
||||
));
|
||||
), (route) => false);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-11 11:02:19
|
||||
* @LastEditTime : 2022-10-12 13:25:49
|
||||
* @LastEditTime : 2022-10-14 12:16:04
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -236,7 +236,11 @@ class FetchContactResponse extends TCPResponse {
|
||||
FetchContactResponse({
|
||||
required Map<String, Object?> jsonObject
|
||||
}): super(jsonObject: jsonObject) {
|
||||
var body = jsonObject['body'] as Map<String, Object?>;
|
||||
var body = jsonObject['body'] as Map<String, Object?>? ?? {
|
||||
'contacts': [],
|
||||
'pending': [],
|
||||
'requesting': []
|
||||
};
|
||||
var rawAddedContacts = body['contacts'] as List;
|
||||
var rawPendingContacts = body['pending'] as List;
|
||||
var rawRequestingContacts = body['requesting'] as List;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-11 09:42:05
|
||||
* @LastEditTime : 2022-10-12 23:35:10
|
||||
* @LastEditTime : 2022-10-14 09:15:47
|
||||
* @Description : TCP repository
|
||||
*/
|
||||
|
||||
@ -56,6 +56,13 @@ class TCPRepository {
|
||||
);
|
||||
}
|
||||
|
||||
Future<TCPRepository> clone() async {
|
||||
return await TCPRepository.create(
|
||||
serverAddress: _remoteAddress,
|
||||
serverPort: _remotePort
|
||||
);
|
||||
}
|
||||
|
||||
final Socket _socket;
|
||||
final String _remoteAddress;
|
||||
final int _remotePort;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 17:04:12
|
||||
* @LastEditTime : 2022-10-13 23:24:13
|
||||
* @LastEditTime : 2022-10-14 10:38:44
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -59,11 +59,17 @@ class SearchPage extends StatelessWidget {
|
||||
if(state.userResults.isNotEmpty)
|
||||
...[
|
||||
const SizedBox(height: 16.0,),
|
||||
const Text(
|
||||
'Users',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 36.0,
|
||||
vertical: 8.0
|
||||
),
|
||||
child: Text(
|
||||
'Users',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8.0,),
|
||||
@ -72,11 +78,17 @@ class SearchPage extends StatelessWidget {
|
||||
if(state.historyResults.isNotEmpty)
|
||||
...[
|
||||
const SizedBox(height: 16.0,),
|
||||
const Text(
|
||||
'Histories',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 36.0,
|
||||
vertical: 8.0
|
||||
),
|
||||
child: Text(
|
||||
'Histories',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8.0,),
|
||||
@ -86,16 +98,22 @@ class SearchPage extends StatelessWidget {
|
||||
))
|
||||
],
|
||||
if(state.historyResults.isEmpty && state.userResults.isEmpty)
|
||||
const Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'No result found',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20
|
||||
...[
|
||||
const SizedBox(height: 16.0,),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 36.0,
|
||||
vertical: 8.0
|
||||
),
|
||||
child: Text(
|
||||
'No Results',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:41:49
|
||||
* @LastEditTime : 2022-10-13 22:31:37
|
||||
* @LastEditTime : 2022-10-14 10:38:31
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -25,7 +25,7 @@ class HistoryTile extends StatelessWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16.0,
|
||||
horizontal: 24.0
|
||||
horizontal: 36.0
|
||||
),
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
|
||||
@ -1,14 +1,21 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:41:41
|
||||
* @LastEditTime : 2022-10-13 23:26:46
|
||||
* @LastEditTime : 2022-10-14 12:04:26
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/common/avatar/avatar.dart';
|
||||
import 'package:tcp_client/common/username/username.dart';
|
||||
import 'package:tcp_client/profile/user_profile_page.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/user_repository/user_repository.dart';
|
||||
import 'package:tcp_client/search/cubit/search_cubit.dart';
|
||||
|
||||
class UserTile extends StatelessWidget {
|
||||
const UserTile({
|
||||
@ -20,54 +27,37 @@ class UserTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
border: Border.all(
|
||||
color: Colors.grey[700]!,
|
||||
width: 1.0
|
||||
)
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
child: OverflowBox(
|
||||
alignment: Alignment.center,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
child: Image.memory(base64.decode(userInfo.avatarEncoded!)),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
if(userInfo.avatarEncoded == null || userInfo.avatarEncoded!.isEmpty)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
border: Border.all(
|
||||
color: Colors.grey[700]!,
|
||||
width: 1.0
|
||||
)
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12,),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12.0
|
||||
),
|
||||
child: Text(
|
||||
userInfo.userName,
|
||||
style: const TextStyle(
|
||||
fontSize: 18.0
|
||||
),
|
||||
),
|
||||
)
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(ProfilePage.route(
|
||||
userID: userInfo.userID,
|
||||
localServiceRepository: context.read<SearchCubit>().localServiceRepository,
|
||||
tcpRepository: context.read<SearchCubit>().tcpRepository,
|
||||
userRepository: context.read<UserRepository>()
|
||||
));
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 36,
|
||||
vertical: 16,
|
||||
),
|
||||
],
|
||||
child: Row(
|
||||
children: [
|
||||
UserAvatar(userid: userInfo.userID),
|
||||
const SizedBox(width: 12,),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12.0
|
||||
),
|
||||
child: UserNameText(
|
||||
userid: userInfo.userID,
|
||||
)
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user