Files
PiliPlus/lib/pages/pgc_review/view.dart
dom 855b35e1dc opt tabbar
Signed-off-by: dom <githubaccount56556@proton.me>
2026-06-23 12:00:50 +08:00

164 lines
5.4 KiB
Dart

import 'package:PiliPlus/models/common/pgc_review_type.dart';
import 'package:PiliPlus/pages/pgc_review/child/controller.dart';
import 'package:PiliPlus/pages/pgc_review/child/view.dart';
import 'package:PiliPlus/pages/pgc_review/post/view.dart';
import 'package:PiliPlus/pages/webview/view.dart';
import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
import 'package:PiliPlus/utils/extension/theme_ext.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class PgcReviewPage extends StatefulWidget {
const PgcReviewPage({
super.key,
required this.name,
required this.mediaId,
});
final String name;
final dynamic mediaId;
@override
State<PgcReviewPage> createState() => _PgcReviewPageState();
}
class _PgcReviewPageState extends State<PgcReviewPage>
with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
late final TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(
length: PgcReviewType.values.length,
vsync: this,
);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
final theme = Theme.of(context);
return Stack(
clipBehavior: Clip.none,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TabBar(
dividerHeight: 0,
indicatorWeight: 0,
isScrollable: true,
indicatorSize: .tab,
tabAlignment: .start,
controller: _tabController,
padding: const .only(left: 6),
dividerColor: Colors.transparent,
splashFactory: NoSplash.splashFactory,
indicatorPadding: const .symmetric(horizontal: 3, vertical: 8),
overlayColor: const WidgetStatePropertyAll(Colors.transparent),
indicator: BoxDecoration(
borderRadius: const .all(.circular(20)),
color: theme.colorScheme.secondaryContainer,
),
labelColor: theme.colorScheme.onSecondaryContainer,
unselectedLabelColor: theme.colorScheme.outline,
labelStyle: const TextStyle(fontSize: 13),
tabs: PgcReviewType.values
.map((e) => Tab(text: e.label))
.toList(),
onTap: (index) {
try {
if (!_tabController.indexIsChanging) {
final item = PgcReviewType.values[index];
Get.find<PgcReviewController>(
tag: '${widget.mediaId}${item.name}',
).scrollController.animToTop();
}
} catch (_) {}
},
),
Expanded(
child: TabBarView(
controller: _tabController,
physics: const NeverScrollableScrollPhysics(),
children: PgcReviewType.values
.map(
(e) => PgcReviewChildPage(
type: e,
name: widget.name,
mediaId: widget.mediaId,
),
)
.toList(),
),
),
],
),
Positioned(
right: kFloatingActionButtonMargin,
bottom:
MediaQuery.viewPaddingOf(context).bottom +
kFloatingActionButtonMargin,
child: FloatingActionButton(
onPressed: () => showDialog(
context: context,
builder: (context) => AlertDialog(
clipBehavior: Clip.hardEdge,
contentPadding: const EdgeInsets.symmetric(vertical: 12),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
dense: true,
title: const Text(
'写短评',
style: TextStyle(fontSize: 14),
),
onTap: () {
Get.back();
showModalBottomSheet(
context: context,
useSafeArea: true,
isScrollControlled: true,
builder: (context) {
return PgcReviewPostPanel(
name: widget.name,
mediaId: widget.mediaId,
);
},
);
},
),
ListTile(
dense: true,
title: const Text(
'写长评',
style: TextStyle(fontSize: 14),
),
onTap: () => WebViewPage.toWebView(
'https://member.bilibili.com/article-text/mobile?theme=${theme.isDark ? 1 : 0}&media_id=${widget.mediaId}',
getBack: true,
),
),
],
),
),
),
child: const Icon(Icons.edit),
),
),
],
);
}
@override
bool get wantKeepAlive => true;
}