This commit is contained in:
chen08209
2026-03-12 15:04:33 +08:00
parent 67402899a8
commit 88d3c23cdc
5 changed files with 110 additions and 113 deletions

View File

@@ -431,4 +431,21 @@ enum CoreStatus { connecting, connected, disconnected }
enum RuleScene { added, disabled, custom }
enum ItemPosition { start, middle, end, startAndEnd }
enum ItemPosition {
start,
middle,
end,
startAndEnd;
static ItemPosition get(int index, int length) {
ItemPosition position = ItemPosition.middle;
if (length == 1) {
position = ItemPosition.startAndEnd;
} else if (index == length - 1) {
position = ItemPosition.end;
} else if (index == 0) {
position = ItemPosition.start;
}
return position;
}
}

View File

@@ -34,6 +34,29 @@ class _CustomProxyGroupsView extends ConsumerWidget {
);
}
Widget _buildItem({
required BuildContext context,
required ProxyGroup proxyGroup,
required int index,
required int total,
}) {
final position = ItemPosition.get(index, total);
return ItemPositionProvider(
position: position,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: DecorationListItem(
minVerticalPadding: 8,
title: Text(proxyGroup.name),
subtitle: Text(proxyGroup.type.name),
onPressed: () {
_handleEditProxyGroup(context, proxyGroup);
},
),
),
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final proxyGroups = ref.watch(proxyGroupsProvider(profileId)).value ?? [];
@@ -42,38 +65,19 @@ class _CustomProxyGroupsView extends ConsumerWidget {
body: ReorderableListView.builder(
buildDefaultDragHandles: false,
padding: EdgeInsets.only(bottom: 16),
itemBuilder: (_, index) {
itemBuilder: (context, index) {
final proxyGroup = proxyGroups[index];
return ReorderableDelayedDragStartListener(
key: ValueKey(proxyGroup),
index: index,
child: Container(
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 16),
child: CommonCard(
radius: 16,
padding: EdgeInsets.all(16),
onPressed: () {
_handleEditProxyGroup(context, proxyGroup);
},
child: ListTile(
minTileHeight: 0,
minVerticalPadding: 0,
titleTextStyle: context.textTheme.bodyMedium?.toJetBrainsMono,
contentPadding: const EdgeInsets.symmetric(
horizontal: 4,
vertical: 4,
),
title: Text(proxyGroup.name),
subtitle: Text(proxyGroup.type.name),
),
),
child: _buildItem(
context: context,
proxyGroup: proxyGroup,
total: proxyGroups.length,
index: index,
),
);
},
itemExtent:
28 +
globalState.measure.bodyMediumHeight +
globalState.measure.bodyLargeHeight,
itemCount: proxyGroups.length,
onReorder: (oldIndex, newIndex) {
_handleReorder(ref, profileId, oldIndex, newIndex);
@@ -248,7 +252,7 @@ class _EditProxyGroupViewState extends ConsumerState<_EditProxyGroupView> {
Widget? trailing,
final VoidCallback? onPressed,
}) {
return CommonInputListItem(
return DecorationListItem(
onPressed: onPressed,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -589,6 +593,34 @@ class _EditProxiesViewState extends ConsumerState<_EditProxiesView> {
);
}
Widget _buildItem({
required String proxyName,
required String? proxyType,
required int index,
required int length,
}) {
final position = ItemPosition.get(index, length);
return Container(
key: Key(proxyName),
padding: EdgeInsets.symmetric(horizontal: 16),
child: ItemPositionProvider(
position: position,
child: DecorationListItem(
minVerticalPadding: 8,
title: Text(proxyName),
subtitle: Text(proxyType ?? proxyName.toLowerCase()),
leading: CommonMinIconButtonTheme(
child: IconButton.filledTonal(
onPressed: () {},
icon: Icon(Icons.remove, size: 18),
padding: EdgeInsets.zero,
),
),
),
),
);
}
@override
Widget build(BuildContext context) {
final profileId = ProfileIdProvider.of(context)!.profileId;
@@ -645,44 +677,15 @@ class _EditProxiesViewState extends ConsumerState<_EditProxiesView> {
SliverReorderableList(
itemBuilder: (_, index) {
final proxyName = proxyNames[index];
return Container(
key: Key(proxyName),
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 16),
color: Colors.transparent,
child: Row(
spacing: 8,
children: [
Flexible(
child: CommonCard(
radius: 18,
onPressed: () {},
child: ListTile(
leading: CommonMinIconButtonTheme(
child: IconButton.filledTonal(
onPressed: () {},
icon: Icon(Icons.remove, size: 18),
padding: EdgeInsets.zero,
),
),
minTileHeight:
32 + globalState.measure.bodyMediumHeight,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
),
title: Text(proxyName),
subtitle: Text(
proxyTypeMap[proxyName] ??
proxyName.toLowerCase(),
),
),
),
),
],
),
return _buildItem(
proxyName: proxyName,
proxyType: proxyTypeMap[proxyName],
index: index,
length: proxyNames.length,
);
},
itemExtent:
24 +
16 +
globalState.measure.bodyMediumHeight +
globalState.measure.bodyLargeHeight,
itemCount: proxyNames.length,

View File

@@ -439,19 +439,12 @@ class _ReorderableProfilesSheetState extends State<ReorderableProfilesSheet> {
}
Widget _buildItem(int index, [bool isDecorator = false]) {
ItemPosition position = ItemPosition.middle;
if (profiles.length == 1) {
position = ItemPosition.startAndEnd;
} else if (index == profiles.length - 1) {
position = ItemPosition.end;
} else if (index == 0) {
position = ItemPosition.start;
}
final position = ItemPosition.get(index, profiles.length);
final profile = profiles[index];
return ItemPositionProvider(
key: Key(profile.id.toString()),
position: position,
child: CommonInputListItem(
child: DecorationListItem(
trailing: ReorderableDelayedDragStartListener(
index: index,
child: const Icon(Icons.drag_handle),

View File

@@ -321,25 +321,18 @@ class _ListInputPageState extends ConsumerState<ListInputPage> {
Widget _buildItem({
required String value,
required int index,
required int totalLength,
required int length,
required bool isSelected,
required bool isEditing,
isDecorator = false,
}) {
ItemPosition position = ItemPosition.middle;
if (totalLength == 1) {
position = ItemPosition.startAndEnd;
} else if (index == totalLength - 1) {
position = ItemPosition.end;
} else if (index == 0) {
position = ItemPosition.start;
}
final position = ItemPosition.get(index, length);
return ReorderableDelayedDragStartListener(
key: ValueKey(value),
index: index,
child: ItemPositionProvider(
position: position,
child: CommonSelectedInputListItem(
child: SelectedDecorationListItem(
isDecorator: isDecorator,
title: widget.titleBuilder(value),
isSelected: isSelected,
@@ -424,7 +417,7 @@ class _ListInputPageState extends ConsumerState<ListInputPage> {
return _buildItem(
value: value,
index: index,
totalLength: _items.length,
length: _items.length,
isSelected: selectedItems.contains(value),
isEditing: selectedItems.isNotEmpty,
);
@@ -435,7 +428,7 @@ class _ListInputPageState extends ConsumerState<ListInputPage> {
_buildItem(
value: value,
index: index,
totalLength: _items.length,
length: _items.length,
isDecorator: true,
isSelected: selectedItems.contains(value),
isEditing: selectedItems.isNotEmpty,
@@ -581,25 +574,18 @@ class _MapInputPageState extends ConsumerState<MapInputPage> {
Widget _buildItem({
required MapEntry<String, String> value,
required int index,
required int totalLength,
required int length,
required bool isSelected,
required bool isEditing,
isDecorator = false,
}) {
ItemPosition position = ItemPosition.middle;
if (totalLength == 1) {
position = ItemPosition.startAndEnd;
} else if (index == totalLength - 1) {
position = ItemPosition.end;
} else if (index == 0) {
position = ItemPosition.start;
}
final position = ItemPosition.get(index, length);
return ReorderableDelayedDragStartListener(
key: ValueKey(value),
index: index,
child: ItemPositionProvider(
position: position,
child: CommonSelectedInputListItem(
child: SelectedDecorationListItem(
isDecorator: isDecorator,
title: widget.titleBuilder(value),
leading: widget.leadingBuilder != null
@@ -687,7 +673,7 @@ class _MapInputPageState extends ConsumerState<MapInputPage> {
return _buildItem(
value: value,
index: index,
totalLength: _items.length,
length: _items.length,
isSelected: selectedItems.contains(value.key),
isEditing: selectedItems.isNotEmpty,
);
@@ -698,7 +684,7 @@ class _MapInputPageState extends ConsumerState<MapInputPage> {
_buildItem(
value: value,
index: index,
totalLength: _items.length,
length: _items.length,
isDecorator: true,
isSelected: selectedItems.contains(value.key),
isEditing: selectedItems.isNotEmpty,

View File

@@ -548,15 +548,9 @@ Widget generateSectionV3({
List<Widget>? actions,
}) {
final genItems = items.mapIndexed<Widget>((index, item) {
if (items.length == 1) {
return ItemPositionProvider(
position: ItemPosition.startAndEnd,
child: item,
);
} else if (index == 0) {
return ItemPositionProvider(position: ItemPosition.start, child: item);
} else if (index == items.length - 1) {
return ItemPositionProvider(position: ItemPosition.end, child: item);
final position = ItemPosition.get(index, items.length);
if (position != ItemPosition.middle) {
return ItemPositionProvider(position: position, child: item);
}
return item;
});
@@ -649,24 +643,26 @@ class CommonSelectedListItem extends StatelessWidget {
}
}
class CommonInputListItem extends StatelessWidget {
class DecorationListItem extends StatelessWidget {
final bool isDecorator;
final Widget? title;
final Widget title;
final Widget? subtitle;
final Widget? leading;
final Widget? trailing;
final bool? isSelected;
final VoidCallback? onPressed;
final double minVerticalPadding;
const CommonInputListItem({
const DecorationListItem({
super.key,
this.isDecorator = false,
this.title,
required this.title,
this.leading,
this.trailing,
this.subtitle,
this.isSelected,
this.onPressed,
this.minVerticalPadding = 6,
});
@override
@@ -681,7 +677,7 @@ class CommonInputListItem extends StatelessWidget {
ItemPosition.startAndEnd,
].contains(position);
return Container(
clipBehavior: Clip.hardEdge,
clipBehavior: Clip.antiAlias,
decoration: ShapeDecoration(
shape: isDecorator == true
? LinearBorder.none
@@ -695,10 +691,12 @@ class CommonInputListItem extends StatelessWidget {
child: CommonCard(
radius: 0,
isSelected: isSelected,
padding: EdgeInsets.zero,
type: CommonCardType.filled,
onPressed: onPressed,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: ListTile(
@@ -706,7 +704,7 @@ class CommonInputListItem extends StatelessWidget {
contentPadding: const EdgeInsets.only(right: 16, left: 16),
title: title,
subtitle: subtitle,
minVerticalPadding: 0,
minVerticalPadding: minVerticalPadding,
minTileHeight: 54,
trailing: trailing,
),
@@ -720,7 +718,7 @@ class CommonInputListItem extends StatelessWidget {
}
}
class CommonSelectedInputListItem extends StatelessWidget {
class SelectedDecorationListItem extends StatelessWidget {
final bool isSelected;
final bool isEditing;
final Widget title;
@@ -730,7 +728,7 @@ class CommonSelectedInputListItem extends StatelessWidget {
final bool isDecorator;
final Widget? leading;
const CommonSelectedInputListItem({
const SelectedDecorationListItem({
super.key,
required this.isSelected,
required this.onSelected,
@@ -744,7 +742,7 @@ class CommonSelectedInputListItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CommonInputListItem(
return DecorationListItem(
title: title,
isDecorator: isDecorator,
isSelected: isSelected,