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 cb91777b2..622d5da23 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
@@ -79,6 +79,10 @@ object PreferenceKeys {
const val navigationModeWebtoon = "reader_navigation_mode_webtoon"
+ const val showNavigationOverlayNewUser = "reader_navigation_overlay_new_user"
+
+ const val showNavigationOverlayOnStart = "reader_navigation_overlay_on_start"
+
const val webtoonSidePadding = "webtoon_side_padding"
const val portraitColumns = "pref_library_columns_portrait_key"
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 09b6ef143..65b02c323 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
@@ -149,6 +149,10 @@ class PreferencesHelper(val context: Context) {
fun navigationModeWebtoon() = flowPrefs.getInt(Keys.navigationModeWebtoon, 0)
+ fun showNavigationOverlayNewUser() = flowPrefs.getBoolean(Keys.showNavigationOverlayNewUser, true)
+
+ fun showNavigationOverlayOnStart() = flowPrefs.getBoolean(Keys.showNavigationOverlayOnStart, false)
+
fun portraitColumns() = flowPrefs.getInt(Keys.portraitColumns, 0)
fun landscapeColumns() = flowPrefs.getInt(Keys.landscapeColumns, 0)
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 000000000..13e0b22f0
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt
@@ -0,0 +1,140 @@
+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.R
+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
+
+ fun setNavigation(navigation: ViewerNavigation, showOnStart: Boolean) {
+ if (!showOnStart && this.navigation == null) {
+ this.navigation = navigation
+ isVisible = false
+ return
+ }
+
+ this.navigation = navigation
+ invalidate()
+
+ if (isVisible) return
+
+ viewPropertyAnimator = animate()
+ .alpha(1f)
+ .setDuration(1000L)
+ .withStartAction {
+ isVisible = true
+ }
+ .withEndAction {
+ viewPropertyAnimator = null
+ }
+ viewPropertyAnimator?.start()
+ }
+
+ 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 { region ->
+
+ val paint = paintForRegion(region.type)
+
+ val rect = region.rectF
+
+ canvas?.save()
+
+ // Scale rect from 1f,1f to screen width and height
+ canvas?.scale(width.toFloat(), height.toFloat())
+ canvas?.drawRect(rect, paint)
+
+ 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(region.type.name, x, y, textBorderPaint)
+ canvas?.drawText(region.type.name, x, y, textPaint)
+
+ canvas?.restore()
+ }
+ }
+
+ private fun paintForRegion(type: ViewerNavigation.NavigationRegion): Paint {
+ return Paint().apply {
+ when (type) {
+ ViewerNavigation.NavigationRegion.NEXT -> {
+ color = ContextCompat.getColor(context, R.color.navigation_next)
+ }
+ ViewerNavigation.NavigationRegion.PREV -> {
+ color = ContextCompat.getColor(context, R.color.navigation_prev)
+ }
+ ViewerNavigation.NavigationRegion.MENU -> {
+ color = ContextCompat.getColor(context, R.color.navigation_menu)
+ }
+ ViewerNavigation.NavigationRegion.RIGHT -> {
+ color = ContextCompat.getColor(context, R.color.navigation_right)
+ }
+ ViewerNavigation.NavigationRegion.LEFT -> {
+ color = ContextCompat.getColor(context, R.color.navigation_left)
+ }
+ }
+ }
+ }
+
+ override fun performClick(): Boolean {
+ super.performClick()
+
+ if (viewPropertyAnimator == null && isVisible) {
+ viewPropertyAnimator = animate()
+ .alpha(0f)
+ .setDuration(1000L)
+ .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)
+ }
+}
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 95184c0cd..79f8b8374 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
@@ -15,6 +15,8 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
var imagePropertyChangedListener: (() -> Unit)? = null
+ var navigationModeChangedListener: (() -> Unit)? = null
+
var tappingEnabled = true
var tappingInverted = TappingInvertMode.NONE
var longTapEnabled = true
@@ -27,6 +29,10 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
var navigationMode = 0
protected set
+ var forceNavigationOverlay = false
+
+ var navigationOverlayOnStart = false
+
var dualPageSplit = false
protected set
@@ -60,6 +66,14 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
preferences.alwaysShowChapterTransition()
.register({ alwaysShowChapterTransition = it })
+
+ forceNavigationOverlay = preferences.showNavigationOverlayNewUser().get()
+ if (forceNavigationOverlay) {
+ preferences.showNavigationOverlayNewUser().set(false)
+ }
+
+ preferences.showNavigationOverlayOnStart()
+ .register({ navigationOverlayOnStart = it })
}
protected abstract fun defaultNavigation(): ViewerNavigation
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 1e134ba83..0f835e74c 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
@@ -90,6 +90,7 @@ class PagerConfig(
4 -> RightAndLeftNavigation()
else -> defaultNavigation()
}
+ navigationModeChangedListener?.invoke()
}
enum class ZoomType {
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 5265423ab..039d1e63b 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
@@ -119,6 +119,11 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
config.imagePropertyChangedListener = {
refreshAdapter()
}
+
+ config.navigationModeChangedListener = {
+ val showOnStart = config.navigationOverlayOnStart || config.forceNavigationOverlay
+ activity.binding.navigationOverlay.setNavigation(config.navigator, showOnStart)
+ }
}
override fun destroy() {
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 f427cff4c..f59a96a91 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
@@ -63,5 +63,6 @@ class WebtoonConfig(
4 -> RightAndLeftNavigation()
else -> defaultNavigation()
}
+ navigationModeChangedListener?.invoke()
}
}
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 a132199d5..991c89df7 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
@@ -136,6 +136,11 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
refreshAdapter()
}
+ config.navigationModeChangedListener = {
+ val showOnStart = config.navigationOverlayOnStart || config.forceNavigationOverlay
+ activity.binding.navigationOverlay.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 443375f10..a3e0aa065 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
@@ -50,6 +50,12 @@ class SettingsReaderController : SettingsController() {
summaryRes = R.string.pref_show_reading_mode_summary
defaultValue = true
}
+ switchPreference {
+ key = Keys.showNavigationOverlayOnStart
+ titleRes = R.string.pref_show_navigation_mode
+ summaryRes = R.string.pref_show_navigation_mode_summary
+ defaultValue = false
+ }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
switchPreference {
key = Keys.trueColor
diff --git a/app/src/main/res/layout/reader_activity.xml b/app/src/main/res/layout/reader_activity.xml
index f12965ffe..ec537b1f1 100644
--- a/app/src/main/res/layout/reader_activity.xml
+++ b/app/src/main/res/layout/reader_activity.xml
@@ -43,6 +43,12 @@
android:layout_height="match_parent"
android:visibility="gone" />
+
+
#47a84a
+
+ #CB84E296
+ #CCFF7733
+ #CC95818D
+ #CCA6CFD5
+ #CC7D1128
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 83380e22b..d26dc8e4d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -252,6 +252,8 @@
Fullscreen
+ Show navigation layout overlay
+ Show overlay when reader is opened
Dual page split (ALPHA)
Invert dual page split placement
If the placement of the dual page split doesn\'t match reading direction