diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 627056742..19bfbb066 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -11,12 +11,6 @@ import androidx.core.content.edit import androidx.preference.PreferenceManager import com.google.android.material.color.DynamicColors import dagger.hilt.android.qualifiers.ApplicationContext -import java.io.File -import java.text.DateFormat -import java.text.SimpleDateFormat -import java.util.* -import javax.inject.Inject -import javax.inject.Singleton import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.network.DoHProvider @@ -26,6 +20,14 @@ import org.koitharu.kotatsu.utils.ext.getEnumValue import org.koitharu.kotatsu.utils.ext.observe import org.koitharu.kotatsu.utils.ext.putEnumValue import org.koitharu.kotatsu.utils.ext.toUriOrNull +import java.io.File +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.Collections +import java.util.EnumSet +import java.util.Locale +import javax.inject.Inject +import javax.inject.Singleton @Singleton class AppSettings @Inject constructor(@ApplicationContext context: Context) { @@ -206,6 +208,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { val isReaderBarEnabled: Boolean get() = prefs.getBoolean(KEY_READER_BAR, true) + val isReaderSliderEnabled: Boolean + get() = prefs.getBoolean(KEY_READER_SLIDER, true) + val dnsOverHttps: DoHProvider get() = prefs.getEnumValue(KEY_DOH, DoHProvider.NONE) @@ -328,6 +333,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_INCOGNITO_MODE = "incognito" const val KEY_SYNC = "sync" const val KEY_READER_BAR = "reader_bar" + const val KEY_READER_SLIDER = "reader_slider" const val KEY_SHORTCUTS = "dynamic_shortcuts" const val KEY_READER_TAPS_LTR = "reader_taps_ltr" const val KEY_LOCAL_LIST_ORDER = "local_order" diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index abbc542cb..ffa7432ef 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -9,15 +9,23 @@ import android.transition.Fade import android.transition.Slide import android.transition.TransitionManager import android.transition.TransitionSet -import android.view.* +import android.view.Gravity +import android.view.KeyEvent +import android.view.Menu +import android.view.MenuItem +import android.view.MotionEvent +import android.view.View +import android.view.WindowManager import androidx.core.graphics.Insets -import androidx.core.view.* +import androidx.core.view.OnApplyWindowInsetsListener +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.isGone +import androidx.core.view.isVisible +import androidx.core.view.updatePadding import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint -import java.util.concurrent.TimeUnit -import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -42,7 +50,16 @@ import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.utils.GridTouchHelper import org.koitharu.kotatsu.utils.IdlingDetector import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.utils.ext.assistedViewModels +import org.koitharu.kotatsu.utils.ext.getDisplayMessage +import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat +import org.koitharu.kotatsu.utils.ext.hasGlobalPoint +import org.koitharu.kotatsu.utils.ext.isReportable +import org.koitharu.kotatsu.utils.ext.observeWithPrevious +import org.koitharu.kotatsu.utils.ext.postDelayed +import org.koitharu.kotatsu.utils.ext.report +import java.util.concurrent.TimeUnit +import javax.inject.Inject @AndroidEntryPoint class ReaderActivity : @@ -145,6 +162,7 @@ class ReaderActivity : R.id.action_settings -> { startActivity(SettingsActivity.newReaderSettingsIntent(this)) } + R.id.action_chapters -> { ChaptersBottomSheet.show( supportFragmentManager, @@ -152,6 +170,7 @@ class ReaderActivity : viewModel.getCurrentState()?.chapterId ?: 0L, ) } + R.id.action_pages_thumbs -> { val pages = viewModel.getCurrentChapterPages() if (!pages.isNullOrEmpty()) { @@ -165,6 +184,7 @@ class ReaderActivity : return false } } + R.id.action_bookmark -> { if (viewModel.isBookmarkAdded.value == true) { viewModel.removeBookmark() @@ -172,11 +192,13 @@ class ReaderActivity : viewModel.addBookmark() } } + R.id.action_options -> { viewModel.saveCurrentState(readerManager.currentReader?.getCurrentState()) val currentMode = readerManager.currentMode ?: return false ReaderConfigBottomSheet.show(supportFragmentManager, currentMode) } + else -> return super.onOptionsItemSelected(item) } return true @@ -364,7 +386,7 @@ class ReaderActivity : binding.toastView.showTemporary(uiState.chapterName, TOAST_DURATION) } } - if (uiState.totalPages > 1 && uiState.currentPage < uiState.totalPages) { + if (uiState.isSliderAvailable()) { binding.slider.valueTo = uiState.totalPages.toFloat() - 1 binding.slider.value = uiState.currentPage.toFloat() binding.slider.isVisible = true diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index 57e36e6ce..ea9abd350 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -10,10 +10,22 @@ import androidx.lifecycle.viewModelScope import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import java.util.* -import javax.inject.Provider -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +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.launch +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.base.domain.MangaIntent @@ -21,7 +33,11 @@ import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.core.prefs.* +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.prefs.ReaderMode +import org.koitharu.kotatsu.core.prefs.ScreenshotsPolicy +import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.core.prefs.observeAsLiveData import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.parsers.exception.NotFoundException @@ -39,6 +55,8 @@ import org.koitharu.kotatsu.utils.ext.printStackTraceDebug import org.koitharu.kotatsu.utils.ext.processLifecycleScope import org.koitharu.kotatsu.utils.ext.requireValue import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import java.util.Date +import javax.inject.Provider private const val BOUNDS_PAGE_OFFSET = 2 private const val PREFETCH_LIMIT = 10 @@ -116,6 +134,10 @@ class ReaderViewModel @AssistedInject constructor( init { loadImpl() + settings.observe() + .onEach { key -> + if (key == AppSettings.KEY_READER_SLIDER) notifyStateChanged() + }.launchIn(viewModelScope) } override fun onCleared() { @@ -348,6 +370,7 @@ class ReaderViewModel @AssistedInject constructor( chaptersTotal = chapters.size(), totalPages = if (chapter != null) chaptersLoader.getPagesCount(chapter.id) else 0, currentPage = state?.page ?: 0, + isSliderEnabled = settings.isReaderSliderEnabled, ) uiState.postValue(newState) } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt index 7014b1a5e..1ffe455ea 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt @@ -7,8 +7,13 @@ data class ReaderUiState( val chaptersTotal: Int, val currentPage: Int, val totalPages: Int, + private val isSliderEnabled: Boolean, ) { + fun isSliderAvailable(): Boolean { + return isSliderEnabled && totalPages > 1 && currentPage < totalPages + } + fun computePercent(): Float { val ppc = 1f / chaptersTotal val chapterIndex = chapterNumber - 1 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 16906a84e..1d9453ba7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -389,4 +389,5 @@ You have unsaved changes, do you want to save or discard them? Discard No space left on device + Show page switching slider diff --git a/app/src/main/res/xml/pref_reader.xml b/app/src/main/res/xml/pref_reader.xml index dbbe245e0..1842876fa 100644 --- a/app/src/main/res/xml/pref_reader.xml +++ b/app/src/main/res/xml/pref_reader.xml @@ -45,6 +45,11 @@ android:key="reader_bar" android:title="@string/reader_info_bar" /> + +