diff --git a/android/app/src/main/java/deckers/thibault/aves/channelhandlers/AppAdapterHandler.java b/android/app/src/main/java/deckers/thibault/aves/channelhandlers/AppAdapterHandler.java index 0ce02be0a..5305bad5e 100644 --- a/android/app/src/main/java/deckers/thibault/aves/channelhandlers/AppAdapterHandler.java +++ b/android/app/src/main/java/deckers/thibault/aves/channelhandlers/AppAdapterHandler.java @@ -21,12 +21,35 @@ public class AppAdapterHandler implements MethodChannel.MethodCallHandler { @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { switch (call.method) { + case "edit": { + String title = call.argument("title"); + Uri uri = Uri.parse(call.argument("uri")); + String mimeType = call.argument("mimeType"); + edit(title, uri, mimeType); + result.success(null); + break; + } + case "setAs": { + String title = call.argument("title"); + Uri uri = Uri.parse(call.argument("uri")); + String mimeType = call.argument("mimeType"); + setAs(title, uri, mimeType); + result.success(null); + break; + } case "share": { String title = call.argument("title"); Uri uri = Uri.parse(call.argument("uri")); String mimeType = call.argument("mimeType"); - share(context, title, uri, mimeType); + share(title, uri, mimeType); result.success(null); + break; + } + case "showOnMap": { + Uri geoUri = Uri.parse(call.argument("geoUri")); + showOnMap(geoUri); + result.success(null); + break; } default: result.notImplemented(); @@ -34,10 +57,29 @@ public class AppAdapterHandler implements MethodChannel.MethodCallHandler { } } - private void share(Context context, String title, Uri uri, String mimeType) { + private void edit(String title, Uri uri, String mimeType) { + Intent intent = new Intent(Intent.ACTION_EDIT); + intent.setDataAndType(uri, mimeType); + context.startActivity(Intent.createChooser(intent, title)); + } + + private void setAs(String title, Uri uri, String mimeType) { + Intent intent = new Intent(Intent.ACTION_ATTACH_DATA); + intent.setDataAndType(uri, mimeType); + context.startActivity(Intent.createChooser(intent, title)); + } + + private void share(String title, Uri uri, String mimeType) { Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, uri); intent.setType(mimeType); context.startActivity(Intent.createChooser(intent, title)); } + + private void showOnMap(Uri geoUri) { + Intent intent = new Intent(Intent.ACTION_VIEW, geoUri); + if (intent.resolveActivity(context.getPackageManager()) != null) { + context.startActivity(intent); + } + } } diff --git a/lib/main.dart b/lib/main.dart index 23555ceda..4e5835e0c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -75,7 +75,7 @@ class _HomePageState extends State { debugPrint('$runtimeType catalogEntries cataloging complete'); // sort with more accurate date - entries.sort((a,b) => b.bestDate.compareTo(a.bestDate)); + entries.sort((a, b) => b.bestDate.compareTo(a.bestDate)); setState(() {}); debugPrint('$runtimeType catalogEntries locating start'); diff --git a/lib/model/image_entry.dart b/lib/model/image_entry.dart index bd0df7936..d08872633 100644 --- a/lib/model/image_entry.dart +++ b/lib/model/image_entry.dart @@ -129,6 +129,8 @@ class ImageEntry with ChangeNotifier { Tuple2 get latLng => isCataloged ? Tuple2(catalogMetadata.latitude, catalogMetadata.longitude) : null; + String get geoUri => hasGps ? 'geo:${catalogMetadata.latitude},${catalogMetadata.longitude}' : null; + List get xmpSubjects => catalogMetadata?.xmpSubjects?.split(';')?.where((tag) => tag.isNotEmpty)?.toList() ?? []; catalog() async { diff --git a/lib/utils/android_app_service.dart b/lib/utils/android_app_service.dart index 1f799001a..8144fc420 100644 --- a/lib/utils/android_app_service.dart +++ b/lib/utils/android_app_service.dart @@ -4,6 +4,30 @@ import 'package:flutter/services.dart'; class AndroidAppService { static const platform = const MethodChannel('deckers.thibault/aves/app'); + static edit(String uri, String mimeType) async { + try { + await platform.invokeMethod('edit', { + 'title': 'Edit', + 'uri': uri, + 'mimeType': mimeType, + }); + } on PlatformException catch (e) { + debugPrint('edit failed with exception=${e.message}'); + } + } + + static setAs(String uri, String mimeType) async { + try { + await platform.invokeMethod('setAs', { + 'title': 'Set as', + 'uri': uri, + 'mimeType': mimeType, + }); + } on PlatformException catch (e) { + debugPrint('setAs failed with exception=${e.message}'); + } + } + static share(String uri, String mimeType) async { try { await platform.invokeMethod('share', { @@ -15,4 +39,15 @@ class AndroidAppService { debugPrint('share failed with exception=${e.message}'); } } + + static showOnMap(String geoUri) async { + if (geoUri == null) return; + try { + await platform.invokeMethod('showOnMap', { + 'geoUri': geoUri, + }); + } on PlatformException catch (e) { + debugPrint('share failed with exception=${e.message}'); + } + } } diff --git a/lib/widgets/fullscreen/image_page.dart b/lib/widgets/fullscreen/image_page.dart index 37081081d..73399f067 100644 --- a/lib/widgets/fullscreen/image_page.dart +++ b/lib/widgets/fullscreen/image_page.dart @@ -195,17 +195,26 @@ class FullscreenPageState extends State with SingleTickerProvide onActionSelected(ImageEntry entry, FullscreenAction action) { switch (action) { + case FullscreenAction.edit: + AndroidAppService.edit(entry.uri, entry.mimeType); + break; case FullscreenAction.info: goToVerticalPage(1); break; + case FullscreenAction.setAs: + AndroidAppService.setAs(entry.uri, entry.mimeType); + break; case FullscreenAction.share: AndroidAppService.share(entry.uri, entry.mimeType); break; + case FullscreenAction.showOnMap: + AndroidAppService.showOnMap(entry.geoUri); + break; } } } -enum FullscreenAction { info, share } +enum FullscreenAction { edit, info, setAs, share, showOnMap } class ImagePage extends StatefulWidget { final List entries; diff --git a/lib/widgets/fullscreen/overlay_top.dart b/lib/widgets/fullscreen/overlay_top.dart index a16e16ac4..18b4fbedc 100644 --- a/lib/widgets/fullscreen/overlay_top.dart +++ b/lib/widgets/fullscreen/overlay_top.dart @@ -52,6 +52,19 @@ class FullscreenTopOverlay extends StatelessWidget { value: FullscreenAction.info, child: Text("Info"), ), + PopupMenuItem( + value: FullscreenAction.edit, + child: Text("Edit"), + ), + PopupMenuItem( + value: FullscreenAction.setAs, + child: Text("Set as"), + ), + if (entry.hasGps) + PopupMenuItem( + value: FullscreenAction.showOnMap, + child: Text("Show on map"), + ), ], onSelected: onActionSelected, ),