mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-13 12:50:10 +08:00
feat: live area
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -42,10 +42,13 @@ class _SelfSizedHorizontalListState extends State<SelfSizedHorizontalList> {
|
|||||||
}
|
}
|
||||||
if (widget.itemCount == 0) return const SizedBox.shrink();
|
if (widget.itemCount == 0) return const SizedBox.shrink();
|
||||||
if (isInit) {
|
if (isInit) {
|
||||||
return Container(
|
return Align(
|
||||||
key: infoKey,
|
alignment: Alignment.centerLeft,
|
||||||
padding: widget.padding,
|
child: Padding(
|
||||||
child: widget.childBuilder(0),
|
key: infoKey,
|
||||||
|
padding: widget.padding ?? EdgeInsets.zero,
|
||||||
|
child: widget.childBuilder(0),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -802,4 +802,7 @@ class Api {
|
|||||||
|
|
||||||
static const String liveFollow =
|
static const String liveFollow =
|
||||||
'${HttpString.liveBaseUrl}/xlive/web-ucenter/user/following';
|
'${HttpString.liveBaseUrl}/xlive/web-ucenter/user/following';
|
||||||
|
|
||||||
|
static const String liveSecondList =
|
||||||
|
'${HttpString.liveBaseUrl}/xlive/app-interface/v2/second/getList';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'package:PiliPlus/models/live/live_room/danmu_info.dart';
|
|||||||
import 'package:PiliPlus/models/live/live_room/item.dart';
|
import 'package:PiliPlus/models/live/live_room/item.dart';
|
||||||
import 'package:PiliPlus/models/live/live_room/room_info.dart';
|
import 'package:PiliPlus/models/live/live_room/room_info.dart';
|
||||||
import 'package:PiliPlus/models/live/live_room/room_info_h5.dart';
|
import 'package:PiliPlus/models/live/live_room/room_info_h5.dart';
|
||||||
|
import 'package:PiliPlus/models/live/live_second_list/data.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:PiliPlus/utils/wbi_sign.dart';
|
import 'package:PiliPlus/utils/wbi_sign.dart';
|
||||||
@@ -172,6 +173,7 @@ class LiveHttp {
|
|||||||
static Future<LoadingState<LiveIndexData>> liveFeedIndex({
|
static Future<LoadingState<LiveIndexData>> liveFeedIndex({
|
||||||
required int pn,
|
required int pn,
|
||||||
required bool isLogin,
|
required bool isLogin,
|
||||||
|
bool? moduleSelect,
|
||||||
}) async {
|
}) async {
|
||||||
final params = {
|
final params = {
|
||||||
if (isLogin) 'access_key': Accounts.main.accessKey,
|
if (isLogin) 'access_key': Accounts.main.accessKey,
|
||||||
@@ -185,17 +187,16 @@ class LiveHttp {
|
|||||||
'fnval': '912',
|
'fnval': '912',
|
||||||
'disable_rcmd': '0',
|
'disable_rcmd': '0',
|
||||||
'https_url_req': '1',
|
'https_url_req': '1',
|
||||||
'login_event': isLogin ? '1' : '0',
|
if (moduleSelect == true) 'module_select': '1',
|
||||||
'mobi_app': 'android_hd',
|
'mobi_app': 'android_hd',
|
||||||
'module_select': '0',
|
|
||||||
'network': 'wifi',
|
'network': 'wifi',
|
||||||
'page': pn.toString(),
|
'page': pn,
|
||||||
'platform': 'android',
|
'platform': 'android',
|
||||||
if (isLogin) 'relation_page': '1',
|
if (isLogin) 'relation_page': '1',
|
||||||
's_locale': 'zh_CN',
|
's_locale': 'zh_CN',
|
||||||
'scale': '2',
|
'scale': '2',
|
||||||
'statistics': Constants.statistics,
|
'statistics': Constants.statistics,
|
||||||
'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(),
|
'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||||
};
|
};
|
||||||
Utils.appSign(
|
Utils.appSign(
|
||||||
params,
|
params,
|
||||||
@@ -229,4 +230,53 @@ class LiveHttp {
|
|||||||
return LoadingState.error(res.data['message']);
|
return LoadingState.error(res.data['message']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<LoadingState<LiveSecondData>> liveSecondList({
|
||||||
|
required int pn,
|
||||||
|
required bool isLogin,
|
||||||
|
required int? areaId,
|
||||||
|
required int? parentAreaId,
|
||||||
|
}) async {
|
||||||
|
final params = {
|
||||||
|
if (isLogin) 'access_key': Accounts.main.accessKey,
|
||||||
|
'appkey': Constants.appKey,
|
||||||
|
'actionKey': 'appkey',
|
||||||
|
if (areaId != null) 'area_id': areaId,
|
||||||
|
if (parentAreaId != null) 'parent_area_id': parentAreaId,
|
||||||
|
'build': '8350200',
|
||||||
|
'c_locale': 'zh_CN',
|
||||||
|
'device': 'pad',
|
||||||
|
'device_name': 'vivo',
|
||||||
|
'device_type': '0',
|
||||||
|
'fnval': '912',
|
||||||
|
'disable_rcmd': '0',
|
||||||
|
'https_url_req': '1',
|
||||||
|
'mobi_app': 'android_hd',
|
||||||
|
'module_select': '0',
|
||||||
|
'network': 'wifi',
|
||||||
|
'page': pn,
|
||||||
|
'page_size': '20',
|
||||||
|
'platform': 'android',
|
||||||
|
'qn': '0',
|
||||||
|
'tag_version': '1',
|
||||||
|
's_locale': 'zh_CN',
|
||||||
|
'scale': '2',
|
||||||
|
'statistics': Constants.statistics,
|
||||||
|
'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(),
|
||||||
|
};
|
||||||
|
Utils.appSign(
|
||||||
|
params,
|
||||||
|
Constants.appKey,
|
||||||
|
Constants.appSec,
|
||||||
|
);
|
||||||
|
var res = await Request().get(
|
||||||
|
Api.liveSecondList,
|
||||||
|
queryParameters: params,
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return LoadingState.success(LiveSecondData.fromJson(res.data['data']));
|
||||||
|
} else {
|
||||||
|
return LoadingState.error(res.data['message']);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
class Avatar {
|
|
||||||
String? cover;
|
|
||||||
String? event;
|
|
||||||
String? text;
|
|
||||||
int? uid;
|
|
||||||
String? url;
|
|
||||||
|
|
||||||
Avatar({this.cover, this.event, this.text, this.uid, this.url});
|
|
||||||
|
|
||||||
factory Avatar.fromJson(Map<String, dynamic> json) => Avatar(
|
|
||||||
cover: json['cover'] as String?,
|
|
||||||
event: json['event'] as String?,
|
|
||||||
text: json['text'] as String?,
|
|
||||||
uid: json['uid'] as int?,
|
|
||||||
url: json['url'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'cover': cover,
|
|
||||||
'event': event,
|
|
||||||
'text': text,
|
|
||||||
'uid': uid,
|
|
||||||
'url': url,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
class CalendarButton {
|
|
||||||
String? text;
|
|
||||||
String? link;
|
|
||||||
|
|
||||||
CalendarButton({this.text, this.link});
|
|
||||||
|
|
||||||
factory CalendarButton.fromJson(Map<String, dynamic> json) {
|
|
||||||
return CalendarButton(
|
|
||||||
text: json['text'] as String?,
|
|
||||||
link: json['link'] as String?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'text': text,
|
|
||||||
'link': link,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -5,11 +5,13 @@ import 'card_data_item.dart';
|
|||||||
class CardData {
|
class CardData {
|
||||||
CardDataItem? bannerV2;
|
CardDataItem? bannerV2;
|
||||||
CardDataItem? myIdolV1;
|
CardDataItem? myIdolV1;
|
||||||
|
CardDataItem? areaEntranceV3;
|
||||||
CardLiveItem? smallCardV1;
|
CardLiveItem? smallCardV1;
|
||||||
|
|
||||||
CardData({
|
CardData({
|
||||||
this.bannerV2,
|
this.bannerV2,
|
||||||
this.myIdolV1,
|
this.myIdolV1,
|
||||||
|
this.areaEntranceV3,
|
||||||
this.smallCardV1,
|
this.smallCardV1,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,6 +22,10 @@ class CardData {
|
|||||||
myIdolV1: json['my_idol_v1'] == null
|
myIdolV1: json['my_idol_v1'] == null
|
||||||
? null
|
? null
|
||||||
: CardDataItem.fromJson(json['my_idol_v1'] as Map<String, dynamic>),
|
: CardDataItem.fromJson(json['my_idol_v1'] as Map<String, dynamic>),
|
||||||
|
areaEntranceV3: json['area_entrance_v3'] == null
|
||||||
|
? null
|
||||||
|
: CardDataItem.fromJson(
|
||||||
|
json['area_entrance_v3'] as Map<String, dynamic>),
|
||||||
smallCardV1: json['small_card_v1'] == null
|
smallCardV1: json['small_card_v1'] == null
|
||||||
? null
|
? null
|
||||||
: CardLiveItem.fromJson(
|
: CardLiveItem.fromJson(
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import 'quality_description.dart';
|
|
||||||
import 'watched_show.dart';
|
import 'watched_show.dart';
|
||||||
|
|
||||||
class CardLiveItem {
|
class CardLiveItem {
|
||||||
int? id;
|
|
||||||
int? roomid;
|
int? roomid;
|
||||||
int? uid;
|
int? uid;
|
||||||
String? uname;
|
String? uname;
|
||||||
@@ -18,35 +16,14 @@ class CardLiveItem {
|
|||||||
int? areaV2ParentId;
|
int? areaV2ParentId;
|
||||||
String? liveTagName;
|
String? liveTagName;
|
||||||
int? online;
|
int? online;
|
||||||
String? playUrl;
|
|
||||||
String? playUrlH265;
|
|
||||||
List? acceptQuality;
|
|
||||||
int? currentQuality;
|
|
||||||
int? pkId;
|
|
||||||
String? link;
|
String? link;
|
||||||
int? specialAttention;
|
|
||||||
int? broadcastType;
|
|
||||||
String? pendentRu;
|
|
||||||
String? pendentRuColor;
|
|
||||||
String? pendentRuPic;
|
|
||||||
int? officialVerify;
|
int? officialVerify;
|
||||||
int? currentQn;
|
int? currentQn;
|
||||||
List<QualityDescription>? qualityDescription;
|
|
||||||
String? playUrlCard;
|
|
||||||
int? flag;
|
|
||||||
List<dynamic>? pendentList;
|
|
||||||
int? p2pType;
|
|
||||||
String? sessionId;
|
|
||||||
int? groupId;
|
|
||||||
WatchedShow? watchedShow;
|
WatchedShow? watchedShow;
|
||||||
int? isNft;
|
|
||||||
String? nftDmark;
|
|
||||||
String? statusText;
|
String? statusText;
|
||||||
String? darkFace;
|
int? tagType;
|
||||||
String? trackid;
|
|
||||||
|
|
||||||
CardLiveItem({
|
CardLiveItem({
|
||||||
this.id,
|
|
||||||
this.roomid,
|
this.roomid,
|
||||||
this.uid,
|
this.uid,
|
||||||
this.uname,
|
this.uname,
|
||||||
@@ -62,37 +39,16 @@ class CardLiveItem {
|
|||||||
this.areaV2ParentId,
|
this.areaV2ParentId,
|
||||||
this.liveTagName,
|
this.liveTagName,
|
||||||
this.online,
|
this.online,
|
||||||
this.playUrl,
|
|
||||||
this.playUrlH265,
|
|
||||||
this.acceptQuality,
|
|
||||||
this.currentQuality,
|
|
||||||
this.pkId,
|
|
||||||
this.link,
|
this.link,
|
||||||
this.specialAttention,
|
|
||||||
this.broadcastType,
|
|
||||||
this.pendentRu,
|
|
||||||
this.pendentRuColor,
|
|
||||||
this.pendentRuPic,
|
|
||||||
this.officialVerify,
|
this.officialVerify,
|
||||||
this.currentQn,
|
this.currentQn,
|
||||||
this.qualityDescription,
|
|
||||||
this.playUrlCard,
|
|
||||||
this.flag,
|
|
||||||
this.pendentList,
|
|
||||||
this.p2pType,
|
|
||||||
this.sessionId,
|
|
||||||
this.groupId,
|
|
||||||
this.watchedShow,
|
this.watchedShow,
|
||||||
this.isNft,
|
|
||||||
this.nftDmark,
|
|
||||||
this.statusText,
|
this.statusText,
|
||||||
this.darkFace,
|
this.tagType,
|
||||||
this.trackid,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
factory CardLiveItem.fromJson(Map<String, dynamic> json) => CardLiveItem(
|
factory CardLiveItem.fromJson(Map<String, dynamic> json) => CardLiveItem(
|
||||||
id: json['id'] as int?,
|
roomid: json['roomid'] ?? json['id'],
|
||||||
roomid: json['roomid'] as int?,
|
|
||||||
uid: json['uid'] as int?,
|
uid: json['uid'] as int?,
|
||||||
uname: json['uname'] as String?,
|
uname: json['uname'] as String?,
|
||||||
face: json['face'] as String?,
|
face: json['face'] as String?,
|
||||||
@@ -107,37 +63,15 @@ class CardLiveItem {
|
|||||||
areaV2ParentId: json['area_v2_parent_id'] as int?,
|
areaV2ParentId: json['area_v2_parent_id'] as int?,
|
||||||
liveTagName: json['live_tag_name'] as String?,
|
liveTagName: json['live_tag_name'] as String?,
|
||||||
online: json['online'] as int?,
|
online: json['online'] as int?,
|
||||||
playUrl: json['play_url'] as String?,
|
|
||||||
playUrlH265: json['play_url_h265'] as String?,
|
|
||||||
acceptQuality: json['accept_quality'],
|
|
||||||
currentQuality: json['current_quality'] as int?,
|
|
||||||
pkId: json['pk_id'] as int?,
|
|
||||||
link: json['link'] as String?,
|
link: json['link'] as String?,
|
||||||
specialAttention: json['special_attention'] as int?,
|
|
||||||
broadcastType: json['broadcast_type'] as int?,
|
|
||||||
pendentRu: json['pendent_ru'] as String?,
|
|
||||||
pendentRuColor: json['pendent_ru_color'] as String?,
|
|
||||||
pendentRuPic: json['pendent_ru_pic'] as String?,
|
|
||||||
officialVerify: json['official_verify'] as int?,
|
officialVerify: json['official_verify'] as int?,
|
||||||
currentQn: json['current_qn'] as int?,
|
currentQn: json['current_qn'] as int?,
|
||||||
qualityDescription: (json['quality_description'] as List<dynamic>?)
|
|
||||||
?.map((e) => QualityDescription.fromJson(e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
playUrlCard: json['play_url_card'] as String?,
|
|
||||||
flag: json['flag'] as int?,
|
|
||||||
pendentList: json['pendent_list'] as List<dynamic>?,
|
|
||||||
p2pType: json['p2p_type'] as int?,
|
|
||||||
sessionId: json['session_id'] as String?,
|
|
||||||
groupId: json['group_id'] as int?,
|
|
||||||
watchedShow: json['watched_show'] == null
|
watchedShow: json['watched_show'] == null
|
||||||
? null
|
? null
|
||||||
: WatchedShow.fromJson(
|
: WatchedShow.fromJson(
|
||||||
json['watched_show'] as Map<String, dynamic>),
|
json['watched_show'] as Map<String, dynamic>),
|
||||||
isNft: json['is_nft'] as int?,
|
|
||||||
nftDmark: json['nft_dmark'] as String?,
|
|
||||||
statusText: json['status_text'] as String?,
|
statusText: json['status_text'] as String?,
|
||||||
darkFace: json['dark_face'] as String?,
|
tagType: json['tag_type'],
|
||||||
trackid: json['trackid'] as String?,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
@@ -156,32 +90,10 @@ class CardLiveItem {
|
|||||||
'area_v2_parent_id': areaV2ParentId,
|
'area_v2_parent_id': areaV2ParentId,
|
||||||
'live_tag_name': liveTagName,
|
'live_tag_name': liveTagName,
|
||||||
'online': online,
|
'online': online,
|
||||||
'play_url': playUrl,
|
|
||||||
'play_url_h265': playUrlH265,
|
|
||||||
'accept_quality': acceptQuality,
|
|
||||||
'current_quality': currentQuality,
|
|
||||||
'pk_id': pkId,
|
|
||||||
'link': link,
|
'link': link,
|
||||||
'special_attention': specialAttention,
|
|
||||||
'broadcast_type': broadcastType,
|
|
||||||
'pendent_ru': pendentRu,
|
|
||||||
'pendent_ru_color': pendentRuColor,
|
|
||||||
'pendent_ru_pic': pendentRuPic,
|
|
||||||
'official_verify': officialVerify,
|
'official_verify': officialVerify,
|
||||||
'current_qn': currentQn,
|
'current_qn': currentQn,
|
||||||
'quality_description':
|
|
||||||
qualityDescription?.map((e) => e.toJson()).toList(),
|
|
||||||
'play_url_card': playUrlCard,
|
|
||||||
'flag': flag,
|
|
||||||
'pendent_list': pendentList,
|
|
||||||
'p2p_type': p2pType,
|
|
||||||
'session_id': sessionId,
|
|
||||||
'group_id': groupId,
|
|
||||||
'watched_show': watchedShow?.toJson(),
|
'watched_show': watchedShow?.toJson(),
|
||||||
'is_nft': isNft,
|
|
||||||
'nft_dmark': nftDmark,
|
|
||||||
'status_text': statusText,
|
'status_text': statusText,
|
||||||
'dark_face': darkFace,
|
|
||||||
'trackid': trackid,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ class LiveIndexData {
|
|||||||
int? hasMore;
|
int? hasMore;
|
||||||
int? triggerTime;
|
int? triggerTime;
|
||||||
int? isNeedRefresh;
|
int? isNeedRefresh;
|
||||||
|
LiveCardList? followItem;
|
||||||
|
LiveCardList? areaItem;
|
||||||
|
|
||||||
LiveIndexData({
|
LiveIndexData({
|
||||||
this.cardList,
|
this.cardList,
|
||||||
@@ -17,14 +19,22 @@ class LiveIndexData {
|
|||||||
|
|
||||||
LiveIndexData.fromJson(Map<String, dynamic> json) {
|
LiveIndexData.fromJson(Map<String, dynamic> json) {
|
||||||
if ((json['card_list'] as List<dynamic>?)?.isNotEmpty == true) {
|
if ((json['card_list'] as List<dynamic>?)?.isNotEmpty == true) {
|
||||||
cardList = <LiveCardList>[];
|
|
||||||
// banner_v2
|
// banner_v2
|
||||||
// my_idol_v1
|
// my_idol_v1
|
||||||
// area_entrance_v3
|
// area_entrance_v3
|
||||||
// small_card_v1
|
// small_card_v1
|
||||||
for (var json in json['card_list']) {
|
for (var json in json['card_list']) {
|
||||||
if (const ['my_idol_v1', 'small_card_v1'].contains(json['card_type'])) {
|
switch (json['card_type']) {
|
||||||
cardList!.add(LiveCardList.fromJson(json));
|
case 'my_idol_v1':
|
||||||
|
followItem = LiveCardList.fromJson(json);
|
||||||
|
break;
|
||||||
|
case 'area_entrance_v3':
|
||||||
|
areaItem = LiveCardList.fromJson(json);
|
||||||
|
break;
|
||||||
|
case 'small_card_v1':
|
||||||
|
cardList ??= <LiveCardList>[];
|
||||||
|
cardList!.add(LiveCardList.fromJson(json));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
class InLive {
|
|
||||||
int? alphaLight;
|
|
||||||
int? alphaNight;
|
|
||||||
String? animationUrl;
|
|
||||||
String? animationUrlHash;
|
|
||||||
String? backgroundColorLight;
|
|
||||||
String? backgroundColorNight;
|
|
||||||
String? fontColor;
|
|
||||||
String? text;
|
|
||||||
|
|
||||||
InLive({
|
|
||||||
this.alphaLight,
|
|
||||||
this.alphaNight,
|
|
||||||
this.animationUrl,
|
|
||||||
this.animationUrlHash,
|
|
||||||
this.backgroundColorLight,
|
|
||||||
this.backgroundColorNight,
|
|
||||||
this.fontColor,
|
|
||||||
this.text,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory InLive.fromJson(Map<String, dynamic> json) => InLive(
|
|
||||||
alphaLight: json['alpha_light'] as int?,
|
|
||||||
alphaNight: json['alpha_night'] as int?,
|
|
||||||
animationUrl: json['animation_url'] as String?,
|
|
||||||
animationUrlHash: json['animation_url_hash'] as String?,
|
|
||||||
backgroundColorLight: json['background_color_light'] as String?,
|
|
||||||
backgroundColorNight: json['background_color_night'] as String?,
|
|
||||||
fontColor: json['font_color'] as String?,
|
|
||||||
text: json['text'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'alpha_light': alphaLight,
|
|
||||||
'alpha_night': alphaNight,
|
|
||||||
'animation_url': animationUrl,
|
|
||||||
'animation_url_hash': animationUrlHash,
|
|
||||||
'background_color_light': backgroundColorLight,
|
|
||||||
'background_color_night': backgroundColorNight,
|
|
||||||
'font_color': fontColor,
|
|
||||||
'text': text,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
import 'avatar.dart';
|
|
||||||
import 'calendar_button.dart';
|
|
||||||
import 'player_args.dart';
|
|
||||||
import 'right_top_live_badge.dart';
|
|
||||||
|
|
||||||
class InlineLive {
|
|
||||||
Avatar? avatar;
|
|
||||||
String? cover;
|
|
||||||
int? inlineStartDelayTime;
|
|
||||||
int? inlineSustainDuration;
|
|
||||||
String? link;
|
|
||||||
PlayerArgs? playerArgs;
|
|
||||||
dynamic rankListInfo;
|
|
||||||
RightTopLiveBadge? rightTopLiveBadge;
|
|
||||||
String? title;
|
|
||||||
dynamic topViewInfo;
|
|
||||||
String? upName;
|
|
||||||
String? inlinePlayUrl;
|
|
||||||
CalendarButton? calendarButton;
|
|
||||||
|
|
||||||
InlineLive({
|
|
||||||
this.avatar,
|
|
||||||
this.cover,
|
|
||||||
this.inlineStartDelayTime,
|
|
||||||
this.inlineSustainDuration,
|
|
||||||
this.link,
|
|
||||||
this.playerArgs,
|
|
||||||
this.rankListInfo,
|
|
||||||
this.rightTopLiveBadge,
|
|
||||||
this.title,
|
|
||||||
this.topViewInfo,
|
|
||||||
this.upName,
|
|
||||||
this.inlinePlayUrl,
|
|
||||||
this.calendarButton,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory InlineLive.fromJson(Map<String, dynamic> json) => InlineLive(
|
|
||||||
avatar: json['avatar'] == null
|
|
||||||
? null
|
|
||||||
: Avatar.fromJson(json['avatar'] as Map<String, dynamic>),
|
|
||||||
cover: json['cover'] as String?,
|
|
||||||
inlineStartDelayTime: json['inline_start_delay_time'] as int?,
|
|
||||||
inlineSustainDuration: json['inline_sustain_duration'] as int?,
|
|
||||||
link: json['link'] as String?,
|
|
||||||
playerArgs: json['player_args'] == null
|
|
||||||
? null
|
|
||||||
: PlayerArgs.fromJson(json['player_args'] as Map<String, dynamic>),
|
|
||||||
rankListInfo: json['rank_list_info'] as dynamic,
|
|
||||||
rightTopLiveBadge: json['right_top_live_badge'] == null
|
|
||||||
? null
|
|
||||||
: RightTopLiveBadge.fromJson(json['right_top_live_badge'] as Map<String, dynamic>),
|
|
||||||
title: json['title'] as String?,
|
|
||||||
topViewInfo: json['top_view_info'] as dynamic,
|
|
||||||
upName: json['up_name'] as String?,
|
|
||||||
inlinePlayUrl: json['inline_play_url'] as String?,
|
|
||||||
calendarButton: json['calendar_button'] == null
|
|
||||||
? null
|
|
||||||
: CalendarButton.fromJson(json['calendar_button'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'avatar': avatar?.toJson(),
|
|
||||||
'cover': cover,
|
|
||||||
'inline_start_delay_time': inlineStartDelayTime,
|
|
||||||
'inline_sustain_duration': inlineSustainDuration,
|
|
||||||
'link': link,
|
|
||||||
'player_args': playerArgs?.toJson(),
|
|
||||||
'rank_list_info': rankListInfo,
|
|
||||||
'right_top_live_badge': rightTopLiveBadge?.toJson(),
|
|
||||||
'title': title,
|
|
||||||
'top_view_info': topViewInfo,
|
|
||||||
'up_name': upName,
|
|
||||||
'inline_play_url': inlinePlayUrl,
|
|
||||||
'calendar_button': calendarButton?.toJson(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
class PlayerArgs {
|
|
||||||
int? canPlay;
|
|
||||||
bool? hideDanmuSwitch;
|
|
||||||
int? liveStatus;
|
|
||||||
int? parentAreaId;
|
|
||||||
int? areaId;
|
|
||||||
int? roomId;
|
|
||||||
int? upId;
|
|
||||||
|
|
||||||
PlayerArgs({
|
|
||||||
this.canPlay,
|
|
||||||
this.hideDanmuSwitch,
|
|
||||||
this.liveStatus,
|
|
||||||
this.parentAreaId,
|
|
||||||
this.areaId,
|
|
||||||
this.roomId,
|
|
||||||
this.upId,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory PlayerArgs.fromJson(Map<String, dynamic> json) => PlayerArgs(
|
|
||||||
canPlay: json['can_play'] as int?,
|
|
||||||
hideDanmuSwitch: json['hide_danmu_switch'] as bool?,
|
|
||||||
liveStatus: json['live_status'] as int?,
|
|
||||||
parentAreaId: json['parent_area_id'] as int?,
|
|
||||||
areaId: json['area_id'] as int?,
|
|
||||||
roomId: json['room_id'] as int?,
|
|
||||||
upId: json['up_id'] as int?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'can_play': canPlay,
|
|
||||||
'hide_danmu_switch': hideDanmuSwitch,
|
|
||||||
'live_status': liveStatus,
|
|
||||||
'parent_area_id': parentAreaId,
|
|
||||||
'area_id': areaId,
|
|
||||||
'room_id': roomId,
|
|
||||||
'up_id': upId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
class QualityDescription {
|
|
||||||
int? qn;
|
|
||||||
String? desc;
|
|
||||||
|
|
||||||
QualityDescription({this.qn, this.desc});
|
|
||||||
|
|
||||||
factory QualityDescription.fromJson(Map<String, dynamic> json) {
|
|
||||||
return QualityDescription(
|
|
||||||
qn: json['qn'] as int?,
|
|
||||||
desc: json['desc'] as String?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'qn': qn,
|
|
||||||
'desc': desc,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import 'in_live.dart';
|
|
||||||
|
|
||||||
class RightTopLiveBadge {
|
|
||||||
InLive? inLive;
|
|
||||||
int? liveStatus;
|
|
||||||
|
|
||||||
RightTopLiveBadge({this.inLive, this.liveStatus});
|
|
||||||
|
|
||||||
factory RightTopLiveBadge.fromJson(Map<String, dynamic> json) {
|
|
||||||
return RightTopLiveBadge(
|
|
||||||
inLive: json['in_live'] == null
|
|
||||||
? null
|
|
||||||
: InLive.fromJson(json['in_live'] as Map<String, dynamic>),
|
|
||||||
liveStatus: json['live_status'] as int?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'in_live': inLive?.toJson(),
|
|
||||||
'live_status': liveStatus,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
23
lib/models/live/live_second_list/data.dart
Normal file
23
lib/models/live/live_second_list/data.dart
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import 'package:PiliPlus/models/live/live_feed_index/card_data_list_item.dart';
|
||||||
|
|
||||||
|
class LiveSecondData {
|
||||||
|
int? count;
|
||||||
|
List<CardLiveItem>? cardList;
|
||||||
|
|
||||||
|
LiveSecondData({
|
||||||
|
this.count,
|
||||||
|
this.cardList,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory LiveSecondData.fromJson(Map<String, dynamic> json) => LiveSecondData(
|
||||||
|
count: json['count'] as int?,
|
||||||
|
cardList: (json['list'] as List<dynamic>?)
|
||||||
|
?.map((e) => CardLiveItem.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'count': count,
|
||||||
|
'list': cardList?.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,26 +1,90 @@
|
|||||||
|
import 'package:PiliPlus/common/widgets/pair.dart';
|
||||||
import 'package:PiliPlus/http/live.dart';
|
import 'package:PiliPlus/http/live.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
|
import 'package:PiliPlus/models/live/live_feed_index/card_data_list_item.dart';
|
||||||
import 'package:PiliPlus/models/live/live_feed_index/card_list.dart';
|
import 'package:PiliPlus/models/live/live_feed_index/card_list.dart';
|
||||||
import 'package:PiliPlus/models/live/live_feed_index/data.dart';
|
|
||||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:get/get_rx/src/rx_types/rx_types.dart';
|
import 'package:get/get_rx/src/rx_types/rx_types.dart';
|
||||||
|
|
||||||
class LiveController extends CommonListController<LiveIndexData, LiveCardList> {
|
class LiveController extends CommonListController {
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
queryData();
|
queryData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int? areaId;
|
||||||
|
int? parentAreaId;
|
||||||
|
final RxInt areaIndex = 0.obs;
|
||||||
|
final Rx<Pair<LiveCardList?, LiveCardList?>> topState =
|
||||||
|
Pair<LiveCardList?, LiveCardList?>(first: null, second: null).obs;
|
||||||
final RxBool isLogin = Accounts.main.isLogin.obs;
|
final RxBool isLogin = Accounts.main.isLogin.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<LiveCardList>? getDataList(LiveIndexData response) {
|
List? getDataList(response) {
|
||||||
return response.cardList;
|
return response.cardList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LoadingState<LiveIndexData>> customGetData() =>
|
bool customHandleResponse(bool isRefresh, Success response) {
|
||||||
LiveHttp.liveFeedIndex(pn: currentPage, isLogin: isLogin.value);
|
if (isRefresh && areaIndex.value == 0) {
|
||||||
|
topState.value = Pair(
|
||||||
|
first: response.response.followItem,
|
||||||
|
second: response.response.areaItem,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<LoadingState> customGetData() {
|
||||||
|
if (areaIndex.value != 0) {
|
||||||
|
return LiveHttp.liveSecondList(
|
||||||
|
pn: currentPage,
|
||||||
|
isLogin: isLogin.value,
|
||||||
|
areaId: areaId,
|
||||||
|
parentAreaId: parentAreaId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return LiveHttp.liveFeedIndex(pn: currentPage, isLogin: isLogin.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onRefresh() async {
|
||||||
|
currentPage = 1;
|
||||||
|
isEnd = false;
|
||||||
|
if (areaIndex.value != 0) {
|
||||||
|
queryTop();
|
||||||
|
}
|
||||||
|
await queryData();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> queryTop() async {
|
||||||
|
final res = await LiveHttp.liveFeedIndex(
|
||||||
|
pn: currentPage,
|
||||||
|
isLogin: isLogin.value,
|
||||||
|
moduleSelect: true,
|
||||||
|
);
|
||||||
|
if (res is Success) {
|
||||||
|
final data = res.data;
|
||||||
|
topState.value = Pair(
|
||||||
|
first: data.followItem,
|
||||||
|
second: data.areaItem,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSelectArea(int index, CardLiveItem? cardLiveItem) {
|
||||||
|
if (index == areaIndex.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
areaIndex.value = index;
|
||||||
|
areaId = cardLiveItem?.areaV2Id;
|
||||||
|
parentAreaId = cardLiveItem?.areaV2ParentId;
|
||||||
|
|
||||||
|
currentPage = 1;
|
||||||
|
isEnd = false;
|
||||||
|
queryData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:PiliPlus/common/constants.dart';
|
|||||||
import 'package:PiliPlus/common/skeleton/video_card_v.dart';
|
import 'package:PiliPlus/common/skeleton/video_card_v.dart';
|
||||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||||
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
||||||
|
import 'package:PiliPlus/common/widgets/pair.dart';
|
||||||
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||||
import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart';
|
import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
@@ -11,7 +12,7 @@ import 'package:PiliPlus/pages/common/common_page.dart';
|
|||||||
import 'package:PiliPlus/pages/live/controller.dart';
|
import 'package:PiliPlus/pages/live/controller.dart';
|
||||||
import 'package:PiliPlus/pages/live/widgets/live_item_app.dart';
|
import 'package:PiliPlus/pages/live/widgets/live_item_app.dart';
|
||||||
import 'package:PiliPlus/pages/live_follow/view.dart';
|
import 'package:PiliPlus/pages/live_follow/view.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/pages/search/widgets/search_text.dart';
|
||||||
import 'package:PiliPlus/utils/grid.dart';
|
import 'package:PiliPlus/utils/grid.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -54,7 +55,10 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
|||||||
top: StyleString.cardSpace,
|
top: StyleString.cardSpace,
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
),
|
),
|
||||||
sliver: Obx(() => _buildBody(controller.loadingState.value)),
|
sliver: SliverMainAxisGroup(slivers: [
|
||||||
|
Obx(() => _buildTop(controller.topState.value)),
|
||||||
|
Obx(() => _buildBody(controller.loadingState.value)),
|
||||||
|
]),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -62,7 +66,51 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody(LoadingState<List<LiveCardList>?> loadingState) {
|
Widget _buildTop(Pair<LiveCardList?, LiveCardList?> data) {
|
||||||
|
return SliverMainAxisGroup(
|
||||||
|
slivers: [
|
||||||
|
if (data.first != null)
|
||||||
|
SliverToBoxAdapter(child: _buildFollowList(data.first!)),
|
||||||
|
if (data.second?.cardData?.areaEntranceV3?.list?.isNotEmpty == true)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: SelfSizedHorizontalList(
|
||||||
|
gapSize: 12,
|
||||||
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
|
childBuilder: (index) {
|
||||||
|
late final item =
|
||||||
|
data.second!.cardData!.areaEntranceV3!.list![index - 1];
|
||||||
|
return Obx(
|
||||||
|
() => SearchText(
|
||||||
|
fontSize: 14,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
text: index == 0 ? '推荐' : '${item.title}',
|
||||||
|
bgColor: index == controller.areaIndex.value
|
||||||
|
? Theme.of(context).colorScheme.secondaryContainer
|
||||||
|
: Colors.transparent,
|
||||||
|
textColor: index == controller.areaIndex.value
|
||||||
|
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||||
|
: null,
|
||||||
|
onTap: (value) {
|
||||||
|
controller.onSelectArea(
|
||||||
|
index,
|
||||||
|
index == 0 ? null : item,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount:
|
||||||
|
data.second!.cardData!.areaEntranceV3!.list!.length + 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildBody(LoadingState<List?> loadingState) {
|
||||||
return switch (loadingState) {
|
return switch (loadingState) {
|
||||||
Loading() => SliverGrid(
|
Loading() => SliverGrid(
|
||||||
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
||||||
@@ -80,47 +128,30 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Success() => loadingState.response?.isNotEmpty == true
|
Success() => loadingState.response?.isNotEmpty == true
|
||||||
? Builder(builder: (context) {
|
? SliverGrid(
|
||||||
List<LiveCardList> list = loadingState.response!;
|
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
||||||
LiveCardList? followItem;
|
mainAxisSpacing: StyleString.cardSpace,
|
||||||
if (list.first.cardType == 'my_idol_v1') {
|
crossAxisSpacing: StyleString.cardSpace,
|
||||||
followItem = list.first;
|
maxCrossAxisExtent: Grid.smallCardWidth,
|
||||||
list = list.sublist(1);
|
childAspectRatio: StyleString.aspectRatio,
|
||||||
}
|
mainAxisExtent: MediaQuery.textScalerOf(context).scale(90),
|
||||||
return SliverMainAxisGroup(
|
),
|
||||||
slivers: [
|
delegate: SliverChildBuilderDelegate(
|
||||||
if (followItem != null)
|
(context, index) {
|
||||||
SliverPadding(
|
if (index == loadingState.response!.length - 1) {
|
||||||
padding: const EdgeInsets.only(bottom: 12),
|
controller.onLoadMore();
|
||||||
sliver: SliverToBoxAdapter(
|
}
|
||||||
child: _buildFollowList(followItem),
|
final item = loadingState.response![index];
|
||||||
),
|
if (item is LiveCardList) {
|
||||||
),
|
return LiveCardVApp(
|
||||||
if (list.isNotEmpty)
|
item: item.cardData!.smallCardV1!,
|
||||||
SliverGrid(
|
);
|
||||||
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
}
|
||||||
mainAxisSpacing: StyleString.cardSpace,
|
return LiveCardVApp(item: item);
|
||||||
crossAxisSpacing: StyleString.cardSpace,
|
},
|
||||||
maxCrossAxisExtent: Grid.smallCardWidth,
|
childCount: loadingState.response!.length,
|
||||||
childAspectRatio: StyleString.aspectRatio,
|
),
|
||||||
mainAxisExtent:
|
)
|
||||||
MediaQuery.textScalerOf(context).scale(90),
|
|
||||||
),
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
if (index == list.length - 1) {
|
|
||||||
controller.onLoadMore();
|
|
||||||
}
|
|
||||||
return LiveCardVApp(
|
|
||||||
item: list[index].cardData!.smallCardV1!,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
childCount: list.length,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: HttpError(onReload: controller.onReload),
|
: HttpError(onReload: controller.onReload),
|
||||||
Error() => HttpError(
|
Error() => HttpError(
|
||||||
errMsg: loadingState.errMsg,
|
errMsg: loadingState.errMsg,
|
||||||
@@ -183,22 +214,21 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
_buildFollowBody(theme, item.cardData?.myIdolV1?.list),
|
if (item.cardData?.myIdolV1?.list?.isNotEmpty == true)
|
||||||
|
_buildFollowBody(theme, item.cardData!.myIdolV1!.list!),
|
||||||
|
const SizedBox(height: 10),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFollowBody(ThemeData theme, List<CardLiveItem>? list) {
|
Widget _buildFollowBody(ThemeData theme, List<CardLiveItem> followList) {
|
||||||
if (list.isNullOrEmpty) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
return MediaQuery.removePadding(
|
return MediaQuery.removePadding(
|
||||||
context: context,
|
context: context,
|
||||||
removeLeft: context.orientation == Orientation.landscape,
|
removeLeft: context.orientation == Orientation.landscape,
|
||||||
child: SelfSizedHorizontalList(
|
child: SelfSizedHorizontalList(
|
||||||
gapSize: 5,
|
gapSize: 5,
|
||||||
childBuilder: (index) {
|
childBuilder: (index) {
|
||||||
final item = list[index];
|
final item = followList[index];
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: 65,
|
width: 65,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
@@ -244,7 +274,7 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
itemCount: list!.length,
|
itemCount: followList.length,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ class LiveCardVApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String heroTag = Utils.makeHeroTag(item.id);
|
String heroTag = Utils.makeHeroTag(item.roomid);
|
||||||
return Card(
|
return Card(
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.toNamed('/liveRoom?roomid=${item.id}');
|
Get.toNamed('/liveRoom?roomid=${item.roomid}');
|
||||||
},
|
},
|
||||||
onLongPress: () => imageSaveDialog(
|
onLongPress: () => imageSaveDialog(
|
||||||
title: item.title,
|
title: item.title,
|
||||||
|
|||||||
Reference in New Issue
Block a user