150 lines
4.7 KiB
Dart
150 lines
4.7 KiB
Dart
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:yumi/app_localizations.dart';
|
||
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
|
||
import 'package:provider/provider.dart';
|
||
import 'package:yumi/app/constants/sc_screen.dart';
|
||
import 'package:yumi/services/audio/rtc_manager.dart';
|
||
import 'package:yumi/ui_kit/widgets/room/room_msg_item.dart';
|
||
import 'package:yumi/services/audio/rtm_manager.dart';
|
||
|
||
class AllChatPage extends StatefulWidget {
|
||
@override
|
||
_AllChatPageState createState() => _AllChatPageState();
|
||
}
|
||
|
||
class _AllChatPageState extends State<AllChatPage> {
|
||
ScrollController _controller = ScrollController();
|
||
bool showGoBottom = true;
|
||
bool _isDisposed = false;
|
||
List<Msg> _msgList = [];
|
||
late RtmProvider provider;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_controller.addListener(_scrollListener);
|
||
provider = Provider.of<RtmProvider>(context, listen: false);
|
||
var msgList = provider.roomAllMsgList;
|
||
provider.msgAllListener = _onNewMsg;
|
||
_msgList.addAll(msgList ??= []);
|
||
// 使用安全的方式初始化滚动位置
|
||
_initScrollPosition();
|
||
}
|
||
|
||
void _scrollListener() {
|
||
final position = _controller.position;
|
||
|
||
// 容差范围(5像素)避免精度问题
|
||
const tolerance = 10.0;
|
||
|
||
// 判断是否在第一个项目(颠倒列表的底部)
|
||
final isAtBottom = position.pixels < position.minScrollExtent + tolerance;
|
||
|
||
// 判断是否在最后一个项目(颠倒列表的顶部)
|
||
// final isAtTop = position.pixels >= position.maxScrollExtent - tolerance;
|
||
if (isAtBottom != showGoBottom) {
|
||
showGoBottom = isAtBottom;
|
||
if (!_isDisposed) {
|
||
setState(() {});
|
||
}
|
||
}
|
||
}
|
||
|
||
// 安全初始化滚动位置
|
||
void _initScrollPosition() {
|
||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||
if (_isDisposed) return;
|
||
_controller.jumpTo(0.0);
|
||
});
|
||
}
|
||
|
||
_onNewMsg(Msg msg) {
|
||
if (_isDisposed) return; // 如果组件已销毁,直接返回
|
||
if (msg.groupId == "-1000") {
|
||
///清屏
|
||
_msgList.clear();
|
||
setState(() {});
|
||
return;
|
||
}
|
||
if (!_msgList.contains(msg)) {
|
||
setState(() {
|
||
_msgList.insert(0, msg);
|
||
});
|
||
_controller.jumpTo(0.0);
|
||
}
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_isDisposed = true;
|
||
provider.msgAllListener = null;
|
||
_controller.removeListener(_scrollListener);
|
||
_controller.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
backgroundColor: Colors.transparent,
|
||
resizeToAvoidBottomInset: false,
|
||
body: Stack(
|
||
alignment: Alignment.bottomLeft,
|
||
children: [
|
||
ListView.builder(
|
||
reverse: true,
|
||
controller: _controller,
|
||
shrinkWrap: true,
|
||
itemBuilder: (BuildContext context, int index) {
|
||
return MsgItem(
|
||
msg: _msgList[index],
|
||
onClick: (SocialChatUserProfile? user) {
|
||
Provider.of<RtcProvider>(context, listen: false).clickSite(
|
||
Provider.of<RtcProvider>(
|
||
context,
|
||
listen: false,
|
||
).userOnMaiInIndex(user?.id ?? ""),
|
||
clickUser: user,
|
||
);
|
||
},
|
||
);
|
||
},
|
||
itemCount: _msgList.length,
|
||
),
|
||
Visibility(
|
||
visible: !showGoBottom,
|
||
child: GestureDetector(
|
||
onTap: () {
|
||
if (_controller.hasClients) {
|
||
_controller.jumpTo(0.0);
|
||
}
|
||
},
|
||
child: Container(
|
||
margin: EdgeInsets.symmetric(horizontal: width(15)),
|
||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.w),
|
||
decoration: BoxDecoration(
|
||
borderRadius: BorderRadius.circular(52),
|
||
color: Colors.white,
|
||
),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: <Widget>[
|
||
Text(
|
||
SCAppLocalizations.of(context)!.scrollToTheBottom,
|
||
style: TextStyle(fontSize: 10.sp),
|
||
),
|
||
SizedBox(width: 4.w),
|
||
Icon(Icons.chevron_right, size: 10.w),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|