diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 8025694fc..dc738ecc8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -363,10 +363,6 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { val isReaderBarEnabled: Boolean get() = prefs.getBoolean(KEY_READER_BAR, true) - var isReaderSliderEnabled: Boolean - get() = prefs.getBoolean(KEY_READER_SLIDER, true) - set(value) = prefs.edit { putBoolean(KEY_READER_SLIDER, value) } - val isReaderKeepScreenOn: Boolean get() = prefs.getBoolean(KEY_READER_SCREEN_ON, true) @@ -671,7 +667,6 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_SYNC = "sync" const val KEY_SYNC_SETTINGS = "sync_settings" const val KEY_READER_BAR = "reader_bar" - const val KEY_READER_SLIDER = "reader_slider" const val KEY_READER_BACKGROUND = "reader_background" const val KEY_READER_SCREEN_ON = "reader_screen_on" const val KEY_SHORTCUTS = "dynamic_shortcuts" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt index 3a5d98268..2805778ed 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.core.ui.widgets import android.content.Context import android.util.AttributeSet import android.view.View -import android.view.View.OnClickListener import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.StringRes @@ -34,7 +33,7 @@ import com.google.android.material.R as materialR class ChipsView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, - defStyleAttr: Int = com.google.android.material.R.attr.chipGroupStyle, + defStyleAttr: Int = materialR.attr.chipGroupStyle, ) : ChipGroup(context, attrs, defStyleAttr) { @Inject @@ -49,6 +48,7 @@ class ChipsView @JvmOverloads constructor( onChipCloseClickListener?.onChipCloseClick(chip, data) ?: onChipClickListener?.onChipClick(chip, data) } private val chipStyle: Int + private val iconsVisible: Boolean var onChipClickListener: OnChipClickListener? = null set(value) { field = value @@ -60,6 +60,7 @@ class ChipsView @JvmOverloads constructor( init { val ta = context.obtainStyledAttributes(attrs, R.styleable.ChipsView, defStyleAttr, 0) chipStyle = ta.getResourceId(R.styleable.ChipsView_chipStyle, R.style.Widget_Kotatsu_Chip) + iconsVisible = ta.getBoolean(R.styleable.ChipsView_chipIconVisible, true) ta.recycle() if (isInEditMode) { @@ -170,12 +171,7 @@ class ChipsView @JvmOverloads constructor( private fun bindIcon(model: ChipModel) { when { - model.isChecked -> { - imageRequest?.dispose() - imageRequest = null - chipIcon = null - isChipIconVisible = false - } + model.isChecked -> disposeIcon() model.isLoading -> { imageRequest?.dispose() @@ -184,6 +180,8 @@ class ChipsView @JvmOverloads constructor( setProgressIcon() } + !iconsVisible -> disposeIcon() + model.iconData != null -> { val placeholder = model.icon.ifZero { materialR.drawable.navigation_empty_icon } imageRequest = ImageRequest.Builder(context) @@ -207,14 +205,16 @@ class ChipsView @JvmOverloads constructor( isChipIconVisible = true } - else -> { - imageRequest?.dispose() - imageRequest = null - chipIcon = null - isChipIconVisible = false - } + else -> disposeIcon() } } + + private fun disposeIcon() { + imageRequest?.dispose() + imageRequest = null + chipIcon = null + isChipIconVisible = false + } } private inner class InternalChipClickListener : OnClickListener { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ZoomControl.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ZoomControl.kt index b6f8d222a..52625e94e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ZoomControl.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ZoomControl.kt @@ -4,14 +4,14 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.view.View -import android.widget.LinearLayout +import com.google.android.material.button.MaterialButtonGroup import org.koitharu.kotatsu.R import org.koitharu.kotatsu.databinding.ViewZoomBinding class ZoomControl @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, -) : LinearLayout(context, attrs), View.OnClickListener { +) : MaterialButtonGroup(context, attrs), View.OnClickListener { private val binding = ViewZoomBinding.inflate(LayoutInflater.from(context), this) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/LocaleStringComparator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/LocaleStringComparator.kt index 4bf0be081..0bb5b7ec4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/LocaleStringComparator.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/LocaleStringComparator.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.core.util import androidx.core.os.LocaleListCompat +import org.koitharu.kotatsu.core.util.ext.indexOfContains import org.koitharu.kotatsu.core.util.ext.iterator class LocaleStringComparator : Comparator { @@ -14,7 +15,7 @@ class LocaleStringComparator : Comparator { val set = HashSet(localeList.size() + 1) set.add(null) for (locale in localeList) { - val lang = locale.getDisplayLanguage(locale).lowercase() + val lang = locale.getDisplayLanguage(locale) if (set.add(lang)) { add(lang) } @@ -23,8 +24,8 @@ class LocaleStringComparator : Comparator { } override fun compare(a: String?, b: String?): Int { - val indexA = deviceLocales.indexOf(a?.lowercase()) - val indexB = deviceLocales.indexOf(b?.lowercase()) + val indexA = deviceLocales.indexOfContains(a, true) + val indexB = deviceLocales.indexOfContains(b, true) return when { indexA < 0 && indexB < 0 -> compareValues(a, b) indexA < 0 -> 1 diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt index a7455af10..44f5dbe66 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt @@ -108,3 +108,7 @@ fun Collection.mapSortedByCount(isDescending: Boolean = true, mapper: } return sorted.map { it.first } } + +fun Collection.indexOfContains(element: CharSequence?, ignoreCase: Boolean): Int = indexOfFirst { x -> + (x == null && element == null) || (x != null && element != null && x.contains(element, ignoreCase)) +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesSheet.kt index ab31b68dd..43570c7f7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/ChaptersPagesSheet.kt @@ -91,8 +91,8 @@ class ChaptersPagesSheet : BaseAdaptiveSheet(), Actio } val binding = viewBinding ?: return val isActionModeStarted = actionModeDelegate?.isActionModeStarted == true - binding.toolbar.menuView?.isVisible = newState != STATE_COLLAPSED && !isActionModeStarted - binding.splitButtonRead.isVisible = newState == STATE_COLLAPSED && !isActionModeStarted + binding.toolbar.menuView?.isVisible = newState == STATE_EXPANDED && !isActionModeStarted + binding.splitButtonRead.isVisible = newState != STATE_EXPANDED && !isActionModeStarted && viewModel is DetailsViewModel } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index 669270e42..4cc5e354e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -145,12 +145,10 @@ class ReaderActivity : viewModel.content.observe(this) { onLoadingStateChanged(viewModel.isLoading.value) } - viewModel.isSliderVisible.observe(this) { updateSliderVisibility() } viewModel.isKeepScreenOnEnabled.observe(this, this::setKeepScreenOn) viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged) - val bottomMenuInvalidator = MenuInvalidator(viewBinding.toolbarBottom) - viewModel.isBookmarkAdded.observe(this, bottomMenuInvalidator) - viewModel.isPagesSheetEnabled.observe(this, bottomMenuInvalidator) + viewModel.isBookmarkAdded.observe(this, MenuInvalidator(this)) + viewModel.isPagesSheetEnabled.observe(this, MenuInvalidator(viewBinding.toolbarBottom)) viewModel.onShowToast.observeEvent(this) { msgId -> Snackbar.make(viewBinding.container, msgId, Snackbar.LENGTH_SHORT) .setAnchorView(viewBinding.appbarBottom) @@ -159,7 +157,8 @@ class ReaderActivity : viewModel.isZoomControlsEnabled.observe(this) { viewBinding.zoomControl.isVisible = it } - viewBinding.toolbarBottom.addMenuProvider(ReaderMenuProvider(this, readerManager, viewModel)) + addMenuProvider(ReaderMenuTopProvider(viewModel)) + viewBinding.toolbarBottom.addMenuProvider(ReaderMenuBottomProvider(this, readerManager, viewModel)) } override fun getParentActivityIntent(): Intent? { @@ -234,7 +233,7 @@ class ReaderActivity : rawX >= viewBinding.root.width - gestureInsets.right || rawY >= viewBinding.root.height - gestureInsets.bottom || viewBinding.appbarTop.hasGlobalPoint(rawX, rawY) || - viewBinding.appbarBottom?.hasGlobalPoint(rawX, rawY) == true + viewBinding.appbarBottom.hasGlobalPoint(rawX, rawY) == true ) { false } else { @@ -301,20 +300,14 @@ class ReaderActivity : .setOrdering(TransitionSet.ORDERING_TOGETHER) .addTransition(Slide(Gravity.TOP).addTarget(viewBinding.appbarTop)) .addTransition(Fade().addTarget(viewBinding.infoBar)) - viewBinding.appbarBottom?.let { bottomBar -> - transition.addTransition(Slide(Gravity.BOTTOM).addTarget(bottomBar)) - transition.addTransition(Slide(Gravity.BOTTOM).addTarget(viewBinding.floatingToolbar)) - } ?: run { - transition.addTransition(Slide(Gravity.END).addTarget(viewBinding.floatingToolbar)) - } + .addTransition(Slide(Gravity.BOTTOM).addTarget(viewBinding.appbarBottom)) TransitionManager.beginDelayedTransition(viewBinding.root, transition) } val isFullscreen = settings.isReaderFullscreenEnabled viewBinding.appbarTop.isVisible = isUiVisible - viewBinding.appbarBottom?.isVisible = isUiVisible + viewBinding.appbarBottom.isVisible = isUiVisible viewBinding.infoBar.isGone = isUiVisible || (!viewModel.isInfoBarEnabled.value) viewBinding.infoBar.isTimeVisible = isFullscreen - updateSliderVisibility() systemUiController.setSystemUiVisible(isUiVisible || !isFullscreen) } } @@ -327,7 +320,7 @@ class ReaderActivity : right = systemBars.right, left = systemBars.left, ) - viewBinding.appbarBottom?.updateLayoutParams { + viewBinding.appbarBottom.updateLayoutParams { bottomMargin = systemBars.bottom + topMargin rightMargin = systemBars.right + topMargin leftMargin = systemBars.left + topMargin @@ -383,33 +376,31 @@ class ReaderActivity : viewBinding.infoBar.update(uiState) if (uiState == null) { supportActionBar?.subtitle = null - updateSliderVisibility() + viewBinding.layoutSlider.isVisible = false return } supportActionBar?.subtitle = when { uiState.incognito -> getString(R.string.incognito_mode) else -> uiState.chapterName } - if (previous?.chapterName != null && uiState.chapterName != previous.chapterName) { - if (!uiState.chapterName.isNullOrEmpty()) { - viewBinding.toastView.showTemporary(uiState.chapterName, TOAST_DURATION) - } + if (uiState.chapterName != previous?.chapterName && !uiState.chapterName.isNullOrEmpty()) { + viewBinding.toastView.showTemporary(uiState.chapterName, TOAST_DURATION) } if (uiState.isSliderAvailable()) { viewBinding.slider.valueTo = uiState.totalPages.toFloat() - 1 viewBinding.slider.setValueRounded(uiState.currentPage.toFloat()) + } else { + viewBinding.slider.valueTo = 1f + viewBinding.slider.value = 0f } - updateSliderVisibility() - } - - private fun updateSliderVisibility() { - viewBinding.floatingToolbar.isVisible = viewBinding.appbarTop.isVisible && - viewModel.isSliderVisible.value && - viewModel.uiState.value?.isSliderAvailable() == true + viewBinding.slider.isEnabled = uiState.isSliderAvailable() + viewBinding.buttonNext.isEnabled = uiState.hasNextChapter() + viewBinding.buttonPrev.isEnabled = uiState.hasPreviousChapter() + viewBinding.layoutSlider.isVisible = true } companion object { - private const val TOAST_DURATION = 1500L + private const val TOAST_DURATION = 2000L } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuBottomProvider.kt similarity index 70% rename from app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuBottomProvider.kt index 946852172..c938b91bf 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuProvider.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuBottomProvider.kt @@ -8,14 +8,14 @@ import androidx.fragment.app.FragmentActivity import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.nav.router -class ReaderMenuProvider( +class ReaderMenuBottomProvider( private val activity: FragmentActivity, private val readerManager: ReaderManager, private val viewModel: ReaderViewModel, ) : MenuProvider { override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { - menuInflater.inflate(R.menu.opt_reader, menu) + menuInflater.inflate(R.menu.opt_reader_bottom, menu) onPrepareMenu(menu) // fix, not called in toolbar } @@ -27,15 +27,6 @@ class ReaderMenuProvider( setIcon(if (viewModel.isPagesSheetEnabled.value) R.drawable.ic_grid else R.drawable.ic_list) } } - menu.findItem(R.id.action_bookmark)?.let { bookmarkItem -> - val hasPages = viewModel.content.value.pages.isNotEmpty() - bookmarkItem.isEnabled = hasPages - if (hasPages) { - val hasBookmark = viewModel.isBookmarkAdded.value - bookmarkItem.setTitle(if (hasBookmark) R.string.bookmark_remove else R.string.bookmark_add) - bookmarkItem.setIcon(if (hasBookmark) R.drawable.ic_bookmark_added else R.drawable.ic_bookmark) - } - } } override fun onMenuItemSelected(menuItem: MenuItem): Boolean { @@ -52,11 +43,6 @@ class ReaderMenuProvider( true } - R.id.action_slider -> { - viewModel.setSliderVisibility(!viewModel.isSliderVisible.value) - true - } - R.id.action_bookmark -> { if (viewModel.isBookmarkAdded.value) { viewModel.removeBookmark() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuTopProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuTopProvider.kt new file mode 100644 index 000000000..aa66de0eb --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuTopProvider.kt @@ -0,0 +1,43 @@ +package org.koitharu.kotatsu.reader.ui + +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import androidx.core.view.MenuProvider +import org.koitharu.kotatsu.R + +class ReaderMenuTopProvider( + private val viewModel: ReaderViewModel, +) : MenuProvider { + + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + menuInflater.inflate(R.menu.opt_reader_top, menu) + } + + override fun onPrepareMenu(menu: Menu) { + menu.findItem(R.id.action_bookmark)?.let { bookmarkItem -> + val hasPages = viewModel.content.value.pages.isNotEmpty() + bookmarkItem.isEnabled = hasPages + if (hasPages) { + val hasBookmark = viewModel.isBookmarkAdded.value + bookmarkItem.setTitle(if (hasBookmark) R.string.bookmark_remove else R.string.bookmark_add) + bookmarkItem.setIcon(if (hasBookmark) R.drawable.ic_bookmark_added else R.drawable.ic_bookmark) + } + } + } + + override fun onMenuItemSelected(menuItem: MenuItem): Boolean { + return when (menuItem.itemId) { + R.id.action_bookmark -> { + if (viewModel.isBookmarkAdded.value) { + viewModel.removeBookmark() + } else { + viewModel.addBookmark() + } + true + } + + else -> false + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt index a2acc8df7..6357c20f7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt @@ -1,16 +1,19 @@ package org.koitharu.kotatsu.reader.ui +import android.animation.Animator +import android.animation.AnimatorListenerAdapter import android.content.Context import android.util.AttributeSet -import android.view.Gravity -import android.view.ViewGroup +import android.view.ViewPropertyAnimator +import android.view.animation.AccelerateInterpolator +import android.view.animation.DecelerateInterpolator import androidx.annotation.StringRes +import androidx.core.view.isGone import androidx.core.view.isVisible -import androidx.transition.Fade -import androidx.transition.Slide -import androidx.transition.TransitionManager -import androidx.transition.TransitionSet import com.google.android.material.textview.MaterialTextView +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.getAnimationDuration +import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled class ReaderToastView @JvmOverloads constructor( context: Context, @@ -18,6 +21,8 @@ class ReaderToastView @JvmOverloads constructor( defStyleAttr: Int = 0, ) : MaterialTextView(context, attrs, defStyleAttr) { + private var currentAnimator: ViewPropertyAnimator? = null + private var hideRunnable = Runnable { hide() } @@ -25,8 +30,7 @@ class ReaderToastView @JvmOverloads constructor( fun show(message: CharSequence) { removeCallbacks(hideRunnable) text = message - setupTransition() - isVisible = true + showImpl() } fun show(@StringRes messageId: Int) { @@ -40,8 +44,7 @@ class ReaderToastView @JvmOverloads constructor( fun hide() { removeCallbacks(hideRunnable) - setupTransition() - isVisible = false + hideImpl() } override fun onDetachedFromWindow() { @@ -49,13 +52,41 @@ class ReaderToastView @JvmOverloads constructor( super.onDetachedFromWindow() } - private fun setupTransition() { - val parentView = parent as? ViewGroup ?: return - val transition = TransitionSet() - .setOrdering(TransitionSet.ORDERING_TOGETHER) - .addTarget(this) - .addTransition(Slide(Gravity.BOTTOM)) - .addTransition(Fade()) - TransitionManager.beginDelayedTransition(parentView, transition) + private fun showImpl() { + currentAnimator?.cancel() + clearAnimation() + if (!context.isAnimationsEnabled) { + currentAnimator = null + isVisible = true + return + } + alpha = 0f + isVisible = true + currentAnimator = animate() + .alpha(1f) + .setInterpolator(DecelerateInterpolator()) + .setDuration(context.getAnimationDuration(R.integer.config_shorterAnimTime)) + .setListener(null) } -} \ No newline at end of file + + private fun hideImpl() { + currentAnimator?.cancel() + clearAnimation() + if (!context.isAnimationsEnabled) { + currentAnimator = null + isGone = true + return + } + currentAnimator = animate() + .alpha(0f) + .setInterpolator(AccelerateInterpolator()) + .setDuration(context.getAnimationDuration(R.integer.config_shorterAnimTime)) + .setListener( + object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + isGone = true + } + }, + ) + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index 030a56284..e54afbb41 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -21,9 +21,7 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.plus @@ -132,12 +130,6 @@ class ReaderViewModel @Inject constructor( valueProducer = { readerAnimation }, ) - val isSliderVisible = settings.observeAsStateFlow( - scope = viewModelScope + Dispatchers.Default, - key = AppSettings.KEY_READER_SLIDER, - valueProducer = { isReaderSliderEnabled }, - ) - val isInfoBarEnabled = settings.observeAsStateFlow( scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_READER_BAR, @@ -199,10 +191,6 @@ class ReaderViewModel @Inject constructor( init { loadImpl() - settings.observe() - .onEach { key -> - if (key == AppSettings.KEY_READER_SLIDER) notifyStateChanged() - }.launchIn(viewModelScope + Dispatchers.Default) launchJob(Dispatchers.Default) { val mangaId = manga.filterNotNull().first().id appShortcutManager.notifyMangaOpened(mangaId) @@ -220,10 +208,6 @@ class ReaderViewModel @Inject constructor( } } - fun setSliderVisibility(visible: Boolean) { - settings.isReaderSliderEnabled = visible - } - fun switchMode(newMode: ReaderMode) { launchJob { val manga = checkNotNull(getMangaOrNull()) @@ -459,7 +443,6 @@ class ReaderViewModel @Inject constructor( chaptersTotal = m.chapters[chapter.branch].sizeOrZero(), totalPages = chaptersLoader.getPagesCount(chapter.id), currentPage = state.page, - isSliderEnabled = settings.isReaderSliderEnabled, percent = computePercent(state.chapterId, state.page), incognito = incognitoMode.value, ) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt index f4de7734b..151a3ee0c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt @@ -10,10 +10,11 @@ data class ReaderUiState( val totalPages: Int, val percent: Float, val incognito: Boolean, - private val isSliderEnabled: Boolean, ) { - fun isSliderAvailable(): Boolean { - return isSliderEnabled && totalPages > 1 && currentPage < totalPages - } + fun hasNextChapter(): Boolean = chapterNumber < chaptersTotal + + fun hasPreviousChapter(): Boolean = chapterNumber > 1 + + fun isSliderAvailable(): Boolean = totalPages > 1 && currentPage < totalPages } diff --git a/app/src/main/res/color-v23/bg_floating_button.xml b/app/src/main/res/color-v23/bg_floating_button.xml new file mode 100644 index 000000000..1ebbd47ea --- /dev/null +++ b/app/src/main/res/color-v23/bg_floating_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/color/bg_floating_button.xml b/app/src/main/res/color/bg_floating_button.xml new file mode 100644 index 000000000..b40058de7 --- /dev/null +++ b/app/src/main/res/color/bg_floating_button.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/layout-w600dp-land/activity_reader.xml b/app/src/main/res/layout-w600dp-land/activity_reader.xml deleted file mode 100644 index d7971c32e..000000000 --- a/app/src/main/res/layout-w600dp-land/activity_reader.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index 7e112fb7f..79dba1369 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -19,6 +19,7 @@ android:layout_gravity="bottom|end" android:layout_margin="16dp" android:orientation="vertical" + android:spacing="2dp" android:visibility="gone" app:layout_dodgeInsetEdges="bottom" tools:visibility="visible" /> @@ -66,62 +67,56 @@ android:id="@+id/toolbar_bottom" android:layout_width="match_parent" android:layout_height="wrap_content" - tools:menu="@menu/opt_reader" /> + tools:menu="@menu/opt_reader_bottom"> + + + + + + + + + + + + - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/view_zoom.xml b/app/src/main/res/layout/view_zoom.xml index b8297bf85..258f0f16a 100644 --- a/app/src/main/res/layout/view_zoom.xml +++ b/app/src/main/res/layout/view_zoom.xml @@ -5,39 +5,28 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:parentTag="android.widget.LinearLayout"> + tools:orientation="vertical" + tools:parentTag="com.google.android.material.button.MaterialButtonGroup"> - + app:backgroundTint="@color/bg_floating_button" + app:icon="@drawable/ic_zoom_in" /> - + app:backgroundTint="@color/bg_floating_button" + app:icon="@drawable/ic_zoom_out" /> diff --git a/app/src/main/res/menu/opt_reader.xml b/app/src/main/res/menu/opt_reader_bottom.xml similarity index 65% rename from app/src/main/res/menu/opt_reader.xml rename to app/src/main/res/menu/opt_reader_bottom.xml index 185879d73..21b800716 100644 --- a/app/src/main/res/menu/opt_reader.xml +++ b/app/src/main/res/menu/opt_reader_bottom.xml @@ -5,19 +5,6 @@ xmlns:tools="http://schemas.android.com/tools" tools:ignore="AlwaysShowAction"> - - - - + + + + + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index a59b59b5b..1727ef8c6 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -141,6 +141,7 @@ + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7254889a3..5be0e3b70 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ conscrypt = "2.5.2" constraintlayout = "2.2.0" coreKtx = "1.15.0" coroutines = "1.9.0" -desugar = "2.1.3" +desugar = "2.1.4" diskLruCache = "1.4" fragment = "1.8.5" gradle = "8.7.3" @@ -27,7 +27,7 @@ ksp = "2.0.21-1.0.28" leakcanary = "3.0-alpha-8" lifecycle = "2.8.7" markwon = "4.6.2" -material = "1.13.0-alpha08" +material = "1.13.0-alpha09" moshi = "1.15.2" okhttp = "4.12.0" okio = "3.9.1"