2026-07-01 18:25:58 +08:00

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),
);
}
}