feat: like live room

Closes #963

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-09 11:14:33 +08:00
parent bd490b87ca
commit 2df6c91a3d
6 changed files with 151 additions and 2 deletions

View File

@@ -24,6 +24,7 @@ import 'package:canvas_danmaku/canvas_danmaku.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class LiveRoomController extends GetxController {
@@ -256,6 +257,7 @@ class LiveRoomController extends GetxController {
@override
void onClose() {
cancelLikeTimer();
cancelLiveTimer();
savedDanmaku?.clear();
savedDanmaku = null;
@@ -330,4 +332,43 @@ class LiveRoomController extends GetxController {
})
..init();
}
final RxInt likeClickTime = 0.obs;
Timer? likeClickTimer;
void cancelLikeTimer() {
likeClickTimer?.cancel();
likeClickTimer = null;
}
void onLikeTapDown([_]) {
cancelLikeTimer();
likeClickTime.value++;
}
void onLikeTapUp([_]) {
likeClickTimer ??= Timer(
const Duration(milliseconds: 800),
onLike,
);
}
Future<void> onLike() async {
if (!Accounts.heartbeat.isLogin) {
likeClickTime.value = 0;
return;
}
var res = await LiveHttp.liveLikeReport(
clickTime: likeClickTime.value,
roomId: roomId,
uid: accountService.mid,
anchorId: roomInfoH5.value?.roomInfo?.uid,
);
if (res['status']) {
SmartDialog.showToast('点赞成功');
} else {
SmartDialog.showToast(res['msg']);
}
likeClickTime.value = 0;
}
}

View File

@@ -578,6 +578,60 @@ class _LiveRoomPageState extends State<LiveRoomPage>
style: TextStyle(color: _color),
),
),
Builder(
builder: (context) {
final theme = Theme.of(context).colorScheme;
return Material(
type: MaterialType.transparency,
child: Stack(
clipBehavior: Clip.none,
children: [
InkWell(
overlayColor: overlayColor(theme),
customBorder: const CircleBorder(),
onTapDown: _liveRoomController.onLikeTapDown,
onTapUp: _liveRoomController.onLikeTapUp,
onTapCancel: _liveRoomController.onLikeTapUp,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.thumb_up_off_alt, color: _color),
),
),
Positioned(
right: -12,
top: -12,
child: Obx(() {
final likeClickTime =
_liveRoomController.likeClickTime.value;
if (likeClickTime == 0) {
return const SizedBox.shrink();
}
return AnimatedSwitcher(
duration: const Duration(milliseconds: 160),
transitionBuilder: (child, animation) {
return ScaleTransition(
scale: animation,
child: child,
);
},
child: Text(
key: ValueKey(likeClickTime),
'x$likeClickTime',
style: TextStyle(
fontSize: 16,
color: theme.brightness.isDark
? theme.primary
: theme.inversePrimary,
),
),
);
}),
),
],
),
);
},
),
IconButton(
onPressed: () => onSendDanmaku(true),
icon: Icon(Icons.emoji_emotions_outlined, color: _color),
@@ -588,8 +642,33 @@ class _LiveRoomPageState extends State<LiveRoomPage>
),
);
WidgetStateProperty<Color?>? overlayColor(ColorScheme theme) =>
WidgetStateProperty.resolveWith((Set<WidgetState> states) {
if (states.contains(WidgetState.selected)) {
if (states.contains(WidgetState.pressed)) {
return theme.primary.withValues(alpha: 0.1);
}
if (states.contains(WidgetState.hovered)) {
return theme.primary.withValues(alpha: 0.08);
}
if (states.contains(WidgetState.focused)) {
return theme.primary.withValues(alpha: 0.1);
}
}
if (states.contains(WidgetState.pressed)) {
return theme.onSurfaceVariant.withValues(alpha: 0.1);
}
if (states.contains(WidgetState.hovered)) {
return theme.onSurfaceVariant.withValues(alpha: 0.08);
}
if (states.contains(WidgetState.focused)) {
return theme.onSurfaceVariant.withValues(alpha: 0.1);
}
return Colors.transparent;
});
void onSendDanmaku([bool fromEmote = false]) {
if (!_liveRoomController.accountService.isLogin.value) {
if (!_liveRoomController.isLogin) {
SmartDialog.showToast('账号未登录');
return;
}

View File

@@ -54,7 +54,7 @@ class BottomControl extends StatelessWidget {
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: () {
if (liveRoomCtr.accountService.isLogin.value) {
if (liveRoomCtr.isLogin) {
Get.toNamed(
'/liveDmBlockPage',
parameters: {