* opt: cache

* opt: MediaListPanel

* feat: nested replyreply panel

* tweaks

* opt: abstract class

* opt: PageStorageKey

* opt: contextExt

* opt: EpisodePanel

* opt

* opt: context instead GlobalKey

* feat: jump to reply

* refa: reply_reply

* fix: jump

* fix: index

* update

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt: keepalive

* reapply: nested replyreply

* mod: spacing

* opt: CommonSlidePageState

* fix drag bottomsheet

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt reply jump

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt reply2reply

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* tweaks

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* tweaks

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* reapply: jumpToReply

* fix: padding

* fix: anim

* fix some panels

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* opt: implements Scaffold

* opt: remove keepalive

* revert: GlobalKey

* tweaks

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

---------

Co-authored-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
My-Responsitories
2025-09-15 18:45:28 +08:00
committed by GitHub
parent b9a55ccbce
commit 37fb63c3b1
75 changed files with 6300 additions and 1140 deletions

View File

@@ -7,8 +7,11 @@ import 'package:PiliPlus/pages/video/reply_new/view.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/request_utils.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
import 'package:fixnum/fixnum.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'package:get/get_navigation/src/dialog/dialog_route.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
@@ -22,10 +25,8 @@ class VideoReplyReplyController extends ReplyController
required this.rpid,
required this.dialog,
required this.replyType,
required this.isDialogue,
});
final int? dialog;
final bool isDialogue;
int? id;
// 视频aid 请求时使用的oid
int oid;
@@ -34,12 +35,18 @@ class VideoReplyReplyController extends ReplyController
int replyType;
bool hasRoot = false;
late final Rx<ReplyInfo?> firstFloor = Rx<ReplyInfo?>(null);
final Rx<ReplyInfo?> firstFloor = Rx(null);
final index = RxnInt();
int? index;
AnimationController? animController;
final listController = ListController();
AnimationController? _controller;
AnimationController get animController => _controller ??= AnimationController(
duration: const Duration(milliseconds: 1000),
vsync: this,
);
late final horizontalPreview = Pref.horizontalPreview;
@override
@@ -54,7 +61,7 @@ class VideoReplyReplyController extends ReplyController
@override
List<ReplyInfo>? getDataList(response) {
return isDialogue ? response.replies : response.root.replies;
return dialog != null ? response.replies : response.root.replies;
}
@override
@@ -73,29 +80,7 @@ class VideoReplyReplyController extends ReplyController
firstFloor.value ??= data.root;
}
if (id != null) {
final id64 = Int64(id!);
final index = data.root.replies.indexWhere((item) => item.id == id64);
if (index != -1) {
this.index = index;
animController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
WidgetsBinding.instance.addPostFrameCallback((_) async {
try {
listController.jumpToItem(
index: index,
scrollController: scrollController,
alignment: 0.25,
);
await Future.delayed(
const Duration(milliseconds: 800),
animController?.forward,
);
this.index = null;
} catch (_) {}
});
}
setIndexById(Int64(id!), data.root.replies);
id = null;
}
}
@@ -103,8 +88,41 @@ class VideoReplyReplyController extends ReplyController
return false;
}
bool setIndexById(Int64 id64, [List<ReplyInfo>? replies]) {
final index = (replies ?? loadingState.value.data!).indexWhere(
(item) => item.id == id64,
);
if (index != -1) {
this.index.value = index;
jumpToItem(index);
return true;
}
return false;
}
ExtendedNestedScrollController? nestedController;
void jumpToItem(int index) {
SchedulerBinding.instance.addPostFrameCallback((_) {
animController.forward(from: 0);
try {
// ignore: invalid_use_of_visible_for_testing_member
final offset = listController.getOffsetToReveal(index, 0.25);
if (offset.isFinite) {
if (nestedController case final nestedController?) {
nestedController.nestedPositions.last.localJumpTo(offset);
} else {
scrollController.jumpTo(offset);
}
}
} catch (_) {
if (kDebugMode) rethrow;
}
});
}
@override
Future<LoadingState> customGetData() => isDialogue
Future<LoadingState> customGetData() => dialog != null
? ReplyGrpc.dialogList(
type: replyType,
oid: oid,
@@ -129,6 +147,14 @@ class VideoReplyReplyController extends ReplyController
onReload();
}
@override
Future<void> onReload() {
if (loadingState.value.isSuccess) {
index.value = null;
}
return super.onReload();
}
@override
void onReply(
BuildContext context, {
@@ -201,8 +227,8 @@ class VideoReplyReplyController extends ReplyController
@override
void onClose() {
animController?.dispose();
listController.dispose();
_controller?.dispose();
_controller = null;
super.dispose();
}
}