mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 11:08:03 +08:00
@@ -200,6 +200,186 @@ class _AudioPageState extends State<AudioPage> {
|
||||
builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
final colorScheme = theme.colorScheme;
|
||||
Widget child = CustomScrollView(
|
||||
controller: scrollController,
|
||||
physics: _controller.reachStart
|
||||
? null
|
||||
: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 100,
|
||||
),
|
||||
sliver: SliverList.builder(
|
||||
itemCount: playlist.length,
|
||||
itemBuilder: (_, index) {
|
||||
if (index == playlist.length - 1) {
|
||||
_controller.loadNext(context);
|
||||
}
|
||||
final isCurr = index == _controller.index;
|
||||
final item = playlist[index];
|
||||
if (item.parts.length > 1) {
|
||||
final subId = _controller.subId.firstOrNull;
|
||||
return ExpansionTile(
|
||||
dense: true,
|
||||
minTileHeight: 45,
|
||||
initiallyExpanded: isCurr,
|
||||
collapsedIconColor: isCurr ? colorScheme.primary : null,
|
||||
iconColor: isCurr ? null : colorScheme.onSurfaceVariant,
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
title: Text(
|
||||
item.arc.title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: isCurr
|
||||
? TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
)
|
||||
: const TextStyle(fontSize: 14),
|
||||
),
|
||||
trailing: isCurr
|
||||
? null
|
||||
: iconButton(
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
if (index < _controller.index!) {
|
||||
_controller.index -= 1;
|
||||
}
|
||||
playlist.removeAt(index);
|
||||
(context as Element).markNeedsBuild();
|
||||
},
|
||||
iconColor: colorScheme.outline,
|
||||
size: 28,
|
||||
iconSize: 18,
|
||||
),
|
||||
children: item.parts.map((e) {
|
||||
final isCurr = e.subId == subId;
|
||||
return ListTile(
|
||||
dense: true,
|
||||
minTileHeight: 45,
|
||||
contentPadding: const EdgeInsetsDirectional.only(
|
||||
start: 56.0,
|
||||
end: 24.0,
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
if (!isCurr) {
|
||||
_controller.playIndex(
|
||||
index,
|
||||
subId: [e.subId],
|
||||
);
|
||||
}
|
||||
},
|
||||
title: Text.rich(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: isCurr
|
||||
? TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
)
|
||||
: TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
TextSpan(
|
||||
children: [
|
||||
if (isCurr) ...[
|
||||
WidgetSpan(
|
||||
alignment: .bottom,
|
||||
child: Image.asset(
|
||||
'assets/images/live.gif',
|
||||
width: 16,
|
||||
height: 16,
|
||||
cacheWidth: 16.cacheSize(
|
||||
context,
|
||||
),
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
const TextSpan(text: ' '),
|
||||
],
|
||||
TextSpan(text: e.title),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
return ListTile(
|
||||
dense: true,
|
||||
minTileHeight: 45,
|
||||
onTap: () {
|
||||
Get.back();
|
||||
if (!isCurr) {
|
||||
_controller.playIndex(index);
|
||||
}
|
||||
},
|
||||
title: Text.rich(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: isCurr
|
||||
? TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
)
|
||||
: const TextStyle(fontSize: 14),
|
||||
TextSpan(
|
||||
children: [
|
||||
if (isCurr) ...[
|
||||
WidgetSpan(
|
||||
alignment: .bottom,
|
||||
child: Image.asset(
|
||||
'assets/images/live.gif',
|
||||
width: 16,
|
||||
height: 16,
|
||||
cacheWidth: 16.cacheSize(
|
||||
context,
|
||||
),
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
const TextSpan(text: ' '),
|
||||
],
|
||||
TextSpan(
|
||||
text: item.arc.title,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
trailing: isCurr
|
||||
? null
|
||||
: iconButton(
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
if (index < _controller.index!) {
|
||||
_controller.index -= 1;
|
||||
}
|
||||
playlist.removeAt(index);
|
||||
(context as Element).markNeedsBuild();
|
||||
},
|
||||
iconColor: colorScheme.outline,
|
||||
size: 28,
|
||||
iconSize: 18,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
if (!_controller.reachStart) {
|
||||
child = refreshIndicator(
|
||||
onRefresh: () => _controller.loadPrev(context),
|
||||
isClampingScrollPhysics: true,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
return FractionallySizedBox(
|
||||
heightFactor:
|
||||
PlatformUtils.isMobile && !context.mediaQuerySize.isPortrait
|
||||
@@ -219,9 +399,7 @@ class _AudioPageState extends State<AudioPage> {
|
||||
height: 3,
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.outline,
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(3),
|
||||
),
|
||||
borderRadius: const .all(.circular(3)),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -231,200 +409,8 @@ class _AudioPageState extends State<AudioPage> {
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: Theme(
|
||||
data: theme.copyWith(
|
||||
dividerColor: Colors.transparent,
|
||||
),
|
||||
child: refreshIndicator(
|
||||
onRefresh: () => _controller.loadPrev(context),
|
||||
isClampingScrollPhysics: true,
|
||||
child: CustomScrollView(
|
||||
controller: scrollController,
|
||||
physics: _controller.reachStart
|
||||
? const ClampingScrollPhysics()
|
||||
: const AlwaysScrollableScrollPhysics(
|
||||
parent: ClampingScrollPhysics(),
|
||||
),
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom:
|
||||
MediaQuery.paddingOf(context).bottom + 100,
|
||||
),
|
||||
sliver: SliverList.builder(
|
||||
itemCount: playlist.length,
|
||||
itemBuilder: (_, index) {
|
||||
if (index == playlist.length - 1) {
|
||||
_controller.loadNext(context);
|
||||
}
|
||||
final isCurr = index == _controller.index;
|
||||
final item = playlist[index];
|
||||
if (item.parts.length > 1) {
|
||||
final subId = _controller.subId.firstOrNull;
|
||||
return ExpansionTile(
|
||||
dense: true,
|
||||
minTileHeight: 45,
|
||||
initiallyExpanded: isCurr,
|
||||
collapsedIconColor: isCurr
|
||||
? colorScheme.primary
|
||||
: null,
|
||||
iconColor: isCurr
|
||||
? null
|
||||
: colorScheme.onSurfaceVariant,
|
||||
controlAffinity:
|
||||
ListTileControlAffinity.leading,
|
||||
title: Text(
|
||||
item.arc.title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: isCurr
|
||||
? TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
)
|
||||
: const TextStyle(fontSize: 14),
|
||||
),
|
||||
trailing: isCurr
|
||||
? null
|
||||
: iconButton(
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
if (index <
|
||||
_controller.index!) {
|
||||
_controller.index -= 1;
|
||||
}
|
||||
playlist.removeAt(index);
|
||||
(context as Element)
|
||||
.markNeedsBuild();
|
||||
},
|
||||
iconColor: colorScheme.outline,
|
||||
size: 28,
|
||||
iconSize: 18,
|
||||
),
|
||||
children: item.parts.map((e) {
|
||||
final isCurr = e.subId == subId;
|
||||
return ListTile(
|
||||
dense: true,
|
||||
minTileHeight: 45,
|
||||
contentPadding:
|
||||
const EdgeInsetsDirectional.only(
|
||||
start: 56.0,
|
||||
end: 24.0,
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
if (!isCurr) {
|
||||
_controller.playIndex(
|
||||
index,
|
||||
subId: [e.subId],
|
||||
);
|
||||
}
|
||||
},
|
||||
title: Text.rich(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: isCurr
|
||||
? TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
)
|
||||
: TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme
|
||||
.onSurfaceVariant,
|
||||
),
|
||||
TextSpan(
|
||||
children: [
|
||||
if (isCurr) ...[
|
||||
WidgetSpan(
|
||||
alignment: .bottom,
|
||||
child: Image.asset(
|
||||
'assets/images/live.gif',
|
||||
width: 16,
|
||||
height: 16,
|
||||
cacheWidth: 16.cacheSize(
|
||||
context,
|
||||
),
|
||||
color:
|
||||
colorScheme.primary,
|
||||
),
|
||||
),
|
||||
const TextSpan(text: ' '),
|
||||
],
|
||||
TextSpan(text: e.title),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
return ListTile(
|
||||
dense: true,
|
||||
minTileHeight: 45,
|
||||
onTap: () {
|
||||
Get.back();
|
||||
if (!isCurr) {
|
||||
_controller.playIndex(index);
|
||||
}
|
||||
},
|
||||
title: Text.rich(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: isCurr
|
||||
? TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
)
|
||||
: const TextStyle(fontSize: 14),
|
||||
TextSpan(
|
||||
children: [
|
||||
if (isCurr) ...[
|
||||
WidgetSpan(
|
||||
alignment: .bottom,
|
||||
child: Image.asset(
|
||||
'assets/images/live.gif',
|
||||
width: 16,
|
||||
height: 16,
|
||||
cacheWidth: 16.cacheSize(
|
||||
context,
|
||||
),
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
const TextSpan(text: ' '),
|
||||
],
|
||||
TextSpan(
|
||||
text: item.arc.title,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
trailing: isCurr
|
||||
? null
|
||||
: iconButton(
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
if (index < _controller.index!) {
|
||||
_controller.index -= 1;
|
||||
}
|
||||
playlist.removeAt(index);
|
||||
(context as Element)
|
||||
.markNeedsBuild();
|
||||
},
|
||||
iconColor: colorScheme.outline,
|
||||
size: 28,
|
||||
iconSize: 18,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
data: theme.copyWith(dividerColor: Colors.transparent),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user