Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-07-30 13:53:37 +08:00
parent b5b15dbed6
commit c4c0852dea
105 changed files with 2063 additions and 1360 deletions

View File

@@ -5,6 +5,7 @@ import 'dart:ui';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/pair.dart';
import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
import 'package:PiliPlus/common/widgets/scaffold/mini_scaffold.dart';
import 'package:PiliPlus/grpc/bilibili/app/listener/v1.pbenum.dart'
show PlaylistSource;
import 'package:PiliPlus/grpc/dm.dart';
@@ -119,7 +120,7 @@ class VideoDetailController extends GetxController
final RxBool _autoPlay = Pref.autoPlayEnable.obs;
final videoPlayerKey = GlobalKey();
final childKey = GlobalKey<ScaffoldState>();
final childKey = GlobalKey<MiniScaffoldState>();
final plPlayerController = PlPlayerController.getInstance()
..brightness.value = -1;
@@ -503,7 +504,6 @@ class VideoDetailController extends GetxController
);
} else {
childKey.currentState?.showBottomSheet(
backgroundColor: Colors.transparent,
constraints: const BoxConstraints(),
(context) => panel(),
);
@@ -1008,7 +1008,6 @@ class VideoDetailController extends GetxController
);
} else {
childKey.currentState?.showBottomSheet(
backgroundColor: Colors.transparent,
constraints: const BoxConstraints(),
(context) => PostPanel(
videoDetailController: this,
@@ -1345,7 +1344,6 @@ class VideoDetailController extends GetxController
);
} else {
childKey.currentState?.showBottomSheet(
backgroundColor: Colors.transparent,
constraints: const BoxConstraints(),
(context) => NoteListPage(
oid: aid,

View File

@@ -2,6 +2,7 @@ import 'package:PiliPlus/common/skeleton/video_reply.dart';
import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/common/widgets/scaffold/mini_scaffold.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/common/image_type.dart';
import 'package:PiliPlus/models_new/video/video_note_list/list.dart';
@@ -55,8 +56,7 @@ class _NoteListPageState extends State<NoteListPage>
@override
Widget buildPage(ThemeData theme) {
return Scaffold(
resizeToAvoidBottomInset: false,
return MiniScaffold(
body: Column(
children: [
SizedBox(
@@ -153,7 +153,7 @@ class _NoteListPageState extends State<NoteListPage>
SmartDialog.showToast('账号未登录');
return;
}
Scaffold.of(context).showBottomSheet(
MiniScaffold.of(context).showBottomSheet(
constraints: const BoxConstraints(),
(context) => WebviewPage(
oid: widget.oid,

View File

@@ -4,6 +4,7 @@ import 'dart:math';
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
import 'package:PiliPlus/common/widgets/pair.dart';
import 'package:PiliPlus/common/widgets/scaffold/simple_scaffold.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/sponsor_block.dart';
import 'package:PiliPlus/models/common/sponsor_block/action_type.dart';
@@ -186,10 +187,11 @@ class _PostPanelState extends State<PostPanel>
double currentPos() => plPlayerController.positionInMilliseconds / 1000;
late double bottom;
@override
Widget buildPage(ThemeData theme) {
return Scaffold(
resizeToAvoidBottomInset: false,
return SimpleScaffold(
appBar: AppBar(
primary: false,
toolbarHeight: 45,
@@ -230,6 +232,37 @@ class _PostPanelState extends State<PostPanel>
],
),
body: enableSlide ? slideList(theme) : buildList(theme),
fab: list.isEmpty
? null
: Padding(
padding: .only(
right: kFloatingActionButtonMargin,
bottom: kFloatingActionButtonMargin + bottom,
),
child: FloatingActionButton(
tooltip: '提交',
onPressed: () => showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('确定无误再提交'),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'取消',
style: TextStyle(color: theme.colorScheme.outline),
),
),
TextButton(
onPressed: _onPost,
child: const Text('确定提交'),
),
],
),
),
child: const Icon(Icons.check),
),
),
);
}
@@ -240,6 +273,7 @@ class _PostPanelState extends State<PostPanel>
super.didChangeDependencies();
final controller = PrimaryScrollController.of(context);
_key = ValueKey(controller.hashCode);
bottom = MediaQuery.viewPaddingOf(context).bottom;
}
@override
@@ -247,47 +281,14 @@ class _PostPanelState extends State<PostPanel>
if (list.isEmpty) {
return scrollableError;
}
final bottom = MediaQuery.viewPaddingOf(context).bottom;
return Stack(
clipBehavior: Clip.none,
children: [
ListView.builder(
key: _key,
physics: const AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.only(bottom: 88 + bottom),
itemCount: list.length,
itemBuilder: (context, index) {
return _buildItem(theme, index, list[index]);
},
),
Positioned(
right: kFloatingActionButtonMargin,
bottom: kFloatingActionButtonMargin + bottom,
child: FloatingActionButton(
tooltip: '提交',
onPressed: () => showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('确定无误再提交'),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'取消',
style: TextStyle(color: theme.colorScheme.outline),
),
),
TextButton(
onPressed: _onPost,
child: const Text('确定提交'),
),
],
),
),
child: const Icon(Icons.check),
),
),
],
return ListView.builder(
key: _key,
physics: const AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.only(bottom: 88 + bottom),
itemCount: list.length,
itemBuilder: (context, index) {
return _buildItem(theme, index, list[index]);
},
);
}

View File

@@ -2,6 +2,8 @@ import 'package:PiliPlus/common/skeleton/video_reply.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/common/widgets/scaffold/mini_scaffold.dart';
import 'package:PiliPlus/common/widgets/scaffold/simple_scaffold.dart';
import 'package:PiliPlus/common/widgets/sliver/sliver_floating_header.dart';
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
show ReplyInfo;
@@ -71,80 +73,73 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
child: refreshIndicator(
onRefresh: _videoReplyController.onRefresh,
isClampingScrollPhysics: widget.isNested,
child: Stack(
clipBehavior: .none,
children: [
CustomScrollView(
controller: widget.isNested
? null
: _videoReplyController.scrollController,
physics: const AlwaysScrollableScrollPhysics(),
key: const PageStorageKey(_VideoReplyPanelState),
slivers: [
SliverFloatingHeaderWidget(
backgroundColor: colorScheme.surface,
child: Padding(
padding: const .fromLTRB(12, 2.5, 6, 2.5),
child: Obx(() {
final sortType = _videoReplyController.sortType.value;
return Row(
mainAxisAlignment: .spaceBetween,
children: [
Text(
sortType.title,
style: const TextStyle(fontSize: 13),
child: ScaffoldLayout(
body: CustomScrollView(
controller: widget.isNested
? null
: _videoReplyController.scrollController,
physics: const AlwaysScrollableScrollPhysics(),
key: const PageStorageKey(_VideoReplyPanelState),
slivers: [
SliverFloatingHeaderWidget(
backgroundColor: colorScheme.surface,
child: Padding(
padding: const .fromLTRB(12, 2.5, 6, 2.5),
child: Obx(() {
final sortType = _videoReplyController.sortType.value;
return Row(
mainAxisAlignment: .spaceBetween,
children: [
Text(
sortType.title,
style: const TextStyle(fontSize: 13),
),
TextButton.icon(
style: Style.buttonStyle,
onPressed: _videoReplyController.queryBySort,
icon: Icon(
Icons.sort,
size: 16,
color: colorScheme.secondary,
),
TextButton.icon(
style: Style.buttonStyle,
onPressed: _videoReplyController.queryBySort,
icon: Icon(
Icons.sort,
size: 16,
label: Text(
sortType.label,
style: TextStyle(
fontSize: 13,
color: colorScheme.secondary,
),
label: Text(
sortType.label,
style: TextStyle(
fontSize: 13,
color: colorScheme.secondary,
),
),
),
],
);
}),
),
),
Obx(() => _buildBody(_videoReplyController.loadingState.value)),
],
),
Positioned(
right: 0,
bottom: 0,
child: SlideTransition(
position: fabAnimation,
child: Padding(
padding: .only(
right: kFloatingActionButtonMargin,
bottom: kFloatingActionButtonMargin + bottom,
),
child: FloatingActionButton(
heroTag: null,
onPressed: () {
feedBack();
_videoReplyController.onReply(
null,
oid: _videoReplyController.aid,
replyType: _videoReplyController.videoType.replyType,
);
},
tooltip: '发表评论',
child: const Icon(Icons.reply),
),
),
],
);
}),
),
),
Obx(() => _buildBody(_videoReplyController.loadingState.value)),
],
),
fab: SlideTransition(
position: fabAnimation,
child: Padding(
padding: .only(
right: kFloatingActionButtonMargin,
bottom: kFloatingActionButtonMargin + bottom,
),
child: FloatingActionButton(
heroTag: null,
onPressed: () {
feedBack();
_videoReplyController.onReply(
null,
oid: _videoReplyController.aid,
replyType: _videoReplyController.videoType.replyType,
);
},
tooltip: '发表评论',
child: const Icon(Icons.reply),
),
),
],
),
),
),
);
@@ -239,8 +234,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
EasyThrottle.throttle('replyReply', const Duration(milliseconds: 500), () {
int oid = replyItem.oid.toInt();
int rpid = replyItem.id.toInt();
Scaffold.of(context).showBottomSheet(
backgroundColor: Colors.transparent,
MiniScaffold.of(context).showBottomSheet(
constraints: const BoxConstraints(),
(context) => VideoReplyReplyPanel(
id: id,

View File

@@ -3,6 +3,9 @@ import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/colored_box_transition.dart';
import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/common/widgets/scaffold/mini_scaffold.dart';
import 'package:PiliPlus/common/widgets/scaffold/simple_scaffold.dart';
import 'package:PiliPlus/common/widgets/simple_colored_box.dart';
import 'package:PiliPlus/common/widgets/sliver/sliver_pinned_header.dart';
import 'package:PiliPlus/common/widgets/view_safe_area.dart';
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
@@ -65,8 +68,7 @@ class VideoReplyReplyPanel extends CommonSlidePage {
'type': type,
'enterUri': ?uri?.toString(), // save panel
},
() => Scaffold(
resizeToAvoidBottomInset: false,
() => SimpleScaffold(
appBar: AppBar(
title: const Text('评论详情'),
actions: [
@@ -140,38 +142,40 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
@override
Widget buildPage(ThemeData theme) {
Widget child() => enableSlide ? slideList(theme) : buildList(theme);
return Scaffold(
resizeToAvoidBottomInset: false,
body: widget.isVideoDetail
? Column(
children: [
Container(
height: 45,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1,
color: theme.dividerColor.withValues(alpha: 0.1),
return SimpleColoredBox(
color: theme.canvasColor,
child: MiniScaffold(
body: widget.isVideoDetail
? Column(
children: [
Container(
height: 45,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1,
color: theme.dividerColor.withValues(alpha: 0.1),
),
),
),
padding: const EdgeInsets.only(left: 12, right: 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(isDialogue ? '对话列表' : '评论详情'),
IconButton(
tooltip: '关闭',
icon: const Icon(Icons.close, size: 20),
onPressed: Get.back,
),
],
),
),
padding: const EdgeInsets.only(left: 12, right: 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(isDialogue ? '对话列表' : '评论详情'),
IconButton(
tooltip: '关闭',
icon: const Icon(Icons.close, size: 20),
onPressed: Get.back,
),
],
),
),
Expanded(child: child()),
],
)
: child(),
Expanded(child: child()),
],
)
: child(),
),
);
}
@@ -335,8 +339,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
onReply: (replyItem) => _controller.onReply(replyItem, index: index),
onDelete: (item, subIndex) => _controller.onRemove(index, item, null),
upMid: _controller.upMid,
showDialogue: () => Scaffold.of(context).showBottomSheet(
backgroundColor: Colors.transparent,
showDialogue: () => MiniScaffold.of(context).showBottomSheet(
constraints: const BoxConstraints(),
(context) => VideoReplyReplyPanel(
oid: replyItem.oid.toInt(),

View File

@@ -1,3 +1,4 @@
import 'package:PiliPlus/common/widgets/scaffold/simple_scaffold.dart';
import 'package:PiliPlus/common/widgets/scroll_physics.dart' show tabBarView;
import 'package:PiliPlus/common/widgets/view_safe_area.dart';
import 'package:PiliPlus/models/common/reply/reply_search_type.dart';
@@ -35,8 +36,7 @@ class _ReplySearchPageState extends State<ReplySearchPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
return SimpleScaffold(
appBar: AppBar(
actions: [
IconButton(

View File

@@ -8,6 +8,8 @@ import 'package:PiliPlus/common/widgets/flutter/pop_scope.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/route_aware_mixin.dart';
import 'package:PiliPlus/common/widgets/scaffold/mini_scaffold.dart';
import 'package:PiliPlus/common/widgets/scaffold/simple_scaffold.dart';
import 'package:PiliPlus/common/widgets/scroll_behavior.dart'
show NoOverscrollIndicator;
import 'package:PiliPlus/common/widgets/scroll_physics.dart'
@@ -486,38 +488,32 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
return Obx(
() {
final isFullScreen = this.isFullScreen;
return Scaffold(
resizeToAvoidBottomInset: false,
return SimpleScaffold(
appBar: removeAppBar(isFullScreen)
? null
: PreferredSize(
preferredSize: const .fromHeight(0),
child: Obx(
() {
final scrollRatio =
videoDetailController.scrollRatio.value;
Brightness? statusBarIconBrightness;
if (Platform.isAndroid) {
statusBarIconBrightness =
isPortrait && scrollRatio >= 0.5
? colorScheme.brightness.reverse
: .light;
}
final backgroundColor = isPortrait && scrollRatio > 0
? Color.lerp(
Colors.black,
colorScheme.surface,
scrollRatio,
)!
: Colors.black;
return SimpleAppBar(
height: padding.top,
backgroundColor: backgroundColor,
brightness: colorScheme.brightness,
statusBarIconBrightness: statusBarIconBrightness,
);
},
),
: Obx(
() {
final scrollRatio = videoDetailController.scrollRatio.value;
Brightness? statusBarIconBrightness;
if (Platform.isAndroid) {
statusBarIconBrightness = isPortrait && scrollRatio >= 0.5
? colorScheme.brightness.reverse
: .light;
}
final backgroundColor = isPortrait && scrollRatio > 0
? Color.lerp(
Colors.black,
colorScheme.surface,
scrollRatio,
)!
: Colors.black;
return SimpleAppBar(
height: padding.top,
backgroundColor: backgroundColor,
brightness: colorScheme.brightness,
statusBarIconBrightness: statusBarIconBrightness,
);
},
),
body: ExtendedNestedScrollView(
onlyOneScrollInBody: true,
@@ -578,10 +574,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
),
];
},
body: Scaffold(
body: MiniScaffold(
key: videoDetailController.childKey,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
children: [
buildTabBar(onTap: videoDetailController.animToTop),
@@ -752,16 +746,12 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
Widget get childWhenDisabledLandscape => Obx(
() {
final isFullScreen = this.isFullScreen;
return Scaffold(
resizeToAvoidBottomInset: false,
return SimpleScaffold(
appBar: removeAppBar(isFullScreen)
? null
: PreferredSize(
preferredSize: const .fromHeight(0),
child: SimpleAppBar(
height: padding.top,
brightness: colorScheme.brightness,
),
: SimpleAppBar(
height: padding.top,
brightness: colorScheme.brightness,
),
body: Padding(
padding: isFullScreen
@@ -794,10 +784,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
child: SizedBox(
width: introWidth,
height: maxHeight - padding.top,
child: Scaffold(
child: MiniScaffold(
key: videoDetailController.childKey,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -860,10 +848,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
child: SizedBox(
width: introWidth,
height: introHeight,
child: Scaffold(
child: MiniScaffold(
key: videoDetailController.childKey,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
children: [
buildTabBar(showIntro: false),
@@ -944,10 +930,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
child: SizedBox(
width: maxWidth - width - padding.horizontal,
height: maxHeight - padding.top,
child: Scaffold(
child: MiniScaffold(
key: videoDetailController.childKey,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -993,16 +977,12 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
Widget get childWhenDisabledAlmostSquare => Obx(() {
final isFullScreen = this.isFullScreen;
return Scaffold(
resizeToAvoidBottomInset: false,
return SimpleScaffold(
appBar: removeAppBar(isFullScreen)
? null
: PreferredSize(
preferredSize: const .fromHeight(0),
child: SimpleAppBar(
height: padding.top,
brightness: colorScheme.brightness,
),
: SimpleAppBar(
height: padding.top,
brightness: colorScheme.brightness,
),
body: Padding(
padding: isFullScreen
@@ -1052,10 +1032,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
child: SizedBox(
width: maxWidth - padding.horizontal,
height: bottomHeight,
child: Scaffold(
child: MiniScaffold(
key: videoDetailController.childKey,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -1090,10 +1068,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
);
}
Widget get manualPlayerWidget => Obx(() {
Widget manualPlayerWidget(double height) => Obx(() {
if (!videoDetailController.autoPlay) {
return Stack(
clipBehavior: Clip.none,
children: [
Positioned(
top: 0,
@@ -1156,12 +1133,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
),
Positioned(
right: 12,
bottom: 10,
child: IconButton(
tooltip: '播放',
onPressed: handlePlay,
icon: const PlayIcon(),
),
top: height - 70,
child: const PlayIcon(),
),
],
);
@@ -1498,7 +1471,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
}
return const SizedBox.shrink();
}),
manualPlayerWidget,
manualPlayerWidget(height),
if (videoDetailController.plPlayerController.enableBlock ||
videoDetailController.continuePlayingPart)
@@ -1863,7 +1836,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
// ai总结
void showAiBottomSheet() {
videoDetailController.childKey.currentState?.showBottomSheet(
backgroundColor: Colors.transparent,
constraints: const BoxConstraints(),
(context) =>
AiConclusionPanel(item: ugcIntroController.aiConclusionResult!),
@@ -1875,7 +1847,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
List<VideoTagItem>? videoTags,
) {
videoDetailController.childKey.currentState?.showBottomSheet(
backgroundColor: Colors.transparent,
constraints: const BoxConstraints(),
(context) => PgcIntroPanel(
item: videoDetail,
@@ -1946,7 +1917,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
);
} else {
videoDetailController.childKey.currentState?.showBottomSheet(
backgroundColor: Colors.transparent,
constraints: const BoxConstraints(),
(context) => listSheetContent(),
);
@@ -2027,7 +1997,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
);
} else {
videoDetailController.childKey.currentState?.showBottomSheet(
backgroundColor: Colors.transparent,
constraints: const BoxConstraints(),
(context) => ViewPointsPage(
videoDetailController: videoDetailController,
@@ -2039,7 +2008,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
void onShowMemberPage(int? mid) {
videoDetailController.childKey.currentState?.showBottomSheet(
shape: const RoundedRectangleBorder(),
constraints: const BoxConstraints(),
(context) {
return HorizontalMemberPage(

View File

@@ -2,6 +2,7 @@ import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
import 'package:PiliPlus/common/widgets/scaffold/simple_scaffold.dart';
import 'package:PiliPlus/pages/common/slide/common_slide_page.dart';
import 'package:PiliPlus/pages/video/controller.dart';
import 'package:PiliPlus/plugin/pl_player/controller.dart';
@@ -34,8 +35,7 @@ class _ViewPointsPageState extends State<ViewPointsPage>
@override
Widget buildPage(ThemeData theme) {
return Scaffold(
resizeToAvoidBottomInset: false,
return SimpleScaffold(
appBar: AppBar(
primary: false,
automaticallyImplyLeading: false,