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:
parent
53bd081802
commit
e0346a8e88
7 changed files with 51 additions and 32 deletions
|
@ -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)
|
||||
|
|
|
@ -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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
Loading…
Reference in a new issue