Details activity fixes
This commit is contained in:
@@ -146,7 +146,7 @@ dependencies {
|
|||||||
implementation 'org.conscrypt:conscrypt-android:2.5.2'
|
implementation 'org.conscrypt:conscrypt-android:2.5.2'
|
||||||
|
|
||||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.14'
|
||||||
debugImplementation 'com.github.Koitharu:WorkInspector:2c2919f9f1'
|
debugImplementation 'com.github.Koitharu:WorkInspector:5778dd1747'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
testImplementation 'org.json:json:20240303'
|
testImplementation 'org.json:json:20240303'
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ import org.koitharu.kotatsu.local.data.LocalMangaRepository
|
|||||||
import org.koitharu.kotatsu.local.data.PagesCache
|
import org.koitharu.kotatsu.local.data.PagesCache
|
||||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||||
import org.koitharu.workinspector.WorkInspector
|
|
||||||
|
|
||||||
class KotatsuApp : BaseApp() {
|
class KotatsuApp : BaseApp() {
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
super.attachBaseContext(base)
|
super.attachBaseContext(base)
|
||||||
enableStrictMode()
|
enableStrictMode()
|
||||||
WorkInspector.setLauncherIconEnabled(base, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun enableStrictMode() {
|
private fun enableStrictMode() {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<bool name="leak_canary_add_launcher_icon" tools:node="replace">false</bool>
|
<bool name="leak_canary_add_launcher_icon" tools:node="replace">false</bool>
|
||||||
|
<bool name="wi_launcher_icon_enabled" tools:node="replace">false</bool>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ class DetailsActivity :
|
|||||||
|
|
||||||
private val viewModel: DetailsViewModel by viewModels()
|
private val viewModel: DetailsViewModel by viewModels()
|
||||||
|
|
||||||
private lateinit var chaptersBadge: ViewBadge
|
|
||||||
private lateinit var menuProvider: DetailsMenuProvider
|
private lateinit var menuProvider: DetailsMenuProvider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -158,11 +157,9 @@ class DetailsActivity :
|
|||||||
viewBinding.containerBottomSheet?.let { BottomSheetBehavior.from(it) }?.let { behavior ->
|
viewBinding.containerBottomSheet?.let { BottomSheetBehavior.from(it) }?.let { behavior ->
|
||||||
onBackPressedDispatcher.addCallback(BottomSheetClollapseCallback(behavior))
|
onBackPressedDispatcher.addCallback(BottomSheetClollapseCallback(behavior))
|
||||||
}
|
}
|
||||||
chaptersBadge = ViewBadge(viewBinding.buttonRead, this)
|
|
||||||
|
|
||||||
viewModel.details.filterNotNull().observe(this, ::onMangaUpdated)
|
viewModel.details.filterNotNull().observe(this, ::onMangaUpdated)
|
||||||
viewModel.onMangaRemoved.observeEvent(this, ::onMangaRemoved)
|
viewModel.onMangaRemoved.observeEvent(this, ::onMangaRemoved)
|
||||||
viewModel.newChaptersCount.observe(this, ::onNewChaptersChanged)
|
|
||||||
viewModel.onError
|
viewModel.onError
|
||||||
.filterNot { ChaptersPagesSheet.isShown(supportFragmentManager) }
|
.filterNot { ChaptersPagesSheet.isShown(supportFragmentManager) }
|
||||||
.observeEvent(this, DetailsErrorObserver(this, viewModel, exceptionResolver))
|
.observeEvent(this, DetailsErrorObserver(this, viewModel, exceptionResolver))
|
||||||
@@ -379,15 +376,6 @@ class DetailsActivity :
|
|||||||
chip.textAndVisible = time?.formatShort(chip.resources)
|
chip.textAndVisible = time?.formatShort(chip.resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDescriptionChanged(description: CharSequence?) {
|
|
||||||
val tv = viewBinding.textViewDescription
|
|
||||||
if (description.isNullOrBlank()) {
|
|
||||||
tv.setText(R.string.no_description)
|
|
||||||
} else {
|
|
||||||
tv.text = description
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onLocalSizeChanged(size: Long) {
|
private fun onLocalSizeChanged(size: Long) {
|
||||||
val chip = viewBinding.infoLayout.chipSize
|
val chip = viewBinding.infoLayout.chipSize
|
||||||
if (size == 0L) {
|
if (size == 0L) {
|
||||||
@@ -550,10 +538,6 @@ class DetailsActivity :
|
|||||||
buttonRead.isEnabled = info.isValid
|
buttonRead.isEnabled = info.isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onNewChaptersChanged(count: Int) {
|
|
||||||
chaptersBadge.counter = count
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showBranchPopupMenu(v: View) {
|
private fun showBranchPopupMenu(v: View) {
|
||||||
val menu = PopupMenu(v.context, v)
|
val menu = PopupMenu(v.context, v)
|
||||||
val branches = viewModel.branches.value
|
val branches = viewModel.branches.value
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.koitharu.kotatsu.browser.BrowserActivity
|
|||||||
import org.koitharu.kotatsu.core.os.AppShortcutManager
|
import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||||
import org.koitharu.kotatsu.core.util.ShareHelper
|
import org.koitharu.kotatsu.core.util.ShareHelper
|
||||||
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesSheet
|
|
||||||
import org.koitharu.kotatsu.download.ui.dialog.DownloadOption
|
import org.koitharu.kotatsu.download.ui.dialog.DownloadOption
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
import org.koitharu.kotatsu.scrobbling.common.ui.selector.ScrobblingSelectorSheet
|
import org.koitharu.kotatsu.scrobbling.common.ui.selector.ScrobblingSelectorSheet
|
||||||
@@ -135,7 +134,6 @@ class DetailsMenuProvider(
|
|||||||
is DownloadOption.WholeManga -> null
|
is DownloadOption.WholeManga -> null
|
||||||
is DownloadOption.SelectionHint -> {
|
is DownloadOption.SelectionHint -> {
|
||||||
viewModel.startChaptersSelection()
|
viewModel.startChaptersSelection()
|
||||||
ChaptersPagesSheet.show(activity.supportFragmentManager, ChaptersPagesSheet.TAB_CHAPTERS)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ class DetailsViewModel @Inject constructor(
|
|||||||
val mangaId = intent.mangaId
|
val mangaId = intent.mangaId
|
||||||
|
|
||||||
val onActionDone = MutableEventFlow<ReversibleAction>()
|
val onActionDone = MutableEventFlow<ReversibleAction>()
|
||||||
val onShowTip = MutableEventFlow<Unit>()
|
|
||||||
val onSelectChapter = MutableEventFlow<Long>()
|
val onSelectChapter = MutableEventFlow<Long>()
|
||||||
val onDownloadStarted = MutableEventFlow<Unit>()
|
val onDownloadStarted = MutableEventFlow<Unit>()
|
||||||
|
|
||||||
@@ -161,11 +160,6 @@ class DetailsViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), 0L)
|
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), 0L)
|
||||||
|
|
||||||
@Deprecated("")
|
|
||||||
val description = details
|
|
||||||
.map { it?.description }
|
|
||||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, null)
|
|
||||||
|
|
||||||
val onMangaRemoved = MutableEventFlow<Manga>()
|
val onMangaRemoved = MutableEventFlow<Manga>()
|
||||||
val isScrobblingAvailable: Boolean
|
val isScrobblingAvailable: Boolean
|
||||||
get() = scrobblers.any { it.isAvailable }
|
get() = scrobblers.any { it.isAvailable }
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import com.google.android.material.tabs.TabLayoutMediator
|
|||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior
|
|
||||||
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior.Companion.STATE_COLLAPSED
|
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior.Companion.STATE_COLLAPSED
|
||||||
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior.Companion.STATE_DRAGGING
|
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior.Companion.STATE_DRAGGING
|
||||||
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior.Companion.STATE_EXPANDED
|
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior.Companion.STATE_EXPANDED
|
||||||
@@ -21,6 +20,7 @@ import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior.Companion.STATE_
|
|||||||
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback
|
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback
|
||||||
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
|
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
|
||||||
import org.koitharu.kotatsu.core.ui.util.ActionModeListener
|
import org.koitharu.kotatsu.core.ui.util.ActionModeListener
|
||||||
|
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
||||||
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
||||||
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
|
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
|
||||||
import org.koitharu.kotatsu.core.util.ext.menuView
|
import org.koitharu.kotatsu.core.util.ext.menuView
|
||||||
@@ -64,6 +64,10 @@ class ChaptersPagesSheet : BaseAdaptiveSheet<SheetChaptersPagesBinding>(), Actio
|
|||||||
onBackPressedDispatcher.addCallback(viewLifecycleOwner, menuProvider)
|
onBackPressedDispatcher.addCallback(viewLifecycleOwner, menuProvider)
|
||||||
binding.toolbar.addMenuProvider(menuProvider)
|
binding.toolbar.addMenuProvider(menuProvider)
|
||||||
|
|
||||||
|
val menuInvalidator = MenuInvalidator(binding.toolbar)
|
||||||
|
viewModel.isChaptersReversed.observe(viewLifecycleOwner, menuInvalidator)
|
||||||
|
viewModel.isChaptersInGridView.observe(viewLifecycleOwner, menuInvalidator)
|
||||||
|
|
||||||
actionModeDelegate?.addListener(this, viewLifecycleOwner)
|
actionModeDelegate?.addListener(this, viewLifecycleOwner)
|
||||||
addSheetCallback(this, viewLifecycleOwner)
|
addSheetCallback(this, viewLifecycleOwner)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.core.ui.BaseFragment
|
import org.koitharu.kotatsu.core.ui.BaseFragment
|
||||||
import org.koitharu.kotatsu.core.ui.list.ListSelectionController
|
import org.koitharu.kotatsu.core.ui.list.ListSelectionController
|
||||||
@@ -25,6 +26,7 @@ import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
|
|||||||
import org.koitharu.kotatsu.core.util.ext.dismissParentDialog
|
import org.koitharu.kotatsu.core.util.ext.dismissParentDialog
|
||||||
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
|
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
|
||||||
import org.koitharu.kotatsu.core.util.ext.findParentCallback
|
import org.koitharu.kotatsu.core.util.ext.findParentCallback
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition
|
||||||
import org.koitharu.kotatsu.core.util.ext.observe
|
import org.koitharu.kotatsu.core.util.ext.observe
|
||||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||||
import org.koitharu.kotatsu.databinding.FragmentChaptersBinding
|
import org.koitharu.kotatsu.databinding.FragmentChaptersBinding
|
||||||
@@ -91,12 +93,7 @@ class ChaptersFragment :
|
|||||||
viewModel.isChaptersEmpty.observe(viewLifecycleOwner) {
|
viewModel.isChaptersEmpty.observe(viewLifecycleOwner) {
|
||||||
binding.textViewHolder.isVisible = it
|
binding.textViewHolder.isVisible = it
|
||||||
}
|
}
|
||||||
viewModel.onSelectChapter.observeEvent(viewLifecycleOwner) { chapterId ->
|
viewModel.onSelectChapter.observeEvent(viewLifecycleOwner, ::onSelectChapter)
|
||||||
chaptersAdapter?.observeItems()?.firstOrNull { items ->
|
|
||||||
items.any { x -> x is ChapterListItem && x.chapter.id == chapterId }
|
|
||||||
}
|
|
||||||
selectionController?.onItemLongClick(chapterId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@@ -273,6 +270,22 @@ class ChaptersFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun onSelectChapter(chapterId: Long) {
|
||||||
|
val position = withContext(Dispatchers.Default) {
|
||||||
|
val predicate: (ListModel) -> Boolean = { x -> x is ChapterListItem && x.chapter.id == chapterId }
|
||||||
|
val items = chaptersAdapter?.observeItems()?.firstOrNull { it.any(predicate) }
|
||||||
|
items?.indexOfFirst(predicate) ?: -1
|
||||||
|
}
|
||||||
|
if (position >= 0) {
|
||||||
|
selectionController?.onItemLongClick(chapterId)
|
||||||
|
val lm = (viewBinding?.recyclerViewChapters?.layoutManager as? LinearLayoutManager)
|
||||||
|
if (lm != null) {
|
||||||
|
val offset = resources.getDimensionPixelOffset(R.dimen.chapter_list_item_height)
|
||||||
|
lm.scrollToPositionWithOffset(position, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onLoadingStateChanged(isLoading: Boolean) {
|
private fun onLoadingStateChanged(isLoading: Boolean) {
|
||||||
requireViewBinding().progressBar.isVisible = isLoading
|
requireViewBinding().progressBar.isVisible = isLoading
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,7 +405,7 @@
|
|||||||
android:nestedScrollingEnabled="false"
|
android:nestedScrollingEnabled="false"
|
||||||
android:outlineProvider="background"
|
android:outlineProvider="background"
|
||||||
app:behavior_fitToContents="false"
|
app:behavior_fitToContents="false"
|
||||||
app:behavior_halfExpandedRatio="0.8"
|
app:behavior_halfExpandedRatio="0.00001"
|
||||||
app:behavior_hideable="false"
|
app:behavior_hideable="false"
|
||||||
app:behavior_peekHeight="@dimen/details_bs_peek_height"
|
app:behavior_peekHeight="@dimen/details_bs_peek_height"
|
||||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
||||||
|
|||||||
Reference in New Issue
Block a user