158 lines
4.4 KiB
Dart
158 lines
4.4 KiB
Dart
|
|
import 'package:flutter/material.dart';
|
||
|
|
import 'package:forui/forui.dart';
|
||
|
|
|
||
|
|
import '../../../providers/version_priority_provider.dart';
|
||
|
|
import '../../../shared/theme/app_theme.dart';
|
||
|
|
import '../../../shared/theme/app_theme_scope.dart';
|
||
|
|
|
||
|
|
class VersionPrioritySection extends StatelessWidget {
|
||
|
|
final List<VersionPriority> activePriorities;
|
||
|
|
final ValueChanged<VersionPriority> onToggle;
|
||
|
|
final ValueChanged<List<VersionPriority>> onReorder;
|
||
|
|
|
||
|
|
const VersionPrioritySection({
|
||
|
|
super.key,
|
||
|
|
required this.activePriorities,
|
||
|
|
required this.onToggle,
|
||
|
|
required this.onReorder,
|
||
|
|
});
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
final theme = Theme.of(context);
|
||
|
|
final tokens = context.appTokens;
|
||
|
|
|
||
|
|
return Column(
|
||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
|
children: [
|
||
|
|
Text(
|
||
|
|
'选择后按顺序排列详情页的视频版本',
|
||
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
||
|
|
color: tokens.mutedForeground,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
const SizedBox(height: 12),
|
||
|
|
Wrap(
|
||
|
|
spacing: 8,
|
||
|
|
runSpacing: 8,
|
||
|
|
children: VersionPriority.values.map((p) {
|
||
|
|
final isActive = activePriorities.contains(p);
|
||
|
|
return FilterChip(
|
||
|
|
label: Text(p.label),
|
||
|
|
selected: isActive,
|
||
|
|
onSelected: (_) => onToggle(p),
|
||
|
|
);
|
||
|
|
}).toList(),
|
||
|
|
),
|
||
|
|
if (activePriorities.isNotEmpty) ...[
|
||
|
|
const SizedBox(height: 12),
|
||
|
|
Text(
|
||
|
|
activePriorities
|
||
|
|
.map((p) => p.label.replaceAll('优先', ''))
|
||
|
|
.join(' > '),
|
||
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
||
|
|
color: tokens.mutedForeground,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
if (activePriorities.length > 1) ...[
|
||
|
|
const SizedBox(height: 8),
|
||
|
|
GestureDetector(
|
||
|
|
onTap: () => _showReorderDialog(context),
|
||
|
|
child: Text(
|
||
|
|
'调整顺序',
|
||
|
|
style: TextStyle(fontSize: 12, color: theme.colorScheme.primary),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
],
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
void _showReorderDialog(BuildContext context) {
|
||
|
|
showFDialog(
|
||
|
|
context: context,
|
||
|
|
builder: (_, _, animation) => AppThemeScope(
|
||
|
|
child: FDialog.raw(
|
||
|
|
animation: animation,
|
||
|
|
builder: (context, _) => PriorityOrderDialog(
|
||
|
|
priorities: activePriorities,
|
||
|
|
onChanged: onReorder,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class PriorityOrderDialog extends StatefulWidget {
|
||
|
|
final List<VersionPriority> priorities;
|
||
|
|
final ValueChanged<List<VersionPriority>> onChanged;
|
||
|
|
|
||
|
|
const PriorityOrderDialog({
|
||
|
|
super.key,
|
||
|
|
required this.priorities,
|
||
|
|
required this.onChanged,
|
||
|
|
});
|
||
|
|
|
||
|
|
@override
|
||
|
|
State<PriorityOrderDialog> createState() => PriorityOrderDialogState();
|
||
|
|
}
|
||
|
|
|
||
|
|
class PriorityOrderDialogState extends State<PriorityOrderDialog> {
|
||
|
|
late final List<VersionPriority> _items;
|
||
|
|
|
||
|
|
@override
|
||
|
|
void initState() {
|
||
|
|
super.initState();
|
||
|
|
_items = List.of(widget.priorities);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
return FDialog(
|
||
|
|
title: const Text('调整优先级顺序'),
|
||
|
|
body: SizedBox(
|
||
|
|
width: 320,
|
||
|
|
height: (_items.length * 56.0).clamp(0, 400),
|
||
|
|
child: ReorderableListView.builder(
|
||
|
|
shrinkWrap: true,
|
||
|
|
buildDefaultDragHandles: false,
|
||
|
|
itemCount: _items.length,
|
||
|
|
onReorder: (oldIndex, newIndex) {
|
||
|
|
setState(() {
|
||
|
|
if (newIndex > oldIndex) newIndex -= 1;
|
||
|
|
final item = _items.removeAt(oldIndex);
|
||
|
|
_items.insert(newIndex, item);
|
||
|
|
});
|
||
|
|
widget.onChanged(List.of(_items));
|
||
|
|
},
|
||
|
|
itemBuilder: (context, index) {
|
||
|
|
return ListTile(
|
||
|
|
key: ValueKey(_items[index].name),
|
||
|
|
leading: Text(
|
||
|
|
'${index + 1}',
|
||
|
|
style: const TextStyle(
|
||
|
|
fontSize: 12,
|
||
|
|
fontWeight: FontWeight.w600,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
title: Text(
|
||
|
|
_items[index].label,
|
||
|
|
style: const TextStyle(fontSize: 14),
|
||
|
|
),
|
||
|
|
trailing: ReorderableDragStartListener(
|
||
|
|
index: index,
|
||
|
|
child: const Icon(Icons.drag_handle, size: 18),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
},
|
||
|
|
),
|
||
|
|
),
|
||
|
|
actions: [
|
||
|
|
FButton(onPress: () => Navigator.pop(context), child: const Text('完成')),
|
||
|
|
],
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|