From 43cb79f6ab511eb013033128a4e93b4c354908a7 Mon Sep 17 00:00:00 2001 From: Linloir <3145078758@qq.com> Date: Thu, 13 Oct 2022 17:10:48 +0800 Subject: [PATCH] More Codes - Contacts page (untested) --- lib/chat/chat_page.dart | 31 ++++++- lib/home/cubit/home_cubit.dart | 21 ++++- lib/home/cubit/home_state.dart | 34 ++++++- lib/home/home_page.dart | 73 ++++++++++++++- lib/home/view/bottom_bar.dart | 6 ++ lib/home/view/contact_page/contact_page.dart | 49 ++++++++++- .../contact_page/cubit/contact_cubit.dart | 41 ++++++++- .../contact_page/cubit/contact_state.dart | 31 ++++++- .../contact_page/models/contact_model.dart | 26 ++++++ .../view/contact_page/view/contact_tile.dart | 88 ++++++++++++++++++- .../message_page/cubit/msg_list_cubit.dart | 14 ++- lib/home/view/message_page/mesage_page.dart | 44 ++++------ .../view/message_page/view/message_tile.dart | 3 +- lib/login/login_page.dart | 7 +- lib/main.dart | 7 +- lib/profile/user_profile_page.dart | 6 ++ lib/register/register_page.dart | 7 +- lib/repositories/common_models/userinfo.dart | 8 +- lib/search/cubit/search_cubit.dart | 6 ++ lib/search/cubit/search_state.dart | 6 ++ lib/search/model/search_key.dart | 6 ++ lib/search/search_page.dart | 22 +++++ lib/search/view/search_bar.dart | 17 ++++ pubspec.lock | 35 ++++++++ pubspec.yaml | 4 + 25 files changed, 541 insertions(+), 51 deletions(-) create mode 100644 lib/home/view/bottom_bar.dart create mode 100644 lib/home/view/contact_page/models/contact_model.dart create mode 100644 lib/profile/user_profile_page.dart create mode 100644 lib/search/cubit/search_cubit.dart create mode 100644 lib/search/cubit/search_state.dart create mode 100644 lib/search/model/search_key.dart create mode 100644 lib/search/search_page.dart create mode 100644 lib/search/view/search_bar.dart diff --git a/lib/chat/chat_page.dart b/lib/chat/chat_page.dart index 2015028..b356058 100644 --- a/lib/chat/chat_page.dart +++ b/lib/chat/chat_page.dart @@ -1,6 +1,35 @@ /* * @Author : Linloir * @Date : 2022-10-13 14:03:16 - * @LastEditTime : 2022-10-13 14:03:16 + * @LastEditTime : 2022-10-13 16:29:57 * @Description : */ + +import 'package:flutter/material.dart'; +import 'package:tcp_client/repositories/common_models/userinfo.dart'; + +class ChatPage extends StatelessWidget { + const ChatPage({ + required this.userInfo, + super.key + }); + + final UserInfo userInfo; + + static Route route({required UserInfo userInfo}) => MaterialPageRoute(builder: (context) => ChatPage(userInfo: userInfo,)); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text( + userInfo.userName, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18 + ), + ) + ), + ); + } +} diff --git a/lib/home/cubit/home_cubit.dart b/lib/home/cubit/home_cubit.dart index e39d03e..b2ef9e5 100644 --- a/lib/home/cubit/home_cubit.dart +++ b/lib/home/cubit/home_cubit.dart @@ -1,6 +1,25 @@ /* * @Author : Linloir * @Date : 2022-10-13 14:02:28 - * @LastEditTime : 2022-10-13 14:02:28 + * @LastEditTime : 2022-10-13 16:43:49 * @Description : */ + +import 'package:bloc/bloc.dart'; +import 'package:tcp_client/home/cubit/home_state.dart'; +import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart'; +import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart'; + +class HomeCubit extends Cubit { + HomeCubit({ + required this.localServiceRepository, + required this.tcpRepository, + }): super(const HomeState(page: HomePagePosition.message)); + + final LocalServiceRepository localServiceRepository; + final TCPRepository tcpRepository; + + void switchPage(HomePagePosition newPage) { + emit(state.copyWith(page: newPage)); + } +} diff --git a/lib/home/cubit/home_state.dart b/lib/home/cubit/home_state.dart index a9355f2..b01f524 100644 --- a/lib/home/cubit/home_state.dart +++ b/lib/home/cubit/home_state.dart @@ -1,6 +1,38 @@ /* * @Author : Linloir * @Date : 2022-10-13 14:02:24 - * @LastEditTime : 2022-10-13 14:02:24 + * @LastEditTime : 2022-10-13 16:55:05 * @Description : */ + +import 'package:equatable/equatable.dart'; + +enum HomePagePosition { + message(0), + contact(1), + profile(2); + + const HomePagePosition(int value): _value = value; + final int _value; + final List _literals = const ['Messages', 'Contacts', 'Me']; + int get value => _value; + String get literal => _literals[value]; + + //Construct the enum type by value + factory HomePagePosition.fromValue(int value) { + return HomePagePosition.values.firstWhere((element) => element._value == value, orElse: () => HomePagePosition.message); + } +} + +class HomeState extends Equatable { + final HomePagePosition page; + + const HomeState({required this.page}); + + HomeState copyWith({HomePagePosition? page}) { + return HomeState(page: page ?? this.page); + } + + @override + List get props => [page]; +} diff --git a/lib/home/home_page.dart b/lib/home/home_page.dart index b64287d..09e2297 100644 --- a/lib/home/home_page.dart +++ b/lib/home/home_page.dart @@ -1,19 +1,84 @@ /* * @Author : Linloir * @Date : 2022-10-11 11:05:08 - * @LastEditTime : 2022-10-12 11:03:13 + * @LastEditTime : 2022-10-13 16:55:48 * @Description : */ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:tcp_client/home/cubit/home_cubit.dart'; +import 'package:tcp_client/home/cubit/home_state.dart'; +import 'package:tcp_client/home/view/contact_page/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/repositories/local_service_repository/local_service_repository.dart'; +import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart'; class HomePage extends StatelessWidget { - const HomePage({super.key}); + HomePage({ + required this.localServiceRepository, + required this.tcpRepository, + super.key + }); - static Route route() => MaterialPageRoute(builder: (context) => const HomePage()); + final LocalServiceRepository localServiceRepository; + final TCPRepository tcpRepository; + + final PageController _controller = PageController(); + + static Route route({ + required LocalServiceRepository localServiceRepository, + required TCPRepository tcpRepository + }) => MaterialPageRoute(builder: (context) => HomePage( + localServiceRepository: localServiceRepository, + tcpRepository: tcpRepository, + )); @override Widget build(BuildContext context) { - return const Scaffold(); + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => MessageListCubit( + localServiceRepository: localServiceRepository, + tcpRepository: tcpRepository + ), + ), + BlocProvider( + create: (context) => ContactCubit( + localServiceRepository: localServiceRepository, + tcpRepository: tcpRepository + ), + ), + BlocProvider( + create: (context) => HomeCubit( + localServiceRepository: localServiceRepository, + tcpRepository: tcpRepository + ), + ) + ], + child: BlocListener( + listenWhen:(previous, current) => current.page != previous.page, + listener: (context, state) { + _controller.animateToPage( + state.page.value, + duration: const Duration(milliseconds: 375), + curve: Curves.easeInOutCubicEmphasized + ); + }, + child: Scaffold( + body: PageView( + controller: _controller, + children: const [ + MessagePage(), + ContactPage() + ], + ), + ), + ) + + ); } } diff --git a/lib/home/view/bottom_bar.dart b/lib/home/view/bottom_bar.dart new file mode 100644 index 0000000..2db5ba8 --- /dev/null +++ b/lib/home/view/bottom_bar.dart @@ -0,0 +1,6 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 16:37:30 + * @LastEditTime : 2022-10-13 16:37:30 + * @Description : + */ diff --git a/lib/home/view/contact_page/contact_page.dart b/lib/home/view/contact_page/contact_page.dart index bd6d142..385e983 100644 --- a/lib/home/view/contact_page/contact_page.dart +++ b/lib/home/view/contact_page/contact_page.dart @@ -1,6 +1,53 @@ /* * @Author : Linloir * @Date : 2022-10-12 23:36:07 - * @LastEditTime : 2022-10-12 23:36:08 + * @LastEditTime : 2022-10-13 16:10:57 * @Description : */ + +import 'package:azlistview/azlistview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:tcp_client/home/view/contact_page/cubit/contact_cubit.dart'; +import 'package:tcp_client/home/view/contact_page/cubit/contact_state.dart'; +import 'package:tcp_client/home/view/contact_page/models/contact_model.dart'; +import 'package:tcp_client/home/view/contact_page/view/contact_tile.dart'; + +class ContactPage extends StatelessWidget { + const ContactPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return AzListView( + data: state.indexedData, + itemCount: state.contacts.length, + itemBuilder: (context, index) { + return ContactTile( + userInfo: state.contacts[index], + ); + }, + physics: const BouncingScrollPhysics(), + susItemBuilder: (context, index) { + return Container( + height: 40, + width: MediaQuery.of(context).size.width, + padding: const EdgeInsets.only(left: 16.0), + color: Colors.grey[200], + alignment: Alignment.centerLeft, + child: Text( + ContactModel(userInfo: state.contacts[index]).getSuspensionTag(), + softWrap: false, + style: TextStyle( + fontSize: 14.0, + color: Colors.grey[700], + ), + ), + ); + }, + ); + }, + ); + } +} diff --git a/lib/home/view/contact_page/cubit/contact_cubit.dart b/lib/home/view/contact_page/cubit/contact_cubit.dart index ee96186..d6669c8 100644 --- a/lib/home/view/contact_page/cubit/contact_cubit.dart +++ b/lib/home/view/contact_page/cubit/contact_cubit.dart @@ -1,6 +1,45 @@ /* * @Author : Linloir * @Date : 2022-10-13 14:01:45 - * @LastEditTime : 2022-10-13 14:01:46 + * @LastEditTime : 2022-10-13 14:50:34 * @Description : */ + +import 'package:bloc/bloc.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:tcp_client/home/view/contact_page/cubit/contact_state.dart'; +import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart'; +import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart'; +import 'package:tcp_client/repositories/tcp_repository/models/tcp_response.dart'; +import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart'; + +class ContactCubit extends Cubit { + ContactCubit({ + required this.localServiceRepository, + required this.tcpRepository + }): super(ContactState.empty()) { + tcpRepository.responseStreamBroadcast.listen(_onResponse); + } + + LocalServiceRepository localServiceRepository; + TCPRepository tcpRepository; + + void _onResponse(TCPResponse response) { + switch(response.type) { + case TCPResponseType.fetchContact: { + response as FetchContactResponse; + emit(ContactState( + contacts: response.addedContacts, + pending: response.pendingContacts, + requesting: response.requestingContacts + )); + break; + } + default: break; + } + } + + Future updateContacts() async { + tcpRepository.pushRequest(FetchContactRequest(token: (await SharedPreferences.getInstance()).getInt('token'))); + } +} diff --git a/lib/home/view/contact_page/cubit/contact_state.dart b/lib/home/view/contact_page/cubit/contact_state.dart index 4706d09..5887c3d 100644 --- a/lib/home/view/contact_page/cubit/contact_state.dart +++ b/lib/home/view/contact_page/cubit/contact_state.dart @@ -1,6 +1,35 @@ /* * @Author : Linloir * @Date : 2022-10-13 14:01:39 - * @LastEditTime : 2022-10-13 14:01:40 + * @LastEditTime : 2022-10-13 15:51:23 * @Description : */ + +import 'package:azlistview/azlistview.dart'; +import 'package:equatable/equatable.dart'; +import 'package:tcp_client/home/view/contact_page/models/contact_model.dart'; +import 'package:tcp_client/repositories/common_models/userinfo.dart'; + +class ContactState extends Equatable { + final List contacts; + final List pending; + final List requesting; + + const ContactState({ + required this.contacts, + required this.pending, + required this.requesting + }); + + static ContactState empty() => const ContactState(contacts: [], pending: [], requesting: []); + + List get indexedData { + var indexedList = contacts.map((e) => ContactModel(userInfo: e)).toList(); + SuspensionUtil.sortListBySuspensionTag(indexedList); + SuspensionUtil.setShowSuspensionStatus(indexedList); + return indexedList; + } + + @override + List get props => contacts; +} diff --git a/lib/home/view/contact_page/models/contact_model.dart b/lib/home/view/contact_page/models/contact_model.dart new file mode 100644 index 0000000..c82930e --- /dev/null +++ b/lib/home/view/contact_page/models/contact_model.dart @@ -0,0 +1,26 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 15:34:08 + * @LastEditTime : 2022-10-13 15:41:24 + * @Description : + */ + +import 'package:azlistview/azlistview.dart'; +import 'package:lpinyin/lpinyin.dart'; +import 'package:tcp_client/repositories/common_models/userinfo.dart'; + +class ContactModel extends ISuspensionBean { + final UserInfo userInfo; + + ContactModel({required this.userInfo}); + + @override + String getSuspensionTag() { + var pinyin = PinyinHelper.getPinyinE(userInfo.userName); + var tag = pinyin.substring(0, 1); + if(!RegExp('[A-Z]').hasMatch(tag)) { + tag = '#'; + } + return tag; + } +} diff --git a/lib/home/view/contact_page/view/contact_tile.dart b/lib/home/view/contact_page/view/contact_tile.dart index 5dae9d2..44334a3 100644 --- a/lib/home/view/contact_page/view/contact_tile.dart +++ b/lib/home/view/contact_page/view/contact_tile.dart @@ -1,6 +1,92 @@ /* * @Author : Linloir * @Date : 2022-10-13 14:02:00 - * @LastEditTime : 2022-10-13 14:02:00 + * @LastEditTime : 2022-10-13 16:44:03 * @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/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'; + +class ContactTile extends StatelessWidget { + const ContactTile({ + required this.userInfo, + super.key + }); + + final UserInfo userInfo; + + @override + Widget build(BuildContext context) { + return IntrinsicHeight( + child: Stack( + fit: StackFit.expand, + children: [ + InkWell( + onTap: () { + Navigator.of(context).push(ChatPage.route(userInfo: userInfo)); + context.read().addEmptyMessageOf(user: userInfo); + context.read().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 + ), + ), + ) + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/home/view/message_page/cubit/msg_list_cubit.dart b/lib/home/view/message_page/cubit/msg_list_cubit.dart index 1b5ce5e..7601ace 100644 --- a/lib/home/view/message_page/cubit/msg_list_cubit.dart +++ b/lib/home/view/message_page/cubit/msg_list_cubit.dart @@ -1,7 +1,7 @@ /* * @Author : Linloir * @Date : 2022-10-12 23:38:31 - * @LastEditTime : 2022-10-13 11:14:54 + * @LastEditTime : 2022-10-13 16:12:53 * @Description : */ @@ -19,13 +19,21 @@ class MessageListCubit extends Cubit { required this.localServiceRepository, required this.tcpRepository }): super(MessageListState.empty()) { - tcpRepository.responseStreamBroadcast.listen(onResponse); + tcpRepository.responseStreamBroadcast.listen(_onResponse); } final LocalServiceRepository localServiceRepository; final TCPRepository tcpRepository; - Future onResponse(TCPResponse response) async { + void addEmptyMessageOf({required UserInfo user}) { + if(state.messageList.any((element) => element.userInfo.userID == user.userID)) { + return; + } + var newList = [MessageInfo(userInfo: user)]; + emit(MessageListState(messageList: newList..addAll(state.messageList))); + } + + Future _onResponse(TCPResponse response) async { switch(response.type) { case TCPResponseType.fetchMessage: { response as FetchMessageResponse; diff --git a/lib/home/view/message_page/mesage_page.dart b/lib/home/view/message_page/mesage_page.dart index 9917b9c..2aaf32d 100644 --- a/lib/home/view/message_page/mesage_page.dart +++ b/lib/home/view/message_page/mesage_page.dart @@ -1,7 +1,7 @@ /* * @Author : Linloir * @Date : 2022-10-11 11:05:18 - * @LastEditTime : 2022-10-13 13:58:43 + * @LastEditTime : 2022-10-13 16:11:24 * @Description : */ @@ -10,39 +10,29 @@ import 'package:flutter_bloc/flutter_bloc.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_state.dart'; import 'package:tcp_client/home/view/message_page/view/message_tile.dart'; -import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart'; -import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart'; class MessagePage extends StatelessWidget { const MessagePage({super.key}); @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) { - return MessageListCubit( - localServiceRepository: context.read(), - tcpRepository: context.read() + return BlocBuilder( + builder: (context, state) { + return ListView.separated( + itemBuilder: (context, index) { + return MessageTile( + userInfo: state.messageList[index].userInfo, + message: state.messageList[index].message, + ); + }, + separatorBuilder: (context, index) { + return const Divider( + height: 0.5, + ); + }, + itemCount: state.messageList.length ); - }, - child: BlocBuilder( - builder: (context, state) { - return ListView.separated( - itemBuilder: (context, index) { - return MessageTile( - userInfo: state.messageList[index].userInfo, - message: state.messageList[index].message, - ); - }, - separatorBuilder: (context, index) { - return const Divider( - height: 0.5, - ); - }, - itemCount: state.messageList.length - ); - } - ) + } ); } } diff --git a/lib/home/view/message_page/view/message_tile.dart b/lib/home/view/message_page/view/message_tile.dart index a86908b..5d4cea6 100644 --- a/lib/home/view/message_page/view/message_tile.dart +++ b/lib/home/view/message_page/view/message_tile.dart @@ -1,7 +1,7 @@ /* * @Author : Linloir * @Date : 2022-10-13 13:17:52 - * @LastEditTime : 2022-10-13 14:00:12 + * @LastEditTime : 2022-10-13 14:57:14 * @Description : */ @@ -64,6 +64,7 @@ class MessageTile extends StatelessWidget { ) ), ), + const SizedBox(width: 12,), Expanded( child: Column( children: [ diff --git a/lib/login/login_page.dart b/lib/login/login_page.dart index 15d390f..1c2fcd8 100644 --- a/lib/login/login_page.dart +++ b/lib/login/login_page.dart @@ -1,7 +1,7 @@ /* * @Author : Linloir * @Date : 2022-10-12 15:06:30 - * @LastEditTime : 2022-10-12 23:37:04 + * @LastEditTime : 2022-10-13 16:46:06 * @Description : */ @@ -54,7 +54,10 @@ class LoginPage extends StatelessWidget { const SnackBar(content: Text('Login Successed')) ); Future.delayed(const Duration(seconds: 1)).then((_) { - Navigator.of(context).pushReplacement(HomePage.route()); + Navigator.of(context).pushReplacement(HomePage.route( + localServiceRepository: localServiceRepository, + tcpRepository: tcpRepository + )); }); } }, diff --git a/lib/main.dart b/lib/main.dart index d9784b5..a915aaa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,7 @@ /* * @Author : Linloir * @Date : 2022-10-10 08:04:53 - * @LastEditTime : 2022-10-12 17:55:07 + * @LastEditTime : 2022-10-13 16:46:33 * @Description : */ import 'package:flutter/material.dart'; @@ -52,7 +52,10 @@ class SplashPage extends StatelessWidget { if(state.isDone) { Future.delayed(const Duration(seconds: 1)).then((_) async { if((await SharedPreferences.getInstance()).getInt('userid') != null) { - Navigator.of(context).pushReplacement(HomePage.route()); + Navigator.of(context).pushReplacement(HomePage.route( + localServiceRepository: state.localServiceRepository!, + tcpRepository: state.tcpRepository! + )); } else { Navigator.of(context).pushReplacement(LoginPage.route( diff --git a/lib/profile/user_profile_page.dart b/lib/profile/user_profile_page.dart new file mode 100644 index 0000000..f704aba --- /dev/null +++ b/lib/profile/user_profile_page.dart @@ -0,0 +1,6 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 17:04:44 + * @LastEditTime : 2022-10-13 17:04:44 + * @Description : + */ diff --git a/lib/register/register_page.dart b/lib/register/register_page.dart index 3673073..bb27198 100644 --- a/lib/register/register_page.dart +++ b/lib/register/register_page.dart @@ -1,7 +1,7 @@ /* * @Author : Linloir * @Date : 2022-10-12 17:36:38 - * @LastEditTime : 2022-10-12 17:50:42 + * @LastEditTime : 2022-10-13 16:45:44 * @Description : */ /* @@ -64,7 +64,10 @@ class RegisterPage extends StatelessWidget { const SnackBar(content: Text('Register Successed')) ); Future.delayed(const Duration(seconds: 1)).then((_) { - Navigator.of(context).pushReplacement(HomePage.route()); + Navigator.of(context).pushReplacement(HomePage.route( + localServiceRepository: localServiceRepository, + tcpRepository: tcpRepository + )); }); } }, diff --git a/lib/repositories/common_models/userinfo.dart b/lib/repositories/common_models/userinfo.dart index f02d775..5e081e8 100644 --- a/lib/repositories/common_models/userinfo.dart +++ b/lib/repositories/common_models/userinfo.dart @@ -1,10 +1,12 @@ /* * @Author : Linloir * @Date : 2022-10-11 14:30:10 - * @LastEditTime : 2022-10-11 15:39:13 + * @LastEditTime : 2022-10-13 15:38:18 * @Description : */ +import 'dart:convert'; + import 'package:tcp_client/repositories/common_models/json_encodable.dart'; class UserInfo extends JSONEncodable { @@ -25,7 +27,7 @@ class UserInfo extends JSONEncodable { required Map jsonObject }): _userid = jsonObject['userid'] as int, - _username = jsonObject['username'] as String, + _username = utf8.decode(base64.decode(jsonObject['username'] as String)), _avatar = jsonObject['avatar'] as String?; int get userID => _userid; @@ -35,7 +37,7 @@ class UserInfo extends JSONEncodable { @override Map get jsonObject => { 'userid': _userid, - 'username': _username, + 'username': base64.encode(utf8.encode(_username)), 'avatar': _avatar }; } diff --git a/lib/search/cubit/search_cubit.dart b/lib/search/cubit/search_cubit.dart new file mode 100644 index 0000000..694c7b1 --- /dev/null +++ b/lib/search/cubit/search_cubit.dart @@ -0,0 +1,6 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 17:09:25 + * @LastEditTime : 2022-10-13 17:09:26 + * @Description : + */ diff --git a/lib/search/cubit/search_state.dart b/lib/search/cubit/search_state.dart new file mode 100644 index 0000000..c72a573 --- /dev/null +++ b/lib/search/cubit/search_state.dart @@ -0,0 +1,6 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 17:08:56 + * @LastEditTime : 2022-10-13 17:08:57 + * @Description : + */ diff --git a/lib/search/model/search_key.dart b/lib/search/model/search_key.dart new file mode 100644 index 0000000..09b92ab --- /dev/null +++ b/lib/search/model/search_key.dart @@ -0,0 +1,6 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 17:09:46 + * @LastEditTime : 2022-10-13 17:09:46 + * @Description : + */ diff --git a/lib/search/search_page.dart b/lib/search/search_page.dart new file mode 100644 index 0000000..941fc12 --- /dev/null +++ b/lib/search/search_page.dart @@ -0,0 +1,22 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 17:04:12 + * @LastEditTime : 2022-10-13 17:08:13 + * @Description : + */ + +import 'package:flutter/material.dart'; +import 'package:tcp_client/search/view/search_bar.dart'; + +class SearchPage extends StatelessWidget { + const SearchPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const SearchBar(), + ), + ); + } +} diff --git a/lib/search/view/search_bar.dart b/lib/search/view/search_bar.dart new file mode 100644 index 0000000..8b342b4 --- /dev/null +++ b/lib/search/view/search_bar.dart @@ -0,0 +1,17 @@ +/* + * @Author : Linloir + * @Date : 2022-10-13 17:06:52 + * @LastEditTime : 2022-10-13 17:06:53 + * @Description : + */ + +import 'package:flutter/material.dart'; + +class SearchBar extends StatelessWidget { + const SearchBar({super.key}); + + @override + Widget build(BuildContext context) { + return + } +} diff --git a/pubspec.lock b/pubspec.lock index d8ed5f3..39c2bec 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -8,6 +8,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.9.0" + azlistview: + dependency: "direct main" + description: + name: azlistview + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0" bloc: dependency: "direct main" description: @@ -125,6 +132,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.7" + flutter_slidable: + dependency: "direct main" + description: + name: flutter_slidable + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -163,6 +177,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.1.0" + lpinyin: + dependency: "direct main" + description: + name: lpinyin + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.3" matcher: dependency: transitive description: @@ -284,6 +305,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.0.3" + pull_to_refresh: + dependency: "direct main" + description: + name: pull_to_refresh + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0" + scrollable_positioned_list: + dependency: transitive + description: + name: scrollable_positioned_list + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.3" shared_preferences: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 92634ae..234e27b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,6 +49,10 @@ dependencies: loading_indicator: ^3.1.0 async: ^2.9.0 stream_transform: ^2.0.1 + flutter_slidable: ^2.0.0 + pull_to_refresh: ^2.0.0 + azlistview: ^2.0.0 + lpinyin: ^2.0.3 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.