From 87cdc54441035ba1d7617af9313e3b576f8eef92 Mon Sep 17 00:00:00 2001 From: Yuichiro Kinoshita Date: Mon, 9 Oct 2023 17:05:03 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=82=B5=E3=83=A0=E3=83=8D=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E3=81=8C=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=81=BE=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../milktea/media/ImageFragment.kt | 41 ++++++++++--------- .../milktea/media/ImageViewModel.kt | 33 +++++++++++---- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageFragment.kt b/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageFragment.kt index fbd6a799e3..fe3fe38b15 100644 --- a/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageFragment.kt +++ b/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageFragment.kt @@ -14,30 +14,29 @@ import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target import com.wada811.databinding.dataBinding -import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import net.pantasystem.milktea.common.glide.GlideApp import net.pantasystem.milktea.media.databinding.FragmentImageBinding -class ImageFragment : Fragment(R.layout.fragment_image){ +class ImageFragment : Fragment(R.layout.fragment_image) { - companion object{ + companion object { private const val EXTRA_INDEX = "jp.panta.misskeyandroidclient.ui.media.EXTRA_INDEX" - fun newInstance(index: Int, url: String): ImageFragment { - val bundle = Bundle().apply{ + fun newInstance(index: Int, url: String, thumbnailUrl: String? = null): ImageFragment { + val bundle = Bundle().apply { putString(ImageViewModel.EXTRA_IMAGE_URL, url) putInt(EXTRA_INDEX, index) + putString(ImageViewModel.EXTRA_IMAGE_THUMBNAIL_URL, thumbnailUrl) } - return ImageFragment().apply{ + return ImageFragment().apply { arguments = bundle } } fun newInstance(index: Int, uri: Uri): ImageFragment { - return ImageFragment().apply{ - arguments = Bundle().apply{ + return ImageFragment().apply { + arguments = Bundle().apply { putString(ImageViewModel.EXTRA_IMAGE_URI, uri.toString()) putInt(EXTRA_INDEX, index) } @@ -45,7 +44,7 @@ class ImageFragment : Fragment(R.layout.fragment_image){ } fun newInstance(index: Int, file: File): ImageFragment { - return newInstance(index, file.path!!) + return newInstance(index, file.path!!, file.thumbnailUrl) } } @@ -57,18 +56,16 @@ class ImageFragment : Fragment(R.layout.fragment_image){ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - index = arguments?.getInt(EXTRA_INDEX)?: 0 + index = arguments?.getInt(EXTRA_INDEX) ?: 0 binding.swipeFinishLayout.setOnFinishEventListener { requireActivity().finish() } - viewModel.uiState.map { - it.uri ?: it.url - }.distinctUntilChanged().onEach { url -> + viewModel.uiState.onEach { uiState -> GlideApp.with(view) - .load(url) + .load(uiState.uri) .addListener(object : RequestListener { override fun onLoadFailed( e: GlideException?, @@ -91,12 +88,18 @@ class ImageFragment : Fragment(R.layout.fragment_image){ return false } }) + .let { + if (uiState.thumbnailUrl != null && uiState.uri != uiState.thumbnailUrl) + it.thumbnail( + GlideApp.with(view).load(uiState.thumbnailUrl) + ) + else + it + } .into(binding.imageView) }.flowWithLifecycle(lifecycle).launchIn(lifecycleScope) - viewModel.uiState.map { - it.isLoading - }.distinctUntilChanged().onEach { + viewModel.isImageLoading.onEach { binding.progressBar.isVisible = it }.flowWithLifecycle(lifecycle).launchIn(lifecycleScope) } @@ -105,7 +108,7 @@ class ImageFragment : Fragment(R.layout.fragment_image){ super.onResume() val activity = requireActivity() - if(activity is MediaActivity){ + if (activity is MediaActivity) { activity.setCurrentFileIndex(index) } diff --git a/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageViewModel.kt b/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageViewModel.kt index a32b1cf37b..6d25db4314 100644 --- a/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageViewModel.kt +++ b/modules/features/media/src/main/java/net/pantasystem/milktea/media/ImageViewModel.kt @@ -2,9 +2,13 @@ package net.pantasystem.milktea.media import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -15,6 +19,7 @@ class ImageViewModel @Inject constructor( companion object { const val EXTRA_IMAGE_URL = "jp.panta.misskeyandroidclient.ui.media.EXTRA_IMAGE_URL" const val EXTRA_IMAGE_URI = "jp.panta.misskeyandroidclient.ui.media.EXTRA_IMAGE_URI" + const val EXTRA_IMAGE_THUMBNAIL_URL = "jp.panta.misskeyandroidclient.ui.media.EXTRA_IMAGE_THUMBNAIL_URL" } private val url = savedStateHandle.getStateFlow( @@ -27,27 +32,37 @@ class ImageViewModel @Inject constructor( null, ) - private val isImageLoading = MutableStateFlow(true) + private val thumbnailUrl = savedStateHandle.getStateFlow( + EXTRA_IMAGE_THUMBNAIL_URL, + null, + ) + + private val _isImageLoading = MutableStateFlow(true) + val isImageLoading = _isImageLoading.asStateFlow() - val uiState = combine(url, uri, isImageLoading) { url, uri, loading -> + val uiState = combine(url, uri, thumbnailUrl) { url, uri, thumbnail -> ImageUiState( - url = url, - uri = uri, - isLoading = loading, + uri = url ?: uri, + thumbnailUrl = thumbnail, ) } fun onResourceReady() { - isImageLoading.value = false + viewModelScope.launch { + delay(100) + _isImageLoading.value = false + } } fun onLoadFailed() { - isImageLoading.value = false + viewModelScope.launch { + delay(100) + _isImageLoading.value = false + } } } data class ImageUiState( val uri: String?, - val url: String?, - val isLoading: Boolean = false, + val thumbnailUrl: String?, ) \ No newline at end of file