diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt index 1668282e8..155643700 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt @@ -7,7 +7,7 @@ import org.koitharu.kotatsu.core.db.entity.* @Database( entities = [ MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class, - FavouriteCategoryEntity::class, FavouriteEntity::class + FavouriteCategoryEntity::class, FavouriteEntity::class, MangaPrefsEntity::class ], version = 1 ) abstract class MangaDatabase : RoomDatabase() { @@ -20,5 +20,7 @@ abstract class MangaDatabase : RoomDatabase() { abstract fun favouritesDao(): FavouritesDao + abstract fun preferencesDao(): PreferencesDao + abstract fun favouriteCategoriesDao(): FavouriteCategoriesDao } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/PreferencesDao.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/PreferencesDao.kt new file mode 100644 index 000000000..bc910f6b0 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/PreferencesDao.kt @@ -0,0 +1,24 @@ +package org.koitharu.kotatsu.core.db + +import androidx.room.* +import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity + +@Dao +abstract class PreferencesDao { + + @Query("SELECT * FROM preferences WHERE manga_id = :mangaId") + abstract suspend fun find(mangaId: Long): MangaPrefsEntity? + + @Insert(onConflict = OnConflictStrategy.IGNORE) + abstract suspend fun insert(pref: MangaPrefsEntity): Long + + @Update + abstract suspend fun update(pref: MangaPrefsEntity): Int + + @Transaction + open suspend fun upsert(pref: MangaPrefsEntity) { + if (update(pref) == 0) { + insert(pref) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt index 30de9db09..e69769501 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt @@ -46,7 +46,6 @@ data class MangaEntity( altTitle = manga.altTitle, rating = manga.rating, state = manga.state?.name, -// tags = manga.tags.map(TagEntity.Companion::fromMangaTag), title = manga.title ) } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt new file mode 100644 index 000000000..444310d99 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt @@ -0,0 +1,12 @@ +package org.koitharu.kotatsu.core.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "preferences") +data class MangaPrefsEntity( + @PrimaryKey(autoGenerate = false) + @ColumnInfo(name = "manga_id") val mangaId: Long, + @ColumnInfo(name = "mode") val mode: Int +) \ No newline at end of file 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 new file mode 100644 index 000000000..368cb0bf9 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/ReaderMode.kt @@ -0,0 +1,13 @@ +package org.koitharu.kotatsu.core.prefs + +enum class ReaderMode(val id: Int) { + + UNKNOWN(0), + STANDARD(1), + WEBTOON(2); + + companion object { + + fun valueOf(id: Int) = values().firstOrNull { it.id == id } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/MangaPreferencesRepository.kt b/app/src/main/java/org/koitharu/kotatsu/domain/MangaPreferencesRepository.kt new file mode 100644 index 000000000..fdf14f74a --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/domain/MangaPreferencesRepository.kt @@ -0,0 +1,26 @@ +package org.koitharu.kotatsu.domain + +import org.koin.core.KoinComponent +import org.koin.core.inject +import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity +import org.koitharu.kotatsu.core.prefs.ReaderMode + +class MangaPreferencesRepository : KoinComponent { + + private val db: MangaDatabase by inject() + + suspend fun saveData(mangaId: Long, mode: ReaderMode) { + db.preferencesDao().upsert( + MangaPrefsEntity( + mangaId = mangaId, + mode = mode.id + ) + ) + } + + suspend fun getReaderMode(mangaId: Long): ReaderMode { + return db.preferencesDao().find(mangaId)?.let { ReaderMode.valueOf(it.mode) } + ?: ReaderMode.UNKNOWN + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/ListModeSelectDialog.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/ListModeSelectDialog.kt index 42a5b744a..e9bff691b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/ListModeSelectDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/ListModeSelectDialog.kt @@ -13,7 +13,14 @@ import org.koitharu.kotatsu.ui.common.AlertDialogFragment class ListModeSelectDialog : AlertDialogFragment(R.layout.dialog_list_mode), View.OnClickListener { - private val setting by inject() + private val settings by inject() + + private lateinit var mode: ListMode + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mode = settings.listMode + } override fun onBuildDialog(builder: AlertDialog.Builder) { builder.setTitle(R.string.list_mode) @@ -22,7 +29,6 @@ class ListModeSelectDialog : AlertDialogFragment(R.layout.dialog_list_mode), Vie override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val mode = setting.listMode button_list.isChecked = mode == ListMode.LIST button_list_detailed.isChecked = mode == ListMode.DETAILED_LIST button_grid.isChecked = mode == ListMode.GRID @@ -35,10 +41,13 @@ class ListModeSelectDialog : AlertDialogFragment(R.layout.dialog_list_mode), Vie override fun onClick(v: View) { when (v.id) { - R.id.button_ok -> dismiss() - R.id.button_list -> setting.listMode = ListMode.LIST - R.id.button_list_detailed -> setting.listMode = ListMode.DETAILED_LIST - R.id.button_grid -> setting.listMode = ListMode.GRID + R.id.button_ok -> { + settings.listMode = mode + dismiss() + } + R.id.button_list -> mode = ListMode.LIST + R.id.button_list_detailed -> mode = ListMode.DETAILED_LIST + R.id.button_grid -> mode = ListMode.GRID } } 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 99b3ed97c..af9ae2302 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 @@ -15,24 +15,25 @@ import androidx.core.view.updatePadding import androidx.fragment.app.commit import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.activity_reader.* -import moxy.MvpDelegate import moxy.ktx.moxyPresenter import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.MangaChapter import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.ui.common.BaseFullscreenActivity import org.koitharu.kotatsu.ui.reader.standard.StandardReaderFragment import org.koitharu.kotatsu.ui.reader.thumbnails.OnPageSelectListener import org.koitharu.kotatsu.ui.reader.thumbnails.PagesThumbnailsSheet +import org.koitharu.kotatsu.ui.reader.wetoon.WebtoonReaderFragment import org.koitharu.kotatsu.utils.GridTouchHelper import org.koitharu.kotatsu.utils.ShareHelper import org.koitharu.kotatsu.utils.anim.Motion import org.koitharu.kotatsu.utils.ext.* class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnChapterChangeListener, - GridTouchHelper.OnGridTouchListener, OnPageSelectListener { + GridTouchHelper.OnGridTouchListener, OnPageSelectListener, ReaderConfigDialog.Callback { private val presenter by moxyPresenter(factory = ReaderPresenter.Companion::getInstance) @@ -70,14 +71,22 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh insets } - if (reader == null) { - supportFragmentManager.commit { - replace(R.id.container, StandardReaderFragment()) - } - } + presenter.loadChapter(state) + } - if (savedInstanceState?.containsKey(MvpDelegate.MOXY_DELEGATE_TAGS_KEY) != true) { - presenter.loadChapter(state) + override fun onInitReader(pages: List, mode: ReaderMode, state: ReaderState) { + val currentReader = reader + when (mode) { + ReaderMode.WEBTOON -> if (currentReader !is WebtoonReaderFragment) { + supportFragmentManager.commit { + replace(R.id.container, WebtoonReaderFragment()) + } + } + else -> if (currentReader !is StandardReaderFragment) { + supportFragmentManager.commit { + replace(R.id.container, StandardReaderFragment()) + } + } } } @@ -94,9 +103,20 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh return super.onCreateOptionsMenu(menu) } + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.putParcelable(EXTRA_STATE, state) + } + override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { R.id.action_settings -> { - ReaderConfigDialog.show(supportFragmentManager) + ReaderConfigDialog.show( + supportFragmentManager, when (reader) { + is StandardReaderFragment -> ReaderMode.STANDARD + is WebtoonReaderFragment -> ReaderMode.WEBTOON + else -> ReaderMode.UNKNOWN + } + ) true } R.id.action_chapters -> { @@ -136,10 +156,6 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh else -> super.onOptionsItemSelected(item) } - override fun onPagesReady(pages: List, index: Int) { - - } - override fun onLoadingStateChanged(isLoading: Boolean) { layout_loading.isVisible = isLoading } @@ -202,12 +218,11 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh } override fun onChapterChanged(chapter: MangaChapter) { - presenter.loadChapter( - state.copy( - chapterId = chapter.id, - page = 0 - ) + state = state.copy( + chapterId = chapter.id, + page = 0 ) + presenter.loadChapter(state) } override fun onPageSelected(page: MangaPage) { @@ -219,6 +234,14 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh } } + override fun onReaderModeChanged(mode: ReaderMode) { + reader?.let { + state = state.copy(page = it.currentPageIndex) + } + presenter.saveState(state, mode) + recreate() + } + override fun onPageSaved(uri: Uri?) { if (uri != null) { Snackbar.make(container, R.string.page_saved, Snackbar.LENGTH_LONG) 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 2d9a3b894..b37711986 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 @@ -4,33 +4,65 @@ import android.os.Bundle import android.view.View import androidx.appcompat.app.AlertDialog import androidx.fragment.app.FragmentManager +import kotlinx.android.synthetic.main.dialog_list_mode.button_ok +import kotlinx.android.synthetic.main.dialog_reader_config.* import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.ui.common.AlertDialogFragment +import org.koitharu.kotatsu.utils.ext.withArgs class ReaderConfigDialog : AlertDialogFragment(R.layout.dialog_reader_config), View.OnClickListener { + private lateinit var mode: ReaderMode + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mode = arguments?.getInt(ARG_MODE, ReaderMode.UNKNOWN.id) + ?.let { ReaderMode.valueOf(it) } + ?.takeUnless { it == ReaderMode.UNKNOWN } + ?: ReaderMode.STANDARD + } + override fun onBuildDialog(builder: AlertDialog.Builder) { - builder//.setTitle(R.string.list_mode) + builder.setTitle(R.string.read_mode) .setCancelable(true) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + button_standard.isChecked = mode == ReaderMode.STANDARD + button_webtoon.isChecked = mode == ReaderMode.WEBTOON + button_ok.setOnClickListener(this) + button_standard.setOnClickListener(this) + button_webtoon.setOnClickListener(this) } override fun onClick(v: View) { when (v.id) { - R.id.button_ok -> dismiss() - + R.id.button_ok -> { + ((parentFragment as? Callback) + ?: (activity as? Callback))?.onReaderModeChanged(mode) + dismiss() + } + R.id.button_standard -> mode = ReaderMode.STANDARD + R.id.button_webtoon -> mode = ReaderMode.WEBTOON } } + interface Callback { + + fun onReaderModeChanged(mode: ReaderMode) + } + companion object { private const val TAG = "ReaderConfigDialog" + private const val ARG_MODE = "mode" - fun show(fm: FragmentManager) = ReaderConfigDialog().show(fm, TAG) + fun show(fm: FragmentManager, mode: ReaderMode) = ReaderConfigDialog().withArgs(1) { + putInt(ARG_MODE, mode.id) + }.show(fm, TAG) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt index 4c5472ab1..f33e981f0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt @@ -12,6 +12,8 @@ import okhttp3.OkHttpClient import okhttp3.Request import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.core.prefs.ReaderMode +import org.koitharu.kotatsu.domain.MangaPreferencesRepository import org.koitharu.kotatsu.domain.MangaProviderFactory import org.koitharu.kotatsu.domain.history.HistoryRepository import org.koitharu.kotatsu.ui.common.BasePresenter @@ -27,14 +29,14 @@ class ReaderPresenter : BasePresenter() { presenterScope.launch { viewState.onLoadingStateChanged(isLoading = true) try { - val pages = withContext(Dispatchers.IO) { + val (pages, mode) = withContext(Dispatchers.IO) { val repo = MangaProviderFactory.create(state.manga.source) val chapter = state.chapter ?: repo.getDetails(state.manga).chapters ?.first { it.id == state.chapterId } ?: throw RuntimeException("Chapter ${state.chapterId} not found") - repo.getPages(chapter) + repo.getPages(chapter) to MangaPreferencesRepository().getReaderMode(state.manga.id) } - viewState.onPagesReady(pages, state.page) + viewState.onInitReader(pages, mode, state) } catch (e: Exception) { if (BuildConfig.DEBUG) { e.printStackTrace() @@ -46,13 +48,19 @@ class ReaderPresenter : BasePresenter() { } } - fun saveState(state: ReaderState) { + fun saveState(state: ReaderState, mode: ReaderMode? = null) { presenterScope.launch(Dispatchers.IO) { HistoryRepository().addOrUpdate( manga = state.manga, chapterId = state.chapterId, page = state.page ) + if (mode != null) { + MangaPreferencesRepository().saveData( + mangaId = state.manga.id, + mode = mode + ) + } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt index f7e52a877..e5f854db4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt @@ -5,11 +5,12 @@ import moxy.MvpView import moxy.viewstate.strategy.alias.AddToEndSingle import moxy.viewstate.strategy.alias.OneExecution import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.core.prefs.ReaderMode interface ReaderView : MvpView { @AddToEndSingle - fun onPagesReady(pages: List, index: Int) + fun onInitReader(pages: List, mode: ReaderMode, state: ReaderState) @AddToEndSingle fun onLoadingStateChanged(isLoading: Boolean) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/StandardReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/StandardReaderFragment.kt index acb331a26..f0fd3cf54 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/StandardReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/StandardReaderFragment.kt @@ -6,9 +6,11 @@ import kotlinx.android.synthetic.main.fragment_reader_standard.* import moxy.ktx.moxyPresenter import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.ui.reader.BaseReaderFragment import org.koitharu.kotatsu.ui.reader.PageLoader import org.koitharu.kotatsu.ui.reader.ReaderPresenter +import org.koitharu.kotatsu.ui.reader.ReaderState class StandardReaderFragment : BaseReaderFragment(R.layout.fragment_reader_standard) { @@ -29,10 +31,10 @@ class StandardReaderFragment : BaseReaderFragment(R.layout.fragment_reader_stand pager.offscreenPageLimit = 2 } - override fun onPagesReady(pages: List, index: Int) { + override fun onInitReader(pages: List, mode: ReaderMode, state: ReaderState) { adapter?.let { it.replaceData(pages) - pager.setCurrentItem(index, false) + pager.setCurrentItem(state.page, false) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonAdapter.kt new file mode 100644 index 000000000..61b22bc95 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonAdapter.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.ui.reader.wetoon + +import android.view.ViewGroup +import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter +import org.koitharu.kotatsu.ui.reader.PageLoader + +class WebtoonAdapter(private val loader: PageLoader) : BaseRecyclerAdapter() { + + override fun onCreateViewHolder(parent: ViewGroup) = + WebtoonHolder(parent, loader) + + override fun onGetItemId(item: MangaPage) = item.id + + override fun getExtra(item: MangaPage, position: Int) = Unit +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonHolder.kt new file mode 100644 index 000000000..7f8e9be58 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonHolder.kt @@ -0,0 +1,80 @@ +package org.koitharu.kotatsu.ui.reader.wetoon + +import android.graphics.PointF +import android.view.ViewGroup +import androidx.core.net.toUri +import androidx.core.view.isVisible +import com.davemorrissey.labs.subscaleview.ImageSource +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView +import kotlinx.android.synthetic.main.item_page.* +import kotlinx.coroutines.* +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.ui.common.list.BaseViewHolder +import org.koitharu.kotatsu.ui.reader.PageLoader +import org.koitharu.kotatsu.utils.ext.getDisplayMessage + + +class WebtoonHolder(parent: ViewGroup, private val loader: PageLoader) : + BaseViewHolder(parent, R.layout.item_page), + SubsamplingScaleImageView.OnImageEventListener, CoroutineScope by loader { + + private var job: Job? = null + + init { + ssiv.setOnImageEventListener(this) + button_retry.setOnClickListener { + doLoad(boundData ?: return@setOnClickListener, force = true) + } + } + + override fun onBind(data: MangaPage, extra: Unit) { + doLoad(data, force = false) + } + + private fun doLoad(data: MangaPage, force: Boolean) { + job?.cancel() + job = launch { + layout_error.isVisible = false + progressBar.isVisible = true + ssiv.recycle() + try { + val uri = withContext(Dispatchers.IO) { + loader.loadFile(data.url, force) + }.toUri() + ssiv.setImage(ImageSource.uri(uri)) + } catch (e: CancellationException) { + //do nothing + } catch (e: Exception) { + onError(e) + } + } + } + + override fun onReady() { + ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM) + ssiv.minScale = ssiv.width / ssiv.sWidth.toFloat() + ssiv.setScaleAndCenter( + ssiv.minScale, + PointF(ssiv.sWidth / 2f, 0f) + ) + } + + override fun onImageLoadError(e: Exception) = onError(e) + + override fun onImageLoaded() { + progressBar.isVisible = false + } + + override fun onTileLoadError(e: Exception?) = Unit + + override fun onPreviewReleased() = Unit + + override fun onPreviewLoadError(e: Exception?) = Unit + + private fun onError(e: Throwable) { + textView_error.text = e.getDisplayMessage(context.resources) + layout_error.isVisible = true + progressBar.isVisible = false + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonReaderFragment.kt new file mode 100644 index 000000000..9b1430a34 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/wetoon/WebtoonReaderFragment.kt @@ -0,0 +1,62 @@ +package org.koitharu.kotatsu.ui.reader.wetoon + +import android.os.Bundle +import android.view.View +import kotlinx.android.synthetic.main.fragment_reader_webtoon.* +import moxy.ktx.moxyPresenter +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.model.MangaPage +import org.koitharu.kotatsu.core.prefs.ReaderMode +import org.koitharu.kotatsu.ui.reader.BaseReaderFragment +import org.koitharu.kotatsu.ui.reader.PageLoader +import org.koitharu.kotatsu.ui.reader.ReaderPresenter +import org.koitharu.kotatsu.ui.reader.ReaderState +import org.koitharu.kotatsu.utils.ext.firstItem + +class WebtoonReaderFragment : BaseReaderFragment(R.layout.fragment_reader_webtoon) { + + private val presenter by moxyPresenter(factory = ReaderPresenter.Companion::getInstance) + + private var adapter: WebtoonAdapter? = null + private lateinit var loader: PageLoader + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + loader = PageLoader() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + adapter = WebtoonAdapter(loader) + recyclerView.adapter = adapter + } + + override fun onInitReader(pages: List, mode: ReaderMode, state: ReaderState) { + adapter?.let { + it.replaceData(pages) + recyclerView.firstItem = state.page + } + } + + override fun onDestroy() { + loader.dispose() + super.onDestroy() + } + + override val hasItems: Boolean + get() = adapter?.hasItems == true + + override val currentPageIndex: Int + get() = recyclerView.firstItem + + override val pages: List + get() = adapter?.items.orEmpty() + + override fun setCurrentPage(index: Int, smooth: Boolean) { + if (smooth) { + recyclerView.smoothScrollToPosition(index) + } else { + recyclerView.firstItem = index + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_reader_webtoon.xml b/app/src/main/res/layout/fragment_reader_webtoon.xml new file mode 100644 index 000000000..72db1bfac --- /dev/null +++ b/app/src/main/res/layout/fragment_reader_webtoon.xml @@ -0,0 +1,9 @@ + + \ 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 fa91a7afe..6e2019b00 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -82,4 +82,5 @@ Downloading: %d%% Standard Webtoon + Read mode \ No newline at end of file