diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 160d6801e2..36c4190220 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -53,6 +53,17 @@ object PreferenceKeys { const val readWithVolumeKeysInverted = "reader_volume_keys_inverted" + const val navigationModePager = "reader_navigation_mode_pager" + + const val navigationModeWebtoon = "reader_navigation_mode_webtoon" + + const val pagerNavInverted = "reader_tapping_inverted" + + const val webtoonNavInverted = "reader_tapping_inverted_webtoon" + + const val showNavigationOverlayNewUser = "reader_navigation_overlay_new_user" + const val showNavigationOverlayNewUserWebtoon = "reader_navigation_overlay_new_user_webtoon" + const val webtoonSidePadding = "webtoon_side_padding" const val webtoonEnableZoomOut = "webtoon_enable_zoom_out" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 16a8ab554d..0e3733bc80 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -10,6 +10,7 @@ import com.f2prateek.rx.preferences.RxSharedPreferences import com.tfcporciuncula.flow.FlowSharedPreferences import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.TrackService +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.onEach import java.io.File @@ -130,6 +131,18 @@ class PreferencesHelper(val context: Context) { fun readWithVolumeKeysInverted() = flowPrefs.getBoolean(Keys.readWithVolumeKeysInverted, false) + fun navigationModePager() = flowPrefs.getInt(Keys.navigationModePager, 0) + + fun navigationModeWebtoon() = flowPrefs.getInt(Keys.navigationModeWebtoon, 0) + + fun pagerNavInverted() = flowPrefs.getEnum(Keys.pagerNavInverted, ViewerNavigation.TappingInvertMode.NONE) + + fun webtoonNavInverted() = flowPrefs.getEnum(Keys.webtoonNavInverted, ViewerNavigation.TappingInvertMode.NONE) + + fun showNavigationOverlayNewUser() = flowPrefs.getBoolean(Keys.showNavigationOverlayNewUser, true) + + fun showNavigationOverlayNewUserWebtoon() = flowPrefs.getBoolean(Keys.showNavigationOverlayNewUserWebtoon, true) + fun updateOnlyNonCompleted() = prefs.getBoolean(Keys.updateOnlyNonCompleted, false) fun autoUpdateTrack() = prefs.getBoolean(Keys.autoUpdateTrack, true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index f2c65b62db..fc8a9a125c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -534,6 +534,7 @@ class ReaderActivity : viewer = newViewer viewer_container.addView(newViewer.getView()) + navigation_overlay.isLTR = !(viewer is L2RPagerViewer) viewer_container.setBackgroundColor( if (viewer is WebtoonViewer) { Color.BLACK diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt new file mode 100644 index 0000000000..4baeceaa18 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt @@ -0,0 +1,130 @@ +package eu.kanade.tachiyomi.ui.reader + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import android.view.ViewPropertyAnimator +import androidx.core.content.ContextCompat +import androidx.core.view.isVisible +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation +import kotlin.math.abs + +class ReaderNavigationOverlayView(context: Context, attributeSet: AttributeSet) : View(context, attributeSet) { + + private var viewPropertyAnimator: ViewPropertyAnimator? = null + + private var navigation: ViewerNavigation? = null + + var isLTR = true + + fun setNavigation(navigation: ViewerNavigation, showOnStart: Boolean) { + if (!showOnStart && (this.navigation == null || this.navigation === navigation) && !forceShowOverlay) { + if (this.navigation == null) { + this.navigation = navigation + isVisible = false + } + return + } + + forceShowOverlay = false + this.navigation = navigation + invalidate() + + if (isVisible) return + + viewPropertyAnimator = animate() + .alpha(1f) + .setDuration(FADE_DURATION) + .withStartAction { + isVisible = true + } + .withEndAction { + viewPropertyAnimator = null + } + viewPropertyAnimator?.start() + } + + private val regionPaint = Paint() + + private val textPaint = Paint().apply { + textAlign = Paint.Align.CENTER + color = Color.WHITE + textSize = 64f + } + + private val textBorderPaint = Paint().apply { + textAlign = Paint.Align.CENTER + color = Color.BLACK + textSize = 64f + style = Paint.Style.STROKE + strokeWidth = 8f + } + + override fun onDraw(canvas: Canvas?) { + if (navigation == null) return + + navigation?.regions?.forEach { + val region = it.invert(navigation!!.invertMode) + val rect = region.rectF + + canvas?.save() + + // Scale rect from 1f,1f to screen width and height + canvas?.scale(width.toFloat(), height.toFloat()) + val directionalRegion = region.type.directionalRegion(isLTR) + regionPaint.color = ContextCompat.getColor(context, directionalRegion.colorRes) + canvas?.drawRect(rect, regionPaint) + + canvas?.restore() + // Don't want scale anymore because it messes with drawText + canvas?.save() + + // Translate origin to rect start (left, top) + canvas?.translate((width * rect.left), (height * rect.top)) + + // Calculate center of rect width on screen + val x = width * (abs(rect.left - rect.right) / 2) + + // Calculate center of rect height on screen + val y = height * (abs(rect.top - rect.bottom) / 2) + + canvas?.drawText(context.getString(directionalRegion.nameRes), x, y, textBorderPaint) + canvas?.drawText(context.getString(directionalRegion.nameRes), x, y, textPaint) + + canvas?.restore() + } + } + + override fun performClick(): Boolean { + super.performClick() + + if (viewPropertyAnimator == null && isVisible) { + viewPropertyAnimator = animate() + .alpha(0f) + .setDuration(FADE_DURATION) + .withEndAction { + isVisible = false + viewPropertyAnimator = null + } + viewPropertyAnimator?.start() + } + + return true + } + + override fun onTouchEvent(event: MotionEvent?): Boolean { + // Hide overlay if user start tapping or swiping + performClick() + return super.onTouchEvent(event) + } + + companion object { + var forceShowOverlay = false + } +} + +private const val FADE_DURATION = 1000L diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderGeneralView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderGeneralView.kt index 6c37bc6929..95cc661eb1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderGeneralView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderGeneralView.kt @@ -24,7 +24,7 @@ class ReaderGeneralView @JvmOverloads constructor(context: Context, attrs: Attri initPagerPreferences() } } - viewer_series.setSelection((context as? ReaderActivity)?.presenter?.manga?.viewer ?: 0) + viewer_series.setSelection((context as? ReaderActivity)?.presenter?.getMangaViewer() ?: 0) rotation_mode.bindToPreference(preferences.rotation(), 1) background_color.bindToPreference(preferences.readerTheme(), 0) show_page_number.bindToPreference(preferences.showPageNumber()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderPagedView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderPagedView.kt index 42d53a6b34..fc2ed1ac85 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderPagedView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderPagedView.kt @@ -4,6 +4,7 @@ import android.content.Context import android.util.AttributeSet import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.ReaderActivity +import eu.kanade.tachiyomi.ui.reader.ReaderNavigationOverlayView import eu.kanade.tachiyomi.util.bindToPreference import eu.kanade.tachiyomi.util.view.visibleIf import eu.kanade.tachiyomi.widget.BaseReaderSettingsView @@ -17,6 +18,10 @@ class ReaderPagedView @JvmOverloads constructor(context: Context, attrs: Attribu zoom_start.bindToPreference(preferences.zoomStart(), 1) crop_borders.bindToPreference(preferences.cropBorders()) page_transitions.bindToPreference(preferences.pageTransitions()) + pager_nav.bindToPreference(preferences.navigationModePager()) + pager_invert.bindToPreference(preferences.pagerNavInverted()) { + ReaderNavigationOverlayView.forceShowOverlay = true + } val mangaViewer = (context as ReaderActivity).presenter.getMangaViewer() val isWebtoonView = mangaViewer == ReaderActivity.WEBTOON || mangaViewer == ReaderActivity.VERTICAL_PLUS @@ -24,6 +29,10 @@ class ReaderPagedView @JvmOverloads constructor(context: Context, attrs: Attribu crop_borders_webtoon.bindToPreference(if (hasMargins) preferences.cropBorders() else preferences.cropBordersWebtoon()) webtoon_side_padding.bindToIntPreference(preferences.webtoonSidePadding(), R.array.webtoon_side_padding_values) webtoon_enable_zoom_out.bindToPreference(preferences.webtoonEnableZoomOut()) + webtoon_nav.bindToPreference(preferences.navigationModeWebtoon()) + webtoon_invert.bindToPreference(preferences.webtoonNavInverted()) { + ReaderNavigationOverlayView.forceShowOverlay = true + } updatePagedGroup(!isWebtoonView) } @@ -36,8 +45,8 @@ class ReaderPagedView @JvmOverloads constructor(context: Context, attrs: Attribu updatePagedGroup(!isWebtoonView) } - fun updatePagedGroup(show: Boolean) { - listOf(scale_type, zoom_start, crop_borders, page_transitions).forEach { it.visibleIf(show) } - listOf(crop_borders_webtoon, webtoon_side_padding, webtoon_enable_zoom_out).forEach { it.visibleIf(!show) } + private fun updatePagedGroup(show: Boolean) { + listOf(scale_type, zoom_start, crop_borders, page_transitions, pager_nav, pager_invert).forEach { it.visibleIf(show) } + listOf(crop_borders_webtoon, webtoon_side_padding, webtoon_enable_zoom_out, webtoon_nav, webtoon_invert).forEach { it.visibleIf(!show) } } } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderSpinnerView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderSpinnerView.kt index 11ce61f2f3..0c602308af 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderSpinnerView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/settings/ReaderSpinnerView.kt @@ -21,26 +21,28 @@ class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: Attri private var selectedPosition = 0 private var pref: Preference? = null private var prefOffset = 0 + private var popup:PopupMenu? = null + var onItemSelectedListener: ((Int) -> Unit)? = null set(value) { field = value if (value != null) { - val popup = makeSettingsPopup() - setOnTouchListener(popup.dragToOpenListener) + popup = makeSettingsPopup() + setOnTouchListener(popup?.dragToOpenListener) setOnClickListener { - popup.show() + popup?.show() } } } init { inflate(context, R.layout.reader_preference, this) - val a = context.obtainStyledAttributes(attrs, R.styleable.ReaderPreferenceView, 0, 0) + val a = context.obtainStyledAttributes(attrs, R.styleable.ReaderSpinnerView, 0, 0) - val str = a.getString(R.styleable.ReaderPreferenceView_title) ?: "" + val str = a.getString(R.styleable.ReaderSpinnerView_title) ?: "" title_view.text = str - val entries = (a.getTextArray(R.styleable.ReaderPreferenceView_android_entries) ?: emptyArray()).map { it.toString() } + val entries = (a.getTextArray(R.styleable.ReaderSpinnerView_android_entries) ?: emptyArray()).map { it.toString() } this.entries = entries detail_view.text = entries.firstOrNull().orEmpty() @@ -49,15 +51,39 @@ class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: Attri } fun setSelection(selection: Int) { + popup?.menu?.get(selectedPosition)?.isCheckable = false + popup?.menu?.get(selectedPosition)?.isChecked = false selectedPosition = selection detail_view.text = entries.getOrNull(selection).orEmpty() + popup?.menu?.get(selectedPosition)?.isCheckable = true + popup?.menu?.get(selectedPosition)?.isChecked = true } fun bindToPreference(pref: Preference, offset: Int = 0, block: ((Int) -> Unit)? = null) { setSelection(pref.get() - offset) this.pref = pref prefOffset = offset - val popup = makeSettingsPopup(pref, prefOffset, block) + popup = makeSettingsPopup(pref, prefOffset, block) + setOnTouchListener(popup?.dragToOpenListener) + setOnClickListener { + popup?.show() + } + } + + inline fun > bindToPreference(pref: Preference) { + val enumConstants = T::class.java.enumConstants + enumConstants?.indexOf(pref.get())?.let { setSelection(it) } + val popup = makeSettingsPopup(pref) + setOnTouchListener(popup.dragToOpenListener) + setOnClickListener { + popup.show() + } + } + + inline fun > bindToPreference(pref: Preference, crossinline block: ((Int) -> Unit)) { + val enumConstants = T::class.java.enumConstants + enumConstants?.indexOf(pref.get())?.let { setSelection(it) } + val popup = makeSettingsPopup(pref, block) setOnTouchListener(popup.dragToOpenListener) setOnClickListener { popup.show() @@ -69,13 +95,45 @@ class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: Attri this.pref = pref prefOffset = 0 val intValues = resources.getStringArray(intValuesResource).map { it.toIntOrNull() } - val popup = makeSettingsPopup(pref, intValues, block) - setOnTouchListener(popup.dragToOpenListener) + popup = makeSettingsPopup(pref, intValues, block) + setOnTouchListener(popup?.dragToOpenListener) setOnClickListener { - popup.show() + popup?.show() } } + inline fun > makeSettingsPopup(preference: Preference): PopupMenu { + val popup = popup() + + // Set a listener so we are notified if a menu item is clicked + popup.setOnMenuItemClickListener { menuItem -> + val pos = popup.menuClicked(menuItem) + onItemSelectedListener?.invoke(pos) + true + } + // Set a listener so we are notified if a menu item is clicked + popup.setOnMenuItemClickListener { menuItem -> + val enumConstants = T::class.java.enumConstants + val pos = popup.menuClicked(menuItem) + enumConstants?.get(pos)?.let { preference.set(it) } + true + } + return popup + } + + inline fun > makeSettingsPopup(preference: Preference, crossinline block: ((Int) -> Unit)): PopupMenu { + val popup = popup() + // Set a listener so we are notified if a menu item is clicked + popup.setOnMenuItemClickListener { menuItem -> + val enumConstants = T::class.java.enumConstants + val pos = popup.menuClicked(menuItem) + enumConstants?.get(pos)?.let { preference.set(it) } + block(pos) + true + } + return popup + } + private fun makeSettingsPopup(preference: Preference, intValues: List, block: ((Int) -> Unit)? = null): PopupMenu { val popup = popup() // Set a listener so we are notified if a menu item is clicked @@ -112,7 +170,7 @@ class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: Attri return popup } - private fun PopupMenu.menuClicked(menuItem: MenuItem): Int { + fun PopupMenu.menuClicked(menuItem: MenuItem): Int { val pos = menuItem.itemId menu[selectedPosition].isCheckable = false menu[selectedPosition].isChecked = false @@ -122,7 +180,7 @@ class ReaderSpinnerView @JvmOverloads constructor(context: Context, attrs: Attri return pos } - private fun popup(): PopupMenu { + fun popup(): PopupMenu { val popup = PopupMenu(context, this, Gravity.END) entries.forEachIndexed { index, entry -> popup.menu.add(0, index, 0, entry) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt index 1aeef22345..f52a3c5f7b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt @@ -17,12 +17,23 @@ abstract class ViewerConfig(preferences: PreferencesHelper) { var imagePropertyChangedListener: (() -> Unit)? = null + var navigationModeChangedListener: (() -> Unit)? = null + var tappingEnabled = true + var tappingInverted = ViewerNavigation.TappingInvertMode.NONE var doubleTapAnimDuration = 500 var volumeKeysEnabled = false var volumeKeysInverted = false var alwaysShowChapterTransition = true + + var navigationOverlayForNewUser = false + var navigationMode = 0 + protected set + + abstract var navigator: ViewerNavigation + protected set + init { preferences.readWithTapping() .register({ tappingEnabled = it }) @@ -51,4 +62,8 @@ abstract class ViewerConfig(preferences: PreferencesHelper) { } .launchIn(scope) } + + protected abstract fun defaultNavigation(): ViewerNavigation + + abstract fun updateNavigation(navigationMode: Int) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerNavigation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerNavigation.kt new file mode 100644 index 0000000000..2bd5d79848 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerNavigation.kt @@ -0,0 +1,72 @@ +package eu.kanade.tachiyomi.ui.reader.viewer + +import android.graphics.PointF +import android.graphics.RectF +import androidx.annotation.StringRes +import eu.kanade.tachiyomi.R + +abstract class ViewerNavigation { + + sealed class NavigationRegion(@StringRes val nameRes: Int, val colorRes: Int) { + object MENU : NavigationRegion(R.string.menu, R.color.navigation_menu) + object PREV : NavigationRegion(R.string.previous, R.color.navigation_prev) + object NEXT : NavigationRegion(R.string.next, R.color.navigation_next) + object LEFT : NavigationRegion(R.string.left, R.color.navigation_left) + object RIGHT : NavigationRegion(R.string.right, R.color.navigation_right) + + fun directionalRegion(LTR: Boolean): NavigationRegion { + return if (this === LEFT || this === RIGHT) { + if (if (LTR) this === LEFT else this === RIGHT) NEXT else PREV + } + else this + } + } + + data class Region( + val rectF: RectF, + val type: NavigationRegion + ) { + fun invert(invertMode: TappingInvertMode): Region { + if (invertMode == TappingInvertMode.NONE) return this + return this.copy( + rectF = this.rectF.invert(invertMode) + ) + } + } + + private var constantMenuRegion: RectF = RectF(0f, 0f, 1f, 0.05f) + + abstract var regions: List + + var invertMode: TappingInvertMode = TappingInvertMode.NONE + + fun getAction(pos: PointF): NavigationRegion { + val x = pos.x + val y = pos.y + val region = regions.map { it.invert(invertMode) } + .find { it.rectF.contains(x, y) } + return when { + region != null -> region.type + constantMenuRegion.contains(x, y) -> NavigationRegion.MENU + else -> NavigationRegion.MENU + } + } + + enum class TappingInvertMode(val shouldInvertHorizontal: Boolean = false, val shouldInvertVertical: Boolean = false) { + NONE, + HORIZONTAL(shouldInvertHorizontal = true), + VERTICAL(shouldInvertVertical = true), + BOTH(shouldInvertHorizontal = true, shouldInvertVertical = true) + } +} + +fun RectF.invert(invertMode: ViewerNavigation.TappingInvertMode): RectF { + val horizontal = invertMode.shouldInvertHorizontal + val vertical = invertMode.shouldInvertVertical + return when { + horizontal && vertical -> RectF(1f - this.right, 1f - this.bottom, 1f - this.left, 1f - this.top) + vertical -> RectF(this.left, 1f - this.bottom, this.right, 1f - this.top) + horizontal -> RectF(1f - this.right, this.top, 1f - this.left, this.bottom) + else -> this + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/EdgeNavigation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/EdgeNavigation.kt new file mode 100644 index 0000000000..c06c703a34 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/EdgeNavigation.kt @@ -0,0 +1,32 @@ +package eu.kanade.tachiyomi.ui.reader.viewer.navigation + +import android.graphics.RectF +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation + +/** + * Visualization of default state without any inversion + * +---+---+---+ + * | N | N | N | P: Previous + * +---+---+---+ + * | N | M | N | M: Menu + * +---+---+---+ + * | N | P | N | N: Next + * +---+---+---+ +*/ +class EdgeNavigation : ViewerNavigation() { + + override var regions: List = listOf( + Region( + rectF = RectF(0f, 0f, 0.33f, 1f), + type = NavigationRegion.NEXT + ), + Region( + rectF = RectF(0.33f, 0.66f, 0.66f, 1f), + type = NavigationRegion.PREV + ), + Region( + rectF = RectF(0.66f, 0f, 1f, 1f), + type = NavigationRegion.NEXT + ), + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/KindlishNavigation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/KindlishNavigation.kt new file mode 100644 index 0000000000..43c081f870 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/KindlishNavigation.kt @@ -0,0 +1,28 @@ +package eu.kanade.tachiyomi.ui.reader.viewer.navigation + +import android.graphics.RectF +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation + +/** + * Visualization of default state without any inversion + * +---+---+---+ + * | M | M | M | P: Previous + * +---+---+---+ + * | P | N | N | M: Menu + * +---+---+---+ + * | P | N | N | N: Next + * +---+---+---+ +*/ +class KindlishNavigation : ViewerNavigation() { + + override var regions: List = listOf( + Region( + rectF = RectF(0.33f, 0.33f, 1f, 1f), + type = NavigationRegion.NEXT + ), + Region( + rectF = RectF(0f, 0.33f, 0.33f, 1f), + type = NavigationRegion.PREV + ) + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/LNavigation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/LNavigation.kt new file mode 100644 index 0000000000..6d3390818a --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/LNavigation.kt @@ -0,0 +1,36 @@ +package eu.kanade.tachiyomi.ui.reader.viewer.navigation + +import android.graphics.RectF +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation + +/** + * Visualization of default state without any inversion + * +---+---+---+ + * | P | P | P | P: Previous + * +---+---+---+ + * | P | M | N | M: Menu + * +---+---+---+ + * | N | N | N | N: Next + * +---+---+---+ + */ +open class LNavigation : ViewerNavigation() { + + override var regions: List = listOf( + Region( + rectF = RectF(0f, 0.33f, 0.33f, 0.66f), + type = NavigationRegion.PREV + ), + Region( + rectF = RectF(0f, 0f, 1f, 0.33f), + type = NavigationRegion.PREV + ), + Region( + rectF = RectF(0.66f, 0.33f, 1f, 0.66f), + type = NavigationRegion.NEXT + ), + Region( + rectF = RectF(0f, 0.66f, 1f, 1f), + type = NavigationRegion.NEXT + ) + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/RightAndLeftNavigation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/RightAndLeftNavigation.kt new file mode 100644 index 0000000000..f0df1afa2d --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/RightAndLeftNavigation.kt @@ -0,0 +1,28 @@ +package eu.kanade.tachiyomi.ui.reader.viewer.navigation + +import android.graphics.RectF +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation + +/** + * Visualization of default state without any inversion + * +---+---+---+ + * | N | M | P | P: Move Right + * +---+---+---+ + * | N | M | P | M: Menu + * +---+---+---+ + * | N | M | P | N: Move Left + * +---+---+---+ + */ +class RightAndLeftNavigation : ViewerNavigation() { + + override var regions: List = listOf( + Region( + rectF = RectF(0f, 0f, 0.33f, 1f), + type = NavigationRegion.LEFT + ), + Region( + rectF = RectF(0.66f, 0f, 1f, 1f), + type = NavigationRegion.RIGHT + ), + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt index c6ac8ad7ce..9a7d10cc9c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt @@ -2,6 +2,11 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.reader.viewer.ViewerConfig +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.EdgeNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.KindlishNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.RightAndLeftNavigation import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -33,6 +38,15 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe preferences.imageScaleType() .register({ imageScaleType = it }, { imagePropertyChangedListener?.invoke() }) + preferences.navigationModePager() + .register({ navigationMode = it }, { updateNavigation(navigationMode) }) + + preferences.pagerNavInverted() + .register({ tappingInverted = it }, { + navigator.invertMode = it + navigationModeChangedListener?.invoke() + }) + preferences.zoomStart() .register({ zoomTypeFromPreference(it) }, { imagePropertyChangedListener?.invoke() }) @@ -41,6 +55,11 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe preferences.readerTheme() .register({ readerTheme = it }, { imagePropertyChangedListener?.invoke() }) + + navigationOverlayForNewUser = preferences.showNavigationOverlayNewUser().get() + if (navigationOverlayForNewUser) { + preferences.showNavigationOverlayNewUser().set(false) + } } private fun zoomTypeFromPreference(value: Int) { @@ -60,6 +79,30 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe } } + override var navigator: ViewerNavigation = defaultNavigation() + set(value) { + field = value.also { it.invertMode = this.tappingInverted } + } + + override fun defaultNavigation(): ViewerNavigation { + return when (viewer) { + is VerticalPagerViewer -> LNavigation() + else -> RightAndLeftNavigation() + } + } + + override fun updateNavigation(navigationMode: Int) { + navigator = when (navigationMode) { + 0 -> defaultNavigation() + 1 -> LNavigation() + 2 -> KindlishNavigation() + 3 -> EdgeNavigation() + 4 -> RightAndLeftNavigation() + else -> defaultNavigation() + } + navigationModeChangedListener?.invoke() + } + enum class ZoomType { Left, Center, Right } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt index da50e94ace..c7280be0a3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt @@ -93,11 +93,11 @@ class PagerTransitionHolder( textView.text = if (nextChapter != null) { SpannableStringBuilder().apply { - append(context.getString(R.string.finished)) + append(context.getString(R.string.finished_chapter)) setSpan(StyleSpan(Typeface.BOLD), 0, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${transition.from.chapter.name}\n\n") val currSize = length - append(context.getString(R.string.next)) + append(context.getString(R.string.next_chapter)) setSpan(StyleSpan(Typeface.BOLD), currSize, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${nextChapter.chapter.name}\n\n") } @@ -118,11 +118,11 @@ class PagerTransitionHolder( textView.text = if (prevChapter != null) { SpannableStringBuilder().apply { - append(context.getString(R.string.current)) + append(context.getString(R.string.current_chapter)) setSpan(StyleSpan(Typeface.BOLD), 0, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${transition.from.chapter.name}\n\n") val currSize = length - append(context.getString(R.string.previous)) + append(context.getString(R.string.previous_chapter)) setSpan(StyleSpan(Typeface.BOLD), currSize, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${prevChapter.chapter.name}\n\n") } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt index 36e48b0b21..f73059db40 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager +import android.graphics.PointF import android.view.InputDevice import android.view.KeyEvent import android.view.MotionEvent @@ -12,8 +13,10 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.visible +import kotlinx.android.synthetic.main.reader_activity.* import timber.log.Timber /** @@ -81,18 +84,31 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer { } } ) - pager.tapListener = { event -> - val positionX = event.x - when { - positionX < pager.width * 0.33f && config.tappingEnabled -> moveLeft() - positionX > pager.width * 0.66f && config.tappingEnabled -> moveRight() - else -> activity.toggleMenu() + pager.tapListener = f@{ event -> + if (!config.tappingEnabled) { + activity.toggleMenu() + return@f + } + + val pos = PointF(event.rawX / pager.width, event.rawY / pager.height) + val navigator = config.navigator + when (navigator.getAction(pos)) { + ViewerNavigation.NavigationRegion.MENU -> activity.toggleMenu() + ViewerNavigation.NavigationRegion.NEXT -> moveToNext() + ViewerNavigation.NavigationRegion.PREV -> moveToPrevious() + ViewerNavigation.NavigationRegion.RIGHT -> moveRight() + ViewerNavigation.NavigationRegion.LEFT -> moveLeft() } } config.imagePropertyChangedListener = { refreshAdapter() } + + config.navigationModeChangedListener = { + val showOnStart = config.navigationOverlayForNewUser + activity.navigation_overlay.setNavigation(config.navigator, showOnStart) + } } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt index 5070c63cf0..82de7c05a7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt @@ -2,6 +2,11 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.reader.viewer.ViewerConfig +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.EdgeNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.KindlishNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation +import eu.kanade.tachiyomi.ui.reader.viewer.navigation.RightAndLeftNavigation import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -21,9 +26,19 @@ class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) : ViewerConfi var enableZoomOut = false private set + var zoomPropertyChangedListener: ((Boolean) -> Unit)? = null init { + preferences.navigationModeWebtoon() + .register({ navigationMode = it }, { updateNavigation(it) }) + + preferences.webtoonNavInverted() + .register({ tappingInverted = it }, { + navigator.invertMode = it + navigationModeChangedListener?.invoke() + }) + preferences.cropBordersWebtoon() .register({ webtoonCropBorders = it }, { imagePropertyChangedListener?.invoke() }) @@ -35,5 +50,31 @@ class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) : ViewerConfi preferences.webtoonEnableZoomOut() .register({ enableZoomOut = it }, { zoomPropertyChangedListener?.invoke(it) }) + + navigationOverlayForNewUser = preferences.showNavigationOverlayNewUserWebtoon().get() + if (navigationOverlayForNewUser) { + preferences.showNavigationOverlayNewUserWebtoon().set(false) + } + } + + override var navigator: ViewerNavigation = defaultNavigation() + set(value) { + field = value.also { it.invertMode = tappingInverted } + } + + override fun defaultNavigation(): ViewerNavigation { + return LNavigation() + } + + override fun updateNavigation(navigationMode: Int) { + this.navigator = when (navigationMode) { + 0 -> defaultNavigation() + 1 -> LNavigation() + 2 -> KindlishNavigation() + 3 -> EdgeNavigation() + 4 -> RightAndLeftNavigation() + else -> defaultNavigation() + } + navigationModeChangedListener?.invoke() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt index bb8050d757..de96dd3616 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt @@ -95,11 +95,11 @@ class WebtoonTransitionHolder( textView.text = if (nextChapter != null) { SpannableStringBuilder().apply { - append(context.getString(R.string.finished)) + append(context.getString(R.string.finished_chapter)) setSpan(StyleSpan(Typeface.BOLD), 0, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${transition.from.chapter.name}\n\n") val currSize = length - append(context.getString(R.string.next)) + append(context.getString(R.string.next_chapter)) setSpan(StyleSpan(Typeface.BOLD), currSize, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${nextChapter.chapter.name}\n\n") } @@ -120,11 +120,11 @@ class WebtoonTransitionHolder( textView.text = if (prevChapter != null) { SpannableStringBuilder().apply { - append(context.getString(R.string.current)) + append(context.getString(R.string.current_chapter)) setSpan(StyleSpan(Typeface.BOLD), 0, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${transition.from.chapter.name}\n\n") val currSize = length - append(context.getString(R.string.previous)) + append(context.getString(R.string.previous_chapter)) setSpan(StyleSpan(Typeface.BOLD), currSize, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) append("\n${prevChapter.chapter.name}\n\n") } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt index fc380cbab9..6844b60100 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt @@ -1,6 +1,7 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon import android.graphics.Color +import android.graphics.PointF import android.view.KeyEvent import android.view.MotionEvent import android.view.View @@ -13,7 +14,9 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation import eu.kanade.tachiyomi.util.view.visible +import kotlinx.android.synthetic.main.reader_activity.* import rx.subscriptions.CompositeSubscription import timber.log.Timber import kotlin.math.max @@ -95,15 +98,21 @@ class WebtoonViewer(val activity: ReaderActivity, val hasMargins: Boolean = fals } } ) - recycler.tapListener = { event -> - val positionX = event.rawX - val positionY = event.rawY - when { - positionY < recycler.height * 0.25 && config.tappingEnabled -> scrollUp() - positionY > recycler.height * 0.75 && config.tappingEnabled -> scrollDown() - positionX < recycler.width * 0.33 && config.tappingEnabled -> scrollUp() - positionX > recycler.width * 0.66 && config.tappingEnabled -> scrollDown() - else -> activity.toggleMenu() + recycler.tapListener = f@{ event -> + if (!config.tappingEnabled) { + activity.toggleMenu() + return@f + } + + val pos = PointF(event.rawX / recycler.width, event.rawY / recycler.height) + if (!config.tappingEnabled) activity.toggleMenu() + else { + val navigator = config.navigator + when (navigator.getAction(pos)) { + ViewerNavigation.NavigationRegion.MENU -> activity.toggleMenu() + ViewerNavigation.NavigationRegion.NEXT, ViewerNavigation.NavigationRegion.RIGHT -> scrollDown() + ViewerNavigation.NavigationRegion.PREV, ViewerNavigation.NavigationRegion.LEFT -> scrollUp() + } } } @@ -115,6 +124,11 @@ class WebtoonViewer(val activity: ReaderActivity, val hasMargins: Boolean = fals frame.enableZoomOut = it } + config.navigationModeChangedListener = { + val showOnStart = config.navigationOverlayForNewUser + activity.navigation_overlay.setNavigation(config.navigator, showOnStart) + } + frame.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT) frame.addView(recycler) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt index 0c4b90d50b..d211791354 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt @@ -4,6 +4,7 @@ import android.os.Build import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.asImmediateFlow +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation import kotlinx.coroutines.flow.launchIn import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys @@ -43,7 +44,7 @@ class SettingsReaderController : SettingsController() { } switchPreference { key = Keys.enableTransitions - titleRes = R.string.page_transitions + titleRes = R.string.animate_page_transitions defaultValue = true } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -124,6 +125,38 @@ class SettingsReaderController : SettingsController() { preferenceCategory { titleRes = R.string.paged + intListPreference(activity) { + key = Keys.navigationModePager + titleRes = R.string.nav_layout + entries = context.resources.getStringArray(R.array.reader_nav).also { values -> + entryRange = 0..values.size + }.toList() + defaultValue = "0" + summary = "%s" + + preferences.readWithTapping().asImmediateFlow { isVisible = it }.launchIn(viewScope) + } + listPreference(activity) { + key = Keys.pagerNavInverted + titleRes = R.string.invert_tapping + entriesRes = arrayOf( + R.string.none, + R.string.horizontally, + R.string.vertically, + R.string.both_axes + ) + entryValues = listOf( + ViewerNavigation.TappingInvertMode.NONE.name, + ViewerNavigation.TappingInvertMode.HORIZONTAL.name, + ViewerNavigation.TappingInvertMode.VERTICAL.name, + ViewerNavigation.TappingInvertMode.BOTH.name + ) + defaultValue = ViewerNavigation.TappingInvertMode.NONE.name + summary = "%s" + + preferences.readWithTapping().asImmediateFlow { isVisible = it }.launchIn(viewScope) + } + intListPreference(activity) { key = Keys.imageScaleType titleRes = R.string.scale_type @@ -159,6 +192,38 @@ class SettingsReaderController : SettingsController() { preferenceCategory { titleRes = R.string.webtoon + intListPreference(activity) { + key = Keys.navigationModeWebtoon + titleRes = R.string.nav_layout + entries = context.resources.getStringArray(R.array.reader_nav).also { values -> + entryRange = 0..values.size + }.toList() + defaultValue = "0" + summary = "%s" + + preferences.readWithTapping().asImmediateFlow { isVisible = it }.launchIn(viewScope) + } + listPreference(activity) { + key = Keys.webtoonNavInverted + titleRes = R.string.invert_tapping + entriesRes = arrayOf( + R.string.none, + R.string.horizontally, + R.string.vertically, + R.string.both_axes + ) + entryValues = listOf( + ViewerNavigation.TappingInvertMode.NONE.name, + ViewerNavigation.TappingInvertMode.HORIZONTAL.name, + ViewerNavigation.TappingInvertMode.VERTICAL.name, + ViewerNavigation.TappingInvertMode.BOTH.name + ) + defaultValue = ViewerNavigation.TappingInvertMode.NONE.name + summary = "%s" + + preferences.readWithTapping().asImmediateFlow { isVisible = it }.launchIn(viewScope) + } + switchPreference { key = Keys.cropBordersWebtoon titleRes = R.string.crop_borders diff --git a/app/src/main/res/layout/reader_activity.xml b/app/src/main/res/layout/reader_activity.xml index 09e049db06..3ff8aec711 100644 --- a/app/src/main/res/layout/reader_activity.xml +++ b/app/src/main/res/layout/reader_activity.xml @@ -34,6 +34,12 @@ android:layout_height="match_parent" android:visibility="gone" /> + + + + + + + + + تحديد ترحيل نسخ - تمَّ الانتهاء من: - الحالي: - التّالي: - السّابق: + تمَّ الانتهاء من: + الحالي: + التّالي: + السّابق: لا يوجدُ فصل تالي لا يوجدُ فصل سابق جار تحميل الصّفحات… diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index b6b8f0e2ed..3159295ad2 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -331,10 +331,10 @@ Начало Тип Мангата няма връзка с акаунта, молим отново да натиснете заглавието и да изберете мангата - Завършени: - Текущи: - Следва: - Предишна: + Завършени: + Текущи: + Следва: + Предишна: Няма повече глави Няма предишна глава Зареждане на страниците… diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index b105584ecf..17ca25339e 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -296,10 +296,10 @@ শুরু হয়েছে ধরণ গাঢ় নীল - "শেষ :" - "এখনকার :" - আসছে : - পূর্ববর্তী : + "শেষ :" + "এখনকার :" + আসছে : + পূর্ববর্তী : কোন পরের অধ্যায় আছে কোন পূর্ববর্তী অধ্যায় আছে পৃষ্ঠা লোড হচ্ছে … diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index abce7a39e1..d417f8bf64 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -272,10 +272,10 @@ No s\'ha pogut descodificar la imatge Voleu definir aquesta imatge com a portada\? Lector per a aquesta sèrie - Finalitzat: - Actual: - Següent: - Anterior: + Finalitzat: + Actual: + Següent: + Anterior: No hi ha capítol següent No hi ha capítol anterior S\'estan carregant les pàgines… diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 27ffbb482b..583584b722 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -138,10 +138,10 @@ Stránka: %1$d Další kapitola nenalezena Obrázek nemohl být dekódován - Dokončeno: - Aktuální: - Následující: - Předchozí: + Dokončeno: + Aktuální: + Následující: + Předchozí: Žádná další kapitola Žádná předchozí kapitola Načítání stránek… diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 8375d5ac9c..bead67663d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -269,10 +269,10 @@ Das Bild konnte nicht dekodiert werden Wollen Sie dieses Bild als Vorschaubild setzen? Leser dieser Serie - Beendet: - Aktuell: - Nächste: - Vorherige: + Beendet: + Aktuell: + Nächste: + Vorherige: Es gibt kein nächstes Kapitel Es gibt kein vorheriges Kapitel Lade Seiten… diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 983d7d1c2c..f65260f79a 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -270,10 +270,10 @@ Δεν ήταν δυνατή η αποκωδικοποίηση της εικόνας Θέλετε να ορίσετε αυτήν την εικόνα ως εξώφυλλο; Αναγνώστης για αυτήν τη σειρά - Διαβασμένο: - Τρέχον: - Επόμενο: - Προηγούμενο: + Διαβασμένο: + Τρέχον: + Επόμενο: + Προηγούμενο: Δεν υπάρχει επόμενο κεφάλαιο Δεν υπάρχει προηγούμενο κεφάλαιο Φόρτωση σελίδων… diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 6834529db1..3de0ab2b38 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -304,8 +304,8 @@ También asegúrese de haber iniciado sesión en las fuentes que lo requieren an Idioma: %1$s Normal Rápida - Siguiente: - Anterior: + Siguiente: + Anterior: No hay capítulo siguiente No hay capítulo anterior Migrar @@ -325,8 +325,8 @@ También asegúrese de haber iniciado sesión en las fuentes que lo requieren an Empezado Tipo La dirección del manga no está fijada, por favor haga clic en el título y seleccione el manga de nuevo - Finalizado: - Actual: + Finalizado: + Actual: Cargando páginas… Error al cargar páginas: %1$s Seleccionar diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 49237a744c..1bd45c6993 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -27,10 +27,10 @@ Kuvaa ei voitu decoodata Haluatko asettaa tämän kuvan kansikuvaksi\? Katselin tälle sarjalle - Valmistunut: - Nykyinen: - Seuraava: - Aiempi: + Valmistunut: + Nykyinen: + Seuraava: + Aiempi: Seuraavaa lukua ei ole Aiempaa lukua ei ole Ladataan sivuja… diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8417a1af66..a170ee990f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -327,10 +327,10 @@ Assurez-vous que vous êtes connecté à des sources qui le demande avant de com Non fiable Pager Relecture - A jour : - En cours : - Suivant : - Précédent : + A jour : + En cours : + Suivant : + Précédent : C\'était le dernier chapitre Il n\'y a pas de chapitre précédent Chargement des pages… diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 6149afd20d..7a6df4de49 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -293,10 +293,10 @@ शुरू कर दिया है प्रकार मंगा यूआरएल सेट नहीं है कृपया शीर्षक पर क्लिक करें और फिर मंगा का चयन करें - समाप्त: - प्रचलित: - अगला: - पिछला: + समाप्त: + प्रचलित: + अगला: + पिछला: कोई अगला अध्याय नहीं है कोई पिछला अध्याय नहीं है पेज लोड हो रहे है … diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index c3c5462c11..e75e7c3487 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -294,10 +294,10 @@ Tipe URL Manga belum siap, silahkan klik judul dan pilih manga lagi Biru gelap - Selesai: - Saat ini: - Selanjutnya: - Sebelumnya: + Selesai: + Saat ini: + Selanjutnya: + Sebelumnya: Tidak ada chapter lanjutannya Tidak ada chapter sebelumnya Memuat halaman… diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index c07d1ba6af..d06b114aa8 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -328,10 +328,10 @@ Migrare Copia Comune - Finito: - Corrente: - Prossimo: - Precedente: + Finito: + Corrente: + Prossimo: + Precedente: Nessun capitolo successivo Nessun capitolo precedente Caricamento pagine… diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 3d9ae36390..bf2125ae67 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -213,10 +213,10 @@ 이미지를 디코드 할 수 없습니다 이 이미지를 표지로 설정하시겠습니까\? 이 시리즈에 대한 뷰어 - 완료: - 현재: - 다음: - 이전: + 완료: + 현재: + 다음: + 이전: 다움 챕터가 없습니다 이전 챕터가 없습니다 페이지 로딩중… diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index 909a782eab..38ee76653f 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -297,10 +297,10 @@ Bermula Jenis Manga url tidak ditetapkan, sila klik tajuk dan pilih manga sekali lagi - Selesai: - Sekarang: - Seterusnya: - Sebelumnya: + Selesai: + Sekarang: + Seterusnya: + Sebelumnya: Tiada bab seterusnya dijumpai Tiada bab sebelumnya dijumpai Memuatkan halaman… diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index f956748f3b..701d012735 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -261,10 +261,10 @@ Side: %1$d Fant ikke neste kapittel Kunne ikke dekode bildet - Fullført: - Nåværende: - Neste: - Forrige: + Fullført: + Nåværende: + Neste: + Forrige: Det finnes ikke flere kapittel Det er ikke noe tidligere kapittel Laster inn sider… diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index fbb9f2dbf5..18520562e3 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -294,10 +294,10 @@ Zorg ook dat je ingelogd bent voor bronnen die dit vereisen alvorens je het teru Gestart Soort Manga url is niet ingesteld, klik alstublieft op de titel en selecteer de manga opnieuw - Afgerond: - Huidige: - Volgende: - Vorige: + Afgerond: + Huidige: + Volgende: + Vorige: Er is geen volgend hoofdstuk Er is geen vorig hoofdstuk Pagina\'s aan het laden… diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 91f3e1101a..5821164917 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -280,10 +280,10 @@ Nie udało się wczytać obrazka Czy chcesz ustawić ten obrazek jako okładkę? Widok dla tej serii - Przeczytany: - Obecny: - Następny: - Poprzedni: + Przeczytany: + Obecny: + Następny: + Poprzedni: Brak następnego rozdziału Brak wcześniejszych rozdziałów Ładowanie stron... diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index a1459af875..885a1718aa 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -273,10 +273,10 @@ Não foi possível descodificar a imagem Deseja usar esta imagem como capa? Leitura para esta série - Concluído: - Atual: - Próximo: - Anterior: + Concluído: + Atual: + Próximo: + Anterior: Não há próximo capítulo Não há capítulo anterior Carregando páginas… diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 9b21ab3869..3a4ef2ea03 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -321,10 +321,10 @@ Usar como capa Capa atualizada Deseja usar esta imagem como capa\? - Concluído: - Atual: - Próximo: - Anterior: + Concluído: + Atual: + Próximo: + Anterior: Não há próximo capítulo Não há capítulo anterior Carregando páginas… diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 23fa3dd23e..b613bbb389 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -269,10 +269,10 @@ Imaginea nu a putu fi decodată Doriți să setați această imagine drept copertă\? Cititor al acestei serii - Terminat: - Actual: - Următorul: - Precedent: + Terminat: + Actual: + Următorul: + Precedent: Nu există capitolul următor Nu există capitolul precedent Încărcând paginile… diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 7f703521b5..11364258e7 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -471,14 +471,14 @@ - Текущая: - Закончена: - Следующая: + Текущая: + Закончена: + Следующая: Следующей части нет Предыдущей части нет Не удалось загрузить страницы: %1$s Идёт загрузка страниц… - Предыдущая: + Предыдущая: Неизвестно Неизвестная ошибка diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index a271022a6f..9fd54c6211 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -271,10 +271,10 @@ No est istadu possìbile decodificare s\'immàgine Cheres impostare custa immàgine comente cobertedda\? Visualizadore pro custa sèrie - Acabadu: - Atuale: - Imbeniente: - Antepostu: + Acabadu: + Atuale: + Imbeniente: + Antepostu: Non b\'at unu capìtulu imbeniente Non b\'at unu capìtulu antepostu Carrighende pàginas… diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 0e7eff4a9b..4b03df0b56 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -270,10 +270,10 @@ Bilden kunde inte avkodas Vill du ställa in denna bilden som omslaget\? Visare för denna serie - Färdig: - Nuvarande: - Nästa: - Tidigare: + Färdig: + Nuvarande: + Nästa: + Tidigare: Det finns inget mer kapitel Det finns inget tidigare kapitel Laddar sidor… diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index b5ea0ecbcb..46b48a2665 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -282,10 +282,10 @@ ไม่สามารถถอดรหัสรูปภาพได้ คุณต้องการที่จะตั้งค่าภาพเป็นภาพที่ปกใช่มั้ย\? ตัวแสดงสำหรับชุดนี้ - เสร็จแล้ว: - ปัจจุบัน: - ต่อไป: - ก่อนหน้า: + เสร็จแล้ว: + ปัจจุบัน: + ต่อไป: + ก่อนหน้า: ไม่มีบทต่อไป ไม่มีบทก่อนหน้านี้ กำลังโหลดหน้า … diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml index 5acc0bee1f..1f3139b3ee 100644 --- a/app/src/main/res/values-tl/strings.xml +++ b/app/src/main/res/values-tl/strings.xml @@ -283,10 +283,10 @@ Hindi ma-decode ang larawan Gusto mo bang i-set ang larawang ito bilang pabalat\? Viewer para sa seryeng ito - Natapos: - Kasalukuyan: - Susunod: - Nakaraan: + Natapos: + Kasalukuyan: + Susunod: + Nakaraan: Walang susunod na kabanata Walang nakaraang kabanata Kinakarga ang mga pahina… diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 585f5d4e5d..cc4caa0a9b 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -295,10 +295,10 @@ Ağ bağlantısı yok İndirme duraklatıldı Genel - Biten: - Şu anki: - Sonraki: - Önceki: + Biten: + Şu anki: + Sonraki: + Önceki: Sonraki bölüm yok Önceki bölüm yok Sayfalar yükleniyor… diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 5b1f42606c..26a8005d24 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -270,10 +270,10 @@ Зображення не може бути декодовано Ви бажаєте встановити цю картинку як обкладинку\? Відображення для цієї серії - Завершено: - Поточна: - Наступна: - Попередня: + Завершено: + Поточна: + Наступна: + Попередня: Наступної частини немає Попередньої частини немає Завантаження сторінок… diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index d6cf3e3742..f06bf8929d 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -326,10 +326,10 @@ Đã bắt đầu Loại Đường dẫn truyện chưa được đặt, vui lòng nhấn vào tiêu đề và chọn lại truyện một lần nữa - Đã đọc xong: - Đang đọc: - Chương kế: - Chương trước: + Đã đọc xong: + Đang đọc: + Chương kế: + Chương trước: Không có chương tiếp theo Không có chương trước đó Đang tải trang… diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 7bcbd89e1f..7430b72426 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -270,10 +270,10 @@ \n请尝试更换图片解码器或选择以下选项 要将此页设为封面吗? 阅读模式 - 已读完: - "当前: " - 下一章: - "上一章: " + 已读完: + "当前: " + 下一章: + "上一章: " 下面没有啦 前面没有啦 页面加载中… diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 2fac4a0789..5ed0120b37 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -271,8 +271,8 @@ 已有名稱相同的分類! 第 %1$d 頁 找不到下一章 - 已閱畢: - 下一章: + 已閱畢: + 下一章: 發現新章節 略過已讀的章節 閱畢後刪除 @@ -306,8 +306,8 @@ 類型 漫畫網址未設置,請點擊標題再選擇一次漫畫 這將會清除此章節的閱讀日期,確定嗎? - 當前章節: - 上一章: + 當前章節: + 上一章: %1$s - 第%2$s章 下載時發生錯誤。請再試一次 下載時發生不可預期的錯誤 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index b9baa0c991..cfc796b59e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -62,6 +62,21 @@ @string/screen + + @string/default_value + @string/l_nav + @string/kindlish_nav + @string/edge_nav + @string/right_and_left_nav + + + + @string/none + @string/horizontally + @string/vertically + @string/both_axes + + @string/clean_orphaned_downloads @string/clean_read_downloads diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 6bd1e44d86..05092b3aa0 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -16,7 +16,7 @@ - + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 83ccb5e079..b154e0327e 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -62,4 +62,12 @@ #F44336 #99CC99 + + + #CB84E296 + #CCFF7733 + #CC95818D + #CCA6CFD5 + #CC7D1128 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d271965df5..6a0961fd98 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -290,10 +290,10 @@ The image could not be decoded Use this image as cover art? Viewer for this series - Finished: - Current: - Next: - Previous: + Finished: + Current: + Next: + Previous: There\'s no next chapter There\'s no previous chapter Loading pages… @@ -303,7 +303,7 @@ Fullscreen - Page transitions + Animate page transitions Enable zoom out Double tap animation speed Show page number @@ -339,6 +339,7 @@ Continuous vertical Paged Scale type + Navigation layout Fit screen Stretch Fit width @@ -363,6 +364,15 @@ 15% 20% 25% + L shaped + Kindle-ish + Edge + Right and Left + Invert tapping + None + Horizontally + Vertically + Both Axes About this %1$s @@ -792,12 +802,14 @@ Mark as unread Mark previous as read Mark previous as unread + menu More Move to bottom Move to top Moved to %1$s Never Newest + Next No animation Normal Oldest @@ -809,6 +821,7 @@ Picture saved Pin Pinned + Previous Refresh Refreshing Remove