Media: use telephoto library
This commit is contained in:
parent
81a80a1a8a
commit
d36bc58e60
5 changed files with 11 additions and 128 deletions
|
|
@ -54,6 +54,8 @@ dependencies {
|
||||||
implementation(libs.androidx.media3.exoplayer)
|
implementation(libs.androidx.media3.exoplayer)
|
||||||
implementation(libs.androidx.media3.ui)
|
implementation(libs.androidx.media3.ui)
|
||||||
implementation(libs.accompanist.systemui)
|
implementation(libs.accompanist.systemui)
|
||||||
|
implementation(libs.vanniktech.blurhash)
|
||||||
|
implementation(libs.telephoto.zoomableimage)
|
||||||
|
|
||||||
testImplementation(libs.test.junit)
|
testImplementation(libs.test.junit)
|
||||||
testImplementation(libs.coroutines.test)
|
testImplementation(libs.coroutines.test)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
@ -36,9 +35,8 @@ import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.ui.AspectRatioFrameLayout
|
import androidx.media3.ui.AspectRatioFrameLayout
|
||||||
import androidx.media3.ui.PlayerView
|
import androidx.media3.ui.PlayerView
|
||||||
import coil.compose.AsyncImage
|
|
||||||
import io.element.android.libraries.designsystem.components.ZoomableBox
|
|
||||||
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
|
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
|
||||||
|
import me.saket.telephoto.zoomable.coil.ZoomableAsyncImage
|
||||||
|
|
||||||
@SuppressLint("UnsafeOptInUsageError")
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -64,19 +62,12 @@ private fun MediaImageView(
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
ZoomableBox(
|
ZoomableAsyncImage(
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.Center,
|
model = uri,
|
||||||
) {
|
contentDescription = "Image",
|
||||||
AsyncImage(
|
contentScale = ContentScale.Fit,
|
||||||
modifier = Modifier
|
)
|
||||||
.zoomable()
|
|
||||||
.fillMaxSize(),
|
|
||||||
model = uri,
|
|
||||||
contentDescription = "Image",
|
|
||||||
contentScale = ContentScale.Fit,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ appyx = "1.2.0"
|
||||||
dependencycheck = "8.2.1"
|
dependencycheck = "8.2.1"
|
||||||
stem = "2.3.0"
|
stem = "2.3.0"
|
||||||
sqldelight = "1.5.5"
|
sqldelight = "1.5.5"
|
||||||
|
telephoto = "0.3.0"
|
||||||
|
|
||||||
# DI
|
# DI
|
||||||
dagger = "2.46.1"
|
dagger = "2.46.1"
|
||||||
|
|
@ -142,6 +143,7 @@ unifiedpush = "com.github.UnifiedPush:android-connector:2.1.1"
|
||||||
gujun_span = "me.gujun.android:span:1.7"
|
gujun_span = "me.gujun.android:span:1.7"
|
||||||
otaliastudios_transcoder = "com.otaliastudios:transcoder:0.10.5"
|
otaliastudios_transcoder = "com.otaliastudios:transcoder:0.10.5"
|
||||||
vanniktech_blurhash = "com.vanniktech:blurhash:0.1.0"
|
vanniktech_blurhash = "com.vanniktech:blurhash:0.1.0"
|
||||||
|
telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" }
|
||||||
|
|
||||||
# Di
|
# Di
|
||||||
inject = "javax.inject:javax.inject:1"
|
inject = "javax.inject:javax.inject:1"
|
||||||
|
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.libraries.designsystem.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
|
||||||
import androidx.compose.foundation.gestures.detectTransformGestures
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
|
||||||
import androidx.compose.foundation.layout.LayoutScopeMarker
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import androidx.compose.runtime.Stable
|
|
||||||
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.draw.clip
|
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
|
||||||
import androidx.compose.ui.unit.IntSize
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ZoomableBox(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
contentAlignment: Alignment = Alignment.TopStart,
|
|
||||||
minZoom: Float = 1f,
|
|
||||||
maxZoom: Float = 5f,
|
|
||||||
content: @Composable ZoomableBoxScope.() -> Unit
|
|
||||||
) {
|
|
||||||
var zoom by remember { mutableStateOf(minZoom) }
|
|
||||||
var offsetX by remember { mutableStateOf(0f) }
|
|
||||||
var offsetY by remember { mutableStateOf(0f) }
|
|
||||||
var size by remember { mutableStateOf(IntSize.Zero) }
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = modifier
|
|
||||||
.clip(RectangleShape)
|
|
||||||
.onSizeChanged {
|
|
||||||
size = it
|
|
||||||
}
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectTransformGestures { _, panChange, zoomChange, _ ->
|
|
||||||
zoom = (zoom * zoomChange).coerceIn(minZoom, maxZoom)
|
|
||||||
val maxX = (size.width * (zoom - 1)) / 2f
|
|
||||||
val minX = -maxX
|
|
||||||
val maxY = (size.height * (zoom - 1)) / 2f
|
|
||||||
val minY = -maxY
|
|
||||||
offsetX = maxOf(minX, minOf(maxX, offsetX + panChange.x))
|
|
||||||
offsetY = maxOf(minY, minOf(maxY, offsetY + panChange.y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectTapGestures(
|
|
||||||
onDoubleTap = {
|
|
||||||
offsetX = 0f
|
|
||||||
offsetY = 0f
|
|
||||||
zoom = if (zoom > minZoom) {
|
|
||||||
minZoom
|
|
||||||
} else {
|
|
||||||
maxZoom / 2f
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
contentAlignment = contentAlignment,
|
|
||||||
) {
|
|
||||||
DefaultZoomableBoxScope(this, zoom, offsetX, offsetY).content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@LayoutScopeMarker
|
|
||||||
@Immutable
|
|
||||||
interface ZoomableBoxScope : BoxScope {
|
|
||||||
@Stable
|
|
||||||
fun Modifier.zoomable(): Modifier
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DefaultZoomableBoxScope(
|
|
||||||
private val parentScope: BoxScope,
|
|
||||||
private val scale: Float,
|
|
||||||
private val offsetX: Float,
|
|
||||||
private val offsetY: Float
|
|
||||||
) : ZoomableBoxScope, BoxScope by parentScope {
|
|
||||||
|
|
||||||
override fun Modifier.zoomable() = this.then(
|
|
||||||
graphicsLayer(
|
|
||||||
scaleX = scale,
|
|
||||||
scaleY = scale,
|
|
||||||
translationX = offsetX,
|
|
||||||
translationY = offsetY,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -23,7 +23,7 @@ object Versions {
|
||||||
|
|
||||||
const val compileSdk = 33
|
const val compileSdk = 33
|
||||||
const val targetSdk = 33
|
const val targetSdk = 33
|
||||||
const val minSdk = 23
|
const val minSdk = 24
|
||||||
val javaCompileVersion = JavaVersion.VERSION_17
|
val javaCompileVersion = JavaVersion.VERSION_17
|
||||||
val javaLanguageVersion: JavaLanguageVersion = JavaLanguageVersion.of(11)
|
val javaLanguageVersion: JavaLanguageVersion = JavaLanguageVersion.of(11)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue