From c491c9dc8cfa0f83274a97e61ad3b13c04ac4b31 Mon Sep 17 00:00:00 2001 From: Clark Date: Tue, 6 Jun 2023 11:42:24 -0400 Subject: [PATCH] Fix chosen location not being sent sometimes. --- .../components/location/SignalMapView.java | 76 +++++++++++-------- .../ConversationParentFragment.java | 10 ++- .../securesms/maps/PlacePickerActivity.java | 36 ++++++++- .../securesms/mms/AttachmentManager.java | 14 ++++ .../main/res/layout/activity_place_picker.xml | 8 ++ 5 files changed, 105 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/location/SignalMapView.java b/app/src/main/java/org/thoughtcrime/securesms/components/location/SignalMapView.java index 99bf79bd58..548c46eb87 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/location/SignalMapView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/location/SignalMapView.java @@ -1,9 +1,7 @@ package org.thoughtcrime.securesms.components.location; -import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; -import android.os.Build; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -11,16 +9,20 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; + import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.SettableFuture; +import java.util.concurrent.ExecutionException; + public class SignalMapView extends LinearLayout { private MapView mapView; @@ -53,42 +55,50 @@ public class SignalMapView extends LinearLayout { public ListenableFuture display(final SignalPlace place) { final SettableFuture future = new SettableFuture<>(); - this.mapView.onCreate(null); - this.mapView.onResume(); - - this.mapView.setVisibility(View.VISIBLE); this.imageView.setVisibility(View.GONE); - - this.mapView.getMapAsync(new OnMapReadyCallback() { + this.textView.setText(place.getDescription()); + snapshot(place, mapView).addListener(new ListenableFuture.Listener() { @Override - public void onMapReady(final GoogleMap googleMap) { - googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(place.getLatLong(), 13)); - googleMap.addMarker(new MarkerOptions().position(place.getLatLong())); - googleMap.setBuildingsEnabled(true); - googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); - googleMap.getUiSettings().setAllGesturesEnabled(false); - googleMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { - @Override - public void onMapLoaded() { - googleMap.snapshot(new GoogleMap.SnapshotReadyCallback() { - @Override - public void onSnapshotReady(Bitmap bitmap) { - future.set(bitmap); - imageView.setImageBitmap(bitmap); - imageView.setVisibility(View.VISIBLE); - mapView.setVisibility(View.GONE); - mapView.onPause(); - mapView.onDestroy(); - } - }); - } - }); + public void onSuccess(Bitmap result) { + future.set(result); + imageView.setImageBitmap(result); + imageView.setVisibility(View.VISIBLE); + } + + @Override + public void onFailure(ExecutionException e) { + future.setException(e); } }); - this.textView.setText(place.getDescription()); - return future; } + public static ListenableFuture snapshot(final LatLng place, @NonNull final MapView mapView) { + final SettableFuture future = new SettableFuture<>(); + mapView.onCreate(null); + mapView.onResume(); + + mapView.setVisibility(View.VISIBLE); + + mapView.getMapAsync(googleMap -> { + googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(place, 13)); + googleMap.addMarker(new MarkerOptions().position(place)); + googleMap.setBuildingsEnabled(true); + googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); + googleMap.getUiSettings().setAllGesturesEnabled(false); + googleMap.setOnMapLoadedCallback(() -> googleMap.snapshot(bitmap -> { + future.set(bitmap); + mapView.setVisibility(View.GONE); + mapView.onPause(); + mapView.onDestroy(); + })); + }); + + return future; + } + public static ListenableFuture snapshot(final SignalPlace place, @NonNull final MapView mapView) { + return snapshot(place.getLatLong(), mapView); + } + } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java index a0b1ce5d54..7eb365d314 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java @@ -734,9 +734,13 @@ public class ConversationParentFragment extends Fragment }, nothing -> onRecipientChanged(recipient.get())); break; case PICK_LOCATION: - SignalPlace place = new SignalPlace(PlacePickerActivity.addressFromData(data)); - attachmentManager.setLocation(place, getCurrentMediaConstraints()); - draftViewModel.setLocationDraft(place); + if (data.getData() != null) { + SignalPlace place = new SignalPlace(PlacePickerActivity.addressFromData(data)); + attachmentManager.setLocation(place, data.getData()); + draftViewModel.setLocationDraft(place); + } else { + Log.w(TAG, "Location missing thumbnail"); + } break; case SMS_DEFAULT: viewModel.updateSecurityInfo(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/maps/PlacePickerActivity.java b/app/src/main/java/org/thoughtcrime/securesms/maps/PlacePickerActivity.java index b2e46b4bb8..a0e70671ff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/maps/PlacePickerActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/maps/PlacePickerActivity.java @@ -6,9 +6,11 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Resources; +import android.graphics.Bitmap; import android.graphics.Color; import android.location.Address; import android.location.Geocoder; +import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; @@ -25,18 +27,26 @@ import androidx.fragment.app.Fragment; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MapStyleOptions; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.components.location.SignalMapView; +import org.thoughtcrime.securesms.providers.BlobProvider; +import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicTheme; +import org.thoughtcrime.securesms.util.MediaUtil; +import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; +import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; import java.io.IOException; import java.util.List; import java.util.Locale; +import java.util.concurrent.ExecutionException; /** * Allows selection of an address from a google map. @@ -180,9 +190,29 @@ public final class PlacePickerActivity extends AppCompatActivity { String address = currentAddress != null && currentAddress.getAddressLine(0) != null ? currentAddress.getAddressLine(0) : ""; AddressData addressData = new AddressData(currentLocation.latitude, currentLocation.longitude, address); - returnIntent.putExtra(ADDRESS_INTENT, addressData); - setResult(RESULT_OK, returnIntent); - finish(); + SimpleProgressDialog.DismissibleDialog dismissibleDialog = SimpleProgressDialog.showDelayed(this); + MapView mapView = findViewById(R.id.map_view); + SignalMapView.snapshot(currentLocation, mapView).addListener(new ListenableFuture.Listener<>() { + @Override + public void onSuccess(Bitmap result) { + dismissibleDialog.dismiss(); + byte[] blob = BitmapUtil.toByteArray(result); + Uri uri = BlobProvider.getInstance() + .forData(blob) + .withMimeType(MediaUtil.IMAGE_JPEG) + .createForSingleSessionInMemory(); + returnIntent.putExtra(ADDRESS_INTENT, addressData); + returnIntent.setData(uri); + setResult(RESULT_OK, returnIntent); + finish(); + } + + @Override + public void onFailure(ExecutionException e) { + dismissibleDialog.dismiss(); + Log.e(TAG, "Failed to generate snapshot", e); + } + }); } private void enableMyLocationButtonIfHaveThePermission(GoogleMap googleMap) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java b/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java index 18b0a336ed..da3f71f1f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -238,6 +238,20 @@ public class AttachmentManager { return returnResult; } + public void setLocation(@NonNull final SignalPlace place, + @NonNull final Uri thumbnailUri) + { + inflateStub(); + + mapView.display(place); + + attachmentViewStub.get().setVisibility(View.VISIBLE); + removableMediaView.display(mapView, false); + LocationSlide locationSlide = new LocationSlide(context, thumbnailUri, BlobProvider.getFileSize(thumbnailUri), place); + setSlide(locationSlide); + attachmentListener.onAttachmentChanged(); + } + @SuppressLint("StaticFieldLeak") public ListenableFuture setMedia(@NonNull final GlideRequests glideRequests, @NonNull final Uri uri, diff --git a/app/src/main/res/layout/activity_place_picker.xml b/app/src/main/res/layout/activity_place_picker.xml index e9ce679f59..e1ff0d29ce 100644 --- a/app/src/main/res/layout/activity_place_picker.xml +++ b/app/src/main/res/layout/activity_place_picker.xml @@ -8,6 +8,14 @@ android:layout_height="match_parent" tools:context="org.thoughtcrime.securesms.maps.PlacePickerActivity"> + +