711 lines
23 KiB
Dart
711 lines
23 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:aslan/app_localizations.dart';
|
|
import 'package:aslan/chatvibe_ui/theme/chatvibe_theme.dart';
|
|
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
|
|
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
|
|
import 'package:aslan/chatvibe_data/sources/repositories/room_repository_imp.dart';
|
|
import 'package:aslan/chatvibe_data/sources/repositories/user_repository_impl.dart';
|
|
import 'package:aslan/chatvibe_domain/models/res/room_res.dart';
|
|
import 'package:aslan/chatvibe_features/index/main_route.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:aslan/chatvibe_ui/components/chatvibe_gradient_button.dart';
|
|
import 'package:aslan/chatvibe_ui/components/at_tts.dart';
|
|
import 'package:aslan/chatvibe_core/constants/at_screen.dart';
|
|
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
|
|
import 'package:aslan/chatvibe_data/sources/local/data_persistence.dart';
|
|
import 'package:aslan/chatvibe_domain/models/res/login_res.dart';
|
|
import 'package:aslan/chatvibe_domain/usecases/at_fixed_width_tabIndicator.dart';
|
|
import 'package:aslan/chatvibe_managers/rtc_manager.dart';
|
|
|
|
import '../../chatvibe_ui/components/at_compontent.dart';
|
|
import '../../chatvibe_ui/components/at_debounce_widget.dart';
|
|
import '../../chatvibe_ui/components/at_page_list.dart';
|
|
import '../../chatvibe_ui/components/text/at_text.dart';
|
|
|
|
///搜索房间
|
|
class SearchPage extends ATPageList {
|
|
@override
|
|
_SearchPageState createState() => _SearchPageState();
|
|
}
|
|
|
|
class _SearchPageState extends ATPageListState<dynamic, SearchPage>
|
|
with SingleTickerProviderStateMixin {
|
|
String search = '';
|
|
List<String> historys = [];
|
|
|
|
late TabController _tabController;
|
|
|
|
bool enablePullUp = false;
|
|
bool enablePullDown = false;
|
|
|
|
late TextEditingController _textEditingController;
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadHistory();
|
|
_tabController = TabController(vsync: this, length: 2);
|
|
_textEditingController = TextEditingController();
|
|
_textEditingController.addListener(() {
|
|
if (_textEditingController.text.isEmpty) {
|
|
search = "";
|
|
_loadHistory();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Stack(
|
|
children: [
|
|
Scaffold(
|
|
backgroundColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageScaffoldBackgroundColor(),
|
|
body: Column(
|
|
children: [
|
|
Container(
|
|
height: kToolbarHeight + ScreenUtil().statusBarHeight,
|
|
padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight),
|
|
alignment: AlignmentDirectional.centerStart,
|
|
child: Row(
|
|
children: <Widget>[
|
|
SizedBox(width: width(10)),
|
|
ATDebounceWidget(
|
|
child: Icon(
|
|
Icons.chevron_left,
|
|
color:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageBackIconColor(),
|
|
size: 25.w,
|
|
),
|
|
onTap: () {
|
|
ATNavigatorUtils.goBack(context);
|
|
},
|
|
),
|
|
Expanded(
|
|
child: searchWidget(
|
|
padding: EdgeInsets.symmetric(horizontal: 2.w),
|
|
hint:
|
|
ATAppLocalizations.of(context)!.pleaseEnterContent,
|
|
controller: _textEditingController,
|
|
borderColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageInputBorderColor(),
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageInputTextColor(),
|
|
),
|
|
),
|
|
chatvibeGradientButton(
|
|
text: ATAppLocalizations.of(context)!.search,
|
|
radius: 25,
|
|
textSize: 14.sp,
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageButtonTextColor(),
|
|
gradient: LinearGradient(
|
|
colors:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageButtonGradient(),
|
|
begin: Alignment.centerLeft,
|
|
end: Alignment.centerRight,
|
|
),
|
|
onPress: () {
|
|
_reqSearch();
|
|
},
|
|
),
|
|
SizedBox(width: width(10)),
|
|
],
|
|
),
|
|
),
|
|
search.isEmpty || search == "" ? _history() : _result(),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
_history() {
|
|
if (historys.isEmpty) {
|
|
return mainEmpty(msg: ATAppLocalizations.of(context)!.noData);
|
|
} else {
|
|
return Expanded(
|
|
child: Column(
|
|
children: <Widget>[
|
|
SizedBox(height: 20.w),
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: <Widget>[
|
|
SizedBox(width: width(15)),
|
|
text(
|
|
ATAppLocalizations.of(context)!.history,
|
|
fontSize: 16.sp,
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryTitleTextColor(),
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
Expanded(child: SizedBox(width: width(1))),
|
|
GestureDetector(
|
|
behavior: HitTestBehavior.opaque,
|
|
onTap: () {
|
|
setState(() {
|
|
historys.clear();
|
|
_saveHistory("");
|
|
});
|
|
},
|
|
child: Row(
|
|
children: <Widget>[
|
|
Image.asset(
|
|
'atu_images/general/at_icon_delete.png',
|
|
width: 17.w,
|
|
),
|
|
//SizedBox(width: width(5),),
|
|
//Text("清空", style: TextStyle(fontSize: 13.sp, color: Color(0xffaaaaaa)),),
|
|
SizedBox(width: width(15)),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: height(10)),
|
|
Expanded(
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
SizedBox(width: 12.w),
|
|
Expanded(
|
|
child: Wrap(
|
|
runSpacing: 10,
|
|
spacing: 10,
|
|
direction: Axis.horizontal,
|
|
children:
|
|
historys
|
|
.asMap()
|
|
.keys
|
|
.map((e) => _historyItem(historys[e]))
|
|
.toList(),
|
|
),
|
|
),
|
|
SizedBox(width: 12.w),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
_saveHistory(String msg) async {
|
|
historys.removeWhere((history) => history == msg || history.isEmpty);
|
|
|
|
if (!historys.any((history) => history.startsWith(msg))) {
|
|
if (msg.isNotEmpty) {
|
|
historys.insert(0, msg);
|
|
}
|
|
}
|
|
|
|
setState(() {});
|
|
DataPersistence.setSearchHistroy(
|
|
AccountStorage().getCurrentUser()?.userProfile?.account ?? "",
|
|
jsonEncode(historys),
|
|
);
|
|
}
|
|
|
|
_loadHistory() async {
|
|
String json = DataPersistence.getSearchHistroy(
|
|
AccountStorage().getCurrentUser()?.userProfile?.account ?? "",
|
|
);
|
|
historys = List<String>.from(jsonDecode(json));
|
|
setState(() {});
|
|
}
|
|
|
|
Widget _historyItem(String history) {
|
|
return GestureDetector(
|
|
onTap: () {
|
|
_textEditingController.text = history;
|
|
_reqSearch();
|
|
},
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 6.w),
|
|
decoration: BoxDecoration(
|
|
color:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryItemBackgroundColor(),
|
|
borderRadius: BorderRadius.circular(52.w),
|
|
),
|
|
child: Text(
|
|
history,
|
|
style: TextStyle(
|
|
fontSize: sp(13),
|
|
color:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryItemTextColor(),
|
|
fontWeight: FontWeight.w400,
|
|
decoration: TextDecoration.none,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
_result() {
|
|
return Expanded(
|
|
child: Column(
|
|
children: [
|
|
Theme(
|
|
data: ThemeData(
|
|
brightness: Brightness.light,
|
|
splashColor: Colors.transparent,
|
|
highlightColor: Colors.transparent,
|
|
),
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(vertical: 1.w),
|
|
decoration: BoxDecoration(
|
|
// color: Colors.white,
|
|
//border: Border(bottom: BorderSide(color: Color(0xffEEEEEE),width: 0.5.w))
|
|
),
|
|
child: TabBar(
|
|
tabs:
|
|
[
|
|
ATAppLocalizations.of(context)!.rooms,
|
|
ATAppLocalizations.of(context)!.users,
|
|
].map((e) => Tab(text: e)).toList(),
|
|
indicator: ATFixedWidthTabIndicator(
|
|
width: 15.w,
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageTabIndicatorGradientStartColor(),
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageTabIndicatorGradientEndColor(),
|
|
],
|
|
),
|
|
),
|
|
indicatorSize: TabBarIndicatorSize.label,
|
|
// 控制指示器宽度
|
|
labelPadding: EdgeInsetsDirectional.only(start: 15, end: 15),
|
|
isScrollable: false,
|
|
controller: _tabController,
|
|
labelColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageTabSelectedLabelColor(),
|
|
dividerColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageTabDividerColor(),
|
|
unselectedLabelColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageTabUnselectedLabelColor(),
|
|
unselectedLabelStyle:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageTabUnselectedLabelStyle(),
|
|
labelStyle:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageTabSelectedLabelStyle(),
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
height: 8.w,
|
|
color:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageDividerContainerBackgroundColor(),
|
|
),
|
|
Expanded(
|
|
child: TabBarView(
|
|
controller: _tabController,
|
|
children: [
|
|
SearchRoomList(search, (String text) {
|
|
_saveHistory(text);
|
|
}),
|
|
SearchUserList(search, (String text) {
|
|
_saveHistory(text);
|
|
}),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _reqSearch() {
|
|
search = _textEditingController.text;
|
|
setState(() {});
|
|
if (search.trim().isNotEmpty) {
|
|
_saveHistory(search);
|
|
} else {
|
|
items.clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
class SearchRoomList extends StatefulWidget {
|
|
final String text;
|
|
Function(String text) saveHistroy;
|
|
|
|
SearchRoomList(this.text, this.saveHistroy);
|
|
|
|
@override
|
|
_SearchRoomListState createState() => _SearchRoomListState(saveHistroy);
|
|
}
|
|
|
|
class _SearchRoomListState extends State<SearchRoomList> {
|
|
List<ChatVibeRoomRes>? rooms;
|
|
Function(String text) saveHistroy;
|
|
|
|
_SearchRoomListState(this.saveHistroy);
|
|
|
|
@override
|
|
void initState() {
|
|
loadPage();
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(SearchRoomList oldWidget) {
|
|
var oldText = oldWidget.text;
|
|
var text = widget.text;
|
|
if (oldText != text) {
|
|
rooms?.clear();
|
|
loadPage();
|
|
}
|
|
super.didUpdateWidget(oldWidget);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (rooms == null) {
|
|
return Center(child: CupertinoActivityIndicator());
|
|
} else if (rooms!.length == 0) {
|
|
return empty();
|
|
}
|
|
|
|
return ListView.separated(
|
|
itemBuilder: (context, i) => buildItem(rooms![i]),
|
|
itemCount: rooms!.length,
|
|
padding: EdgeInsets.symmetric(vertical: 10.w),
|
|
separatorBuilder:
|
|
(context, i) => Divider(
|
|
height: height(1),
|
|
color: ChatVibeTheme.dividerColor,
|
|
indent: width(28), //25+50+10
|
|
endIndent: width(15),
|
|
),
|
|
);
|
|
}
|
|
|
|
///构建列表项
|
|
Widget buildItem(ChatVibeRoomRes e) {
|
|
//return roomItem(room: e,context: context);
|
|
return GestureDetector(
|
|
behavior: HitTestBehavior.opaque,
|
|
onTap: () async {
|
|
if (context != null) {
|
|
Provider.of<RtcProvider>(
|
|
context,
|
|
listen: false,
|
|
).joinRoom(context, e.id ?? "");
|
|
}
|
|
},
|
|
child: Stack(
|
|
children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Color(0xffF6BE00), width: 0.5),
|
|
borderRadius: BorderRadius.circular(10.w),
|
|
),
|
|
// color: Colors.white,
|
|
padding: EdgeInsets.symmetric(vertical: 12.w, horizontal: 10.w),
|
|
margin: EdgeInsets.symmetric(horizontal: 8.w),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
netImage(
|
|
url: e.roomCover ?? "",
|
|
width: 50.w,
|
|
borderRadius: BorderRadius.circular(10.w),
|
|
),
|
|
Expanded(
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 10.w),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// richText(
|
|
// txt: e.roomName ?? "",
|
|
// key: widget.text,
|
|
// highlight: ChatVibeTheme.primaryColor,
|
|
// defaultColor: Colors.black,
|
|
// ),
|
|
text(
|
|
e.roomName ?? "",
|
|
fontSize: 15.sp,
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryTitleTextColor(),
|
|
),
|
|
text(
|
|
"ID:${e.userProfile?.getID()}",
|
|
fontSize: 12.sp,
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryItemTextColor(),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
PositionedDirectional(
|
|
end: 18.w,
|
|
top: 15.w,
|
|
child: Row(
|
|
children: [
|
|
(e.extValues?.roomSetting?.password?.isEmpty ?? false)
|
|
? Image.asset(
|
|
"atu_images/index/at_icon_room_flot_ani.gif",
|
|
width: 14.w,
|
|
height: 14.w,
|
|
)
|
|
: Container(),
|
|
(e.extValues?.roomSetting?.password?.isEmpty ?? false)
|
|
? text(
|
|
e.extValues?.memberQuantity ?? "0",
|
|
textColor: Colors.black38,
|
|
fontSize: 11.sp,
|
|
)
|
|
: Container(),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
loadPage() async {
|
|
widget.saveHistroy(widget.text);
|
|
try {
|
|
rooms = await ChatRoomRepository().searchRoom(widget.text);
|
|
} catch (e) {
|
|
} finally {
|
|
setState(() {});
|
|
}
|
|
}
|
|
|
|
empty() {
|
|
return mainEmpty(msg: ATAppLocalizations.of(context)!.noData);
|
|
}
|
|
}
|
|
|
|
class SearchUserList extends ATPageList {
|
|
final String text;
|
|
Function(String text) saveHistroy;
|
|
|
|
SearchUserList(this.text, this.saveHistroy);
|
|
|
|
@override
|
|
_SearchUserListState createState() => _SearchUserListState(saveHistroy);
|
|
}
|
|
|
|
class _SearchUserListState
|
|
extends ATPageListState<ChatVibeUserProfile, SearchUserList> {
|
|
Function(String text) saveHistroy;
|
|
|
|
_SearchUserListState(this.saveHistroy);
|
|
|
|
@override
|
|
void initState() {
|
|
// TODO: implement initState
|
|
backgroundColor = Colors.transparent;
|
|
loadData(1);
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(ATPageList oldWidget) {
|
|
// TODO: implement didUpdateWidget
|
|
var oldText = (oldWidget as SearchUserList).text;
|
|
var text = (widget as SearchUserList).text;
|
|
if (oldText != text) {
|
|
items.clear();
|
|
loadData(1);
|
|
}
|
|
super.didUpdateWidget(oldWidget);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return buildList(context);
|
|
}
|
|
|
|
///构建列表项
|
|
Widget buildItem(ChatVibeUserProfile data) {
|
|
return GestureDetector(
|
|
behavior: HitTestBehavior.opaque,
|
|
onTap: () {
|
|
ATNavigatorUtils.push(
|
|
context,
|
|
"${MainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == data.id}&tageId=${data.id}",
|
|
);
|
|
},
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(vertical: 5.w),
|
|
margin: EdgeInsets.symmetric(horizontal: 10.w),
|
|
child: Row(
|
|
children: [
|
|
head(url: data.userAvatar ?? "", width: 55.w),
|
|
SizedBox(width: 2.w),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: <Widget>[
|
|
xb(
|
|
data.userSex,
|
|
color:
|
|
data.userSex == 1
|
|
? Colors.blue
|
|
: Colors.purpleAccent,
|
|
),
|
|
SizedBox(width: 5.w),
|
|
// richText(
|
|
// txt: data.userNickname ?? "",
|
|
// key: (widget as SearchUserList).text,
|
|
// highlight: ChatVibeTheme.primaryColor,
|
|
// defaultColor: Colors.black,
|
|
// ),
|
|
Expanded(
|
|
child: chatvibeNickNameText(
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryTitleTextColor(),
|
|
data.userNickname ?? "",
|
|
fontSize: 15.sp,
|
|
type: data.getVIP()?.name ?? "",
|
|
needScroll:
|
|
(data.userNickname?.characters.length ?? 0) > 18,
|
|
),
|
|
),
|
|
SizedBox(width: 5.w),
|
|
// dj(data.level.toString()),
|
|
],
|
|
),
|
|
GestureDetector(
|
|
child: Row(
|
|
children: [
|
|
getIdIcon(
|
|
data.wealthLevel ?? 0,
|
|
width: 32.w,
|
|
height: 32.w,
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w600,
|
|
textColor: Color(0xFF333333),
|
|
),
|
|
Container(
|
|
child: chatvibeNickNameText(
|
|
maxWidth: 135.w,
|
|
data.getID() ?? "",
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryTitleTextColor(),
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w600,
|
|
type: data.getVIP()?.name ?? "",
|
|
needScroll:
|
|
(data.getID().characters.length ?? 0) > 13,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
onTap: () {
|
|
Clipboard.setData(ClipboardData(text: data.getID()));
|
|
ATTts.show(
|
|
ATAppLocalizations.of(context)!.copiedToClipboard,
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
loadPage({
|
|
required int page,
|
|
required Function(List<ChatVibeUserProfile>) onSuccess,
|
|
Function? onErr,
|
|
}) async {
|
|
saveHistroy((widget as SearchUserList).text);
|
|
items.clear();
|
|
AccountRepository()
|
|
.searchUser((widget as SearchUserList).text)
|
|
.then((data) {
|
|
List<ChatVibeUserProfile> users = [];
|
|
users.add(data);
|
|
onSuccess(users);
|
|
})
|
|
.catchError((e) {
|
|
if (onErr != null) {
|
|
onErr();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
empty() {
|
|
return mainEmpty(
|
|
msg: ATAppLocalizations.of(context)!.noData,
|
|
textColor:
|
|
ATGlobalConfig.businessLogicStrategy
|
|
.getSearchPageHistoryTitleTextColor(),
|
|
);
|
|
}
|
|
|
|
@override
|
|
builderDivider() {
|
|
return Divider(
|
|
height: height(1),
|
|
color: ChatVibeTheme.dividerColor,
|
|
indent: width(85),
|
|
endIndent: width(15),
|
|
);
|
|
}
|
|
}
|