cache season fav state

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-12-19 23:31:08 +08:00
parent 5bcd822251
commit a0f3b3e442
11 changed files with 55 additions and 49 deletions

View File

@@ -77,7 +77,7 @@ class CustomGridView extends StatelessWidget {
final bool fullScreen;
static bool horizontalPreview = Pref.horizontalPreview;
static final _regex = RegExp(r'/(videoV|dynamicDetail)');
static const _routes = ['/videoV', '/dynamicDetail'];
void onTap(BuildContext context, int index) {
final imgList = picArr.map(
@@ -94,7 +94,7 @@ class CustomGridView extends StatelessWidget {
).toList();
if (horizontalPreview &&
!fullScreen &&
Get.currentRoute.startsWith(_regex) &&
_routes.contains(Get.currentRoute) &&
!context.mediaQuerySize.isPortrait) {
final scaffoldState = Scaffold.maybeOf(context);
if (scaffoldState != null) {

View File

@@ -169,14 +169,24 @@ class _EpisodePanelState extends State<EpisodePanel>
_isReversed = List.filled(widget.list.length, false);
if (widget.type == EpisodeType.season && Accounts.main.isLogin) {
_favState = LoadingState<bool>.loading().obs;
VideoHttp.videoRelation(bvid: widget.bvid).then(
(result) {
if (result case Success(:var response)) {
_favState!.value = Success(response.seasonFav ?? false);
}
},
);
final favState =
widget.ugcIntroController?.seasonFavState[widget.seasonId];
if (favState != null) {
_favState = Success(favState).obs;
} else {
_favState = LoadingState<bool>.loading().obs;
VideoHttp.videoRelation(bvid: widget.bvid).then(
(result) {
if (!mounted) return;
if (result case Success(:var response)) {
final seasonFav = response.seasonFav ?? false;
_favState!.value = Success(seasonFav);
widget.ugcIntroController?.seasonFavState[widget.seasonId] =
seasonFav;
}
},
);
}
}
}
@@ -588,6 +598,8 @@ class _EpisodePanelState extends State<EpisodePanel>
if (result.isSuccess) {
SmartDialog.showToast('${response ? '取消' : ''}订阅成功');
_favState!.value = Success(!response);
widget.ugcIntroController?.seasonFavState[widget.seasonId] =
!response;
} else {
result.toast();
}

View File

@@ -3,6 +3,7 @@ import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart';
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
import 'package:PiliPlus/common/widgets/scroll_physics.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/common/image_type.dart';
@@ -171,14 +172,7 @@ class _UpowerRankPageState extends State<UpowerRankPage>
) {
late final width = MediaQuery.textScalerOf(context).scale(32);
return switch (loadingState) {
Loading() => const SliverToBoxAdapter(
child: SizedBox(
height: 125,
child: Center(
child: CircularProgressIndicator(),
),
),
),
Loading() => linearLoading,
Success<List<UpowerRankInfo>?>(:var response) =>
response != null && response.isNotEmpty
? SliverList.builder(

View File

@@ -202,11 +202,11 @@ class _SharePanelState extends State<SharePanel> {
height: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: theme.colorScheme.secondaryContainer,
color: theme.colorScheme.onInverseSurface,
),
child: Icon(
Icons.person_add_alt,
color: theme.colorScheme.onSecondaryContainer,
color: theme.colorScheme.onSurfaceVariant,
),
),
),

View File

@@ -1657,6 +1657,10 @@ class VideoDetailController extends GetxController
@override
void onClose() {
cancelSkipTimer();
positionSubscription?.cancel();
positionSubscription = null;
cid.close();
if (isFileSource) {
cacheLocalProgress();
}

View File

@@ -64,6 +64,8 @@ class UgcIntroController extends CommonIntroController with ReloadMixin {
AiConclusionResult? aiConclusionResult;
late final Map<int?, bool> seasonFavState = {};
@override
void onInit() {
super.onInit();

View File

@@ -1,6 +1,7 @@
import 'dart:math' show pi;
import 'package:PiliPlus/utils/extension/theme_ext.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:flutter/material.dart';
class ActionItem extends StatelessWidget {
@@ -74,6 +75,9 @@ class ActionItem extends StatelessWidget {
borderRadius: const BorderRadius.all(Radius.circular(6)),
onTap: _isThumbsUp ? null : onTap,
onLongPress: _isThumbsUp ? null : onLongPress,
onSecondaryTap: PlatformUtils.isMobile || _isThumbsUp
? null
: onLongPress,
onTapDown: _isThumbsUp ? (_) => onStartTriple!() : null,
onTapUp: _isThumbsUp ? (_) => onCancelTriple!(true) : null,
onTapCancel: _isThumbsUp ? onCancelTriple : null,

View File

@@ -324,11 +324,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
?..removeStatusLister(playerListener)
..removePositionListener(positionListener);
videoDetailController
..cancelSkipTimer()
..positionSubscription?.cancel()
..cid.close()
..animController?.removeListener(animListener);
videoDetailController.animController?.removeListener(animListener);
Get.delete<HorizontalMemberPageController>(
tag: videoDetailController.heroTag,

View File

@@ -55,25 +55,6 @@ class _WhisperDetailPageState
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
leading: Center(
child: SizedBox(
width: 34,
height: 34,
child: IconButton(
tooltip: '返回',
style: IconButton.styleFrom(
padding: EdgeInsets.zero,
backgroundColor: theme.colorScheme.secondaryContainer,
),
onPressed: Get.back,
icon: Icon(
Icons.arrow_back_outlined,
size: 18,
color: theme.colorScheme.onSecondaryContainer,
),
),
),
),
title: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
@@ -118,18 +99,19 @@ class _WhisperDetailPageState
),
actions: [
IconButton(
tooltip: '设置',
onPressed: () => Get.to(
WhisperLinkSettingPage(
talkerUid: _whisperDetailController.talkerId,
),
),
icon: Icon(
size: 20,
size: 22,
Icons.settings,
color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.8),
),
),
const SizedBox(width: 10),
const SizedBox(width: 5),
],
),
body: Padding(

View File

@@ -1721,7 +1721,9 @@ class PlPlayerController {
disableAutoEnterPip();
setPlayCallBack(null);
dmState.clear();
_clearPreview();
if (showSeekPreview) {
_clearPreview();
}
Utils.channel.setMethodCallHandler(null);
_timer?.cancel();
_timerForSeek?.cancel();
@@ -1744,6 +1746,9 @@ class PlPlayerController {
}
await removeListeners();
subscriptions.clear();
_positionListeners.clear();
_statusListeners.clear();
if (playerStatus.playing) {
WakelockPlus.disable();
}
@@ -1779,7 +1784,7 @@ class PlPlayerController {
);
}
final Map<String, ui.Image?> previewCache = {};
late final Map<String, ui.Image?> previewCache = {};
LoadingState<VideoShotData>? videoShot;
late final RxBool showPreview = false.obs;
late final showSeekPreview = Pref.showSeekPreview;

View File

@@ -1846,6 +1846,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
plPlayerController,
maxWidth,
maxHeight,
() => mounted,
),
if (isFullScreen || plPlayerController.isDesktopPip) ...[
@@ -2537,6 +2538,7 @@ Widget buildSeekPreviewWidget(
PlPlayerController plPlayerController,
double maxWidth,
double maxHeight,
ValueGetter<bool> isMounted,
) {
return Obx(
() {
@@ -2591,6 +2593,7 @@ Widget buildSeekPreviewWidget(
onSetSize: (xSize, ySize) => data
..imgXSize = imgXSize = xSize
..imgYSize = imgYSize = ySize,
isMounted: isMounted,
),
);
},
@@ -2615,6 +2618,7 @@ class VideoShotImage extends StatefulWidget {
required this.imgYSize,
required this.height,
required this.onSetSize,
required this.isMounted,
});
final Map<String, ui.Image?> imageCache;
@@ -2625,6 +2629,7 @@ class VideoShotImage extends StatefulWidget {
final double imgYSize;
final double height;
final Function(double imgXSize, double imgYSize) onSetSize;
final ValueGetter<bool> isMounted;
@override
State<VideoShotImage> createState() => _VideoShotImageState();
@@ -2707,7 +2712,9 @@ class _VideoShotImageState extends State<VideoShotImage> {
widget.imageCache[url] = null;
_getImg(url).then((image) {
if (image != null) {
widget.imageCache[url] = image;
if (widget.isMounted()) {
widget.imageCache[url] = image;
}
if (mounted) {
_image = image;
_initSizeIfNeeded();