Clear updates feed from options menu

pull/26/head
Koitharu 5 years ago
parent 510c5b70c9
commit bbcd96b981

@ -2,6 +2,7 @@ package org.koitharu.kotatsu.tracker.ui
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
import androidx.appcompat.app.AlertDialog
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -55,6 +56,9 @@ class FeedFragment : BaseFragment<FragmentFeedBinding>(), PaginationScrollListen
viewModel.content.observe(viewLifecycleOwner, this::onListChanged) viewModel.content.observe(viewLifecycleOwner, this::onListChanged)
viewModel.onError.observe(viewLifecycleOwner, this::onError) viewModel.onError.observe(viewLifecycleOwner, this::onError)
viewModel.onFeedCleared.observe(viewLifecycleOwner) {
onFeedCleared()
}
TrackWorker.getProgressLiveData(view.context.applicationContext) TrackWorker.getProgressLiveData(view.context.applicationContext)
.observe(viewLifecycleOwner, this::onUpdateProgressChanged) .observe(viewLifecycleOwner, this::onUpdateProgressChanged)
} }
@ -64,7 +68,8 @@ class FeedFragment : BaseFragment<FragmentFeedBinding>(), PaginationScrollListen
inflater.inflate(R.menu.opt_feed, menu) inflater.inflate(R.menu.opt_feed, menu)
} }
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_update -> { R.id.action_update -> {
TrackWorker.startNow(requireContext()) TrackWorker.startNow(requireContext())
Snackbar.make( Snackbar.make(
@ -74,8 +79,19 @@ class FeedFragment : BaseFragment<FragmentFeedBinding>(), PaginationScrollListen
).show() ).show()
true true
} }
R.id.action_clear_feed -> {
AlertDialog.Builder(context ?: return false)
.setTitle(R.string.clear_updates_feed)
.setMessage(R.string.text_clear_updates_feed_prompt)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.clear) { _, _ ->
viewModel.clearFeed()
}.show()
true
}
else -> super.onOptionsItemSelected(item) else -> super.onOptionsItemSelected(item)
} }
}
override fun onDestroyView() { override fun onDestroyView() {
feedAdapter = null feedAdapter = null
@ -95,6 +111,14 @@ class FeedFragment : BaseFragment<FragmentFeedBinding>(), PaginationScrollListen
feedAdapter?.items = list feedAdapter?.items = list
} }
private fun onFeedCleared() {
Snackbar.make(
binding.recyclerView,
R.string.updates_feed_cleared,
Snackbar.LENGTH_LONG
).show()
}
private fun onError(e: Throwable) { private fun onError(e: Throwable) {
Snackbar.make( Snackbar.make(
binding.recyclerView, binding.recyclerView,

@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
@ -16,6 +17,7 @@ import org.koitharu.kotatsu.list.ui.model.LoadingFooter
import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.LoadingState
import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.tracker.ui.model.toFeedItem import org.koitharu.kotatsu.tracker.ui.model.toFeedItem
import org.koitharu.kotatsu.utils.SingleLiveEvent
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.ext.mapItems import org.koitharu.kotatsu.utils.ext.mapItems
@ -29,6 +31,7 @@ class FeedViewModel(
private var loadingJob: Job? = null private var loadingJob: Job? = null
val isEmptyState = MutableLiveData(false) val isEmptyState = MutableLiveData(false)
val onFeedCleared = SingleLiveEvent<Unit>()
val content = combine( val content = combine(
logList.filterNotNull().mapItems { logList.filterNotNull().mapItems {
it.toFeedItem(context.resources) it.toFeedItem(context.resources)
@ -40,7 +43,10 @@ class FeedViewModel(
isHasNextPage -> list + LoadingFooter isHasNextPage -> list + LoadingFooter
else -> list else -> list
} }
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) }.asLiveDataDistinct(
viewModelScope.coroutineContext + Dispatchers.Default,
listOf(LoadingState)
)
init { init {
loadList(append = false) loadList(append = false)
@ -62,4 +68,15 @@ class FeedViewModel(
hasNextPage.value = list.isNotEmpty() hasNextPage.value = list.isNotEmpty()
} }
} }
fun clearFeed() {
val lastJob = loadingJob
loadingJob = launchLoadingJob(Dispatchers.Default) {
lastJob?.cancelAndJoin()
repository.clearLogs()
logList.value = emptyList()
isEmptyState.postValue(true)
onFeedCleared.postCall(Unit)
}
}
} }

@ -69,3 +69,23 @@ inline fun <T, reified R> Array<T>.mapToArray(transform: (T) -> R): Array<R> = A
} }
fun <T : Enum<T>> Array<T>.names() = mapToArray { it.name } fun <T : Enum<T>> Array<T>.names() = mapToArray { it.name }
fun <T> Collection<T>.isDistinct(): Boolean {
val set = HashSet<T>(size)
for (item in this) {
if (!set.add(item)) {
return false
}
}
return set.size == size
}
fun <T, K> Collection<T>.isDistinctBy(selector: (T) -> K): Boolean {
val set = HashSet<K>(size)
for (item in this) {
if (!set.add(selector(item))) {
return false
}
}
return set.size == size
}

@ -9,4 +9,10 @@
android:title="@string/update" android:title="@string/update"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/action_clear_feed"
android:orderInCategory="50"
android:title="@string/clear_feed"
app:showAsAction="never" />
</menu> </menu>

@ -193,4 +193,6 @@
<string name="clear_cookies">Очистить куки</string> <string name="clear_cookies">Очистить куки</string>
<string name="cookies_cleared">Все куки удалены</string> <string name="cookies_cleared">Все куки удалены</string>
<string name="chapers_checking_progress">Проверка новых глав: %1$d из %2$d</string> <string name="chapers_checking_progress">Проверка новых глав: %1$d из %2$d</string>
<string name="clear_feed">Очистить ленту</string>
<string name="text_clear_updates_feed_prompt">Вся история обновлений будет очищена и её нельзя будет вернуть. Вы уверены?</string>
</resources> </resources>

@ -195,4 +195,6 @@
<string name="clear_cookies">Clear cookies</string> <string name="clear_cookies">Clear cookies</string>
<string name="cookies_cleared">All cookies was removed</string> <string name="cookies_cleared">All cookies was removed</string>
<string name="chapers_checking_progress">Checking for new chapters: %1$d of %2$d</string> <string name="chapers_checking_progress">Checking for new chapters: %1$d of %2$d</string>
<string name="clear_feed">Clear feed</string>
<string name="text_clear_updates_feed_prompt">All updates history will be cleared and this action cannot be undone. Are you sure?</string>
</resources> </resources>
Loading…
Cancel
Save