mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: get theme color
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -35,9 +35,6 @@ class _AboutPageState extends State<AboutPage> {
|
||||
|
||||
late int _pressCount = 0;
|
||||
|
||||
late Color outline;
|
||||
late TextStyle subTitleStyle;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -56,16 +53,11 @@ class _AboutPageState extends State<AboutPage> {
|
||||
currentVersion.value = "${currentInfo.version}+$buildNumber";
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
outline = Theme.of(context).colorScheme.outline;
|
||||
subTitleStyle =
|
||||
TextStyle(fontSize: 13, color: Theme.of(context).colorScheme.outline);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final outline = theme.colorScheme.outline;
|
||||
final subTitleStyle = TextStyle(fontSize: 13, color: outline);
|
||||
return Scaffold(
|
||||
appBar:
|
||||
widget.showAppBar == false ? null : AppBar(title: const Text('关于')),
|
||||
@@ -107,8 +99,7 @@ class _AboutPageState extends State<AboutPage> {
|
||||
title: Text(
|
||||
'PiliPlus',
|
||||
textAlign: TextAlign.center,
|
||||
style:
|
||||
Theme.of(context).textTheme.titleMedium!.copyWith(height: 2),
|
||||
style: theme.textTheme.titleMedium!.copyWith(height: 2),
|
||||
),
|
||||
subtitle: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@@ -153,7 +144,7 @@ Commit Hash: ${BuildConfig.commitHash}''',
|
||||
Divider(
|
||||
thickness: 1,
|
||||
height: 30,
|
||||
color: Theme.of(context).colorScheme.outlineVariant,
|
||||
color: theme.colorScheme.outlineVariant,
|
||||
),
|
||||
ListTile(
|
||||
onTap: () => PageUtils.launchURL(_sourceCodeUrl),
|
||||
|
||||
@@ -227,6 +227,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: _buildAppBar,
|
||||
@@ -249,18 +250,16 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
controller: _articleCtr.scrollController,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
_buildContent(maxWidth),
|
||||
_buildContent(theme, maxWidth),
|
||||
SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
thickness: 8,
|
||||
color: Theme.of(context)
|
||||
.dividerColor
|
||||
.withOpacity(0.05),
|
||||
color: theme.dividerColor.withOpacity(0.05),
|
||||
),
|
||||
),
|
||||
_buildReplyHeader,
|
||||
Obx(() =>
|
||||
_buildReplyList(_articleCtr.loadingState.value)),
|
||||
Obx(() => _buildReplyList(
|
||||
theme, _articleCtr.loadingState.value)),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -286,7 +285,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
MediaQuery.paddingOf(context).bottom +
|
||||
80,
|
||||
),
|
||||
sliver: _buildContent(maxWidth),
|
||||
sliver: _buildContent(theme, maxWidth),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -295,7 +294,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
),
|
||||
VerticalDivider(
|
||||
thickness: 8,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.05),
|
||||
color: theme.dividerColor.withOpacity(0.05),
|
||||
),
|
||||
Expanded(
|
||||
flex: _ratio[1].toInt(),
|
||||
@@ -314,7 +313,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
slivers: [
|
||||
_buildReplyHeader,
|
||||
Obx(() => _buildReplyList(
|
||||
_articleCtr.loadingState.value)),
|
||||
theme, _articleCtr.loadingState.value)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -327,13 +326,13 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
},
|
||||
),
|
||||
),
|
||||
_buildBottom,
|
||||
_buildBottom(theme),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContent(double maxWidth) => SliverPadding(
|
||||
Widget _buildContent(ThemeData theme, double maxWidth) => SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
sliver: Obx(
|
||||
() {
|
||||
@@ -401,22 +400,17 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
Text(
|
||||
_articleCtr.summary.author?.name ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
.fontSize,
|
||||
fontSize:
|
||||
theme.textTheme.titleSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
if (pubTime != null)
|
||||
Text(
|
||||
Utils.dateFormat(pubTime),
|
||||
style: TextStyle(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline,
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize:
|
||||
theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -436,7 +430,8 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildReplyList(LoadingState<List<ReplyInfo>?> loadingState) {
|
||||
Widget _buildReplyList(
|
||||
ThemeData theme, LoadingState<List<ReplyInfo>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemCount: 12,
|
||||
@@ -463,7 +458,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
: '没有更多了',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -663,7 +658,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
],
|
||||
);
|
||||
|
||||
Widget get _buildBottom => Positioned(
|
||||
Widget _buildBottom(ThemeData theme) => Positioned(
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
@@ -711,8 +706,8 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
}) {
|
||||
final show = stat?.status == true;
|
||||
final color = show
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline;
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline;
|
||||
return TextButton.icon(
|
||||
onPressed: callback,
|
||||
icon: Icon(
|
||||
@@ -723,8 +718,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.outline,
|
||||
foregroundColor: theme.colorScheme.outline,
|
||||
),
|
||||
label: Text(stat?.count != null
|
||||
? Utils.numFormat(stat!.count)
|
||||
@@ -749,13 +743,10 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
_articleCtr.stats.value != null
|
||||
? Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.surface,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
color: theme.colorScheme.outline
|
||||
.withOpacity(0.08),
|
||||
),
|
||||
),
|
||||
@@ -858,12 +849,8 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
color: _articleCtr.stats.value
|
||||
?.like?.status ==
|
||||
true
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
semanticLabel: _articleCtr
|
||||
.stats
|
||||
.value
|
||||
@@ -877,9 +864,8 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 15),
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
foregroundColor:
|
||||
theme.colorScheme.outline,
|
||||
),
|
||||
label: AnimatedSwitcher(
|
||||
duration: const Duration(
|
||||
@@ -902,12 +888,10 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
color: _articleCtr.stats.value
|
||||
?.like?.status ==
|
||||
true
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
? theme
|
||||
.colorScheme.primary
|
||||
: theme
|
||||
.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -179,7 +179,7 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData t = Theme.of(context);
|
||||
final ThemeData theme = Theme.of(context);
|
||||
bool isLandscape =
|
||||
MediaQuery.of(context).orientation == Orientation.landscape;
|
||||
return SliverPadding(
|
||||
@@ -282,12 +282,12 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
foregroundColor:
|
||||
bangumiIntroController
|
||||
.isFollowed.value
|
||||
? t.colorScheme.outline
|
||||
? theme.colorScheme.outline
|
||||
: null,
|
||||
backgroundColor:
|
||||
bangumiIntroController
|
||||
.isFollowed.value
|
||||
? t.colorScheme
|
||||
? theme.colorScheme
|
||||
.onInverseSurface
|
||||
: null,
|
||||
),
|
||||
@@ -353,28 +353,32 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
if (isLandscape) ...[
|
||||
const SizedBox(width: 6),
|
||||
AreasAndPubTime(
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
t: t),
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
theme: theme,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
NewEpDesc(
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
t: t),
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
theme: theme,
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
SizedBox(height: isLandscape ? 2 : 6),
|
||||
if (!isLandscape)
|
||||
AreasAndPubTime(
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
t: t),
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
theme: theme,
|
||||
),
|
||||
if (!isLandscape)
|
||||
NewEpDesc(
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
t: t),
|
||||
widget: widget,
|
||||
bangumiItem: bangumiItem,
|
||||
theme: theme,
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'简介:${!widget.isLoading ? widget.bangumiDetail!.evaluate! : bangumiItem!.evaluate!}',
|
||||
@@ -382,7 +386,7 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: t.colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -394,7 +398,7 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
// 点赞收藏转发 布局样式2
|
||||
actionGrid(context, bangumiIntroController),
|
||||
actionGrid(theme, bangumiIntroController),
|
||||
// 番剧分p
|
||||
if ((!widget.isLoading &&
|
||||
widget.bangumiDetail!.episodes!.isNotEmpty) ||
|
||||
@@ -427,115 +431,111 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
||||
}
|
||||
|
||||
Widget actionGrid(
|
||||
BuildContext context, BangumiIntroController bangumiIntroController) {
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Material(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 1),
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
|
||||
onTap: () =>
|
||||
handleState(bangumiIntroController.actionLikeVideo),
|
||||
onLongPress: bangumiIntroController.actionOneThree,
|
||||
selectStatus: bangumiIntroController.hasLike.value,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '点赞',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['likes']!)
|
||||
: Utils.numFormat(
|
||||
bangumiItem!.stat!['likes']!,
|
||||
),
|
||||
needAnim: true,
|
||||
hasTriple: bangumiIntroController.hasLike.value &&
|
||||
bangumiIntroController.hasCoin &&
|
||||
bangumiIntroController.hasFav.value,
|
||||
callBack: (start) {
|
||||
if (start) {
|
||||
HapticFeedback.lightImpact();
|
||||
_coinKey.currentState?.controller?.forward();
|
||||
_favKey.currentState?.controller?.forward();
|
||||
} else {
|
||||
_coinKey.currentState?.controller?.reverse();
|
||||
_favKey.currentState?.controller?.reverse();
|
||||
}
|
||||
},
|
||||
),
|
||||
ThemeData theme, BangumiIntroController bangumiIntroController) {
|
||||
return Material(
|
||||
color: theme.colorScheme.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 1),
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
|
||||
onTap: () =>
|
||||
handleState(bangumiIntroController.actionLikeVideo),
|
||||
onLongPress: bangumiIntroController.actionOneThree,
|
||||
selectStatus: bangumiIntroController.hasLike.value,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '点赞',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['likes']!)
|
||||
: Utils.numFormat(
|
||||
bangumiItem!.stat!['likes']!,
|
||||
),
|
||||
needAnim: true,
|
||||
hasTriple: bangumiIntroController.hasLike.value &&
|
||||
bangumiIntroController.hasCoin &&
|
||||
bangumiIntroController.hasFav.value,
|
||||
callBack: (start) {
|
||||
if (start) {
|
||||
HapticFeedback.lightImpact();
|
||||
_coinKey.currentState?.controller?.forward();
|
||||
_favKey.currentState?.controller?.forward();
|
||||
} else {
|
||||
_coinKey.currentState?.controller?.reverse();
|
||||
_favKey.currentState?.controller?.reverse();
|
||||
}
|
||||
},
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _coinKey,
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
selectIcon: const Icon(FontAwesomeIcons.b),
|
||||
onTap: () =>
|
||||
handleState(bangumiIntroController.actionCoinVideo),
|
||||
selectStatus: bangumiIntroController.hasCoin,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '投币',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!)
|
||||
: Utils.numFormat(
|
||||
bangumiItem!.stat!['coins']!,
|
||||
),
|
||||
needAnim: true,
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _coinKey,
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
selectIcon: const Icon(FontAwesomeIcons.b),
|
||||
onTap: () =>
|
||||
handleState(bangumiIntroController.actionCoinVideo),
|
||||
selectStatus: bangumiIntroController.hasCoin,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '投币',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!)
|
||||
: Utils.numFormat(
|
||||
bangumiItem!.stat!['coins']!,
|
||||
),
|
||||
needAnim: true,
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _favKey,
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
onTap: () =>
|
||||
bangumiIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => bangumiIntroController
|
||||
.showFavBottomSheet(context, type: 'longPress'),
|
||||
selectStatus: bangumiIntroController.hasFav.value,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '收藏',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(
|
||||
widget.bangumiDetail!.stat!['favorite']!)
|
||||
: Utils.numFormat(
|
||||
bangumiItem!.stat!['favorite']!,
|
||||
),
|
||||
needAnim: true,
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _favKey,
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
onTap: () =>
|
||||
bangumiIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => bangumiIntroController
|
||||
.showFavBottomSheet(context, type: 'longPress'),
|
||||
selectStatus: bangumiIntroController.hasFav.value,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '收藏',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(
|
||||
widget.bangumiDetail!.stat!['favorite']!)
|
||||
: Utils.numFormat(
|
||||
bangumiItem!.stat!['favorite']!,
|
||||
),
|
||||
needAnim: true,
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
selectIcon: const Icon(FontAwesomeIcons.reply),
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
selectIcon: const Icon(FontAwesomeIcons.reply),
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '评论',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['reply']!),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
onTap: () => bangumiIntroController.actionShareVideo(context),
|
||||
selectStatus: false,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '评论',
|
||||
semanticsLabel: '转发',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['reply']!),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
onTap: () =>
|
||||
bangumiIntroController.actionShareVideo(context),
|
||||
selectStatus: false,
|
||||
loadingStatus: false,
|
||||
semanticsLabel: '转发',
|
||||
text: !widget.isLoading
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['share']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['share']!)),
|
||||
],
|
||||
),
|
||||
? Utils.numFormat(widget.bangumiDetail!.stat!['share']!)
|
||||
: Utils.numFormat(bangumiItem!.stat!['share']!)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget actionRow(
|
||||
@@ -609,12 +609,12 @@ class AreasAndPubTime extends StatelessWidget {
|
||||
super.key,
|
||||
required this.widget,
|
||||
required this.bangumiItem,
|
||||
required this.t,
|
||||
required this.theme,
|
||||
});
|
||||
|
||||
final BangumiInfo widget;
|
||||
final BangumiInfoModel? bangumiItem;
|
||||
final ThemeData t;
|
||||
final ThemeData theme;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -630,7 +630,7 @@ class AreasAndPubTime extends StatelessWidget {
|
||||
: ''),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: t.colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
@@ -640,7 +640,7 @@ class AreasAndPubTime extends StatelessWidget {
|
||||
: bangumiItem!.publish!['pub_time_show'],
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: t.colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -653,12 +653,12 @@ class NewEpDesc extends StatelessWidget {
|
||||
super.key,
|
||||
required this.widget,
|
||||
required this.bangumiItem,
|
||||
required this.t,
|
||||
required this.theme,
|
||||
});
|
||||
|
||||
final BangumiInfo widget;
|
||||
final BangumiInfoModel? bangumiItem;
|
||||
final ThemeData t;
|
||||
final ThemeData theme;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -668,7 +668,7 @@ class NewEpDesc extends StatelessWidget {
|
||||
: bangumiItem!.newEp!['desc'],
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: t.colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,15 +22,10 @@ class IntroDetail extends CommonCollapseSlidePage {
|
||||
}
|
||||
|
||||
class _IntroDetailState extends CommonCollapseSlidePageState<IntroDetail> {
|
||||
late final TextStyle smallTitle = TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget get buildPage {
|
||||
Widget buildPage(ThemeData theme) {
|
||||
return Material(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.surface,
|
||||
child: Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
@@ -44,16 +39,14 @@ class _IntroDetailState extends CommonCollapseSlidePageState<IntroDetail> {
|
||||
width: 32,
|
||||
height: 3,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
.withOpacity(0.5),
|
||||
color:
|
||||
theme.colorScheme.onSecondaryContainer.withOpacity(0.5),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: enableSlide ? slideList() : buildList,
|
||||
child: enableSlide ? slideList(theme) : buildList(theme),
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -61,98 +54,104 @@ class _IntroDetailState extends CommonCollapseSlidePageState<IntroDetail> {
|
||||
}
|
||||
|
||||
@override
|
||||
Widget get buildList => ListView(
|
||||
controller: ScrollController(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: EdgeInsets.only(
|
||||
left: 14,
|
||||
right: 14,
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
Widget buildList(ThemeData theme) {
|
||||
final TextStyle smallTitle = TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.onSurface,
|
||||
);
|
||||
return ListView(
|
||||
controller: ScrollController(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: EdgeInsets.only(
|
||||
left: 14,
|
||||
right: 14,
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
children: [
|
||||
SelectableText(
|
||||
widget.bangumiDetail.title!,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
children: [
|
||||
SelectableText(
|
||||
widget.bangumiDetail.title!,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(widget.bangumiDetail.stat!['views']),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(widget.bangumiDetail.stat!['danmakus']),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(widget.bangumiDetail.stat!['views']),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(widget.bangumiDetail.stat!['danmakus']),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
widget.bangumiDetail.areas!.first['name'],
|
||||
style: smallTitle,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
widget.bangumiDetail.publish!['pub_time_show'],
|
||||
style: smallTitle,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
widget.bangumiDetail.newEp!['desc'],
|
||||
style: smallTitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'简介:',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SelectableText(
|
||||
widget.bangumiDetail.evaluate!,
|
||||
style: smallTitle.copyWith(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'声优:',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SelectableText(
|
||||
widget.bangumiDetail.actors!,
|
||||
style: smallTitle.copyWith(fontSize: 14),
|
||||
),
|
||||
if (widget.videoTags is List && widget.videoTags.isNotEmpty) ...[
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: (widget.videoTags as List)
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
fontSize: 13,
|
||||
text: item['tag_name'],
|
||||
onTap: (_) => Get.toNamed(
|
||||
'/searchResult',
|
||||
parameters: {
|
||||
'keyword': item['tag_name'],
|
||||
},
|
||||
),
|
||||
onLongPress: (_) => Utils.copyText(item['tag_name']),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
widget.bangumiDetail.areas!.first['name'],
|
||||
style: smallTitle,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
widget.bangumiDetail.publish!['pub_time_show'],
|
||||
style: smallTitle,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
widget.bangumiDetail.newEp!['desc'],
|
||||
style: smallTitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'简介:',
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SelectableText(
|
||||
widget.bangumiDetail.evaluate!,
|
||||
style: smallTitle.copyWith(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'声优:',
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SelectableText(
|
||||
widget.bangumiDetail.actors!,
|
||||
style: smallTitle.copyWith(fontSize: 14),
|
||||
),
|
||||
if (widget.videoTags is List && widget.videoTags.isNotEmpty) ...[
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: (widget.videoTags as List)
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
fontSize: 13,
|
||||
text: item['tag_name'],
|
||||
onTap: (_) => Get.toNamed(
|
||||
'/searchResult',
|
||||
parameters: {
|
||||
'keyword': item['tag_name'],
|
||||
},
|
||||
),
|
||||
onLongPress: (_) => Utils.copyText(item['tag_name']),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
)
|
||||
],
|
||||
);
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,15 +35,16 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return widget.indexType == null
|
||||
? Scaffold(
|
||||
appBar: AppBar(title: const Text('索引')),
|
||||
body: Obx(() => _buildBody(_ctr.conditionState.value)),
|
||||
body: Obx(() => _buildBody(theme, _ctr.conditionState.value)),
|
||||
)
|
||||
: Obx(() => _buildBody(_ctr.conditionState.value));
|
||||
: Obx(() => _buildBody(theme, _ctr.conditionState.value));
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState loadingState) {
|
||||
Widget _buildBody(ThemeData theme, LoadingState loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => loadingWidget,
|
||||
Success() => Builder(builder: (context) {
|
||||
@@ -63,8 +64,8 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
alignment: Alignment.topCenter,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: count > 5
|
||||
? Obx(() => _buildSortWidget(count, data))
|
||||
: _buildSortWidget(count, data),
|
||||
? Obx(() => _buildSortWidget(theme, count, data))
|
||||
: _buildSortWidget(theme, count, data),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
@@ -90,7 +91,7 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
};
|
||||
}
|
||||
|
||||
Widget _buildSortWidget(count, data) => Column(
|
||||
Widget _buildSortWidget(ThemeData theme, count, data) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -129,9 +130,7 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
(item[childIndex] is Order
|
||||
? item[childIndex].field
|
||||
: item[childIndex].keyword)
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: Colors.transparent,
|
||||
textColor: (item[childIndex] is Order
|
||||
? _ctr.indexParams['order']
|
||||
@@ -144,12 +143,8 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
(item[childIndex] is Order
|
||||
? item[childIndex].field
|
||||
: item[childIndex].keyword)
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: theme.colorScheme.onSurfaceVariant,
|
||||
text: item[childIndex].name,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
@@ -192,14 +187,14 @@ class _PgcIndexPageState extends State<PgcIndexPage>
|
||||
Text(
|
||||
_ctr.isExpand.value ? '收起' : '展开',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
_ctr.isExpand.value
|
||||
? Icons.keyboard_arrow_up
|
||||
: Icons.keyboard_arrow_down,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -46,6 +46,7 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final ThemeData theme = Theme.of(context);
|
||||
return refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.onRefresh();
|
||||
@@ -54,17 +55,17 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
controller: controller.scrollController,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
_buildFollow,
|
||||
_buildFollow(theme),
|
||||
if (controller.showPgcTimeline)
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: Grid.smallCardWidth / 2 / 0.75 +
|
||||
MediaQuery.textScalerOf(context).scale(96),
|
||||
child:
|
||||
Obx(() => _buildTimeline(controller.timelineState.value)),
|
||||
child: Obx(() =>
|
||||
_buildTimeline(theme, controller.timelineState.value)),
|
||||
),
|
||||
),
|
||||
..._buildRcmd,
|
||||
..._buildRcmd(theme),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -80,7 +81,8 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
'日',
|
||||
];
|
||||
|
||||
Widget _buildTimeline(LoadingState<List<Result>?> loadingState) =>
|
||||
Widget _buildTimeline(
|
||||
ThemeData theme, LoadingState<List<Result>?> loadingState) =>
|
||||
switch (loadingState) {
|
||||
Loading() => loadingWidget,
|
||||
Success() => loadingState.response?.isNotEmpty == true
|
||||
@@ -99,7 +101,7 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
'追番时间表',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
@@ -118,16 +120,13 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
vertical: 10,
|
||||
),
|
||||
indicator: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(20)),
|
||||
),
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
labelColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer,
|
||||
labelColor:
|
||||
theme.colorScheme.onSecondaryContainer,
|
||||
labelStyle: TabBarTheme.of(context)
|
||||
.labelStyle
|
||||
?.copyWith(fontSize: 14) ??
|
||||
@@ -200,8 +199,8 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
),
|
||||
};
|
||||
|
||||
List<Widget> get _buildRcmd => [
|
||||
_buildRcmdTitle,
|
||||
List<Widget> _buildRcmd(ThemeData theme) => [
|
||||
_buildRcmdTitle(theme),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
StyleString.safeSpace, 0, StyleString.safeSpace, 0),
|
||||
@@ -211,7 +210,7 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
),
|
||||
];
|
||||
|
||||
Widget get _buildRcmdTitle => SliverToBoxAdapter(
|
||||
Widget _buildRcmdTitle(ThemeData theme) => SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
@@ -224,7 +223,7 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
children: [
|
||||
Text(
|
||||
'推荐',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
@@ -279,12 +278,12 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.chevron_right,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -332,12 +331,12 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
};
|
||||
}
|
||||
|
||||
Widget get _buildFollow => SliverToBoxAdapter(
|
||||
Widget _buildFollow(ThemeData theme) => SliverToBoxAdapter(
|
||||
child: Obx(
|
||||
() => controller.isLogin.value
|
||||
? Column(
|
||||
children: [
|
||||
_buildFollowTitle,
|
||||
_buildFollowTitle(theme),
|
||||
SizedBox(
|
||||
height: Grid.smallCardWidth / 2 / 0.75 +
|
||||
MediaQuery.textScalerOf(context).scale(50),
|
||||
@@ -351,14 +350,14 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _buildFollowTitle => Padding(
|
||||
Widget _buildFollowTitle(ThemeData theme) => Padding(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => Text(
|
||||
'最近${widget.tabType == TabType.bangumi ? '追番' : '追剧'}${controller.followCount.value == -1 ? '' : ' ${controller.followCount.value}'}',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
@@ -398,13 +397,12 @@ class _BangumiPageState extends CommonPageState<BangumiPage, BangumiController>
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.chevron_right,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -23,7 +23,6 @@ class BangumiCardV extends StatelessWidget {
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: bangumiItem.title,
|
||||
cover: bangumiItem.cover,
|
||||
),
|
||||
@@ -88,6 +87,11 @@ class BangumiCardV extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget bagumiContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
final style = TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
);
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(4, 5, 0, 3),
|
||||
@@ -108,19 +112,13 @@ class BangumiCardV extends StatelessWidget {
|
||||
Text(
|
||||
bangumiItem.indexShow,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
style: style,
|
||||
),
|
||||
if (bangumiItem.progress != null)
|
||||
Text(
|
||||
bangumiItem.progress,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
style: style,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -27,7 +27,6 @@ class BangumiCardVMemberHome extends StatelessWidget {
|
||||
PageUtils.viewBangumi(seasonId: seasonId);
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: bangumiItem.title,
|
||||
cover: bangumiItem.cover,
|
||||
),
|
||||
|
||||
@@ -21,7 +21,6 @@ class BangumiCardVPgcIndex extends StatelessWidget {
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: bangumiItem['title'],
|
||||
cover: bangumiItem['cover'],
|
||||
),
|
||||
@@ -73,6 +72,7 @@ class BangumiCardVPgcIndex extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget bagumiContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(4, 5, 0, 3),
|
||||
@@ -94,8 +94,8 @@ class BangumiCardVPgcIndex extends StatelessWidget {
|
||||
bangumiItem['index_show'],
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -22,7 +22,6 @@ class BangumiCardVSearch extends StatelessWidget {
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: item.title?.map((e) => e['text']).join(),
|
||||
cover: item.cover,
|
||||
),
|
||||
|
||||
@@ -22,7 +22,6 @@ class BangumiCardVTimeline extends StatelessWidget {
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
),
|
||||
@@ -71,6 +70,7 @@ class BangumiCardVTimeline extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget bagumiContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(4, 5, 0, 3),
|
||||
@@ -90,8 +90,8 @@ class BangumiCardVTimeline extends StatelessWidget {
|
||||
item.pubIndex ?? '',
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -81,6 +81,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
@@ -95,7 +96,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -140,7 +141,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
right: index == widget.pages.length - 1 ? 0 : 10,
|
||||
),
|
||||
child: Material(
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
@@ -169,7 +170,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
if (index == currentIndex) ...<Widget>[
|
||||
Image.asset(
|
||||
'assets/images/live.png',
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
height: 12,
|
||||
semanticLabel: "正在播放:",
|
||||
),
|
||||
@@ -185,10 +186,8 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: index == currentIndex
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface),
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface),
|
||||
)),
|
||||
const SizedBox(width: 2),
|
||||
if (item.badge != null) ...[
|
||||
@@ -205,8 +204,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
item.badge!,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color:
|
||||
Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -222,10 +220,8 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: index == currentIndex
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface),
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)
|
||||
]
|
||||
|
||||
@@ -275,6 +275,9 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
|
||||
}
|
||||
|
||||
Widget buildImage(int index, double height) {
|
||||
final color =
|
||||
Theme.of(context).colorScheme.secondaryContainer.withOpacity(0.5);
|
||||
|
||||
void onClear() {
|
||||
pathList.removeAt(index);
|
||||
if (pathList.isEmpty && editController.text.trim().isEmpty) {
|
||||
@@ -319,10 +322,7 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
|
||||
},
|
||||
size: 24,
|
||||
iconSize: 14,
|
||||
bgColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer
|
||||
.withOpacity(0.5),
|
||||
bgColor: color,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
@@ -334,10 +334,7 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
|
||||
onPressed: onClear,
|
||||
size: 24,
|
||||
iconSize: 14,
|
||||
bgColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer
|
||||
.withOpacity(0.5),
|
||||
bgColor: color,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -345,14 +342,14 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
|
||||
}
|
||||
|
||||
void onCropImage(int index) async {
|
||||
final theme = Theme.of(context);
|
||||
CroppedFile? croppedFile = await ImageCropper().cropImage(
|
||||
sourcePath: pathList[index],
|
||||
uiSettings: [
|
||||
AndroidUiSettings(
|
||||
toolbarTitle: '裁剪',
|
||||
toolbarColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||
toolbarWidgetColor:
|
||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
toolbarColor: theme.colorScheme.secondaryContainer,
|
||||
toolbarWidgetColor: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
IOSUiSettings(
|
||||
title: '裁剪',
|
||||
|
||||
@@ -19,19 +19,20 @@ abstract class CommonSlidePageState<T extends CommonSlidePage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return enableSlide
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(top: padding),
|
||||
child: buildPage,
|
||||
child: buildPage(theme),
|
||||
)
|
||||
: buildPage;
|
||||
: buildPage(theme);
|
||||
}
|
||||
|
||||
Widget get buildPage;
|
||||
Widget buildPage(ThemeData theme);
|
||||
|
||||
Widget get buildList => throw UnimplementedError();
|
||||
Widget buildList(ThemeData theme) => throw UnimplementedError();
|
||||
|
||||
Widget slideList([Widget? buildList]) => GestureDetector(
|
||||
Widget slideList(ThemeData theme, [Widget? buildList]) => GestureDetector(
|
||||
onPanDown: (event) {
|
||||
if (event.localPosition.dx > 30) {
|
||||
isSliding = false;
|
||||
@@ -86,6 +87,6 @@ abstract class CommonSlidePageState<T extends CommonSlidePage>
|
||||
downPos = null;
|
||||
isSliding = null;
|
||||
},
|
||||
child: buildList ?? this.buildList,
|
||||
child: buildList ?? this.buildList(theme),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,10 +36,11 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: _buildAppBar,
|
||||
appBar: _buildAppBar(theme),
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -65,16 +66,16 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildReplyOptionWidget,
|
||||
_buildReplyOptionWidget(theme),
|
||||
const SizedBox(height: 5),
|
||||
_buildPrivateWidget,
|
||||
_buildPrivateWidget(theme),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
_buildImageList,
|
||||
_buildImageList(theme),
|
||||
const SizedBox(height: 2),
|
||||
],
|
||||
),
|
||||
@@ -86,7 +87,7 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildImageList => Obx(
|
||||
Widget _buildImageList(ThemeData theme) => Obx(
|
||||
() => SizedBox(
|
||||
height: 100,
|
||||
child: ListView.separated(
|
||||
@@ -114,7 +115,7 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
),
|
||||
child: Center(child: Icon(Icons.add, size: 35)),
|
||||
),
|
||||
@@ -129,7 +130,7 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
),
|
||||
);
|
||||
|
||||
PreferredSizeWidget get _buildAppBar => PreferredSize(
|
||||
PreferredSizeWidget _buildAppBar(ThemeData theme) => PreferredSize(
|
||||
preferredSize: Size.fromHeight(66),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -147,9 +148,7 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: WidgetStateProperty.resolveWith(
|
||||
(states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer;
|
||||
return theme.colorScheme.secondaryContainer;
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -157,7 +156,7 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
icon: Icon(
|
||||
Icons.arrow_back_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
color: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -193,127 +192,124 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _buildPrivateWidget => PopupMenuButton(
|
||||
initialValue: _isPrivate,
|
||||
onOpened: controller.keepChatPanel,
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
_isPrivate = value;
|
||||
});
|
||||
},
|
||||
itemBuilder: (context) => List.generate(
|
||||
2,
|
||||
(index) => PopupMenuItem<bool>(
|
||||
enabled: _publishTime != null && index == 1 ? false : true,
|
||||
value: index == 0 ? false : true,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
index == 0 ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(index == 0 ? '所有人可见' : '仅自己可见'),
|
||||
],
|
||||
Widget _buildPrivateWidget(ThemeData theme) {
|
||||
final color =
|
||||
_isPrivate ? theme.colorScheme.error : theme.colorScheme.secondary;
|
||||
return PopupMenuButton(
|
||||
initialValue: _isPrivate,
|
||||
onOpened: controller.keepChatPanel,
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
_isPrivate = value;
|
||||
});
|
||||
},
|
||||
itemBuilder: (context) => List.generate(
|
||||
2,
|
||||
(index) => PopupMenuItem<bool>(
|
||||
enabled: _publishTime != null && index == 1 ? false : true,
|
||||
value: index == 0 ? false : true,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
index == 0 ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(index == 0 ? '所有人可见' : '仅自己可见'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
_isPrivate ? Icons.visibility_off : Icons.visibility,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_isPrivate ? '仅自己可见' : '所有人可见',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: color,
|
||||
),
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
),
|
||||
Icon(
|
||||
size: 20,
|
||||
Icons.keyboard_arrow_right,
|
||||
color: color,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
_isPrivate ? Icons.visibility_off : Icons.visibility,
|
||||
color: _isPrivate
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_isPrivate ? '仅自己可见' : '所有人可见',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: _isPrivate
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
),
|
||||
Icon(
|
||||
size: 20,
|
||||
Icons.keyboard_arrow_right,
|
||||
color: _isPrivate
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildReplyOptionWidget => PopupMenuButton(
|
||||
initialValue: _replyOption,
|
||||
onOpened: controller.keepChatPanel,
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
_replyOption = item;
|
||||
});
|
||||
},
|
||||
itemBuilder: (context) => ReplyOption.values
|
||||
.map(
|
||||
(item) => PopupMenuItem<ReplyOption>(
|
||||
value: item,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
item.iconData,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(item.title),
|
||||
],
|
||||
),
|
||||
Widget _buildReplyOptionWidget(ThemeData theme) {
|
||||
final color = _replyOption == ReplyOption.close
|
||||
? theme.colorScheme.error
|
||||
: theme.colorScheme.secondary;
|
||||
return PopupMenuButton(
|
||||
initialValue: _replyOption,
|
||||
onOpened: controller.keepChatPanel,
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
_replyOption = item;
|
||||
});
|
||||
},
|
||||
itemBuilder: (context) => ReplyOption.values
|
||||
.map(
|
||||
(item) => PopupMenuItem<ReplyOption>(
|
||||
value: item,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
item.iconData,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(item.title),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
_replyOption.iconData,
|
||||
color: _replyOption == ReplyOption.close
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
size: 19,
|
||||
_replyOption.iconData,
|
||||
color: color,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_replyOption.title,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: color,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_replyOption.title,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: _replyOption == ReplyOption.close
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
),
|
||||
Icon(
|
||||
size: 20,
|
||||
Icons.keyboard_arrow_right,
|
||||
color: _replyOption == ReplyOption.close
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
),
|
||||
Icon(
|
||||
size: 20,
|
||||
Icons.keyboard_arrow_right,
|
||||
color: color,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildPubtimeWidget => _publishTime == null
|
||||
? FilledButton.tonal(
|
||||
|
||||
@@ -282,6 +282,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
@@ -353,14 +354,14 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
onRefresh: () async {
|
||||
await _dynamicDetailController.onRefresh();
|
||||
},
|
||||
child: _buildBody(context.orientation),
|
||||
child: _buildBody(context.orientation, theme),
|
||||
)
|
||||
: _buildBody(context.orientation),
|
||||
: _buildBody(context.orientation, theme),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(Orientation orientation) => Stack(
|
||||
Widget _buildBody(Orientation orientation, ThemeData theme) => Stack(
|
||||
children: [
|
||||
Builder(
|
||||
builder: (context) {
|
||||
@@ -377,10 +378,10 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
callback: _getImageCallback,
|
||||
),
|
||||
),
|
||||
replyPersistentHeader(context),
|
||||
replyPersistentHeader(theme),
|
||||
Obx(
|
||||
() => replyList(
|
||||
_dynamicDetailController.loadingState.value),
|
||||
theme, _dynamicDetailController.loadingState.value),
|
||||
),
|
||||
]
|
||||
.map<Widget>((e) => SliverPadding(
|
||||
@@ -429,13 +430,15 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(right: padding / 4),
|
||||
sliver: replyPersistentHeader(context),
|
||||
sliver: replyPersistentHeader(theme),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(right: padding / 4),
|
||||
sliver: Obx(
|
||||
() => replyList(_dynamicDetailController
|
||||
.loadingState.value),
|
||||
() => replyList(
|
||||
theme,
|
||||
_dynamicDetailController
|
||||
.loadingState.value),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -499,12 +502,10 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.surface,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
color: theme.colorScheme.outline
|
||||
.withOpacity(0.08),
|
||||
),
|
||||
),
|
||||
@@ -565,17 +566,14 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
icon: Icon(
|
||||
FontAwesomeIcons.shareFromSquare,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
semanticLabel: "转发",
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
foregroundColor:
|
||||
theme.colorScheme.outline,
|
||||
),
|
||||
label: Text(
|
||||
_dynamicDetailController
|
||||
@@ -606,17 +604,14 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
icon: Icon(
|
||||
FontAwesomeIcons.shareNodes,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
semanticLabel: "分享",
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
foregroundColor:
|
||||
theme.colorScheme.outline,
|
||||
),
|
||||
label: const Text('分享'),
|
||||
),
|
||||
@@ -652,12 +647,8 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
?.like
|
||||
?.status ==
|
||||
true
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
semanticLabel:
|
||||
_dynamicDetailController
|
||||
.item
|
||||
@@ -672,9 +663,8 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
foregroundColor:
|
||||
theme.colorScheme.outline,
|
||||
),
|
||||
label: AnimatedSwitcher(
|
||||
duration: const Duration(
|
||||
@@ -709,12 +699,8 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
?.like
|
||||
?.status ==
|
||||
true
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -733,10 +719,10 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
],
|
||||
);
|
||||
|
||||
SliverPersistentHeader replyPersistentHeader(BuildContext context) {
|
||||
SliverPersistentHeader replyPersistentHeader(ThemeData theme) {
|
||||
return SliverPersistentHeader(
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
bgColor: Theme.of(context).colorScheme.surface,
|
||||
bgColor: theme.colorScheme.surface,
|
||||
child: Container(
|
||||
height: 45,
|
||||
padding: const EdgeInsets.only(left: 12, right: 6),
|
||||
@@ -763,13 +749,13 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
icon: Icon(
|
||||
Icons.sort,
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
label: Obx(() => Text(
|
||||
_dynamicDetailController.sortType.value.label,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
)),
|
||||
),
|
||||
@@ -782,7 +768,8 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget replyList(LoadingState<List<ReplyInfo>?> loadingState) {
|
||||
Widget replyList(
|
||||
ThemeData theme, LoadingState<List<ReplyInfo>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemBuilder: (context, index) {
|
||||
@@ -808,7 +795,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
: '没有更多了',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -70,6 +70,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
return AnimatedSize(
|
||||
alignment: Alignment.topCenter,
|
||||
curve: Curves.ease,
|
||||
@@ -79,10 +80,13 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: _isMax ? 16 : 10),
|
||||
_buildAppBar,
|
||||
if (_isMax) Expanded(child: _buildEditPanel) else _buildEditPanel,
|
||||
_buildAppBar(theme),
|
||||
if (_isMax)
|
||||
Expanded(child: _buildEditPanel(theme))
|
||||
else
|
||||
_buildEditPanel(theme),
|
||||
if (_isMax.not)
|
||||
..._biuldDismiss
|
||||
..._biuldDismiss(theme)
|
||||
else ...[
|
||||
_buildToolbar,
|
||||
buildPanelContainer(Colors.transparent),
|
||||
@@ -92,7 +96,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildEditPanel => Column(
|
||||
Widget _buildEditPanel(ThemeData theme) => Column(
|
||||
mainAxisSize: _isMax ? MainAxisSize.max : MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
@@ -105,28 +109,30 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
width: 2,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
child: _isMax.not ? _buildEditPlaceHolder : _buildEditWidget,
|
||||
child: _isMax.not
|
||||
? _buildEditPlaceHolder(theme)
|
||||
: _buildEditWidget,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
_buildRefWidget,
|
||||
_buildRefWidget(theme),
|
||||
],
|
||||
);
|
||||
|
||||
Widget get _buildRefWidget => Container(
|
||||
Widget _buildRefWidget(ThemeData theme) => Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh ==
|
||||
Theme.of(context).colorScheme.surface
|
||||
? Theme.of(context).colorScheme.onInverseSurface
|
||||
: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
color: theme.colorScheme.surfaceContainerHigh ==
|
||||
theme.colorScheme.surface
|
||||
? theme.colorScheme.onInverseSurface
|
||||
: theme.colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
@@ -149,7 +155,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
Text(
|
||||
'@$_uname',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
@@ -165,7 +171,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _buildEditPlaceHolder => GestureDetector(
|
||||
Widget _buildEditPlaceHolder(ThemeData theme) => GestureDetector(
|
||||
onTap: () async {
|
||||
setState(() => _isMax = true);
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
@@ -178,7 +184,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
style: TextStyle(
|
||||
height: 1.75,
|
||||
fontSize: 15,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -212,7 +218,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _buildAppBar => _isMax.not
|
||||
Widget _buildAppBar(ThemeData theme) => _isMax.not
|
||||
? Row(
|
||||
children: [
|
||||
const SizedBox(width: 16),
|
||||
@@ -253,14 +259,14 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor:
|
||||
WidgetStateProperty.resolveWith((states) {
|
||||
return Theme.of(context).colorScheme.secondaryContainer;
|
||||
return theme.colorScheme.secondaryContainer;
|
||||
}),
|
||||
),
|
||||
onPressed: Get.back,
|
||||
icon: Icon(
|
||||
Icons.arrow_back_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
color: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -316,11 +322,11 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
),
|
||||
);
|
||||
|
||||
List<Widget> get _biuldDismiss => [
|
||||
List<Widget> _biuldDismiss(ThemeData theme) => [
|
||||
const SizedBox(height: 10),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
color: theme.colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
@@ -328,7 +334,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
|
||||
title: Center(
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -35,6 +35,14 @@ class _DynamicsPageState extends State<DynamicsPage>
|
||||
final DynamicsController _dynamicsController = Get.put(DynamicsController());
|
||||
late UpPanelPosition upPanelPosition;
|
||||
|
||||
late ThemeData theme;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
theme = Theme.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
@@ -49,7 +57,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
return Theme.of(context).colorScheme.secondaryContainer;
|
||||
return theme.colorScheme.secondaryContainer;
|
||||
}),
|
||||
),
|
||||
onPressed: () {
|
||||
@@ -65,7 +73,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
color: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -103,7 +111,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
||||
return Container(
|
||||
//抽屉模式增加底色
|
||||
color: upPanelPosition.index > 1
|
||||
? Theme.of(context).colorScheme.surface
|
||||
? theme.colorScheme.surface
|
||||
: Colors.transparent,
|
||||
width: 64,
|
||||
child: Obx(
|
||||
@@ -149,9 +157,9 @@ class _DynamicsPageState extends State<DynamicsPage>
|
||||
dividerColor: Colors.transparent,
|
||||
dividerHeight: 0,
|
||||
tabAlignment: TabAlignment.center,
|
||||
indicatorColor: Theme.of(context).colorScheme.primary,
|
||||
labelColor: Theme.of(context).colorScheme.primary,
|
||||
unselectedLabelColor: Theme.of(context).colorScheme.onSurface,
|
||||
indicatorColor: theme.colorScheme.primary,
|
||||
labelColor: theme.colorScheme.primary,
|
||||
unselectedLabelColor: theme.colorScheme.onSurface,
|
||||
labelStyle:
|
||||
TabBarTheme.of(context).labelStyle?.copyWith(fontSize: 13) ??
|
||||
const TextStyle(fontSize: 13),
|
||||
|
||||
@@ -58,8 +58,10 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var color = Theme.of(context).colorScheme.outline;
|
||||
var primary = Theme.of(context).colorScheme.primary;
|
||||
final theme = Theme.of(context);
|
||||
final color = theme.colorScheme.outline;
|
||||
final primary = theme.colorScheme.primary;
|
||||
final outline = theme.colorScheme.outline;
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
@@ -90,7 +92,7 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
foregroundColor: outline,
|
||||
),
|
||||
label: Text(
|
||||
widget.item.modules.moduleStat!.forward!.count != null
|
||||
@@ -113,7 +115,7 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
foregroundColor: outline,
|
||||
),
|
||||
label: Text(
|
||||
widget.item.modules.moduleStat!.comment!.count != null
|
||||
@@ -140,7 +142,7 @@ class _ActionPanelState extends State<ActionPanel> {
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||
foregroundColor: outline,
|
||||
),
|
||||
label: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -6,33 +7,36 @@ import 'package:PiliPlus/common/widgets/network_img_layer.dart';
|
||||
import 'package:PiliPlus/http/search.dart';
|
||||
|
||||
/// TODO 点击跳转
|
||||
Widget addWidget(item, context, type, {floor = 1}) {
|
||||
Widget addWidget(
|
||||
ThemeData theme, DynamicItemModel item, BuildContext context, type,
|
||||
{floor = 1}) {
|
||||
Map<dynamic, dynamic> dynamicProperty = {
|
||||
'ADDITIONAL_TYPE_UGC': item.modules.moduleDynamic.additional.ugc,
|
||||
'ADDITIONAL_TYPE_UGC': item.modules.moduleDynamic!.additional!.ugc,
|
||||
// 直播预约
|
||||
'ADDITIONAL_TYPE_RESERVE': item.modules.moduleDynamic.additional.reserve,
|
||||
'ADDITIONAL_TYPE_RESERVE': item.modules.moduleDynamic!.additional!.reserve,
|
||||
// 商品
|
||||
'ADDITIONAL_TYPE_GOODS': item.modules.moduleDynamic.additional.goods,
|
||||
'ADDITIONAL_TYPE_GOODS': item.modules.moduleDynamic!.additional!.goods,
|
||||
// 比赛信息
|
||||
'ADDITIONAL_TYPE_MATCH': item.modules.moduleDynamic.additional.match,
|
||||
'ADDITIONAL_TYPE_MATCH': item.modules.moduleDynamic!.additional!.match,
|
||||
// 游戏信息
|
||||
'ADDITIONAL_TYPE_COMMON': item.modules.moduleDynamic.additional.common,
|
||||
'ADDITIONAL_TYPE_COMMON': item.modules.moduleDynamic!.additional!.common,
|
||||
};
|
||||
dynamic content = dynamicProperty[type];
|
||||
Color bgColor = floor == 1
|
||||
? Theme.of(context).dividerColor.withOpacity(0.08)
|
||||
: Theme.of(context).colorScheme.surface;
|
||||
? theme.dividerColor.withOpacity(0.08)
|
||||
: theme.colorScheme.surface;
|
||||
switch (type) {
|
||||
case 'ADDITIONAL_TYPE_UGC':
|
||||
// 转发的投稿
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
String text = dynamicProperty[type].jumpUrl;
|
||||
String text = content.jumpUrl;
|
||||
RegExp bvRegex = RegExp(r'BV[0-9A-Za-z]{10}', caseSensitive: false);
|
||||
Iterable<Match> matches = bvRegex.allMatches(text);
|
||||
if (matches.isNotEmpty) {
|
||||
Match match = matches.first;
|
||||
String bvid = match.group(0)!;
|
||||
String cover = dynamicProperty[type].cover;
|
||||
String cover = content.cover;
|
||||
try {
|
||||
int cid = await SearchHttp.ab2c(bvid: bvid);
|
||||
PageUtils.toVideoPage(
|
||||
@@ -58,7 +62,7 @@ Widget addWidget(item, context, type, {floor = 1}) {
|
||||
NetworkImgLayer(
|
||||
width: 120,
|
||||
height: 75,
|
||||
src: dynamicProperty[type].cover,
|
||||
src: content.cover,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
@@ -67,17 +71,16 @@ Widget addWidget(item, context, type, {floor = 1}) {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
dynamicProperty[type].title,
|
||||
content.title,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
dynamicProperty[type].descSecond,
|
||||
content.descSecond,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -88,22 +91,22 @@ Widget addWidget(item, context, type, {floor = 1}) {
|
||||
),
|
||||
);
|
||||
case 'ADDITIONAL_TYPE_RESERVE':
|
||||
return dynamicProperty[type].state != -1
|
||||
? dynamicProperty[type].title != null
|
||||
return content.state != -1
|
||||
? content.title != null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.only(
|
||||
left: 12, top: 10, right: 12, bottom: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 10),
|
||||
color: bgColor,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
dynamicProperty[type].title,
|
||||
content.title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -111,21 +114,15 @@ Widget addWidget(item, context, type, {floor = 1}) {
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize),
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
children: [
|
||||
if (dynamicProperty[type].desc1 != null)
|
||||
TextSpan(
|
||||
text:
|
||||
dynamicProperty[type].desc1['text']),
|
||||
if (content.desc1 != null)
|
||||
TextSpan(text: content.desc1['text']),
|
||||
const TextSpan(text: ' '),
|
||||
if (dynamicProperty[type].desc2 != null)
|
||||
TextSpan(
|
||||
text:
|
||||
dynamicProperty[type].desc2['text']),
|
||||
if (content.desc2 != null)
|
||||
TextSpan(text: content.desc2['text']),
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -146,6 +143,6 @@ Widget addWidget(item, context, type, {floor = 1}) {
|
||||
case 'ADDITIONAL_TYPE_VOTE':
|
||||
return const SizedBox.shrink();
|
||||
default:
|
||||
return const Text('11');
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
|
||||
import '../../../common/constants.dart';
|
||||
import 'pic_panel.dart';
|
||||
|
||||
Widget articlePanel(source, item, context, callback, {floor = 1}) {
|
||||
TextStyle authorStyle =
|
||||
TextStyle(color: Theme.of(context).colorScheme.primary);
|
||||
Widget articlePanel(
|
||||
ThemeData theme,
|
||||
String? source,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
callback, {
|
||||
floor = 1,
|
||||
}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: Column(
|
||||
@@ -15,37 +21,32 @@ Widget articlePanel(source, item, context, callback, {floor = 1}) {
|
||||
if (floor == 2) ...[
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
child: Text(
|
||||
'@${item.modules.moduleAuthor.name}',
|
||||
style: authorStyle,
|
||||
),
|
||||
Text(
|
||||
'@${item.modules.moduleAuthor!.name}',
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
Utils.dateFormat(item.modules.moduleAuthor.pubTs),
|
||||
Utils.dateFormat(item.modules.moduleAuthor!.pubTs),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
Text(
|
||||
item.modules.moduleDynamic.major.opus.title,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
item.modules.moduleDynamic!.major!.opus!.title!,
|
||||
style: theme.textTheme.titleMedium!
|
||||
.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
if (item.modules.moduleDynamic.major.opus.summary.text !=
|
||||
if (item.modules.moduleDynamic?.major?.opus?.summary?.text !=
|
||||
'undefined') ...[
|
||||
Text(
|
||||
item.modules.moduleDynamic.major.opus.summary.richTextNodes.first
|
||||
.text,
|
||||
item.modules.moduleDynamic!.major!.opus!.summary!.richTextNodes!
|
||||
.first.text!,
|
||||
maxLines: source == 'detail' ? null : 4,
|
||||
style: const TextStyle(height: 1.55),
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
|
||||
@@ -241,6 +241,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
maxWidth: min(640, min(Get.width, Get.height)),
|
||||
),
|
||||
builder: (context1) {
|
||||
final theme = Theme.of(context);
|
||||
return Padding(
|
||||
padding:
|
||||
EdgeInsets.only(bottom: MediaQuery.of(context1).padding.bottom),
|
||||
@@ -261,7 +262,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
width: 32,
|
||||
height: 3,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(3))),
|
||||
),
|
||||
@@ -283,7 +284,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
leading: const Icon(Icons.watch_later_outlined, size: 19),
|
||||
title: Text(
|
||||
'稍后再看',
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
style: theme.textTheme.titleSmall,
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
@@ -293,13 +294,12 @@ class AuthorPanel extends StatelessWidget {
|
||||
},
|
||||
minLeadingWidth: 0,
|
||||
leading: const Icon(Icons.save_alt, size: 19),
|
||||
title: Text('保存动态',
|
||||
style: Theme.of(context).textTheme.titleSmall!),
|
||||
title: Text('保存动态', style: theme.textTheme.titleSmall!),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'分享动态',
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
style: theme.textTheme.titleSmall,
|
||||
),
|
||||
leading: const Icon(Icons.share_outlined, size: 19),
|
||||
onTap: () {
|
||||
@@ -314,7 +314,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
ListTile(
|
||||
title: Text(
|
||||
'分享至消息',
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
style: theme.textTheme.titleSmall,
|
||||
),
|
||||
leading: const Icon(Icons.forward_to_inbox, size: 19),
|
||||
onTap: () {
|
||||
@@ -359,7 +359,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
ListTile(
|
||||
title: Text(
|
||||
'临时屏蔽:${item.modules.moduleAuthor?.name}',
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
style: theme.textTheme.titleSmall,
|
||||
),
|
||||
leading: const Icon(Icons.visibility_off_outlined, size: 19),
|
||||
onTap: () {
|
||||
@@ -387,8 +387,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
Icon(Icons.published_with_changes_sharp, size: 12),
|
||||
],
|
||||
),
|
||||
title: Text('检查动态',
|
||||
style: Theme.of(context).textTheme.titleSmall!),
|
||||
title: Text('检查动态', style: theme.textTheme.titleSmall!),
|
||||
),
|
||||
if (onSetTop != null)
|
||||
ListTile(
|
||||
@@ -401,7 +400,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
leading: const Icon(Icons.vertical_align_top, size: 19),
|
||||
title: Text(
|
||||
'${item.modules.moduleTag?.text != null ? '取消' : ''}置顶',
|
||||
style: Theme.of(context).textTheme.titleSmall!),
|
||||
style: theme.textTheme.titleSmall!),
|
||||
),
|
||||
if (onRemove != null)
|
||||
ListTile(
|
||||
@@ -417,7 +416,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -434,24 +433,24 @@ class AuthorPanel extends StatelessWidget {
|
||||
},
|
||||
minLeadingWidth: 0,
|
||||
leading: Icon(Icons.delete_outline,
|
||||
color: Theme.of(context).colorScheme.error, size: 19),
|
||||
color: theme.colorScheme.error, size: 19),
|
||||
title: Text('删除',
|
||||
style: Theme.of(context).textTheme.titleSmall!.copyWith(
|
||||
color: Theme.of(context).colorScheme.error)),
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(color: theme.colorScheme.error)),
|
||||
),
|
||||
],
|
||||
if (Accounts.main.isLogin)
|
||||
ListTile(
|
||||
title: Text(
|
||||
'举报',
|
||||
style: Theme.of(context).textTheme.titleSmall!.copyWith(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
),
|
||||
leading: Icon(
|
||||
Icons.error_outline_outlined,
|
||||
size: 19,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
@@ -483,8 +482,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
dense: true,
|
||||
title: Text(
|
||||
'取消',
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
// 内容
|
||||
import 'package:PiliPlus/common/widgets/image_view.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'rich_node_panel.dart';
|
||||
|
||||
Widget content(bool isSave, BuildContext context, item, source, callback) {
|
||||
Widget content(
|
||||
ThemeData theme,
|
||||
bool isSave,
|
||||
BuildContext context,
|
||||
DynamicItemModel item,
|
||||
String? source,
|
||||
Function(List<String>, int)? callback,
|
||||
) {
|
||||
InlineSpan picsNodes() {
|
||||
return WidgetSpan(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => imageView(
|
||||
constraints.maxWidth,
|
||||
(item.modules.moduleDynamic.major.opus.pics as List)
|
||||
(item.modules.moduleDynamic!.major!.opus!.pics as List)
|
||||
.map(
|
||||
(item) => ImageModel(
|
||||
width: item.width,
|
||||
@@ -26,9 +34,7 @@ Widget content(bool isSave, BuildContext context, item, source, callback) {
|
||||
);
|
||||
}
|
||||
|
||||
TextStyle authorStyle =
|
||||
TextStyle(color: Theme.of(context).colorScheme.primary);
|
||||
InlineSpan? richNodes = richNode(item, context);
|
||||
TextSpan? richNodes = richNode(theme, item, context);
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
@@ -36,24 +42,17 @@ Widget content(bool isSave, BuildContext context, item, source, callback) {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item.modules.moduleDynamic.topic != null) ...[
|
||||
GestureDetector(
|
||||
child: Text(
|
||||
'#${item.modules.moduleDynamic.topic.name}',
|
||||
style: authorStyle,
|
||||
),
|
||||
if (item.modules.moduleDynamic?.topic != null) ...[
|
||||
Text(
|
||||
'#${item.modules.moduleDynamic!.topic!.name}',
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
],
|
||||
if (richNodes != null)
|
||||
source == 'detail'
|
||||
? SelectableRegion(
|
||||
magnifierConfiguration: const TextMagnifierConfiguration(),
|
||||
focusNode: FocusNode(),
|
||||
selectionControls: MaterialTextSelectionControls(),
|
||||
child: Text.rich(
|
||||
style: TextStyle(fontSize: !isSave ? 16 : 15),
|
||||
richNodes,
|
||||
),
|
||||
? SelectableText.rich(
|
||||
richNodes,
|
||||
style: TextStyle(fontSize: !isSave ? 16 : 15),
|
||||
)
|
||||
: Text.rich(
|
||||
style: const TextStyle(fontSize: 15),
|
||||
@@ -61,12 +60,8 @@ Widget content(bool isSave, BuildContext context, item, source, callback) {
|
||||
maxLines: 6,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
if (item.modules.moduleDynamic.major != null &&
|
||||
item.modules.moduleDynamic.major.opus != null &&
|
||||
item.modules.moduleDynamic.major.opus.pics.isNotEmpty)
|
||||
Text.rich(
|
||||
picsNodes(),
|
||||
),
|
||||
if (item.modules.moduleDynamic?.major?.opus?.pics?.isNotEmpty == true)
|
||||
Text.rich(picsNodes()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -29,6 +29,7 @@ class DynamicPanel extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final authorWidget = AuthorPanel(
|
||||
item: item,
|
||||
source: source,
|
||||
@@ -45,7 +46,7 @@ class DynamicPanel extends StatelessWidget {
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
width: 8,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.05),
|
||||
color: theme.dividerColor.withOpacity(0.05),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -76,8 +77,8 @@ class DynamicPanel extends StatelessWidget {
|
||||
),
|
||||
if (item.modules.moduleDynamic!.desc != null ||
|
||||
item.modules.moduleDynamic!.major != null)
|
||||
content(isSave, context, item, source, callback),
|
||||
forWard(isSave, item, context, source, callback),
|
||||
content(theme, isSave, context, item, source, callback),
|
||||
forWard(theme, isSave, item, context, source, callback),
|
||||
const SizedBox(height: 2),
|
||||
if (source == null) ActionPanel(item: item),
|
||||
if (source == 'detail' && !isSave) const SizedBox(height: 12),
|
||||
@@ -121,7 +122,6 @@ class DynamicPanel extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: title,
|
||||
cover: cover,
|
||||
);
|
||||
|
||||
@@ -19,7 +19,10 @@ import 'pic_panel.dart';
|
||||
import 'rich_node_panel.dart';
|
||||
import 'video_panel.dart';
|
||||
|
||||
InlineSpan picsNodes(List<OpusPicsModel> pics, callback) {
|
||||
InlineSpan picsNodes(
|
||||
List<OpusPicsModel> pics,
|
||||
Function(List<String>, int)? callback,
|
||||
) {
|
||||
return WidgetSpan(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => imageView(
|
||||
@@ -40,7 +43,7 @@ InlineSpan picsNodes(List<OpusPicsModel> pics, callback) {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _blockedItem(BuildContext context, DynamicItemModel item, source) {
|
||||
Widget _blockedItem(ThemeData theme, DynamicItemModel item, String? source) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(
|
||||
@@ -53,7 +56,7 @@ Widget _blockedItem(BuildContext context, DynamicItemModel item, source) {
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.blocked!['title'],
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
if (item.modules.moduleDynamic!.major!.blocked!['hint_message'] != null)
|
||||
@@ -61,7 +64,7 @@ Widget _blockedItem(BuildContext context, DynamicItemModel item, source) {
|
||||
item.modules.moduleDynamic!.major!.blocked!['hint_message'],
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -70,15 +73,21 @@ Widget _blockedItem(BuildContext context, DynamicItemModel item, source) {
|
||||
}
|
||||
|
||||
Widget forWard(
|
||||
bool isSave, DynamicItemModel item, BuildContext context, source, callback,
|
||||
{floor = 1}) {
|
||||
ThemeData theme,
|
||||
bool isSave,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
source,
|
||||
callback, {
|
||||
floor = 1,
|
||||
}) {
|
||||
switch (item.type) {
|
||||
// 图文
|
||||
case 'DYNAMIC_TYPE_DRAW':
|
||||
bool hasPics =
|
||||
item.modules.moduleDynamic?.major?.opus?.pics?.isNotEmpty == true;
|
||||
|
||||
InlineSpan? richNodes = richNode(item, context);
|
||||
TextSpan? richNodes = richNode(theme, item, context);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -91,17 +100,15 @@ Widget forWard(
|
||||
arguments: {'face': item.modules.moduleAuthor!.face}),
|
||||
child: Text(
|
||||
'@${item.modules.moduleAuthor!.name}',
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.primary),
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
Utils.dateFormat(item.modules.moduleAuthor!.pubTs),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -139,22 +146,24 @@ Widget forWard(
|
||||
/// 附加内容 商品信息、直播预约等等
|
||||
if (item.modules.moduleDynamic?.additional != null)
|
||||
addWidget(
|
||||
theme,
|
||||
item,
|
||||
context,
|
||||
item.modules.moduleDynamic?.additional?.type,
|
||||
floor: floor,
|
||||
),
|
||||
if (item.modules.moduleDynamic?.major?.blocked != null)
|
||||
_blockedItem(context, item, source),
|
||||
_blockedItem(theme, item, source),
|
||||
],
|
||||
);
|
||||
// 视频
|
||||
case 'DYNAMIC_TYPE_AV':
|
||||
return videoSeasonWidget(source, item, context, 'archive', floor: floor);
|
||||
return videoSeasonWidget(theme, source, item, context, 'archive',
|
||||
floor: floor);
|
||||
// 文章
|
||||
case 'DYNAMIC_TYPE_ARTICLE':
|
||||
return item.isForwarded == true
|
||||
? articlePanel(source, item, context, callback, floor: floor)
|
||||
? articlePanel(theme, source, item, context, callback, floor: floor)
|
||||
: item.modules.moduleDynamic?.major?.blocked != null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
@@ -168,7 +177,7 @@ Widget forWard(
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.blocked!['title'],
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
if (item.modules.moduleDynamic?.major
|
||||
@@ -179,7 +188,7 @@ Widget forWard(
|
||||
.blocked!['hint_message'],
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -225,29 +234,28 @@ Widget forWard(
|
||||
return;
|
||||
}
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: title,
|
||||
cover: cover,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.08),
|
||||
child: forWard(isSave, item.orig!, context, source, callback,
|
||||
color: theme.dividerColor.withOpacity(0.08),
|
||||
child: forWard(theme, isSave, item.orig!, context, source, callback,
|
||||
floor: floor + 1),
|
||||
),
|
||||
);
|
||||
// 直播
|
||||
case 'DYNAMIC_TYPE_LIVE_RCMD':
|
||||
return liveRcmdPanel(source, item, context, floor: floor);
|
||||
return liveRcmdPanel(theme, source, item, context, floor: floor);
|
||||
// 直播
|
||||
case 'DYNAMIC_TYPE_LIVE':
|
||||
return livePanel(source, item, context, floor: floor);
|
||||
return livePanel(theme, source, item, context, floor: floor);
|
||||
// 合集
|
||||
case 'DYNAMIC_TYPE_UGC_SEASON':
|
||||
return videoSeasonWidget(source, item, context, 'ugcSeason');
|
||||
return videoSeasonWidget(theme, source, item, context, 'ugcSeason');
|
||||
case 'DYNAMIC_TYPE_WORD':
|
||||
InlineSpan? richNodes = richNode(item, context);
|
||||
late TextSpan? richNodes = richNode(theme, item, context);
|
||||
return floor == 2
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -260,17 +268,15 @@ Widget forWard(
|
||||
arguments: {'face': item.modules.moduleAuthor?.face}),
|
||||
child: Text(
|
||||
'@${item.modules.moduleAuthor?.name}',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary),
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
Utils.dateFormat(item.modules.moduleAuthor?.pubTs),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -294,18 +300,21 @@ Widget forWard(
|
||||
)
|
||||
: item.modules.moduleDynamic?.additional != null
|
||||
? addWidget(
|
||||
theme,
|
||||
item,
|
||||
context,
|
||||
item.modules.moduleDynamic!.additional!.type,
|
||||
floor: floor,
|
||||
)
|
||||
: item.modules.moduleDynamic?.major?.blocked != null
|
||||
? _blockedItem(context, item, source)
|
||||
? _blockedItem(theme, item, source)
|
||||
: const SizedBox(height: 0);
|
||||
case 'DYNAMIC_TYPE_PGC':
|
||||
return videoSeasonWidget(source, item, context, 'pgc', floor: floor);
|
||||
return videoSeasonWidget(theme, source, item, context, 'pgc',
|
||||
floor: floor);
|
||||
case 'DYNAMIC_TYPE_PGC_UNION':
|
||||
return videoSeasonWidget(source, item, context, 'pgc', floor: floor);
|
||||
return videoSeasonWidget(theme, source, item, context, 'pgc',
|
||||
floor: floor);
|
||||
// 直播结束
|
||||
case 'DYNAMIC_TYPE_NONE':
|
||||
return Row(
|
||||
@@ -347,7 +356,7 @@ Widget forWard(
|
||||
width: double.infinity,
|
||||
padding:
|
||||
const EdgeInsets.only(left: 12, top: 10, right: 12, bottom: 10),
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.08),
|
||||
color: theme.dividerColor.withOpacity(0.08),
|
||||
child: Row(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
@@ -365,7 +374,7 @@ Widget forWard(
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.common!['title'],
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -374,9 +383,8 @@ Widget forWard(
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.common!['desc'],
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -398,7 +406,7 @@ Widget forWard(
|
||||
width: double.infinity,
|
||||
padding:
|
||||
const EdgeInsets.only(left: 12, top: 10, right: 12, bottom: 10),
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.08),
|
||||
color: theme.dividerColor.withOpacity(0.08),
|
||||
child: Row(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
@@ -415,7 +423,7 @@ Widget forWard(
|
||||
Text(
|
||||
music['title'],
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -424,9 +432,8 @@ Widget forWard(
|
||||
Text(
|
||||
music['label'],
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -464,9 +471,8 @@ Widget forWard(
|
||||
item.modules.moduleAuthor!.vip!['status'] > 0 &&
|
||||
item.modules.moduleAuthor!.vip!['type'] == 2
|
||||
? context.vipColor
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.titleMedium!.fontSize,
|
||||
: theme.colorScheme.onSurface,
|
||||
fontSize: theme.textTheme.titleMedium!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -510,10 +516,7 @@ Widget forWard(
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.medialist!['title'],
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.fontSize,
|
||||
fontSize: theme.textTheme.titleMedium!.fontSize,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (item.modules.moduleDynamic?.major
|
||||
@@ -524,11 +527,8 @@ Widget forWard(
|
||||
item.modules.moduleDynamic!.major!
|
||||
.medialist!['sub_title'],
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelLarge!
|
||||
.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline),
|
||||
fontSize: theme.textTheme.labelLarge!.fontSize,
|
||||
color: theme.colorScheme.outline),
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:PiliPlus/common/widgets/image_save.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
|
||||
@@ -6,11 +7,19 @@ import 'package:PiliPlus/utils/utils.dart';
|
||||
|
||||
import 'rich_node_panel.dart';
|
||||
|
||||
Widget livePanel(source, item, context, {floor = 1}) {
|
||||
dynamic content = item.modules.moduleDynamic.major;
|
||||
late final TextStyle authorStyle =
|
||||
TextStyle(color: Theme.of(context).colorScheme.primary);
|
||||
InlineSpan? richNodes = richNode(item, context);
|
||||
Widget livePanel(
|
||||
ThemeData theme,
|
||||
String? source,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
}) {
|
||||
DynamicMajorModel? content = item.modules.moduleDynamic!.major;
|
||||
if (content == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
late final authorStyle = TextStyle(color: theme.colorScheme.primary);
|
||||
TextSpan? richNodes = richNode(theme, item, context);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -19,40 +28,41 @@ Widget livePanel(source, item, context, {floor = 1}) {
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed(
|
||||
'/member?mid=${item.modules.moduleAuthor.mid}',
|
||||
arguments: {'face': item.modules.moduleAuthor.face}),
|
||||
'/member?mid=${item.modules.moduleAuthor!.mid}',
|
||||
arguments: {'face': item.modules.moduleAuthor!.face}),
|
||||
child: Text(
|
||||
'@${item.modules.moduleAuthor.name}',
|
||||
'@${item.modules.moduleAuthor!.name}',
|
||||
style: authorStyle,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
Utils.dateFormat(item.modules.moduleAuthor.pubTs),
|
||||
Utils.dateFormat(item.modules.moduleAuthor?.pubTs),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
if (item.modules.moduleDynamic.topic != null) ...[
|
||||
if (item.modules.moduleDynamic?.topic != null) ...[
|
||||
Padding(
|
||||
padding: floor == 2
|
||||
? EdgeInsets.zero
|
||||
: const EdgeInsets.only(left: 12, right: 12),
|
||||
child: GestureDetector(
|
||||
child: Text(
|
||||
'#${item.modules.moduleDynamic.topic.name}',
|
||||
style: authorStyle,
|
||||
),
|
||||
child: Text(
|
||||
'#${item.modules.moduleDynamic!.topic!.name}',
|
||||
style: authorStyle,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
if (floor == 2 && item.modules.moduleDynamic.desc != null) ...[
|
||||
if (richNodes != null) Text.rich(richNodes),
|
||||
if (floor == 2 &&
|
||||
item.modules.moduleDynamic?.desc != null &&
|
||||
richNodes != null) ...[
|
||||
Text.rich(richNodes),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
GestureDetector(
|
||||
@@ -63,9 +73,8 @@ Widget livePanel(source, item, context, {floor = 1}) {
|
||||
onLongPress: () {
|
||||
Feedback.forLongPress(context);
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: content.live.title,
|
||||
cover: content.live.cover,
|
||||
title: content.live!.title,
|
||||
cover: content.live!.cover,
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
@@ -75,7 +84,7 @@ Widget livePanel(source, item, context, {floor = 1}) {
|
||||
NetworkImgLayer(
|
||||
width: 120,
|
||||
height: 75,
|
||||
src: content.live.cover,
|
||||
src: content.live!.cover,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
@@ -84,26 +93,26 @@ Widget livePanel(source, item, context, {floor = 1}) {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
content.live.title,
|
||||
content.live!.title!,
|
||||
maxLines: source == 'detail' ? null : 2,
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
content.live.descFirst,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
)
|
||||
if (content.live?.descFirst != null)
|
||||
Text(
|
||||
content.live!.descFirst!,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
content.live.badge['text'],
|
||||
content.live!.badge!['text'],
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
),
|
||||
)
|
||||
],
|
||||
|
||||
@@ -9,13 +9,21 @@ import 'package:PiliPlus/utils/utils.dart';
|
||||
|
||||
import 'rich_node_panel.dart';
|
||||
|
||||
Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) {
|
||||
TextStyle authorStyle =
|
||||
TextStyle(color: Theme.of(context).colorScheme.primary);
|
||||
DynamicLiveModel liveRcmd = item.modules.moduleDynamic!.major!.liveRcmd!;
|
||||
int liveStatus = liveRcmd.liveStatus!;
|
||||
Map watchedShow = liveRcmd.watchedShow!;
|
||||
InlineSpan? richNodes = richNode(item, context);
|
||||
Widget liveRcmdPanel(
|
||||
ThemeData theme,
|
||||
String? source,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
}) {
|
||||
DynamicLiveModel? liveRcmd = item.modules.moduleDynamic?.major?.liveRcmd;
|
||||
if (liveRcmd == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
int? liveStatus = liveRcmd.liveStatus;
|
||||
Map? watchedShow = liveRcmd.watchedShow;
|
||||
TextSpan? richNodes = richNode(theme, item, context);
|
||||
late final authorStyle = TextStyle(color: theme.colorScheme.primary);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -24,8 +32,9 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) {
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed(
|
||||
'/member?mid=${item.modules.moduleAuthor?.mid}',
|
||||
arguments: {'face': item.modules.moduleAuthor?.face}),
|
||||
'/member?mid=${item.modules.moduleAuthor?.mid}',
|
||||
arguments: {'face': item.modules.moduleAuthor?.face},
|
||||
),
|
||||
child: Text(
|
||||
'@${item.modules.moduleAuthor?.name}',
|
||||
style: authorStyle,
|
||||
@@ -35,8 +44,9 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) {
|
||||
Text(
|
||||
Utils.dateFormat(item.modules.moduleAuthor?.pubTs),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -46,27 +56,27 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) {
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: GestureDetector(
|
||||
child: Text(
|
||||
'#${item.modules.moduleDynamic!.topic!.name}',
|
||||
style: authorStyle,
|
||||
),
|
||||
child: Text(
|
||||
'#${item.modules.moduleDynamic!.topic!.name}',
|
||||
style: authorStyle,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
if (floor == 2 && item.modules.moduleDynamic?.desc != null) ...[
|
||||
if (richNodes != null) Text.rich(richNodes),
|
||||
if (floor == 2 &&
|
||||
item.modules.moduleDynamic?.desc != null &&
|
||||
richNodes != null) ...[
|
||||
Text.rich(richNodes),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
PageUtils.pushDynDetail(item, floor);
|
||||
},
|
||||
child: LayoutBuilder(builder: (context, box) {
|
||||
padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
PageUtils.pushDynDetail(item, floor);
|
||||
},
|
||||
child: LayoutBuilder(
|
||||
builder: (context, box) {
|
||||
double width = box.maxWidth;
|
||||
return Stack(
|
||||
children: [
|
||||
@@ -75,33 +85,31 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) {
|
||||
child: NetworkImgLayer(
|
||||
width: width,
|
||||
height: width / StyleString.aspectRatio,
|
||||
src: item.modules.moduleDynamic?.major?.liveRcmd?.cover,
|
||||
src: liveRcmd.cover,
|
||||
),
|
||||
),
|
||||
PBadge(
|
||||
text: watchedShow['text_large'],
|
||||
text: watchedShow?['text_large'],
|
||||
top: 6,
|
||||
right: 56,
|
||||
bottom: null,
|
||||
left: null,
|
||||
type: 'gray',
|
||||
),
|
||||
PBadge(
|
||||
text: liveStatus == 1 ? '直播中' : '直播结束',
|
||||
top: 6,
|
||||
right: 6,
|
||||
bottom: null,
|
||||
left: null,
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 80,
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 10, 10),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
if (liveRcmd.areaName != null)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 80,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 10, 10),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
@@ -111,45 +119,42 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) {
|
||||
],
|
||||
),
|
||||
borderRadius: floor == 1
|
||||
? StyleString.mdRadius
|
||||
: const BorderRadius.all(Radius.circular(6))),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
DefaultTextStyle.merge(
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.fontSize,
|
||||
color: Colors.white),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(item.modules.moduleDynamic?.major?.liveRcmd
|
||||
?.areaName ??
|
||||
''),
|
||||
],
|
||||
),
|
||||
? const BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
)
|
||||
: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(6),
|
||||
bottomRight: Radius.circular(6),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
liveRcmd.areaName!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
)),
|
||||
const SizedBox(height: 6),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: Text(
|
||||
item.modules.moduleDynamic!.major!.liveRcmd!.title!,
|
||||
maxLines: source == 'detail' ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
if (liveRcmd.title != null)
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: Text(
|
||||
liveRcmd.title!,
|
||||
maxLines: source == 'detail' ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import 'package:PiliPlus/common/widgets/image_view.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget picWidget(item, context, callback) {
|
||||
if (item.modules.moduleDynamic.major?.draw?.items == null ||
|
||||
item.modules.moduleDynamic.major.type == 'MAJOR_TYPE_OPUS') {
|
||||
Widget picWidget(
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
Function(List<String>, int)? callback,
|
||||
) {
|
||||
if (item.modules.moduleDynamic?.major?.draw?.items == null ||
|
||||
item.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_OPUS') {
|
||||
/// fix 图片跟rich_node_panel重复
|
||||
// pictures = item.modules.moduleDynamic.major.opus.pics;
|
||||
return const SizedBox.shrink();
|
||||
@@ -11,7 +16,7 @@ Widget picWidget(item, context, callback) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) => imageView(
|
||||
constraints.maxWidth,
|
||||
(item.modules.moduleDynamic.major.draw.items as List)
|
||||
(item.modules.moduleDynamic!.major!.draw!.items as List)
|
||||
.map(
|
||||
(item) => ImageModel(
|
||||
width: item.width,
|
||||
|
||||
@@ -10,27 +10,27 @@ import 'package:PiliPlus/http/search.dart';
|
||||
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||
|
||||
// 富文本
|
||||
InlineSpan? richNode(item, BuildContext context) {
|
||||
final spacer = _VerticalSpaceSpan(0.0);
|
||||
TextSpan? richNode(
|
||||
ThemeData theme,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
) {
|
||||
try {
|
||||
TextStyle authorStyle =
|
||||
TextStyle(color: Theme.of(context).colorScheme.primary);
|
||||
late final authorStyle = TextStyle(color: theme.colorScheme.primary);
|
||||
List<InlineSpan> spanChildren = [];
|
||||
|
||||
List<RichTextNodeItem>? richTextNodes;
|
||||
if (item.modules.moduleDynamic.desc != null) {
|
||||
richTextNodes = item.modules.moduleDynamic.desc.richTextNodes;
|
||||
} else if (item.modules.moduleDynamic.major != null) {
|
||||
if (item.modules.moduleDynamic?.desc != null) {
|
||||
richTextNodes = item.modules.moduleDynamic!.desc!.richTextNodes;
|
||||
} else if (item.modules.moduleDynamic?.major != null) {
|
||||
// 动态页面 richTextNodes 层级可能与主页动态层级不同
|
||||
richTextNodes =
|
||||
item.modules.moduleDynamic.major.opus?.summary?.richTextNodes;
|
||||
if (item.modules.moduleDynamic.major.opus?.title != null) {
|
||||
item.modules.moduleDynamic!.major!.opus?.summary?.richTextNodes;
|
||||
if (item.modules.moduleDynamic?.major?.opus?.title != null) {
|
||||
spanChildren.add(
|
||||
TextSpan(
|
||||
text: item.modules.moduleDynamic.major.opus.title + '\n',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
text: '${item.modules.moduleDynamic!.major!.opus!.title!}\n',
|
||||
style: theme.textTheme.titleMedium!
|
||||
.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
@@ -42,7 +42,8 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
for (var i in richTextNodes) {
|
||||
if (i.type == 'RICH_TEXT_NODE_TYPE_TEXT') {
|
||||
spanChildren.add(
|
||||
TextSpan(text: i.origText, style: const TextStyle(height: 1.65)));
|
||||
TextSpan(text: i.origText, style: const TextStyle(height: 1.65)),
|
||||
);
|
||||
}
|
||||
// @用户
|
||||
else if (i.type == 'RICH_TEXT_NODE_TYPE_AT') {
|
||||
@@ -53,8 +54,7 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${i.rid}',
|
||||
arguments: {'face': null}),
|
||||
onTap: () => Get.toNamed('/member?mid=${i.rid}'),
|
||||
child: Text(
|
||||
' ${i.text}',
|
||||
style: authorStyle,
|
||||
@@ -88,7 +88,7 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
child: Icon(
|
||||
Icons.link,
|
||||
size: 20,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -120,14 +120,12 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
try {
|
||||
String dynamicId = item.basic.commentIdStr;
|
||||
String dynamicId = item.basic!.commentIdStr!;
|
||||
Get.toNamed(
|
||||
'/webview',
|
||||
parameters: {
|
||||
'url':
|
||||
'https://t.bilibili.com/vote/h5/index/#/result?vote_id=${i.rid}&dynamic_id=$dynamicId&isWeb=1',
|
||||
'type': 'vote',
|
||||
'pageTitle': '投票'
|
||||
},
|
||||
);
|
||||
} catch (_) {}
|
||||
@@ -161,7 +159,7 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
child: Icon(
|
||||
Icons.redeem_rounded,
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -195,7 +193,7 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
child: Icon(
|
||||
Icons.shopping_bag_outlined,
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -220,7 +218,7 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
child: Icon(
|
||||
Icons.play_circle_outline_outlined,
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -234,7 +232,6 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
PageUtils.toVideoPage(
|
||||
'bvid=${i.rid}&cid=$cid',
|
||||
arguments: {
|
||||
'pic': null,
|
||||
'heroTag': Utils.makeHeroTag(i.rid),
|
||||
},
|
||||
);
|
||||
@@ -285,11 +282,6 @@ InlineSpan? richNode(item, BuildContext context) {
|
||||
}
|
||||
} catch (err) {
|
||||
debugPrint('❌rich_node_panel err: $err');
|
||||
return spacer;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class _VerticalSpaceSpan extends WidgetSpan {
|
||||
_VerticalSpaceSpan(double height)
|
||||
: super(child: SizedBox(height: height, width: double.infinity));
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ class _UpPanelState extends State<UpPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
if (widget.dynamicsController.isLogin.value.not) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
@@ -74,14 +75,15 @@ class _UpPanelState extends State<UpPanel> {
|
||||
SliverList.builder(
|
||||
itemCount: liveList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return upItemBuild(liveList[index]);
|
||||
return upItemBuild(theme, liveList[index]);
|
||||
},
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: upItemBuild(UpItem(face: '', uname: '全部动态', mid: -1)),
|
||||
child: upItemBuild(theme, UpItem(face: '', uname: '全部动态', mid: -1)),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: upItemBuild(
|
||||
theme,
|
||||
UpItem(
|
||||
uname: '我',
|
||||
face: widget.dynamicsController.face,
|
||||
@@ -93,7 +95,7 @@ class _UpPanelState extends State<UpPanel> {
|
||||
SliverList.builder(
|
||||
itemCount: upList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return upItemBuild(upList[index]);
|
||||
return upItemBuild(theme, upList[index]);
|
||||
},
|
||||
),
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 200)),
|
||||
@@ -101,7 +103,7 @@ class _UpPanelState extends State<UpPanel> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget upItemBuild(data) {
|
||||
Widget upItemBuild(theme, data) {
|
||||
bool isCurrent = widget.dynamicsController.currentMid == data.mid ||
|
||||
widget.dynamicsController.currentMid == -1;
|
||||
return SizedBox(
|
||||
@@ -163,17 +165,14 @@ class _UpPanelState extends State<UpPanel> {
|
||||
child: Badge(
|
||||
smallSize: 8,
|
||||
label: data.type == 'live' ? const Text(' Live ') : null,
|
||||
textColor:
|
||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
textColor: theme.colorScheme.onSecondaryContainer,
|
||||
alignment: AlignmentDirectional.topStart,
|
||||
isLabelVisible: data.type == 'live' ||
|
||||
(data.type == 'up' && (data.hasUpdate ?? false)),
|
||||
backgroundColor: data.type == 'live'
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer
|
||||
? theme.colorScheme.secondaryContainer
|
||||
.withOpacity(0.75)
|
||||
: Theme.of(context).colorScheme.primary,
|
||||
: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -189,8 +188,8 @@ class _UpPanelState extends State<UpPanel> {
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: widget.dynamicsController.currentMid == data.mid
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
height: 1.1,
|
||||
fontSize: 12.5,
|
||||
),
|
||||
@@ -203,31 +202,3 @@ class _UpPanelState extends State<UpPanel> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UpPanelSkeleton extends StatelessWidget {
|
||||
const UpPanelSkeleton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 6),
|
||||
width: 45,
|
||||
height: 12,
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// 视频or合集
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
@@ -8,21 +9,28 @@ import 'package:PiliPlus/utils/utils.dart';
|
||||
|
||||
import 'rich_node_panel.dart';
|
||||
|
||||
Widget videoSeasonWidget(source, item, context, type, {floor = 1}) {
|
||||
if (item.modules.moduleDynamic.major?.type == 'MAJOR_TYPE_NONE') {
|
||||
return item.modules.moduleDynamic.major?.none?.tips != null
|
||||
Widget videoSeasonWidget(
|
||||
ThemeData theme,
|
||||
String? source,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
String type, {
|
||||
floor = 1,
|
||||
}) {
|
||||
if (item.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_NONE') {
|
||||
return item.modules.moduleDynamic?.major?.none?.tips != null
|
||||
? Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
'${item.modules.moduleDynamic.major.none.tips}',
|
||||
item.modules.moduleDynamic!.major!.none!.tips!,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -30,8 +38,6 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) {
|
||||
: const SizedBox.shrink();
|
||||
}
|
||||
|
||||
TextStyle authorStyle =
|
||||
TextStyle(color: Theme.of(context).colorScheme.primary);
|
||||
// type archive ugcSeason
|
||||
// archive 视频/显示发布人
|
||||
// ugcSeason 合集/不显示发布人
|
||||
@@ -39,93 +45,97 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) {
|
||||
// floor 1 2
|
||||
// 1 投稿视频 铺满 borderRadius 0
|
||||
// 2 转发视频 铺满 borderRadius 6
|
||||
Map<dynamic, dynamic> dynamicProperty = {
|
||||
'ugcSeason': item.modules.moduleDynamic.major.ugcSeason,
|
||||
'archive': item.modules.moduleDynamic.major.archive,
|
||||
'pgc': item.modules.moduleDynamic.major.pgc
|
||||
|
||||
DynamicArchiveModel? content = switch (type) {
|
||||
'ugcSeason' => item.modules.moduleDynamic?.major?.ugcSeason,
|
||||
'archive' => item.modules.moduleDynamic?.major?.archive,
|
||||
'pgc' => item.modules.moduleDynamic?.major?.pgc,
|
||||
_ => null,
|
||||
};
|
||||
dynamic content = dynamicProperty[type];
|
||||
InlineSpan? richNodes = richNode(item, context);
|
||||
|
||||
if (content == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
TextSpan? richNodes = richNode(theme, item, context);
|
||||
|
||||
Widget buildCover() {
|
||||
if (content?.cover == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return LayoutBuilder(builder: (context, box) {
|
||||
double width = box.maxWidth;
|
||||
return Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: width,
|
||||
height: width / StyleString.aspectRatio,
|
||||
src: content.cover,
|
||||
semanticsLabel: content.title,
|
||||
),
|
||||
if (content?.badge?['text'] != null)
|
||||
PBadge(
|
||||
text: content.badge['text'],
|
||||
top: 8.0,
|
||||
right: 10.0,
|
||||
bottom: null,
|
||||
left: null,
|
||||
type: content.badge['text'] == '充电专属' ? 'error' : 'primary',
|
||||
return LayoutBuilder(
|
||||
builder: (context, box) {
|
||||
double width = box.maxWidth;
|
||||
return Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: width,
|
||||
height: width / StyleString.aspectRatio,
|
||||
src: content.cover,
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 70,
|
||||
padding: const EdgeInsets.fromLTRB(10, 0, 8, 8),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: <Color>[
|
||||
Colors.transparent,
|
||||
Colors.black54,
|
||||
],
|
||||
if (content.badge?['text'] != null)
|
||||
PBadge(
|
||||
text: content.badge!['text'],
|
||||
top: 8.0,
|
||||
right: 10.0,
|
||||
bottom: null,
|
||||
left: null,
|
||||
type: content.badge!['text'] == '充电专属' ? 'error' : 'primary',
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
height: 70,
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: const EdgeInsets.fromLTRB(10, 0, 8, 8),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Colors.transparent,
|
||||
Colors.black54,
|
||||
],
|
||||
),
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: StyleString.imgRadius,
|
||||
bottomRight: StyleString.imgRadius,
|
||||
),
|
||||
),
|
||||
borderRadius: StyleString.mdRadius,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
DefaultTextStyle.merge(
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white),
|
||||
child: Row(
|
||||
children: [
|
||||
if (content.durationText != null)
|
||||
Text(
|
||||
content.durationText,
|
||||
semanticsLabel:
|
||||
'时长${Utils.durationReadFormat(content.durationText)}',
|
||||
),
|
||||
if (content.durationText != null)
|
||||
const SizedBox(width: 6),
|
||||
Text(content.stat.play + '次围观'),
|
||||
child: DefaultTextStyle.merge(
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (content.durationText != null) ...[
|
||||
Text(
|
||||
content.durationText!,
|
||||
semanticsLabel:
|
||||
'时长${Utils.durationReadFormat(content.durationText!)}',
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(content.stat.danmu + '条弹幕')
|
||||
],
|
||||
),
|
||||
Text('${content.stat?.play}次围观'),
|
||||
const SizedBox(width: 6),
|
||||
Text('${content.stat?.danmu}条弹幕'),
|
||||
const Spacer(),
|
||||
Image.asset(
|
||||
'assets/images/play.png',
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
],
|
||||
),
|
||||
Image.asset(
|
||||
'assets/images/play.png',
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
@@ -137,45 +147,50 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) {
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed(
|
||||
'/member?mid=${item.modules.moduleAuthor.mid}',
|
||||
arguments: {'face': item.modules.moduleAuthor.face}),
|
||||
'/member?mid=${item.modules.moduleAuthor!.mid}',
|
||||
arguments: {'face': item.modules.moduleAuthor!.face},
|
||||
),
|
||||
child: Text(
|
||||
item.modules.moduleAuthor.type == null
|
||||
? '@${item.modules.moduleAuthor.name}'
|
||||
: item.modules.moduleAuthor.name,
|
||||
style: authorStyle,
|
||||
item.modules.moduleAuthor?.type == null
|
||||
? '@${item.modules.moduleAuthor!.name}'
|
||||
: item.modules.moduleAuthor!.name!,
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
Utils.dateFormat(item.modules.moduleAuthor.pubTs),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||
),
|
||||
if (item.modules.moduleAuthor?.pubTs != null)
|
||||
Text(
|
||||
Utils.dateFormat(item.modules.moduleAuthor!.pubTs),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
if (floor == 2 && item.modules.moduleDynamic.desc != null) ...[
|
||||
if (richNodes != null) Text.rich(richNodes),
|
||||
if (floor == 2 && content.desc != null && richNodes != null) ...[
|
||||
Text.rich(richNodes),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
if (item.isForwarded == true)
|
||||
buildCover()
|
||||
else
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: buildCover(),
|
||||
),
|
||||
if (content.cover != null)
|
||||
if (item.isForwarded == true)
|
||||
buildCover()
|
||||
else
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: buildCover(),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
if (content?.title != null)
|
||||
if (content.title != null)
|
||||
Padding(
|
||||
padding: floor == 1
|
||||
? const EdgeInsets.only(left: 12, right: 12)
|
||||
: EdgeInsets.zero,
|
||||
child: Text(
|
||||
content.title,
|
||||
content.title!,
|
||||
maxLines: source == 'detail' ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
|
||||
@@ -17,6 +17,7 @@ class FavArticleItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: Stack(
|
||||
@@ -66,10 +67,7 @@ class FavArticleItem extends StatelessWidget {
|
||||
child: Text(
|
||||
item['content'],
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.fontSize,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
@@ -83,7 +81,7 @@ class FavArticleItem extends StatelessWidget {
|
||||
// context: context,
|
||||
// value: item['stat']['view'],
|
||||
// goto: 'picture',
|
||||
// textColor: Theme.of(context).colorScheme.outline,
|
||||
// textColor: theme.colorScheme.outline,
|
||||
// ),
|
||||
// const SizedBox(width: 16),
|
||||
StatView(
|
||||
@@ -92,7 +90,7 @@ class FavArticleItem extends StatelessWidget {
|
||||
value: item['stat']['like'] == ''
|
||||
? 0
|
||||
: item['stat']['like'],
|
||||
textColor: Theme.of(context).colorScheme.outline,
|
||||
textColor: theme.colorScheme.outline,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -103,7 +101,7 @@ class FavArticleItem extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
),
|
||||
@@ -122,7 +120,7 @@ class FavArticleItem extends StatelessWidget {
|
||||
context: context,
|
||||
onPressed: onDelete,
|
||||
icon: Icons.clear,
|
||||
iconColor: Theme.of(context).colorScheme.outline,
|
||||
iconColor: theme.colorScheme.outline,
|
||||
bgColor: Colors.transparent,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -28,6 +28,7 @@ class _FavNoteChildPageState extends State<FavNoteChildPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) => Stack(
|
||||
clipBehavior: Clip.none,
|
||||
@@ -55,14 +56,11 @@ class _FavNoteChildPageState extends State<FavNoteChildPage>
|
||||
child: Container(
|
||||
padding: MediaQuery.paddingOf(context),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
width: 0.5,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.5),
|
||||
color: theme.colorScheme.outline.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -25,6 +25,7 @@ class _FavNotePageState extends State<FavNotePage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -43,7 +44,7 @@ class _FavNotePageState extends State<FavNotePage>
|
||||
indicatorPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 3, vertical: 8),
|
||||
indicator: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
@@ -51,8 +52,8 @@ class _FavNotePageState extends State<FavNotePage>
|
||||
.labelStyle
|
||||
?.copyWith(fontSize: 14) ??
|
||||
const TextStyle(fontSize: 14),
|
||||
labelColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
unselectedLabelColor: Theme.of(context).colorScheme.outline,
|
||||
labelColor: theme.colorScheme.onSecondaryContainer,
|
||||
unselectedLabelColor: theme.colorScheme.outline,
|
||||
tabs: [
|
||||
Tab(text: '未发布笔记'),
|
||||
Tab(text: '公开笔记'),
|
||||
@@ -61,7 +62,7 @@ class _FavNotePageState extends State<FavNotePage>
|
||||
),
|
||||
// TextButton(
|
||||
// style: TextButton.styleFrom(
|
||||
// foregroundColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
// foregroundColor: theme.colorScheme.onSurfaceVariant,
|
||||
// visualDensity: VisualDensity(horizontal: -2, vertical: -2),
|
||||
// tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
// ),
|
||||
|
||||
@@ -19,6 +19,7 @@ class FavNoteItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
@@ -72,7 +73,7 @@ class FavNoteItem extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
),
|
||||
@@ -83,7 +84,7 @@ class FavNoteItem extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
),
|
||||
@@ -137,9 +138,7 @@ class FavNoteItem extends StatelessWidget {
|
||||
backgroundColor:
|
||||
WidgetStateProperty.resolveWith(
|
||||
(states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.surface
|
||||
return theme.colorScheme.surface
|
||||
.withOpacity(0.8);
|
||||
},
|
||||
),
|
||||
@@ -147,9 +146,7 @@ class FavNoteItem extends StatelessWidget {
|
||||
onPressed: null,
|
||||
icon: Icon(
|
||||
Icons.done_all_outlined,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -35,6 +35,7 @@ class _FavPgcChildPageState extends State<FavPgcChildPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) => Stack(
|
||||
clipBehavior: Clip.none,
|
||||
@@ -62,14 +63,11 @@ class _FavPgcChildPageState extends State<FavPgcChildPage>
|
||||
child: Container(
|
||||
padding: MediaQuery.paddingOf(context),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
width: 0.5,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.5),
|
||||
color: theme.colorScheme.outline.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -135,9 +133,7 @@ class _FavPgcChildPageState extends State<FavPgcChildPage>
|
||||
child: Text(
|
||||
'标记为${item['title']}',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -27,6 +27,7 @@ class _FavPgcPageState extends State<FavPgcPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -45,7 +46,7 @@ class _FavPgcPageState extends State<FavPgcPage>
|
||||
indicatorPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 3, vertical: 8),
|
||||
indicator: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
@@ -53,8 +54,8 @@ class _FavPgcPageState extends State<FavPgcPage>
|
||||
.labelStyle
|
||||
?.copyWith(fontSize: 14) ??
|
||||
const TextStyle(fontSize: 14),
|
||||
labelColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
unselectedLabelColor: Theme.of(context).colorScheme.outline,
|
||||
labelColor: theme.colorScheme.onSecondaryContainer,
|
||||
unselectedLabelColor: theme.colorScheme.outline,
|
||||
tabs: const [
|
||||
Tab(text: '想看'),
|
||||
Tab(text: '在看'),
|
||||
@@ -64,7 +65,7 @@ class _FavPgcPageState extends State<FavPgcPage>
|
||||
),
|
||||
// TextButton(
|
||||
// style: TextButton.styleFrom(
|
||||
// foregroundColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
// foregroundColor: theme.colorScheme.onSurfaceVariant,
|
||||
// visualDensity: VisualDensity(horizontal: -2, vertical: -2),
|
||||
// tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
// ),
|
||||
|
||||
@@ -23,6 +23,7 @@ class FavPgcItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: Stack(
|
||||
@@ -108,9 +109,8 @@ class FavPgcItem extends StatelessWidget {
|
||||
WidgetStateProperty
|
||||
.resolveWith(
|
||||
(states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.surface
|
||||
return theme
|
||||
.colorScheme.surface
|
||||
.withOpacity(0.8);
|
||||
},
|
||||
),
|
||||
@@ -118,9 +118,7 @@ class FavPgcItem extends StatelessWidget {
|
||||
onPressed: null,
|
||||
icon: Icon(
|
||||
Icons.done_all_outlined,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -148,9 +146,7 @@ class FavPgcItem extends StatelessWidget {
|
||||
'${item.newEp?['index_show']}${item.isFinish == 0 && item.renewalTime?.isNotEmpty == true ? ',${item.renewalTime}' : ''}',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -162,9 +158,7 @@ class FavPgcItem extends StatelessWidget {
|
||||
item.progress!,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -183,7 +177,7 @@ class FavPgcItem extends StatelessWidget {
|
||||
context: context,
|
||||
onPressed: onUpdateStatus,
|
||||
icon: Icons.more_vert,
|
||||
iconColor: Theme.of(context).colorScheme.outline,
|
||||
iconColor: theme.colorScheme.outline,
|
||||
bgColor: Colors.transparent,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -27,7 +27,6 @@ class FavItem extends StatelessWidget {
|
||||
(onTap == null
|
||||
? null
|
||||
: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: favFolderItem.title,
|
||||
cover: favFolderItem.cover,
|
||||
)),
|
||||
@@ -61,6 +60,9 @@ class FavItem extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
final fontSize = theme.textTheme.labelMedium!.fontSize;
|
||||
final color = theme.colorScheme.outline;
|
||||
return Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -76,23 +78,23 @@ class FavItem extends StatelessWidget {
|
||||
Text(
|
||||
favFolderItem.intro!,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${favFolderItem.mediaCount}个内容',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
Utils.isPublicFavText(favFolderItem.attr ?? 0),
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -56,6 +56,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Obx(
|
||||
() => PopScope(
|
||||
canPop: _favDetailController.enableMultiSelect.value.not,
|
||||
@@ -111,13 +112,11 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
children: [
|
||||
Text(
|
||||
_favDetailController.item.value.title ?? '',
|
||||
style:
|
||||
Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
'共${_favDetailController.item.value.mediaCount}条视频',
|
||||
style:
|
||||
Theme.of(context).textTheme.labelMedium,
|
||||
style: theme.textTheme.labelMedium,
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -152,9 +151,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
child: Text(
|
||||
'复制',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -176,9 +173,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
child: Text(
|
||||
'移动',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -191,8 +186,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
_favDetailController.onDelChecked(context),
|
||||
child: Text(
|
||||
'删除',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error),
|
||||
style:
|
||||
TextStyle(color: theme.colorScheme.error),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
@@ -310,9 +305,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
child: Text(
|
||||
'删除',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.error,
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -362,10 +355,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
.item.value.title ??
|
||||
'',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.fontSize,
|
||||
fontSize: theme.textTheme
|
||||
.titleMedium!.fontSize,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (_favDetailController
|
||||
@@ -376,13 +367,10 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
.item.value.intro ??
|
||||
'',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline),
|
||||
fontSize: theme.textTheme
|
||||
.labelSmall!.fontSize,
|
||||
color:
|
||||
theme.colorScheme.outline),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
@@ -390,13 +378,9 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
.item.value.upper?.name ??
|
||||
'',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline),
|
||||
fontSize: theme.textTheme
|
||||
.labelSmall!.fontSize,
|
||||
color: theme.colorScheme.outline),
|
||||
),
|
||||
const Spacer(),
|
||||
if (_favDetailController
|
||||
@@ -405,13 +389,10 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
Text(
|
||||
'共${_favDetailController.item.value.mediaCount}条视频 · ${Utils.isPublicFavText(_favDetailController.item.value.attr ?? 0)}',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline),
|
||||
fontSize: theme.textTheme
|
||||
.labelSmall!.fontSize,
|
||||
color:
|
||||
theme.colorScheme.outline),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -424,8 +405,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(() =>
|
||||
_buildBody(_favDetailController.loadingState.value)),
|
||||
Obx(() => _buildBody(
|
||||
theme, _favDetailController.loadingState.value)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -435,7 +416,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<FavDetailItemData>?> loadingState) {
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<FavDetailItemData>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverGrid(
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
@@ -463,7 +445,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
child: Text(
|
||||
_favDetailController.isEnd.not ? '加载中...' : '没有更多了',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
@@ -552,9 +534,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
backgroundColor:
|
||||
WidgetStateProperty.resolveWith(
|
||||
(states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.surface
|
||||
return theme.colorScheme.surface
|
||||
.withOpacity(0.8);
|
||||
},
|
||||
),
|
||||
@@ -562,9 +542,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
onPressed: null,
|
||||
icon: Icon(
|
||||
Icons.done_all_outlined,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -75,7 +75,6 @@ class FavVideoCardH extends StatelessWidget {
|
||||
onLongPress!();
|
||||
} else {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: videoItem.title,
|
||||
cover: videoItem.pic,
|
||||
);
|
||||
@@ -130,6 +129,7 @@ class FavVideoCardH extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
@@ -154,7 +154,7 @@ class FavVideoCardH extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
@@ -184,7 +184,7 @@ class FavVideoCardH extends StatelessWidget {
|
||||
context: context,
|
||||
icon: Icons.clear,
|
||||
tooltip: '取消收藏',
|
||||
iconColor: Theme.of(context).colorScheme.outline,
|
||||
iconColor: theme.colorScheme.outline,
|
||||
bgColor: Colors.transparent,
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
@@ -198,8 +198,8 @@ class FavVideoCardH extends StatelessWidget {
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline),
|
||||
style:
|
||||
TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
|
||||
@@ -23,6 +23,7 @@ class FollowItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
String heroTag = Utils.makeHeroTag(item.mid);
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
@@ -60,7 +61,7 @@ class FollowItem extends StatelessWidget {
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.surface,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.offline_bolt,
|
||||
@@ -99,12 +100,11 @@ class FollowItem extends StatelessWidget {
|
||||
},
|
||||
style: FilledButton.styleFrom(
|
||||
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
foregroundColor: item.attribute == -1
|
||||
? null
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
foregroundColor:
|
||||
item.attribute == -1 ? null : theme.colorScheme.outline,
|
||||
backgroundColor: item.attribute == -1
|
||||
? null
|
||||
: Theme.of(context).colorScheme.onInverseSurface,
|
||||
: theme.colorScheme.onInverseSurface,
|
||||
),
|
||||
child: Text(
|
||||
'${item.attribute == -1 ? '' : '已'}关注',
|
||||
|
||||
@@ -36,6 +36,7 @@ class HistoryItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
int aid = videoItem.history.oid!;
|
||||
String bvid = videoItem.history.bvid ?? IdUtils.av2bv(aid);
|
||||
return InkWell(
|
||||
@@ -112,7 +113,6 @@ class HistoryItem extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: videoItem.title,
|
||||
cover: videoItem.cover,
|
||||
);
|
||||
@@ -200,9 +200,7 @@ class HistoryItem extends StatelessWidget {
|
||||
backgroundColor:
|
||||
WidgetStateProperty.resolveWith(
|
||||
(states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.surface
|
||||
return theme.colorScheme.surface
|
||||
.withOpacity(0.8);
|
||||
},
|
||||
),
|
||||
@@ -212,8 +210,7 @@ class HistoryItem extends StatelessWidget {
|
||||
onChoose?.call();
|
||||
},
|
||||
icon: Icon(Icons.done_all_outlined,
|
||||
color:
|
||||
Theme.of(context).colorScheme.primary),
|
||||
color: theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -237,7 +234,7 @@ class HistoryItem extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
videoContent(theme),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -252,7 +249,7 @@ class HistoryItem extends StatelessWidget {
|
||||
tooltip: '功能菜单',
|
||||
icon: Icon(
|
||||
Icons.more_vert_outlined,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
size: 18,
|
||||
),
|
||||
position: PopupMenuPosition.under,
|
||||
@@ -321,7 +318,7 @@ class HistoryItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
Widget videoContent(ThemeData theme) {
|
||||
return Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -331,7 +328,7 @@ class HistoryItem extends StatelessWidget {
|
||||
videoItem.title,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
@@ -343,16 +340,16 @@ class HistoryItem extends StatelessWidget {
|
||||
Text(
|
||||
videoItem.authorName!,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
Utils.dateFormat(videoItem.viewAt!),
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -30,6 +30,7 @@ class _HomePageState extends State<HomePage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(toolbarHeight: 0),
|
||||
@@ -37,10 +38,10 @@ class _HomePageState extends State<HomePage>
|
||||
children: [
|
||||
if (!_homeController.useSideBar &&
|
||||
context.orientation == Orientation.portrait)
|
||||
customAppBar,
|
||||
customAppBar(theme),
|
||||
if (_homeController.tabs.length > 1)
|
||||
Material(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.surface,
|
||||
child: Container(
|
||||
height: 42,
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
@@ -78,10 +79,10 @@ class _HomePageState extends State<HomePage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget get searchBarAndUser {
|
||||
Widget searchBarAndUser(ThemeData theme) {
|
||||
return Row(
|
||||
children: [
|
||||
searchBar,
|
||||
searchBar(theme),
|
||||
const SizedBox(width: 4),
|
||||
Obx(
|
||||
() => _homeController.isLogin.value
|
||||
@@ -108,9 +109,7 @@ class _HomePageState extends State<HomePage>
|
||||
child: InkWell(
|
||||
onTap: () =>
|
||||
_homeController.showUserInfoDialog(context),
|
||||
splashColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
splashColor: theme.colorScheme.primaryContainer
|
||||
.withOpacity(0.3),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
@@ -126,17 +125,14 @@ class _HomePageState extends State<HomePage>
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
size: 16,
|
||||
MdiIcons.incognito,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer,
|
||||
color:
|
||||
theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -144,7 +140,8 @@ class _HomePageState extends State<HomePage>
|
||||
),
|
||||
],
|
||||
)
|
||||
: DefaultUser(
|
||||
: defaultUser(
|
||||
theme: theme,
|
||||
onPressed: () =>
|
||||
_homeController.showUserInfoDialog(context),
|
||||
),
|
||||
@@ -154,7 +151,7 @@ class _HomePageState extends State<HomePage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget get customAppBar {
|
||||
Widget customAppBar(ThemeData theme) {
|
||||
return StreamBuilder(
|
||||
stream: _homeController.hideSearchBar
|
||||
? _mainController.navSearchStreamDebounce
|
||||
@@ -173,14 +170,14 @@ class _HomePageState extends State<HomePage>
|
||||
duration: const Duration(milliseconds: 500),
|
||||
height: snapshot.data ? 52 : 0,
|
||||
padding: const EdgeInsets.fromLTRB(14, 6, 14, 0),
|
||||
child: searchBarAndUser,
|
||||
child: searchBarAndUser(theme),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget get searchBar {
|
||||
Widget searchBar(ThemeData theme) {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
height: 44,
|
||||
@@ -189,13 +186,9 @@ class _HomePageState extends State<HomePage>
|
||||
borderRadius: BorderRadius.circular(25),
|
||||
),
|
||||
child: Material(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
.withOpacity(0.05),
|
||||
color: theme.colorScheme.onSecondaryContainer.withOpacity(0.05),
|
||||
child: InkWell(
|
||||
splashColor:
|
||||
Theme.of(context).colorScheme.primaryContainer.withOpacity(0.3),
|
||||
splashColor: theme.colorScheme.primaryContainer.withOpacity(0.3),
|
||||
onTap: () => Get.toNamed(
|
||||
'/search',
|
||||
parameters: {
|
||||
@@ -208,7 +201,7 @@ class _HomePageState extends State<HomePage>
|
||||
const SizedBox(width: 14),
|
||||
Icon(
|
||||
Icons.search_outlined,
|
||||
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
color: theme.colorScheme.onSecondaryContainer,
|
||||
semanticLabel: '搜索',
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
@@ -219,8 +212,7 @@ class _HomePageState extends State<HomePage>
|
||||
_homeController.defaultSearch.value,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline),
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -235,32 +227,29 @@ class _HomePageState extends State<HomePage>
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultUser extends StatelessWidget {
|
||||
const DefaultUser({super.key, required this.onPressed});
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 38,
|
||||
height: 38,
|
||||
child: IconButton(
|
||||
tooltip: '默认用户头像',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
return Theme.of(context).colorScheme.onInverseSurface;
|
||||
}),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
icon: Icon(
|
||||
Icons.person_rounded,
|
||||
size: 22,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Widget defaultUser({
|
||||
required ThemeData theme,
|
||||
required VoidCallback onPressed,
|
||||
}) {
|
||||
return SizedBox(
|
||||
width: 38,
|
||||
height: 38,
|
||||
child: IconButton(
|
||||
tooltip: '默认用户头像',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
return theme.colorScheme.onInverseSurface;
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
onPressed: onPressed,
|
||||
icon: Icon(
|
||||
Icons.person_rounded,
|
||||
size: 22,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget msgBadge(MainController mainController) {
|
||||
|
||||
@@ -61,6 +61,7 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<HotVideoItemModel>?> loadingState) {
|
||||
final theme = Theme.of(context);
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverGrid(
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
@@ -150,9 +151,7 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
|
||||
backgroundColor:
|
||||
WidgetStateProperty.resolveWith(
|
||||
(states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.surface
|
||||
return theme.colorScheme.surface
|
||||
.withOpacity(0.8);
|
||||
},
|
||||
),
|
||||
@@ -160,9 +159,7 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
|
||||
onPressed: null,
|
||||
icon: Icon(
|
||||
Icons.done_all_outlined,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -186,7 +183,7 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
|
||||
);
|
||||
},
|
||||
icon: Icons.clear,
|
||||
iconColor: Theme.of(context).colorScheme.outline,
|
||||
iconColor: theme.colorScheme.outline,
|
||||
bgColor: Colors.transparent,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -129,7 +129,8 @@ class _LaterPageState extends State<LaterPage>
|
||||
}
|
||||
|
||||
PreferredSizeWidget get _buildAppbar {
|
||||
Color color = Theme.of(context).colorScheme.secondary;
|
||||
final theme = Theme.of(context);
|
||||
Color color = theme.colorScheme.secondary;
|
||||
|
||||
return AppBarWidget(
|
||||
visible: _baseCtr.enableMultiSelect.value,
|
||||
@@ -284,7 +285,7 @@ class _LaterPageState extends State<LaterPage>
|
||||
child: Text(
|
||||
'复制',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -305,7 +306,7 @@ class _LaterPageState extends State<LaterPage>
|
||||
child: Text(
|
||||
'移动',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -316,7 +317,7 @@ class _LaterPageState extends State<LaterPage>
|
||||
onPressed: () => currCtr().onDelChecked(context),
|
||||
child: Text(
|
||||
'移除',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
style: TextStyle(color: theme.colorScheme.error),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
|
||||
@@ -120,6 +120,7 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
||||
}
|
||||
|
||||
Widget _buildFollowList() {
|
||||
final theme = Theme.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -135,14 +136,14 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
||||
text: '${controller.liveCount.value}',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: '人正在直播',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -160,25 +161,25 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
||||
Text(
|
||||
'查看更多',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
size: 20,
|
||||
Icons.keyboard_arrow_right_outlined,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Obx(() => _buildFollowBody(controller.followListState.value)),
|
||||
Obx(() => _buildFollowBody(theme, controller.followListState.value)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFollowBody(LoadingState loadingState) {
|
||||
Widget _buildFollowBody(ThemeData theme, LoadingState loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SizedBox(
|
||||
height: 80,
|
||||
@@ -223,7 +224,7 @@ class _LivePageState extends CommonPageState<LivePage, LiveController>
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 1.5,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
strokeAlign: BorderSide.strokeAlignOutside,
|
||||
),
|
||||
shape: BoxShape.circle,
|
||||
|
||||
@@ -26,7 +26,6 @@ class LiveCardV extends StatelessWidget {
|
||||
Get.toNamed('/liveRoom?roomid=${liveItem.roomId}');
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: liveItem.title,
|
||||
cover: liveItem.cover,
|
||||
),
|
||||
@@ -72,6 +71,7 @@ class LiveCardV extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget liveContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
@@ -96,9 +96,8 @@ class LiveCardV extends StatelessWidget {
|
||||
'${liveItem.uname}',
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
@@ -26,7 +26,6 @@ class LiveCardVFollow extends StatelessWidget {
|
||||
Get.toNamed('/liveRoom?roomid=${liveItem.roomId}');
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: liveItem.title,
|
||||
cover: liveItem.roomCover,
|
||||
),
|
||||
@@ -72,6 +71,7 @@ class LiveCardVFollow extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget liveContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
@@ -96,9 +96,8 @@ class LiveCardVFollow extends StatelessWidget {
|
||||
'${liveItem.uname}',
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
@@ -48,6 +48,7 @@ class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return MediaQuery.removePadding(
|
||||
removeTop: true,
|
||||
context: context,
|
||||
@@ -67,9 +68,8 @@ class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
buildInputView(),
|
||||
buildPanelContainer(
|
||||
Theme.of(context).colorScheme.surface),
|
||||
buildInputView(theme),
|
||||
buildPanelContainer(theme.colorScheme.surface),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -98,7 +98,7 @@ class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
|
||||
),
|
||||
);
|
||||
|
||||
Widget buildInputView() {
|
||||
Widget buildInputView(ThemeData theme) {
|
||||
return Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
||||
@@ -107,7 +107,7 @@ class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
|
||||
topLeft: Radius.circular(12),
|
||||
topRight: Radius.circular(12),
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.surface,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -145,7 +145,7 @@ class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
|
||||
hintText: "输入弹幕内容",
|
||||
border: InputBorder.none,
|
||||
hintStyle: TextStyle(fontSize: 14)),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
style: theme.textTheme.bodyLarge,
|
||||
inputFormatters: [LengthLimitingTextInputFormatter(20)],
|
||||
),
|
||||
),
|
||||
@@ -154,7 +154,7 @@ class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
|
||||
),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
color: theme.dividerColor.withOpacity(0.1),
|
||||
),
|
||||
Container(
|
||||
height: 52,
|
||||
|
||||
@@ -26,7 +26,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
bool showPassword = false;
|
||||
GlobalKey globalKey = GlobalKey();
|
||||
|
||||
Widget loginByQRCode() {
|
||||
Widget loginByQRCode(ThemeData theme) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
@@ -35,7 +35,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
Obx(() => Text('剩余有效时间: ${_loginPageCtr.qrCodeLeftTime} 秒',
|
||||
style: TextStyle(
|
||||
fontFeatures: const [FontFeature.tabularFigures()],
|
||||
color: Theme.of(context).colorScheme.primaryFixedDim))),
|
||||
color: theme.colorScheme.primaryFixedDim))),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@@ -110,8 +110,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
const SizedBox(height: 10),
|
||||
Obx(() => Text(
|
||||
_loginPageCtr.statusQRCode.value,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondaryFixedDim),
|
||||
style: TextStyle(color: theme.colorScheme.secondaryFixedDim),
|
||||
)),
|
||||
Obx(() => GestureDetector(
|
||||
onTap: () {
|
||||
@@ -123,26 +122,20 @@ class _LoginPageState extends State<LoginPage> {
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
|
||||
child: Text(_loginPageCtr.codeInfo['data']?['url'] ?? "",
|
||||
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withOpacity(0.4))),
|
||||
style: theme.textTheme.labelSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurface.withOpacity(0.4))),
|
||||
),
|
||||
)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Text('请务必在 PiliPlus 开源仓库等可信渠道下载安装。',
|
||||
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withOpacity(0.4)))),
|
||||
style: theme.textTheme.labelSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurface.withOpacity(0.4)))),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget loginByCookie() {
|
||||
Widget loginByCookie(ThemeData theme) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -153,9 +146,9 @@ class _LoginPageState extends State<LoginPage> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Text(
|
||||
'使用App端Api实现的功能将不可用',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@@ -186,7 +179,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget loginByPassword() {
|
||||
Widget loginByPassword(ThemeData theme) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
@@ -317,16 +310,13 @@ class _LoginPageState extends State<LoginPage> {
|
||||
'账号密码仅用于该登录接口,不予保存;本地仅存储登录凭证。\n'
|
||||
'请务必在 PiliPlus 开源仓库等可信渠道下载安装。',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withOpacity(0.4)))),
|
||||
style: theme.textTheme.labelSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurface.withOpacity(0.4)))),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget loginBySmS() {
|
||||
Widget loginBySmS(ThemeData theme) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
@@ -337,15 +327,14 @@ class _LoginPageState extends State<LoginPage> {
|
||||
child: Container(
|
||||
decoration: UnderlineTabIndicator(
|
||||
borderSide: BorderSide(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline.withOpacity(0.4)),
|
||||
color: theme.colorScheme.outline.withOpacity(0.4)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(width: 12),
|
||||
Icon(
|
||||
Icons.phone,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
PopupMenuButton<Map<String, dynamic>>(
|
||||
@@ -379,10 +368,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
SizedBox(
|
||||
height: 24,
|
||||
child: VerticalDivider(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.5),
|
||||
color: theme.colorScheme.outline.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
@@ -410,8 +396,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
child: Container(
|
||||
decoration: UnderlineTabIndicator(
|
||||
borderSide: BorderSide(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline.withOpacity(0.4)),
|
||||
color: theme.colorScheme.outline.withOpacity(0.4)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -455,17 +440,15 @@ class _LoginPageState extends State<LoginPage> {
|
||||
'本地仅存储登录凭证。\n'
|
||||
'请务必在 PiliPlus 开源仓库等可信渠道下载安装。',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withOpacity(0.4)))),
|
||||
style: theme.textTheme.labelSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurface.withOpacity(0.4)))),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return OrientationBuilder(builder: (context, orientation) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -542,10 +525,10 @@ class _LoginPageState extends State<LoginPage> {
|
||||
child: tabBarView(
|
||||
controller: _loginPageCtr.tabController,
|
||||
children: [
|
||||
tabViewOuter(loginByPassword()),
|
||||
tabViewOuter(loginBySmS()),
|
||||
tabViewOuter(loginByQRCode()),
|
||||
tabViewOuter(loginByCookie()),
|
||||
tabViewOuter(loginByPassword(theme)),
|
||||
tabViewOuter(loginBySmS(theme)),
|
||||
tabViewOuter(loginByQRCode(theme)),
|
||||
tabViewOuter(loginByCookie(theme)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -173,6 +173,7 @@ class _MainAppState extends State<MainApp>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final bool isPortrait = context.orientation == Orientation.portrait;
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
@@ -192,8 +193,7 @@ class _MainAppState extends State<MainApp>
|
||||
child: AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle(
|
||||
systemNavigationBarColor: Colors.transparent,
|
||||
systemNavigationBarIconBrightness:
|
||||
Theme.of(context).brightness.reverse,
|
||||
systemNavigationBarIconBrightness: theme.brightness.reverse,
|
||||
),
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
@@ -210,7 +210,7 @@ class _MainAppState extends State<MainApp>
|
||||
SizedBox(
|
||||
height:
|
||||
MediaQuery.paddingOf(context).top + 50),
|
||||
userAndSearchVertical,
|
||||
userAndSearchVertical(theme),
|
||||
const Spacer(flex: 2),
|
||||
Expanded(
|
||||
flex: 5,
|
||||
@@ -259,7 +259,7 @@ class _MainAppState extends State<MainApp>
|
||||
_mainController.selectedIndex.value,
|
||||
onDestinationSelected: setIndex,
|
||||
labelType: NavigationRailLabelType.selected,
|
||||
leading: userAndSearchVertical,
|
||||
leading: userAndSearchVertical(theme),
|
||||
destinations: _mainController.navigationBars
|
||||
.map(
|
||||
(e) => NavigationRailDestination(
|
||||
@@ -285,7 +285,7 @@ class _MainAppState extends State<MainApp>
|
||||
top: 10,
|
||||
),
|
||||
width: 80,
|
||||
child: userAndSearchVertical,
|
||||
child: userAndSearchVertical(theme),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -293,8 +293,7 @@ class _MainAppState extends State<MainApp>
|
||||
width: 1,
|
||||
indent: MediaQuery.of(context).padding.top,
|
||||
endIndent: MediaQuery.of(context).padding.bottom,
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline.withOpacity(0.06),
|
||||
color: theme.colorScheme.outline.withOpacity(0.06),
|
||||
),
|
||||
],
|
||||
Expanded(
|
||||
@@ -418,7 +417,7 @@ class _MainAppState extends State<MainApp>
|
||||
)
|
||||
: icon;
|
||||
|
||||
Widget get userAndSearchVertical {
|
||||
Widget userAndSearchVertical(ThemeData theme) {
|
||||
return Column(
|
||||
children: [
|
||||
Semantics(
|
||||
@@ -440,9 +439,7 @@ class _MainAppState extends State<MainApp>
|
||||
child: InkWell(
|
||||
onTap: () =>
|
||||
_homeController.showUserInfoDialog(context),
|
||||
splashColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
splashColor: theme.colorScheme.primaryContainer
|
||||
.withOpacity(0.3),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
@@ -458,17 +455,14 @@ class _MainAppState extends State<MainApp>
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
size: 16,
|
||||
MdiIcons.incognito,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer,
|
||||
color:
|
||||
theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -476,9 +470,11 @@ class _MainAppState extends State<MainApp>
|
||||
),
|
||||
],
|
||||
)
|
||||
: DefaultUser(
|
||||
: defaultUser(
|
||||
theme: theme,
|
||||
onPressed: () =>
|
||||
_homeController.showUserInfoDialog(context)),
|
||||
_homeController.showUserInfoDialog(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
@@ -39,7 +39,8 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
Color primary = Theme.of(context).colorScheme.primary;
|
||||
final theme = Theme.of(context);
|
||||
Color primary = theme.colorScheme.primary;
|
||||
return MediaQuery.removePadding(
|
||||
context: context,
|
||||
removeLeft: context.orientation == Orientation.landscape,
|
||||
@@ -59,7 +60,7 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
child: Text(
|
||||
'媒体库',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.titleLarge!.fontSize,
|
||||
fontSize: theme.textTheme.titleLarge!.fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -97,7 +98,7 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
Obx(
|
||||
() => controller.loadingState.value is Loading
|
||||
? const SizedBox.shrink()
|
||||
: favFolder(),
|
||||
: favFolder(theme),
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -105,12 +106,12 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
);
|
||||
}
|
||||
|
||||
Widget favFolder() {
|
||||
Widget favFolder(ThemeData theme) {
|
||||
return Column(
|
||||
children: [
|
||||
Divider(
|
||||
height: 20,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
color: theme.dividerColor.withOpacity(0.1),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
@@ -129,24 +130,22 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
TextSpan(
|
||||
text: '我的收藏 ',
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.titleMedium!.fontSize,
|
||||
fontSize: theme.textTheme.titleMedium!.fontSize,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (controller.count.value != -1)
|
||||
TextSpan(
|
||||
text: "${controller.count.value} ",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
Theme.of(context).textTheme.titleSmall!.fontSize,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontSize: theme.textTheme.titleSmall!.fontSize,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
WidgetSpan(
|
||||
child: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -163,14 +162,14 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 200,
|
||||
child: Obx(() => _buildBody(controller.loadingState.value)),
|
||||
child: Obx(() => _buildBody(theme, controller.loadingState.value)),
|
||||
),
|
||||
const SizedBox(height: 100),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState loadingState) {
|
||||
Widget _buildBody(ThemeData theme, LoadingState loadingState) {
|
||||
if (loadingState is Success) {
|
||||
List<FavFolderItemData>? favFolderList = loadingState.response.list;
|
||||
if (favFolderList.isNullOrEmpty) {
|
||||
@@ -189,9 +188,7 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: WidgetStateProperty.resolveWith((states) {
|
||||
return Theme.of(context)
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
return theme.colorScheme.primaryContainer
|
||||
.withOpacity(0.5);
|
||||
}),
|
||||
),
|
||||
@@ -204,7 +201,7 @@ class _MediaPageState extends CommonPageState<MediaPage, MediaController>
|
||||
icon: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -266,6 +263,7 @@ class FavFolderItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Container(
|
||||
margin: EdgeInsets.only(left: index == 0 ? 20 : 0, right: 14),
|
||||
child: GestureDetector(
|
||||
@@ -282,16 +280,10 @@ class FavFolderItem extends StatelessWidget {
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onInverseSurface
|
||||
.withOpacity(0.4),
|
||||
color: theme.colorScheme.onInverseSurface.withOpacity(0.4),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onInverseSurface
|
||||
.withOpacity(0.4),
|
||||
color: theme.colorScheme.onInverseSurface.withOpacity(0.4),
|
||||
offset: const Offset(4, -12),
|
||||
blurRadius: 0.0,
|
||||
spreadRadius: 0.0,
|
||||
@@ -318,10 +310,8 @@ class FavFolderItem extends StatelessWidget {
|
||||
),
|
||||
Text(
|
||||
' 共${item!.mediaCount}条视频 · ${Utils.isPublicFavText(item?.attr ?? 0)}',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline),
|
||||
style: theme.textTheme.labelSmall!
|
||||
.copyWith(color: theme.colorScheme.outline),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
||||
@@ -13,6 +13,8 @@ class MemberArticleItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final outline = theme.colorScheme.outline;
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
@@ -23,7 +25,6 @@ class MemberArticleItem extends StatelessWidget {
|
||||
},
|
||||
onLongPress: () {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: item.title,
|
||||
cover: item.originImageUrls?.firstOrNull,
|
||||
);
|
||||
@@ -65,10 +66,7 @@ class MemberArticleItem extends StatelessWidget {
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.fontSize,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
@@ -80,7 +78,7 @@ class MemberArticleItem extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
@@ -90,14 +88,14 @@ class MemberArticleItem extends StatelessWidget {
|
||||
context: context,
|
||||
value: item.stats?.view ?? 0,
|
||||
goto: 'picture',
|
||||
textColor: Theme.of(context).colorScheme.outline,
|
||||
textColor: outline,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
StatView(
|
||||
context: context,
|
||||
goto: 'reply',
|
||||
value: item.stats?.reply ?? 0,
|
||||
textColor: Theme.of(context).colorScheme.outline,
|
||||
textColor: outline,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -39,6 +39,7 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
||||
}
|
||||
|
||||
_buildBody(LoadingState loadingState) {
|
||||
final theme = Theme.of(context);
|
||||
return switch (loadingState) {
|
||||
Loading() => loadingWidget,
|
||||
Success() => (loadingState.response as List?)?.isNotEmpty == true
|
||||
@@ -50,12 +51,12 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Obx(
|
||||
() => _buildItem(_controller.first.value, true),
|
||||
() => _buildItem(theme, _controller.first.value, true),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Obx(
|
||||
() => _buildItem(_controller.second.value, false),
|
||||
() => _buildItem(theme, _controller.second.value, false),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
@@ -76,9 +77,9 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
||||
};
|
||||
}
|
||||
|
||||
_buildItem(Datum data, bool isFirst) {
|
||||
_buildItem(ThemeData theme, Datum data, bool isFirst) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
data: theme.copyWith(
|
||||
dividerColor: Colors.transparent,
|
||||
),
|
||||
child: ExpansionTile(
|
||||
@@ -95,7 +96,7 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
||||
text: ' ${data.mediaListResponse?.count}',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -127,14 +128,14 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
||||
? _controller.firstEnd.value
|
||||
: _controller.secondEnd.value)
|
||||
? const SizedBox.shrink()
|
||||
: _buildLoadMoreItem(isFirst),
|
||||
: _buildLoadMoreItem(theme, isFirst),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_buildLoadMoreItem(bool isFirst) {
|
||||
_buildLoadMoreItem(ThemeData theme, bool isFirst) {
|
||||
return ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
@@ -148,7 +149,7 @@ class _MemberFavoriteState extends State<MemberFavorite>
|
||||
'查看更多内容',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ class MemberFavItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
@@ -58,7 +59,6 @@ class MemberFavItem extends StatelessWidget {
|
||||
},
|
||||
onLongPress: () {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
);
|
||||
@@ -100,12 +100,12 @@ class MemberFavItem extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.video_library_outlined,
|
||||
size: 12,
|
||||
color: Theme.of(context).colorScheme.onPrimary,
|
||||
color: theme.colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -136,7 +136,7 @@ class MemberFavItem extends StatelessWidget {
|
||||
: '${item.mediaCount}个内容',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -19,7 +19,6 @@ class SeasonSeriesCard extends StatelessWidget {
|
||||
return InkWell(
|
||||
onLongPress: () {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: item['meta']['name'],
|
||||
cover: item['meta']['cover'],
|
||||
);
|
||||
@@ -67,6 +66,7 @@ class SeasonSeriesCard extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -75,7 +75,7 @@ class SeasonSeriesCard extends StatelessWidget {
|
||||
item['meta']['name'],
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
@@ -89,7 +89,7 @@ class SeasonSeriesCard extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -61,6 +61,7 @@ class _MemberVideoState extends State<MemberVideo>
|
||||
}
|
||||
|
||||
_buildBody(LoadingState<List<Item>?> loadingState) {
|
||||
final theme = Theme.of(context);
|
||||
return switch (loadingState) {
|
||||
Loading() => loadingWidget,
|
||||
Success() => loadingState.response?.isNotEmpty == true
|
||||
@@ -82,7 +83,7 @@ class _MemberVideoState extends State<MemberVideo>
|
||||
floating: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
extent: 40,
|
||||
bgColor: Theme.of(context).colorScheme.surface,
|
||||
bgColor: theme.colorScheme.surface,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: Row(
|
||||
@@ -115,9 +116,8 @@ class _MemberVideoState extends State<MemberVideo>
|
||||
icon: Icon(
|
||||
Icons.play_circle_outline_rounded,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary,
|
||||
color:
|
||||
theme.colorScheme.secondary,
|
||||
),
|
||||
label: Text(
|
||||
_controller.episodicButton.value
|
||||
@@ -125,9 +125,8 @@ class _MemberVideoState extends State<MemberVideo>
|
||||
'播放全部',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary,
|
||||
color:
|
||||
theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -142,9 +141,7 @@ class _MemberVideoState extends State<MemberVideo>
|
||||
icon: Icon(
|
||||
Icons.sort,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
label: Obx(
|
||||
() => Text(
|
||||
@@ -158,9 +155,7 @@ class _MemberVideoState extends State<MemberVideo>
|
||||
: '倒序',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -40,6 +40,7 @@ class _MemberContributeState extends State<MemberContribute>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return _controller.tabs != null
|
||||
? Column(
|
||||
children: [
|
||||
@@ -58,7 +59,7 @@ class _MemberContributeState extends State<MemberContribute>
|
||||
indicatorPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 3, vertical: 8),
|
||||
indicator: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
@@ -66,9 +67,8 @@ class _MemberContributeState extends State<MemberContribute>
|
||||
.labelStyle
|
||||
?.copyWith(fontSize: 14) ??
|
||||
const TextStyle(fontSize: 14),
|
||||
labelColor:
|
||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
unselectedLabelColor: Theme.of(context).colorScheme.outline,
|
||||
labelColor: theme.colorScheme.onSecondaryContainer,
|
||||
unselectedLabelColor: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
|
||||
@@ -245,100 +245,94 @@ class _MemberHomeState extends State<MemberHome>
|
||||
required String param,
|
||||
String? param1,
|
||||
required int count,
|
||||
}) =>
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text.rich(
|
||||
}) {
|
||||
final color = Theme.of(context).colorScheme.outline;
|
||||
return SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(text: '$title '),
|
||||
TextSpan(
|
||||
text: count.toString(),
|
||||
style: TextStyle(fontSize: 13, color: color),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
int index =
|
||||
_ctr.tab2!.indexWhere((item) => item.param == param);
|
||||
if (index != -1) {
|
||||
if (['video', 'article', 'audio'].contains(param1)) {
|
||||
List<Item> items = _ctr.tab2!
|
||||
.firstWhere((item) => item.param == param)
|
||||
.items!;
|
||||
int index1 =
|
||||
items.indexWhere((item) => item.param == param1);
|
||||
try {
|
||||
final contributeCtr =
|
||||
Get.find<MemberContributeCtr>(tag: widget.heroTag);
|
||||
// contributeCtr.tabController?.animateTo(index1);
|
||||
if (contributeCtr.tabController?.index != index1) {
|
||||
contributeCtr.tabController?.index = index1;
|
||||
}
|
||||
debugPrint('initialized');
|
||||
} catch (e) {
|
||||
_ctr.contributeInitialIndex.value = index1;
|
||||
debugPrint('not initialized');
|
||||
}
|
||||
}
|
||||
_ctr.tabController?.animateTo(index);
|
||||
} else {
|
||||
if (param == 'coinArchive') {
|
||||
Get.to(MemberCoinPage(
|
||||
mid: _ctr.mid,
|
||||
name: _ctr.username,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if (param == 'likeArchive') {
|
||||
Get.to(MemberLikePage(
|
||||
mid: _ctr.mid,
|
||||
name: _ctr.username,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
// else TODO
|
||||
SmartDialog.showToast('view $param');
|
||||
}
|
||||
},
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(text: '$title '),
|
||||
TextSpan(
|
||||
text: count.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
text: '查看更多',
|
||||
style: TextStyle(color: color),
|
||||
),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.top,
|
||||
child: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color: color,
|
||||
),
|
||||
style: TextStyle(fontSize: 13, color: color),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
int index =
|
||||
_ctr.tab2!.indexWhere((item) => item.param == param);
|
||||
if (index != -1) {
|
||||
if (['video', 'article', 'audio'].contains(param1)) {
|
||||
List<Item> items = _ctr.tab2!
|
||||
.firstWhere((item) => item.param == param)
|
||||
.items!;
|
||||
int index1 =
|
||||
items.indexWhere((item) => item.param == param1);
|
||||
try {
|
||||
final contributeCtr =
|
||||
Get.find<MemberContributeCtr>(tag: widget.heroTag);
|
||||
// contributeCtr.tabController?.animateTo(index1);
|
||||
if (contributeCtr.tabController?.index != index1) {
|
||||
contributeCtr.tabController?.index = index1;
|
||||
}
|
||||
debugPrint('initialized');
|
||||
} catch (e) {
|
||||
_ctr.contributeInitialIndex.value = index1;
|
||||
debugPrint('not initialized');
|
||||
}
|
||||
}
|
||||
_ctr.tabController?.animateTo(index);
|
||||
} else {
|
||||
if (param == 'coinArchive') {
|
||||
Get.to(MemberCoinPage(
|
||||
mid: _ctr.mid,
|
||||
name: _ctr.username,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if (param == 'likeArchive') {
|
||||
Get.to(MemberLikePage(
|
||||
mid: _ctr.mid,
|
||||
name: _ctr.username,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
// else TODO
|
||||
SmartDialog.showToast('view $param');
|
||||
}
|
||||
},
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '查看更多',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.top,
|
||||
child: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ class MemberFavItem extends StatelessWidget {
|
||||
},
|
||||
onLongPress: () {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: item['title'],
|
||||
cover: item['cover'],
|
||||
);
|
||||
|
||||
@@ -60,6 +60,7 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
extendBody: true,
|
||||
extendBodyBehindAppBar: true,
|
||||
@@ -149,13 +150,12 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
size: 19,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
'举报',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error),
|
||||
style: TextStyle(color: theme.colorScheme.error),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -192,7 +192,7 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
child: Column(
|
||||
children: [
|
||||
if ((_userController.tab2?.length ?? 0) > 1)
|
||||
_buildTab,
|
||||
_buildTab(theme),
|
||||
Expanded(child: _buildBody),
|
||||
],
|
||||
),
|
||||
@@ -208,8 +208,8 @@ class _MemberPageNewState extends State<MemberPageNew> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget get _buildTab => Material(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
Widget _buildTab(ThemeData theme) => Material(
|
||||
color: theme.colorScheme.surface,
|
||||
child: TabBar(
|
||||
controller: _userController.tabController,
|
||||
tabs: _userController.tabs,
|
||||
@@ -316,6 +316,7 @@ class _ReportPanelState extends State<ReportPanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -364,8 +365,7 @@ class _ReportPanelState extends State<ReportPanel> {
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
|
||||
@@ -47,9 +47,10 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('账号资料')),
|
||||
body: _buildBody(_loadingState),
|
||||
body: _buildBody(theme, _loadingState),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -77,23 +78,24 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget get _divider => Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
);
|
||||
Widget _buildBody(ThemeData theme, LoadingState loadingState) {
|
||||
late final divider = Divider(
|
||||
height: 1,
|
||||
color: theme.dividerColor.withOpacity(0.1),
|
||||
);
|
||||
|
||||
Widget get _divider1 => Divider(
|
||||
thickness: 16,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
);
|
||||
late final divider1 = Divider(
|
||||
thickness: 16,
|
||||
color: theme.dividerColor.withOpacity(0.1),
|
||||
);
|
||||
|
||||
Widget _buildBody(LoadingState loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => loadingWidget,
|
||||
Success() => SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
_item(
|
||||
theme: theme,
|
||||
title: '头像',
|
||||
widget: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
@@ -108,12 +110,13 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
EasyThrottle.throttle(
|
||||
'imagePicker', const Duration(milliseconds: 500),
|
||||
() async {
|
||||
_pickImg();
|
||||
_pickImg(theme);
|
||||
});
|
||||
},
|
||||
),
|
||||
_divider,
|
||||
divider,
|
||||
_item(
|
||||
theme: theme,
|
||||
title: '昵称',
|
||||
text: loadingState.response['name'],
|
||||
onTap: () {
|
||||
@@ -128,8 +131,9 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
}
|
||||
},
|
||||
),
|
||||
_divider,
|
||||
divider,
|
||||
_item(
|
||||
theme: theme,
|
||||
title: '性别',
|
||||
text: _sex(loadingState.response['sex']),
|
||||
onTap: () {
|
||||
@@ -140,8 +144,9 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
);
|
||||
},
|
||||
),
|
||||
_divider,
|
||||
divider,
|
||||
_item(
|
||||
theme: theme,
|
||||
title: '出生年月',
|
||||
text: loadingState.response['birthday'],
|
||||
onTap: () {
|
||||
@@ -161,8 +166,9 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
});
|
||||
},
|
||||
),
|
||||
_divider,
|
||||
divider,
|
||||
_item(
|
||||
theme: theme,
|
||||
title: '个性签名',
|
||||
text: loadingState.response['sign'].isEmpty
|
||||
? '无'
|
||||
@@ -175,27 +181,30 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
);
|
||||
},
|
||||
),
|
||||
_divider1,
|
||||
divider1,
|
||||
_item(
|
||||
theme: theme,
|
||||
title: '头像挂件',
|
||||
onTap: () => PageUtils.launchURL(
|
||||
'https://www.bilibili.com/h5/mall/pendant/home'),
|
||||
),
|
||||
_divider1,
|
||||
divider1,
|
||||
_item(
|
||||
theme: theme,
|
||||
title: 'UID',
|
||||
needIcon: false,
|
||||
text: loadingState.response['mid'].toString(),
|
||||
onTap: () =>
|
||||
Utils.copyText(loadingState.response['mid'].toString()),
|
||||
),
|
||||
_divider1,
|
||||
divider1,
|
||||
_item(
|
||||
theme: theme,
|
||||
title: '哔哩哔哩认证',
|
||||
onTap: () => PageUtils.launchURL(
|
||||
'https://account.bilibili.com/official/mobile/home'),
|
||||
),
|
||||
_divider,
|
||||
divider,
|
||||
SizedBox(height: 25 + MediaQuery.paddingOf(context).bottom),
|
||||
],
|
||||
),
|
||||
@@ -254,6 +263,7 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return AlertDialog(
|
||||
title: Text('修改$title'),
|
||||
content: TextField(
|
||||
@@ -272,7 +282,7 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
hintText: text,
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -281,7 +291,7 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
@@ -372,6 +382,7 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
}
|
||||
|
||||
Widget _item({
|
||||
required ThemeData theme,
|
||||
required String title,
|
||||
Widget? widget,
|
||||
String? text,
|
||||
@@ -399,7 +410,7 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
)
|
||||
else if (widget != null)
|
||||
@@ -407,14 +418,14 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
if (needIcon)
|
||||
Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _pickImg() async {
|
||||
void _pickImg(ThemeData theme) async {
|
||||
try {
|
||||
XFile? pickedFile = await _imagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
@@ -432,9 +443,8 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
uiSettings: [
|
||||
AndroidUiSettings(
|
||||
toolbarTitle: '裁剪',
|
||||
toolbarColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||
toolbarWidgetColor:
|
||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
toolbarColor: theme.colorScheme.secondaryContainer,
|
||||
toolbarWidgetColor: theme.colorScheme.onSecondaryContainer,
|
||||
aspectRatioPresets: [
|
||||
CropAspectRatioPresetCustom(),
|
||||
],
|
||||
|
||||
@@ -38,10 +38,12 @@ class UserInfoCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return isV ? _buildV(context) : _buildH(context);
|
||||
final theme = Theme.of(context);
|
||||
return isV ? _buildV(context, theme) : _buildH(context, theme);
|
||||
}
|
||||
|
||||
Widget _countWidget({
|
||||
required ThemeData theme,
|
||||
required String title,
|
||||
required int count,
|
||||
required VoidCallback onTap,
|
||||
@@ -62,7 +64,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 11,
|
||||
color: Theme.of(Get.context!).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -70,8 +72,8 @@ class UserInfoCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
_buildHeader(BuildContext context) {
|
||||
bool darken = Theme.of(context).brightness == Brightness.dark;
|
||||
_buildHeader(BuildContext context, ThemeData theme) {
|
||||
bool darken = theme.brightness == Brightness.dark;
|
||||
String imgUrl = (darken
|
||||
? images.nightImgurl?.isEmpty == true
|
||||
? images.imgUrl
|
||||
@@ -107,7 +109,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
_buildLeft(BuildContext context) => [
|
||||
_buildLeft(BuildContext context, ThemeData theme) => [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Wrap(
|
||||
@@ -181,7 +183,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
),
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
@@ -192,7 +194,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.surface,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.offline_bolt,
|
||||
@@ -212,10 +214,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withOpacity(0.7),
|
||||
color: theme.colorScheme.onSurface.withOpacity(0.7),
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -245,7 +244,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
'UID: ${card.mid}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -255,7 +254,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
item.title ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -264,14 +263,14 @@ class UserInfoCard extends StatelessWidget {
|
||||
),
|
||||
if (silence == 1)
|
||||
Builder(builder: (context) {
|
||||
bool isLight = Theme.of(context).brightness == Brightness.light;
|
||||
bool isLight = theme.brightness == Brightness.light;
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
color: isLight
|
||||
? Theme.of(context).colorScheme.errorContainer
|
||||
: Theme.of(context).colorScheme.error,
|
||||
? theme.colorScheme.errorContainer
|
||||
: theme.colorScheme.error,
|
||||
),
|
||||
margin: const EdgeInsets.only(left: 20, top: 8, right: 20),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
@@ -284,16 +283,16 @@ class UserInfoCard extends StatelessWidget {
|
||||
Icons.info,
|
||||
size: 17,
|
||||
color: isLight
|
||||
? Theme.of(context).colorScheme.onErrorContainer
|
||||
: Theme.of(context).colorScheme.onError,
|
||||
? theme.colorScheme.onErrorContainer
|
||||
: theme.colorScheme.onError,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' 该账号封禁中${endTime ?? ''}',
|
||||
style: TextStyle(
|
||||
color: isLight
|
||||
? Theme.of(context).colorScheme.onErrorContainer
|
||||
: Theme.of(context).colorScheme.onError,
|
||||
? theme.colorScheme.onErrorContainer
|
||||
: theme.colorScheme.onError,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -303,7 +302,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
}),
|
||||
];
|
||||
|
||||
_buildRight(BuildContext context) => Column(
|
||||
_buildRight(BuildContext context, ThemeData theme) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
@@ -312,6 +311,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
5,
|
||||
(index) => index % 2 == 0
|
||||
? _countWidget(
|
||||
theme: theme,
|
||||
title: ['粉丝', '关注', '获赞'][index ~/ 2],
|
||||
count: index == 0
|
||||
? card.fans
|
||||
@@ -358,10 +358,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
style: IconButton.styleFrom(
|
||||
side: BorderSide(
|
||||
width: 1.0,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.5),
|
||||
color: theme.colorScheme.outline.withOpacity(0.5),
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
@@ -378,7 +375,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
onPressed: onFollow,
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: relation != 0
|
||||
? Theme.of(context).colorScheme.onInverseSurface
|
||||
? theme.colorScheme.onInverseSurface
|
||||
: null,
|
||||
visualDensity: const VisualDensity(
|
||||
horizontal: -2,
|
||||
@@ -387,9 +384,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
),
|
||||
child: Text.rich(
|
||||
style: TextStyle(
|
||||
color: relation != 0
|
||||
? Theme.of(context).colorScheme.outline
|
||||
: null,
|
||||
color: relation != 0 ? theme.colorScheme.outline : null,
|
||||
),
|
||||
TextSpan(
|
||||
children: [
|
||||
@@ -399,7 +394,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
child: Icon(
|
||||
Icons.sort,
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
@@ -440,7 +435,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
.imageView(imgList: [SourceModel(url: card.face.http2https)]),
|
||||
));
|
||||
|
||||
_buildV(BuildContext context) => Column(
|
||||
_buildV(BuildContext context, ThemeData theme) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -450,7 +445,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildHeader(context),
|
||||
_buildHeader(context, theme),
|
||||
const SizedBox(width: double.infinity, height: 85)
|
||||
],
|
||||
),
|
||||
@@ -468,21 +463,21 @@ class UserInfoCard extends StatelessWidget {
|
||||
builder: (_, constraints) => FittedBox(
|
||||
child: SizedBox(
|
||||
width: constraints.maxWidth,
|
||||
child: _buildRight(context),
|
||||
child: _buildRight(context, theme),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
..._buildLeft(context),
|
||||
if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo,
|
||||
..._buildLeft(context, theme),
|
||||
if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo(theme),
|
||||
const SizedBox(height: 5),
|
||||
],
|
||||
);
|
||||
|
||||
Widget get buildPrInfo => Builder(builder: (context) {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
Widget buildPrInfo(ThemeData theme) => Builder(builder: (context) {
|
||||
final isDark = theme.brightness == Brightness.dark;
|
||||
final textColor = isDark
|
||||
? Color(int.parse('FF${card.prInfo?.textColorNight?.substring(1)}',
|
||||
radix: 16))
|
||||
@@ -537,7 +532,7 @@ class UserInfoCard extends StatelessWidget {
|
||||
);
|
||||
});
|
||||
|
||||
_buildH(BuildContext context) => Column(
|
||||
_buildH(BuildContext context, ThemeData theme) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -565,16 +560,16 @@ class UserInfoCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
..._buildLeft(context),
|
||||
..._buildLeft(context, theme),
|
||||
const SizedBox(height: 5),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: _buildRight(context)),
|
||||
Expanded(child: _buildRight(context, theme)),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo,
|
||||
if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo(theme),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ class MemberCoinsItem extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: coinItem.title,
|
||||
cover: coinItem.pic,
|
||||
),
|
||||
|
||||
@@ -93,8 +93,9 @@ class MineController extends GetxController {
|
||||
displayTime: const Duration(seconds: 2),
|
||||
alignment: Alignment.bottomCenter,
|
||||
builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
return ColoredBox(
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
color: theme.colorScheme.primaryContainer,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: 15,
|
||||
@@ -111,8 +112,7 @@ class MineController extends GetxController {
|
||||
MdiIcons.incognito,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text('已进入无痕模式',
|
||||
style: Theme.of(context).textTheme.titleMedium)
|
||||
Text('已进入无痕模式', style: theme.textTheme.titleMedium)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@@ -121,7 +121,7 @@ class MineController extends GetxController {
|
||||
'不产生查询或播放记录\n'
|
||||
'点赞等其它操作不受影响\n'
|
||||
'(前往隐私设置了解详情)',
|
||||
style: Theme.of(context).textTheme.bodySmall),
|
||||
style: theme.textTheme.bodySmall),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
@@ -133,7 +133,7 @@ class MineController extends GetxController {
|
||||
child: Text(
|
||||
'保存为永久',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
)),
|
||||
const SizedBox(width: 10),
|
||||
@@ -145,7 +145,7 @@ class MineController extends GetxController {
|
||||
child: Text(
|
||||
'仅本次(默认)',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -169,8 +169,9 @@ class MineController extends GetxController {
|
||||
displayTime: const Duration(seconds: 1),
|
||||
alignment: Alignment.bottomCenter,
|
||||
builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
return ColoredBox(
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: 15,
|
||||
@@ -185,8 +186,7 @@ class MineController extends GetxController {
|
||||
MdiIcons.incognitoOff,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text('已退出无痕模式',
|
||||
style: Theme.of(context).textTheme.titleMedium),
|
||||
Text('已退出无痕模式', style: theme.textTheme.titleMedium),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -18,7 +18,7 @@ class _MinePageState extends State<MinePage> {
|
||||
final MineController _mineController = Get.put(MineController())
|
||||
..queryUserInfo();
|
||||
|
||||
Widget get _header => FittedBox(
|
||||
Widget _header(ThemeData theme) => FittedBox(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@@ -31,7 +31,7 @@ class _MinePageState extends State<MinePage> {
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
'PiliPlus',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(width: 30),
|
||||
IconButton(
|
||||
@@ -92,24 +92,25 @@ class _MinePageState extends State<MinePage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return IntrinsicWidth(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
_header,
|
||||
_header(theme),
|
||||
const SizedBox(height: 10),
|
||||
Obx(userInfoBuild),
|
||||
Obx(() => userInfoBuild(theme)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget userInfoBuild() {
|
||||
Widget userInfoBuild(ThemeData theme) {
|
||||
LevelInfo? levelInfo = _mineController.userInfo.value.levelInfo;
|
||||
TextStyle style = TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.titleMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontSize: theme.textTheme.titleMedium!.fontSize,
|
||||
color: theme.colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
return Column(
|
||||
@@ -137,7 +138,7 @@ class _MinePageState extends State<MinePage> {
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
),
|
||||
child: Image.asset(
|
||||
'assets/images/noface.jpeg',
|
||||
@@ -158,9 +159,7 @@ class _MinePageState extends State<MinePage> {
|
||||
children: [
|
||||
Text(
|
||||
_mineController.userInfo.value.uname ?? '点击头像登录',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
style: theme.textTheme.titleMedium!
|
||||
.copyWith(height: 1),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
@@ -181,11 +180,8 @@ class _MinePageState extends State<MinePage> {
|
||||
TextSpan(
|
||||
text: '硬币 ',
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
@@ -193,22 +189,16 @@ class _MinePageState extends State<MinePage> {
|
||||
(_mineController.userInfo.value.money ?? '-')
|
||||
.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " 经验 ",
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
@@ -216,23 +206,17 @@ class _MinePageState extends State<MinePage> {
|
||||
semanticsLabel:
|
||||
"当前${levelInfo?.currentExp ?? '-'}",
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: "/${levelInfo?.nextExp ?? '-'}",
|
||||
semanticsLabel: "升级需${levelInfo?.nextExp ?? '-'}",
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall!
|
||||
.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -247,10 +231,9 @@ class _MinePageState extends State<MinePage> {
|
||||
value: levelInfo != null
|
||||
? (levelInfo.currentExp! / levelInfo.nextExp!)
|
||||
: 0,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.inversePrimary,
|
||||
backgroundColor: theme.colorScheme.inversePrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
Theme.of(context).colorScheme.primary),
|
||||
theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -286,7 +269,7 @@ class _MinePageState extends State<MinePage> {
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'动态',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
style: theme.textTheme.labelMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -307,7 +290,7 @@ class _MinePageState extends State<MinePage> {
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'关注',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
style: theme.textTheme.labelMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -329,7 +312,7 @@ class _MinePageState extends State<MinePage> {
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'粉丝',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
style: theme.textTheme.labelMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -24,6 +24,7 @@ class _AtMePageState extends State<AtMePage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('@我的'),
|
||||
@@ -38,7 +39,8 @@ class _AtMePageState extends State<AtMePage> {
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver: Obx(() => _buildBody(_atMeController.loadingState.value)),
|
||||
sliver: Obx(
|
||||
() => _buildBody(theme, _atMeController.loadingState.value)),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -46,7 +48,8 @@ class _AtMePageState extends State<AtMePage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<AtMeItems>?> loadingState) {
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<AtMeItems>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemCount: 12,
|
||||
@@ -94,21 +97,15 @@ class _AtMePageState extends State<AtMePage> {
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.user?.nickname}",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " 在${item.item?.business}中@了我",
|
||||
style:
|
||||
Theme.of(context).textTheme.titleSmall!.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -121,20 +118,16 @@ class _AtMePageState extends State<AtMePage> {
|
||||
Text(item.item!.sourceContent!,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline)),
|
||||
style: theme.textTheme.bodyMedium!
|
||||
.copyWith(color: theme.colorScheme.outline)),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
Utils.dateFormat(item.atTime),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -57,6 +57,7 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
},
|
||||
),
|
||||
Success() => () {
|
||||
final theme = Theme.of(context);
|
||||
Pair<List<LikeMeItems>, List<LikeMeItems>> pair =
|
||||
loadingState.response;
|
||||
List<LikeMeItems> latest = pair.first;
|
||||
@@ -65,13 +66,14 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
if (latest.isNotEmpty) ...[
|
||||
_buildHeader('最新'),
|
||||
_buildHeader(theme, '最新'),
|
||||
SliverList.separated(
|
||||
itemBuilder: (context, index) {
|
||||
if (total.isEmpty && index == latest.length - 1) {
|
||||
_likeMeController.onLoadMore();
|
||||
}
|
||||
return _buildItem(
|
||||
theme,
|
||||
latest[index],
|
||||
(id) {
|
||||
_likeMeController.onRemove(id, index, true);
|
||||
@@ -90,13 +92,14 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
),
|
||||
],
|
||||
if (total.isNotEmpty) ...[
|
||||
_buildHeader('累计'),
|
||||
_buildHeader(theme, '累计'),
|
||||
SliverList.separated(
|
||||
itemBuilder: (context, index) {
|
||||
if (index == total.length - 1) {
|
||||
_likeMeController.onLoadMore();
|
||||
}
|
||||
return _buildItem(
|
||||
theme,
|
||||
total[index],
|
||||
(id) {
|
||||
_likeMeController.onRemove(id, index, false);
|
||||
@@ -126,7 +129,7 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
};
|
||||
}
|
||||
|
||||
Widget _buildHeader(String title) {
|
||||
Widget _buildHeader(ThemeData theme, String title) {
|
||||
return SliverSafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
@@ -135,16 +138,16 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
child: Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
style: theme.textTheme.labelLarge!.copyWith(
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildItem(LikeMeItems item, ValueChanged onRemove) {
|
||||
Widget _buildItem(ThemeData theme, LikeMeItems item, ValueChanged onRemove) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
String? nativeUri = item.item?.nativeUri;
|
||||
@@ -193,23 +196,21 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.users![0].nickname}",
|
||||
style: Theme.of(context).textTheme.titleSmall!.copyWith(
|
||||
height: 1.5, color: Theme.of(context).colorScheme.primary),
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(height: 1.5, color: theme.colorScheme.primary),
|
||||
),
|
||||
if (item.counts! > 1)
|
||||
TextSpan(
|
||||
text: ' 等${item.counts}人',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(fontSize: 12, height: 1.5),
|
||||
),
|
||||
TextSpan(
|
||||
text: " 赞了我的${item.item?.business}",
|
||||
style: Theme.of(context).textTheme.titleSmall!.copyWith(
|
||||
height: 1.5,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
height: 1.5,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -224,16 +225,16 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
Text(item.item!.title!,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.outline, height: 1.5)),
|
||||
style: theme.textTheme.bodyMedium!
|
||||
.copyWith(color: theme.colorScheme.outline, height: 1.5)),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
Utils.dateFormat(item.likeTime),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -24,6 +24,7 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('回复我的')),
|
||||
body: refreshIndicator(
|
||||
@@ -36,8 +37,8 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver:
|
||||
Obx(() => _buildBody(_replyMeController.loadingState.value)),
|
||||
sliver: Obx(() =>
|
||||
_buildBody(theme, _replyMeController.loadingState.value)),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -45,7 +46,8 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<ReplyMeItems>?> loadingState) {
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<ReplyMeItems>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemCount: 12,
|
||||
@@ -98,30 +100,20 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.user?.nickname}",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary),
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(color: theme.colorScheme.primary),
|
||||
),
|
||||
if (item.isMulti == 1)
|
||||
TextSpan(
|
||||
text: " 等人",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(fontSize: 12),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
" 对我的${item.item?.business}发布了${item.counts}条评论",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -132,38 +124,28 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text(item.item?.sourceContent ?? "",
|
||||
style: Theme.of(context).textTheme.bodyMedium),
|
||||
style: theme.textTheme.bodyMedium),
|
||||
const SizedBox(height: 4),
|
||||
if (item.item?.targetReplyContent != null &&
|
||||
item.item?.targetReplyContent != "")
|
||||
Text("| ${item.item?.targetReplyContent}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline,
|
||||
height: 1.5)),
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
color: theme.colorScheme.outline, height: 1.5)),
|
||||
if (item.item?.rootReplyContent != null &&
|
||||
item.item?.rootReplyContent != "")
|
||||
Text(" | ${item.item?.rootReplyContent}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline,
|
||||
height: 1.5)),
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
color: theme.colorScheme.outline, height: 1.5)),
|
||||
Text(
|
||||
Utils.dateFormat(item.replyTime),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -29,6 +29,7 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('系统通知'),
|
||||
@@ -43,8 +44,8 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver:
|
||||
Obx(() => _buildBody(_sysMsgController.loadingState.value)),
|
||||
sliver: Obx(() =>
|
||||
_buildBody(theme, _sysMsgController.loadingState.value)),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -52,7 +53,8 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<SystemNotifyList>?> loadingState) {
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<SystemNotifyList>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverSafeArea(
|
||||
sliver: SliverList.builder(
|
||||
@@ -92,20 +94,17 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
},
|
||||
title: Text(
|
||||
"${item.title}",
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text.rich(
|
||||
_buildContent(content ?? ''),
|
||||
_buildContent(theme, content ?? ''),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withOpacity(0.85),
|
||||
color: theme.colorScheme.onSurface.withOpacity(0.85),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
@@ -115,13 +114,10 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
"${item.timeAt}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
textAlign: TextAlign.end,
|
||||
),
|
||||
),
|
||||
@@ -146,7 +142,7 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
};
|
||||
}
|
||||
|
||||
InlineSpan _buildContent(String content) {
|
||||
InlineSpan _buildContent(ThemeData theme, String content) {
|
||||
final List<InlineSpan> spanChildren = <InlineSpan>[];
|
||||
RegExp urlRegExp = RegExp(
|
||||
r'#\{([^}]*)\}\{([^}]*)\}|https?:\/\/[^\s/\$.?#].[^\s]*|www\.[^\s/\$.?#].[^\s]*|【(.*?)】|((\d+))');
|
||||
@@ -158,7 +154,7 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
spanChildren.add(
|
||||
TextSpan(
|
||||
text: match[1],
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
try {
|
||||
@@ -181,7 +177,7 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
spanChildren.add(
|
||||
TextSpan(
|
||||
text: match[3],
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
try {
|
||||
@@ -206,7 +202,7 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
spanChildren.add(
|
||||
TextSpan(
|
||||
text: '查看动态',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
try {
|
||||
@@ -225,7 +221,7 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
spanChildren.add(
|
||||
TextSpan(
|
||||
text: '\u{1F517}网页链接',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
try {
|
||||
|
||||
@@ -20,6 +20,7 @@ class _RankPageState extends State<RankPage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
super.build(context);
|
||||
return Row(
|
||||
children: [
|
||||
@@ -45,8 +46,8 @@ class _RankPageState extends State<RankPage>
|
||||
},
|
||||
child: ColoredBox(
|
||||
color: index == _rankController.tabIndex.value
|
||||
? Theme.of(context).colorScheme.onInverseSurface
|
||||
: Theme.of(context).colorScheme.surface,
|
||||
? theme.colorScheme.onInverseSurface
|
||||
: theme.colorScheme.surface,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -54,7 +55,7 @@ class _RankPageState extends State<RankPage>
|
||||
height: double.infinity,
|
||||
width: 3,
|
||||
color: index == _rankController.tabIndex.value
|
||||
? Theme.of(context).colorScheme.primary
|
||||
? theme.colorScheme.primary
|
||||
: Colors.transparent,
|
||||
),
|
||||
Expanded(
|
||||
@@ -66,12 +67,10 @@ class _RankPageState extends State<RankPage>
|
||||
child: Text(
|
||||
tabsConfig[index]['label'],
|
||||
style: TextStyle(
|
||||
color: index ==
|
||||
_rankController.tabIndex.value
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface,
|
||||
color:
|
||||
index == _rankController.tabIndex.value
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface,
|
||||
fontSize: 15,
|
||||
),
|
||||
maxLines: 1,
|
||||
|
||||
@@ -23,7 +23,6 @@ class PgcRankItem extends StatelessWidget {
|
||||
},
|
||||
onLongPress: () {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
);
|
||||
|
||||
@@ -27,12 +27,13 @@ class _SearchPageState extends State<SearchPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
appBar: AppBar(
|
||||
shape: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.08),
|
||||
color: theme.dividerColor.withOpacity(0.08),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@@ -81,9 +82,9 @@ class _SearchPageState extends State<SearchPage> {
|
||||
// 搜索建议
|
||||
if (_searchController.searchSuggestion) _searchSuggest(),
|
||||
if (context.orientation == Orientation.portrait) ...[
|
||||
if (_searchController.enableHotKey) hotSearch(),
|
||||
if (_searchController.recordSearchHistory.value) _history(),
|
||||
if (_searchController.enableSearchRcmd) hotSearch(false)
|
||||
if (_searchController.enableHotKey) hotSearch(theme),
|
||||
if (_searchController.recordSearchHistory.value) _history(theme),
|
||||
if (_searchController.enableSearchRcmd) hotSearch(theme, false)
|
||||
] else
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -93,14 +94,14 @@ class _SearchPageState extends State<SearchPage> {
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
if (_searchController.enableHotKey) hotSearch(),
|
||||
if (_searchController.enableHotKey) hotSearch(theme),
|
||||
if (_searchController.enableSearchRcmd)
|
||||
hotSearch(false)
|
||||
hotSearch(theme, false)
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_searchController.recordSearchHistory.value)
|
||||
Expanded(child: _history()),
|
||||
Expanded(child: _history(theme)),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -141,13 +142,11 @@ class _SearchPageState extends State<SearchPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget hotSearch([bool isHot = true]) {
|
||||
Widget hotSearch(ThemeData theme, [bool isHot = true]) {
|
||||
final text = Text(
|
||||
isHot ? '大家都在搜' : '搜索发现',
|
||||
strutStyle: const StrutStyle(leading: 0, height: 1),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
style: theme.textTheme.titleMedium!
|
||||
.copyWith(height: 1, fontWeight: FontWeight.bold),
|
||||
);
|
||||
return Padding(
|
||||
@@ -180,14 +179,13 @@ class _SearchPageState extends State<SearchPage> {
|
||||
'完整榜单',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
icon: Icon(
|
||||
size: 16,
|
||||
Icons.keyboard_arrow_right,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
iconAlignment: IconAlignment.end,
|
||||
),
|
||||
@@ -209,12 +207,12 @@ class _SearchPageState extends State<SearchPage> {
|
||||
icon: Icon(
|
||||
Icons.refresh_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
label: Text(
|
||||
'刷新',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -233,7 +231,7 @@ class _SearchPageState extends State<SearchPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _history() {
|
||||
Widget _history(ThemeData theme) {
|
||||
return Obx(
|
||||
() => Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
@@ -257,9 +255,7 @@ class _SearchPageState extends State<SearchPage> {
|
||||
Text(
|
||||
'搜索历史',
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
style: theme.textTheme.titleMedium!
|
||||
.copyWith(height: 1, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
@@ -273,8 +269,8 @@ class _SearchPageState extends State<SearchPage> {
|
||||
? '记录搜索'
|
||||
: '无痕搜索',
|
||||
icon: _searchController.recordSearchHistory.value
|
||||
? historyIcon
|
||||
: historyIcon.disable(),
|
||||
? historyIcon(theme)
|
||||
: historyIcon(theme).disable(),
|
||||
style: IconButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
@@ -307,12 +303,12 @@ class _SearchPageState extends State<SearchPage> {
|
||||
icon: Icon(
|
||||
Icons.clear_all_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
label: Text(
|
||||
'清空',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -343,8 +339,8 @@ class _SearchPageState extends State<SearchPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Icon get historyIcon => Icon(Icons.history,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.8));
|
||||
Icon historyIcon(ThemeData theme) => Icon(Icons.history,
|
||||
color: theme.colorScheme.onSurfaceVariant.withOpacity(0.8));
|
||||
|
||||
Widget _buildHotKey(
|
||||
LoadingState<SearchKeywordData> loadingState, bool isHot) {
|
||||
|
||||
@@ -24,8 +24,9 @@ class SearchText extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
late final theme = Theme.of(context);
|
||||
return Material(
|
||||
color: bgColor ?? Theme.of(context).colorScheme.onInverseSurface,
|
||||
color: bgColor ?? theme.colorScheme.onInverseSurface,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
@@ -45,8 +46,7 @@ class SearchText extends StatelessWidget {
|
||||
textAlign: textAlign,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color:
|
||||
textColor ?? Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
color: textColor ?? theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -17,7 +17,6 @@ class SearchAllPanel extends CommonSearchPanel {
|
||||
required super.keyword,
|
||||
required super.tag,
|
||||
required super.searchType,
|
||||
super.hasHeader = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -36,22 +35,12 @@ class _SearchAllPanelState
|
||||
tag: widget.searchType.name + widget.tag,
|
||||
);
|
||||
|
||||
late final TextStyle pgcStyle = TextStyle(fontSize: 13);
|
||||
late TextStyle userStyle;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
userStyle = TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildList(List<dynamic> list) {
|
||||
Widget buildList(ThemeData theme, List<dynamic> list) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: SliverWaterfallFlow.extent(
|
||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||
crossAxisSpacing: StyleString.safeSpace,
|
||||
@@ -76,7 +65,7 @@ class _SearchAllPanelState
|
||||
List<SearchMBangumiItemModel>() => item.length == 1
|
||||
? SizedBox(
|
||||
height: 160,
|
||||
child: SearchPgcItem(style: pgcStyle, item: item.first),
|
||||
child: SearchPgcItem(item: item.first),
|
||||
)
|
||||
: SizedBox(
|
||||
height: Grid.smallCardWidth / 2 / 0.75 +
|
||||
@@ -103,7 +92,6 @@ class _SearchAllPanelState
|
||||
SearchUserItemModel() => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 5),
|
||||
child: SearchUserItem(
|
||||
style: userStyle,
|
||||
item: item,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -69,83 +69,87 @@ class SearchArticleController
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: min(640, min(Get.width, Get.height)),
|
||||
),
|
||||
builder: (context) => SingleChildScrollView(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(
|
||||
top: 20,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 80 + MediaQuery.of(context).padding.bottom,
|
||||
builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(
|
||||
top: 20,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 80 + MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const Text('排序', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: orderFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentOrderFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
order.value = item['order'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentOrderFilterval.value
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor:
|
||||
item['value'] == currentOrderFilterval.value
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Text('分区', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: zoneFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentZoneFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
categoryId = item['categoryId'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentZoneFilterval.value
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] == currentZoneFilterval.value
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const Text('排序', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: orderFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentOrderFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
order.value = item['order'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentOrderFilterval.value
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] == currentOrderFilterval.value
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Text('分区', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: zoneFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentZoneFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
categoryId = item['categoryId'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentZoneFilterval.value
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] == currentZoneFilterval.value
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart';
|
||||
import 'package:PiliPlus/common/widgets/image_save.dart';
|
||||
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/search/result.dart';
|
||||
import 'package:PiliPlus/pages/search_panel/article/controller.dart';
|
||||
import 'package:PiliPlus/pages/search_panel/article/widgets/item.dart';
|
||||
import 'package:PiliPlus/pages/search_panel/view.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
@@ -17,7 +13,6 @@ class SearchArticlePanel extends CommonSearchPanel {
|
||||
required super.keyword,
|
||||
required super.tag,
|
||||
required super.searchType,
|
||||
super.hasHeader = true,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -36,191 +31,78 @@ class _SearchArticlePanelState extends CommonSearchPanelState<
|
||||
tag: widget.searchType.name + widget.tag,
|
||||
);
|
||||
|
||||
late TextStyle textStyle;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
textStyle = TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildHeader(LoadingState<List<SearchArticleItemModel>?> loadingState) {
|
||||
if (loadingState is Success) {
|
||||
return SliverPersistentHeader(
|
||||
pinned: false,
|
||||
floating: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
extent: 40,
|
||||
bgColor: Theme.of(context).colorScheme.surface,
|
||||
child: Container(
|
||||
height: 40,
|
||||
padding: const EdgeInsets.only(left: 25, right: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => Text(
|
||||
'排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Obx(
|
||||
() => Text(
|
||||
'分区: ${controller.zoneFiltersList[controller.currentZoneFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '筛选',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () {
|
||||
controller.onShowFilterDialog(context);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.filter_list_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
Widget buildList(ThemeData theme, List<SearchArticleItemModel> list) {
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
SliverPersistentHeader(
|
||||
pinned: false,
|
||||
floating: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
extent: 40,
|
||||
bgColor: theme.colorScheme.surface,
|
||||
child: Container(
|
||||
height: 40,
|
||||
padding: const EdgeInsets.only(left: 25, right: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => Text(
|
||||
'排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
const Spacer(),
|
||||
Obx(
|
||||
() => Text(
|
||||
'分区: ${controller.zoneFiltersList[controller.currentZoneFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '筛选',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () {
|
||||
controller.onShowFilterDialog(context);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.filter_list_outlined,
|
||||
size: 18,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SliverToBoxAdapter();
|
||||
}
|
||||
|
||||
late final TextStyle style = TextStyle(fontSize: 13);
|
||||
|
||||
@override
|
||||
Widget buildList(List<SearchArticleItemModel> list) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
if (index == list.length - 1) {
|
||||
controller.onLoadMore();
|
||||
}
|
||||
final item = list[index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
'/articlePage',
|
||||
parameters: {
|
||||
'id': '${item.id}',
|
||||
'type': 'read',
|
||||
},
|
||||
);
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
if (index == list.length - 1) {
|
||||
controller.onLoadMore();
|
||||
}
|
||||
return SearchArticleItem(item: list[index]);
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: item.title?.map((item) => item['text']).join() ?? '',
|
||||
cover: item.imageUrls?.firstOrNull,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
vertical: 5,
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
final double width = (boxConstraints.maxWidth -
|
||||
StyleString.cardSpace *
|
||||
6 /
|
||||
MediaQuery.textScalerOf(context).scale(1.0)) /
|
||||
2;
|
||||
return Container(
|
||||
constraints: const BoxConstraints(minHeight: 88),
|
||||
height: width / StyleString.aspectRatio,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
if (item.imageUrls?.isNotEmpty == true)
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
double maxWidth = boxConstraints.maxWidth;
|
||||
double maxHeight = boxConstraints.maxHeight;
|
||||
return NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
src: item.imageUrls?.firstOrNull,
|
||||
);
|
||||
}),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text.rich(
|
||||
maxLines: 2,
|
||||
TextSpan(
|
||||
children: [
|
||||
for (var i in item.title!) ...[
|
||||
TextSpan(
|
||||
text: i['text'],
|
||||
style: TextStyle(
|
||||
color: i['type'] == 'em'
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface,
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
Utils.dateFormat(item.pubTime,
|
||||
formatType: 'detail'),
|
||||
style: textStyle,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text('${item.view}浏览', style: textStyle),
|
||||
Text(' • ', style: textStyle),
|
||||
Text('${item.reply}评论', style: textStyle),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
childCount: list.length,
|
||||
childCount: list.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
99
lib/pages/search_panel/article/widgets/item.dart
Normal file
99
lib/pages/search_panel/article/widgets/item.dart
Normal file
@@ -0,0 +1,99 @@
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/image_save.dart';
|
||||
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/search/result.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class SearchArticleItem extends StatelessWidget {
|
||||
const SearchArticleItem({super.key, required this.item});
|
||||
|
||||
final SearchArticleItemModel item;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final textStyle = TextStyle(
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
);
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
'/articlePage',
|
||||
parameters: {
|
||||
'id': '${item.id}',
|
||||
'type': 'read',
|
||||
},
|
||||
);
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
title: item.title?.map((item) => item['text']).join() ?? '',
|
||||
cover: item.imageUrls?.firstOrNull,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
if (item.imageUrls?.isNotEmpty == true)
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(builder: (context, boxConstraints) {
|
||||
double maxWidth = boxConstraints.maxWidth;
|
||||
double maxHeight = boxConstraints.maxHeight;
|
||||
return NetworkImgLayer(
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
src: item.imageUrls?.firstOrNull,
|
||||
);
|
||||
}),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text.rich(
|
||||
maxLines: 2,
|
||||
TextSpan(
|
||||
children: [
|
||||
for (var i in item.title!) ...[
|
||||
TextSpan(
|
||||
text: i['text'],
|
||||
style: TextStyle(
|
||||
color: i['type'] == 'em'
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
Utils.dateFormat(item.pubTime, formatType: 'detail'),
|
||||
style: textStyle,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text('${item.view}浏览', style: textStyle),
|
||||
Text(' • ', style: textStyle),
|
||||
Text('${item.reply}评论', style: textStyle),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -32,12 +32,12 @@ class _SearchLivePanelState extends CommonSearchPanelState<SearchLivePanel,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget buildList(List<SearchLiveItemModel> list) {
|
||||
Widget buildList(ThemeData theme, List<SearchLiveItemModel> list) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.only(
|
||||
padding: EdgeInsets.only(
|
||||
left: StyleString.safeSpace,
|
||||
right: StyleString.safeSpace,
|
||||
bottom: 80,
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithExtentAndRatio(
|
||||
|
||||
@@ -12,6 +12,7 @@ class LiveItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Card(
|
||||
elevation: 1,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
@@ -21,7 +22,6 @@ class LiveItem extends StatelessWidget {
|
||||
Get.toNamed('/liveRoom?roomid=${liveItem.roomid}');
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: liveItem.title?.map((item) => item['text']).join() ?? '',
|
||||
cover: liveItem.cover,
|
||||
),
|
||||
@@ -60,14 +60,14 @@ class LiveItem extends StatelessWidget {
|
||||
}),
|
||||
),
|
||||
),
|
||||
liveContent(context)
|
||||
liveContent(theme)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget liveContent(BuildContext context) => Expanded(
|
||||
Widget liveContent(ThemeData theme) => Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(9, 8, 9, 6),
|
||||
child: Column(
|
||||
@@ -83,8 +83,8 @@ class LiveItem extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
letterSpacing: 0.3,
|
||||
color: i['type'] == 'em'
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -97,8 +97,8 @@ class LiveItem extends StatelessWidget {
|
||||
liveItem.uname!,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -30,12 +30,11 @@ class _SearchPgcPanelState extends CommonSearchPanelState<SearchPgcPanel,
|
||||
tag: widget.searchType.name + widget.tag,
|
||||
);
|
||||
|
||||
late final TextStyle style = TextStyle(fontSize: 13);
|
||||
|
||||
@override
|
||||
Widget buildList(List<SearchMBangumiItemModel> list) {
|
||||
Widget buildList(ThemeData theme, List<SearchMBangumiItemModel> list) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
padding:
|
||||
EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||
@@ -46,7 +45,7 @@ class _SearchPgcPanelState extends CommonSearchPanelState<SearchPgcPanel,
|
||||
if (index == list.length - 1) {
|
||||
controller.onLoadMore();
|
||||
}
|
||||
return SearchPgcItem(style: style, item: list[index]);
|
||||
return SearchPgcItem(item: list[index]);
|
||||
},
|
||||
childCount: list.length,
|
||||
),
|
||||
|
||||
@@ -10,21 +10,20 @@ import 'package:flutter/material.dart';
|
||||
class SearchPgcItem extends StatelessWidget {
|
||||
const SearchPgcItem({
|
||||
super.key,
|
||||
required this.style,
|
||||
required this.item,
|
||||
});
|
||||
|
||||
final TextStyle style;
|
||||
final SearchMBangumiItemModel item;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final TextStyle style = TextStyle(fontSize: 13);
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
PageUtils.viewBangumi(seasonId: item.seasonId);
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
context: context,
|
||||
title: item.title?.map((item) => item['text']).join() ?? '',
|
||||
cover: item.cover,
|
||||
),
|
||||
@@ -60,21 +59,17 @@ class SearchPgcItem extends StatelessWidget {
|
||||
const SizedBox(height: 4),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface),
|
||||
style: TextStyle(color: theme.colorScheme.onSurface),
|
||||
children: [
|
||||
for (var i in item.title!) ...[
|
||||
TextSpan(
|
||||
text: i['text'],
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall!
|
||||
.fontSize!,
|
||||
fontSize: theme.textTheme.titleSmall!.fontSize!,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: i['type'] == 'em'
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -41,85 +41,90 @@ class SearchUserController
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: min(640, min(Get.width, Get.height)),
|
||||
),
|
||||
builder: (context) => SingleChildScrollView(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(
|
||||
top: 20,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 80 + MediaQuery.of(context).padding.bottom,
|
||||
builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(
|
||||
top: 20,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 80 + MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const Text('用户粉丝数及等级排序顺序', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: orderFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentOrderFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
orderSort = item['orderSort'];
|
||||
order.value = item['order'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentOrderFilterval.value
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor:
|
||||
item['value'] == currentOrderFilterval.value
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Text('用户分类', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: userTypeFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentUserTypeFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
userType = item['userType'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor:
|
||||
item['value'] == currentUserTypeFilterval.value
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor:
|
||||
item['value'] == currentUserTypeFilterval.value
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const Text('用户粉丝数及等级排序顺序', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: orderFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentOrderFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
orderSort = item['orderSort'];
|
||||
order.value = item['order'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentOrderFilterval.value
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] == currentOrderFilterval.value
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Text('用户分类', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: userTypeFiltersList
|
||||
.map(
|
||||
(item) => SearchText(
|
||||
text: item['label'],
|
||||
onTap: (_) async {
|
||||
Get.back();
|
||||
currentUserTypeFilterval.value = item['value'];
|
||||
SmartDialog.dismiss();
|
||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||
userType = item['userType'];
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentUserTypeFilterval.value
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] ==
|
||||
currentUserTypeFilterval.value
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/search/result.dart';
|
||||
import 'package:PiliPlus/pages/search_panel/user/controller.dart';
|
||||
import 'package:PiliPlus/pages/search_panel/user/widgets/item.dart';
|
||||
@@ -14,7 +13,6 @@ class SearchUserPanel extends CommonSearchPanel {
|
||||
required super.keyword,
|
||||
required super.tag,
|
||||
required super.searchType,
|
||||
super.hasHeader = true,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -33,98 +31,82 @@ class _SearchUserPanelState extends CommonSearchPanelState<SearchUserPanel,
|
||||
tag: widget.searchType.name + widget.tag,
|
||||
);
|
||||
|
||||
late TextStyle style;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
style = TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildHeader(LoadingState<List<SearchUserItemModel>?> loadingState) {
|
||||
if (loadingState is Success) {
|
||||
return SliverPersistentHeader(
|
||||
pinned: false,
|
||||
floating: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
extent: 40,
|
||||
bgColor: Theme.of(context).colorScheme.surface,
|
||||
child: Container(
|
||||
height: 40,
|
||||
padding: const EdgeInsets.only(left: 25, right: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => Text(
|
||||
'排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Obx(
|
||||
() => Text(
|
||||
'用户类型: ${controller.userTypeFiltersList[controller.currentUserTypeFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '筛选',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () {
|
||||
controller.onShowFilterDialog(context);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.filter_list_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
Widget buildList(ThemeData theme, List<SearchUserItemModel> list) {
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
SliverPersistentHeader(
|
||||
pinned: false,
|
||||
floating: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
extent: 40,
|
||||
bgColor: theme.colorScheme.surface,
|
||||
child: Container(
|
||||
height: 40,
|
||||
padding: const EdgeInsets.only(left: 25, right: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => Text(
|
||||
'排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
const Spacer(),
|
||||
Obx(
|
||||
() => Text(
|
||||
'用户类型: ${controller.userTypeFiltersList[controller.currentUserTypeFilterval.value]['label']}',
|
||||
maxLines: 1,
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '筛选',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () {
|
||||
controller.onShowFilterDialog(context);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.filter_list_outlined,
|
||||
size: 18,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SliverToBoxAdapter();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildList(List<SearchUserItemModel> list) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||
mainAxisExtent: 66,
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
||||
mainAxisExtent: 66,
|
||||
),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
if (index == list.length - 1) {
|
||||
controller.onLoadMore();
|
||||
}
|
||||
return SearchUserItem(
|
||||
item: list[index],
|
||||
);
|
||||
},
|
||||
childCount: list.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
if (index == list.length - 1) {
|
||||
controller.onLoadMore();
|
||||
}
|
||||
return SearchUserItem(
|
||||
style: style,
|
||||
item: list[index],
|
||||
);
|
||||
},
|
||||
childCount: list.length,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,19 @@ import 'package:get/get.dart';
|
||||
class SearchUserItem extends StatelessWidget {
|
||||
const SearchUserItem({
|
||||
super.key,
|
||||
required this.style,
|
||||
required this.item,
|
||||
});
|
||||
|
||||
final TextStyle style;
|
||||
final SearchUserItemModel item;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String heroTag = Utils.makeHeroTag(item.mid);
|
||||
final theme = Theme.of(context);
|
||||
final style = TextStyle(
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
);
|
||||
return InkWell(
|
||||
onTap: () => Get.toNamed(
|
||||
'/member?mid=${item.mid}',
|
||||
|
||||
@@ -151,6 +151,7 @@ class SearchVideoController
|
||||
),
|
||||
builder: (context) => StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
final theme = Theme.of(context);
|
||||
Widget dateWidget([bool isFirst = true]) {
|
||||
return SearchText(
|
||||
text: DateFormat('yyyy-MM-dd')
|
||||
@@ -200,12 +201,12 @@ class SearchVideoController
|
||||
},
|
||||
bgColor: currentPubTimeFilter == -1 &&
|
||||
(isFirst ? customPubBeginDate : customPubEndDate)
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: theme.colorScheme.outline.withOpacity(0.1),
|
||||
textColor: currentPubTimeFilter == -1 &&
|
||||
(isFirst ? customPubBeginDate : customPubEndDate)
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: Theme.of(context).colorScheme.outline.withOpacity(0.8),
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: theme.colorScheme.outline.withOpacity(0.8),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -271,14 +272,10 @@ class SearchVideoController
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentPubTimeFilter
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] == currentPubTimeFilter
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
@@ -318,14 +315,10 @@ class SearchVideoController
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentTimeFilter
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] == currentTimeFilter
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
@@ -352,14 +345,10 @@ class SearchVideoController
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
bgColor: item['value'] == currentZoneFilter
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: null,
|
||||
textColor: item['value'] == currentZoneFilter
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: null,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart';
|
||||
import 'package:PiliPlus/common/widgets/video_card_h.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/search/result.dart';
|
||||
import 'package:PiliPlus/pages/search/widgets/search_text.dart';
|
||||
import 'package:PiliPlus/pages/search_panel/video/controller.dart';
|
||||
@@ -16,7 +15,6 @@ class SearchVideoPanel extends CommonSearchPanel {
|
||||
required super.keyword,
|
||||
required super.tag,
|
||||
required super.searchType,
|
||||
super.hasHeader = true,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -36,95 +34,93 @@ class _SearchVideoPanelState extends CommonSearchPanelState<SearchVideoPanel,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget buildHeader(LoadingState<List<SearchVideoItemModel>?> loadingState) {
|
||||
if (loadingState is Success) {
|
||||
return SliverPersistentHeader(
|
||||
pinned: false,
|
||||
floating: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
extent: 34,
|
||||
bgColor: Theme.of(context).colorScheme.surface,
|
||||
child: Container(
|
||||
height: 34,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Wrap(
|
||||
children: [
|
||||
for (var i in controller.filterList) ...[
|
||||
Obx(
|
||||
() => SearchText(
|
||||
fontSize: 13,
|
||||
text: i['label'],
|
||||
bgColor: Colors.transparent,
|
||||
textColor:
|
||||
controller.selectedType.value == i['type']
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
onTap: (value) async {
|
||||
controller.selectedType.value = i['type'];
|
||||
controller.order.value =
|
||||
i['type'].toString().split('.').last;
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await controller.onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
Widget buildList(ThemeData theme, List<SearchVideoItemModel> list) {
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
SliverPersistentHeader(
|
||||
pinned: false,
|
||||
floating: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
extent: 34,
|
||||
bgColor: theme.colorScheme.surface,
|
||||
child: Container(
|
||||
height: 34,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Wrap(
|
||||
children: [
|
||||
for (var i in controller.filterList) ...[
|
||||
Obx(
|
||||
() => SearchText(
|
||||
fontSize: 13,
|
||||
text: i['label'],
|
||||
bgColor: Colors.transparent,
|
||||
textColor:
|
||||
controller.selectedType.value == i['type']
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
onTap: (value) async {
|
||||
controller.selectedType.value = i['type'];
|
||||
controller.order.value =
|
||||
i['type'].toString().split('.').last;
|
||||
SmartDialog.showLoading(msg: 'loading');
|
||||
await controller.onReload();
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const VerticalDivider(indent: 7, endIndent: 8),
|
||||
const SizedBox(width: 3),
|
||||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '筛选',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () => controller.onShowFilterDialog(context),
|
||||
icon: Icon(
|
||||
Icons.filter_list_outlined,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
const VerticalDivider(indent: 7, endIndent: 8),
|
||||
const SizedBox(width: 3),
|
||||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: IconButton(
|
||||
tooltip: '筛选',
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () => controller.onShowFilterDialog(context),
|
||||
icon: Icon(
|
||||
Icons.filter_list_outlined,
|
||||
size: 18,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SliverToBoxAdapter();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildList(List<SearchVideoItemModel> list) {
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == list.length - 1) {
|
||||
controller.onLoadMore();
|
||||
}
|
||||
return VideoCardH(
|
||||
videoItem: list[index],
|
||||
showPubdate: true,
|
||||
);
|
||||
},
|
||||
childCount: list.length,
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: Grid.videoCardHDelegate(context),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == list.length - 1) {
|
||||
controller.onLoadMore();
|
||||
}
|
||||
return VideoCardH(
|
||||
videoItem: list[index],
|
||||
showPubdate: true,
|
||||
);
|
||||
},
|
||||
childCount: list.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,13 +20,11 @@ abstract class CommonSearchPanel extends StatefulWidget {
|
||||
required this.keyword,
|
||||
required this.searchType,
|
||||
required this.tag,
|
||||
this.hasHeader = false,
|
||||
});
|
||||
|
||||
final String keyword;
|
||||
final SearchType searchType;
|
||||
final String tag;
|
||||
final bool hasHeader;
|
||||
}
|
||||
|
||||
abstract class CommonSearchPanelState<
|
||||
@@ -41,6 +39,7 @@ abstract class CommonSearchPanelState<
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = Theme.of(context);
|
||||
return refreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.onRefresh();
|
||||
@@ -49,18 +48,12 @@ abstract class CommonSearchPanelState<
|
||||
controller: controller.scrollController,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
if (widget.hasHeader)
|
||||
Obx(() => buildHeader(controller.loadingState.value)),
|
||||
Obx(() => _buildBody(controller.loadingState.value)),
|
||||
Obx(() => _buildBody(theme, controller.loadingState.value)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildHeader(LoadingState<List<T>?> loadingState) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Widget get _builLoading {
|
||||
return SliverGrid(
|
||||
gridDelegate: switch (widget.searchType) {
|
||||
@@ -103,7 +96,7 @@ abstract class CommonSearchPanelState<
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<T>?> loadingState) {
|
||||
Widget _buildBody(ThemeData theme, LoadingState<List<T>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => widget.searchType == SearchType.live_room
|
||||
? SliverPadding(
|
||||
@@ -115,7 +108,7 @@ abstract class CommonSearchPanelState<
|
||||
)
|
||||
: _builLoading,
|
||||
Success() => loadingState.response?.isNotEmpty == true
|
||||
? buildList(loadingState.response!)
|
||||
? buildList(theme, loadingState.response!)
|
||||
: HttpError(
|
||||
onReload: controller.onReload,
|
||||
),
|
||||
@@ -126,5 +119,5 @@ abstract class CommonSearchPanelState<
|
||||
};
|
||||
}
|
||||
|
||||
Widget buildList(List<T> list);
|
||||
Widget buildList(ThemeData theme, List<T> list);
|
||||
}
|
||||
|
||||
@@ -62,11 +62,12 @@ class _SearchResultPageState extends State<SearchResultPage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
shape: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.08),
|
||||
color: theme.dividerColor.withOpacity(0.08),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@@ -86,7 +87,7 @@ class _SearchResultPageState extends State<SearchResultPage>
|
||||
width: double.infinity,
|
||||
child: Text(
|
||||
_searchResultController.keyword,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
@@ -121,18 +122,18 @@ class _SearchResultPageState extends State<SearchResultPage>
|
||||
indicatorPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 3, vertical: 8),
|
||||
indicator: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
labelColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
labelColor: theme.colorScheme.onSecondaryContainer,
|
||||
labelStyle: TabBarTheme.of(context)
|
||||
.labelStyle
|
||||
?.copyWith(fontSize: 13) ??
|
||||
const TextStyle(fontSize: 13),
|
||||
dividerColor: Colors.transparent,
|
||||
dividerHeight: 0,
|
||||
unselectedLabelColor: Theme.of(context).colorScheme.outline,
|
||||
unselectedLabelColor: theme.colorScheme.outline,
|
||||
tabAlignment: TabAlignment.start,
|
||||
onTap: (index) {
|
||||
if (_tabController.indexIsChanging.not) {
|
||||
|
||||
@@ -52,6 +52,7 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
final maxWidth = constraints.maxWidth;
|
||||
final width = constraints.maxWidth > constraints.maxHeight
|
||||
@@ -78,10 +79,8 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.surface
|
||||
.withOpacity(_scrollRatio.value),
|
||||
backgroundColor:
|
||||
theme.colorScheme.surface.withOpacity(_scrollRatio.value),
|
||||
foregroundColor: flag ? null : Colors.white,
|
||||
systemOverlayStyle: flag
|
||||
? null
|
||||
@@ -94,10 +93,7 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
||||
preferredSize: Size.fromHeight(1),
|
||||
child: Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.1),
|
||||
color: theme.colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
@@ -134,7 +130,8 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
||||
},
|
||||
),
|
||||
),
|
||||
Obx(() => _buildBody(_controller.loadingState.value)),
|
||||
Obx(() =>
|
||||
_buildBody(theme, _controller.loadingState.value)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -145,7 +142,8 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<SearchKeywordList>?> loadingState) {
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<SearchKeywordList>?> loadingState) {
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverToBoxAdapter(child: LinearProgressIndicator()),
|
||||
Success() => loadingState.response?.isNotEmpty == true
|
||||
@@ -180,7 +178,7 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
||||
0 => const Color(0xFFfdad13),
|
||||
1 => const Color(0xFF8aace1),
|
||||
2 => const Color(0xFFdfa777),
|
||||
_ => Theme.of(context).colorScheme.outline,
|
||||
_ => theme.colorScheme.outline,
|
||||
},
|
||||
fontSize: 17,
|
||||
fontStyle: FontStyle.italic,
|
||||
@@ -218,7 +216,7 @@ class _SearchTrendingPageState extends State<SearchTrendingPage> {
|
||||
separatorBuilder: (context, index) => Divider(
|
||||
height: 1,
|
||||
indent: 48,
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
color: theme.colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -42,14 +42,13 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
final ColorSelectController ctr = Get.put(ColorSelectController());
|
||||
FlexSchemeVariant _dynamicSchemeVariant =
|
||||
FlexSchemeVariant.values[GStorage.schemeVariant];
|
||||
TextStyle get titleStyle => Theme.of(context).textTheme.titleMedium!;
|
||||
TextStyle get subTitleStyle => Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
TextStyle titleStyle = theme.textTheme.titleMedium!;
|
||||
TextStyle subTitleStyle =
|
||||
theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('选择应用主题')),
|
||||
body: SafeArea(
|
||||
@@ -119,11 +118,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
height: 1,
|
||||
fontSize: 13,
|
||||
color: ctr.type.value == 0
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.8)
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
? theme.colorScheme.outline.withOpacity(0.8)
|
||||
: theme.colorScheme.secondary,
|
||||
),
|
||||
strutStyle: StrutStyle(leading: 0, height: 1),
|
||||
),
|
||||
@@ -131,11 +127,8 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
size: 20,
|
||||
Icons.keyboard_arrow_right,
|
||||
color: ctr.type.value == 0
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.8)
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
? theme.colorScheme.outline.withOpacity(0.8)
|
||||
: theme.colorScheme.secondary,
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -236,9 +229,7 @@ class _ColorSelectPageState extends State<ColorSelectPage> {
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ctr.currentColor.value != index
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
? theme.colorScheme.outline
|
||||
: null,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -35,6 +35,7 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
actions: [
|
||||
@@ -65,11 +66,8 @@ class _FontSizeSelectPageState extends State<FontSizeSelectPage> {
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
.withOpacity(0.3))),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
color: theme.colorScheme.primary.withOpacity(0.3))),
|
||||
color: theme.colorScheme.surface,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
@@ -129,7 +129,7 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||
}
|
||||
|
||||
// 设定倍速弹窗
|
||||
void showBottomSheet(index) {
|
||||
void showBottomSheet(ThemeData theme, int index) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
useSafeArea: true,
|
||||
@@ -150,11 +150,11 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||
menuAction(index, item['id']);
|
||||
},
|
||||
minLeadingWidth: 0,
|
||||
iconColor: Theme.of(context).colorScheme.onSurface,
|
||||
iconColor: theme.colorScheme.onSurface,
|
||||
leading: item['leading'],
|
||||
title: Text(
|
||||
item['title'],
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
style: theme.textTheme.titleSmall,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -194,6 +194,7 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('倍速设置'),
|
||||
@@ -218,7 +219,7 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||
const EdgeInsets.only(left: 14, right: 14, top: 6, bottom: 0),
|
||||
child: Text(
|
||||
'点击下方按钮设置默认(长按)倍速',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
@@ -255,7 +256,7 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||
children: [
|
||||
Text(
|
||||
'倍速列表',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
TextButton(
|
||||
@@ -278,7 +279,7 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
|
||||
children: List.generate(
|
||||
speedList.length,
|
||||
(index) => FilledButton.tonal(
|
||||
onPressed: () => showBottomSheet(index),
|
||||
onPressed: () => showBottomSheet(theme, index),
|
||||
child: Text(speedList[index].toString()),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -8,6 +8,7 @@ class RecommendSetting extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: showAppBar == false ? null : AppBar(title: const Text('推荐流设置')),
|
||||
body: ListView(
|
||||
@@ -20,9 +21,8 @@ class RecommendSetting extends StatelessWidget {
|
||||
'* 其它(如热门视频、手动搜索、链接跳转等)均不受过滤器影响。\n'
|
||||
'* 设定较严苛的条件可导致推荐项数锐减或多次请求,请酌情选择。\n'
|
||||
'* 后续可能会增加更多过滤条件,敬请期待。',
|
||||
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline.withOpacity(0.7)),
|
||||
style: theme.textTheme.labelSmall!
|
||||
.copyWith(color: theme.colorScheme.outline.withOpacity(0.7)),
|
||||
),
|
||||
),
|
||||
SizedBox(height: MediaQuery.paddingOf(context).bottom + 80),
|
||||
|
||||
@@ -56,12 +56,6 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
TextStyle get _titleStyle => TextStyle(fontSize: 15);
|
||||
TextStyle get _subTitleStyle => TextStyle(
|
||||
fontSize: 13,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
);
|
||||
|
||||
_checkServerStatus() {
|
||||
Request()
|
||||
.get(
|
||||
@@ -78,7 +72,9 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget get _blockLimitItem => ListTile(
|
||||
Widget _blockLimitItem(
|
||||
ThemeData theme, TextStyle titleStyle, TextStyle subTitleStyle) =>
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
_textController.text = _blockLimit.toString();
|
||||
@@ -86,7 +82,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('最短片段时长', style: _titleStyle),
|
||||
title: Text('最短片段时长', style: titleStyle),
|
||||
content: TextFormField(
|
||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||
controller: _textController,
|
||||
@@ -102,7 +98,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -121,10 +117,10 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
},
|
||||
);
|
||||
},
|
||||
title: Text('最短片段时长', style: _titleStyle),
|
||||
title: Text('最短片段时长', style: titleStyle),
|
||||
subtitle: Text(
|
||||
'忽略短于此时长的片段',
|
||||
style: _subTitleStyle,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
trailing: Text(
|
||||
'${_blockLimit}s',
|
||||
@@ -132,17 +128,19 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _aboudItem => ListTile(
|
||||
Widget _aboudItem(TextStyle titleStyle, TextStyle subTitleStyle) => ListTile(
|
||||
dense: true,
|
||||
title: Text('关于空降助手', style: _titleStyle),
|
||||
subtitle: Text(_url, style: _subTitleStyle),
|
||||
title: Text('关于空降助手', style: titleStyle),
|
||||
subtitle: Text(_url, style: subTitleStyle),
|
||||
onTap: () => PageUtils.launchURL(_url),
|
||||
);
|
||||
|
||||
Widget get _userIdItem => ListTile(
|
||||
Widget _userIdItem(
|
||||
ThemeData theme, TextStyle titleStyle, TextStyle subTitleStyle) =>
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: Text('用户ID', style: _titleStyle),
|
||||
subtitle: Text(_userId, style: _subTitleStyle),
|
||||
title: Text('用户ID', style: titleStyle),
|
||||
subtitle: Text(_userId, style: subTitleStyle),
|
||||
onTap: () {
|
||||
final key = GlobalKey<FormState>();
|
||||
_textController.text = _userId;
|
||||
@@ -150,7 +148,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('用户ID', style: _titleStyle),
|
||||
title: Text('用户ID', style: titleStyle),
|
||||
content: Form(
|
||||
key: key,
|
||||
child: TextFormField(
|
||||
@@ -184,7 +182,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -218,12 +216,12 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Widget get _blockToastItem => ListTile(
|
||||
Widget _blockToastItem(TextStyle titleStyle) => ListTile(
|
||||
dense: true,
|
||||
onTap: _updateBlockToast,
|
||||
title: Text(
|
||||
'显示跳过Toast',
|
||||
style: _titleStyle,
|
||||
style: titleStyle,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
alignment: Alignment.centerRight,
|
||||
@@ -242,36 +240,39 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
),
|
||||
));
|
||||
|
||||
Widget get _blockTrackItem => ListTile(
|
||||
dense: true,
|
||||
onTap: _updateBlockTrack,
|
||||
title: Text(
|
||||
'跳过次数统计跟踪',
|
||||
style: _titleStyle,
|
||||
),
|
||||
subtitle: Text(
|
||||
// from origin extension
|
||||
'此功能追踪您跳过了哪些片段,让用户知道他们提交的片段帮助了多少人。同时点赞会作为依据,确保垃圾信息不会污染数据库。在您每次跳过片段时,我们都会向服务器发送一条消息。希望大家开启此项设置,以便得到更准确的统计数据。:)',
|
||||
style: _subTitleStyle,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
alignment: Alignment.centerRight,
|
||||
scale: 0.8,
|
||||
child: Switch(
|
||||
thumbIcon: WidgetStateProperty.resolveWith<Icon?>((states) {
|
||||
if (states.isNotEmpty && states.first == WidgetState.selected) {
|
||||
return const Icon(Icons.done);
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
value: _blockTrack,
|
||||
onChanged: (val) {
|
||||
_updateBlockTrack();
|
||||
},
|
||||
),
|
||||
));
|
||||
Widget _blockTrackItem(TextStyle titleStyle, TextStyle subTitleStyle) =>
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: _updateBlockTrack,
|
||||
title: Text(
|
||||
'跳过次数统计跟踪',
|
||||
style: titleStyle,
|
||||
),
|
||||
subtitle: Text(
|
||||
// from origin extension
|
||||
'此功能追踪您跳过了哪些片段,让用户知道他们提交的片段帮助了多少人。同时点赞会作为依据,确保垃圾信息不会污染数据库。在您每次跳过片段时,我们都会向服务器发送一条消息。希望大家开启此项设置,以便得到更准确的统计数据。:)',
|
||||
style: subTitleStyle,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
alignment: Alignment.centerRight,
|
||||
scale: 0.8,
|
||||
child: Switch(
|
||||
thumbIcon: WidgetStateProperty.resolveWith<Icon?>((states) {
|
||||
if (states.isNotEmpty && states.first == WidgetState.selected) {
|
||||
return const Icon(Icons.done);
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
value: _blockTrack,
|
||||
onChanged: (val) {
|
||||
_updateBlockTrack();
|
||||
},
|
||||
),
|
||||
));
|
||||
|
||||
Widget get _blockServerItem => ListTile(
|
||||
Widget _blockServerItem(
|
||||
ThemeData theme, TextStyle titleStyle, TextStyle subTitleStyle) =>
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
_textController.text = _blockServer;
|
||||
@@ -279,7 +280,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('服务器地址', style: _titleStyle),
|
||||
title: Text('服务器地址', style: titleStyle),
|
||||
content: TextFormField(
|
||||
keyboardType: TextInputType.url,
|
||||
controller: _textController,
|
||||
@@ -302,7 +303,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -324,20 +325,20 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
},
|
||||
title: Text(
|
||||
'服务器地址',
|
||||
style: _titleStyle,
|
||||
style: titleStyle,
|
||||
),
|
||||
subtitle: Text(
|
||||
_blockServer,
|
||||
style: _subTitleStyle,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _serverStatusItem => ListTile(
|
||||
Widget _serverStatusItem(ThemeData theme, TextStyle titleStyle) => ListTile(
|
||||
dense: true,
|
||||
onTap: _checkServerStatus,
|
||||
title: Text(
|
||||
'服务器状态',
|
||||
style: _titleStyle,
|
||||
style: titleStyle,
|
||||
),
|
||||
trailing: Text(
|
||||
_serverStatus == null
|
||||
@@ -350,41 +351,51 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
color: _serverStatus == null
|
||||
? null
|
||||
: _serverStatus == true
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.error,
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.error,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _divider => SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
);
|
||||
|
||||
Widget get _dividerL => SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
thickness: 16,
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final titleStyle = TextStyle(fontSize: 15);
|
||||
|
||||
final subTitleStyle = TextStyle(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
);
|
||||
|
||||
final divider = SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
height: 1,
|
||||
color: theme.colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
);
|
||||
|
||||
final dividerL = SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
thickness: 16,
|
||||
color: theme.colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('空降助手')),
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
_dividerL,
|
||||
SliverToBoxAdapter(child: _serverStatusItem),
|
||||
_dividerL,
|
||||
SliverToBoxAdapter(child: _blockLimitItem),
|
||||
_divider,
|
||||
SliverToBoxAdapter(child: _blockToastItem),
|
||||
_divider,
|
||||
SliverToBoxAdapter(child: _blockTrackItem),
|
||||
_dividerL,
|
||||
dividerL,
|
||||
SliverToBoxAdapter(child: _serverStatusItem(theme, titleStyle)),
|
||||
dividerL,
|
||||
SliverToBoxAdapter(
|
||||
child: _blockLimitItem(theme, titleStyle, subTitleStyle)),
|
||||
divider,
|
||||
SliverToBoxAdapter(child: _blockToastItem(titleStyle)),
|
||||
divider,
|
||||
SliverToBoxAdapter(child: _blockTrackItem(titleStyle, titleStyle)),
|
||||
dividerL,
|
||||
SliverList.separated(
|
||||
itemCount: _blockSettings.length,
|
||||
itemBuilder: (context, index) => ListTile(
|
||||
@@ -493,11 +504,8 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
fontSize: 14,
|
||||
color: _blockSettings[index].second ==
|
||||
SkipType.disable
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.7)
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
? theme.colorScheme.outline.withOpacity(0.7)
|
||||
: theme.colorScheme.secondary,
|
||||
),
|
||||
strutStyle: StrutStyle(height: 1, leading: 0),
|
||||
),
|
||||
@@ -506,11 +514,8 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
size: MediaQuery.textScalerOf(context).scale(14),
|
||||
color:
|
||||
_blockSettings[index].second == SkipType.disable
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withOpacity(0.7)
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
? theme.colorScheme.outline.withOpacity(0.7)
|
||||
: theme.colorScheme.secondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -524,22 +529,24 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
fontSize: 12,
|
||||
color: _blockSettings[index].second == SkipType.disable
|
||||
? null
|
||||
: Theme.of(context).colorScheme.outline,
|
||||
: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
separatorBuilder: (context, index) => Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
color: theme.colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
_dividerL,
|
||||
SliverToBoxAdapter(child: _userIdItem),
|
||||
_divider,
|
||||
SliverToBoxAdapter(child: _blockServerItem),
|
||||
_dividerL,
|
||||
SliverToBoxAdapter(child: _aboudItem),
|
||||
_dividerL,
|
||||
dividerL,
|
||||
SliverToBoxAdapter(
|
||||
child: _userIdItem(theme, titleStyle, subTitleStyle)),
|
||||
divider,
|
||||
SliverToBoxAdapter(
|
||||
child: _blockServerItem(theme, titleStyle, subTitleStyle)),
|
||||
dividerL,
|
||||
SliverToBoxAdapter(child: _aboudItem(titleStyle, subTitleStyle)),
|
||||
dividerL,
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: 55 + MediaQuery.paddingOf(context).bottom,
|
||||
|
||||
@@ -42,11 +42,6 @@ class SettingPage extends StatefulWidget {
|
||||
class _SettingPageState extends State<SettingPage> {
|
||||
late String _type = 'privacySetting';
|
||||
final RxBool _noAccount = Accounts.accountMode.isEmpty.obs;
|
||||
TextStyle get _titleStyle => Theme.of(context).textTheme.titleMedium!;
|
||||
TextStyle get _subTitleStyle => Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline);
|
||||
bool get _isPortrait => context.orientation == Orientation.portrait;
|
||||
|
||||
final List<_SettingsModel> _items = [
|
||||
@@ -100,6 +95,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: _isPortrait
|
||||
@@ -117,7 +113,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
}),
|
||||
),
|
||||
body: _isPortrait
|
||||
? _buildList
|
||||
? _buildList(theme)
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -127,12 +123,12 @@ class _SettingPageState extends State<SettingPage> {
|
||||
context: context,
|
||||
removeRight: true,
|
||||
removeTop: true,
|
||||
child: _buildList,
|
||||
child: _buildList(theme),
|
||||
),
|
||||
),
|
||||
VerticalDivider(
|
||||
width: 1,
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
|
||||
color: theme.colorScheme.outline.withOpacity(0.1),
|
||||
),
|
||||
Expanded(
|
||||
flex: 6,
|
||||
@@ -167,29 +163,30 @@ class _SettingPageState extends State<SettingPage> {
|
||||
}
|
||||
}
|
||||
|
||||
Color? _getTileColor(String name) {
|
||||
Color? _getTileColor(ThemeData theme, String name) {
|
||||
if (_isPortrait) {
|
||||
return null;
|
||||
} else {
|
||||
return name == _type
|
||||
? Theme.of(context).colorScheme.onInverseSurface
|
||||
: null;
|
||||
return name == _type ? theme.colorScheme.onInverseSurface : null;
|
||||
}
|
||||
}
|
||||
|
||||
Widget get _buildList {
|
||||
Widget _buildList(ThemeData theme) {
|
||||
TextStyle titleStyle = theme.textTheme.titleMedium!;
|
||||
TextStyle subTitleStyle =
|
||||
theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline);
|
||||
return ListView(
|
||||
children: [
|
||||
_buildSearchItem,
|
||||
_buildSearchItem(theme),
|
||||
..._items.sublist(0, _items.length - 1).map(
|
||||
(item) => ListTile(
|
||||
tileColor: _getTileColor(item.name),
|
||||
tileColor: _getTileColor(theme, item.name),
|
||||
onTap: () => _toPage(item.name),
|
||||
leading: Icon(item.icon),
|
||||
title: Text(item.title, style: _titleStyle),
|
||||
title: Text(item.title, style: titleStyle),
|
||||
subtitle: item.subtitle == null
|
||||
? null
|
||||
: Text(item.subtitle!, style: _subTitleStyle),
|
||||
: Text(item.subtitle!, style: subTitleStyle),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
@@ -203,14 +200,14 @@ class _SettingPageState extends State<SettingPage> {
|
||||
: ListTile(
|
||||
leading: const Icon(Icons.logout_outlined),
|
||||
onTap: () => _logoutDialog(context),
|
||||
title: Text('退出登录', style: _titleStyle),
|
||||
title: Text('退出登录', style: titleStyle),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
tileColor: _getTileColor(_items.last.name),
|
||||
tileColor: _getTileColor(theme, _items.last.name),
|
||||
onTap: () => _toPage(_items.last.name),
|
||||
leading: Icon(_items.last.icon),
|
||||
title: Text(_items.last.title, style: _titleStyle),
|
||||
title: Text(_items.last.title, style: titleStyle),
|
||||
),
|
||||
SizedBox(height: MediaQuery.paddingOf(context).bottom + 80),
|
||||
],
|
||||
@@ -234,9 +231,10 @@ class _SettingPageState extends State<SettingPage> {
|
||||
return Accounts.deleteAll(result);
|
||||
}
|
||||
|
||||
await showDialog(
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
final theme = Theme.of(context);
|
||||
return AlertDialog(
|
||||
title: const Text('提示'),
|
||||
content: Text(
|
||||
@@ -247,7 +245,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
child: Text(
|
||||
'点错了',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -258,7 +256,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
},
|
||||
child: Text(
|
||||
'仅登出',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
style: TextStyle(color: theme.colorScheme.error),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
@@ -281,7 +279,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget get _buildSearchItem => Padding(
|
||||
Widget _buildSearchItem(ThemeData theme) => Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 5),
|
||||
child: InkWell(
|
||||
onTap: () => Get.toNamed('/settingsSearch'),
|
||||
@@ -290,7 +288,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
),
|
||||
child: Center(
|
||||
child: Row(
|
||||
|
||||
@@ -27,6 +27,7 @@ class _MultiSelectDialogState<T> extends State<MultiSelectDialog<T>> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return AlertDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
title: Text(widget.title),
|
||||
@@ -43,7 +44,7 @@ class _MultiSelectDialogState<T> extends State<MultiSelectDialog<T>> {
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
title: Text(
|
||||
i.value,
|
||||
style: Theme.of(context).textTheme.titleMedium!,
|
||||
style: theme.textTheme.titleMedium!,
|
||||
),
|
||||
onChanged: (value) {
|
||||
isChecked
|
||||
@@ -63,7 +64,7 @@ class _MultiSelectDialogState<T> extends State<MultiSelectDialog<T>> {
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -91,10 +91,9 @@ class _SetSelectItemState extends State<SetSelectItem> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextStyle subTitleStyle = Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline);
|
||||
final theme = Theme.of(context);
|
||||
TextStyle subTitleStyle =
|
||||
theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline);
|
||||
return ListTile(
|
||||
onTap: () {},
|
||||
title: Text(widget.title!),
|
||||
|
||||
@@ -59,7 +59,7 @@ class _SetSwitchItemState extends State<SetSwitchItem> {
|
||||
setVal();
|
||||
}
|
||||
|
||||
void switchChange(value) async {
|
||||
void switchChange(ThemeData theme, value) async {
|
||||
if (widget.setKey == SettingBoxKey.badCertificateCallback &&
|
||||
(value ?? !val)) {
|
||||
showDialog(
|
||||
@@ -73,7 +73,7 @@ class _SetSwitchItemState extends State<SetSwitchItem> {
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -111,22 +111,21 @@ class _SetSwitchItemState extends State<SetSwitchItem> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
TextStyle titleStyle = widget.titleStyle ??
|
||||
Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
color: widget.onTap != null && !val
|
||||
? Theme.of(context).colorScheme.outline
|
||||
: null,
|
||||
);
|
||||
TextStyle subTitleStyle = Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium!
|
||||
.copyWith(color: Theme.of(context).colorScheme.outline);
|
||||
theme.textTheme.titleMedium!.copyWith(
|
||||
color:
|
||||
widget.onTap != null && !val ? theme.colorScheme.outline : null,
|
||||
);
|
||||
TextStyle subTitleStyle =
|
||||
theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline);
|
||||
return ListTile(
|
||||
contentPadding: widget.contentPadding,
|
||||
enabled: widget.onTap != null ? val : true,
|
||||
enableFeedback: true,
|
||||
onTap: () =>
|
||||
widget.onTap != null ? widget.onTap?.call() : switchChange(null),
|
||||
onTap: () => widget.onTap != null
|
||||
? widget.onTap?.call()
|
||||
: switchChange(theme, null),
|
||||
title: Text(widget.title!, style: titleStyle),
|
||||
subtitle: widget.subtitle != null
|
||||
? Text(widget.subtitle!, style: subTitleStyle)
|
||||
@@ -144,7 +143,7 @@ class _SetSwitchItemState extends State<SetSwitchItem> {
|
||||
return null;
|
||||
}),
|
||||
value: val,
|
||||
onChanged: switchChange,
|
||||
onChanged: (value) => switchChange(theme, value),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user