ViewStub for entire AttachmentManager

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2017-01-18 12:27:48 -08:00
parent 4906bdbdcc
commit 3d6cbdd775
4 changed files with 130 additions and 75 deletions

View File

@ -33,49 +33,12 @@
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" /> android:layout_weight="1" />
<FrameLayout android:id="@+id/attachment_editor" <ViewStub
android:layout_width="match_parent" android:id="@+id/attachment_editor_stub"
android:layout_height="wrap_content" android:inflatedId="@+id/attachment_editor"
android:gravity="center_horizontal" android:layout="@layout/conversation_activity_attachment_editor_stub"
android:background="?android:windowBackground" android:layout_width="match_parent"
android:visibility="gone"> android:layout_height="wrap_content"/>
<org.thoughtcrime.securesms.components.RemovableEditableMediaView
android:id="@+id/removable_media_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<org.thoughtcrime.securesms.components.location.SignalMapView
android:id="@+id/attachment_location"
android:layout_width="210dp"
android:layout_height="210dp"
android:layout_gravity="center_horizontal"
android:visibility="gone"/>
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/attachment_thumbnail"
android:layout_width="230dp"
android:layout_height="150dp"
android:layout_gravity="center_horizontal"
android:visibility="gone"
android:contentDescription="@string/conversation_activity__attachment_thumbnail"
app:backgroundColorHint="?conversation_background" />
<org.thoughtcrime.securesms.components.AudioView
android:id="@+id/attachment_audio"
android:layout_width="210dp"
android:layout_height="wrap_content"
android:visibility="gone"
android:paddingTop="15dp"
android:paddingBottom="15dp"
app:widgetBackground="@color/white"
app:foregroundTintColor="@color/grey_500"
app:backgroundTintColor="@color/white"/>
</org.thoughtcrime.securesms.components.RemovableEditableMediaView>
</FrameLayout>
<include layout="@layout/conversation_input_panel"/> <include layout="@layout/conversation_input_panel"/>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/attachment_editor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:background="?android:windowBackground"
android:visibility="gone">
<org.thoughtcrime.securesms.components.RemovableEditableMediaView
android:id="@+id/removable_media_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<org.thoughtcrime.securesms.components.location.SignalMapView
android:id="@+id/attachment_location"
android:layout_width="210dp"
android:layout_height="210dp"
android:layout_gravity="center_horizontal"
android:visibility="gone"/>
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/attachment_thumbnail"
android:layout_width="230dp"
android:layout_height="150dp"
android:layout_gravity="center_horizontal"
android:visibility="gone"
android:contentDescription="@string/conversation_activity__attachment_thumbnail"
app:backgroundColorHint="?conversation_background" />
<org.thoughtcrime.securesms.components.AudioView
android:id="@+id/attachment_audio"
android:layout_width="210dp"
android:layout_height="wrap_content"
android:visibility="gone"
android:paddingTop="15dp"
android:paddingBottom="15dp"
app:widgetBackground="@color/white"
app:foregroundTintColor="@color/grey_500"
app:backgroundTintColor="@color/white"/>
</org.thoughtcrime.securesms.components.RemovableEditableMediaView>
</FrameLayout>

View File

@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener; import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture.Listener; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture.Listener;
import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException; import java.io.IOException;
@ -69,47 +70,60 @@ public class AttachmentManager {
private final static String TAG = AttachmentManager.class.getSimpleName(); private final static String TAG = AttachmentManager.class.getSimpleName();
private final @NonNull Context context; private final @NonNull Context context;
private final @NonNull View attachmentView; private final @NonNull Stub<View> attachmentViewStub;
private final @NonNull RemovableEditableMediaView removableMediaView;
private final @NonNull ThumbnailView thumbnail;
private final @NonNull AudioView audioView;
private final @NonNull SignalMapView mapView;
private final @NonNull AttachmentListener attachmentListener; private final @NonNull AttachmentListener attachmentListener;
private RemovableEditableMediaView removableMediaView;
private ThumbnailView thumbnail;
private AudioView audioView;
private SignalMapView mapView;
private @NonNull List<Uri> garbage = new LinkedList<>(); private @NonNull List<Uri> garbage = new LinkedList<>();
private @NonNull Optional<Slide> slide = Optional.absent(); private @NonNull Optional<Slide> slide = Optional.absent();
private @Nullable Uri captureUri; private @Nullable Uri captureUri;
public AttachmentManager(@NonNull Activity activity, @NonNull AttachmentListener listener) { public AttachmentManager(@NonNull Activity activity, @NonNull AttachmentListener listener) {
this.attachmentView = ViewUtil.findById(activity, R.id.attachment_editor);
this.thumbnail = ViewUtil.findById(activity, R.id.attachment_thumbnail);
this.audioView = ViewUtil.findById(activity, R.id.attachment_audio);
this.mapView = ViewUtil.findById(activity, R.id.attachment_location);
this.removableMediaView = ViewUtil.findById(activity, R.id.removable_media_view);
this.context = activity; this.context = activity;
this.attachmentListener = listener; this.attachmentListener = listener;
this.attachmentViewStub = ViewUtil.findStubById(activity, R.id.attachment_editor_stub);
}
private void inflateStub() {
if (!attachmentViewStub.resolved()) {
View root = attachmentViewStub.get();
this.thumbnail = ViewUtil.findById(root, R.id.attachment_thumbnail);
this.audioView = ViewUtil.findById(root, R.id.attachment_audio);
this.mapView = ViewUtil.findById(root, R.id.attachment_location);
this.removableMediaView = ViewUtil.findById(root, R.id.removable_media_view);
removableMediaView.setRemoveClickListener(new RemoveButtonListener());
removableMediaView.setEditClickListener(new EditButtonListener());
thumbnail.setOnClickListener(new ThumbnailClickListener());
}
removableMediaView.setRemoveClickListener(new RemoveButtonListener());
removableMediaView.setEditClickListener(new EditButtonListener());
thumbnail.setOnClickListener(new ThumbnailClickListener());
} }
public void clear() { public void clear() {
ViewUtil.fadeOut(attachmentView, 200).addListener(new Listener<Boolean>() { if (attachmentViewStub.resolved()) {
@Override ViewUtil.fadeOut(attachmentViewStub.get(), 200).addListener(new Listener<Boolean>() {
public void onSuccess(Boolean result) { @Override
thumbnail.clear(); public void onSuccess(Boolean result) {
attachmentView.setVisibility(View.GONE); thumbnail.clear();
attachmentListener.onAttachmentChanged(); attachmentViewStub.get().setVisibility(View.GONE);
} attachmentListener.onAttachmentChanged();
}
@Override @Override
public void onFailure(ExecutionException e) {} public void onFailure(ExecutionException e) {
}); }
});
markGarbage(getSlideUri()); markGarbage(getSlideUri());
slide = Optional.absent(); slide = Optional.absent();
audioView.cleanup();
audioView.cleanup();
}
} }
public void cleanup() { public void cleanup() {
@ -153,9 +167,11 @@ public class AttachmentManager {
@NonNull final SignalPlace place, @NonNull final SignalPlace place,
@NonNull final MediaConstraints constraints) @NonNull final MediaConstraints constraints)
{ {
inflateStub();
ListenableFuture<Bitmap> future = mapView.display(place); ListenableFuture<Bitmap> future = mapView.display(place);
attachmentView.setVisibility(View.VISIBLE); attachmentViewStub.get().setVisibility(View.VISIBLE);
removableMediaView.display(mapView, false); removableMediaView.display(mapView, false);
future.addListener(new AssertedSuccessListener<Bitmap>() { future.addListener(new AssertedSuccessListener<Bitmap>() {
@ -177,12 +193,14 @@ public class AttachmentManager {
@NonNull final MediaType mediaType, @NonNull final MediaType mediaType,
@NonNull final MediaConstraints constraints) @NonNull final MediaConstraints constraints)
{ {
inflateStub();
new AsyncTask<Void, Void, Slide>() { new AsyncTask<Void, Void, Slide>() {
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
thumbnail.clear(); thumbnail.clear();
thumbnail.showProgressSpinner(); thumbnail.showProgressSpinner();
attachmentView.setVisibility(View.VISIBLE); attachmentViewStub.get().setVisibility(View.VISIBLE);
} }
@Override @Override
@ -202,18 +220,18 @@ public class AttachmentManager {
@Override @Override
protected void onPostExecute(@Nullable final Slide slide) { protected void onPostExecute(@Nullable final Slide slide) {
if (slide == null) { if (slide == null) {
attachmentView.setVisibility(View.GONE); attachmentViewStub.get().setVisibility(View.GONE);
Toast.makeText(context, Toast.makeText(context,
R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment, R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} else if (!areConstraintsSatisfied(context, masterSecret, slide, constraints)) { } else if (!areConstraintsSatisfied(context, masterSecret, slide, constraints)) {
attachmentView.setVisibility(View.GONE); attachmentViewStub.get().setVisibility(View.GONE);
Toast.makeText(context, Toast.makeText(context,
R.string.ConversationActivity_attachment_exceeds_size_limits, R.string.ConversationActivity_attachment_exceeds_size_limits,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} else { } else {
setSlide(slide); setSlide(slide);
attachmentView.setVisibility(View.VISIBLE); attachmentViewStub.get().setVisibility(View.VISIBLE);
if (slide.hasAudio()) { if (slide.hasAudio()) {
audioView.setAudio(masterSecret, (AudioSlide)slide, false); audioView.setAudio(masterSecret, (AudioSlide)slide, false);
@ -230,7 +248,7 @@ public class AttachmentManager {
} }
public boolean isAttachmentPresent() { public boolean isAttachmentPresent() {
return attachmentView.getVisibility() == View.VISIBLE; return attachmentViewStub.resolved() && attachmentViewStub.get().getVisibility() == View.VISIBLE;
} }
public @NonNull SlideDeck buildSlideDeck() { public @NonNull SlideDeck buildSlideDeck() {

View File

@ -0,0 +1,27 @@
package org.thoughtcrime.securesms.util.views;
import android.view.ViewStub;
public class Stub<T> {
private final ViewStub viewStub;
private T view;
public Stub(ViewStub viewStub) {
this.viewStub = viewStub;
}
public T get() {
if (view == null) {
view = (T)viewStub.inflate();
}
return view;
}
public boolean resolved() {
return view != null;
}
}