Add contact import functionality and update UI feedback for import status

This commit is contained in:
Winston Lowe 2026-01-27 18:43:59 -08:00
parent eeb8ff34e8
commit d0c8fab6fb
3 changed files with 59 additions and 9 deletions

View file

@ -1680,6 +1680,12 @@ class MeshCoreConnector extends ChangeNotifier {
_isLoadingContacts = true;
notifyListeners();
break;
case pushCodeNewAdvert:
debugPrint('Got NEW_ADVERT');
_handleContact(frame);
notifyListeners();
unawaited(_persistContacts());
break;
case respCodeContact:
debugPrint('Got CONTACT');
_handleContact(frame);
@ -1737,6 +1743,7 @@ class MeshCoreConnector extends ChangeNotifier {
break;
case respCodeCustomVars:
_handleCustomVars(frame);
break;
default:
debugPrint('Unknown frame code: $code');
}

View file

@ -1309,8 +1309,23 @@
"listFilter_roomServers": "Room servers",
"listFilter_unreadOnly": "Unread only",
"listFilter_newGroup": "New group",
"contacts_pathTrace": "Path Trace",
"contacts_ping": "Ping",
"contacts_repeaterPathTrace": "Path trace to repeater",
"contacts_repeaterPing": "Ping repeater",
"contacts_roomPathTrace": "Path trace to room server",
"contacts_roomPing": "Ping room server",
"contacts_chatTraceRoute": "Path trace route",
"contacts_pathTraceTo": "Trace route to {name}",
"@contacts_pathTraceTo": {
"placeholders": {
"name": {"type": "String"}
}
},
"contacts_clipboardEmpty": "Clipboard Is Empty.",
"contacts_invalidAdvertFormat": "Invalid Contact Data",
"contacts_contactAdded": "Contact has been added."
"contacts_contactImported": "Contact has been Imported.",
"contacts_contactImportFailed": "Contact Failed to Imported."
}

View file

@ -54,6 +54,7 @@ class _ContactsScreenState extends State<ContactsScreen>
List<ContactGroup> _groups = [];
Timer? _searchDebounce;
bool _imported = false;
StreamSubscription<Uint8List>? _frameSubscription;
@override
@ -96,6 +97,23 @@ class _ContactsScreenState extends State<ContactsScreen>
final hexString = pubKeyToHex(advertPacket);
Clipboard.setData(ClipboardData(text: "meshcore://$hexString"));
}
if(code == respCodeOk && _imported) {
// Show a snackbar indicating success
_imported = false;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.l10n.contacts_contactImported)),
);
}
if(code == respCodeErr && _imported) {
// Show a snackbar indicating success
_imported = false;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.l10n.contacts_contactImportFailed)),
);
}
});
}
@ -126,9 +144,7 @@ class _ContactsScreenState extends State<ContactsScreen>
final connector = Provider.of<MeshCoreConnector>(context, listen: false);
final importContactFrame = buildImportContactFrame(hexString);
await connector.sendFrame(importContactFrame);
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(content: Text(context.l10n.contacts_contactAdded)),
// );
_imported = true;
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.l10n.contacts_invalidAdvertFormat)),
@ -923,6 +939,7 @@ class _ContactsScreenState extends State<ContactsScreen>
_openChat(context, contact);
},
),
],
ListTile(
leading: const Icon(Icons.delete, color: Colors.red),
title: Text(
@ -997,7 +1014,7 @@ class _ContactTile extends StatelessWidget {
),
title: Text(contact.name),
subtitle: Text(
'${contact.typeLabel}${contact.pathLabel} $shotPublicKey',
'${contact.typeLabel}\n${contact.shortPubKeyHex}',
),
// Clamp text scaling in trailing section to prevent overflow while
// maintaining accessibility. Primary content (title/subtitle) scales normally.
@ -1019,13 +1036,24 @@ class _ContactTile extends StatelessWidget {
_formatLastSeen(context, lastSeen),
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
),
if (contact.hasLocation)
Icon(Icons.location_on, size: 14, color: Colors.grey[400]),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(contact.pathLabel,
style: TextStyle(fontSize: 12, color: Colors.grey[600])),
if (contact.hasLocation)
Icon(Icons.location_on, size: 14, color: Colors.grey[400]),
],
),
Text(
_formatLastSeen(context, lastSeen),
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
),
if (contact.hasLocation)
Icon(Icons.location_on, size: 14, color: Colors.grey[400]),
],
),
),
onTap: onTap,
onLongPress: onLongPress,
);
}