Issue#7 Fix order of videos

Show the Pending Videos in the order they will be downloaded in
This commit is contained in:
Gergely Hegedus 2022-04-21 20:37:32 +03:00
parent ca2cca9944
commit 8d709206fd
6 changed files with 16 additions and 15 deletions

View file

@ -36,6 +36,7 @@ android {
buildTypes { buildTypes {
debug { debug {
versionNameSuffix "-dev" versionNameSuffix "-dev"
applicationIdSuffix ".debug"
debuggable true debuggable true
shrinkResources false shrinkResources false
minifyEnabled false minifyEnabled false

View file

@ -16,7 +16,7 @@ class VideoInPendingLocalSource(
get() = sharedPreferencesManager.pendingVideosFlow get() = sharedPreferencesManager.pendingVideosFlow
.map { stringSet -> .map { stringSet ->
stringSet.asSequence().map { timeThenUrl -> timeThenUrl.getTimeAndOriginal() } stringSet.asSequence().map { timeThenUrl -> timeThenUrl.getTimeAndOriginal() }
.sortedByDescending { it.first } .sortedBy { it.first }
.map { it.second } .map { it.second }
.map { it.asVideoInPending() } .map { it.asVideoInPending() }
.toList() .toList()

View file

@ -43,7 +43,7 @@ class VideoDownloadingProcessorUseCase(
private val fetch = MutableStateFlow(ProcessingState.RUNNING) private val fetch = MutableStateFlow(ProcessingState.RUNNING)
private val _processState by lazy { private val _processState by lazy {
combineIntoPair(fetch, videoInPendingLocalSource.observeLastPendingVideo()) combineIntoPair(fetch, videoInPendingLocalSource.observeFirstPendingVideo())
.filter { it.first == ProcessingState.RUNNING } .filter { it.first == ProcessingState.RUNNING }
.map { it.second } .map { it.second }
.debounce(WORK_FLOW_DEBOUNCE) .debounce(WORK_FLOW_DEBOUNCE)
@ -134,7 +134,7 @@ class VideoDownloadingProcessorUseCase(
private fun <T, R> combineIntoPair(flow1: Flow<T>, flow2: Flow<R>): Flow<Pair<T, R>> = private fun <T, R> combineIntoPair(flow1: Flow<T>, flow2: Flow<R>): Flow<Pair<T, R>> =
combine(flow1, flow2) { item1, item2 -> item1 to item2 } combine(flow1, flow2) { item1, item2 -> item1 to item2 }
private fun VideoInPendingLocalSource.observeLastPendingVideo(): Flow<VideoInPending?> = private fun VideoInPendingLocalSource.observeFirstPendingVideo(): Flow<VideoInPending?> =
pendingVideos.map { it.lastOrNull() }.distinctUntilChanged() pendingVideos.map { it.firstOrNull() }.distinctUntilChanged()
} }
} }

View file

@ -38,25 +38,25 @@ class QueueFragment : Fragment(R.layout.fragment_queue) {
input.setText("") input.setText("")
} }
viewModel.navigationEvent.observe(viewLifecycleOwner, Observer { viewModel.navigationEvent.observe(viewLifecycleOwner) {
val intent = when (val data = it.item) { val intent = when (val data = it.item) {
is QueueViewModel.NavigationEvent.OpenBrowser -> { is QueueViewModel.NavigationEvent.OpenBrowser -> {
createBrowserIntent(data.url) createBrowserIntent(data.url)
} }
is QueueViewModel.NavigationEvent.OpenGallery -> is QueueViewModel.NavigationEvent.OpenGallery ->
createGalleryIntent(data.uri) createGalleryIntent(data.uri)
null -> return@Observer null -> return@observe
} }
startActivity(intent) startActivity(intent)
}) }
viewModel.downloads.observe(viewLifecycleOwner, { videoStates -> viewModel.downloads.observe(viewLifecycleOwner) { videoStates ->
adapter.submitList(videoStates, Runnable { adapter.submitList(videoStates, Runnable {
val indexToScrollTo = videoStates.indexOfFirst { it is VideoState.InProcess } val indexToScrollTo = videoStates.indexOfFirst { it is VideoState.InProcess }
.takeIf { it != -1 } ?: return@Runnable .takeIf { it != -1 } ?: return@Runnable
recycler.smoothScrollToPosition(indexToScrollTo) recycler.smoothScrollToPosition(indexToScrollTo)
}) })
}) }
} }
companion object { companion object {

View file

@ -1,12 +1,12 @@
package org.fnives.tiktokdownloader.ui.shared package org.fnives.tiktokdownloader.ui.shared
import androidx.fragment.app.Fragment import androidx.lifecycle.LiveData
import androidx.lifecycle.* import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.properties.ReadOnlyProperty
fun <T> CoroutineScope.asLiveData(flow: Flow<T>): LiveData<T> { fun <T> CoroutineScope.asLiveData(flow: Flow<T>): LiveData<T> {
val liveData = MutableLiveData<T>() val liveData = MutableLiveData<T>()

View file

@ -76,11 +76,11 @@ class VideoInPendingLocalSourceTest {
} }
@Test @Test
fun GIVEN_observing_PendingVideos_WHEN_2_video_marked_as_pending_THEN_both_of_them_are_sent_out_in_correct_reverse_order() = fun GIVEN_observing_PendingVideos_WHEN_2_video_marked_as_pending_THEN_both_of_them_are_sent_out_in_correct_order() =
runBlocking<Unit> { runBlocking<Unit> {
val videoInPending1 = VideoInPending("id1", "alma1") val videoInPending1 = VideoInPending("id1", "alma1")
val videoInPending2 = VideoInPending("id2", "alma2") val videoInPending2 = VideoInPending("id2", "alma2")
val expected = listOf(emptyList(), listOf(videoInPending1), listOf(videoInPending2, videoInPending1)) val expected = listOf(emptyList(), listOf(videoInPending1), listOf(videoInPending1, videoInPending2))
val actual = async(coroutineContext) { val actual = async(coroutineContext) {
sut.pendingVideos.take(3).toList() sut.pendingVideos.take(3).toList()