Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-01-24 18:07:08 +08:00
parent 68872f7b14
commit e9b5cffa91
18 changed files with 326 additions and 366 deletions

View File

@@ -4,11 +4,9 @@
import 'dart:ui' show SemanticsRole;
import 'package:PiliPlus/common/widgets/flutter/page/page_view.dart';
import 'package:PiliPlus/common/widgets/gesture/horizontal_drag_gesture_recognizer.dart';
import 'package:flutter/foundation.dart' show clampDouble;
import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/material.dart' hide TabBarView, PageView;
import 'package:flutter/material.dart' hide TabBarView;
/// A page view that displays the widget which corresponds to the currently
/// selected tab.
@@ -357,7 +355,7 @@ class _CustomTabBarViewState extends State<CustomTabBarView> {
return NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: PageView<CustomHorizontalDragGestureRecognizer>(
child: PageView(
scrollDirection: widget.scrollDirection,
dragStartBehavior: widget.dragStartBehavior,
clipBehavior: widget.clipBehavior,
@@ -365,8 +363,6 @@ class _CustomTabBarViewState extends State<CustomTabBarView> {
physics: widget.physics == null
? const PageScrollPhysics().applyTo(const ClampingScrollPhysics())
: const PageScrollPhysics().applyTo(widget.physics),
horizontalDragGestureRecognizer:
CustomHorizontalDragGestureRecognizer(),
children: _childrenWithKey,
),
);

View File

@@ -26,7 +26,7 @@ class CustomHorizontalDragGestureRecognizer
globalDistanceMoved.abs(),
gestureSettings,
pointerDeviceKind,
_initialPosition!,
_initialPosition,
lastPosition.global,
);
}
@@ -38,7 +38,7 @@ bool _computeHitSlop(
double globalDistanceMoved,
DeviceGestureSettings? settings,
PointerDeviceKind kind,
Offset initialPosition,
Offset? initialPosition,
Offset lastPosition,
) {
switch (kind) {
@@ -49,13 +49,13 @@ bool _computeHitSlop(
case PointerDeviceKind.unknown:
case PointerDeviceKind.touch:
return globalDistanceMoved > touchSlopH &&
_cacl(initialPosition, lastPosition);
_calc(initialPosition!, lastPosition);
case PointerDeviceKind.trackpad:
return globalDistanceMoved > (settings?.touchSlop ?? kTouchSlop);
}
}
bool _cacl(Offset initialPosition, Offset lastPosition) {
bool _calc(Offset initialPosition, Offset lastPosition) {
final offset = lastPosition - initialPosition;
return offset.dx.abs() > offset.dy.abs() * 3;
}

View File

@@ -121,7 +121,7 @@ class CustomGridView extends StatelessWidget {
);
}
static BorderRadius borderRadius(
static BorderRadius _borderRadius(
int col,
int length,
int index, {
@@ -255,7 +255,7 @@ class CustomGridView extends StatelessWidget {
height: imageHeight,
children: List.generate(length, (index) {
final item = picArr[index];
final radius = borderRadius(column, length, index);
final borderRadius = _borderRadius(column, length, index);
return LayoutId(
id: index,
child: GestureDetector(
@@ -274,17 +274,14 @@ class CustomGridView extends StatelessWidget {
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
ClipRRect(
borderRadius: radius,
child: NetworkImgLayer(
type: .emote,
src: item.url,
width: imageWidth,
height: imageHeight,
alignment: item.isLongPic ? .topCenter : .center,
cacheWidth: item.width <= item.height,
getPlaceHolder: () => placeHolder,
),
NetworkImgLayer(
src: item.url,
width: imageWidth,
height: imageHeight,
borderRadius: borderRadius,
alignment: item.isLongPic ? .topCenter : .center,
cacheWidth: item.width <= item.height,
getPlaceHolder: () => placeHolder,
),
if (item.isLivePhoto)
const PBadge(

View File

@@ -239,6 +239,8 @@ class PageInfo {
final String? downloadTitle;
final String? downloadSubtitle;
bool get cacheWidth => width <= height;
PageInfo({
required this.cid,
required this.page,

View File

@@ -3,6 +3,7 @@ import 'package:PiliPlus/models_new/later/bangumi.dart';
import 'package:PiliPlus/models_new/later/page.dart';
import 'package:PiliPlus/models_new/later/rights.dart';
import 'package:PiliPlus/models_new/later/stat.dart';
import 'package:PiliPlus/models_new/video/video_detail/dimension.dart';
import 'package:PiliPlus/pages/common/multi_select/base.dart';
class LaterItemModel with MultiSelectData {
@@ -27,6 +28,7 @@ class LaterItemModel with MultiSelectData {
bool? isPugv;
int? seasonId;
bool? isCharging;
Dimension? dimension;
LaterItemModel({
this.aid,
@@ -50,6 +52,7 @@ class LaterItemModel with MultiSelectData {
this.isPugv,
this.seasonId,
this.isCharging,
this.dimension,
});
factory LaterItemModel.fromJson(Map<String, dynamic> json) => LaterItemModel(
@@ -89,5 +92,8 @@ class LaterItemModel with MultiSelectData {
isPugv: json['is_pugv'] as bool?,
seasonId: json['season_id'] as int?,
isCharging: json['charging_pay']?['level'] != null,
dimension: json['dimension'] == null
? null
: Dimension.fromJson(json['dimension'] as Map<String, dynamic>),
);
}

View File

@@ -2,6 +2,13 @@ class Dimension {
int? width;
int? height;
bool? get cacheWidth {
if (width != null && height != null) {
return width! <= height!;
}
return null;
}
Dimension({this.width, this.height});
factory Dimension.fromJson(Map<String, dynamic> json) => Dimension(

View File

@@ -175,17 +175,24 @@ class DetailItem extends StatelessWidget {
final cover = File(
path.join(entry.entryDirPath, PathUtils.coverName),
);
final maxWidth = constraints.maxWidth;
final maxHeight = constraints.maxHeight;
int? cacheWidth, cacheHeight;
if (entry.pageData?.cacheWidth ?? false) {
cacheWidth = maxWidth.cacheSize(context);
} else {
cacheHeight = maxHeight.cacheSize(context);
}
return cover.existsSync()
? ClipRRect(
borderRadius: StyleString.mdRadius,
child: Image.file(
cover,
width: constraints.maxWidth,
height: constraints.maxHeight,
width: maxWidth,
height: maxHeight,
fit: BoxFit.cover,
cacheHeight: constraints.maxWidth.cacheSize(
context,
),
cacheWidth: cacheWidth,
cacheHeight: cacheHeight,
colorBlendMode: NetworkImgLayer.reduce
? BlendMode.modulate
: null,
@@ -196,8 +203,9 @@ class DetailItem extends StatelessWidget {
)
: NetworkImgLayer(
src: entry.cover,
width: constraints.maxWidth,
height: constraints.maxHeight,
width: maxWidth,
height: maxHeight,
cacheWidth: entry.pageData?.cacheWidth,
);
},
),

View File

@@ -377,6 +377,7 @@ class _EpisodePanelState extends State<EpisodePanel>
int? view;
int? danmaku;
bool? isCharging;
bool? cacheWidth;
switch (episode) {
case Part part:
@@ -384,15 +385,21 @@ class _EpisodePanelState extends State<EpisodePanel>
title = part.part!;
duration = part.duration;
pubdate = part.ctime;
cacheWidth = part.dimension?.cacheWidth;
break;
case ugc.EpisodeItem item:
title = item.title!;
cover = item.arc?.pic;
bvid = item.bvid;
duration = item.arc?.duration;
pubdate = item.arc?.pubdate;
view = item.arc?.stat?.view;
danmaku = item.arc?.stat?.danmaku;
if (item.arc case final arc?) {
cover = arc.pic;
duration = arc.duration;
pubdate = arc.pubdate;
if (arc.stat case final stat?) {
view = stat.view;
danmaku = stat.danmaku;
}
cacheWidth = arc.dimension?.cacheWidth;
}
if (item.attribute == 8) {
isCharging = true;
}
@@ -408,6 +415,7 @@ class _EpisodePanelState extends State<EpisodePanel>
duration = item.duration == null ? null : item.duration! ~/ 1000;
}
pubdate = item.pubTime;
cacheWidth = item.dimension?.cacheWidth;
break;
}
late final Color primary = theme.colorScheme.primary;
@@ -468,6 +476,7 @@ class _EpisodePanelState extends State<EpisodePanel>
src: cover,
width: 140.8,
height: 88,
cacheWidth: cacheWidth,
),
if (duration != null && duration > 0)
PBadge(

View File

@@ -37,9 +37,9 @@ class _LaterPageState extends State<LaterPage>
);
}
final sortKey = GlobalKey();
final _sortKey = GlobalKey();
void listener() {
(sortKey.currentContext as Element?)?.markNeedsBuild();
(_sortKey.currentContext as Element?)?.markNeedsBuild();
}
@override
@@ -77,9 +77,7 @@ class _LaterPageState extends State<LaterPage>
appBar: _buildAppbar(enableMultiSelect),
floatingActionButtonLocation: const CustomFabLocation(),
floatingActionButton: Padding(
padding: const EdgeInsets.only(
right: kFloatingActionButtonMargin,
),
padding: const .only(right: kFloatingActionButtonMargin),
child: Obx(
() => currCtr().loadingState.value.isSuccess
? AnimatedSlide(
@@ -126,10 +124,8 @@ class _LaterPageState extends State<LaterPage>
onTap: (_) {
if (!_tabController.indexIsChanging) {
currCtr().scrollController.animToTop();
} else {
if (enableMultiSelect) {
currCtr(_tabController.previousIndex).handleSelect();
}
} else if (enableMultiSelect) {
currCtr(_tabController.previousIndex).handleSelect();
}
},
),
@@ -164,9 +160,7 @@ class _LaterPageState extends State<LaterPage>
ctr: currCtr(),
actions: [
TextButton(
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
),
style: TextButton.styleFrom(visualDensity: .compact),
onPressed: () {
final ctr = currCtr();
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
@@ -179,15 +173,11 @@ class _LaterPageState extends State<LaterPage>
},
child: Text(
'复制',
style: TextStyle(
color: theme.colorScheme.onSurfaceVariant,
),
style: TextStyle(color: theme.colorScheme.onSurfaceVariant),
),
),
TextButton(
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
),
style: TextButton.styleFrom(visualDensity: .compact),
onPressed: () {
final ctr = currCtr();
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
@@ -200,9 +190,7 @@ class _LaterPageState extends State<LaterPage>
},
child: Text(
'移动',
style: TextStyle(
color: theme.colorScheme.onSurfaceVariant,
),
style: TextStyle(color: theme.colorScheme.onSurfaceVariant),
),
),
],
@@ -226,113 +214,97 @@ class _LaterPageState extends State<LaterPage>
},
icon: const Icon(Icons.search),
),
Material(
clipBehavior: Clip.hardEdge,
type: MaterialType.transparency,
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: Builder(
key: sortKey,
builder: (context) {
final value = currCtr().asc.value;
return PopupMenuButton(
initialValue: value,
tooltip: '排序',
onSelected: (value) {
currCtr()
..asc.value = value
..onReload();
},
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
Builder(
key: _sortKey,
builder: (context) {
final value = currCtr().asc.value;
return PopupMenuButton(
initialValue: value,
tooltip: '排序',
onSelected: (value) => currCtr()
..asc.value = value
..onReload(),
borderRadius: const .all(.circular(20)),
child: Padding(
padding: const .symmetric(horizontal: 12, vertical: 6),
child: Text.rich(
style: TextStyle(fontSize: 14, height: 1, color: color),
strutStyle: const StrutStyle(
leading: 0,
height: 1,
fontSize: 14,
),
child: Text.rich(
style: TextStyle(fontSize: 14, height: 1, color: color),
strutStyle: const StrutStyle(
leading: 0,
height: 1,
fontSize: 14,
),
TextSpan(
children: [
TextSpan(text: value ? '最早添加' : '最近添加'),
WidgetSpan(
alignment: .middle,
child: Icon(
size: 14,
MdiIcons.unfoldMoreHorizontal,
color: color,
),
TextSpan(
children: [
TextSpan(text: value ? '最早添加' : '最近添加'),
WidgetSpan(
alignment: .middle,
child: Icon(
size: 14,
MdiIcons.unfoldMoreHorizontal,
color: color,
),
],
style: TextStyle(color: color),
),
),
],
style: TextStyle(color: color),
),
),
itemBuilder: (BuildContext context) => [
const PopupMenuItem(
value: false,
child: Text('最近添加'),
),
const PopupMenuItem(
value: true,
child: Text('最早添加'),
),
itemBuilder: (_) => [
const PopupMenuItem(
value: false,
child: Text('最近添加'),
),
const PopupMenuItem(
value: true,
child: Text('最早添加'),
),
],
);
},
),
PopupMenuButton(
tooltip: '清空',
borderRadius: const .all(.circular(20)),
child: Padding(
padding: const .symmetric(horizontal: 12, vertical: 6),
child: Text.rich(
style: TextStyle(fontSize: 14, height: 1, color: color),
strutStyle: const StrutStyle(
leading: 0,
height: 1,
fontSize: 14,
),
TextSpan(
children: [
const TextSpan(text: '清空'),
WidgetSpan(
alignment: .middle,
child: Icon(
size: 14,
MdiIcons.unfoldMoreHorizontal,
color: color,
),
),
],
);
},
),
),
Material(
clipBehavior: Clip.hardEdge,
type: MaterialType.transparency,
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: PopupMenuButton(
tooltip: '清空',
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
child: Text.rich(
style: TextStyle(fontSize: 14, height: 1, color: color),
strutStyle: const StrutStyle(
leading: 0,
height: 1,
fontSize: 14,
),
TextSpan(
children: [
const TextSpan(text: '清空'),
WidgetSpan(
alignment: .middle,
child: Icon(
size: 14,
MdiIcons.unfoldMoreHorizontal,
color: color,
),
),
],
style: TextStyle(color: color),
),
style: TextStyle(color: color),
),
),
itemBuilder: (BuildContext context) => [
PopupMenuItem(
onTap: () => currCtr().toViewClear(context, 1),
child: const Text('清空失效'),
),
PopupMenuItem(
onTap: () => currCtr().toViewClear(context, 2),
child: const Text('清空看完'),
),
PopupMenuItem(
onTap: () => currCtr().toViewClear(context),
child: const Text('清空全部'),
),
],
),
itemBuilder: (_) => [
PopupMenuItem(
onTap: () => currCtr().toViewClear(context, 1),
child: const Text('清空失效'),
),
PopupMenuItem(
onTap: () => currCtr().toViewClear(context, 2),
child: const Text('清空看完'),
),
PopupMenuItem(
onTap: () => currCtr().toViewClear(context),
child: const Text('清空全部'),
),
],
),
const SizedBox(width: 8),
],

View File

@@ -97,6 +97,7 @@ class VideoCardHLater extends StatelessWidget {
src: videoItem.pic,
width: maxWidth,
height: maxHeight,
cacheWidth: videoItem.dimension?.cacheWidth,
),
if (videoItem.isCharging == true)
const PBadge(

View File

@@ -48,17 +48,17 @@ class LiveController extends CommonListController with AccountMixin {
bool customHandleResponse(bool isRefresh, Success response) {
if (isRefresh) {
final res = response.response;
if (res case final LiveIndexData data) {
if (data.hasMore == 0) {
if (res is LiveIndexData) {
if (res.hasMore == 0) {
isEnd = true;
}
topState.value = Pair(
first: data.followItem,
second: data.areaItem,
first: res.followItem,
second: res.areaItem,
);
} else if (res case final LiveSecondData data) {
count = data.count;
newTags = data.newTags;
} else if (res is LiveSecondData) {
count = res.count;
newTags = res.newTags;
if (sortType != null) {
tagIndex.value =
newTags?.indexWhere((e) => e.sortType == sortType) ?? -1;

View File

@@ -95,43 +95,41 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
child: SizedBox(
// 10+14*textScaler
height: 10.0 + textScaler.scale(14),
child: ListView.separated(
scrollDirection: .horizontal,
padding: const .only(right: 8),
physics: const AlwaysScrollableScrollPhysics(),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, index) {
late final item = list[index - 1];
return Obx(
() {
final isCurr =
index == controller.areaIndex.value;
return SearchText(
fontSize: 14,
height: 1,
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 5,
),
text: index == 0 ? '推荐' : '${item.title}',
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: null,
onTap: (value) {
controller.onSelectArea(
index,
index == 0 ? null : item,
);
},
);
},
);
},
itemCount: list.length + 1,
),
child: Obx(() {
final areaIndex = controller.areaIndex.value;
return ListView.separated(
scrollDirection: .horizontal,
padding: const .only(right: 8),
physics: const AlwaysScrollableScrollPhysics(),
separatorBuilder: (_, _) =>
const SizedBox(width: 12),
itemBuilder: (context, index) {
final isFirst = index == 0;
late final item = list[index - 1];
final isCurr = index == areaIndex;
return SearchText(
fontSize: 14,
height: 1,
padding: const .symmetric(
horizontal: 8,
vertical: 5,
),
text: isFirst ? '推荐' : item.title!,
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: null,
onTap: (_) => controller.onSelectArea(
index,
isFirst ? null : item,
),
);
},
itemCount: list.length + 1,
);
}),
),
),
iconButton(
@@ -189,42 +187,34 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
child: SizedBox(
// 8+10+13*textScaler
height: 18.0 + textScaler.scale(13),
child: ListView.separated(
scrollDirection: .horizontal,
padding: const .only(bottom: 8),
separatorBuilder: (_, _) => const SizedBox(width: 12),
physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
late final item = newTags[index];
return Obx(
() {
final isCurr = index == controller.tagIndex.value;
return SearchText(
height: 1,
fontSize: 13,
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 5,
),
text: '${item.name}',
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: null,
onTap: (value) {
controller.onSelectTag(
index,
item.sortType,
);
},
);
},
);
},
itemCount: newTags.length,
),
child: Obx(() {
final tagIndex = controller.tagIndex.value;
return ListView.separated(
scrollDirection: .horizontal,
padding: const .only(bottom: 8),
separatorBuilder: (_, _) => const SizedBox(width: 12),
physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
final item = newTags[index];
final isCurr = index == tagIndex;
return SearchText(
height: 1,
fontSize: 13,
padding: const .symmetric(horizontal: 8, vertical: 5),
text: item.name!,
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: null,
onTap: (value) =>
controller.onSelectTag(index, item.sortType),
);
},
itemCount: newTags.length,
);
}),
),
),
response != null && response.isNotEmpty

View File

@@ -81,39 +81,31 @@ class _LiveAreaChildPageState extends State<LiveAreaChildPage>
slivers: [
if (_controller.newTags?.isNotEmpty == true)
SliverToBoxAdapter(
child: SelfSizedHorizontalList(
padding: const .only(bottom: 12),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, index) {
late final item = _controller.newTags![index];
return Obx(
() {
final isCurr = index == _controller.tagIndex.value;
return SearchText(
fontSize: 14,
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 3,
),
text: '${item.name}',
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: null,
onTap: (value) {
_controller.onSelectTag(
index,
item.sortType,
);
},
);
},
);
},
itemCount: _controller.newTags!.length,
),
child: Obx(() {
final tagIndex = _controller.tagIndex.value;
return SelfSizedHorizontalList(
padding: const .only(bottom: 12),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, index) {
final item = _controller.newTags![index];
final isCurr = index == tagIndex;
return SearchText(
fontSize: 14,
padding: const .symmetric(horizontal: 8, vertical: 3),
text: item.name!,
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: null,
onTap: (value) =>
_controller.onSelectTag(index, item.sortType),
);
},
itemCount: _controller.newTags!.length,
);
}),
),
response != null && response.isNotEmpty
? SliverGrid.builder(

View File

@@ -1,10 +1,8 @@
import 'dart:io';
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/flutter/page/page_view.dart';
import 'package:PiliPlus/common/widgets/flutter/pop_scope.dart';
import 'package:PiliPlus/common/widgets/flutter/tabs.dart';
import 'package:PiliPlus/common/widgets/gesture/horizontal_drag_gesture_recognizer.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/models/common/nav_bar_config.dart';
import 'package:PiliPlus/pages/home/view.dart';
@@ -20,7 +18,7 @@ import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart' hide PageView;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:tray_manager/tray_manager.dart';
@@ -395,11 +393,9 @@ class _MainAppState extends PopScopeState<MainApp>
children: _mainController.navigationBars.map((i) => i.page).toList(),
);
} else {
child = PageView<CustomHorizontalDragGestureRecognizer>(
child = PageView(
physics: const NeverScrollableScrollPhysics(),
controller: _mainController.controller,
horizontalDragGestureRecognizer:
CustomHorizontalDragGestureRecognizer(),
children: _mainController.navigationBars.map((i) => i.page).toList(),
);
}

View File

@@ -103,58 +103,45 @@ class _PgcIndexPageState extends State<PgcIndexPage>
ThemeData theme,
int index,
PgcIndexConditionData data,
item,
Object item,
Map<String, dynamic> indexParams,
) {
if (item case final PgcConditionOrder e) {
return Obx(
() {
final isCurr = _ctr.indexParams['order'] == e.field;
return SearchText(
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: theme.colorScheme.onSurfaceVariant,
text: e.name!,
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 3,
),
onTap: (_) => _ctr
..indexParams['order'] = e.field
..onReload(),
);
},
if (item is PgcConditionOrder) {
final isCurr = indexParams['order'] == item.field;
return SearchText(
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: theme.colorScheme.onSurfaceVariant,
text: item.name!,
padding: const .symmetric(horizontal: 6, vertical: 3),
onTap: (_) => _ctr
..indexParams['order'] = item.field
..onReload(),
);
}
if (item case final PgcConditionValue e) {
if (item is PgcConditionValue) {
final hasOrder = data.order?.isNotEmpty == true;
if (hasOrder) index -= 1;
final key = data.filter![index].field!;
return Obx(
() {
final isCurr = _ctr.indexParams[key] == e.keyword;
return SearchText(
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: theme.colorScheme.onSurfaceVariant,
text: e.name!,
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 3,
),
onTap: (_) => _ctr
..indexParams[key] = e.keyword
..onReload(),
);
},
final isCurr = indexParams[key] == item.keyword;
return SearchText(
bgColor: isCurr
? theme.colorScheme.secondaryContainer
: Colors.transparent,
textColor: isCurr
? theme.colorScheme.onSecondaryContainer
: theme.colorScheme.onSurfaceVariant,
text: item.name!,
padding: const .symmetric(horizontal: 6, vertical: 3),
onTap: (_) => _ctr
..indexParams[key] = item.keyword
..onReload(),
);
}
throw UnsupportedError('${item.runtimeType}');
throw UnsupportedError(item.runtimeType.toString());
}
Widget _buildSortsWidget(
@@ -179,16 +166,24 @@ class _PgcIndexPageState extends State<PgcIndexPage>
: data.filter![index - 1].values
: data.filter![index].values;
if (item != null && item.isNotEmpty) {
return SelfSizedHorizontalList(
padding: isFirst
? const .symmetric(horizontal: 12)
: const .fromLTRB(12, 10, 12, 0),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, childIndex) {
return _buildSortWidget(theme, index, data, item[childIndex]);
},
itemCount: item.length,
);
return Obx(() {
// ignore: invalid_use_of_protected_member
final indexParams = _ctr.indexParams.value;
return SelfSizedHorizontalList(
padding: isFirst
? const .symmetric(horizontal: 12)
: const .fromLTRB(12, 10, 12, 0),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, childIndex) => _buildSortWidget(
theme,
index,
data,
item[childIndex],
indexParams,
),
itemCount: item.length,
);
});
}
return const SizedBox.shrink();
},

View File

@@ -48,10 +48,11 @@ class _RankPageState extends State<RankPage>
width: 64,
child: Obx(() {
final tabIndex = _rankController.tabIndex.value;
return ListView(
return ListView.builder(
padding: .only(bottom: MediaQuery.paddingOf(context).bottom + 105),
children: RankType.values.map((e) {
final index = e.index;
itemCount: RankType.values.length,
itemBuilder: (context, index) {
final item = RankType.values[index];
final isCurr = index == tabIndex;
return IntrinsicHeight(
child: Material(
@@ -59,15 +60,11 @@ class _RankPageState extends State<RankPage>
? theme.colorScheme.onInverseSurface
: theme.colorScheme.surface,
child: InkWell(
onTap: () {
if (isCurr) {
_rankController.animateToTop();
} else {
_rankController
..tabIndex.value = index
..tabController.animateTo(index);
}
},
onTap: isCurr
? _rankController.animateToTop
: () => _rankController
..tabIndex.value = index
..tabController.animateTo(index),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
@@ -85,13 +82,13 @@ class _RankPageState extends State<RankPage>
alignment: Alignment.center,
padding: const .symmetric(vertical: 7),
child: Text(
RankType.values[index].label,
style: TextStyle(
color: isCurr
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
fontSize: 15,
),
item.label,
style: isCurr
? TextStyle(
fontSize: 15,
color: theme.colorScheme.primary,
)
: const TextStyle(fontSize: 15),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
@@ -102,7 +99,7 @@ class _RankPageState extends State<RankPage>
),
),
);
}).toList(),
},
);
}),
);

View File

@@ -332,9 +332,7 @@ class _DownloadPanelState extends State<DownloadPanel> {
int? cid;
String? cover;
int? width;
int? height;
bool cacheWidth = false;
bool? cacheWidth;
switch (episode) {
case Part part:
@@ -343,10 +341,7 @@ class _DownloadPanelState extends State<DownloadPanel> {
title = part.part ?? widget.videoDetail!.title!;
duration = part.duration;
pubdate = part.ctime;
if (part.dimension case final dimension?) {
width = dimension.width;
height = dimension.height;
}
cacheWidth = part.dimension?.cacheWidth;
break;
case ugc.EpisodeItem item:
cid = item.cid;
@@ -359,10 +354,7 @@ class _DownloadPanelState extends State<DownloadPanel> {
view = stat.view;
danmaku = stat.danmaku;
}
if (arc.dimension case final dimension?) {
width = dimension.width;
height = dimension.height;
}
cacheWidth = arc.dimension?.cacheWidth;
}
if (item.attribute == 8) {
isCharging = true;
@@ -379,15 +371,9 @@ class _DownloadPanelState extends State<DownloadPanel> {
duration = item.duration == null ? null : item.duration! ~/ 1000;
}
pubdate = item.pubTime;
if (item.dimension case final dimension?) {
width = dimension.width;
height = dimension.height;
}
cacheWidth = item.dimension?.cacheWidth;
break;
}
if (width != null && height != null) {
cacheWidth = width <= height;
}
late final primary = theme.colorScheme.primary;
return Padding(

View File

@@ -55,6 +55,7 @@ class _LocalIntroPanelState extends State<LocalIntroPanel>
) {
final outline = theme.colorScheme.outline;
final cover = File(path.join(entry.entryDirPath, PathUtils.coverName));
final cacheWidth = entry.pageData?.cacheWidth ?? false;
return Padding(
padding: const EdgeInsets.only(bottom: 2),
child: SizedBox(
@@ -87,7 +88,12 @@ class _LocalIntroPanelState extends State<LocalIntroPanel>
width: 140.8,
height: 88,
fit: BoxFit.cover,
cacheHeight: 140.8.cacheSize(context),
cacheWidth: cacheWidth
? 140.8.cacheSize(context)
: null,
cacheHeight: cacheWidth
? null
: 88.cacheSize(context),
colorBlendMode: NetworkImgLayer.reduce
? BlendMode.modulate
: null,