Open photos embedded in preview cards in the image viewer (#1966)

* Open photos embedded in preview cards in the internal image viewer instead of opening the browser

* Enable toolbar for single image viewer

* Apply review feedback
This commit is contained in:
Levi Bard 2020-10-22 21:15:46 +02:00 committed by GitHub
parent 53bd081802
commit e0346a8e88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 51 additions and 32 deletions

View file

@ -407,7 +407,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
accountAvatarImageView.setOnClickListener { avatarView ->
val intent = ViewMediaActivity.newAvatarIntent(avatarView.context, account.avatar)
val intent = ViewMediaActivity.newSingleImageIntent(avatarView.context, account.avatar)
avatarView.transitionName = account.avatar
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, avatarView, account.avatar)

View file

@ -46,7 +46,7 @@ import com.bumptech.glide.request.FutureTarget
import com.keylesspalace.tusky.BuildConfig.APPLICATION_ID
import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.fragment.ViewImageFragment
import com.keylesspalace.tusky.pager.AvatarImagePagerAdapter
import com.keylesspalace.tusky.pager.SingleImagePagerAdapter
import com.keylesspalace.tusky.pager.ImagePagerAdapter
import com.keylesspalace.tusky.util.getTemporaryMediaFilename
import com.keylesspalace.tusky.viewdata.AttachmentViewData
@ -68,7 +68,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
companion object {
private const val EXTRA_ATTACHMENTS = "attachments"
private const val EXTRA_ATTACHMENT_INDEX = "index"
private const val EXTRA_AVATAR_URL = "avatar"
private const val EXTRA_SINGLE_IMAGE_URL = "single_image"
private const val TAG = "ViewMediaActivity"
@JvmStatic
@ -79,9 +79,10 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
return intent
}
fun newAvatarIntent(context: Context, url: String): Intent {
@JvmStatic
fun newSingleImageIntent(context: Context, url: String): Intent {
val intent = Intent(context, ViewMediaActivity::class.java)
intent.putExtra(EXTRA_AVATAR_URL, url)
intent.putExtra(EXTRA_SINGLE_IMAGE_URL, url)
return intent
}
}
@ -91,6 +92,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
private var attachments: ArrayList<AttachmentViewData>? = null
private val toolbarVisibilityListeners = mutableListOf<ToolbarVisibilityListener>()
private var imageUrl: String? = null
fun addToolbarVisibilityListener(listener: ToolbarVisibilityListener): Function0<Boolean> {
this.toolbarVisibilityListeners.add(listener)
@ -117,10 +119,10 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
ImagePagerAdapter(this, realAttachs, initialPosition)
} else {
val avatarUrl = intent.getStringExtra(EXTRA_AVATAR_URL)
?: throw IllegalArgumentException("attachment list or avatar url has to be set")
imageUrl = intent.getStringExtra(EXTRA_SINGLE_IMAGE_URL)
?: throw IllegalArgumentException("attachment list or image url has to be set")
AvatarImagePagerAdapter(this, avatarUrl)
SingleImagePagerAdapter(this, imageUrl!!)
}
viewPager.adapter = adapter
@ -161,11 +163,10 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
if (attachments != null) {
menuInflater.inflate(R.menu.view_media_toolbar, menu)
return true
}
return false
menuInflater.inflate(R.menu.view_media_toolbar, menu)
// We don't support 'open status' from single image views
menu?.findItem(R.id.action_open_status)?.isVisible = (attachments != null)
return true
}
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
@ -213,7 +214,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
}
private fun downloadMedia() {
val url = attachments!![viewPager.currentItem].attachment.url
val url = imageUrl ?: attachments!![viewPager.currentItem].attachment.url
val filename = Uri.parse(url).lastPathSegment
Toast.makeText(applicationContext, resources.getString(R.string.download_image, filename), Toast.LENGTH_SHORT).show()
@ -240,8 +241,9 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
}
private fun copyLink() {
val url = imageUrl ?: attachments!![viewPager.currentItem].attachment.url
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText(null, attachments!![viewPager.currentItem].attachment.url))
clipboard.setPrimaryClip(ClipData.newPlainText(null, url))
}
private fun shareMedia() {
@ -251,13 +253,17 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
return
}
val attachment = attachments!![viewPager.currentItem].attachment
when (attachment.type) {
Attachment.Type.IMAGE -> shareImage(directory, attachment.url)
Attachment.Type.AUDIO,
Attachment.Type.VIDEO,
Attachment.Type.GIFV -> shareMediaFile(directory, attachment.url)
else -> Log.e(TAG, "Unknown media format for sharing.")
if (imageUrl != null) {
shareImage(directory, imageUrl!!)
} else {
val attachment = attachments!![viewPager.currentItem].attachment
when (attachment.type) {
Attachment.Type.IMAGE -> shareImage(directory, attachment.url)
Attachment.Type.AUDIO,
Attachment.Type.VIDEO,
Attachment.Type.GIFV -> shareMediaFile(directory, attachment.url)
else -> Log.e(TAG, "Unknown media format for sharing.")
}
}
}

View file

@ -31,6 +31,7 @@ import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.GranularRoundedCorners;
import com.google.android.material.button.MaterialButton;
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.ViewMediaActivity;
import com.keylesspalace.tusky.entity.Attachment;
import com.keylesspalace.tusky.entity.Attachment.Focus;
import com.keylesspalace.tusky.entity.Attachment.MetaData;
@ -1069,7 +1070,15 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
cardImage.setImageResource(R.drawable.card_image_placeholder);
}
cardView.setOnClickListener(v -> LinkHelper.openLink(card.getUrl(), v.getContext()));
View.OnClickListener visitLink = v -> LinkHelper.openLink(card.getUrl(), v.getContext());
View.OnClickListener openImage = v -> cardView.getContext().startActivity(ViewMediaActivity.newSingleImageIntent(cardView.getContext(), card.getEmbed_url()));
cardInfo.setOnClickListener(visitLink);
// View embedded photos in our image viewer instead of opening the browser
cardImage.setOnClickListener(card.getType().equals(Card.TYPE_PHOTO) && !TextUtils.isEmpty(card.getEmbed_url()) ?
openImage :
visitLink);
cardView.setClipToOutline(true);
} else {
cardView.setVisibility(View.GONE);

View file

@ -27,7 +27,8 @@ data class Card(
val type: String,
val width: Int,
val height: Int,
val blurhash: String?
val blurhash: String?,
val embed_url: String?
) {
override fun hashCode(): Int {
@ -42,4 +43,7 @@ data class Card(
return account?.url == this.url
}
companion object {
const val TYPE_PHOTO = "photo"
}
}

View file

@ -99,9 +99,9 @@ class ViewImageFragment : ViewMediaFragment() {
url = attachment.url
description = attachment.description
} else {
url = arguments.getString(ARG_AVATAR_URL)
url = arguments.getString(ARG_SINGLE_IMAGE_URL)
if (url == null) {
throw IllegalArgumentException("attachment or avatar url has to be set")
throw IllegalArgumentException("attachment or image url has to be set")
}
}

View file

@ -42,7 +42,7 @@ abstract class ViewMediaFragment : BaseFragment() {
@JvmStatic
protected val ARG_ATTACHMENT = "attach"
@JvmStatic
protected val ARG_AVATAR_URL = "avatarUrl"
protected val ARG_SINGLE_IMAGE_URL = "singleImageUrl"
@JvmStatic
fun newInstance(attachment: Attachment, shouldStartPostponedTransition: Boolean): ViewMediaFragment {
@ -62,10 +62,10 @@ abstract class ViewMediaFragment : BaseFragment() {
}
@JvmStatic
fun newAvatarInstance(avatarUrl: String): ViewMediaFragment {
fun newSingleImageInstance(imageUrl: String): ViewMediaFragment {
val arguments = Bundle(2)
val fragment = ViewImageFragment()
arguments.putString(ARG_AVATAR_URL, avatarUrl)
arguments.putString(ARG_SINGLE_IMAGE_URL, imageUrl)
arguments.putBoolean(ARG_START_POSTPONED_TRANSITION, true)
fragment.arguments = arguments

View file

@ -5,14 +5,14 @@ import androidx.fragment.app.FragmentActivity
import com.keylesspalace.tusky.ViewMediaAdapter
import com.keylesspalace.tusky.fragment.ViewMediaFragment
class AvatarImagePagerAdapter(
class SingleImagePagerAdapter(
activity: FragmentActivity,
private val avatarUrl: String
private val imageUrl: String
) : ViewMediaAdapter(activity) {
override fun createFragment(position: Int): Fragment {
return if (position == 0) {
ViewMediaFragment.newAvatarInstance(avatarUrl)
ViewMediaFragment.newSingleImageInstance(imageUrl)
} else {
throw IllegalStateException()
}