* opt: marquee

* fix: bangumi seek

* opt: post panel

* opt: remove deprecated code

* opt: singleton dynController

* fix: music scheme

* feat: MemberVideo jump keep position

* tweak
This commit is contained in:
My-Responsitories
2025-09-04 20:29:02 +08:00
committed by GitHub
parent e8a674ca2a
commit 172389b12b
51 changed files with 1314 additions and 1227 deletions

View File

@@ -3,84 +3,17 @@ import 'package:PiliPlus/grpc/reply.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/pages/common/reply_controller.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart' show ScrollDirection;
import 'package:get/get.dart';
abstract class CommonDynController extends ReplyController<MainListReply>
with GetSingleTickerProviderStateMixin {
abstract class CommonDynController extends ReplyController<MainListReply> {
int get oid;
int get replyType;
bool _showFab = true;
late final AnimationController fabAnimationCtr;
late final Animation<Offset> fabAnim;
late final RxBool showTitle = false.obs;
late final horizontalPreview = Pref.horizontalPreview;
late final List<double> ratio = Pref.dynamicDetailRatio;
final fabOffset = const Offset(0, 1);
@override
void onInit() {
fabAnimationCtr = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
fabAnim =
Tween<Offset>(
begin: fabOffset,
end: Offset.zero,
).animate(
CurvedAnimation(
parent: fabAnimationCtr,
curve: Curves.easeInOut,
),
);
fabAnimationCtr.forward();
scrollController.addListener(listener);
super.onInit();
}
void listener() {
showTitle.value = scrollController.positions.first.pixels > 55;
final ScrollDirection direction1 =
scrollController.positions.first.userScrollDirection;
late final ScrollDirection direction2 =
scrollController.positions.last.userScrollDirection;
if (direction1 == ScrollDirection.forward ||
direction2 == ScrollDirection.forward) {
showFab();
} else if (direction1 == ScrollDirection.reverse ||
direction2 == ScrollDirection.reverse) {
hideFab();
}
}
void showFab() {
if (!_showFab) {
_showFab = true;
fabAnimationCtr.forward();
}
}
void hideFab() {
if (_showFab) {
_showFab = false;
fabAnimationCtr.reverse();
}
}
@override
void onClose() {
fabAnimationCtr.dispose();
scrollController.removeListener(listener);
super.onClose();
}
@override
Future<LoadingState<MainListReply>> customGetData() => ReplyGrpc.mainList(
type: replyType,

View File

@@ -18,12 +18,15 @@ import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:get/get.dart' hide ContextExtensionss;
abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
with TickerProviderStateMixin {
CommonDynController get controller;
late final scrollController = ScrollController()..addListener(listener);
late final scaffoldKey = GlobalKey<ScaffoldState>();
bool get horizontalPreview => !isPortrait && controller.horizontalPreview;
@@ -35,6 +38,49 @@ abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
late bool isPortrait;
late double maxWidth;
bool _showFab = true;
final fabOffset = const Offset(0, 1);
late final AnimationController fabAnimationCtr = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
)..forward();
late final Animation<Offset> fabAnim = Tween<Offset>(
begin: fabOffset,
end: Offset.zero,
).animate(CurvedAnimation(parent: fabAnimationCtr, curve: Curves.easeInOut));
void listener() {
final pos = scrollController.positions;
controller.showTitle.value = pos.first.pixels > 55;
final direction1 = pos.first.userScrollDirection;
late final direction2 = pos.last.userScrollDirection;
if (direction1 == ScrollDirection.forward ||
direction2 == ScrollDirection.forward) {
showFab();
} else if (direction1 == ScrollDirection.reverse ||
direction2 == ScrollDirection.reverse) {
hideFab();
}
}
void showFab() {
if (!_showFab) {
_showFab = true;
fabAnimationCtr.forward();
}
}
void hideFab() {
if (_showFab) {
_showFab = false;
fabAnimationCtr.reverse();
}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
@@ -43,7 +89,7 @@ abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
isPortrait = size.isPortrait;
imageCallback = horizontalPreview
? (imgList, index) {
controller.hideFab();
hideFab();
PageUtils.onHorizontalPreview(
scaffoldKey,
this,
@@ -55,6 +101,12 @@ abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
padding = MediaQuery.viewPaddingOf(context);
}
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
Widget buildReplyHeader(ThemeData theme) {
final secondary = theme.colorScheme.secondary;
return SliverPersistentHeader(
@@ -220,7 +272,7 @@ abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
} else {
ScaffoldState? scaffoldState = Scaffold.maybeOf(context);
if (scaffoldState != null) {
controller.hideFab();
hideFab();
scaffoldState.showBottomSheet(
backgroundColor: Colors.transparent,
(context) => replyReplyPage(showBackBtn: false),