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 with SingleTickerProviderStateMixin { String search = ''; List 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: [ 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: [ SizedBox(height: 20.w), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ 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: [ 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.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 { List? 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( 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 { 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: [ 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) onSuccess, Function? onErr, }) async { saveHistroy((widget as SearchUserList).text); items.clear(); AccountRepository() .searchUser((widget as SearchUserList).text) .then((data) { List 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), ); } }