mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-03 17:47:30 +01:00
feat: support embedded web view in posts (#799)
This commit is contained in:
parent
5247b0975c
commit
707f6f8a32
@ -45,11 +45,13 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAVideo
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.showInEmbeddedWebView
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.url.getCustomTabsHelper
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.url.toUrlOpeningMode
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.embeddedUrl
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.imageUrl
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.videoUrl
|
||||
|
||||
@ -420,7 +422,11 @@ private fun ExtendedPost(
|
||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||
val optionsMenuOpen = remember { mutableStateOf(false) }
|
||||
val postLinkUrl = post.url.orEmpty().takeIf {
|
||||
it != post.imageUrl && it != post.videoUrl && !it.looksLikeAnImage && !it.looksLikeAVideo
|
||||
it != post.imageUrl
|
||||
&& it != post.videoUrl
|
||||
&& !it.looksLikeAnImage
|
||||
&& !it.looksLikeAVideo
|
||||
&& !it.showInEmbeddedWebView
|
||||
}.orEmpty()
|
||||
|
||||
Column(
|
||||
@ -483,7 +489,34 @@ private fun ExtendedPost(
|
||||
)
|
||||
}
|
||||
|
||||
if (post.videoUrl.isNotEmpty()) {
|
||||
if (post.embeddedUrl.isNotEmpty()) {
|
||||
PostCardEmbeddedWebView(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
vertical = Spacing.xxs,
|
||||
horizontal = if (fullWidthImage) 0.dp else Spacing.s,
|
||||
),
|
||||
blurred = blurNsfw && post.nsfw,
|
||||
autoLoadImages = autoLoadImages,
|
||||
url = post.embeddedUrl,
|
||||
onOpen = {
|
||||
if (postLinkUrl.isNotEmpty()) {
|
||||
navigationCoordinator.handleUrl(
|
||||
url = postLinkUrl,
|
||||
openingMode = settings.urlOpeningMode.toUrlOpeningMode(),
|
||||
uriHandler = uriHandler,
|
||||
customTabsHelper = customTabsHelper,
|
||||
onOpenWeb = onOpenWeb,
|
||||
onOpenCommunity = onOpenCommunity,
|
||||
onOpenPost = onOpenPost,
|
||||
onOpenUser = onOpenCreator,
|
||||
)
|
||||
} else {
|
||||
onClick?.invoke()
|
||||
}
|
||||
},
|
||||
)
|
||||
} else if (post.videoUrl.isNotEmpty()) {
|
||||
PostCardVideo(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
@ -595,7 +628,7 @@ private fun ExtendedPost(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (postLinkUrl.isNotEmpty() && postLinkUrl != post.imageUrl && postLinkUrl != post.videoUrl) {
|
||||
if (postLinkUrl.isNotEmpty()) {
|
||||
PostLinkBanner(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
|
@ -0,0 +1,85 @@
|
||||
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomWebView
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
||||
|
||||
@Composable
|
||||
fun PostCardEmbeddedWebView(
|
||||
modifier: Modifier = Modifier,
|
||||
url: String,
|
||||
blurred: Boolean = false,
|
||||
autoLoadImages: Boolean = true,
|
||||
onOpen: (() -> Unit)? = null,
|
||||
) {
|
||||
if (url.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
if (blurred) {
|
||||
Column(
|
||||
modifier = Modifier.padding(vertical = Spacing.s),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||
) {
|
||||
Text(
|
||||
text = LocalXmlStrings.current.messageVideoNsfw,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
Button(
|
||||
onClick = {
|
||||
onOpen?.invoke()
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = LocalXmlStrings.current.buttonLoad,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var shouldBeRendered by remember(autoLoadImages) { mutableStateOf(autoLoadImages) }
|
||||
if (shouldBeRendered) {
|
||||
CustomWebView(
|
||||
modifier = Modifier.aspectRatio(9f / 16f),
|
||||
url = url,
|
||||
)
|
||||
} else {
|
||||
Button(
|
||||
modifier = Modifier.padding(vertical = Spacing.s),
|
||||
onClick = {
|
||||
shouldBeRendered = true
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = LocalXmlStrings.current.buttonLoad,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
@ -21,9 +23,9 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.VideoPlayer
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||
|
||||
@Composable
|
||||
fun PostCardVideo(
|
||||
@ -39,15 +41,14 @@ fun PostCardVideo(
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(1.33f)
|
||||
.onClick(),
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
if (blurred) {
|
||||
Column(
|
||||
modifier = Modifier.padding(vertical = Spacing.s),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||
) {
|
||||
Text(
|
||||
text = LocalXmlStrings.current.messageVideoNsfw,
|
||||
@ -70,7 +71,7 @@ fun PostCardVideo(
|
||||
var loading by remember { mutableStateOf(true) }
|
||||
if (shouldBeRendered) {
|
||||
VideoPlayer(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
modifier = Modifier.aspectRatio(4f / 3f),
|
||||
url = url,
|
||||
onPlaybackStarted = {
|
||||
loading = false
|
||||
@ -89,6 +90,7 @@ fun PostCardVideo(
|
||||
}
|
||||
} else {
|
||||
Button(
|
||||
modifier = Modifier.padding(vertical = Spacing.s),
|
||||
onClick = {
|
||||
shouldBeRendered = true
|
||||
},
|
||||
|
@ -157,14 +157,22 @@ fun Boolean.toInboxDefaultType(): Int = if (this) 0 else 1
|
||||
|
||||
val String.looksLikeAnImage: Boolean
|
||||
get() {
|
||||
val imageExtensions = listOf(".jpeg", ".jpg", ".png", ".webp", ".gif")
|
||||
return imageExtensions.any { this.endsWith(it) }
|
||||
val extensions = listOf(".jpeg", ".jpg", ".png", ".webp", ".gif")
|
||||
return extensions.any { this.endsWith(it) }
|
||||
}
|
||||
|
||||
val String.looksLikeAVideo: Boolean
|
||||
get() {
|
||||
val imageExtensions = listOf(".mp4", ".mov", ".webm", ".avi")
|
||||
return imageExtensions.any { this.endsWith(it) }
|
||||
val extensions = listOf(".mp4", ".mov", ".webm", ".avi")
|
||||
return extensions.any { this.endsWith(it) }
|
||||
}
|
||||
|
||||
val String.showInEmbeddedWebView: Boolean
|
||||
get() {
|
||||
val patterns = listOf(
|
||||
".redgifs.com/",
|
||||
)
|
||||
return patterns.any { this.contains(it) }
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAVideo
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.showInEmbeddedWebView
|
||||
|
||||
data class PostModel(
|
||||
val id: Long = 0,
|
||||
@ -15,7 +16,6 @@ data class PostModel(
|
||||
val unreadComments: Int? = null,
|
||||
val thumbnailUrl: String? = null,
|
||||
val url: String? = null,
|
||||
val embedVideoUrl: String? = null,
|
||||
val community: CommunityModel? = null,
|
||||
val creator: UserModel? = null,
|
||||
val saved: Boolean = false,
|
||||
@ -34,7 +34,11 @@ data class PostModel(
|
||||
)
|
||||
|
||||
val PostModel.imageUrl: String
|
||||
get() = (thumbnailUrl?.takeIf { it.isNotEmpty() } ?: url?.takeIf { it.looksLikeAnImage }).orEmpty()
|
||||
get() = (thumbnailUrl?.takeIf { it.isNotEmpty() }
|
||||
?: url?.takeIf { it.looksLikeAnImage }).orEmpty()
|
||||
|
||||
val PostModel.videoUrl: String
|
||||
get() = url?.takeIf { it.looksLikeAVideo }?.takeIf { it.isNotEmpty() }.orEmpty()
|
||||
|
||||
val PostModel.embeddedUrl: String
|
||||
get() = url?.takeIf { it.showInEmbeddedWebView }?.takeIf { it.isNotEmpty() }.orEmpty()
|
@ -199,7 +199,6 @@ internal fun Post.toModel() = PostModel(
|
||||
publishDate = published,
|
||||
updateDate = updated,
|
||||
nsfw = nsfw,
|
||||
embedVideoUrl = embedVideoUrl,
|
||||
featuredCommunity = featuredCommunity,
|
||||
featuredLocal = featuredLocal,
|
||||
removed = removed,
|
||||
|
Loading…
x
Reference in New Issue
Block a user