mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-29 21:50:32 +10:00
Refactor contact handling and enhance UI with new advert options and localized strings
This commit is contained in:
@@ -1680,12 +1680,6 @@ 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);
|
||||
@@ -1743,7 +1737,6 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
break;
|
||||
case respCodeCustomVars:
|
||||
_handleCustomVars(frame);
|
||||
break;
|
||||
default:
|
||||
debugPrint('Unknown frame code: $code');
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ class BufferReader {
|
||||
return data;
|
||||
}
|
||||
|
||||
void skipBytes(int count) {
|
||||
_pointer += count;
|
||||
}
|
||||
|
||||
Uint8List readRemainingBytes() => readBytes(remaining);
|
||||
|
||||
String readString() =>
|
||||
@@ -135,6 +139,7 @@ const int cmdSendStatusReq = 27;
|
||||
const int cmdGetContactByKey = 30;
|
||||
const int cmdGetChannel = 31;
|
||||
const int cmdSetChannel = 32;
|
||||
const int cmdSendTracePath = 36;
|
||||
const int cmdGetRadioSettings = 57;
|
||||
const int cmdGetTelemetryReq = 39;
|
||||
const int cmdGetCustomVar = 40;
|
||||
@@ -185,6 +190,7 @@ const int pushCodeLoginSuccess = 0x85;
|
||||
const int pushCodeLoginFail = 0x86;
|
||||
const int pushCodeStatusResponse = 0x87;
|
||||
const int pushCodeLogRxData = 0x88;
|
||||
const int pushCodeTraceData = 0x89;
|
||||
const int pushCodeNewAdvert = 0x8A;
|
||||
const int pushCodeTelemetryResponse = 0x8B;
|
||||
const int pushCodeBinaryResponse = 0x8C;
|
||||
@@ -718,6 +724,21 @@ Uint8List buildSendBinaryReq(Uint8List repeaterPubKey, {Uint8List? payload}) {
|
||||
return writer.toBytes();
|
||||
}
|
||||
|
||||
//Build a trace request frame
|
||||
//[cmd][tag x4][auth x4][flag][payload]
|
||||
Uint8List buildTraceReq(int tag, int auth, int flag, {Uint8List? payload})
|
||||
{
|
||||
final writer = BufferWriter();
|
||||
writer.writeByte(cmdSendTracePath);
|
||||
writer.writeUInt32LE(tag);
|
||||
writer.writeUInt32LE(auth);
|
||||
writer.writeByte(flag);
|
||||
if (payload != null && payload.isNotEmpty) {
|
||||
writer.writeBytes(payload);
|
||||
}
|
||||
return writer.toBytes();
|
||||
}
|
||||
|
||||
// Build a export contact frame
|
||||
// [cmd][pub_key x32 / if empty exports your contact info]
|
||||
Uint8List buildExportContactFrame(Uint8List pubKey) {
|
||||
|
||||
+5
-1
@@ -1327,5 +1327,9 @@
|
||||
"contacts_clipboardEmpty": "Clipboard Is Empty.",
|
||||
"contacts_invalidAdvertFormat": "Invalid Contact Data",
|
||||
"contacts_contactImported": "Contact has been Imported.",
|
||||
"contacts_contactImportFailed": "Contact Failed to Imported."
|
||||
"contacts_contactImportFailed": "Contact Failed to Imported.",
|
||||
"contacts_zeroHopAdvert":"Zero Hop Advert",
|
||||
"contacts_floodAdvert":"Flood Advert",
|
||||
"contacts_copyAdvertToClipboard":"Copy Advert to Clipboard",
|
||||
"contacts_addContactFromClipboard":"Add Contact from Clipboard"
|
||||
}
|
||||
|
||||
@@ -102,6 +102,10 @@ class Contact {
|
||||
return parts.join(',');
|
||||
}
|
||||
|
||||
String get shortPubKeyHex {
|
||||
return "<${publicKeyHex.substring(0, 8)}...${publicKeyHex.substring(publicKeyHex.length - 8)}>";
|
||||
}
|
||||
|
||||
Uint8List get _pathBytesForDisplay {
|
||||
if (pathOverride != null) {
|
||||
if (pathOverride! < 0) return Uint8List(0);
|
||||
|
||||
@@ -177,7 +177,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
children: [
|
||||
const Icon(Icons.connect_without_contact),
|
||||
const SizedBox(width: 8),
|
||||
Text("Zero Hop Advert"),
|
||||
Text(context.l10n.contacts_zeroHopAdvert),
|
||||
],
|
||||
),
|
||||
onTap: () => {
|
||||
@@ -192,7 +192,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
children: [
|
||||
const Icon(Icons.cell_tower),
|
||||
const SizedBox(width: 8),
|
||||
Text("Flood Advert"),
|
||||
Text(context.l10n.contacts_floodAdvert),
|
||||
],
|
||||
),
|
||||
onTap: () => {
|
||||
@@ -207,7 +207,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
children: [
|
||||
const Icon(Icons.copy),
|
||||
const SizedBox(width: 8),
|
||||
Text("Copy Advert to Clipboard"),
|
||||
Text(context.l10n.contacts_copyAdvertToClipboard),
|
||||
],
|
||||
),
|
||||
onTap: () => _contactExport(Uint8List.fromList([])),
|
||||
@@ -217,7 +217,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
children: [
|
||||
const Icon(Icons.paste),
|
||||
const SizedBox(width: 8),
|
||||
Text("Add Contact from Clipboard"),
|
||||
Text(context.l10n.contacts_addContactFromClipboard),
|
||||
],
|
||||
),
|
||||
onTap: () => _contactImport(),
|
||||
@@ -227,12 +227,22 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
),
|
||||
PopupMenuButton(
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.logout, color: Colors.red),
|
||||
const SizedBox(width: 8),
|
||||
Text(context.l10n.common_disconnect),
|
||||
],
|
||||
),
|
||||
onTap: () => _disconnect(context, connector),
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.settings),
|
||||
const SizedBox(width: 8),
|
||||
const Text('Settings'),
|
||||
Text(context.l10n.settings_title),
|
||||
],
|
||||
),
|
||||
onTap: () => Navigator.push(
|
||||
@@ -240,16 +250,6 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
MaterialPageRoute(builder: (context) => const SettingsScreen()),
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.logout, color: Colors.red),
|
||||
const SizedBox(width: 8),
|
||||
const Text('Disconnect'),
|
||||
],
|
||||
),
|
||||
onTap: () => _disconnect(context, connector),
|
||||
)
|
||||
],
|
||||
icon: const Icon(Icons.more_vert),
|
||||
),
|
||||
@@ -930,7 +930,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
||||
_showRoomLogin(context, contact, RoomLoginDestination.management);
|
||||
},
|
||||
),
|
||||
] else
|
||||
] else ...[
|
||||
ListTile(
|
||||
leading: const Icon(Icons.chat),
|
||||
title: Text(context.l10n.contacts_openChat),
|
||||
@@ -1005,17 +1005,16 @@ class _ContactTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final shotPublicKey =
|
||||
"<${contact.publicKeyHex.substring(0, 8)}...${contact.publicKeyHex.substring(contact.publicKeyHex.length - 8)}>";
|
||||
return ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: _getTypeColor(contact.type),
|
||||
child: _buildContactAvatar(contact),
|
||||
),
|
||||
title: Text(contact.name),
|
||||
subtitle: Text(
|
||||
'${contact.typeLabel}\n${contact.shortPubKeyHex}',
|
||||
),
|
||||
subtitle: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text(contact.pathLabel),
|
||||
Text(contact.shortPubKeyHex, style: TextStyle(fontSize: 12))
|
||||
],),
|
||||
// Clamp text scaling in trailing section to prevent overflow while
|
||||
// maintaining accessibility. Primary content (title/subtitle) scales normally.
|
||||
trailing: MediaQuery(
|
||||
@@ -1039,21 +1038,15 @@ class _ContactTile extends StatelessWidget {
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user