Refine contact refresh flow

This commit is contained in:
Janez T
2026-03-16 21:52:46 +01:00
parent 434d3df53e
commit 84cd8eec00
2 changed files with 48 additions and 51 deletions

View File

@@ -1613,14 +1613,9 @@ class AppProvider with ChangeNotifier {
debugPrint( debugPrint(
'🔄 [AppProvider] Path updated for contact: ${publicKey.sublist(0, 6).map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}...', '🔄 [AppProvider] Path updated for contact: ${publicKey.sublist(0, 6).map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}...',
); );
// Trigger a single contact fetch to get the updated path information if (connectionProvider.deviceInfo.isConnected) {
// This is much more efficient than fetching all contacts unawaited(connectionProvider.getContact(publicKey));
// This happens asynchronously to avoid blocking the event handler }
Future.delayed(const Duration(milliseconds: 100), () {
if (connectionProvider.deviceInfo.isConnected) {
connectionProvider.getContact(publicKey);
}
});
}; };
// When an advertisement is received (PUSH_CODE_ADVERT 0x80) // When an advertisement is received (PUSH_CODE_ADVERT 0x80)
@@ -1996,11 +1991,9 @@ class AppProvider with ChangeNotifier {
contactsProvider.resetContactRouteLocal(latestContact.publicKey); contactsProvider.resetContactRouteLocal(latestContact.publicKey);
if (connectionProvider.deviceInfo.isConnected) { if (connectionProvider.deviceInfo.isConnected) {
await connectionProvider.resetPath(latestContact.publicKey); await connectionProvider.resetPath(latestContact.publicKey);
Future.delayed(const Duration(milliseconds: 150), () { if (connectionProvider.deviceInfo.isConnected) {
if (connectionProvider.deviceInfo.isConnected) { await connectionProvider.getContact(latestContact.publicKey);
connectionProvider.getContact(latestContact.publicKey); }
}
});
} }
} }
} }

View File

@@ -740,15 +740,22 @@ class _ContactsTabState extends State<ContactsTab> {
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (context.watch<ConnectionProvider>().deviceInfo.isConnected) if (context
.watch<ConnectionProvider>()
.deviceInfo
.isConnected)
IconButton( IconButton(
icon: const Icon(Icons.radar, size: 20), icon: const Icon(Icons.radar, size: 20),
tooltip: 'Discover repeaters', tooltip: 'Discover repeaters',
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
onPressed: () { onPressed: () {
context.read<ConnectionProvider>().discoverNodeType(advertType: 2); context
.read<ConnectionProvider>()
.discoverNodeType(advertType: 2);
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Repeater discovery sent')), const SnackBar(
content: Text('Repeater discovery sent'),
),
); );
}, },
), ),
@@ -784,7 +791,6 @@ class _ContactsTabState extends State<ContactsTab> {
_InferredContactGroupCard( _InferredContactGroupCard(
label: 'Others', label: 'Others',
contacts: ungroupedRepeaters, contacts: ungroupedRepeaters,
kindLabel: 'Auto group',
compactContacts: true, compactContacts: true,
currentPosition: _currentPosition, currentPosition: _currentPosition,
calculateDistance: _calculateDistanceInMeters, calculateDistance: _calculateDistanceInMeters,
@@ -809,15 +815,22 @@ class _ContactsTabState extends State<ContactsTab> {
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (context.watch<ConnectionProvider>().deviceInfo.isConnected) if (context
.watch<ConnectionProvider>()
.deviceInfo
.isConnected)
IconButton( IconButton(
icon: const Icon(Icons.radar, size: 20), icon: const Icon(Icons.radar, size: 20),
tooltip: 'Discover sensors', tooltip: 'Discover sensors',
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
onPressed: () { onPressed: () {
context.read<ConnectionProvider>().discoverNodeType(advertType: 4); context
.read<ConnectionProvider>()
.discoverNodeType(advertType: 4);
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Sensor discovery sent')), const SnackBar(
content: Text('Sensor discovery sent'),
),
); );
}, },
), ),
@@ -1018,7 +1031,6 @@ class _ContactsTabState extends State<ContactsTab> {
onDelete: () => context onDelete: () => context
.read<ContactsProvider>() .read<ContactsProvider>()
.removeSavedGroupById(group.group.id), .removeSavedGroupById(group.group.id),
kindLabel: group.group.isAutoGroup ? 'Auto group' : 'Saved filter',
), ),
) )
.toList(); .toList();
@@ -1354,7 +1366,6 @@ class _SectionHeader extends StatelessWidget {
class _InferredContactGroupCard extends StatelessWidget { class _InferredContactGroupCard extends StatelessWidget {
final String label; final String label;
final List<Contact> contacts; final List<Contact> contacts;
final String? kindLabel;
final bool compactContacts; final bool compactContacts;
final Position? currentPosition; final Position? currentPosition;
final double Function(double, double, double, double) calculateDistance; final double Function(double, double, double, double) calculateDistance;
@@ -1366,7 +1377,6 @@ class _InferredContactGroupCard extends StatelessWidget {
const _InferredContactGroupCard({ const _InferredContactGroupCard({
required this.label, required this.label,
required this.contacts, required this.contacts,
this.kindLabel,
this.compactContacts = false, this.compactContacts = false,
required this.currentPosition, required this.currentPosition,
required this.calculateDistance, required this.calculateDistance,
@@ -1381,10 +1391,10 @@ class _InferredContactGroupCard extends StatelessWidget {
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
return Container( return Container(
margin: const EdgeInsets.only(bottom: 12), margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colorScheme.surfaceContainerLow, color: colorScheme.surfaceContainerLow,
borderRadius: BorderRadius.circular(18), borderRadius: BorderRadius.circular(16),
border: Border.all( border: Border.all(
color: colorScheme.outlineVariant.withValues(alpha: 0.35), color: colorScheme.outlineVariant.withValues(alpha: 0.35),
), ),
@@ -1392,40 +1402,29 @@ class _InferredContactGroupCard extends StatelessWidget {
child: Theme( child: Theme(
data: Theme.of(context).copyWith(dividerColor: Colors.transparent), data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
child: ExpansionTile( child: ExpansionTile(
tilePadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), tilePadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 0),
childrenPadding: const EdgeInsets.fromLTRB(12, 0, 12, 8), childrenPadding: const EdgeInsets.fromLTRB(10, 0, 10, 6),
minTileHeight: 44,
initiallyExpanded: false, initiallyExpanded: false,
leading: Icon( leading: Icon(
Icons.folder_copy_outlined, Icons.folder_copy_outlined,
size: 18, size: 16,
color: colorScheme.primary, color: colorScheme.primary,
), ),
title: Row( title: Row(
children: [ children: [
Expanded( Expanded(
child: Column( child: Text(
crossAxisAlignment: CrossAxisAlignment.start, label,
children: [ style: Theme.of(context).textTheme.titleSmall?.copyWith(
Text( fontWeight: FontWeight.w800,
label, fontSize: 13,
style: Theme.of(context).textTheme.titleSmall?.copyWith( ),
fontWeight: FontWeight.w800,
),
),
if (kindLabel case final value?)
Text(
value,
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: colorScheme.onSurfaceVariant,
fontWeight: FontWeight.w600,
),
),
],
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 6),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 1),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colorScheme.primaryContainer, color: colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(999), borderRadius: BorderRadius.circular(999),
@@ -1436,13 +1435,19 @@ class _InferredContactGroupCard extends StatelessWidget {
), ),
), ),
if (onDelete != null) ...[ if (onDelete != null) ...[
const SizedBox(width: 4), const SizedBox(width: 2),
IconButton( IconButton(
tooltip: 'Delete group', tooltip: 'Delete group',
onPressed: onDelete, onPressed: onDelete,
visualDensity: VisualDensity.compact,
constraints: const BoxConstraints.tightFor(
width: 32,
height: 32,
),
padding: EdgeInsets.zero,
icon: Icon( icon: Icon(
Icons.delete_outline_rounded, Icons.delete_outline_rounded,
size: 18, size: 16,
color: colorScheme.error, color: colorScheme.error,
), ),
), ),
@@ -1453,7 +1458,6 @@ class _InferredContactGroupCard extends StatelessWidget {
...contacts.map( ...contacts.map(
(contact) => ContactTile( (contact) => ContactTile(
contact: contact, contact: contact,
groupLabel: label,
compact: compactContacts, compact: compactContacts,
currentPosition: currentPosition, currentPosition: currentPosition,
calculateDistance: calculateDistance, calculateDistance: calculateDistance,