Skip to content

Commit

Permalink
Enhance image previewer
Browse files Browse the repository at this point in the history
  • Loading branch information
ismartcoding committed May 19, 2024
1 parent 21eb950 commit 1b9d2b6
Show file tree
Hide file tree
Showing 44 changed files with 319 additions and 164 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ android {
else -> 0
}

val vCode = 283
val vCode = 286
versionCode = vCode - singleAbiNum
versionName = "1.2.50"
versionName = "1.2.51"

ndk {
//noinspection ChromeOsAbiSupport
Expand Down
22 changes: 15 additions & 7 deletions app/src/main/java/com/ismartcoding/plain/helpers/VideoHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@ import android.content.Context
import android.media.MediaMetadataRetriever
import android.net.Uri
import androidx.compose.ui.unit.IntSize
import com.ismartcoding.lib.logcat.LogCat
import java.io.File

object VideoHelper {
fun getIntrinsicSize(context: Context, path: String): IntSize {
val file = File(path)
val retriever = MediaMetadataRetriever()
retriever.setDataSource(context, Uri.fromFile(file))
val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0
val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0
retriever.release()
return IntSize(width, height)
try {
val file = File(path)
val retriever = MediaMetadataRetriever()
retriever.setDataSource(context, Uri.fromFile(file))
val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0
val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0
retriever.release()
return IntSize(width, height)
} catch (ex: Exception) {
LogCat.e(ex.toString())
ex.printStackTrace()
}

return IntSize.Zero
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
Expand All @@ -13,11 +14,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp


@Composable
fun PMiniOutlineButton(
text: String,
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colorScheme.primary,
onClick: () -> Unit,
) {
Button(
Expand All @@ -27,12 +28,11 @@ fun PMiniOutlineButton(
.height(32.dp),
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 0.dp),
shape = RoundedCornerShape(8.dp),
colors =
ButtonDefaults.buttonColors(
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = MaterialTheme.colorScheme.primary,
contentColor = color,
),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary),
border = BorderStroke(1.dp, color),
) {
Text(text, style = MaterialTheme.typography.labelSmall)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fun newImageLoader(context: PlatformContext): ImageLoader {
val memoryPercent = if (activityManager.isLowRamDevice) 0.25 else 0.75
return ImageLoader.Builder(context)
.components {
add(SvgDecoder.Factory(false))
add(SvgDecoder.Factory(true))
add(AnimatedImageDecoder.Factory())
add(ThumbnailDecoder.Factory())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class CoilImagesPlugin internal constructor(coilStore: CoilStore, imageLoader: I

override fun load(drawable: AsyncDrawable) {
val loaded = AtomicBoolean(false)
val target: Target = AsyncDrawableTarget(drawable, loaded)
val request: ImageRequest = coilStore.load(drawable).newBuilder()
val target = AsyncDrawableTarget(drawable, loaded)
val request = coilStore.load(drawable).newBuilder()
.target(target)
.build()
// @since 4.5.1 execute can return result _before_ disposable is created,
Expand All @@ -75,15 +75,7 @@ class CoilImagesPlugin internal constructor(coilStore: CoilStore, imageLoader: I
return null
}

private inner class AsyncDrawableTarget(drawable: AsyncDrawable, loaded: AtomicBoolean) : Target {
private val drawable: AsyncDrawable
private val loaded: AtomicBoolean

init {
this.drawable = drawable
this.loaded = loaded
}

private inner class AsyncDrawableTarget(val drawable: AsyncDrawable,val loaded: AtomicBoolean) : Target {
fun onSuccess(loadedDrawable: Drawable) {
// @since 4.5.1 check finished flag (result can be delivered _before_ disposable is created)
if (cache.remove(drawable) != null
Expand Down Expand Up @@ -121,7 +113,7 @@ class CoilImagesPlugin internal constructor(coilStore: CoilStore, imageLoader: I
context: Context,
imageLoader: ImageLoader
): CoilImagesPlugin {
return create(object : CoilStore {
return CoilImagesPlugin(object : CoilStore {
override fun load(drawable: AsyncDrawable): ImageRequest {
return ImageRequest.Builder(context)
.data(drawable.destination)
Expand All @@ -133,12 +125,5 @@ class CoilImagesPlugin internal constructor(coilStore: CoilStore, imageLoader: I
}
}, imageLoader)
}

fun create(
coilStore: CoilStore,
imageLoader: ImageLoader
): CoilImagesPlugin {
return CoilImagesPlugin(coilStore, imageLoader)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.ismartcoding.lib.channel.sendEvent
import com.ismartcoding.lib.helpers.CoroutinesHelper
import com.ismartcoding.lib.helpers.CoroutinesHelper.coIO
import com.ismartcoding.lib.helpers.CoroutinesHelper.withIO
import com.ismartcoding.plain.R
import com.ismartcoding.plain.TempData
import com.ismartcoding.plain.features.StartHttpServerEvent
Expand Down Expand Up @@ -53,7 +50,7 @@ fun CastDialog(viewModel: CastViewModel) {
scope.launch(Dispatchers.IO) {
viewModel.searchAsync(context)
}
coIO {
scope.launch(Dispatchers.IO) {
delay(5000)
if (itemsState.isEmpty()) {
loadingTextId = R.string.no_devices_found
Expand All @@ -77,7 +74,7 @@ fun CastDialog(viewModel: CastViewModel) {
viewModel.selectDevice(m)
viewModel.enterCastMode()
scope.launch(Dispatchers.IO) {
if(!TempData.webEnabled) {
if (!TempData.webEnabled) {
WebPreference.putAsync(context, true)
sendEvent(StartHttpServerEvent())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ fun ChatListItem(
) {
when (m.type) {
DMessageType.IMAGES.value -> {
ChatImages(context, m, imageWidthDp, previewerState)
ChatImages(context, items, m, imageWidthDp, previewerState)
}

DMessageType.FILES.value -> {
ChatFiles(context, navController, m, previewerState)
ChatFiles(context, items, navController, m, previewerState)
}

DMessageType.TEXT.value -> {
Expand Down Expand Up @@ -140,7 +140,7 @@ fun ChatListItem(
onDismissRequest = {
viewModel.selectedItem.value = null
showContextMenu.value = false
},
},
) {
PDropdownMenuItem(
text = { Text(stringResource(id = R.string.select)) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.PlayCircleOutline
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -116,6 +120,23 @@ fun ImageGridItem(
.background(MaterialTheme.colorScheme.lightMask())
.aspectRatio(1f)
)
} else if (castViewModel.castMode.value) {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.darkMask())
.aspectRatio(1f)
) {
Icon(
modifier =
Modifier
.align(Alignment.Center)
.size(48.dp),
imageVector = Icons.Outlined.PlayCircleOutline,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurface
)
}
}

if (inSelectionMode) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.ismartcoding.plain.ui.components.chat

import android.content.Context
import androidx.activity.ComponentActivity
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -16,7 +15,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
Expand Down Expand Up @@ -55,12 +53,12 @@ import java.io.File
@Composable
fun ChatFiles(
context: Context,
items: List<VChat>,
navController: NavHostController,
m: VChat,
previewerState: MediaPreviewerState,
) {
val fileItems = (m.value as DMessageFiles).items
val context = LocalContext.current as ComponentActivity
val keyboardController = LocalSoftwareKeyboardController.current
Column {
fileItems.forEachIndexed { index, item ->
Expand All @@ -74,12 +72,7 @@ fun ChatFiles(
if (path.isImageFast() || path.isVideoFast()) {
coMain {
keyboardController?.hide()
withIO {
MediaPreviewData.setDataAsync(
context, itemState, fileItems
.filter { it.uri.isVideoFast() || it.uri.isImageFast() }, item
)
}
withIO { MediaPreviewData.setDataAsync(context, itemState, items.reversed(), item) }
previewerState.openTransform(
index = MediaPreviewData.items.indexOfFirst { it.id == item.id },
itemState = itemState,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.ismartcoding.plain.ui.components.chat

import android.content.Context
import androidx.activity.ComponentActivity
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
Expand All @@ -19,7 +18,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
Expand All @@ -39,12 +37,12 @@ import com.ismartcoding.plain.ui.models.VChat
@Composable
fun ChatImages(
context: Context,
items: List<VChat>,
m: VChat,
imageWidthDp: Dp,
previewerState: MediaPreviewerState,
) {
val imageItems = (m.value as DMessageImages).items
val context = LocalContext.current as ComponentActivity
val keyboardController = LocalSoftwareKeyboardController.current

FlowRow(
Expand All @@ -63,7 +61,7 @@ fun ChatImages(
Modifier.clickable {
coMain {
keyboardController?.hide()
withIO { MediaPreviewData.setDataAsync(context, itemState, imageItems, item) }
withIO { MediaPreviewData.setDataAsync(context, itemState, items.reversed(), item) }
previewerState.openTransform(
index = MediaPreviewData.items.indexOfFirst { it.id == item.id },
itemState = itemState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import com.ismartcoding.lib.extensions.isUrl
import com.ismartcoding.lib.extensions.isVideoFast
import com.ismartcoding.lib.logcat.LogCat
import com.ismartcoding.plain.enums.ImageType
Expand Down Expand Up @@ -100,7 +101,7 @@ fun MediaGallery(
key(page) {
val item = getItem(page)
val model: Any?
if (item.path.isVideoFast()) {
if (item.path.isVideoFast() || item.path.isUrl()) {
model = item
} else if (item.size <= 2000 * 1000) {
// If the image size is less than 2MB, load the image directly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import androidx.compose.ui.unit.IntSize
import androidx.media3.common.util.UnstableApi
import coil3.compose.AsyncImage
import coil3.imageLoader
import com.ismartcoding.lib.extensions.isUrl
import com.ismartcoding.plain.ui.components.mediaviewer.previewer.DEFAULT_CROSS_FADE_ANIMATE_SPEC
import com.ismartcoding.plain.ui.preview.PreviewItem
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -151,7 +152,7 @@ fun MediaNormalImage(
var painter by remember {
mutableStateOf<Painter?>(null)
}
if (model.isWebUrl()) {
if (model.path.isUrl()) {
painter = rememberCoilImagePainter(model.path)
var isMounted by remember { mutableStateOf(false) }
imageSpecified = painter!!.intrinsicSize.isSpecified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.compose.ui.input.pointer.util.VelocityTracker
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastForEach
import com.ismartcoding.lib.extensions.isUrl
import com.ismartcoding.lib.extensions.isVideoFast
import com.ismartcoding.lib.logcat.LogCat
import com.ismartcoding.plain.ui.components.mediaviewer.hugeimage.ImageDecoder
Expand Down Expand Up @@ -499,7 +500,7 @@ fun MediaViewer(
state.scale.snapTo(desScale)
state.offsetX.snapTo(desX)
state.offsetY.snapTo(desY)
state.rotation.snapTo(desRotation)
// state.rotation.snapTo(desRotation)
}

// 这里判断是否已运动到边界,如果到了边界,就不消费事件,让上层界面获取到事件
Expand Down Expand Up @@ -539,13 +540,11 @@ fun MediaViewer(
state.mountedFlow.emit(true)
}
}
/**
* 根据不同类型的model进行不同的渲染
*/

when (model) {
is PreviewItem,
-> {
if (model.path.isVideoFast() && !model.isWebUrl()) {
if (model.path.isVideoFast() && !model.path.isUrl()) {
MediaVideo(
pagerState = pagerState,
page = page,
Expand Down
Loading

0 comments on commit 1b9d2b6

Please sign in to comment.