diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/ReaderMode.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/ReaderMode.kt index 368cb0bf9..89fa40761 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/ReaderMode.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/ReaderMode.kt @@ -4,7 +4,8 @@ enum class ReaderMode(val id: Int) { UNKNOWN(0), STANDARD(1), - WEBTOON(2); + WEBTOON(2), + REVERSED(3); companion object { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt index 3671da94b..ec9fc5cda 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt @@ -38,6 +38,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.ui.base.BaseFullscreenActivity import org.koitharu.kotatsu.ui.reader.base.AbstractReader +import org.koitharu.kotatsu.ui.reader.reversed.ReversedReaderFragment import org.koitharu.kotatsu.ui.reader.standard.PagerReaderFragment import org.koitharu.kotatsu.ui.reader.thumbnails.OnPageSelectListener import org.koitharu.kotatsu.ui.reader.thumbnails.PagesThumbnailsSheet @@ -121,6 +122,11 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh replace(R.id.container, WebtoonReaderFragment.newInstance(state)) } } + ReaderMode.REVERSED -> if (currentReader !is ReversedReaderFragment) { + supportFragmentManager.commit { + replace(R.id.container, ReversedReaderFragment.newInstance(state)) + } + } else -> if (currentReader !is PagerReaderFragment) { supportFragmentManager.commit { replace(R.id.container, PagerReaderFragment.newInstance(state)) @@ -130,6 +136,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh toolbar_bottom.menu.findItem(R.id.action_reader_mode).setIcon( when (mode) { ReaderMode.WEBTOON -> R.drawable.ic_script + ReaderMode.REVERSED -> R.drawable.ic_read_reversed else -> R.drawable.ic_book_page } ) @@ -159,6 +166,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh supportFragmentManager, when (reader) { is PagerReaderFragment -> ReaderMode.STANDARD is WebtoonReaderFragment -> ReaderMode.WEBTOON + is ReversedReaderFragment -> ReaderMode.REVERSED else -> ReaderMode.UNKNOWN } ) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderConfigDialog.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderConfigDialog.kt index 33033ea98..791fed5d3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderConfigDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderConfigDialog.kt @@ -32,10 +32,12 @@ class ReaderConfigDialog : AlertDialogFragment(R.layout.dialog_reader_config), override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) button_standard.isChecked = mode == ReaderMode.STANDARD + button_reversed.isChecked = mode == ReaderMode.REVERSED button_webtoon.isChecked = mode == ReaderMode.WEBTOON button_ok.setOnClickListener(this) button_standard.setOnClickListener(this) + button_reversed.setOnClickListener(this) button_webtoon.setOnClickListener(this) } @@ -48,6 +50,7 @@ class ReaderConfigDialog : AlertDialogFragment(R.layout.dialog_reader_config), } R.id.button_standard -> mode = ReaderMode.STANDARD R.id.button_webtoon -> mode = ReaderMode.WEBTOON + R.id.button_reversed -> mode = ReaderMode.REVERSED } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/BaseReaderAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/BaseReaderAdapter.kt index b3f7e9223..fd1bff66e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/BaseReaderAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/base/BaseReaderAdapter.kt @@ -5,7 +5,7 @@ import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.ui.base.list.BaseViewHolder -abstract class BaseReaderAdapter(private val pages: GroupedList) : +abstract class BaseReaderAdapter(protected val pages: GroupedList) : RecyclerView.Adapter>() { init { @@ -18,25 +18,25 @@ abstract class BaseReaderAdapter(private val pages: GroupedList holder.bind(item, Unit) } - fun getItem(position: Int) = pages[position] + open fun getItem(position: Int) = pages[position] - fun notifyItemsAppended(count: Int) { + open fun notifyItemsAppended(count: Int) { notifyItemRangeInserted(pages.size - count, count) } - fun notifyItemsPrepended(count: Int) { + open fun notifyItemsPrepended(count: Int) { notifyItemRangeInserted(0, count) } - fun notifyItemsRemovedStart(count: Int) { + open fun notifyItemsRemovedStart(count: Int) { notifyItemRangeRemoved(0, count) } - fun notifyItemsRemovedEnd(count: Int) { + open fun notifyItemsRemovedEnd(count: Int) { notifyItemRangeRemoved(pages.size - count, count) } - override fun getItemId(position: Int) = pages[position].id + open override fun getItemId(position: Int) = pages[position].id final override fun getItemCount() = pages.size diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedPageAnimTransformer.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedPageAnimTransformer.kt new file mode 100644 index 000000000..3404f0529 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedPageAnimTransformer.kt @@ -0,0 +1,36 @@ +package org.koitharu.kotatsu.ui.reader.reversed + +import android.view.View +import androidx.viewpager2.widget.ViewPager2 + +class ReversedPageAnimTransformer : ViewPager2.PageTransformer { + + override fun transformPage(page: View, position: Float) { + with(page) { + val pageWidth = width + when { + position > 1 -> alpha = 0f + position >= 0 -> { + alpha = 1f + translationX = 0f + translationZ = 0f + scaleX = 1 + FACTOR * position + scaleY = 1f + } + position >= -1 -> { + alpha = 1f + translationX = pageWidth * -position + translationZ = -1f + scaleX = 1f + scaleY = 1f + } + else -> alpha = 0f + } + } + } + + private companion object { + + const val FACTOR = 0.1f + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedPagesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedPagesAdapter.kt new file mode 100644 index 000000000..86259e78c --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedPagesAdapter.kt @@ -0,0 +1,47 @@ +package org.koitharu.kotatsu.ui.reader.reversed + +import android.view.ViewGroup +import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.ui.base.list.BaseViewHolder +import org.koitharu.kotatsu.ui.reader.PageLoader +import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter +import org.koitharu.kotatsu.ui.reader.base.GroupedList +import org.koitharu.kotatsu.ui.reader.standard.PageHolder + +class ReversedPagesAdapter( + pages: GroupedList, + private val loader: PageLoader +) : BaseReaderAdapter(pages) { + + override fun onCreateViewHolder(parent: ViewGroup) = PageHolder(parent, loader) + + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + super.onBindViewHolder(holder, reversed(position)) + } + + override fun getItem(position: Int): MangaPage { + return super.getItem(reversed(position)) + } + + override fun getItemId(position: Int): Long { + return super.getItemId(reversed(position)) + } + + override fun notifyItemsAppended(count: Int) { + super.notifyItemsPrepended(count) + } + + override fun notifyItemsPrepended(count: Int) { + super.notifyItemsAppended(count) + } + + override fun notifyItemsRemovedStart(count: Int) { + super.notifyItemsRemovedEnd(count) + } + + override fun notifyItemsRemovedEnd(count: Int) { + super.notifyItemsRemovedStart(count) + } + + private fun reversed(position: Int) = pages.size - position - 1 +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedReaderFragment.kt new file mode 100644 index 000000000..400f59913 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/reversed/ReversedReaderFragment.kt @@ -0,0 +1,93 @@ +package org.koitharu.kotatsu.ui.reader.reversed + +import android.content.Context +import android.content.SharedPreferences +import android.os.Bundle +import android.view.View +import kotlinx.android.synthetic.main.fragment_reader_standard.* +import org.koin.android.ext.android.inject +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.ui.reader.ReaderState +import org.koitharu.kotatsu.ui.reader.base.AbstractReader +import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter +import org.koitharu.kotatsu.ui.reader.base.GroupedList +import org.koitharu.kotatsu.ui.reader.standard.PageAnimTransformer +import org.koitharu.kotatsu.ui.reader.standard.PagerPaginationListener +import org.koitharu.kotatsu.utils.ext.doOnPageChanged +import org.koitharu.kotatsu.utils.ext.withArgs + +class ReversedReaderFragment : AbstractReader(R.layout.fragment_reader_standard), + SharedPreferences.OnSharedPreferenceChangeListener { + + private var paginationListener: PagerPaginationListener? = null + private val settings by inject() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + paginationListener = PagerPaginationListener(adapter!!, 2, this) + pager.adapter = adapter + if (settings.readerAnimation) { + pager.setPageTransformer(ReversedPageAnimTransformer()) + } + pager.offscreenPageLimit = 2 + pager.registerOnPageChangeCallback(paginationListener!!) + pager.doOnPageChanged { + notifyPageChanged(reversed(it)) + } + } + + override fun onAttach(context: Context) { + super.onAttach(context) + settings.subscribe(this) + } + + override fun onDetach() { + settings.unsubscribe(this) + super.onDetach() + } + + override fun onDestroyView() { + paginationListener = null + super.onDestroyView() + } + + override fun onCreateAdapter(dataSet: GroupedList): BaseReaderAdapter { + return ReversedPagesAdapter(dataSet, loader) + } + + override val itemsCount: Int + get() = adapter?.itemCount ?: 0 + + override fun getCurrentItem() = reversed(pager.currentItem) + + override fun setCurrentItem(position: Int, isSmooth: Boolean) { + pager.setCurrentItem(reversed(position), isSmooth) + } + + override fun getCurrentPageScroll() = 0 + + override fun restorePageScroll(position: Int, scroll: Int) = Unit + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + when (key) { + getString(R.string.key_reader_animation) -> { + if (settings.readerAnimation) { + pager.setPageTransformer(PageAnimTransformer()) + } else { + pager.setPageTransformer(null) + } + } + } + } + + private fun reversed(position: Int) = (itemsCount - position - 1).coerceAtLeast(0) + + companion object { + + fun newInstance(state: ReaderState) = ReversedReaderFragment().withArgs(1) { + putParcelable(ARG_STATE, state) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_read_reversed.xml b/app/src/main/res/drawable/ic_read_reversed.xml new file mode 100644 index 000000000..83be14ff0 --- /dev/null +++ b/app/src/main/res/drawable/ic_read_reversed.xml @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_reader_config.xml b/app/src/main/res/layout/dialog_reader_config.xml index 6d29f4e19..fc7623caf 100644 --- a/app/src/main/res/layout/dialog_reader_config.xml +++ b/app/src/main/res/layout/dialog_reader_config.xml @@ -22,6 +22,14 @@ android:text="@string/standard" app:icon="@drawable/ic_book_page" /> + + Проверка обновления… Ошибка при проверке обновления Нет доступных обновлений + Справа налево \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5ac4f9064..7ad520686 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -160,4 +160,5 @@ Checking for updates… Update check failed No updates available + Right to left \ No newline at end of file