Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-07-24 09:38:34 +08:00
parent 47aaa28898
commit 87c7b84e5c
5 changed files with 169 additions and 158 deletions

View File

@@ -32,7 +32,8 @@ class DownloadSearchController
.where( .where(
(e) => (e) =>
e.title.toLowerCase().contains(text) || e.title.toLowerCase().contains(text) ||
e.showTitle.toLowerCase().contains(text), e.showTitle.toLowerCase().contains(text) ||
(e.ownerName?.toLowerCase().contains(text) ?? false),
) )
.toList(), .toList(),
); );

View File

@@ -395,6 +395,7 @@ class UserInfoCard extends StatelessWidget {
} }
Column _buildRight(ColorScheme colorScheme) => Column( Column _buildRight(ColorScheme colorScheme) => Column(
spacing: 5,
mainAxisSize: .min, mainAxisSize: .min,
children: [ children: [
Row( Row(
@@ -418,7 +419,6 @@ class UserInfoCard extends StatelessWidget {
.skip(1) .skip(1)
.toList(), .toList(),
), ),
const SizedBox(height: 5),
Row( Row(
spacing: 10, spacing: 10,
mainAxisSize: .min, mainAxisSize: .min,
@@ -441,22 +441,25 @@ class UserInfoCard extends StatelessWidget {
} }
}, },
icon: const Icon(Icons.mail_outline, size: 21), icon: const Icon(Icons.mail_outline, size: 21),
style: IconButton.styleFrom( style: ButtonStyle(
side: BorderSide( side: WidgetStatePropertyAll(
width: 1.0, BorderSide(
color: colorScheme.outline.withValues(alpha: 0.3), width: 1.0,
color: colorScheme.outline.withValues(alpha: 0.3),
),
), ),
padding: .zero, padding: const WidgetStatePropertyAll(.zero),
tapTargetSize: .padded, tapTargetSize: .shrinkWrap,
visualDensity: .compact, visualDensity: .compact,
), ),
), ),
Expanded( Expanded(
child: FilledButton.tonal( child: FilledButton.tonal(
onPressed: !isOwner && relation == -1 ? null : onFollow, onPressed: !isOwner && relation == -1 ? null : onFollow,
style: FilledButton.styleFrom( style: ButtonStyle(
padding: const WidgetStatePropertyAll(.zero),
backgroundColor: relation != 0 backgroundColor: relation != 0
? colorScheme.onInverseSurface ? WidgetStatePropertyAll(colorScheme.onInverseSurface)
: null, : null,
tapTargetSize: .padded, tapTargetSize: .padded,
visualDensity: const VisualDensity(vertical: -1.8), visualDensity: const VisualDensity(vertical: -1.8),

View File

@@ -21,7 +21,6 @@ import 'package:PiliPlus/grpc/reply.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/reply.dart'; import 'package:PiliPlus/http/reply.dart';
import 'package:PiliPlus/http/video.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/models/common/image_type.dart';
import 'package:PiliPlus/pages/dynamics/widgets/vote.dart'; import 'package:PiliPlus/pages/dynamics/widgets/vote.dart';
import 'package:PiliPlus/pages/member/widget/medal_widget.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/bili_utils.dart';
import 'package:PiliPlus/utils/color_utils.dart'; import 'package:PiliPlus/utils/color_utils.dart';
import 'package:PiliPlus/utils/danmaku_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/duration_utils.dart';
import 'package:PiliPlus/utils/extension/context_ext.dart'; import 'package:PiliPlus/utils/extension/context_ext.dart';
import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/extension/iterable_ext.dart';
@@ -167,13 +167,14 @@ class ReplyItemGrpc extends StatelessWidget {
? member.garbPendantImage ? member.garbPendantImage
: null, : null,
), ),
Expanded( Flexible(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: .min,
mainAxisSize: MainAxisSize.min, crossAxisAlignment: .start,
children: [ children: [
Row( Row(
spacing: 6, spacing: 6,
mainAxisSize: .min,
children: [ children: [
Flexible( Flexible(
child: Text( child: Text(
@@ -196,7 +197,7 @@ class ReplyItemGrpc extends StatelessWidget {
if (replyItem.mid == upMid) if (replyItem.mid == upMid)
const PBadge( const PBadge(
text: 'UP', text: 'UP',
size: PBadgeSize.small, size: .small,
isStack: false, isStack: false,
fontSize: 9, fontSize: 9,
) )
@@ -211,23 +212,33 @@ class ReplyItemGrpc extends StatelessWidget {
nameColor: DmUtils.decimalToColor( nameColor: DmUtils.decimalToColor(
member.fansMedalColorName.toInt(), member.fansMedalColorName.toInt(),
), ),
padding: const .symmetric( padding: const .symmetric(horizontal: 6, vertical: 1.5),
horizontal: 6,
vertical: 1.5,
),
), ),
], ],
), ),
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: .min,
children: [ children: [
Text( Text(
'${replyItem.replyControl.location}', replyLevel == 0
? DateFormatUtils.format(
replyItem.ctime.toInt(),
format: DateFormatUtils.longFormatDs,
)
: DateFormatUtils.dateFormat(replyItem.ctime.toInt()),
style: TextStyle( style: TextStyle(
fontSize: 11, fontSize: 11,
color: colorScheme.outline, 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: [ children: [
if (replyControl.isUpTop) ...[ if (replyControl.isUpTop) ...[
const WidgetSpan( const WidgetSpan(
alignment: PlaceholderAlignment.middle, alignment: .middle,
child: PBadge( child: PBadge(
text: 'TOP', text: 'TOP',
size: PBadgeSize.small, size: .small,
isStack: false, isStack: false,
type: PBadgeType.line_primary, type: .line_primary,
fontSize: 9, fontSize: 9,
textScaleFactor: 1, textScaleFactor: 1,
), ),
@@ -628,10 +639,10 @@ class ReplyItemGrpc extends StatelessWidget {
if (childReply.mid == upMid) ...[ if (childReply.mid == upMid) ...[
const TextSpan(text: ' '), const TextSpan(text: ' '),
const WidgetSpan( const WidgetSpan(
alignment: PlaceholderAlignment.middle, alignment: .middle,
child: PBadge( child: PBadge(
text: 'UP', text: 'UP',
size: PBadgeSize.small, size: .small,
isStack: false, isStack: false,
fontSize: 9, fontSize: 9,
textScaleFactor: 1, textScaleFactor: 1,

View File

@@ -24,22 +24,17 @@ mixin HeaderMixin<T extends StatefulWidget> on State<T> {
StatefulWidgetBuilder builder, { StatefulWidgetBuilder builder, {
ValueGetter<EdgeInsets>? padding, ValueGetter<EdgeInsets>? padding,
}) { }) {
final theme = this.theme;
return PageUtils.showVideoBottomSheet( return PageUtils.showVideoBottomSheet(
context, context,
maxWidth: 512, maxWidth: 512,
padding: padding, padding: padding,
child: StatefulBuilder( child: theme != null
builder: (context, setState) { ? Theme(
final theme = this.theme;
if (theme != null) {
return Theme(
data: theme, data: theme,
child: builder(this.context, setState), child: StatefulBuilder(builder: builder),
); )
} : StatefulBuilder(builder: builder),
return builder(context, setState);
},
),
); );
} }

View File

@@ -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/controller.dart';
import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_status.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/theme_utils.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -145,130 +146,130 @@ class ShutdownTimerService {
if (isLive) { if (isLive) {
_waitUntilCompleted = false; _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( PageUtils.showVideoBottomSheet(
context, context,
maxWidth: 512, maxWidth: 512,
child: StatefulBuilder( child: isLive ? Theme(data: ThemeUtils.darkTheme, child: child) : child,
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,
),
),
],
);
},
),
),
],
),
),
),
);
},
),
); );
} }
} }