mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-26 05:20:09 +08:00
@@ -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(),
|
||||
);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -24,22 +24,17 @@ mixin HeaderMixin<T extends StatefulWidget> on State<T> {
|
||||
StatefulWidgetBuilder builder, {
|
||||
ValueGetter<EdgeInsets>? 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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user