reorganize connections in bottom sheet
This commit is contained in:
@@ -28,6 +28,7 @@ part 'persisted_bool.g.dart';
|
|||||||
|
|
||||||
enum PersistedBoolKey {
|
enum PersistedBoolKey {
|
||||||
extensionsExpanded(key: 'ExtensionsExpanded', defaultValue: false),
|
extensionsExpanded(key: 'ExtensionsExpanded', defaultValue: false),
|
||||||
|
connectionsExpanded(key: 'ConnectionsExpanded', defaultValue: true),
|
||||||
searchSuggestionsExpanded(
|
searchSuggestionsExpanded(
|
||||||
key: 'SearchSuggestionsExpanded',
|
key: 'SearchSuggestionsExpanded',
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
|
|||||||
+54
-9
@@ -2024,6 +2024,9 @@ class _ConnectionCard extends ConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final connectionsExpanded = ref.watch(
|
||||||
|
persistedBoolProvider(PersistedBoolKey.connectionsExpanded),
|
||||||
|
);
|
||||||
final isTorActive = ref.watch(
|
final isTorActive = ref.watch(
|
||||||
torProxyServiceProvider.select((value) => value.value?.isRunning == true),
|
torProxyServiceProvider.select((value) => value.value?.isRunning == true),
|
||||||
);
|
);
|
||||||
@@ -2103,13 +2106,53 @@ class _ConnectionCard extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
final activeCount =
|
||||||
|
(isTorActive ? 1 : 0) +
|
||||||
|
assignedProfiles
|
||||||
|
.where(
|
||||||
|
(profile) =>
|
||||||
|
runtimeEndpointIds.contains(profile.proxyConnectionId),
|
||||||
|
)
|
||||||
|
.length;
|
||||||
|
|
||||||
return _buildMenuCard(
|
return _buildMenuCard(
|
||||||
context,
|
context,
|
||||||
children: [
|
children: [
|
||||||
for (var i = 0; i < rows.length; i++) ...[
|
Theme(
|
||||||
if (i > 0) _buildDivider(),
|
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
|
||||||
rows[i],
|
child: ExpansionTile(
|
||||||
|
leading: Icon(
|
||||||
|
MdiIcons.transitConnectionVariant,
|
||||||
|
color: activeCount > 0
|
||||||
|
? AppColors.of(context).torActiveGreen
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
title: const Text('Connections'),
|
||||||
|
subtitle: Text(
|
||||||
|
activeCount > 0 ? '$activeCount connected' : 'None connected',
|
||||||
|
),
|
||||||
|
initiallyExpanded: connectionsExpanded,
|
||||||
|
onExpansionChanged: (_) => ref
|
||||||
|
.read(
|
||||||
|
persistedBoolProvider(
|
||||||
|
PersistedBoolKey.connectionsExpanded,
|
||||||
|
).notifier,
|
||||||
|
)
|
||||||
|
.toggle(),
|
||||||
|
children: [
|
||||||
|
for (final row in rows) row,
|
||||||
|
const Divider(indent: 56, endIndent: 16),
|
||||||
|
_buildSubTile(
|
||||||
|
'Manage Connections',
|
||||||
|
icon: MdiIcons.lanConnect,
|
||||||
|
onTap: () async {
|
||||||
|
Navigator.pop(context);
|
||||||
|
await const SingboxProxyProfilesRoute().push<void>(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2138,16 +2181,18 @@ class _ConnectionRow extends StatelessWidget {
|
|||||||
final activeColor = AppColors.of(context).torActiveGreen;
|
final activeColor = AppColors.of(context).torActiveGreen;
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
// Trim the right padding by the IconButton's internal inset (~12px) so the
|
contentPadding: const EdgeInsets.only(left: 56, right: 16),
|
||||||
// edit chevron's glyph lands at the same 16px from the edge as the plain
|
|
||||||
// trailing icons used by the Share/More/Containers rows, while keeping the
|
|
||||||
// button's full 48px touch target.
|
|
||||||
contentPadding: const EdgeInsets.only(left: 16, right: 16),
|
|
||||||
leading: Icon(
|
leading: Icon(
|
||||||
icon,
|
icon,
|
||||||
|
size: 20,
|
||||||
color: active ? activeColor : colorScheme.onSurfaceVariant,
|
color: active ? activeColor : colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
title: Text(label, maxLines: 1, overflow: TextOverflow.ellipsis),
|
title: Text(
|
||||||
|
label,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontSize: 14),
|
||||||
|
),
|
||||||
subtitle: Text(active ? 'Connected' : 'Off'),
|
subtitle: Text(active ? 'Connected' : 'Off'),
|
||||||
onTap: enabled ? () => onToggle() : null,
|
onTap: enabled ? () => onToggle() : null,
|
||||||
dense: true,
|
dense: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user