@@ -20,6 +20,7 @@ import 'package:bluebubbles/utils/logger/logger.dart';
2020import 'package:dio/dio.dart' ;
2121import 'package:flutter/cupertino.dart' ;
2222import 'package:flutter/foundation.dart' ;
23+ import 'package:flutter_slidable/flutter_slidable.dart' ;
2324import 'package:geolocator/geolocator.dart' ;
2425import 'package:flutter/material.dart' ;
2526import 'package:flutter/services.dart' ;
@@ -333,7 +334,7 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
333334 if (placemark != null ) {
334335 cachedAddresses[(cached.lastReport! .lat, cached.lastReport! .long)] = Address (
335336 subAdministrativeArea: placemark.subAdministrativeArea,
336- label: placemark.thoroughfare,
337+ label: placemark.thoroughfare ?? placemark.name ,
337338 streetAddress: placemark.thoroughfare,
338339 country: placemark.country,
339340 countryCode: placemark.isoCountryCode,
@@ -390,10 +391,10 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
390391 audioChannels: [],
391392 lostModeCapable: true ,
392393 snd: null ,
393- batteryLevel: e.batteryLevel.toDouble (),
394+ batteryLevel: e.batteryLevel? .toDouble (),
394395 locationEnabled: true ,
395396 isConsideredAccessory: true ,
396- address: cachedAddresses[(e.lastReport! .lat, e.lastReport! .long)],
397+ address: e.lastReport == null ? null : cachedAddresses[(e.lastReport! .lat, e.lastReport! .long)],
397398 location: location,
398399 modelDisplayName: null ,
399400 deviceColor: null ,
@@ -429,6 +430,9 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
429430 crowdSourcedLocation: null ,
430431 role: {
431432 "emoji" : e.naming.emoji,
433+ "sharingId" : e.shared? .shareId,
434+ "sharingActive" : e.shared? .acceptanceState,
435+ "sharingName" : e.shared? .ownerHandle != null ? RustPushBBUtils .rustHandleToBB (e.shared! .ownerHandle).displayName : null ,
432436 },
433437 lostModeMetadata: null
434438 ));
@@ -572,6 +576,23 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
572576 );
573577 }
574578
579+ Future <void > deleteShared (FindMyDevice item) async {
580+ await api.deleteBeaconShare (items: pushService.state! .icloudServices! .fmfd! , share: item.role! ['sharingId' ]! );
581+ setState (() {
582+ devices.remove (item);
583+ });
584+ beaconCacheDate = null ;
585+ }
586+
587+ Future <void > addShared (FindMyDevice item) async {
588+ await api.acceptBeaconShare (items: pushService.state! .icloudServices! .fmfd! , share: item.role! ['sharingId' ]! );
589+ setState (() {
590+ devices.remove (item); // it'll go away anyways because it has no location
591+ });
592+ beaconCacheDate = null ;
593+ getLocations ();
594+ }
595+
575596 @override
576597 void dispose () {
577598 locationSub? .cancel ();
@@ -592,10 +613,10 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
592613 .toList ();
593614 final itemsWithLocation = devices
594615 .where (
595- (item) => item.location? .latitude != null && item.isConsideredAccessory)
616+ (item) => ( item.location? .latitude != null || item.role ? [ "sharingActive" ] == 0 ) && item.isConsideredAccessory)
596617 .toList ();
597618 final withoutLocation =
598- devices.where ((item) => item.location? .latitude == null ).toList ();
619+ devices.where ((item) => item.location? .latitude == null && item.role ? [ "sharingActive" ] != 0 ).toList ();
599620 final devicesBodySlivers = [
600621 SliverList (
601622 delegate: SliverChildListDelegate ([
@@ -748,10 +769,47 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
748769 findChildIndexCallback: (key) => findChildIndexByKey (itemsWithLocation, key, (item) => item.id ?? randomString (6 )),
749770 itemBuilder: (context, i) {
750771 final item = itemsWithLocation[i];
751- return ListTile (
772+ var tile = ListTile (
752773 key: ValueKey (item.id ?? randomString (6 )),
753774 title: Text (ss.settings.redactedMode.value ? "Item" : (item.name ?? "Unknown Item" )),
754- subtitle: Text (ss.settings.redactedMode.value ? "Location" : (item.address? .label ?? item.address? .mapItemFullAddress ?? "No location found" )),
775+ subtitle: item.role? ["sharingActive" ] == 0 ? Column (
776+ children: [
777+ Text ("${item .role ?["sharingName" ]} wants to share this item with you." ),
778+ Row (
779+ mainAxisAlignment: MainAxisAlignment .end,
780+ children: [
781+ ElevatedButton (
782+ style: ElevatedButton .styleFrom (
783+ backgroundColor: context.theme.colorScheme.outline.withAlpha (64 ),
784+ padding: const EdgeInsets .symmetric (vertical: 5 , horizontal: 13 ),
785+ tapTargetSize: MaterialTapTargetSize .shrinkWrap,
786+ elevation: 0.0 ,
787+ minimumSize: Size .zero,
788+ ),
789+ onPressed: () async {
790+ pushService.wrapPromise (deleteShared (item), "Removing..." );
791+ },
792+ child: Text ("Don't Add" , style: context.theme.textTheme.titleMedium),
793+ ),
794+ const SizedBox (width: 10 ),
795+ ElevatedButton (
796+ style: ElevatedButton .styleFrom (
797+ backgroundColor: context.theme.colorScheme.primary,
798+ padding: const EdgeInsets .symmetric (vertical: 5 , horizontal: 13 ),
799+ tapTargetSize: MaterialTapTargetSize .shrinkWrap,
800+ elevation: 0.0 ,
801+ minimumSize: Size .zero,
802+ ),
803+ onPressed: () async {
804+ pushService.wrapPromise (addShared (item), "Adding..." );
805+ },
806+ child: Text ("Add" , style: context.theme.textTheme.titleMedium? .apply (color: context.theme.colorScheme.onPrimary)),
807+ ),
808+ ],
809+ )
810+ ],
811+ )
812+ : Text (ss.settings.redactedMode.value ? "Location" : (item.address? .label ?? item.address? .mapItemFullAddress ?? "No location found" )),
755813 trailing: item.location? .latitude != null && item.location? .longitude != null ? ButtonTheme (
756814 minWidth: 1 ,
757815 child: TextButton (
@@ -820,6 +878,10 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
820878 );
821879 },
822880 );
881+ if (item.role? ['sharingId' ] != null ) {
882+ return wrapDelete (tile, (context) => deleteShared (item));
883+ }
884+ return tile;
823885 },
824886 itemCount: itemsWithLocation.length,
825887 ),
@@ -838,7 +900,8 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
838900 shape: const RoundedRectangleBorder (side: BorderSide (color: Colors .transparent)),
839901 title: const Text ("Devices without locations" ),
840902 children: withoutLocation
841- .map ((item) => ListTile (
903+ .map ((item) {
904+ var tile = ListTile (
842905 title: Text (ss.settings.redactedMode.value ? "Device" : (item.name ?? "Unknown Device" )),
843906 subtitle: Text (ss.settings.redactedMode.value ? "Location" : (item.address? .label ?? item.address? .mapItemFullAddress ?? "No location found" )),
844907 onTap: item.location? .latitude != null && item.location? .longitude != null
@@ -893,7 +956,12 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
893956 ),
894957 );
895958 },
896- ))
959+ );
960+ if (item.role? ['sharingId' ] != null ) {
961+ return wrapDelete (tile, (context) => deleteShared (item));
962+ }
963+ return tile;
964+ })
897965 .toList ()),
898966 ),
899967 ],
@@ -1302,6 +1370,44 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
13021370 );
13031371 }
13041372
1373+ Widget wrapDelete (Widget child, Function (BuildContext ) onPressed) {
1374+ return Slidable (
1375+ endActionPane: ActionPane (
1376+ motion: const StretchMotion (),
1377+ extentRatio: 0.30 ,
1378+ children: [
1379+ SlidableAction (
1380+ label: 'Remove' ,
1381+ backgroundColor: Colors .red,
1382+ icon: ss.settings.skin.value == Skins .iOS ? CupertinoIcons .trash : Icons .delete_outlined,
1383+ onPressed: (_) async {
1384+ showDialog (
1385+ context: context,
1386+ barrierDismissible: false ,
1387+ builder: (BuildContext context) {
1388+ return AlertDialog (
1389+ backgroundColor: context.theme.colorScheme.properSurface,
1390+ title: Text (
1391+ "Deleting..." ,
1392+ style: context.theme.textTheme.titleLarge,
1393+ ),
1394+ content: Container (
1395+ height: 70 ,
1396+ child: Center (child: buildProgressIndicator (context)),
1397+ ),
1398+ );
1399+ }
1400+ );
1401+ await onPressed (context);
1402+ Get .back ();
1403+ },
1404+ ),
1405+ ],
1406+ ),
1407+ child: child,
1408+ );
1409+ }
1410+
13051411 Widget buildNormal (BuildContext context, List <SliverList > devicesBodySlivers, List <SliverList > friendsBodySlivers) {
13061412 return Obx (
13071413 () => Scaffold (
@@ -1684,16 +1790,38 @@ class _FindMyPageState extends OptimizedState<FindMyPage> with SingleTickerProvi
16841790 borderRadius: BorderRadius .circular (10 ),
16851791 color: context.theme.colorScheme.properSurface.withOpacity (0.8 ),
16861792 ),
1687- padding: const EdgeInsets .all ( 10 ),
1688- child: Column (
1793+ padding: const EdgeInsets .fromLTRB ( 10 , 10 , 0 , 10 ),
1794+ child: Row (
16891795 mainAxisSize: MainAxisSize .min,
1690- crossAxisAlignment: CrossAxisAlignment .start,
16911796 children: [
1692- Text (ss.settings.redactedMode.value ? "Device" : (item.name ?? "Unknown Device" ), style: context.theme.textTheme.labelLarge),
1693- Text (ss.settings.redactedMode.value ? "Location" : (item.location? .latitude != null ? "${item .location ?.latitude }, ${item .location ?.longitude }" : "" ),
1694- style: context.theme.textTheme.bodySmall),
1797+ Column (
1798+ mainAxisSize: MainAxisSize .min,
1799+ crossAxisAlignment: CrossAxisAlignment .start,
1800+ children: [
1801+ Text (ss.settings.redactedMode.value ? "Device" : (item.name ?? "Unknown Device" ), style: context.theme.textTheme.labelLarge),
1802+ Text (ss.settings.redactedMode.value ? "Location" : (item.location? .latitude != null ? "${item .location ?.latitude }, ${item .location ?.longitude }" : "" ),
1803+ style: context.theme.textTheme.bodySmall),
1804+ ],
1805+ ),
1806+ if (item.location? .latitude != null && item.location? .longitude != null )
1807+ ButtonTheme (
1808+ minWidth: 1 ,
1809+ child: TextButton (
1810+ style: TextButton .styleFrom (
1811+ shape: const CircleBorder (),
1812+ backgroundColor: context.theme.colorScheme.primaryContainer,
1813+ ),
1814+ onPressed: () async {
1815+ await MapsLauncher .launchCoordinates (item.location! .latitude! , item.location! .longitude! );
1816+ },
1817+ child: const Icon (
1818+ Icons .directions,
1819+ size: 20
1820+ ),
1821+ ),
1822+ )
16951823 ],
1696- ),
1824+ )
16971825 ),
16981826 );
16991827 } else {
0 commit comments