From 87c7b84e5c038a52e3e0fa0e3e282b24708b8533 Mon Sep 17 00:00:00 2001 From: dom Date: Fri, 24 Jul 2026 09:38:34 +0800 Subject: [PATCH] opt ui Signed-off-by: dom --- lib/pages/download/search/controller.dart | 3 +- lib/pages/member/widget/user_info_card.dart | 21 +- .../video/reply/widgets/reply_item_grpc.dart | 43 ++-- lib/pages/video/widgets/header_mixin.dart | 17 +- lib/services/shutdown_timer_service.dart | 243 +++++++++--------- 5 files changed, 169 insertions(+), 158 deletions(-) diff --git a/lib/pages/download/search/controller.dart b/lib/pages/download/search/controller.dart index e291fa77b..310170f00 100644 --- a/lib/pages/download/search/controller.dart +++ b/lib/pages/download/search/controller.dart @@ -32,7 +32,8 @@ class DownloadSearchController .where( (e) => e.title.toLowerCase().contains(text) || - e.showTitle.toLowerCase().contains(text), + e.showTitle.toLowerCase().contains(text) || + (e.ownerName?.toLowerCase().contains(text) ?? false), ) .toList(), ); diff --git a/lib/pages/member/widget/user_info_card.dart b/lib/pages/member/widget/user_info_card.dart index 45736a180..945531a9c 100644 --- a/lib/pages/member/widget/user_info_card.dart +++ b/lib/pages/member/widget/user_info_card.dart @@ -395,6 +395,7 @@ class UserInfoCard extends StatelessWidget { } Column _buildRight(ColorScheme colorScheme) => Column( + spacing: 5, mainAxisSize: .min, children: [ Row( @@ -418,7 +419,6 @@ class UserInfoCard extends StatelessWidget { .skip(1) .toList(), ), - const SizedBox(height: 5), Row( spacing: 10, mainAxisSize: .min, @@ -441,22 +441,25 @@ class UserInfoCard extends StatelessWidget { } }, icon: const Icon(Icons.mail_outline, size: 21), - style: IconButton.styleFrom( - side: BorderSide( - width: 1.0, - color: colorScheme.outline.withValues(alpha: 0.3), + style: ButtonStyle( + side: WidgetStatePropertyAll( + BorderSide( + width: 1.0, + color: colorScheme.outline.withValues(alpha: 0.3), + ), ), - padding: .zero, - tapTargetSize: .padded, + padding: const WidgetStatePropertyAll(.zero), + tapTargetSize: .shrinkWrap, visualDensity: .compact, ), ), Expanded( child: FilledButton.tonal( onPressed: !isOwner && relation == -1 ? null : onFollow, - style: FilledButton.styleFrom( + style: ButtonStyle( + padding: const WidgetStatePropertyAll(.zero), backgroundColor: relation != 0 - ? colorScheme.onInverseSurface + ? WidgetStatePropertyAll(colorScheme.onInverseSurface) : null, tapTargetSize: .padded, visualDensity: const VisualDensity(vertical: -1.8), diff --git a/lib/pages/video/reply/widgets/reply_item_grpc.dart b/lib/pages/video/reply/widgets/reply_item_grpc.dart index bc9dd3f74..105c9ad05 100644 --- a/lib/pages/video/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/reply/widgets/reply_item_grpc.dart @@ -21,7 +21,6 @@ import 'package:PiliPlus/grpc/reply.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/reply.dart'; import 'package:PiliPlus/http/video.dart'; -import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/dynamics/widgets/vote.dart'; import 'package:PiliPlus/pages/member/widget/medal_widget.dart'; @@ -33,6 +32,7 @@ import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/bili_utils.dart'; import 'package:PiliPlus/utils/color_utils.dart'; import 'package:PiliPlus/utils/danmaku_utils.dart'; +import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension/context_ext.dart'; import 'package:PiliPlus/utils/extension/iterable_ext.dart'; @@ -167,13 +167,14 @@ class ReplyItemGrpc extends StatelessWidget { ? member.garbPendantImage : null, ), - Expanded( + Flexible( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, + crossAxisAlignment: .start, children: [ Row( spacing: 6, + mainAxisSize: .min, children: [ Flexible( child: Text( @@ -196,7 +197,7 @@ class ReplyItemGrpc extends StatelessWidget { if (replyItem.mid == upMid) const PBadge( text: 'UP', - size: PBadgeSize.small, + size: .small, isStack: false, fontSize: 9, ) @@ -211,23 +212,33 @@ class ReplyItemGrpc extends StatelessWidget { nameColor: DmUtils.decimalToColor( member.fansMedalColorName.toInt(), ), - padding: const .symmetric( - horizontal: 6, - vertical: 1.5, - ), + padding: const .symmetric(horizontal: 6, vertical: 1.5), ), ], ), Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Text( - ' • ${replyItem.replyControl.location}', + replyLevel == 0 + ? DateFormatUtils.format( + replyItem.ctime.toInt(), + format: DateFormatUtils.longFormatDs, + ) + : DateFormatUtils.dateFormat(replyItem.ctime.toInt()), style: TextStyle( fontSize: 11, color: colorScheme.outline, ), ), + if (replyItem.replyControl.hasLocation()) + Text( + ' • ${replyItem.replyControl.location}', + style: TextStyle( + fontSize: 11, + color: colorScheme.outline, + ), + ), ], ), ], @@ -337,12 +348,12 @@ class ReplyItemGrpc extends StatelessWidget { children: [ if (replyControl.isUpTop) ...[ const WidgetSpan( - alignment: PlaceholderAlignment.middle, + alignment: .middle, child: PBadge( text: 'TOP', - size: PBadgeSize.small, + size: .small, isStack: false, - type: PBadgeType.line_primary, + type: .line_primary, fontSize: 9, textScaleFactor: 1, ), @@ -628,10 +639,10 @@ class ReplyItemGrpc extends StatelessWidget { if (childReply.mid == upMid) ...[ const TextSpan(text: ' '), const WidgetSpan( - alignment: PlaceholderAlignment.middle, + alignment: .middle, child: PBadge( text: 'UP', - size: PBadgeSize.small, + size: .small, isStack: false, fontSize: 9, textScaleFactor: 1, diff --git a/lib/pages/video/widgets/header_mixin.dart b/lib/pages/video/widgets/header_mixin.dart index cbce50c6e..09844e2c1 100644 --- a/lib/pages/video/widgets/header_mixin.dart +++ b/lib/pages/video/widgets/header_mixin.dart @@ -24,22 +24,17 @@ mixin HeaderMixin on State { StatefulWidgetBuilder builder, { ValueGetter? padding, }) { + final theme = this.theme; return PageUtils.showVideoBottomSheet( context, maxWidth: 512, padding: padding, - child: StatefulBuilder( - builder: (context, setState) { - final theme = this.theme; - if (theme != null) { - return Theme( + child: theme != null + ? Theme( data: theme, - child: builder(this.context, setState), - ); - } - return builder(context, setState); - }, - ), + child: StatefulBuilder(builder: builder), + ) + : StatefulBuilder(builder: builder), ); } diff --git a/lib/services/shutdown_timer_service.dart b/lib/services/shutdown_timer_service.dart index a54c85842..99f2c9dc4 100644 --- a/lib/services/shutdown_timer_service.dart +++ b/lib/services/shutdown_timer_service.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/pages/video/introduction/ugc/widgets/menu_row.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/theme_utils.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -145,130 +146,130 @@ class ShutdownTimerService { if (isLive) { _waitUntilCompleted = false; } + + final child = StatefulBuilder( + builder: (context, setState) { + final ThemeData theme = Theme.of(context); + return Padding( + padding: const .all(12), + child: Material( + clipBehavior: .hardEdge, + color: theme.colorScheme.surface, + borderRadius: const .all(.circular(12)), + child: ListView( + padding: const .symmetric(vertical: 14), + children: [ + const Center(child: Text('定时关闭', style: titleStyle)), + const SizedBox(height: 10), + ...{...scheduleTimeMinutes, _durationInMinutes} + .sorted(Comparable.compare) + .map( + (minutes) => ListTile( + dense: true, + onTap: () { + Navigator.pop(context); + _startShutdownTimer(minutes); + }, + title: Text( + switch (minutes) { + 0 => '禁用', + _ => _format(minutes), + }, + style: titleStyle, + ), + trailing: _durationInMinutes == minutes + ? Icon( + size: 20, + Icons.done, + color: theme.colorScheme.primary, + ) + : null, + ), + ), + ListTile( + dense: true, + onTap: () { + final (int hour, int minute) = _parseMinutes( + _durationInMinutes, + ); + showTimePicker( + context: context, + initialEntryMode: .inputOnly, + initialTime: TimeOfDay(hour: hour, minute: minute), + builder: (context, child) => MediaQuery( + data: MediaQuery.of( + context, + ).copyWith(alwaysUse24HourFormat: true), + child: child!, + ), + ).then((time) { + if (time != null) { + _startShutdownTimer(time.hour * 60 + time.minute); + setState(() {}); + } + }); + }, + title: const Text('自定义', style: titleStyle), + ), + if (!isLive) ...[ + Builder( + builder: (context) { + void onChanged([_]) { + _waitUntilCompleted = !_waitUntilCompleted; + (context as Element).markNeedsBuild(); + } + + return ListTile( + dense: true, + onTap: onChanged, + title: const Text('额外等待视频播放完毕', style: titleStyle), + trailing: Transform.scale( + alignment: Alignment.centerRight, + scale: 0.8, + child: Switch( + value: _waitUntilCompleted, + onChanged: onChanged, + ), + ), + ); + }, + ), + ], + const SizedBox(height: 5), + Padding( + padding: const .only(left: 18), + child: Builder( + builder: (context) { + return Row( + spacing: 12, + children: [ + const Text('倒计时结束:', style: titleStyle), + ..._ShutdownType.values.map( + (e) => ActionRowLineItem( + onTap: () { + _shutdownType = e; + (context as Element).markNeedsBuild(); + }, + text: ' ${e.label} ', + selectStatus: _shutdownType == e, + ), + ), + ], + ); + }, + ), + ), + ], + ), + ), + ); + }, + ); + PageUtils.showVideoBottomSheet( context, maxWidth: 512, - child: StatefulBuilder( - builder: (_, setState) { - final ThemeData theme = Theme.of(context); - return Theme( - data: theme, - child: Padding( - padding: const .all(12), - child: Material( - clipBehavior: .hardEdge, - color: theme.colorScheme.surface, - borderRadius: const .all(.circular(12)), - child: ListView( - padding: const .symmetric(vertical: 14), - children: [ - const Center(child: Text('定时关闭', style: titleStyle)), - const SizedBox(height: 10), - ...{...scheduleTimeMinutes, _durationInMinutes} - .sorted(Comparable.compare) - .map( - (minutes) => ListTile( - dense: true, - onTap: () { - Navigator.pop(context); - _startShutdownTimer(minutes); - }, - title: Text( - switch (minutes) { - 0 => '禁用', - _ => _format(minutes), - }, - style: titleStyle, - ), - trailing: _durationInMinutes == minutes - ? Icon( - size: 20, - Icons.done, - color: theme.colorScheme.primary, - ) - : null, - ), - ), - ListTile( - dense: true, - onTap: () { - final (int hour, int minute) = _parseMinutes( - _durationInMinutes, - ); - showTimePicker( - context: context, - initialEntryMode: .inputOnly, - initialTime: TimeOfDay(hour: hour, minute: minute), - builder: (context, child) => MediaQuery( - data: MediaQuery.of( - context, - ).copyWith(alwaysUse24HourFormat: true), - child: child!, - ), - ).then((time) { - if (time != null) { - _startShutdownTimer(time.hour * 60 + time.minute); - setState(() {}); - } - }); - }, - title: const Text('自定义', style: titleStyle), - ), - if (!isLive) ...[ - Builder( - builder: (context) { - void onChanged([_]) { - _waitUntilCompleted = !_waitUntilCompleted; - (context as Element).markNeedsBuild(); - } - - return ListTile( - dense: true, - onTap: onChanged, - title: const Text('额外等待视频播放完毕', style: titleStyle), - trailing: Transform.scale( - alignment: Alignment.centerRight, - scale: 0.8, - child: Switch( - value: _waitUntilCompleted, - onChanged: onChanged, - ), - ), - ); - }, - ), - ], - const SizedBox(height: 5), - Padding( - padding: const .only(left: 18), - child: Builder( - builder: (context) { - return Row( - spacing: 12, - children: [ - const Text('倒计时结束:', style: titleStyle), - ..._ShutdownType.values.map( - (e) => ActionRowLineItem( - onTap: () { - _shutdownType = e; - (context as Element).markNeedsBuild(); - }, - text: ' ${e.label} ', - selectStatus: _shutdownType == e, - ), - ), - ], - ); - }, - ), - ), - ], - ), - ), - ), - ); - }, - ), + child: isLive ? Theme(data: ThemeUtils.darkTheme, child: child) : child, ); } }