GIFデータの表示を改善

This commit is contained in:
tateisu 2023-07-17 09:37:48 +09:00
parent 406d066437
commit d29cbb1299
5 changed files with 111 additions and 23 deletions

View File

@ -33,6 +33,7 @@ import jp.juggler.subwaytooter.api.entity.TootAttachment.Companion.tootAttachmen
import jp.juggler.subwaytooter.databinding.ActMediaViewerBinding import jp.juggler.subwaytooter.databinding.ActMediaViewerBinding
import jp.juggler.subwaytooter.dialog.actionsDialog import jp.juggler.subwaytooter.dialog.actionsDialog
import jp.juggler.subwaytooter.drawable.MediaBackgroundDrawable import jp.juggler.subwaytooter.drawable.MediaBackgroundDrawable
import jp.juggler.subwaytooter.itemviewholder.reUrlGif
import jp.juggler.subwaytooter.pref.PrefI import jp.juggler.subwaytooter.pref.PrefI
import jp.juggler.subwaytooter.util.permissionSpecMediaDownload import jp.juggler.subwaytooter.util.permissionSpecMediaDownload
import jp.juggler.subwaytooter.util.requester import jp.juggler.subwaytooter.util.requester
@ -61,7 +62,7 @@ import javax.microedition.khronos.opengles.GL10
import javax.net.ssl.HttpsURLConnection import javax.net.ssl.HttpsURLConnection
import kotlin.math.max import kotlin.math.max
@androidx.media3.common.util.UnstableApi @androidx.annotation.OptIn(markerClass = [androidx.media3.common.util.UnstableApi::class])
class ActMediaViewer : AppCompatActivity(), View.OnClickListener { class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
companion object { companion object {
@ -399,6 +400,17 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
setShowNextButton(false) setShowNextButton(false)
setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE) setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE)
} }
views.wvOther.apply{
scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY
settings.apply {
@SuppressLint("SetJavaScriptEnabled")
javaScriptEnabled = true
loadWithOverviewMode = true
useWideViewPort = true
setSupportZoom(true)
}
}
} }
internal fun loadDelta(delta: Int) { internal fun loadDelta(delta: Int) {
@ -414,6 +426,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
// いったんすべて隠す // いったんすべて隠す
views.run { views.run {
wvOther.gone()
pbvImage.gone() pbvImage.gone()
pvVideo.gone() pvVideo.gone()
tvError.gone() tvError.gone()
@ -434,10 +447,15 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
when (ta.type) { when (ta.type) {
TootAttachmentType.Unknown, TootAttachmentType.Unknown,
-> showError(getString(R.string.media_attachment_type_error, ta.type.id)) -> loadOther(ta) // showError(getString(R.string.media_attachment_type_error, ta.type.id))
TootAttachmentType.Image, TootAttachmentType.Image -> when {
-> loadBitmap(ta) reUrlGif.containsMatchIn(ta.remote_url ?: "") ->
loadOther(ta)
else ->
loadBitmap(ta)
}
TootAttachmentType.Video, TootAttachmentType.Video,
TootAttachmentType.GIFV, TootAttachmentType.GIFV,
@ -590,7 +608,21 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
return Pair(bitmap2, null) return Pair(bitmap2, null)
} }
@SuppressLint("StaticFieldLeak") private fun loadOther(ta: TootAttachment) {
val urlList = ta.getLargeUrlList()
if (urlList.isEmpty()) {
showError("missing media attachment url.")
return
}
val url = urlList.first()
views.run {
cbMute.gone()
tvStatus.visible().text = "${ta.type.id} ${url.ellipsizeDot3(100)}"
wvOther.visible().loadUrl(url)
}
}
private fun loadBitmap(ta: TootAttachment) { private fun loadBitmap(ta: TootAttachment) {
views.run { views.run {

View File

@ -7,11 +7,9 @@ class TootAttachmentMSP(
val preview_url: String, val preview_url: String,
) : TootAttachmentLike { ) : TootAttachmentLike {
override val type: TootAttachmentType override val type = TootAttachmentType.Unknown
get() = TootAttachmentType.Unknown
override val description: String? override val description = null
get() = null
override fun urlForThumbnail() = preview_url override fun urlForThumbnail() = preview_url

View File

@ -5,9 +5,35 @@ import android.view.View
import jp.juggler.subwaytooter.ActMain import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.ActMediaViewer import jp.juggler.subwaytooter.ActMediaViewer
import jp.juggler.subwaytooter.R import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.action.* import jp.juggler.subwaytooter.action.clickCardImage
import jp.juggler.subwaytooter.action.clickConversation
import jp.juggler.subwaytooter.action.clickDomainBlock
import jp.juggler.subwaytooter.action.clickFollowInfo
import jp.juggler.subwaytooter.action.clickFollowRequestAccept
import jp.juggler.subwaytooter.action.clickListMoreButton
import jp.juggler.subwaytooter.action.clickListTl
import jp.juggler.subwaytooter.action.clickReplyInfo
import jp.juggler.subwaytooter.action.clickScheduledToot
import jp.juggler.subwaytooter.action.conversationOtherInstance
import jp.juggler.subwaytooter.action.followFromAnotherAccount
import jp.juggler.subwaytooter.action.longClickTootTag
import jp.juggler.subwaytooter.action.openFilterMenu
import jp.juggler.subwaytooter.action.tagDialog
import jp.juggler.subwaytooter.action.userProfileLocal
import jp.juggler.subwaytooter.actmain.nextPosition import jp.juggler.subwaytooter.actmain.nextPosition
import jp.juggler.subwaytooter.api.entity.* import jp.juggler.subwaytooter.api.entity.ServiceType
import jp.juggler.subwaytooter.api.entity.TimelineItem
import jp.juggler.subwaytooter.api.entity.TootAccountRef
import jp.juggler.subwaytooter.api.entity.TootAttachment
import jp.juggler.subwaytooter.api.entity.TootAttachmentMSP
import jp.juggler.subwaytooter.api.entity.TootAttachmentType
import jp.juggler.subwaytooter.api.entity.TootConversationSummary
import jp.juggler.subwaytooter.api.entity.TootDomainBlock
import jp.juggler.subwaytooter.api.entity.TootGap
import jp.juggler.subwaytooter.api.entity.TootNotification
import jp.juggler.subwaytooter.api.entity.TootScheduled
import jp.juggler.subwaytooter.api.entity.TootSearchGap
import jp.juggler.subwaytooter.api.entity.TootTag
import jp.juggler.subwaytooter.column.Column import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.column.startGap import jp.juggler.subwaytooter.column.startGap
import jp.juggler.subwaytooter.pref.PrefB import jp.juggler.subwaytooter.pref.PrefB
@ -62,6 +88,7 @@ fun ItemViewHolder.onClickImpl(v: View?) {
tvContent tvContent
).show() ).show()
} }
btnFollow -> clickFollowInfo( btnFollow -> clickFollowInfo(
pos, pos,
accessInfo, accessInfo,
@ -88,11 +115,13 @@ fun ItemViewHolder.onClickImpl(v: View?) {
followAccount, followAccount,
accept = true accept = true
) )
btnFollowRequestDeny -> clickFollowRequestAccept( btnFollowRequestDeny -> clickFollowRequestAccept(
accessInfo, accessInfo,
followAccount, followAccount,
accept = false accept = false
) )
llFilter -> openFilterMenu(accessInfo, item.cast()) llFilter -> openFilterMenu(accessInfo, item.cast())
ivCardImage -> clickCardImage(pos, accessInfo, statusShowing?.card) ivCardImage -> clickCardImage(pos, accessInfo, statusShowing?.card)
llConversationIcons -> clickConversation( llConversationIcons -> clickConversation(
@ -200,7 +229,7 @@ private fun ItemViewHolder.clickMedia(i: Int) {
statusShowing?.media_attachments ?: (item as? TootScheduled)?.mediaAttachments statusShowing?.media_attachments ?: (item as? TootScheduled)?.mediaAttachments
?: return ?: return
when (val item = if (i < mediaAttachments.size) mediaAttachments[i] else return) { when (val item = mediaAttachments.firstOrNull() ?: return) {
is TootAttachmentMSP -> { is TootAttachmentMSP -> {
// マストドン検索ポータルのデータではmedia_attachmentsが簡略化されている // マストドン検索ポータルのデータではmedia_attachmentsが簡略化されている
// 会話の流れを表示する // 会話の流れを表示する
@ -212,15 +241,16 @@ private fun ItemViewHolder.clickMedia(i: Int) {
is TootAttachment -> when { is TootAttachment -> when {
// unknownが1枚だけなら内蔵ビューアを使わずにインテントを投げる // 添付メディアが1枚だけで、unknownまたはファイル拡張子がGIFなら、ブラウザで開く
item.type == TootAttachmentType.Unknown && mediaAttachments.size == 1 -> { // https://github.com/tateisu/SubwayTooter/pull/119
// https://github.com/tateisu/SubwayTooter/pull/119 // メディアタイプがunknownの場合、そのほとんどはリモートから来たURLである
// メディアタイプがunknownの場合、そのほとんどはリモートから来たURLである // PrefB.bpPriorLocalURL の状態に関わらずリモートURLがあればそれをブラウザで開く
// PrefB.bpPriorLocalURL の状態に関わらずリモートURLがあればそれをブラウザで開く mediaAttachments.size == 1 &&
when (val remoteUrl = item.remote_url.notEmpty()) { (item.type == TootAttachmentType.Unknown ||
null -> activity.openCustomTab(item) reUrlGif.containsMatchIn(item.remote_url ?: ""))
else -> activity.openCustomTab(remoteUrl) -> when (val remoteUrl = item.remote_url.notEmpty()) {
} null -> activity.openCustomTab(item)
else -> activity.openCustomTab(remoteUrl)
} }
// 内蔵メディアビューアを使う // 内蔵メディアビューアを使う
@ -324,9 +354,11 @@ private fun ItemViewHolder.clickTag(pos: Int, item: TimelineItem?) {
item.name, item.name,
tagInfo = item, tagInfo = item,
) )
TootTag.TagType.Link -> TootTag.TagType.Link ->
openCustomTab(item.url) openCustomTab(item.url)
} }
is TootSearchGap -> column.startGap(item, isHead = true) is TootSearchGap -> column.startGap(item, isHead = true)
is TootConversationSummary -> clickConversation( is TootConversationSummary -> clickConversation(
pos, pos,
@ -334,6 +366,7 @@ private fun ItemViewHolder.clickTag(pos: Int, item: TimelineItem?) {
listAdapter, listAdapter,
summary = item summary = item
) )
is TootGap -> clickTootGap(column, item) is TootGap -> clickTootGap(column, item)
is TootDomainBlock -> clickDomainBlock(accessInfo, item) is TootDomainBlock -> clickDomainBlock(accessInfo, item)
is TootScheduled -> clickScheduledToot(accessInfo, item, column) is TootScheduled -> clickScheduledToot(accessInfo, item, column)

View File

@ -356,6 +356,8 @@ private fun ItemViewHolder.showAttachments(status: TootStatus) {
} }
} }
val reUrlGif = """\.gif(?:\z|\?)""".toRegex(RegexOption.IGNORE_CASE)
fun ItemViewHolder.setMedia( fun ItemViewHolder.setMedia(
mediaAttachments: ArrayList<TootAttachmentLike>, mediaAttachments: ArrayList<TootAttachmentLike>,
idx: Int, idx: Int,
@ -390,11 +392,28 @@ fun ItemViewHolder.setMedia(
TootAttachmentType.Unknown -> { TootAttachmentType.Unknown -> {
iv.setMediaType(0) iv.setMediaType(0)
iv.setDefaultImage(defaultColorIcon(activity, R.drawable.wide_question)) iv.setDefaultImage(defaultColorIcon(activity, R.drawable.wide_question))
iv.setImageUrl(0f, null) if (ta is TootAttachment &&
reUrlGif.containsMatchIn(ta.remote_url ?: "") &&
PrefB.bpImageAnimationEnable.value
) {
val url = ta.remote_url!!
iv.setImageUrl(0f, url, url)
} else {
iv.setImageUrl(0f, null)
}
showUrl = true showUrl = true
} }
else -> when (val urlThumbnail = ta.urlForThumbnail()) { else -> if (ta is TootAttachment &&
reUrlGif.containsMatchIn(ta.remote_url ?: "") &&
PrefB.bpImageAnimationEnable.value
) {
iv.setMediaType(0)
iv.setDefaultImage(null)
val url = ta.remote_url!!
iv.setImageUrl(0f, url, url)
showUrl = false
} else when (val urlThumbnail = ta.urlForThumbnail()) {
null, "" -> { null, "" -> {
iv.setMediaType(0) iv.setMediaType(0)
iv.setDefaultImage(defaultColorIcon(activity, R.drawable.wide_question)) iv.setDefaultImage(defaultColorIcon(activity, R.drawable.wide_question))

View File

@ -26,6 +26,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"> android:layout_weight="1">
<WebView
android:id="@+id/wvOther"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<jp.juggler.subwaytooter.view.PinchBitmapView <jp.juggler.subwaytooter.view.PinchBitmapView
android:id="@+id/pbvImage" android:id="@+id/pbvImage"