feat: live following

This commit is contained in:
guozhigq
2024-10-26 23:46:19 +08:00
parent 4f6ac4aff4
commit 638e22a60d
8 changed files with 327 additions and 106 deletions

View File

@ -14,6 +14,7 @@ class LiveController extends GetxController {
RxList<LiveItemModel> liveList = <LiveItemModel>[].obs;
RxList<LiveFollowingItemModel> liveFollowingList =
<LiveFollowingItemModel>[].obs;
RxInt liveFollowingCount = 0.obs;
bool flag = false;
OverlayEntry? popupDialog;
Box setting = GStrorage.setting;
@ -27,9 +28,6 @@ class LiveController extends GetxController {
// 获取推荐
Future queryLiveList(type) async {
// if (type == 'init') {
// _currentPage = 1;
// }
var res = await LiveHttp.liveList(
pn: _currentPage,
);
@ -68,13 +66,14 @@ class LiveController extends GetxController {
//
Future fetchLiveFollowing() async {
var res = await LiveHttp.liveFollowing(pn: 1, ps: 20);
var res = await LiveHttp.liveFollowing(pn: 1, ps: 10);
if (res['status']) {
liveFollowingList.value =
(res['data'].list as List<LiveFollowingItemModel>)
.where((LiveFollowingItemModel item) =>
item.liveStatus == 1 && item.recordLiveTime == 0) // 根据条件过滤
.toList();
liveFollowingCount.value = res['data'].liveCount;
}
return res;
}

View File

@ -162,34 +162,61 @@ class _LivePageState extends State<LivePage>
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(
() => Text.rich(
TextSpan(
children: [
const TextSpan(
text: ' 我的关注 ',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Obx(
() => Text.rich(
TextSpan(
text: ' ${_liveController.liveFollowingList.length}',
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.primary,
),
children: [
const TextSpan(
text: ' 我的关注 ',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
TextSpan(
text: ' ${_liveController.liveFollowingCount}',
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.primary,
),
),
TextSpan(
text: '人正在直播',
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.outline,
),
),
],
),
TextSpan(
text: '人正在直播',
style: TextStyle(
fontSize: 12,
),
),
InkWell(
onTap: () {
Get.toNamed('/liveFollowing');
},
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
child: Row(
children: [
Text(
'查看更多',
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.outline,
),
),
Icon(
Icons.chevron_right,
color: Theme.of(context).colorScheme.outline,
),
),
],
],
),
),
),
],
),
FutureBuilder(
future: _futureBuilderFuture2,
@ -201,8 +228,7 @@ class _LivePageState extends State<LivePage>
Map? data = snapshot.data;
if (data?['status']) {
RxList list = _liveController.liveFollowingList;
// ignore: invalid_use_of_protected_member
return Obx(() => LiveFollowingListView(list: list.value));
return LiveFollowingListView(list: list);
} else {
return SizedBox(
height: 80,
@ -230,69 +256,71 @@ class _LivePageState extends State<LivePage>
}
class LiveFollowingListView extends StatelessWidget {
final List list;
final RxList list;
const LiveFollowingListView({super.key, required this.list});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
final LiveFollowingItemModel item = list[index];
return Padding(
padding: const EdgeInsets.fromLTRB(3, 12, 3, 0),
child: Column(
children: [
InkWell(
onTap: () {
Get.toNamed(
'/liveRoom?roomid=${item.roomId}',
arguments: {
'liveItem': item,
'heroTag': item.roomId.toString()
},
);
},
child: Container(
width: 54,
height: 54,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(27),
border: Border.all(
color: Theme.of(context).colorScheme.primary,
width: 1.5,
return Obx(
() => SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
final LiveFollowingItemModel item = list[index];
return Padding(
padding: const EdgeInsets.fromLTRB(3, 12, 3, 0),
child: Column(
children: [
InkWell(
onTap: () {
Get.toNamed(
'/liveRoom?roomid=${item.roomId}',
arguments: {
'liveItem': item,
'heroTag': item.roomId.toString()
},
);
},
child: Container(
width: 54,
height: 54,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(27),
border: Border.all(
color: Theme.of(context).colorScheme.primary,
width: 1.5,
),
),
child: NetworkImgLayer(
width: 50,
height: 50,
type: 'avatar',
src: list[index].face,
),
),
child: NetworkImgLayer(
width: 50,
height: 50,
type: 'avatar',
src: list[index].face,
),
const SizedBox(height: 6),
SizedBox(
width: 62,
child: Text(
list[index].uname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 12,
),
),
),
),
const SizedBox(height: 6),
SizedBox(
width: 62,
child: Text(
list[index].uname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 12,
),
),
),
],
),
);
},
itemCount: list.length,
],
),
);
},
itemCount: list.length,
),
),
);
}

View File

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/badge.dart';
import 'package:pilipala/models/live/follow.dart';
import 'package:pilipala/models/live/item.dart';
import 'package:pilipala/utils/image_save.dart';
import 'package:pilipala/utils/utils.dart';
@ -9,7 +11,7 @@ import 'package:pilipala/common/widgets/network_img_layer.dart';
// 视频卡片 - 垂直布局
class LiveCardV extends StatelessWidget {
final LiveItemModel liveItem;
final dynamic liveItem;
final int crossAxisCount;
const LiveCardV({
@ -64,6 +66,9 @@ class LiveCardV extends StatelessWidget {
),
),
),
if (liveItem is LiveFollowingItemModel &&
liveItem.liveStatus == 1)
const PBadge(top: 8, right: 8, text: '直播中'),
],
);
}),
@ -148,7 +153,7 @@ class LiveContent extends StatelessWidget {
}
class VideoStat extends StatelessWidget {
final LiveItemModel? liveItem;
final dynamic liveItem;
const VideoStat({
Key? key,
@ -178,25 +183,20 @@ class VideoStat extends StatelessWidget {
liveItem!.areaName!,
style: const TextStyle(fontSize: 11, color: Colors.white),
),
Text(
liveItem!.watchedShow!['text_small'],
style: const TextStyle(fontSize: 11, color: Colors.white),
),
if (liveItem is LiveItemModel) ...[
Text(
liveItem!.watchedShow?['text_small'],
style: const TextStyle(fontSize: 11, color: Colors.white),
),
],
if (liveItem is LiveFollowingItemModel) ...[
Text(
'${liveItem.textSmall}',
style: const TextStyle(fontSize: 11, color: Colors.white),
),
]
],
),
// child: RichText(
// maxLines: 1,
// textAlign: TextAlign.justify,
// softWrap: false,
// text: TextSpan(
// style: const TextStyle(fontSize: 11, color: Colors.white),
// children: [
// TextSpan(text: liveItem!.areaName!),
// TextSpan(text: liveItem!.watchedShow!['text_small']),
// ],
// ),
// ),
);
}
}