diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ReaderControl.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ReaderControl.kt
index 53ba8c4b7..df977ff02 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ReaderControl.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ReaderControl.kt
@@ -4,7 +4,7 @@ import java.util.EnumSet
enum class ReaderControl {
- PREV_CHAPTER, NEXT_CHAPTER, SLIDER, PAGES_SHEET, SCREEN_ROTATION, SAVE_PAGE, TIMER;
+ PREV_CHAPTER, NEXT_CHAPTER, SLIDER, PAGES_SHEET, SCREEN_ROTATION, SAVE_PAGE, TIMER, BOOKMARK;
companion object {
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActionsView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActionsView.kt
index d61ae72e4..53062c990 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActionsView.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActionsView.kt
@@ -26,6 +26,7 @@ import org.koitharu.kotatsu.core.util.ext.hasVisibleChildren
import org.koitharu.kotatsu.core.util.ext.isRtl
import org.koitharu.kotatsu.core.util.ext.setValueRounded
import org.koitharu.kotatsu.databinding.LayoutReaderActionsBinding
+import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesSheet
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesSheet.Companion.TAB_PAGES
import org.koitharu.kotatsu.reader.ui.ReaderControlDelegate.OnInteractionListener
import javax.inject.Inject
@@ -40,7 +41,7 @@ class ReaderActionsView @JvmOverloads constructor(
View.OnClickListener,
SharedPreferences.OnSharedPreferenceChangeListener,
Slider.OnChangeListener,
- Slider.OnSliderTouchListener {
+ Slider.OnSliderTouchListener, View.OnLongClickListener {
@Inject
lateinit var settings: AppSettings
@@ -73,6 +74,14 @@ class ReaderActionsView @JvmOverloads constructor(
binding.buttonPrev.isEnabled = value
}
+ var isBookmarkAdded: Boolean = false
+ set(value) {
+ if (field != value) {
+ field = value
+ updateBookmarkButton()
+ }
+ }
+
var listener: OnInteractionListener? = null
init {
@@ -85,6 +94,7 @@ class ReaderActionsView @JvmOverloads constructor(
binding.buttonScreenRotation.initAction()
binding.buttonPagesThumbs.initAction()
binding.buttonTimer.initAction()
+ binding.buttonBookmark.initAction()
binding.slider.setLabelFormatter(PageLabelFormatter())
binding.slider.addOnChangeListener(this)
binding.slider.addOnSliderTouchListener(this)
@@ -112,13 +122,22 @@ class ReaderActionsView @JvmOverloads constructor(
R.id.button_prev -> listener?.switchChapterBy(-1)
R.id.button_next -> listener?.switchChapterBy(1)
R.id.button_save -> listener?.onSavePageClick()
- R.id.button_timer -> listener?.onScrollTimerClick()
+ R.id.button_timer -> listener?.onScrollTimerClick(isLongClick = false)
R.id.button_pages_thumbs -> AppRouter.from(this)?.showChapterPagesSheet()
R.id.button_screen_rotation -> listener?.toggleScreenOrientation()
R.id.button_options -> listener?.openMenu()
+ R.id.button_bookmark -> listener?.onBookmarkClick()
}
}
+ override fun onLongClick(v: View): Boolean = when (v.id) {
+ R.id.button_bookmark -> AppRouter.from(this)
+ ?.showChapterPagesSheet(ChaptersPagesSheet.TAB_BOOKMARKS)
+ R.id.button_timer -> listener?.onScrollTimerClick(isLongClick = true)
+ R.id.button_options -> AppRouter.from(this)?.openReaderSettings()
+ else -> null
+ } != null
+
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
if (fromUser) {
if (isSliderTracking) {
@@ -175,6 +194,7 @@ class ReaderActionsView @JvmOverloads constructor(
binding.buttonScreenRotation.isVisible = ReaderControl.SCREEN_ROTATION in controls
binding.buttonSave.isVisible = ReaderControl.SAVE_PAGE in controls
binding.buttonTimer.isVisible = ReaderControl.TIMER in controls
+ binding.buttonBookmark.isVisible = ReaderControl.BOOKMARK in controls
binding.slider.isVisible = ReaderControl.SLIDER in controls
adjustLayoutParams()
}
@@ -190,6 +210,16 @@ class ReaderActionsView @JvmOverloads constructor(
)
}
+ private fun updateBookmarkButton() {
+ val button = binding.buttonBookmark
+ button.setIconResource(
+ if (isBookmarkAdded) R.drawable.ic_bookmark_added else R.drawable.ic_bookmark,
+ )
+ button.setTitle(
+ if (isBookmarkAdded) R.string.bookmark_remove else R.string.bookmark_add,
+ )
+ }
+
private fun adjustLayoutParams() {
val isSliderVisible = binding.slider.isVisible
repeat(childCount) { i ->
@@ -222,6 +252,7 @@ class ReaderActionsView @JvmOverloads constructor(
private fun Button.initAction() {
setOnClickListener(this@ReaderActionsView)
+ setOnLongClickListener(this@ReaderActionsView)
ViewCompat.setTooltipText(this, contentDescription)
}
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 371d21514..32dba40e5 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
@@ -114,6 +114,7 @@ class ReaderActivity :
viewBinding.actionsView.listener = this
idlingDetector.bindToLifecycle(this)
screenOrientationHelper.applySettings()
+ viewModel.isBookmarkAdded.observe(this) { viewBinding.actionsView.isBookmarkAdded = it }
scrollTimer.isActive.observe(this) { viewBinding.actionsView.setTimerActive(it) }
viewBinding.timerControl.attach(scrollTimer, this)
if (resources.getBoolean(R.bool.is_tablet)) {
@@ -371,12 +372,20 @@ class ReaderActivity :
return reader.isResumed && supportFragmentManager.fragments.lastOrNull() === reader
}
+ override fun onBookmarkClick() {
+ viewModel.toggleBookmark()
+ }
+
override fun onSavePageClick() {
viewModel.saveCurrentPage(pageSaveHelper)
}
- override fun onScrollTimerClick() {
- viewBinding.timerControl.showOrHide()
+ override fun onScrollTimerClick(isLongClick: Boolean) {
+ if (isLongClick) {
+ scrollTimer.setActive(!scrollTimer.isActive.value)
+ } else {
+ viewBinding.timerControl.showOrHide()
+ }
}
override fun toggleScreenOrientation() {
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt
index 47da7c937..d2151dd4f 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt
@@ -138,11 +138,13 @@ class ReaderControlDelegate(
fun toggleUiVisibility()
+ fun onBookmarkClick()
+
fun openMenu()
fun onSavePageClick()
- fun onScrollTimerClick()
+ fun onScrollTimerClick(isLongClick: Boolean)
fun toggleScreenOrientation()
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuProvider.kt
index 04a3b4522..fd93a2005 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuProvider.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderMenuProvider.kt
@@ -14,26 +14,10 @@ class ReaderMenuProvider(
menuInflater.inflate(R.menu.opt_reader, 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()
- }
+ R.id.action_info -> {
+ // TODO
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 9226f364e..985b05a60 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
@@ -346,39 +346,32 @@ class ReaderViewModel @Inject constructor(
}
}
- fun addBookmark() {
+ fun toggleBookmark() {
if (bookmarkJob?.isActive == true) {
return
}
bookmarkJob = launchJob(Dispatchers.Default) {
loadingJob?.join()
- val state = checkNotNull(readingState.value)
- val page = checkNotNull(getCurrentPage()) { "Page not found" }
- val bookmark = Bookmark(
- manga = requireManga(),
- pageId = page.id,
- chapterId = state.chapterId,
- page = state.page,
- scroll = state.scroll,
- imageUrl = page.preview.ifNullOrEmpty { page.url },
- createdAt = Instant.now(),
- percent = computePercent(state.chapterId, state.page),
- )
- bookmarksRepository.addBookmark(bookmark)
- onShowToast.call(R.string.bookmark_added)
- }
- }
-
- fun removeBookmark() {
- if (bookmarkJob?.isActive == true) {
- return
- }
- bookmarkJob = launchJob {
- loadingJob?.join()
- val manga = requireManga()
val state = checkNotNull(getCurrentState())
- bookmarksRepository.removeBookmark(manga.id, state.chapterId, state.page)
- onShowToast.call(R.string.bookmark_removed)
+ if (isBookmarkAdded.value) {
+ val manga = requireManga()
+ bookmarksRepository.removeBookmark(manga.id, state.chapterId, state.page)
+ onShowToast.call(R.string.bookmark_removed)
+ } else {
+ val page = checkNotNull(getCurrentPage()) { "Page not found" }
+ val bookmark = Bookmark(
+ manga = requireManga(),
+ pageId = page.id,
+ chapterId = state.chapterId,
+ page = state.page,
+ scroll = state.scroll,
+ imageUrl = page.preview.ifNullOrEmpty { page.url },
+ createdAt = Instant.now(),
+ percent = computePercent(state.chapterId, state.page),
+ )
+ bookmarksRepository.addBookmark(bookmark)
+ onShowToast.call(R.string.bookmark_added)
+ }
}
}
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt
index 788c98be5..21f5fac4f 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt
@@ -4,8 +4,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Button
import android.widget.CompoundButton
import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.children
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
@@ -24,6 +26,7 @@ import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.findParentCallback
+import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
import org.koitharu.kotatsu.databinding.SheetReaderConfigBinding
import org.koitharu.kotatsu.reader.domain.PageLoader
@@ -93,8 +96,16 @@ class ReaderConfigSheet :
binding.buttonImageServer.setOnClickListener(this)
binding.buttonColorFilter.setOnClickListener(this)
binding.buttonScrollTimer.setOnClickListener(this)
+ binding.buttonBookmark.setOnClickListener(this)
binding.switchDoubleReader.setOnCheckedChangeListener(this)
+ viewModel.isBookmarkAdded.observe(viewLifecycleOwner) {
+ binding.buttonBookmark.setText(if (it) R.string.bookmark_remove else R.string.bookmark_add)
+ binding.buttonBookmark.setCompoundDrawablesRelativeWithIntrinsicBounds(
+ if (it) R.drawable.ic_bookmark_checked else R.drawable.ic_bookmark, 0, 0, 0,
+ )
+ }
+
viewLifecycleScope.launch {
val isAvailable = imageServerDelegate.isAvailable()
if (isAvailable) {
@@ -120,7 +131,7 @@ class ReaderConfigSheet :
}
R.id.button_scroll_timer -> {
- findParentCallback(Callback::class.java)?.onScrollTimerClick() ?: return
+ findParentCallback(Callback::class.java)?.onScrollTimerClick(false) ?: return
dismissAllowingStateLoss()
}
@@ -133,6 +144,10 @@ class ReaderConfigSheet :
orientationHelper.isLandscape = !orientationHelper.isLandscape
}
+ R.id.button_bookmark -> {
+ viewModel.toggleBookmark()
+ }
+
R.id.button_color_filter -> {
val page = viewModel.getCurrentPage() ?: return
val manga = viewModel.getMangaOrNull() ?: return
@@ -219,6 +234,8 @@ class ReaderConfigSheet :
fun onSavePageClick()
- fun onScrollTimerClick()
+ fun onScrollTimerClick(isLongClick: Boolean)
+
+ fun onBookmarkClick()
}
}
diff --git a/app/src/main/res/layout/layout_reader_actions.xml b/app/src/main/res/layout/layout_reader_actions.xml
index eee3166e9..7a5986f34 100644
--- a/app/src/main/res/layout/layout_reader_actions.xml
+++ b/app/src/main/res/layout/layout_reader_actions.xml
@@ -6,7 +6,8 @@
tools:layout_height="wrap_content"
tools:layout_width="match_parent"
tools:orientation="horizontal"
- tools:parentTag="android.widget.LinearLayout">
+ tools:parentTag="android.widget.LinearLayout"
+ tools:style="?dockedToolbarStyle">
@@ -39,9 +41,10 @@
@@ -52,9 +55,10 @@
@@ -65,10 +69,11 @@
@@ -78,9 +83,10 @@
@@ -90,10 +96,25 @@
android:layout_height="wrap_content">
+
+
+
+
+
@@ -104,9 +125,10 @@
diff --git a/app/src/main/res/layout/sheet_reader_config.xml b/app/src/main/res/layout/sheet_reader_config.xml
index ff679f07a..c08038ac6 100644
--- a/app/src/main/res/layout/sheet_reader_config.xml
+++ b/app/src/main/res/layout/sheet_reader_config.xml
@@ -38,32 +38,27 @@
app:drawableStartCompat="@drawable/ic_save" />
+ app:drawableStartCompat="@drawable/ic_bookmark" />
-
+
+
+
+
-
-
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index fb8fd705d..87116f7e6 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -132,6 +132,7 @@
- @string/screen_orientation
- @string/save_page
- @string/automatic_scroll
+ - @string/bookmark_add
- @string/favourites
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 1abac0400..05409eef8 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -118,10 +118,6 @@
- 42dp
-
-