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 683bf5b62..39ef99bfe 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 @@ -26,6 +26,7 @@ import androidx.core.view.setPadding import com.afollestad.materialdialogs.MaterialDialog import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.elvishew.xlog.XLog +import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.snackbar.Snackbar import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Chapter @@ -35,8 +36,10 @@ import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.databinding.ReaderActivityBinding +import eu.kanade.tachiyomi.databinding.ReaderChaptersSheetBinding import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.AddToLibraryFirst @@ -52,6 +55,7 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer +import eu.kanade.tachiyomi.ui.webview.WebViewActivity import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.GLUtil import eu.kanade.tachiyomi.util.system.hasDisplayCutout @@ -63,7 +67,10 @@ import eu.kanade.tachiyomi.util.view.showBar import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.widget.SimpleAnimationListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener +import exh.util.collapse import exh.util.defaultReaderType +import exh.util.hide +import exh.util.isExpanded import java.io.File import kotlin.math.abs import kotlin.math.roundToLong @@ -120,6 +127,8 @@ class ReaderActivity : BaseRxActivity() private val sourceManager: SourceManager by injectLazy() private val logger = XLog.tag("ReaderActivity") + + lateinit var readerBottomSheetBinding: ReaderChaptersSheetBinding // SY <-- /** @@ -184,6 +193,11 @@ class ReaderActivity : BaseRxActivity() // <-- EH } + // SY --> + readerBottomSheetBinding = ReaderChaptersSheetBinding.bind(binding.readerChaptersSheet.root) + readerBottomSheetBinding.chaptersBottomSheet.setup(this) + // SY <-- + config = ReaderConfig() initializeMenu() @@ -229,6 +243,9 @@ class ReaderActivity : BaseRxActivity() super.onDestroy() viewer?.destroy() viewer = null + // SY --> + readerBottomSheetBinding.chaptersBottomSheet.adapter = null + // SY <-- config = null progressDialog?.dismiss() progressDialog = null @@ -298,7 +315,14 @@ class ReaderActivity : BaseRxActivity() presenter.bookmarkCurrentChapter(false) invalidateOptionsMenu() } - R.id.action_settings -> ReaderSettingsSheet(this).show() + R.id.action_settings -> { + ReaderSettingsSheet(this).show() + // SY --> + if (readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior.isExpanded()) { + readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.collapse() + } + // SY <-- + } R.id.action_custom_filter -> { val sheet = ReaderColorFilterSheet(this) // Remove dimmed backdrop so changes can be previewed @@ -309,6 +333,11 @@ class ReaderActivity : BaseRxActivity() setMenuVisibility(false) sheet.show() + // SY --> + if (readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior.isExpanded()) { + readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.collapse() + } + // SY <-- } } return super.onOptionsItemSelected(item) @@ -364,14 +393,15 @@ class ReaderActivity : BaseRxActivity() } // Init listeners on bottom menu - binding.pageSeekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { + /* SY --> */readerBottomSheetBinding.pageSeekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { /* SY <-- */ override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { if (viewer != null && fromUser) { moveToPageIndex(value) } } }) - binding.leftChapter.setOnClickListener { + + /* SY --> binding.leftChapter.setOnClickListener { if (viewer != null) { if (viewer is R2LPagerViewer) { loadNextChapter() @@ -388,7 +418,7 @@ class ReaderActivity : BaseRxActivity() loadNextChapter() } } - } + } SY <-- */ // --> EH binding.expandEhButton.clicks() @@ -544,6 +574,8 @@ class ReaderActivity : BaseRxActivity() setMenuVisibility(menuVisible) // --> EH + readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.isHideable = !menuVisible + if (!menuVisible) readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.hide() setEhUtilsVisibility(ehUtilsVisible) // <-- EH } @@ -586,8 +618,9 @@ class ReaderActivity : BaseRxActivity() binding.header.startAnimation(toolbarAnimation) // EXH <-- - val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom) - binding.readerMenuBottom.startAnimation(bottomAnimation) + // SY --> + readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.collapse() + // SY <-- } if (preferences.showPageNumber().get()) { @@ -611,8 +644,10 @@ class ReaderActivity : BaseRxActivity() binding.header.startAnimation(toolbarAnimation) // EXH <-- - val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom) - binding.readerMenuBottom.startAnimation(bottomAnimation) + // SY --> + BottomSheetBehavior.from(readerBottomSheetBinding.chaptersBottomSheet).isHideable = true + readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.hide() + // SY <-- } if (preferences.showPageNumber().get()) { @@ -621,6 +656,26 @@ class ReaderActivity : BaseRxActivity() } } + // SY --> + fun openMangaInBrowser() { + val source = sourceManager.getOrStub(presenter.manga!!.source) as? HttpSource ?: return + val url = try { + source.mangaDetailsRequest(presenter.manga!!).url.toString() + } catch (e: Exception) { + return + } + + val intent = WebViewActivity.newIntent( + applicationContext, url, source.id, presenter.manga!!.title + ) + startActivity(intent) + } + + fun refreshSheetChapters() { + readerBottomSheetBinding.chaptersBottomSheet.refreshList() + } + // SY <-- + /** * Reset menu padding and system bar */ @@ -662,7 +717,9 @@ class ReaderActivity : BaseRxActivity() binding.toolbar.title = manga.title - binding.pageSeekbar.isRTL = newViewer is R2LPagerViewer + // SY --> + readerBottomSheetBinding.pageSeekbar.isRTL = newViewer is R2LPagerViewer + // SY <-- binding.pleaseWait.isVisible = true binding.pleaseWait.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in_long)) @@ -745,24 +802,25 @@ class ReaderActivity : BaseRxActivity() */ @SuppressLint("SetTextI18n") fun onPageSelected(page: ReaderPage) { - presenter.onPageSelected(page) + val newChapter = presenter.onPageSelected(page) val pages = page.chapter.pages ?: return // Set bottom page number binding.pageNumber.text = "${page.number}/${pages.size}" - - // Set seekbar page number - if (viewer !is R2LPagerViewer) { - binding.leftPageText.text = "${page.number}" - binding.rightPageText.text = "${pages.size}" - } else { - binding.rightPageText.text = "${page.number}" - binding.leftPageText.text = "${pages.size}" + // SY --> + readerBottomSheetBinding.pageText.text = "${page.number}/${pages.size}" + if (!newChapter && readerBottomSheetBinding.chaptersBottomSheet.shouldCollapse && readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior.isExpanded()) { + readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.collapse() } - + if (readerBottomSheetBinding.chaptersBottomSheet.selectedChapterId != page.chapter.chapter.id) { + readerBottomSheetBinding.chaptersBottomSheet.refreshList() + } + readerBottomSheetBinding.chaptersBottomSheet.shouldCollapse = true // Set seekbar progress - binding.pageSeekbar.max = pages.lastIndex - binding.pageSeekbar.progress = page.index + + readerBottomSheetBinding.pageSeekbar.max = pages.lastIndex + readerBottomSheetBinding.pageSeekbar.progress = page.index + // SY <-- } /** @@ -778,6 +836,9 @@ class ReaderActivity : BaseRxActivity() } catch (e: WindowManager.BadTokenException) { logger.e("Caught and ignoring reader page sheet launch exception!", e) } + if (readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior.isExpanded()) { + readerBottomSheetBinding.chaptersBottomSheet.sheetBehavior?.collapse() + } // EXH <-- } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index d71fa0125..767c65903 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -1,12 +1,14 @@ package eu.kanade.tachiyomi.ui.reader import android.app.Application +import android.content.Context import android.os.Bundle import android.os.Environment import com.jakewharton.rxrelay.BehaviorRelay import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.download.DownloadManager @@ -16,6 +18,7 @@ import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.ui.reader.chapter.ReaderChapterItem import eu.kanade.tachiyomi.ui.reader.loader.ChapterLoader import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderPage @@ -31,8 +34,12 @@ import exh.EH_SOURCE_ID import exh.EXH_SOURCE_ID import exh.util.defaultReaderType import java.io.File +import java.text.DecimalFormat +import java.text.DecimalFormatSymbols import java.util.Date import java.util.concurrent.TimeUnit +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import rx.Completable import rx.Observable import rx.Subscription @@ -250,6 +257,30 @@ class ReaderPresenter( ) } + // SY --> + suspend fun getChapters(context: Context): List { + return withContext(Dispatchers.IO) { + val currentChapter = getCurrentChapter() + val decimalFormat = DecimalFormat( + "#.###", + DecimalFormatSymbols() + .apply { decimalSeparator = '.' } + ) + + chapterList.reversed().map { + ReaderChapterItem( + it.chapter, + manga!!, + it.chapter == currentChapter?.chapter, + context, + preferences.dateFormat(), + decimalFormat + ) + } + } + } + // SY <-- + /** * Returns an observable that loads the given [chapter] with this [loader]. This observable * handles main thread synchronization and updating the currently active chapters on @@ -302,6 +333,11 @@ class ReaderPresenter( .also(::add) } + fun loadNewChapterFromSheet(chapter: Chapter) { + val newChapter = chapterList.firstOrNull { it.chapter.id == chapter.id } ?: return + loadAdjacent(newChapter) + } + /** * Called when the user is going to load the prev/next chapter through the menu button. It * sets the [isLoadingAdjacentChapterRelay] that the view uses to prevent any further @@ -353,8 +389,8 @@ class ReaderPresenter( * read, update tracking services, enqueue downloaded chapter deletion, and updating the active chapter if this * [page]'s chapter is different from the currently active. */ - fun onPageSelected(page: ReaderPage) { - val currentChapters = viewerChaptersRelay.value ?: return + fun onPageSelected(page: ReaderPage): Boolean { + val currentChapters = viewerChaptersRelay.value ?: return /* SY --> */ false /* SY <-- */ val selectedChapter = page.chapter @@ -380,7 +416,14 @@ class ReaderPresenter( Timber.d("Setting ${selectedChapter.chapter.url} as active") onChapterChanged(currentChapters.currChapter) loadNewChapter(selectedChapter) + // SY --> + Observable.just(selectedChapter).subscribeFirst({ view, _ -> + view.refreshSheetChapters() + }) + return true + // SY <-- } + return /* SY --> */ false /* SY <-- */ } /** @@ -472,6 +515,14 @@ class ReaderPresenter( db.updateChapterProgress(chapter).executeAsBlocking() } + // SY --> + fun toggleBookmark(chapter: Chapter) { + chapter.bookmark = !chapter.bookmark + db.updateChapterProgress(chapter).executeAsBlocking() + chapterList.firstOrNull { it.chapter.id == chapter.id }?.let { it.chapter.bookmark == !chapter.bookmark } + } + // SY <-- + /** * Returns the viewer position used by this manga or the default one. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/chapter/ReaderChapterItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/chapter/ReaderChapterItem.kt new file mode 100644 index 000000000..28d03679a --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/chapter/ReaderChapterItem.kt @@ -0,0 +1,104 @@ +package eu.kanade.tachiyomi.ui.reader.chapter + +import android.content.Context +import android.graphics.Typeface +import android.text.SpannableStringBuilder +import android.view.View +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.TextView +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.items.AbstractItem +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.models.Chapter +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.util.system.getResourceColor +import eu.kanade.tachiyomi.util.view.setVectorCompat +import java.text.DateFormat +import java.text.DecimalFormat +import java.util.Date + +class ReaderChapterItem(val chapter: Chapter, val manga: Manga, val isCurrent: Boolean, context: Context, val dateFormat: DateFormat, val decimalFormat: DecimalFormat) : + AbstractItem(), + Chapter by chapter { + + val readColor = context.getResourceColor(R.attr.colorOnSurface, 0.38f) + val unreadColor = context.getResourceColor(R.attr.colorOnSurface) + val bookmarkedColor = context.getResourceColor(R.attr.colorAccent) + + /** defines the type defining this item. must be unique. preferably an id */ + override val type: Int = R.id.reader_chapter_layout + + /** defines the layout which will be used for this item in the list */ + override val layoutRes: Int = R.layout.reader_chapter_item + + override var identifier: Long = chapter.id!! + + override fun getViewHolder(v: View): ViewHolder { + return ViewHolder(v) + } + + class ViewHolder(view: View) : FastAdapter.ViewHolder(view) { + private var chapterTitle: TextView = view.findViewById(R.id.chapter_title) + private var chapterSubtitle: TextView = view.findViewById(R.id.chapter_scanlator) + var bookmarkButton: FrameLayout = view.findViewById(R.id.bookmark_layout) + private var bookmarkImage: ImageView = view.findViewById(R.id.bookmark_image) + + override fun bindView(item: ReaderChapterItem, payloads: List) { + val manga = item.manga + + chapterTitle.text = when (manga.displayMode) { + Manga.DISPLAY_NUMBER -> { + val number = item.decimalFormat.format(item.chapter_number.toDouble()) + itemView.context.getString(R.string.display_mode_chapter, number) + } + else -> item.name + } + + // Set correct text color + val chapterColor = when { + item.read -> item.readColor + item.bookmark -> item.bookmarkedColor + else -> item.unreadColor + } + chapterTitle.setTextColor(chapterColor) + chapterSubtitle.setTextColor(chapterColor) + + // bookmarkImage.isVisible = item.bookmark + + val descriptions = mutableListOf() + + if (item.date_upload > 0) { + descriptions.add(item.dateFormat.format(Date(item.date_upload))) + } + if (!item.scanlator.isNullOrBlank()) { + descriptions.add(item.scanlator!!) + } + + if (descriptions.isNotEmpty()) { + chapterSubtitle.text = descriptions.joinTo(SpannableStringBuilder(), " • ") + } else { + chapterSubtitle.text = "" + } + + if (item.bookmark) { + bookmarkImage.setVectorCompat(R.drawable.ic_bookmark_24dp, R.attr.colorAccent) + } else { + bookmarkImage.setVectorCompat(R.drawable.ic_bookmark_border_24dp, R.attr.colorOnSurface) + } + + if (item.isCurrent) { + chapterTitle.setTypeface(null, Typeface.BOLD_ITALIC) + chapterSubtitle.setTypeface(null, Typeface.BOLD_ITALIC) + } else { + chapterTitle.setTypeface(null, Typeface.NORMAL) + chapterSubtitle.setTypeface(null, Typeface.NORMAL) + } + } + + override fun unbindView(item: ReaderChapterItem) { + chapterTitle.text = null + chapterSubtitle.text = null + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/chapter/ReaderChapterSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/chapter/ReaderChapterSheet.kt new file mode 100644 index 000000000..44dc6edb6 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/chapter/ReaderChapterSheet.kt @@ -0,0 +1,141 @@ +package eu.kanade.tachiyomi.ui.reader.chapter + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.LinearLayout +import androidx.core.view.isInvisible +import androidx.core.view.isVisible +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.adapters.ItemAdapter +import com.mikepenz.fastadapter.listeners.ClickEventHook +import eu.kanade.tachiyomi.databinding.ReaderChaptersSheetBinding +import eu.kanade.tachiyomi.ui.reader.ReaderActivity +import eu.kanade.tachiyomi.ui.reader.ReaderPresenter +import eu.kanade.tachiyomi.util.lang.launchUI +import eu.kanade.tachiyomi.util.system.dpToPx +import exh.util.collapse +import exh.util.expand +import exh.util.isExpanded +import kotlin.math.max + +class ReaderChapterSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + LinearLayout(context, attrs) { + + lateinit var binding: ReaderChaptersSheetBinding + + var sheetBehavior: BottomSheetBehavior? = null + lateinit var presenter: ReaderPresenter + var adapter: FastAdapter? = null + private val itemAdapter = ItemAdapter() + var shouldCollapse = true + var selectedChapterId = -1L + + fun setup(activity: ReaderActivity) { + presenter = activity.presenter + binding = activity.readerBottomSheetBinding + + sheetBehavior = BottomSheetBehavior.from(this) + binding.chaptersButton.setOnClickListener { + if (sheetBehavior.isExpanded()) { + sheetBehavior?.collapse() + } else { + sheetBehavior?.expand() + } + } + + binding.webviewButton.setOnClickListener { + activity.openMangaInBrowser() + } + + post { + binding.chapterRecycler.isClickable = sheetBehavior.isExpanded() + binding.chapterRecycler.isFocusable = sheetBehavior.isExpanded() + } + + sheetBehavior?.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + override fun onSlide(bottomSheet: View, progress: Float) { + val trueProgress = max(progress, 0f) + binding.chaptersButton.alpha = 1 - trueProgress + binding.webviewButton.alpha = trueProgress + binding.webviewButton.isVisible = binding.webviewButton.alpha > 0 + binding.chaptersButton.isInvisible = binding.chaptersButton.alpha <= 0 + } + + override fun onStateChanged(p0: View, state: Int) { + if (state == BottomSheetBehavior.STATE_COLLAPSED) { + shouldCollapse = true + sheetBehavior?.isHideable = false + (binding.chapterRecycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( + adapter?.getPosition(presenter.getCurrentChapter()?.chapter?.id ?: 0L) ?: 0, + binding.chapterRecycler.height / 2 - 30.dpToPx + ) + binding.chaptersButton.alpha = 1f + binding.webviewButton.alpha = 0f + } + if (state == BottomSheetBehavior.STATE_EXPANDED) { + binding.chaptersButton.alpha = 0f + binding.webviewButton.alpha = 1f + } + binding.chapterRecycler.isClickable = state == BottomSheetBehavior.STATE_EXPANDED + binding.chapterRecycler.isFocusable = state == BottomSheetBehavior.STATE_EXPANDED + binding.webviewButton.isVisible = state != BottomSheetBehavior.STATE_COLLAPSED + binding.chaptersButton.isInvisible = state == BottomSheetBehavior.STATE_EXPANDED + } + }) + + adapter = FastAdapter.with(itemAdapter) + binding.chapterRecycler.adapter = adapter + adapter?.onClickListener = { _, _, item, _ -> + if (!sheetBehavior.isExpanded()) { + false + } else { + if (item.chapter.id != presenter.getCurrentChapter()?.chapter?.id) { + shouldCollapse = false + presenter.loadNewChapterFromSheet(item.chapter) + } + true + } + } + adapter?.addEventHook(object : ClickEventHook() { + override fun onBind(viewHolder: RecyclerView.ViewHolder): View? { + return if (viewHolder is ReaderChapterItem.ViewHolder) { + viewHolder.bookmarkButton + } else { + null + } + } + + override fun onClick( + v: View, + position: Int, + fastAdapter: FastAdapter, + item: ReaderChapterItem + ) { + presenter.toggleBookmark(item.chapter) + refreshList() + } + }) + + binding.chapterRecycler.layoutManager = LinearLayoutManager(context) + refreshList() + } + + fun refreshList() { + launchUI { + val chapters = presenter.getChapters(context) + + selectedChapterId = chapters.find { it.isCurrent }?.chapter?.id ?: -1L + itemAdapter.clear() + itemAdapter.add(chapters) + + (binding.chapterRecycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( + adapter?.getPosition(presenter.getCurrentChapter()?.chapter?.id ?: 0L) ?: 0, + binding.chapterRecycler.height / 2 - 30.dpToPx + ) + } + } +} diff --git a/app/src/main/java/exh/util/BottomSheetExtensions.kt b/app/src/main/java/exh/util/BottomSheetExtensions.kt new file mode 100644 index 000000000..7183d7349 --- /dev/null +++ b/app/src/main/java/exh/util/BottomSheetExtensions.kt @@ -0,0 +1,22 @@ +package exh.util + +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED +import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED +import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN + +fun BottomSheetBehavior<*>.hide() { + state = STATE_HIDDEN +} + +fun BottomSheetBehavior<*>.collapse() { + state = STATE_COLLAPSED +} + +fun BottomSheetBehavior<*>.expand() { + state = STATE_EXPANDED +} + +fun BottomSheetBehavior<*>?.isExpanded() = this?.state == STATE_EXPANDED +fun BottomSheetBehavior<*>?.isCollapsed() = this?.state == STATE_COLLAPSED +fun BottomSheetBehavior<*>?.isHidden() = this?.state == STATE_HIDDEN diff --git a/app/src/main/res/drawable/ic_format_list_numbered_24dp.xml b/app/src/main/res/drawable/ic_format_list_numbered_24dp.xml new file mode 100644 index 000000000..a1a196172 --- /dev/null +++ b/app/src/main/res/drawable/ic_format_list_numbered_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/migration_bottom_sheet.xml b/app/src/main/res/layout/migration_bottom_sheet.xml index 6f9a120c2..e51828406 100644 --- a/app/src/main/res/layout/migration_bottom_sheet.xml +++ b/app/src/main/res/layout/migration_bottom_sheet.xml @@ -1,7 +1,6 @@ - - - - - - - - - - - - - - - + + - + diff --git a/app/src/main/res/layout/reader_chapter_item.xml b/app/src/main/res/layout/reader_chapter_item.xml new file mode 100644 index 000000000..26be39f87 --- /dev/null +++ b/app/src/main/res/layout/reader_chapter_item.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/reader_chapters_sheet.xml b/app/src/main/res/layout/reader_chapters_sheet.xml new file mode 100644 index 000000000..b2d5da9a3 --- /dev/null +++ b/app/src/main/res/layout/reader_chapters_sheet.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file