|
|
|
|
@ -13,6 +13,7 @@ import '../connector/meshcore_protocol.dart';
|
|
|
|
|
import '../models/contact.dart';
|
|
|
|
|
import '../models/contact_group.dart';
|
|
|
|
|
import '../storage/contact_group_store.dart';
|
|
|
|
|
import '../storage/contact_settings_store.dart';
|
|
|
|
|
import '../utils/contact_search.dart';
|
|
|
|
|
import '../utils/dialog_utils.dart';
|
|
|
|
|
import '../utils/disconnect_navigation_mixin.dart';
|
|
|
|
|
@ -481,6 +482,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|
|
|
|
contact: contact,
|
|
|
|
|
lastSeen: _resolveLastSeen(contact),
|
|
|
|
|
unreadCount: unreadCount,
|
|
|
|
|
isFavorite: contact.isFavorite,
|
|
|
|
|
onTap: () => _openChat(context, contact),
|
|
|
|
|
onLongPress: () =>
|
|
|
|
|
_showContactOptions(context, connector, contact),
|
|
|
|
|
@ -517,6 +519,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|
|
|
|
})
|
|
|
|
|
.where((group) {
|
|
|
|
|
if (_typeFilter == ContactTypeFilter.all) return true;
|
|
|
|
|
if (_typeFilter == ContactTypeFilter.favorites) return false;
|
|
|
|
|
for (final key in group.memberKeys) {
|
|
|
|
|
final contact = contactsByKey[key];
|
|
|
|
|
if (contact != null && _matchesTypeFilter(contact)) return true;
|
|
|
|
|
@ -591,6 +594,8 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|
|
|
|
switch (_typeFilter) {
|
|
|
|
|
case ContactTypeFilter.all:
|
|
|
|
|
return true;
|
|
|
|
|
case ContactTypeFilter.favorites:
|
|
|
|
|
return contact.isFavorite;
|
|
|
|
|
case ContactTypeFilter.users:
|
|
|
|
|
return contact.type == advTypeChat;
|
|
|
|
|
case ContactTypeFilter.repeaters:
|
|
|
|
|
@ -981,6 +986,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|
|
|
|
) {
|
|
|
|
|
final isRepeater = contact.type == advTypeRepeater;
|
|
|
|
|
final isRoom = contact.type == advTypeRoom;
|
|
|
|
|
final isFavorite = contact.isFavorite;
|
|
|
|
|
|
|
|
|
|
showModalBottomSheet(
|
|
|
|
|
context: context,
|
|
|
|
|
@ -1087,6 +1093,21 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
ListTile(
|
|
|
|
|
leading: Icon(
|
|
|
|
|
isFavorite ? Icons.star : Icons.star_border,
|
|
|
|
|
color: Colors.amber[700],
|
|
|
|
|
),
|
|
|
|
|
title: Text(
|
|
|
|
|
isFavorite
|
|
|
|
|
? '${context.l10n.common_remove} ${context.l10n.listFilter_favorites}'
|
|
|
|
|
: '${context.l10n.common_add} ${context.l10n.listFilter_favorites}',
|
|
|
|
|
),
|
|
|
|
|
onTap: () async {
|
|
|
|
|
Navigator.pop(sheetContext);
|
|
|
|
|
await connector.setContactFavorite(contact, !isFavorite);
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
ListTile(
|
|
|
|
|
leading: const Icon(Icons.copy),
|
|
|
|
|
title: Text(context.l10n.contacts_ShareContact),
|
|
|
|
|
@ -1155,6 +1176,7 @@ class _ContactTile extends StatelessWidget {
|
|
|
|
|
final Contact contact;
|
|
|
|
|
final DateTime lastSeen;
|
|
|
|
|
final int unreadCount;
|
|
|
|
|
final bool isFavorite;
|
|
|
|
|
final VoidCallback onTap;
|
|
|
|
|
final VoidCallback onLongPress;
|
|
|
|
|
|
|
|
|
|
@ -1162,6 +1184,7 @@ class _ContactTile extends StatelessWidget {
|
|
|
|
|
required this.contact,
|
|
|
|
|
required this.lastSeen,
|
|
|
|
|
required this.unreadCount,
|
|
|
|
|
required this.isFavorite,
|
|
|
|
|
required this.onTap,
|
|
|
|
|
required this.onLongPress,
|
|
|
|
|
});
|
|
|
|
|
@ -1214,6 +1237,9 @@ class _ContactTile extends StatelessWidget {
|
|
|
|
|
Row(
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
children: [
|
|
|
|
|
if (isFavorite)
|
|
|
|
|
Icon(Icons.star, size: 14, color: Colors.amber[700]),
|
|
|
|
|
if (isFavorite && contact.hasLocation) const SizedBox(width: 2),
|
|
|
|
|
if (contact.hasLocation)
|
|
|
|
|
Icon(Icons.location_on, size: 14, color: Colors.grey[400]),
|
|
|
|
|
],
|
|
|
|
|
|