224 lines
6.9 KiB
Dart
224 lines
6.9 KiB
Dart
import 'dart:async';
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:yumi/shared/tools/sc_room_utils.dart';
|
||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
|
||
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
|
||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||
import 'package:provider/provider.dart';
|
||
import 'package:yumi/shared/data_sources/sources/remote/net/network_client.dart';
|
||
import 'package:yumi/shared/business_logic/models/res/join_room_res.dart';
|
||
import 'package:yumi/services/audio/rtc_manager.dart';
|
||
import 'package:yumi/app/constants/sc_screen.dart';
|
||
import 'package:yumi/ui_kit/theme/socialchat_theme.dart';
|
||
|
||
// 默认位置
|
||
Offset kDefaultFloatOffset = Offset(
|
||
ScreenUtil().screenWidth - width(90),
|
||
ScreenUtil().screenHeight - height(120),
|
||
);
|
||
|
||
class SCFloatIchart {
|
||
/// 单例模式
|
||
static final SCFloatIchart _SCFloatIchart = SCFloatIchart._internal(); //1
|
||
factory SCFloatIchart() {
|
||
return _SCFloatIchart;
|
||
}
|
||
|
||
SCFloatIchart._internal();
|
||
|
||
bool _inserted = false;
|
||
OverlayEntry? overlayEntry;
|
||
BuildContext? context;
|
||
Offset offset = kDefaultFloatOffset;
|
||
|
||
show() {
|
||
if (overlayEntry != null) {
|
||
remove(); // 先移除已有的
|
||
}
|
||
var overlayState = Overlay.of(context!);
|
||
overlayEntry = OverlayEntry(
|
||
builder: (context) {
|
||
if (inLoginPage) {
|
||
remove();
|
||
return Container();
|
||
} else {
|
||
return buildToastLayout();
|
||
}
|
||
},
|
||
);
|
||
overlayState.insert(overlayEntry!);
|
||
_inserted = true; // 标记已插入
|
||
}
|
||
|
||
bool isShow() {
|
||
return _inserted;
|
||
}
|
||
|
||
remove() {
|
||
if (overlayEntry != null && overlayEntry!.mounted) {
|
||
if (_inserted) {
|
||
overlayEntry?.remove();
|
||
_inserted = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
LayoutBuilder buildToastLayout() {
|
||
Timer? timer;
|
||
return LayoutBuilder(
|
||
builder: (context, constraints) {
|
||
return Stack(
|
||
children: <Widget>[
|
||
Positioned(
|
||
left: offset.dx,
|
||
top: offset.dy,
|
||
child: GestureDetector(
|
||
//更新child的位置
|
||
onPanUpdate: (details) {
|
||
var localPosition = details.delta;
|
||
var dx = (offset.dx + localPosition.dx).clamp(
|
||
0.0,
|
||
ScreenUtil().screenWidth - width(90),
|
||
);
|
||
var dy = (offset.dy + localPosition.dy).clamp(
|
||
0.0,
|
||
ScreenUtil().screenHeight - height(55) - kToolbarHeight,
|
||
);
|
||
offset = Offset(dx, dy);
|
||
overlayEntry!.markNeedsBuild();
|
||
},
|
||
//拖动结束,处理child贴边悬浮
|
||
onPanEnd: (details) {
|
||
var oldPosition = offset.dx;
|
||
var targets =
|
||
offset.dx + width(80) > (ScreenUtil().screenWidth / 2)
|
||
? ScreenUtil().screenWidth - width(90)
|
||
: 0;
|
||
timer = Timer.periodic(Duration(milliseconds: 1), (t) {
|
||
if (targets > 0) {
|
||
oldPosition++;
|
||
} else {
|
||
oldPosition--;
|
||
}
|
||
offset = Offset(oldPosition.toDouble(), offset.dy);
|
||
overlayEntry!.markNeedsBuild();
|
||
if (oldPosition < 0 ||
|
||
oldPosition > ScreenUtil().screenWidth - width(90)) {
|
||
timer?.cancel();
|
||
}
|
||
});
|
||
},
|
||
child: Container(
|
||
child: float(),
|
||
margin: EdgeInsets.only(bottom: height(kToolbarHeight)),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
Widget float() {
|
||
JoinRoomRes? room =
|
||
Provider.of<RealTimeCommunicationManager>(
|
||
context!,
|
||
listen: false,
|
||
).currenRoom;
|
||
// User user = Provider.of<RealTimeCommunicationManager>(context, listen: false).maiMap[0];
|
||
SocialChatLoginRes? user = AccountStorage().getCurrentUser();
|
||
return FloatRoomWindow(room: room, user: user, remove: remove);
|
||
}
|
||
|
||
void init(BuildContext context) {
|
||
this.context = context;
|
||
}
|
||
}
|
||
|
||
class FloatRoomWindow extends StatefulWidget {
|
||
final JoinRoomRes? room;
|
||
final SocialChatLoginRes? user;
|
||
final Function remove;
|
||
|
||
const FloatRoomWindow({Key? key, this.room, this.user, required this.remove})
|
||
: super(key: key);
|
||
|
||
@override
|
||
_FloatRoomWindowState createState() => _FloatRoomWindowState();
|
||
}
|
||
|
||
class _FloatRoomWindowState extends State<FloatRoomWindow> {
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return SCDebounceWidget(
|
||
onTap: () {
|
||
SCRoomUtils.openCurrentRoom(context);
|
||
},
|
||
child: Container(
|
||
height: 55.w,
|
||
width: 90.w,
|
||
decoration: BoxDecoration(
|
||
borderRadius: BorderRadius.circular(8.w),
|
||
color: SocialChatTheme.primaryLight,
|
||
),
|
||
child: Row(
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
children: <Widget>[
|
||
SizedBox(width: 8.w),
|
||
Stack(
|
||
alignment: Alignment.center,
|
||
children: [
|
||
netImage(
|
||
url: widget.room?.roomProfile?.roomProfile?.roomCover ?? "",
|
||
width: 40.w,
|
||
height: 40.w,
|
||
borderRadius: BorderRadius.circular(8.w),
|
||
),
|
||
Image.asset(
|
||
"sc_images/general/sc_icon_online_user.png",
|
||
width: 15.w,
|
||
height: 15.w,
|
||
),
|
||
],
|
||
),
|
||
SizedBox(width: width(5)),
|
||
SCDebounceWidget(
|
||
onTap: () {
|
||
Provider.of<RealTimeCommunicationManager>(
|
||
context,
|
||
listen: false,
|
||
).exitCurrentVoiceRoomSession(false);
|
||
Timer(Duration(milliseconds: 550), () {
|
||
widget.remove.call();
|
||
});
|
||
},
|
||
child: Padding(
|
||
padding: EdgeInsets.all(5.w),
|
||
child: Image.asset(
|
||
"sc_images/index/sc_icon_room_flot_close.png",
|
||
width: 20.w,
|
||
height: 20.w,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|