Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-09-04 22:08:32 +08:00
parent 172389b12b
commit 7e1e42181c
13 changed files with 219 additions and 194 deletions

View File

@@ -479,6 +479,7 @@ class AuthorPanel extends StatelessWidget {
mid: moduleAuthor.mid,
dynId: item.idStr,
reasonType: reasonType,
reasonDesc: reasonType == 0 ? reasonDesc : null,
);
},
);

View File

@@ -172,9 +172,7 @@ class _VotePanelState extends State<VotePanel> {
CheckBoxText(
text: '匿名',
selected: anonymity,
onChanged: (val) {
anonymity = val;
},
onChanged: (val) => anonymity = val,
),
],
);

View File

@@ -1,5 +1,3 @@
import 'dart:ui' show Offset;
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/match.dart';
import 'package:PiliPlus/models_new/match/match_info/contest.dart';
@@ -18,9 +16,6 @@ class MatchInfoController extends CommonDynController {
final Rx<LoadingState<MatchContest?>> infoState =
LoadingState<MatchContest?>.loading().obs;
@override
Offset get fabOffset => const Offset(0, 2);
@override
void onInit() {
super.onInit();

View File

@@ -21,7 +21,7 @@ class MusicDetailController extends CommonDynController {
bool get showDynActionBar => Pref.showDynActionBar;
String get shareUrl =>
'https://music.bilibili.com/h5/music-detail?music_id=${musicId}';
'https://music.bilibili.com/h5/music-detail?music_id=$musicId';
@override
void onInit() {

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
typedef PopupMenuItemSelected<T> = bool Function(T value);
class PopupMenuText<T> extends StatefulWidget {
final String title;
final T initialValue;
@@ -24,9 +26,17 @@ class PopupMenuText<T> extends StatefulWidget {
class _PopupMenuTextState<T> extends State<PopupMenuText<T>> {
late T select = widget.initialValue;
@override
void didUpdateWidget(PopupMenuText<T> oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.initialValue != widget.initialValue) {
select = widget.initialValue;
}
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final secondary = Theme.of(context).colorScheme.secondary;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
@@ -35,10 +45,11 @@ class _PopupMenuTextState<T> extends State<PopupMenuText<T>> {
initialValue: select,
onSelected: (value) {
if (value == select) return;
setState(() {
select = value;
widget.onSelected(value);
});
if (!widget.onSelected(value)) {
setState(() {
select = value;
});
}
},
itemBuilder: widget.itemBuilder,
child: Row(
@@ -49,7 +60,7 @@ class _PopupMenuTextState<T> extends State<PopupMenuText<T>> {
style: TextStyle(
height: 1,
fontSize: 14,
color: theme.colorScheme.secondary,
color: secondary,
),
strutStyle: const StrutStyle(
height: 1,
@@ -59,7 +70,7 @@ class _PopupMenuTextState<T> extends State<PopupMenuText<T>> {
Icon(
MdiIcons.unfoldMoreHorizontal,
size: MediaQuery.textScalerOf(context).scale(14),
color: theme.colorScheme.secondary,
color: secondary,
),
],
),

View File

@@ -57,7 +57,7 @@ class PostPanel extends CommonCollapseSlidePage {
static Widget segmentWidget(
ThemeData theme, {
required PostSegmentModel item,
required double currentPos,
required double Function() currentPos, // get real-time pos
required double videoDuration,
}) {
Widget segment(bool isFirst) => Builder(
@@ -81,7 +81,7 @@ class PostPanel extends CommonCollapseSlidePage {
updateSegment(
isFirst: isFirst,
item: item,
value: currentPos,
value: currentPos(),
);
(context as Element).markNeedsBuild();
},
@@ -377,82 +377,105 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
color: theme.colorScheme.onInverseSurface,
borderRadius: const BorderRadius.all(Radius.circular(12)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (item.actionType != ActionType.full)
PostPanel.segmentWidget(
theme,
item: item,
currentPos: currentPos,
videoDuration: videoDuration,
),
Wrap(
runSpacing: 8,
spacing: 16,
children: [
PopupMenuText(
title: '分类',
initialValue: item.category,
onSelected: (e) {
item.category = e;
List<ActionType> constraintList = e.toActionType;
if (!constraintList.contains(item.actionType)) {
item.actionType = constraintList.first;
}
switch (e) {
case SegmentType.poi_highlight:
PostPanel.updateSegment(
isFirst: false,
item: item,
value: item.segment.first,
);
break;
case SegmentType.exclusive_access:
child: Builder(
builder: (context) => Column(
spacing: 8,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (item.actionType != ActionType.full)
PostPanel.segmentWidget(
theme,
item: item,
currentPos: () => currentPos,
videoDuration: videoDuration,
),
Wrap(
runSpacing: 8,
spacing: 16,
children: [
PopupMenuText(
title: '分类',
initialValue: item.category,
onSelected: (e) {
bool flag = false;
if (item.category == SegmentType.exclusive_access ||
item.category == SegmentType.poi_highlight) {
flag = true;
}
item.category = e;
List<ActionType> constraintList = e.toActionType;
if (!constraintList.contains(item.actionType)) {
item.actionType = constraintList.first;
flag = true;
}
switch (e) {
case SegmentType.poi_highlight:
PostPanel.updateSegment(
isFirst: false,
item: item,
value: item.segment.first,
);
break;
case SegmentType.exclusive_access:
PostPanel.updateSegment(
isFirst: true,
item: item,
value: 0,
);
break;
default:
}
if (flag) {
(context as Element).markNeedsBuild();
}
return flag;
},
itemBuilder: (context) => SegmentType.values
.map(
(e) =>
PopupMenuItem(value: e, child: Text(e.title)),
)
.toList(),
getSelectTitle: (category) => category.title,
),
PopupMenuText(
title: '行为类别',
initialValue: item.actionType,
onSelected: (e) {
bool flag = false;
if (item.actionType == ActionType.full) {
flag = true;
}
item.actionType = e;
if (e == ActionType.full) {
flag = true;
PostPanel.updateSegment(
isFirst: true,
item: item,
value: 0,
);
break;
default:
}
},
itemBuilder: (context) => SegmentType.values
.map(
(e) => PopupMenuItem(value: e, child: Text(e.title)),
)
.toList(),
getSelectTitle: (category) => category.title,
),
PopupMenuText(
title: '行为类别',
initialValue: item.actionType,
onSelected: (e) {
item.actionType = e;
if (e == ActionType.full) {
PostPanel.updateSegment(
isFirst: true,
item: item,
value: 0,
);
}
},
itemBuilder: (context) => ActionType.values
.map(
(e) => PopupMenuItem(
enabled: item.category.toActionType.contains(e),
value: e,
child: Text(e.title),
),
)
.toList(),
getSelectTitle: (i) => i.title,
),
],
),
],
}
if (flag) {
(context as Element).markNeedsBuild();
}
return flag;
},
itemBuilder: (context) => ActionType.values
.map(
(e) => PopupMenuItem(
enabled: item.category.toActionType.contains(e),
value: e,
child: Text(e.title),
),
)
.toList(),
getSelectTitle: (i) => i.title,
),
],
),
],
),
),
),
Positioned(
@@ -492,7 +515,9 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
await Future.delayed(Duration(milliseconds: delay));
}
videoCtr.seek(
Duration(milliseconds: (item.segment.second * 1000).round()),
Duration(
milliseconds: (item.segment.second * 1000).round(),
),
);
}
},

View File

@@ -38,6 +38,7 @@ class _WhisperPageState extends State<WhisperPage> {
onPressed: () => e.type.action(
context: context,
controller: _controller,
item: e,
),
icon: e.type.icon,
);
@@ -57,6 +58,7 @@ class _WhisperPageState extends State<WhisperPage> {
onTap: () => e.type.action(
context: context,
controller: _controller,
item: e,
),
child: Row(
children: [

View File

@@ -47,6 +47,7 @@ class _WhisperSecPageState extends State<WhisperSecPage> {
onTap: () => e.type.action(
context: context,
controller: _controller,
item: e,
),
child: Row(
children: [