mirror of
https://github.com/Linloir/Simple-TCP-Client.git
synced 2026-02-04 14:23:35 +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,35 +1,55 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 14:03:16
|
* @Date : 2022-10-13 14:03:16
|
||||||
* @LastEditTime : 2022-10-13 16:29:57
|
* @LastEditTime : 2022-10-14 11:58:34
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
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 {
|
class ChatPage extends StatelessWidget {
|
||||||
const ChatPage({
|
const ChatPage({
|
||||||
required this.userInfo,
|
required this.userRepository,
|
||||||
|
required this.localServiceRepository,
|
||||||
|
required this.tcpRepository,
|
||||||
|
required this.userID,
|
||||||
super.key
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return RepositoryProvider<UserRepository>.value(
|
||||||
|
value: userRepository,
|
||||||
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: UserNameText(
|
||||||
userInfo.userName,
|
userid: userID,
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 18
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 21:49:53
|
* @Date : 2022-10-13 21:49:53
|
||||||
* @LastEditTime : 2022-10-13 22:17:17
|
* @LastEditTime : 2022-10-14 10:32:50
|
||||||
* @Description :
|
* @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';
|
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||||
|
|
||||||
class UserAvatar extends StatelessWidget {
|
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 int userid;
|
||||||
|
final double size;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -28,16 +33,18 @@ class UserAvatar extends StatelessWidget {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if(state.userInfo.avatarEncoded == null) {
|
if(state.userInfo.avatarEncoded == null) {
|
||||||
return Container(
|
return Container(
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.grey[800],
|
color: Colors.grey[600],
|
||||||
borderRadius: BorderRadius.circular(5.0),
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
boxShadow: [BoxShadow(blurRadius: 10.0, color: Colors.grey[850]!.withOpacity(0.15))]
|
boxShadow: [BoxShadow(blurRadius: 10.0, color: Colors.grey[850]!.withOpacity(0.15))]
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
state.userInfo.userName[0],
|
state.userInfo.userName[0].toUpperCase(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 24 * (size / 48),
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
shadows: [Shadow(blurRadius: 5.0, color: Colors.white.withOpacity(0.15))]
|
shadows: [Shadow(blurRadius: 5.0, color: Colors.white.withOpacity(0.15))]
|
||||||
@ -47,6 +54,8 @@ class UserAvatar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Container(
|
return Container(
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(5.0),
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
boxShadow: [BoxShadow(blurRadius: 10.0, color: Colors.grey[850]!.withOpacity(0.15))]
|
boxShadow: [BoxShadow(blurRadius: 10.0, color: Colors.grey[850]!.withOpacity(0.15))]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 22:05:12
|
* @Date : 2022-10-13 22:05:12
|
||||||
* @LastEditTime : 2022-10-13 22:21:42
|
* @LastEditTime : 2022-10-14 12:10:46
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -15,11 +15,15 @@ class UserNameText extends StatelessWidget {
|
|||||||
const UserNameText({
|
const UserNameText({
|
||||||
required this.userid,
|
required this.userid,
|
||||||
this.fontWeight = FontWeight.normal,
|
this.fontWeight = FontWeight.normal,
|
||||||
|
this.fontSize = 18,
|
||||||
|
this.alignment = Alignment.centerLeft,
|
||||||
super.key
|
super.key
|
||||||
});
|
});
|
||||||
|
|
||||||
final int userid;
|
final int userid;
|
||||||
final FontWeight fontWeight;
|
final FontWeight fontWeight;
|
||||||
|
final double fontSize;
|
||||||
|
final Alignment alignment;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -29,12 +33,15 @@ class UserNameText extends StatelessWidget {
|
|||||||
userRepository: context.read<UserRepository>()
|
userRepository: context.read<UserRepository>()
|
||||||
),
|
),
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Text(
|
return Align(
|
||||||
|
alignment: alignment,
|
||||||
|
child: Text(
|
||||||
state.userInfo.userName,
|
state.userInfo.userName,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: fontSize,
|
||||||
fontWeight: fontWeight
|
fontWeight: fontWeight
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-11 11:05:08
|
* @Date : 2022-10-11 11:05:08
|
||||||
* @LastEditTime : 2022-10-13 23:02:55
|
* @LastEditTime : 2022-10-14 10:52:26
|
||||||
* @Description :
|
* @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/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/cubit/msg_list_cubit.dart';
|
||||||
import 'package:tcp_client/home/view/message_page/mesage_page.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/local_service_repository/local_service_repository.dart';
|
||||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||||
import 'package:tcp_client/repositories/user_repository/user_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 {
|
class HomePage extends StatelessWidget {
|
||||||
const HomePage({
|
const HomePage({
|
||||||
|
required this.userID,
|
||||||
required this.localServiceRepository,
|
required this.localServiceRepository,
|
||||||
required this.tcpRepository,
|
required this.tcpRepository,
|
||||||
super.key
|
super.key
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final int userID;
|
||||||
final LocalServiceRepository localServiceRepository;
|
final LocalServiceRepository localServiceRepository;
|
||||||
final TCPRepository tcpRepository;
|
final TCPRepository tcpRepository;
|
||||||
|
|
||||||
static Route<void> route({
|
static Route<void> route({
|
||||||
|
required int userID,
|
||||||
required LocalServiceRepository localServiceRepository,
|
required LocalServiceRepository localServiceRepository,
|
||||||
required TCPRepository tcpRepository
|
required TCPRepository tcpRepository
|
||||||
}) => MaterialPageRoute<void>(builder: (context) => HomePage(
|
}) => MaterialPageRoute<void>(builder: (context) => HomePage(
|
||||||
|
userID: userID,
|
||||||
localServiceRepository: localServiceRepository,
|
localServiceRepository: localServiceRepository,
|
||||||
tcpRepository: tcpRepository,
|
tcpRepository: tcpRepository,
|
||||||
));
|
));
|
||||||
@ -70,16 +75,20 @@ class HomePage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
child: HomePageView(),
|
child: HomePageView(userID: userID,),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HomePageView extends StatelessWidget {
|
class HomePageView extends StatelessWidget {
|
||||||
HomePageView({super.key});
|
HomePageView({
|
||||||
|
required this.userID,
|
||||||
|
super.key
|
||||||
|
});
|
||||||
|
|
||||||
final PageController _controller = PageController();
|
final PageController _controller = PageController();
|
||||||
|
final int userID;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -122,9 +131,10 @@ class HomePageView extends StatelessWidget {
|
|||||||
builder:(context, state) => PageView(
|
builder:(context, state) => PageView(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
onPageChanged: (value) => context.read<HomeCubit>().switchPage(HomePagePosition.fromValue(value)),
|
onPageChanged: (value) => context.read<HomeCubit>().switchPage(HomePagePosition.fromValue(value)),
|
||||||
children: const [
|
children: [
|
||||||
MessagePage(),
|
const MessagePage(),
|
||||||
ContactPage()
|
const ContactPage(),
|
||||||
|
MyProfilePage(userID: userID)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-12 23:36:07
|
* @Date : 2022-10-12 23:36:07
|
||||||
* @LastEditTime : 2022-10-13 22:59:25
|
* @LastEditTime : 2022-10-14 11:45:35
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -19,7 +19,6 @@ class ContactPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.green,
|
|
||||||
child: BlocBuilder<ContactCubit, ContactState>(
|
child: BlocBuilder<ContactCubit, ContactState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return AzListView(
|
return AzListView(
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 14:01:45
|
* @Date : 2022-10-13 14:01:45
|
||||||
* @LastEditTime : 2022-10-13 14:50:34
|
* @LastEditTime : 2022-10-14 11:49:50
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:tcp_client/home/view/contact_page/cubit/contact_state.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.localServiceRepository,
|
||||||
required this.tcpRepository
|
required this.tcpRepository
|
||||||
}): super(ContactState.empty()) {
|
}): super(ContactState.empty()) {
|
||||||
tcpRepository.responseStreamBroadcast.listen(_onResponse);
|
subscription = tcpRepository.responseStreamBroadcast.listen(_onResponse);
|
||||||
|
updateContacts();
|
||||||
|
timer = Timer.periodic(const Duration(seconds: 5), (timer) {updateContacts();});
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalServiceRepository localServiceRepository;
|
final LocalServiceRepository localServiceRepository;
|
||||||
TCPRepository tcpRepository;
|
final TCPRepository tcpRepository;
|
||||||
|
late final StreamSubscription subscription;
|
||||||
|
late final Timer timer;
|
||||||
|
|
||||||
void _onResponse(TCPResponse response) {
|
void _onResponse(TCPResponse response) {
|
||||||
switch(response.type) {
|
switch(response.type) {
|
||||||
@ -42,4 +48,12 @@ class ContactCubit extends Cubit<ContactState> {
|
|||||||
Future<void> updateContacts() async {
|
Future<void> updateContacts() async {
|
||||||
tcpRepository.pushRequest(FetchContactRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
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
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 14:02:00
|
* @Date : 2022-10-13 14:02:00
|
||||||
* @LastEditTime : 2022-10-13 22:26:07
|
* @LastEditTime : 2022-10-14 11:59:48
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -10,10 +10,15 @@ import 'dart:convert';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:tcp_client/chat/chat_page.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_cubit.dart';
|
||||||
import 'package:tcp_client/home/cubit/home_state.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/home/view/message_page/cubit/msg_list_cubit.dart';
|
||||||
import 'package:tcp_client/repositories/common_models/userinfo.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 {
|
class ContactTile extends StatelessWidget {
|
||||||
const ContactTile({
|
const ContactTile({
|
||||||
@ -31,60 +36,36 @@ class ContactTile extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
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<MessageListCubit>().addEmptyMessageOf(targetUser: userInfo.userID);
|
||||||
context.read<HomeCubit>().switchPage(HomePagePosition.message);
|
context.read<HomeCubit>().switchPage(HomePagePosition.message);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Row(
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
UserAvatar(userid: userInfo.userID),
|
||||||
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,),
|
const SizedBox(width: 12,),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 12.0
|
vertical: 12.0
|
||||||
),
|
),
|
||||||
child: Text(
|
child: UserNameText(userid: userInfo.userID,)
|
||||||
userInfo.userName,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18.0
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-11 11:05:18
|
* @Date : 2022-10-11 11:05:18
|
||||||
* @LastEditTime : 2022-10-13 22:59:10
|
* @LastEditTime : 2022-10-14 11:45:45
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -19,7 +19,6 @@ class MessagePage extends StatelessWidget {
|
|||||||
return BlocBuilder<MessageListCubit, MessageListState>(
|
return BlocBuilder<MessageListCubit, MessageListState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.blue,
|
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return MessageTile(
|
return MessageTile(
|
||||||
|
|||||||
@ -1,17 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 13:17:52
|
* @Date : 2022-10-13 13:17:52
|
||||||
* @LastEditTime : 2022-10-13 22:23:31
|
* @LastEditTime : 2022-10-14 12:07:32
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
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/avatar/avatar.dart';
|
||||||
import 'package:tcp_client/common/username/username.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/message.dart';
|
||||||
import 'package:tcp_client/repositories/common_models/userinfo.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 {
|
class MessageTile extends StatelessWidget {
|
||||||
const MessageTile({
|
const MessageTile({
|
||||||
@ -25,12 +30,25 @@ class MessageTile extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
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(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 16.0,
|
vertical: 8.0,
|
||||||
horizontal: 24.0
|
horizontal: 24.0
|
||||||
),
|
),
|
||||||
child: IntrinsicHeight(
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
@ -67,7 +85,7 @@ class MessageTile extends StatelessWidget {
|
|||||||
// )
|
// )
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(width: 12,),
|
const SizedBox(width: 16,),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -110,6 +128,8 @@ class MessageTile extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-12 23:36:12
|
* @Date : 2022-10-12 23:36:12
|
||||||
* @LastEditTime : 2022-10-12 23:36:57
|
* @LastEditTime : 2022-10-14 12:10:34
|
||||||
* @Description :
|
* @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
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-12 15:06:30
|
* @Date : 2022-10-12 15:06:30
|
||||||
* @LastEditTime : 2022-10-13 16:46:06
|
* @LastEditTime : 2022-10-14 10:47:08
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:formz/formz.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/home/home_page.dart';
|
||||||
import 'package:tcp_client/login/cubit/login_cubit.dart';
|
import 'package:tcp_client/login/cubit/login_cubit.dart';
|
||||||
import 'package:tcp_client/login/cubit/login_state.dart';
|
import 'package:tcp_client/login/cubit/login_state.dart';
|
||||||
@ -53,8 +54,13 @@ class LoginPage extends StatelessWidget {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Login Successed'))
|
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(
|
Navigator.of(context).pushReplacement(HomePage.route(
|
||||||
|
userID: userID,
|
||||||
localServiceRepository: localServiceRepository,
|
localServiceRepository: localServiceRepository,
|
||||||
tcpRepository: tcpRepository
|
tcpRepository: tcpRepository
|
||||||
));
|
));
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-10 08:04:53
|
* @Date : 2022-10-10 08:04:53
|
||||||
* @LastEditTime : 2022-10-13 16:46:33
|
* @LastEditTime : 2022-10-14 11:45:01
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@ -30,6 +31,9 @@ class MyApp extends StatelessWidget {
|
|||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
),
|
),
|
||||||
|
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
||||||
|
dragDevices: {PointerDeviceKind.mouse, PointerDeviceKind.touch, PointerDeviceKind.stylus, PointerDeviceKind.unknown},
|
||||||
|
),
|
||||||
home: const SplashPage(),
|
home: const SplashPage(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -50,9 +54,14 @@ class SplashPage extends StatelessWidget {
|
|||||||
child: BlocListener<InitializationCubit, InitializationState>(
|
child: BlocListener<InitializationCubit, InitializationState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if(state.isDone) {
|
if(state.isDone) {
|
||||||
Future.delayed(const Duration(seconds: 1)).then((_) async {
|
Future<int?>(() async {
|
||||||
if((await SharedPreferences.getInstance()).getInt('userid') != null) {
|
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(
|
Navigator.of(context).pushReplacement(HomePage.route(
|
||||||
|
userID: userID,
|
||||||
localServiceRepository: state.localServiceRepository!,
|
localServiceRepository: state.localServiceRepository!,
|
||||||
tcpRepository: state.tcpRepository!
|
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
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 17:04:44
|
* @Date : 2022-10-13 17:04:44
|
||||||
* @LastEditTime : 2022-10-13 17:04:44
|
* @LastEditTime : 2022-10-14 12:11:26
|
||||||
* @Description :
|
* @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
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-12 17:36:38
|
* @Date : 2022-10-12 17:36:38
|
||||||
* @LastEditTime : 2022-10-13 16:45:44
|
* @LastEditTime : 2022-10-14 11:22:38
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
@ -14,6 +14,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:formz/formz.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/home/home_page.dart';
|
||||||
import 'package:tcp_client/register/cubit/register_cubit.dart';
|
import 'package:tcp_client/register/cubit/register_cubit.dart';
|
||||||
import 'package:tcp_client/register/cubit/register_state.dart';
|
import 'package:tcp_client/register/cubit/register_state.dart';
|
||||||
@ -63,11 +64,16 @@ class RegisterPage extends StatelessWidget {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Register Successed'))
|
const SnackBar(content: Text('Register Successed'))
|
||||||
);
|
);
|
||||||
Future.delayed(const Duration(seconds: 1)).then((_) {
|
Future<int>(() async {
|
||||||
Navigator.of(context).pushReplacement(HomePage.route(
|
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,
|
localServiceRepository: localServiceRepository,
|
||||||
tcpRepository: tcpRepository
|
tcpRepository: tcpRepository
|
||||||
));
|
), (route) => false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-11 11:02:19
|
* @Date : 2022-10-11 11:02:19
|
||||||
* @LastEditTime : 2022-10-12 13:25:49
|
* @LastEditTime : 2022-10-14 12:16:04
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -236,7 +236,11 @@ class FetchContactResponse extends TCPResponse {
|
|||||||
FetchContactResponse({
|
FetchContactResponse({
|
||||||
required Map<String, Object?> jsonObject
|
required Map<String, Object?> jsonObject
|
||||||
}): super(jsonObject: 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 rawAddedContacts = body['contacts'] as List;
|
||||||
var rawPendingContacts = body['pending'] as List;
|
var rawPendingContacts = body['pending'] as List;
|
||||||
var rawRequestingContacts = body['requesting'] as List;
|
var rawRequestingContacts = body['requesting'] as List;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-11 09:42:05
|
* @Date : 2022-10-11 09:42:05
|
||||||
* @LastEditTime : 2022-10-12 23:35:10
|
* @LastEditTime : 2022-10-14 09:15:47
|
||||||
* @Description : TCP repository
|
* @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 Socket _socket;
|
||||||
final String _remoteAddress;
|
final String _remoteAddress;
|
||||||
final int _remotePort;
|
final int _remotePort;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 17:04:12
|
* @Date : 2022-10-13 17:04:12
|
||||||
* @LastEditTime : 2022-10-13 23:24:13
|
* @LastEditTime : 2022-10-14 10:38:44
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -59,26 +59,38 @@ class SearchPage extends StatelessWidget {
|
|||||||
if(state.userResults.isNotEmpty)
|
if(state.userResults.isNotEmpty)
|
||||||
...[
|
...[
|
||||||
const SizedBox(height: 16.0,),
|
const SizedBox(height: 16.0,),
|
||||||
const Text(
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 36.0,
|
||||||
|
vertical: 8.0
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
'Users',
|
'Users',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 20
|
fontSize: 20
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 8.0,),
|
const SizedBox(height: 8.0,),
|
||||||
...state.userResults.map((e) => UserTile(userInfo: e.userInfo))
|
...state.userResults.map((e) => UserTile(userInfo: e.userInfo))
|
||||||
],
|
],
|
||||||
if(state.historyResults.isNotEmpty)
|
if(state.historyResults.isNotEmpty)
|
||||||
...[
|
...[
|
||||||
const SizedBox(height: 16.0,),
|
const SizedBox(height: 16.0,),
|
||||||
const Text(
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 36.0,
|
||||||
|
vertical: 8.0
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
'Histories',
|
'Histories',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 20
|
fontSize: 20
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 8.0,),
|
const SizedBox(height: 8.0,),
|
||||||
...state.historyResults.map((e) => HistoryTile(
|
...state.historyResults.map((e) => HistoryTile(
|
||||||
userID: e.contact,
|
userID: e.contact,
|
||||||
@ -86,16 +98,22 @@ class SearchPage extends StatelessWidget {
|
|||||||
))
|
))
|
||||||
],
|
],
|
||||||
if(state.historyResults.isEmpty && state.userResults.isEmpty)
|
if(state.historyResults.isEmpty && state.userResults.isEmpty)
|
||||||
const Align(
|
...[
|
||||||
alignment: Alignment.center,
|
const SizedBox(height: 16.0,),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 36.0,
|
||||||
|
vertical: 8.0
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'No result found',
|
'No Results',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 20
|
fontSize: 20
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 21:41:49
|
* @Date : 2022-10-13 21:41:49
|
||||||
* @LastEditTime : 2022-10-13 22:31:37
|
* @LastEditTime : 2022-10-14 10:38:31
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ class HistoryTile extends StatelessWidget {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 16.0,
|
vertical: 16.0,
|
||||||
horizontal: 24.0
|
horizontal: 36.0
|
||||||
),
|
),
|
||||||
child: IntrinsicHeight(
|
child: IntrinsicHeight(
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|||||||
@ -1,14 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* @Author : Linloir
|
* @Author : Linloir
|
||||||
* @Date : 2022-10-13 21:41:41
|
* @Date : 2022-10-13 21:41:41
|
||||||
* @LastEditTime : 2022-10-13 23:26:46
|
* @LastEditTime : 2022-10-14 12:04:26
|
||||||
* @Description :
|
* @Description :
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
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/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 {
|
class UserTile extends StatelessWidget {
|
||||||
const UserTile({
|
const UserTile({
|
||||||
@ -20,54 +27,37 @@ class UserTile extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
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: [
|
children: [
|
||||||
if(userInfo.avatarEncoded != null && userInfo.avatarEncoded!.isEmpty)
|
UserAvatar(userid: userInfo.userID),
|
||||||
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,),
|
const SizedBox(width: 12,),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 12.0
|
vertical: 12.0
|
||||||
),
|
),
|
||||||
child: Text(
|
child: UserNameText(
|
||||||
userInfo.userName,
|
userid: userInfo.userID,
|
||||||
style: const TextStyle(
|
)
|
||||||
fontSize: 18.0
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user