diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt index 1712241e6..c6e970ab9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.tracker.ui import android.os.Bundle import android.view.* +import androidx.appcompat.app.AlertDialog import androidx.core.graphics.Insets import androidx.core.view.updatePadding import com.google.android.material.snackbar.Snackbar @@ -55,6 +56,9 @@ class FeedFragment : BaseFragment(), PaginationScrollListen viewModel.content.observe(viewLifecycleOwner, this::onListChanged) viewModel.onError.observe(viewLifecycleOwner, this::onError) + viewModel.onFeedCleared.observe(viewLifecycleOwner) { + onFeedCleared() + } TrackWorker.getProgressLiveData(view.context.applicationContext) .observe(viewLifecycleOwner, this::onUpdateProgressChanged) } @@ -64,17 +68,29 @@ class FeedFragment : BaseFragment(), PaginationScrollListen inflater.inflate(R.menu.opt_feed, menu) } - override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { - R.id.action_update -> { - TrackWorker.startNow(requireContext()) - Snackbar.make( - binding.recyclerView, - R.string.feed_will_update_soon, - Snackbar.LENGTH_SHORT - ).show() - true + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.action_update -> { + TrackWorker.startNow(requireContext()) + Snackbar.make( + binding.recyclerView, + R.string.feed_will_update_soon, + Snackbar.LENGTH_SHORT + ).show() + 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() { @@ -95,6 +111,14 @@ class FeedFragment : BaseFragment(), PaginationScrollListen feedAdapter?.items = list } + private fun onFeedCleared() { + Snackbar.make( + binding.recyclerView, + R.string.updates_feed_cleared, + Snackbar.LENGTH_LONG + ).show() + } + private fun onError(e: Throwable) { Snackbar.make( binding.recyclerView, diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedViewModel.kt index c57753ba3..c187bde99 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine 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.tracker.domain.TrackingRepository 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.mapItems @@ -29,6 +31,7 @@ class FeedViewModel( private var loadingJob: Job? = null val isEmptyState = MutableLiveData(false) + val onFeedCleared = SingleLiveEvent() val content = combine( logList.filterNotNull().mapItems { it.toFeedItem(context.resources) @@ -40,7 +43,10 @@ class FeedViewModel( isHasNextPage -> list + LoadingFooter else -> list } - }.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.asLiveDataDistinct( + viewModelScope.coroutineContext + Dispatchers.Default, + listOf(LoadingState) + ) init { loadList(append = false) @@ -62,4 +68,15 @@ class FeedViewModel( 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) + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CollectionExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CollectionExt.kt index b7a5dc816..8a2468f7a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CollectionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CollectionExt.kt @@ -68,4 +68,24 @@ inline fun Array.mapToArray(transform: (T) -> R): Array = A transform(get(i)) } -fun > Array.names() = mapToArray { it.name } \ No newline at end of file +fun > Array.names() = mapToArray { it.name } + +fun Collection.isDistinct(): Boolean { + val set = HashSet(size) + for (item in this) { + if (!set.add(item)) { + return false + } + } + return set.size == size +} + +fun Collection.isDistinctBy(selector: (T) -> K): Boolean { + val set = HashSet(size) + for (item in this) { + if (!set.add(selector(item))) { + return false + } + } + return set.size == size +} \ No newline at end of file diff --git a/app/src/main/res/menu/opt_feed.xml b/app/src/main/res/menu/opt_feed.xml index f591412fa..7da287e4a 100644 --- a/app/src/main/res/menu/opt_feed.xml +++ b/app/src/main/res/menu/opt_feed.xml @@ -9,4 +9,10 @@ android:title="@string/update" app:showAsAction="never" /> + + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index c86d80cda..9684800c4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -193,4 +193,6 @@ Очистить куки Все куки удалены Проверка новых глав: %1$d из %2$d + Очистить ленту + Вся история обновлений будет очищена и её нельзя будет вернуть. Вы уверены? \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5966784cf..ca4f78f7b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -195,4 +195,6 @@ Clear cookies All cookies was removed Checking for new chapters: %1$d of %2$d + Clear feed + All updates history will be cleared and this action cannot be undone. Are you sure? \ No newline at end of file