Show inconito mode indicator on Read button
This commit is contained in:
@@ -228,18 +228,18 @@ class DetailsActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onHistoryChanged(info: HistoryInfo?) {
|
private fun onHistoryChanged(info: HistoryInfo) {
|
||||||
with(binding.buttonRead) {
|
with(binding.buttonRead) {
|
||||||
if (info?.history != null) {
|
if (info.history != null) {
|
||||||
setText(R.string._continue)
|
setText(R.string._continue)
|
||||||
setIconResource(R.drawable.ic_play)
|
setIconResource(if (info.isIncognitoMode) R.drawable.ic_incognito else R.drawable.ic_play)
|
||||||
} else {
|
} else {
|
||||||
setText(R.string.read)
|
setText(R.string.read)
|
||||||
setIconResource(R.drawable.ic_read)
|
setIconResource(if (info.isIncognitoMode) R.drawable.ic_incognito else R.drawable.ic_play)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val text = when {
|
val text = when {
|
||||||
info == null -> getString(R.string.loading_)
|
!info.isValid -> getString(R.string.loading_)
|
||||||
info.currentChapter >= 0 -> getString(R.string.chapter_d_of_d, info.currentChapter + 1, info.totalChapters)
|
info.currentChapter >= 0 -> getString(R.string.chapter_d_of_d, info.currentChapter + 1, info.totalChapters)
|
||||||
info.totalChapters == 0 -> getString(R.string.no_chapters)
|
info.totalChapters == 0 -> getString(R.string.no_chapters)
|
||||||
else -> resources.getQuantityString(R.plurals.chapters, info.totalChapters, info.totalChapters)
|
else -> resources.getQuantityString(R.plurals.chapters, info.totalChapters, info.totalChapters)
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import coil.request.ImageRequest
|
|||||||
import coil.util.CoilUtils
|
import coil.util.CoilUtils
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||||
@@ -27,9 +26,9 @@ import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration
|
|||||||
import org.koitharu.kotatsu.base.ui.widgets.ChipsView
|
import org.koitharu.kotatsu.base.ui.widgets.ChipsView
|
||||||
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||||
import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter
|
import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter
|
||||||
import org.koitharu.kotatsu.core.model.MangaHistory
|
|
||||||
import org.koitharu.kotatsu.databinding.FragmentDetailsBinding
|
import org.koitharu.kotatsu.databinding.FragmentDetailsBinding
|
||||||
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
||||||
|
import org.koitharu.kotatsu.details.ui.model.HistoryInfo
|
||||||
import org.koitharu.kotatsu.details.ui.scrobbling.ScrobblingItemDecoration
|
import org.koitharu.kotatsu.details.ui.scrobbling.ScrobblingItemDecoration
|
||||||
import org.koitharu.kotatsu.details.ui.scrobbling.ScrollingInfoAdapter
|
import org.koitharu.kotatsu.details.ui.scrobbling.ScrollingInfoAdapter
|
||||||
import org.koitharu.kotatsu.history.domain.PROGRESS_NONE
|
import org.koitharu.kotatsu.history.domain.PROGRESS_NONE
|
||||||
@@ -45,8 +44,20 @@ import org.koitharu.kotatsu.scrobbling.domain.model.ScrobblingInfo
|
|||||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||||
import org.koitharu.kotatsu.search.ui.SearchActivity
|
import org.koitharu.kotatsu.search.ui.SearchActivity
|
||||||
import org.koitharu.kotatsu.utils.FileSize
|
import org.koitharu.kotatsu.utils.FileSize
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.computeSize
|
||||||
|
import org.koitharu.kotatsu.utils.ext.crossfade
|
||||||
|
import org.koitharu.kotatsu.utils.ext.drawableTop
|
||||||
|
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||||
|
import org.koitharu.kotatsu.utils.ext.ifNullOrEmpty
|
||||||
|
import org.koitharu.kotatsu.utils.ext.measureHeight
|
||||||
|
import org.koitharu.kotatsu.utils.ext.referer
|
||||||
|
import org.koitharu.kotatsu.utils.ext.resolveDp
|
||||||
|
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
|
||||||
|
import org.koitharu.kotatsu.utils.ext.textAndVisible
|
||||||
|
import org.koitharu.kotatsu.utils.ext.toFileOrNull
|
||||||
|
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||||
import org.koitharu.kotatsu.utils.image.CoverSizeResolver
|
import org.koitharu.kotatsu.utils.image.CoverSizeResolver
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class DetailsFragment :
|
class DetailsFragment :
|
||||||
@@ -75,7 +86,7 @@ class DetailsFragment :
|
|||||||
binding.chipsTags.onChipClickListener = this
|
binding.chipsTags.onChipClickListener = this
|
||||||
viewModel.manga.observe(viewLifecycleOwner, ::onMangaUpdated)
|
viewModel.manga.observe(viewLifecycleOwner, ::onMangaUpdated)
|
||||||
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
||||||
viewModel.readingHistory.observe(viewLifecycleOwner, ::onHistoryChanged)
|
viewModel.historyInfo.observe(viewLifecycleOwner, ::onHistoryChanged)
|
||||||
viewModel.bookmarks.observe(viewLifecycleOwner, ::onBookmarksChanged)
|
viewModel.bookmarks.observe(viewLifecycleOwner, ::onBookmarksChanged)
|
||||||
viewModel.scrobblingInfo.observe(viewLifecycleOwner, ::onScrobblingInfoChanged)
|
viewModel.scrobblingInfo.observe(viewLifecycleOwner, ::onScrobblingInfoChanged)
|
||||||
viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged)
|
viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged)
|
||||||
@@ -123,12 +134,14 @@ class DetailsFragment :
|
|||||||
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_state_finished)
|
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_state_finished)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MangaState.ONGOING -> {
|
MangaState.ONGOING -> {
|
||||||
infoLayout.textViewState.apply {
|
infoLayout.textViewState.apply {
|
||||||
textAndVisible = resources.getString(R.string.state_ongoing)
|
textAndVisible = resources.getString(R.string.state_ongoing)
|
||||||
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_state_ongoing)
|
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_state_ongoing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> infoLayout.textViewState.isVisible = false
|
else -> infoLayout.textViewState.isVisible = false
|
||||||
}
|
}
|
||||||
if (manga.source == MangaSource.LOCAL) {
|
if (manga.source == MangaSource.LOCAL) {
|
||||||
@@ -178,8 +191,8 @@ class DetailsFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onHistoryChanged(history: MangaHistory?) {
|
private fun onHistoryChanged(history: HistoryInfo) {
|
||||||
binding.progressView.setPercent(history?.percent ?: PROGRESS_NONE, animate = true)
|
binding.progressView.setPercent(history.history?.percent ?: PROGRESS_NONE, animate = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onLoadingStateChanged(isLoading: Boolean) {
|
private fun onLoadingStateChanged(isLoading: Boolean) {
|
||||||
@@ -229,6 +242,7 @@ class DetailsFragment :
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.textView_source -> {
|
R.id.textView_source -> {
|
||||||
startActivity(
|
startActivity(
|
||||||
MangaListActivity.newIntent(
|
MangaListActivity.newIntent(
|
||||||
@@ -237,6 +251,7 @@ class DetailsFragment :
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.imageView_cover -> {
|
R.id.imageView_cover -> {
|
||||||
startActivity(
|
startActivity(
|
||||||
ImageActivity.newIntent(v.context, manga.largeCoverUrl.ifNullOrEmpty { manga.coverUrl }),
|
ImageActivity.newIntent(v.context, manga.largeCoverUrl.ifNullOrEmpty { manga.coverUrl }),
|
||||||
@@ -249,7 +264,7 @@ class DetailsFragment :
|
|||||||
override fun onLongClick(v: View): Boolean {
|
override fun onLongClick(v: View): Boolean {
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.button_read -> {
|
R.id.button_read -> {
|
||||||
if (viewModel.readingHistory.value == null) {
|
if (viewModel.historyInfo.value?.history == null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val menu = PopupMenu(v.context, v)
|
val menu = PopupMenu(v.context, v)
|
||||||
@@ -271,12 +286,14 @@ class DetailsFragment :
|
|||||||
)
|
)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu.show()
|
menu.show()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return false
|
else -> return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,18 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import java.io.IOException
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
||||||
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.flow.transformLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.plus
|
import kotlinx.coroutines.plus
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
@@ -46,6 +54,7 @@ import org.koitharu.kotatsu.utils.asFlowLiveData
|
|||||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||||
import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
|
import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
|
||||||
import org.koitharu.kotatsu.utils.ext.runCatchingCancellable
|
import org.koitharu.kotatsu.utils.ext.runCatchingCancellable
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
class DetailsViewModel @AssistedInject constructor(
|
class DetailsViewModel @AssistedInject constructor(
|
||||||
@Assisted intent: MangaIntent,
|
@Assisted intent: MangaIntent,
|
||||||
@@ -91,17 +100,18 @@ class DetailsViewModel @AssistedInject constructor(
|
|||||||
val manga = delegate.manga.filterNotNull().asLiveData(viewModelScope.coroutineContext)
|
val manga = delegate.manga.filterNotNull().asLiveData(viewModelScope.coroutineContext)
|
||||||
val favouriteCategories = favourite.asLiveData(viewModelScope.coroutineContext)
|
val favouriteCategories = favourite.asLiveData(viewModelScope.coroutineContext)
|
||||||
val newChaptersCount = newChapters.asLiveData(viewModelScope.coroutineContext)
|
val newChaptersCount = newChapters.asLiveData(viewModelScope.coroutineContext)
|
||||||
|
|
||||||
@Deprecated("")
|
|
||||||
val readingHistory = history.asLiveData(viewModelScope.coroutineContext)
|
|
||||||
val isChaptersReversed = chaptersReversed.asLiveData(viewModelScope.coroutineContext)
|
val isChaptersReversed = chaptersReversed.asLiveData(viewModelScope.coroutineContext)
|
||||||
|
|
||||||
val historyInfo = combine(
|
val historyInfo: LiveData<HistoryInfo> = combine(
|
||||||
delegate.manga,
|
delegate.manga,
|
||||||
history,
|
history,
|
||||||
) { m, h ->
|
settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) { isIncognitoModeEnabled },
|
||||||
HistoryInfo(m, h)
|
) { m, h, im ->
|
||||||
}.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, null)
|
HistoryInfo(m, h, im)
|
||||||
|
}.asFlowLiveData(
|
||||||
|
context = viewModelScope.coroutineContext + Dispatchers.Default,
|
||||||
|
defaultValue = HistoryInfo(null, null, false),
|
||||||
|
)
|
||||||
|
|
||||||
val bookmarks = delegate.manga.flatMapLatest {
|
val bookmarks = delegate.manga.flatMapLatest {
|
||||||
if (it != null) bookmarksRepository.observeBookmarks(it) else flowOf(emptyList())
|
if (it != null) bookmarksRepository.observeBookmarks(it) else flowOf(emptyList())
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ class HistoryInfo(
|
|||||||
val totalChapters: Int,
|
val totalChapters: Int,
|
||||||
val currentChapter: Int,
|
val currentChapter: Int,
|
||||||
val history: MangaHistory?,
|
val history: MangaHistory?,
|
||||||
|
val isIncognitoMode: Boolean,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
val isValid: Boolean
|
||||||
|
get() = totalChapters >= 0
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (javaClass != other?.javaClass) return false
|
if (javaClass != other?.javaClass) return false
|
||||||
@@ -18,6 +22,7 @@ class HistoryInfo(
|
|||||||
if (totalChapters != other.totalChapters) return false
|
if (totalChapters != other.totalChapters) return false
|
||||||
if (currentChapter != other.currentChapter) return false
|
if (currentChapter != other.currentChapter) return false
|
||||||
if (history != other.history) return false
|
if (history != other.history) return false
|
||||||
|
if (isIncognitoMode != other.isIncognitoMode) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -26,20 +31,21 @@ class HistoryInfo(
|
|||||||
var result = totalChapters
|
var result = totalChapters
|
||||||
result = 31 * result + currentChapter
|
result = 31 * result + currentChapter
|
||||||
result = 31 * result + (history?.hashCode() ?: 0)
|
result = 31 * result + (history?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + isIncognitoMode.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
fun HistoryInfo(manga: Manga?, history: MangaHistory?, isIncognitoMode: Boolean): HistoryInfo {
|
||||||
fun HistoryInfo(manga: Manga?, history: MangaHistory?): HistoryInfo? {
|
val chapters = manga?.chapters
|
||||||
val chapters = manga?.chapters ?: return null
|
|
||||||
return HistoryInfo(
|
return HistoryInfo(
|
||||||
totalChapters = chapters.size,
|
totalChapters = chapters?.size ?: -1,
|
||||||
currentChapter = if (history != null) {
|
currentChapter = if (history != null && !chapters.isNullOrEmpty()) {
|
||||||
chapters.indexOfFirst { it.id == history.chapterId }
|
chapters.indexOfFirst { it.id == history.chapterId }
|
||||||
} else {
|
} else {
|
||||||
-1
|
-1
|
||||||
},
|
},
|
||||||
history = history,
|
history = history,
|
||||||
|
isIncognitoMode = isIncognitoMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.koitharu.kotatsu.core.db.MangaDatabase
|
|||||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||||
import org.koitharu.kotatsu.core.github.AppUpdateRepository
|
import org.koitharu.kotatsu.core.github.AppUpdateRepository
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
|
import org.koitharu.kotatsu.core.prefs.observeAsFlow
|
||||||
import org.koitharu.kotatsu.core.prefs.observeAsLiveData
|
import org.koitharu.kotatsu.core.prefs.observeAsLiveData
|
||||||
import org.koitharu.kotatsu.history.domain.HistoryRepository
|
import org.koitharu.kotatsu.history.domain.HistoryRepository
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
@@ -34,9 +35,12 @@ class MainViewModel @Inject constructor(
|
|||||||
|
|
||||||
val onOpenReader = SingleLiveEvent<Manga>()
|
val onOpenReader = SingleLiveEvent<Manga>()
|
||||||
|
|
||||||
val isResumeEnabled = historyRepository
|
val isResumeEnabled = combine(
|
||||||
.observeHasItems()
|
historyRepository.observeHasItems(),
|
||||||
.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false)
|
settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) { isIncognitoModeEnabled },
|
||||||
|
) { hasItems, incognito ->
|
||||||
|
hasItems && !incognito
|
||||||
|
}.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false)
|
||||||
|
|
||||||
val isFeedAvailable = settings.observeAsLiveData(
|
val isFeedAvailable = settings.observeAsLiveData(
|
||||||
context = viewModelScope.coroutineContext + Dispatchers.Default,
|
context = viewModelScope.coroutineContext + Dispatchers.Default,
|
||||||
|
|||||||
Reference in New Issue
Block a user