Skip to content

Commit

Permalink
Merge pull request #9 from mehdiyari/development
Browse files Browse the repository at this point in the history
Version 0.9.1
  • Loading branch information
mehdiyari committed Aug 12, 2020
2 parents d6fed93 + d4b336d commit f66650a
Show file tree
Hide file tree
Showing 41 changed files with 209 additions and 235 deletions.
4 changes: 2 additions & 2 deletions fallery/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.google.android.material:material:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
Expand Down
3 changes: 2 additions & 1 deletion fallery/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
android:requestLegacyExternalStorage="true">
android:requestLegacyExternalStorage="true"
android:supportsRtl="true">
<activity
android:windowSoftInputMode="adjustResize"
android:name=".main.ui.FalleryActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ import ir.mehdiyari.fallery.main.di.FalleryActivityComponentHolder
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.InternalCoroutinesApi

@OptIn(ExperimentalCoroutinesApi::class, InternalCoroutinesApi::class)
class BaseBucketContentFragment : Fragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.fragment_base_bucket_content, container, false)

@ExperimentalCoroutinesApi
@InternalCoroutinesApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViewModel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,23 @@ import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean


@OptIn(ExperimentalCoroutinesApi::class)
internal class BucketContentViewModel constructor(
private val abstractBucketContentProvider: AbstractBucketContentProvider,
private val bucketType: BucketType,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : BaseViewModel() {

@ExperimentalCoroutinesApi
private val medias = MutableStateFlow<List<Media>>(listOf())

@ExperimentalCoroutinesApi
val mediaList: StateFlow<List<Media>> = medias

val showPreviewFragmentLiveData = SingleLiveEvent<String>()

@ExperimentalCoroutinesApi
private val loadingMutableStateFlow = MutableStateFlow<LoadingViewState?>(null)

@ExperimentalCoroutinesApi
val loadingViewStateFlow: StateFlow<LoadingViewState?> = loadingMutableStateFlow

@ExperimentalCoroutinesApi
fun getMedias(bucketId: Long, refresh: Boolean = false) {
if (!refresh && mediaList.value.isNotEmpty()) return
val clearList = AtomicBoolean(refresh)
Expand Down Expand Up @@ -66,10 +61,8 @@ internal class BucketContentViewModel constructor(
showPreviewFragmentLiveData.value = path
}

@ExperimentalCoroutinesApi
fun getIndexOfPath(path: String): Int = mediaList.value.indexOfFirst { it.getMediaPath() == path.trim() }

@ExperimentalCoroutinesApi
fun getMediaPathByPosition(position: Int): String? = mediaList.value.getOrNull(position)?.getMediaPath()

fun retry(bucketId: Long) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ class BucketContentAdapter constructor(

private fun initSelectingStateOfView(adapterPosition: Int) {
if (selectedMediaTracker?.contains(getItemPath(adapterPosition)) == true)
itemView.imageViewSelectDeselectPhoto.background = selectedDrawable
itemView.imageViewSelectDeselectPhoto.setImageDrawable(selectedDrawable)
else
itemView.imageViewSelectDeselectPhoto.background = deselectedDrawable
itemView.imageViewSelectDeselectPhoto.setImageDrawable(deselectedDrawable)
}

}
Expand Down Expand Up @@ -149,9 +149,9 @@ class BucketContentAdapter constructor(

private fun initSelectingStateOfView(adapterPosition: Int) {
if (selectedMediaTracker?.contains(getItemPath(adapterPosition)) == true)
itemView.imageViewSelectDeselectVideo.background = selectedDrawable
itemView.imageViewSelectDeselectVideo.setImageDrawable(selectedDrawable)
else
itemView.imageViewSelectDeselectVideo.background = deselectedDrawable
itemView.imageViewSelectDeselectVideo.setImageDrawable(deselectedDrawable)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

@ExperimentalCoroutinesApi
@OptIn(ExperimentalCoroutinesApi::class)
class BucketContentFragment : Fragment() {

private lateinit var bucketContentViewModel: BucketContentViewModel
Expand Down Expand Up @@ -77,7 +77,7 @@ class BucketContentFragment : Fragment() {
requireParentFragment(),
FalleryActivityComponentHolder.getOrNull()!!.provideBucketContentViewModelFactory()
)[BucketContentViewModel::class.java].apply {
lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
loadingViewStateFlow.collect {
when (it) {
is LoadingViewState.ShowLoading -> showLoading()
Expand Down Expand Up @@ -107,7 +107,7 @@ class BucketContentFragment : Fragment() {
})
}

lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
launch {
bucketContentViewModel.mediaList.collect {
bucketContentAdapter.submitList(it)
Expand Down Expand Up @@ -141,4 +141,9 @@ class BucketContentFragment : Fragment() {
recyclerViewBucketContent.visibility = View.VISIBLE
contentLoadingProgressBarBucketContent.hide()
}

override fun onDestroyView() {
recyclerViewBucketContent.adapter = null
super.onDestroyView()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package ir.mehdiyari.fallery.buckets.bucketContent.preview

import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.animation.TranslateAnimation
import androidx.fragment.app.Fragment
Expand All @@ -25,11 +23,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

internal class PreviewFragment : Fragment(), View.OnClickListener {
@OptIn(ExperimentalCoroutinesApi::class)
internal class PreviewFragment : Fragment(R.layout.fragment_preview), View.OnClickListener {

private lateinit var bucketContentViewModel: BucketContentViewModel

@ExperimentalCoroutinesApi
private lateinit var falleryViewModel: FalleryViewModel

private val mediaPreviewAdapter by lazy {
Expand All @@ -46,12 +44,12 @@ internal class PreviewFragment : Fragment(), View.OnClickListener {
FalleryActivityComponentHolder.createOrGetComponent(requireActivity()).provideDeselectedDrawable()
}

@ExperimentalCoroutinesApi
private val pageSelectedCallback by lazy {
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
showToolbarWithAnimation()
checkForSelection(position)
saveCurrentPosition(position)
}
}
}
Expand All @@ -60,32 +58,32 @@ internal class PreviewFragment : Fragment(), View.OnClickListener {
requireActivity() as FalleryToolbarVisibilityController
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.fragment_preview, container, false)

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
requireActivity().window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
falleryToolbarVisibilityController.hideToolbar(false)
}

private fun saveCurrentPosition(position: Int) {
arguments?.putString(
"from_media_path",
bucketContentViewModel.getMediaPathByPosition(position)
)
}

@ExperimentalCoroutinesApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViewModel()
initView()
}

@ExperimentalCoroutinesApi
override fun onStart() {
super.onStart()
viewPagerMediaPreview.registerOnPageChangeCallback(pageSelectedCallback)
if (viewPagerMediaPreview.adapter == null)
viewPagerMediaPreview.adapter = mediaPreviewAdapter
}

@ExperimentalCoroutinesApi
private fun initView() {
FalleryActivityComponentHolder.createOrGetComponent(requireActivity()).provideFalleryOptions().apply {
viewPagerMediaPreview.orientation = mediaPreviewScrollOrientation
Expand All @@ -107,21 +105,19 @@ internal class PreviewFragment : Fragment(), View.OnClickListener {
imageViewBackButton.setOnClickListener { requireActivity().onBackPressed() }
}

@ExperimentalCoroutinesApi
private fun checkForSelection(position: Int) {
appCompatImageButtonMediaSelect.background = bucketContentViewModel.getMediaPathByPosition(position).let {
appCompatImageButtonMediaSelect.setImageDrawable(bucketContentViewModel.getMediaPathByPosition(position).let {
if (it != null && falleryViewModel.isPhotoSelected(it)) selectedDrawable else deselectDrawable
}
})
}

@ExperimentalCoroutinesApi
private fun initViewModel() {
falleryViewModel = ViewModelProvider(
requireActivity(),
FalleryActivityComponentHolder.createOrGetComponent(requireActivity()).provideFalleryViewModelFactory()
)[FalleryViewModel::class.java].apply {
hideSendOrCaptionLayout()
lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
mediaCountStateFlow.collect { setupMediaCountView(it) }
}
}
Expand All @@ -131,15 +127,14 @@ internal class PreviewFragment : Fragment(), View.OnClickListener {
FalleryActivityComponentHolder.createOrGetComponent(requireActivity()).provideBucketContentViewModelFactory()
)[BucketContentViewModel::class.java]

lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
bucketContentViewModel.mediaList.collect {
if (viewPagerMediaPreview == null)
viewPagerMediaPreview.adapter = mediaPreviewAdapter

mediaPreviewAdapter.medias = it
arguments?.getString("from_media_path", null).also { path ->
if (path != null) {
arguments?.remove("from_media_path")
viewPagerMediaPreview.post {
viewPagerMediaPreview.setCurrentItem(bucketContentViewModel.getIndexOfPath(path).apply(this@PreviewFragment::checkForSelection), false)
}
Expand Down Expand Up @@ -189,18 +184,17 @@ internal class PreviewFragment : Fragment(), View.OnClickListener {
}


@ExperimentalCoroutinesApi
override fun onStop() {
viewPagerMediaPreview.unregisterOnPageChangeCallback(pageSelectedCallback)
viewPagerMediaPreview.adapter = null
super.onStop()
}

@ExperimentalCoroutinesApi
override fun onDestroyView() {
requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
falleryViewModel.showSendOrCaptionLayout()
falleryToolbarVisibilityController.showToolbar(false)
viewPagerMediaPreview.adapter = null
super.onDestroyView()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.Manifest
import android.os.Build
import android.os.Bundle
import android.transition.TransitionManager
import android.util.DisplayMetrics
import android.util.Log
import android.view.LayoutInflater
import android.view.View
Expand All @@ -27,7 +26,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

@ExperimentalCoroutinesApi
@OptIn(ExperimentalCoroutinesApi::class)
internal class BucketListFragment : Fragment() {

private lateinit var bucketListViewModel: BucketListViewModel
Expand Down Expand Up @@ -65,8 +64,7 @@ internal class BucketListFragment : Fragment() {
getImageViewWidth = {
if (recyclerViewBuckets.layoutManager is GridLayoutManager) {
(recyclerViewBuckets.layoutManager as GridLayoutManager).let { gridLayoutManager ->
val displayMetric = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getRealMetrics(displayMetric)
val displayMetric = requireActivity().resources.displayMetrics
(((displayMetric.widthPixels - dpToPx(3) * (gridLayoutManager.spanCount - 1)) / gridLayoutManager.spanCount) * 0.5).toInt()
}
} else {
Expand All @@ -91,7 +89,7 @@ internal class BucketListFragment : Fragment() {
FalleryActivityComponentHolder.componentCreator(requireActivity()).provideBucketListViewModelFactory()
)[BucketListViewModel::class.java]

lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
launch {
falleryViewModel.storagePermissionGrantedStateFlow.collect {
if (it == true) {
Expand All @@ -117,7 +115,7 @@ internal class BucketListFragment : Fragment() {
}

bucketListViewModel.apply {
lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
loadingViewStateFlow.collect {
when (it) {
is LoadingViewState.Error -> showErrorLayout()
Expand All @@ -127,7 +125,7 @@ internal class BucketListFragment : Fragment() {
}
}

lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
launch { allMediaCountChanged.collect { falleryViewModel.totalMediaCount = it } }
bucketsStateFlow.collect { bucketAdapter.submitList(it) }
}
Expand Down Expand Up @@ -189,4 +187,9 @@ internal class BucketListFragment : Fragment() {
minCount = 2
)
} else 1

override fun onDestroyView() {
recyclerViewBuckets.adapter = null
super.onDestroyView()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,30 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

@OptIn(ExperimentalCoroutinesApi::class)
internal class BucketListViewModel constructor(
private val abstractMediaBucketProvider: AbstractMediaBucketProvider,
private val bucketType: BucketType = BucketType.VIDEO_PHOTO_BUCKETS,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : BaseViewModel() {

@ExperimentalCoroutinesApi
private val bucketsMutableStateFlow = MutableStateFlow<List<MediaBucket>>(listOf())

@ExperimentalCoroutinesApi
private val allMediaCountChangedStateFlow = MutableStateFlow(0)

@ExperimentalCoroutinesApi
val allMediaCountChanged: StateFlow<Int> = allMediaCountChangedStateFlow

@ExperimentalCoroutinesApi
val bucketsStateFlow: StateFlow<List<MediaBucket>> = this.bucketsMutableStateFlow

@ExperimentalCoroutinesApi
private val loadingMutableStateFlow = MutableStateFlow<LoadingViewState?>(null)

@ExperimentalCoroutinesApi
val loadingViewStateFlow: StateFlow<LoadingViewState?> = loadingMutableStateFlow


fun getBucketNameById(id: Long): String = bucketsStateFlow.value.firstOrNull {
id == it.id
}?.displayName ?: "Unknown"

@ExperimentalCoroutinesApi
fun getBuckets(refresh: Boolean = false) {
if (!refresh && bucketsStateFlow.value.isNotEmpty() || loadingViewStateFlow.value == LoadingViewState.ShowLoading) return
loadingMutableStateFlow.value = LoadingViewState.ShowLoading
Expand All @@ -66,7 +60,6 @@ internal class BucketListViewModel constructor(
}
}

@ExperimentalCoroutinesApi
fun retry() {
getBuckets(true)
}
Expand Down
Loading

0 comments on commit f66650a

Please sign in to comment.