mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: medialist page
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -13,6 +13,7 @@ class PBadge extends StatelessWidget {
|
|||||||
final String? semanticsLabel;
|
final String? semanticsLabel;
|
||||||
final bool bold;
|
final bool bold;
|
||||||
final double? textScaleFactor;
|
final double? textScaleFactor;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
|
||||||
const PBadge({
|
const PBadge({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -28,6 +29,7 @@ class PBadge extends StatelessWidget {
|
|||||||
this.semanticsLabel,
|
this.semanticsLabel,
|
||||||
this.bold = true,
|
this.bold = true,
|
||||||
this.textScaleFactor,
|
this.textScaleFactor,
|
||||||
|
this.padding,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -54,7 +56,7 @@ class PBadge extends StatelessWidget {
|
|||||||
color = t.onError;
|
color = t.onError;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeInsets paddingStyle =
|
late EdgeInsets paddingStyle =
|
||||||
const EdgeInsets.symmetric(vertical: 2, horizontal: 3);
|
const EdgeInsets.symmetric(vertical: 2, horizontal: 3);
|
||||||
double fontSize = 11;
|
double fontSize = 11;
|
||||||
BorderRadius br = BorderRadius.circular(4);
|
BorderRadius br = BorderRadius.circular(4);
|
||||||
@@ -66,7 +68,7 @@ class PBadge extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget content = Container(
|
Widget content = Container(
|
||||||
padding: paddingStyle,
|
padding: padding ?? paddingStyle,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: br,
|
borderRadius: br,
|
||||||
color: bgColor,
|
color: bgColor,
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ class _EpisodePanelState extends CommonSlidePageState<EpisodePanel>
|
|||||||
|
|
||||||
late bool _isInit = true;
|
late bool _isInit = true;
|
||||||
late final Color primary = Theme.of(context).colorScheme.primary;
|
late final Color primary = Theme.of(context).colorScheme.primary;
|
||||||
final height = 120 / StyleString.aspectRatio + 10;
|
|
||||||
|
|
||||||
void listener() {
|
void listener() {
|
||||||
_currentTabIndex.value = _tabController.index;
|
_currentTabIndex.value = _tabController.index;
|
||||||
@@ -248,9 +247,9 @@ class _EpisodePanelState extends CommonSlidePageState<EpisodePanel>
|
|||||||
|
|
||||||
Widget _buildBody(int index, episodes) {
|
Widget _buildBody(int index, episodes) {
|
||||||
return KeepAliveWrapper(
|
return KeepAliveWrapper(
|
||||||
builder: (context) => ScrollablePositionedList.builder(
|
builder: (context) => ScrollablePositionedList.separated(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: 5,
|
top: 7,
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 80,
|
bottom: MediaQuery.of(context).padding.bottom + 80,
|
||||||
),
|
),
|
||||||
reverse: _isReversed[index],
|
reverse: _isReversed[index],
|
||||||
@@ -306,6 +305,7 @@ class _EpisodePanelState extends CommonSlidePageState<EpisodePanel>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
itemScrollController: _itemScrollController[index],
|
itemScrollController: _itemScrollController[index],
|
||||||
|
separatorBuilder: (context, index) => const SizedBox(height: 2),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -356,7 +356,7 @@ class _EpisodePanelState extends CommonSlidePageState<EpisodePanel>
|
|||||||
return Material(
|
return Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: height,
|
height: 98,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (episode.badge != null && episode.badge == "会员") {
|
if (episode.badge != null && episode.badge == "会员") {
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ class FavPgcItem extends StatelessWidget {
|
|||||||
right: 4,
|
right: 4,
|
||||||
top: 4,
|
top: 4,
|
||||||
text: item.badge,
|
text: item.badge,
|
||||||
|
fs: 10,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 2,
|
||||||
|
vertical: 1,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: IgnorePointer(
|
child: IgnorePointer(
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:PiliPlus/common/constants.dart';
|
|
||||||
import 'package:PiliPlus/common/widgets/loading_widget.dart';
|
import 'package:PiliPlus/common/widgets/loading_widget.dart';
|
||||||
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
@@ -79,7 +78,6 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
|||||||
}
|
}
|
||||||
|
|
||||||
_buildItem(Datum data, bool isFirst) {
|
_buildItem(Datum data, bool isFirst) {
|
||||||
final height = 120 / StyleString.aspectRatio + 10;
|
|
||||||
return Theme(
|
return Theme(
|
||||||
data: Theme.of(context).copyWith(
|
data: Theme.of(context).copyWith(
|
||||||
dividerColor: Colors.transparent,
|
dividerColor: Colors.transparent,
|
||||||
@@ -108,7 +106,7 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
|||||||
children: [
|
children: [
|
||||||
...(data.mediaListResponse?.list as List<FavList>).map(
|
...(data.mediaListResponse?.list as List<FavList>).map(
|
||||||
(item) => SizedBox(
|
(item) => SizedBox(
|
||||||
height: height,
|
height: 98,
|
||||||
child: MemberFavItem(
|
child: MemberFavItem(
|
||||||
item: item,
|
item: item,
|
||||||
callback: (res) {
|
callback: (res) {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class _MemberHomeState extends State<MemberHome>
|
|||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 120 / StyleString.aspectRatio + 10,
|
height: 98,
|
||||||
child: MemberFavItem(
|
child: MemberFavItem(
|
||||||
item: loadingState.response.favourite2.item.first,
|
item: loadingState.response.favourite2.item.first,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'package:PiliPlus/common/widgets/dialog.dart';
|
import 'package:PiliPlus/common/widgets/dialog.dart';
|
||||||
import 'package:PiliPlus/common/widgets/icon_button.dart';
|
import 'package:PiliPlus/common/widgets/icon_button.dart';
|
||||||
|
import 'package:PiliPlus/common/widgets/image_save.dart';
|
||||||
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||||
import 'package:PiliPlus/common/widgets/stat/stat.dart';
|
import 'package:PiliPlus/common/widgets/stat/stat.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_collapse_slide_page.dart';
|
import 'package:PiliPlus/pages/common/common_collapse_slide_page.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_slide_page.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -46,7 +46,8 @@ class MediaListPanel extends CommonCollapseSlidePage {
|
|||||||
State<MediaListPanel> createState() => _MediaListPanelState();
|
State<MediaListPanel> createState() => _MediaListPanelState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MediaListPanelState extends CommonSlidePageState<MediaListPanel> {
|
class _MediaListPanelState
|
||||||
|
extends CommonCollapseSlidePageState<MediaListPanel> {
|
||||||
final _scrollController = ItemScrollController();
|
final _scrollController = ItemScrollController();
|
||||||
late RxBool desc;
|
late RxBool desc;
|
||||||
|
|
||||||
@@ -97,6 +98,10 @@ class _MediaListPanelState extends CommonSlidePageState<MediaListPanel> {
|
|||||||
const SizedBox(width: 14),
|
const SizedBox(width: 14),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Divider(
|
||||||
|
height: 1,
|
||||||
|
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: enableSlide ? slideList() : buildList,
|
child: enableSlide ? slideList() : buildList,
|
||||||
),
|
),
|
||||||
@@ -119,11 +124,12 @@ class _MediaListPanelState extends CommonSlidePageState<MediaListPanel> {
|
|||||||
() {
|
() {
|
||||||
final showDelBtn =
|
final showDelBtn =
|
||||||
widget.onDelete != null && widget.mediaList.length > 1;
|
widget.onDelete != null && widget.mediaList.length > 1;
|
||||||
return ScrollablePositionedList.builder(
|
return ScrollablePositionedList.separated(
|
||||||
itemScrollController: _scrollController,
|
itemScrollController: _scrollController,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
itemCount: widget.mediaList.length,
|
itemCount: widget.mediaList.length,
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
|
top: 7,
|
||||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||||
),
|
),
|
||||||
itemBuilder: ((context, index) {
|
itemBuilder: ((context, index) {
|
||||||
@@ -133,158 +139,151 @@ class _MediaListPanelState extends CommonSlidePageState<MediaListPanel> {
|
|||||||
widget.mediaList.length < widget.count!)) {
|
widget.mediaList.length < widget.count!)) {
|
||||||
widget.loadMoreMedia();
|
widget.loadMoreMedia();
|
||||||
}
|
}
|
||||||
return InkWell(
|
return SizedBox(
|
||||||
onTap: () async {
|
height: 98,
|
||||||
if (item.type != 2) {
|
child: InkWell(
|
||||||
SmartDialog.showToast('不支持播放该类型视频');
|
onTap: () async {
|
||||||
return;
|
if (item.type != 2) {
|
||||||
}
|
SmartDialog.showToast('不支持播放该类型视频');
|
||||||
Get.back();
|
return;
|
||||||
String bvid = item.bvid!;
|
}
|
||||||
int? aid = item.id;
|
Get.back();
|
||||||
String cover = item.cover ?? '';
|
String bvid = item.bvid!;
|
||||||
final int cid =
|
int? aid = item.id;
|
||||||
item.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
String cover = item.cover ?? '';
|
||||||
widget.changeMediaList?.call(bvid, cid, aid, cover);
|
final int cid =
|
||||||
},
|
item.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||||
child: Stack(
|
widget.changeMediaList?.call(bvid, cid, aid, cover);
|
||||||
children: [
|
},
|
||||||
Padding(
|
onLongPress: () {
|
||||||
padding: const EdgeInsets.symmetric(
|
imageSaveDialog(
|
||||||
horizontal: 12,
|
context: context,
|
||||||
vertical: 5,
|
title: item.title,
|
||||||
),
|
cover: item.cover,
|
||||||
child: LayoutBuilder(
|
);
|
||||||
builder: (context, boxConstraints) {
|
},
|
||||||
const double width = 120;
|
child: Stack(
|
||||||
return Container(
|
children: [
|
||||||
constraints: const BoxConstraints(minHeight: 88),
|
Padding(
|
||||||
height: width / StyleString.aspectRatio,
|
padding: const EdgeInsets.symmetric(
|
||||||
child: Row(
|
horizontal: 12,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
vertical: 5,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
),
|
||||||
children: <Widget>[
|
child: Row(
|
||||||
AspectRatio(
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
aspectRatio: StyleString.aspectRatio,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: LayoutBuilder(
|
children: [
|
||||||
builder: (BuildContext context,
|
AspectRatio(
|
||||||
BoxConstraints boxConstraints) {
|
aspectRatio: StyleString.aspectRatio,
|
||||||
final double maxWidth =
|
child: LayoutBuilder(
|
||||||
boxConstraints.maxWidth;
|
builder: (context, boxConstraints) {
|
||||||
final double maxHeight =
|
return Stack(
|
||||||
boxConstraints.maxHeight;
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
NetworkImgLayer(
|
|
||||||
src: item.cover ?? '',
|
|
||||||
width: maxWidth,
|
|
||||||
height: maxHeight,
|
|
||||||
),
|
|
||||||
PBadge(
|
|
||||||
text: Utils.timeFormat(
|
|
||||||
item.duration!),
|
|
||||||
right: 6.0,
|
|
||||||
bottom: 6.0,
|
|
||||||
type: 'gray',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
NetworkImgLayer(
|
||||||
item.title as String,
|
src: item.cover,
|
||||||
textAlign: TextAlign.start,
|
width: boxConstraints.maxWidth,
|
||||||
maxLines: 2,
|
height: boxConstraints.maxHeight,
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight:
|
|
||||||
item.bvid == widget.getBvId()
|
|
||||||
? FontWeight.bold
|
|
||||||
: null,
|
|
||||||
color: item.bvid == widget.getBvId()
|
|
||||||
? Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.primary
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
PBadge(
|
||||||
Text(
|
text: Utils.timeFormat(item.duration!),
|
||||||
item.upper?.name as String,
|
right: 6.0,
|
||||||
style: TextStyle(
|
bottom: 6.0,
|
||||||
fontSize: Theme.of(context)
|
type: 'gray',
|
||||||
.textTheme
|
),
|
||||||
.labelMedium!
|
],
|
||||||
.fontSize,
|
);
|
||||||
color: Theme.of(context)
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
item.title!,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: item.bvid == widget.getBvId()
|
||||||
|
? FontWeight.bold
|
||||||
|
: null,
|
||||||
|
color: item.bvid == widget.getBvId()
|
||||||
|
? Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.outline,
|
.primary
|
||||||
),
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
item.upper!.name!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelMedium!
|
||||||
|
.fontSize,
|
||||||
|
color:
|
||||||
|
Theme.of(context).colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
StatView(
|
||||||
|
context: context,
|
||||||
|
theme: 'gray',
|
||||||
|
value: Utils.numFormat(
|
||||||
|
item.cntInfo!['play']!),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(width: 8),
|
||||||
Row(
|
StatDanMu(
|
||||||
children: [
|
context: context,
|
||||||
StatView(
|
theme: 'gray',
|
||||||
context: context,
|
value: Utils.numFormat(
|
||||||
theme: 'gray',
|
item.cntInfo!['danmaku']!),
|
||||||
value: Utils.numFormat(
|
|
||||||
item.cntInfo!['play']!),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
StatDanMu(
|
|
||||||
context: context,
|
|
||||||
theme: 'gray',
|
|
||||||
value: Utils.numFormat(
|
|
||||||
item.cntInfo!['danmaku']!),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
if (showDelBtn && item.bvid != widget.getBvId())
|
||||||
if (showDelBtn && item.bvid != widget.getBvId())
|
Positioned(
|
||||||
Positioned(
|
right: 12,
|
||||||
right: 12,
|
bottom: 0,
|
||||||
bottom: 0,
|
child: InkWell(
|
||||||
child: InkWell(
|
customBorder: const CircleBorder(),
|
||||||
customBorder: const CircleBorder(),
|
onTap: () {
|
||||||
onTap: () {
|
showConfirmDialog(
|
||||||
showConfirmDialog(
|
context: context,
|
||||||
context: context,
|
title: '确定移除该视频?',
|
||||||
title: '确定移除该视频?',
|
onConfirm: () => widget.onDelete!(index),
|
||||||
onConfirm: () => widget.onDelete!(index),
|
);
|
||||||
);
|
},
|
||||||
},
|
onLongPress: () => widget.onDelete!(index),
|
||||||
onLongPress: () => widget.onDelete!(index),
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(9),
|
||||||
padding: const EdgeInsets.all(9),
|
child: Icon(
|
||||||
child: Icon(
|
Icons.clear,
|
||||||
Icons.clear,
|
size: 18,
|
||||||
size: 18,
|
color: Theme.of(context)
|
||||||
color: Theme.of(context)
|
.colorScheme
|
||||||
.colorScheme
|
.onSurfaceVariant,
|
||||||
.onSurfaceVariant,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
separatorBuilder: (context, index) => const SizedBox(height: 2),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user