diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index 87748420d..c52aced57 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -123,6 +123,7 @@ dependencies {
exclude group: 'com.android.support'
exclude module: 'disklrucache' // when there's no disk cache, we can't accidentally use it
}
+ implementation 'com.github.chrisbanes:PhotoView:2.1.4' // later versions already use androidx
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
annotationProcessor "com.github.bumptech.glide:compiler:$glideVersion"
diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml
index e9300a7fd..c0e358843 100644
--- a/briar-android/src/main/AndroidManifest.xml
+++ b/briar-android/src/main/AndroidManifest.xml
@@ -113,6 +113,15 @@
/>
+
+
+
+
new activity.
+ * @param returnTransition used when window is closing, because the activity is finishing.
+ */
+ @RequiresApi(api = 21)
+ public void setSceneTransitionAnimation(
+ @Nullable Transition enterTransition,
+ @Nullable Transition exitTransition,
+ @Nullable Transition returnTransition) {
// workaround for #1007
if (isSamsung7()) {
return;
}
- Transition slide = new Slide(Gravity.RIGHT);
- slide.excludeTarget(android.R.id.statusBarBackground, true);
- slide.excludeTarget(android.R.id.navigationBarBackground, true);
+ if (enterTransition != null) excludeSystemUi(enterTransition);
+ if (exitTransition != null) excludeSystemUi(exitTransition);
+ if (returnTransition != null) excludeSystemUi(returnTransition);
Window window = getWindow();
- window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
- window.setExitTransition(slide);
- window.setEnterTransition(slide);
- window.setTransitionBackgroundFadeDuration(getResources()
- .getInteger(android.R.integer.config_longAnimTime));
+ window.setEnterTransition(enterTransition);
+ window.setExitTransition(exitTransition);
+ window.setReturnTransition(returnTransition);
}
/**
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogActivity.java
index 7877cbc3b..d45b10789 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogActivity.java
@@ -18,7 +18,6 @@ public class ReblogActivity extends BriarActivity implements
@Override
public void onCreate(Bundle savedInstanceState) {
- setSceneTransitionAnimation();
super.onCreate(savedInstanceState);
Intent intent = getIntent();
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/AttachmentItem.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/AttachmentItem.java
index 5a5efb657..bd582d68f 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/AttachmentItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/AttachmentItem.java
@@ -1,5 +1,8 @@
package org.briarproject.briar.android.conversation;
+import android.os.Parcel;
+import android.os.Parcelable;
+
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
@@ -7,13 +10,26 @@ import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
-public class AttachmentItem {
+public class AttachmentItem implements Parcelable {
private final MessageId messageId;
private final int width, height;
private final int thumbnailWidth, thumbnailHeight;
private final boolean hasError;
+ public static final Creator CREATOR =
+ new Creator() {
+ @Override
+ public AttachmentItem createFromParcel(Parcel in) {
+ return new AttachmentItem(in);
+ }
+
+ @Override
+ public AttachmentItem[] newArray(int size) {
+ return new AttachmentItem[size];
+ }
+ };
+
AttachmentItem(MessageId messageId, int width, int height,
int thumbnailWidth, int thumbnailHeight, boolean hasError) {
this.messageId = messageId;
@@ -24,6 +40,17 @@ public class AttachmentItem {
this.hasError = hasError;
}
+ protected AttachmentItem(Parcel in) {
+ byte[] messageIdByte = new byte[MessageId.LENGTH];
+ in.readByteArray(messageIdByte);
+ messageId = new MessageId(messageIdByte);
+ width = in.readInt();
+ height = in.readInt();
+ thumbnailWidth = in.readInt();
+ thumbnailHeight = in.readInt();
+ hasError = in.readByte() != 0;
+ }
+
public MessageId getMessageId() {
return messageId;
}
@@ -48,4 +75,23 @@ public class AttachmentItem {
return hasError;
}
+ String getTransitionName() {
+ return String.valueOf(messageId.hashCode());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByteArray(messageId.getBytes());
+ dest.writeInt(width);
+ dest.writeInt(height);
+ dest.writeInt(thumbnailWidth);
+ dest.writeInt(thumbnailHeight);
+ dest.writeByte((byte) (hasError ? 1 : 0));
+ }
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
index 754e8f06a..e17ad5451 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
@@ -9,11 +9,15 @@ import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.design.widget.Snackbar;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.Toolbar;
+import android.transition.Slide;
+import android.transition.Transition;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuInflater;
@@ -96,8 +100,11 @@ import im.delight.android.identicons.IdenticonDrawable;
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.PromptStateChangeListener;
+import static android.os.Build.VERSION.SDK_INT;
+import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
import static android.support.v4.view.ViewCompat.setTransitionName;
import static android.support.v7.util.SortedList.INVALID_POSITION;
+import static android.view.Gravity.END;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.Collections.emptyList;
import static java.util.Collections.sort;
@@ -108,6 +115,9 @@ import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_INTRODUCTION;
+import static org.briarproject.briar.android.conversation.ImageActivity.ATTACHMENT;
+import static org.briarproject.briar.android.conversation.ImageActivity.DATE;
+import static org.briarproject.briar.android.conversation.ImageActivity.NAME;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
import static org.briarproject.briar.android.util.UiUtils.getBulbTransitionName;
@@ -186,7 +196,10 @@ public class ConversationActivity extends BriarActivity
@Override
public void onCreate(@Nullable Bundle state) {
- setSceneTransitionAnimation();
+ if (SDK_INT >= 21) {
+ Transition slide = new Slide(END);
+ setSceneTransitionAnimation(slide, null, slide);
+ }
super.onCreate(state);
Intent i = getIntent();
@@ -802,6 +815,31 @@ public class ConversationActivity extends BriarActivity
startActivity(i);
}
+ @Override
+ public void onAttachmentClicked(View view,
+ ConversationMessageItem messageItem, AttachmentItem item) {
+ String name;
+ if (messageItem.isIncoming()) {
+ // must be available when items are being displayed
+ name = viewModel.getContactDisplayName().getValue();
+ } else {
+ name = getString(R.string.you);
+ }
+ Intent i = new Intent(this, ImageActivity.class);
+ i.putExtra(ATTACHMENT, item);
+ i.putExtra(NAME, name);
+ i.putExtra(DATE, messageItem.getTime());
+ if (SDK_INT >= 23) {
+ String transitionName = item.getTransitionName();
+ ActivityOptionsCompat options =
+ makeSceneTransitionAnimation(this, view, transitionName);
+ ActivityCompat.startActivity(this, i, options.toBundle());
+ } else {
+ // work-around for android bug #224270
+ startActivity(i);
+ }
+ }
+
@DatabaseExecutor
private void respondToIntroductionRequest(SessionId sessionId,
boolean accept, long time) throws DbException {
@@ -845,4 +883,5 @@ public class ConversationActivity extends BriarActivity
}
return attachments;
}
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java
index 0b56878dc..9c8db9538 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationListener.java
@@ -1,6 +1,7 @@
package org.briarproject.briar.android.conversation;
import android.support.annotation.UiThread;
+import android.view.View;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -14,4 +15,7 @@ interface ConversationListener {
void openRequestedShareable(ConversationRequestItem item);
+ void onAttachmentClicked(View view, ConversationMessageItem messageItem,
+ AttachmentItem attachmentItem);
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationMessageViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationMessageViewHolder.java
index 91977da2c..abef0bffd 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationMessageViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationMessageViewHolder.java
@@ -85,7 +85,7 @@ class ConversationMessageViewHolder extends ConversationItemViewHolder {
if (item.getAttachments().isEmpty()) {
bindTextItem();
} else {
- bindImageItem(item);
+ bindImageItem(item, listener);
}
}
@@ -98,7 +98,8 @@ class ConversationMessageViewHolder extends ConversationItemViewHolder {
textConstraints.applyTo(layout);
}
- private void bindImageItem(ConversationMessageItem item) {
+ private void bindImageItem(ConversationMessageItem item,
+ ConversationListener listener) {
// TODO show more than just the first image
AttachmentItem attachment = item.getAttachments().get(0);
@@ -127,17 +128,18 @@ class ConversationMessageViewHolder extends ConversationItemViewHolder {
clearImage();
imageView.setImageResource(ERROR_RES);
} else {
- loadImage(item, attachment);
+ loadImage(item, attachment, listener);
}
}
private void clearImage() {
GlideApp.with(imageView)
.clear(imageView);
+ imageView.setOnClickListener(null);
}
private void loadImage(ConversationMessageItem item,
- AttachmentItem attachment) {
+ AttachmentItem attachment, ConversationListener listener) {
boolean leftCornerSmall =
(isIncoming() && !isRtl) || (!isIncoming() && isRtl);
boolean bottomRound = item.getText() == null;
@@ -152,6 +154,8 @@ class ConversationMessageViewHolder extends ConversationItemViewHolder {
.transition(withCrossFade())
.into(imageView)
.waitForLayout();
+ imageView.setOnClickListener(
+ view -> listener.onAttachmentClicked(view, item, attachment));
}
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageActivity.java
new file mode 100644
index 000000000..6c489d710
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageActivity.java
@@ -0,0 +1,181 @@
+package org.briarproject.briar.android.conversation;
+
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+import android.support.design.widget.AppBarLayout;
+import android.support.v7.widget.Toolbar;
+import android.transition.Fade;
+import android.transition.Transition;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.TextView;
+
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.engine.GlideException;
+import com.bumptech.glide.request.RequestListener;
+import com.bumptech.glide.request.target.Target;
+import com.github.chrisbanes.photoview.PhotoView;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.conversation.glide.GlideApp;
+
+import static android.graphics.Color.TRANSPARENT;
+import static android.os.Build.VERSION.SDK_INT;
+import static android.view.View.GONE;
+import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+import static android.view.View.VISIBLE;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+import static com.bumptech.glide.load.engine.DiskCacheStrategy.NONE;
+import static java.util.Objects.requireNonNull;
+import static org.briarproject.briar.android.util.UiUtils.formatDateAbsolute;
+
+public class ImageActivity extends BriarActivity {
+
+ final static String ATTACHMENT = "attachment";
+ final static String NAME = "name";
+ final static String DATE = "date";
+
+ private AppBarLayout appBarLayout;
+
+ @Override
+ public void injectActivity(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle state) {
+ super.onCreate(state);
+
+ // Transitions
+ supportPostponeEnterTransition();
+ Window window = getWindow();
+ if (SDK_INT >= 21) {
+ Transition transition = new Fade();
+ setSceneTransitionAnimation(transition, null, transition);
+ }
+
+ // inflate layout
+ setContentView(R.layout.activity_image);
+
+ // Status Bar
+ if (SDK_INT >= 21) {
+ window.setStatusBarColor(TRANSPARENT);
+ } else if (SDK_INT >= 19) {
+ // we can't make the status bar transparent, but translucent
+ window.addFlags(FLAG_TRANSLUCENT_STATUS);
+ }
+
+ // Toolbar
+ appBarLayout = findViewById(R.id.appBarLayout);
+ Toolbar toolbar = requireNonNull(setUpCustomToolbar(true));
+ TextView contactName = toolbar.findViewById(R.id.contactName);
+ TextView dateView = toolbar.findViewById(R.id.dateView);
+
+ // Intent Extras
+ AttachmentItem attachment = getIntent().getParcelableExtra(ATTACHMENT);
+ String name = getIntent().getStringExtra(NAME);
+ long time = getIntent().getLongExtra(DATE, 0);
+ String date = formatDateAbsolute(this, time);
+ contactName.setText(name);
+ dateView.setText(date);
+
+ // Image View
+ PhotoView photoView = findViewById(R.id.photoView);
+ if (SDK_INT >= 16) {
+ photoView.setOnClickListener(view -> toggleSystemUi());
+ window.getDecorView().setSystemUiVisibility(
+ SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ }
+
+ // Request Listener
+ RequestListener listener = new RequestListener() {
+ @Override
+ public boolean onLoadFailed(@Nullable GlideException e,
+ Object model, Target target,
+ boolean isFirstResource) {
+ return false;
+ }
+
+ @Override
+ public boolean onResourceReady(Drawable resource,
+ Object model, Target target,
+ DataSource dataSource, boolean isFirstResource) {
+ if (SDK_INT >= 21 &&
+ !(resource instanceof Animatable)) {
+ // set transition name only when not animatable,
+ // because the animation won't start otherwise
+ photoView.setTransitionName(
+ attachment.getTransitionName());
+ }
+ supportStartPostponedEnterTransition();
+ return false;
+ }
+ };
+
+ // Load Image
+ GlideApp.with(this)
+ .load(attachment)
+ .diskCacheStrategy(NONE)
+ .error(R.drawable.ic_image_broken)
+ .dontTransform()
+ .addListener(listener)
+ .into(photoView);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @RequiresApi(api = 16)
+ private void toggleSystemUi() {
+ View decorView = getWindow().getDecorView();
+ if (appBarLayout.getVisibility() == VISIBLE) {
+ hideSystemUI(decorView);
+ } else {
+ showSystemUI(decorView);
+ }
+ }
+
+ @RequiresApi(api = 16)
+ private void hideSystemUI(View decorView) {
+ decorView.setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | SYSTEM_UI_FLAG_FULLSCREEN
+ );
+ appBarLayout.animate()
+ .translationYBy(-1 * appBarLayout.getHeight())
+ .alpha(0f)
+ .withEndAction(() -> appBarLayout.setVisibility(GONE))
+ .start();
+ }
+
+ @RequiresApi(api = 16)
+ private void showSystemUI(View decorView) {
+ decorView.setSystemUiVisibility(
+ SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ );
+ appBarLayout.animate()
+ .translationYBy(appBarLayout.getHeight())
+ .alpha(1f)
+ .withStartAction(() -> appBarLayout.setVisibility(VISIBLE))
+ .start();
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
index 5f59251f9..c73214fb9 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
@@ -16,6 +16,7 @@ import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
@@ -31,6 +32,7 @@ import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.URLSpan;
+import android.transition.Transition;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.View;
@@ -60,12 +62,16 @@ import static android.support.v7.app.AppCompatDelegate.MODE_NIGHT_NO;
import static android.support.v7.app.AppCompatDelegate.MODE_NIGHT_YES;
import static android.support.v7.app.AppCompatDelegate.setDefaultNightMode;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
+import static android.text.format.DateUtils.FORMAT_ABBREV_ALL;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE;
import static android.text.format.DateUtils.FORMAT_ABBREV_TIME;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
+import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
+import static android.text.format.DateUtils.FORMAT_SHOW_YEAR;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
+import static android.text.format.DateUtils.YEAR_IN_MILLIS;
import static android.view.KeyEvent.ACTION_DOWN;
import static android.view.KeyEvent.KEYCODE_ENTER;
import static android.view.inputmethod.EditorInfo.IME_NULL;
@@ -117,6 +123,13 @@ public class UiUtils {
MIN_DATE_RESOLUTION, flags).toString();
}
+ public static String formatDateAbsolute(Context ctx, long time) {
+ int flags = FORMAT_SHOW_TIME | FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL;
+ long diff = System.currentTimeMillis() - time;
+ if (diff >= YEAR_IN_MILLIS) flags |= FORMAT_SHOW_YEAR;
+ return DateUtils.formatDateTime(ctx, time, flags);
+ }
+
public static int getDaysUntilExpiry() {
long now = System.currentTimeMillis();
long daysBeforeExpiry = (EXPIRY_DATE - now) / 1000 / 60 / 60 / 24;
@@ -318,6 +331,12 @@ public class UiUtils {
keyEvent.getKeyCode() == KEYCODE_ENTER;
}
+ @RequiresApi(api = 21)
+ public static void excludeSystemUi(Transition transition) {
+ transition.excludeTarget(android.R.id.statusBarBackground, true);
+ transition.excludeTarget(android.R.id.navigationBarBackground, true);
+ }
+
/**
* Observes the given {@link LiveData} until the first change.
* If the LiveData's value is available, the {@link Observer} will be
diff --git a/briar-android/src/main/res/layout/activity_image.xml b/briar-android/src/main/res/layout/activity_image.xml
new file mode 100644
index 000000000..2be562fbd
--- /dev/null
+++ b/briar-android/src/main/res/layout/activity_image.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
index a7ee15079..2f87d2a26 100644
--- a/briar-android/src/main/res/values/strings.xml
+++ b/briar-android/src/main/res/values/strings.xml
@@ -134,6 +134,8 @@
Confirm Contact Deletion
Are you sure that you want to remove this contact and all messages exchanged with this contact?
Contact deleted
+
+ You
Add a Contact
diff --git a/briar-android/witness.gradle b/briar-android/witness.gradle
index 29a9c2f01..ee7273494 100644
--- a/briar-android/witness.gradle
+++ b/briar-android/witness.gradle
@@ -89,6 +89,7 @@ dependencyVerification {
'com.github.bumptech.glide:compiler:4.8.0:compiler-4.8.0.jar:1fa93dd0cf7ef0b8b98a59a67a1ee84915416c2d677d83a771ea3e32ad15e6bf',
'com.github.bumptech.glide:gifdecoder:4.8.0:gifdecoder-4.8.0.aar:b00c5454a023a9488ea49603930d9c25e09192e5ceaadf64977aa52946b3c1b4',
'com.github.bumptech.glide:glide:4.8.0:glide-4.8.0.aar:5ddf08b12cc43332e812988f16c2c39e7fce49d1c4d94b7948dcde7f00bf49d6',
+ 'com.github.chrisbanes:PhotoView:2.1.4:PhotoView-2.1.4.aar:04cb397fcb3df0757c8aed6927ebdd247930b5c78ee9acc59cd07dccdaaf3460',
'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.0:accessibility-test-framework-2.0.jar:cdf16ef8f5b8023d003ce3cc1b0d51bda737762e2dab2fedf43d1c4292353f7f',
'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.1:accessibility-test-framework-2.1.jar:7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
diff --git a/build.gradle b/build.gradle
index 877e86667..516f8f7fe 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,6 +5,7 @@ allprojects {
jcenter()
mavenLocal()
google()
+ maven { url "https://jitpack.io" }
}
afterEvaluate {
tasks.withType(Test) {