Skip to content

Commit

Permalink
Add overscroll to pager, add slider to seek page in reader
Browse files Browse the repository at this point in the history
  • Loading branch information
VietAnh14 committed Apr 17, 2022
1 parent 280df3e commit 87c61b4
Show file tree
Hide file tree
Showing 24 changed files with 186 additions and 147 deletions.
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
applicationId "com.vianh.blogtruyen"
minSdkVersion 21
targetSdkVersion 31
versionCode 16
versionName "0.15"
versionCode 18
versionName "0.18"
setArchivesBaseName("blogTruyen_$versionName")

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class MangaDetailsViewModel(
return
}

commentJob = launchJob {
commentJob = launchJob(Dispatchers.Default) {
val commentMap = repo.loadComments(mangaFlow.value.id, offset)
hasNextCommentPage = commentMap.isNotEmpty()
val flattenComments = ArrayList(comments.value!!)
Expand All @@ -209,7 +209,7 @@ class MangaDetailsViewModel(
flattenComments.addAll(comment.value)
}

comments.value = flattenComments
comments.postValue(flattenComments)
++commentPage
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import com.vianh.blogtruyen.databinding.CommentPageFragmentBinding
import com.vianh.blogtruyen.features.base.BaseFragment
import com.vianh.blogtruyen.features.details.MangaDetailsViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,26 @@ class ChapterHeaderAdapter(private val viewModel: MangaDetailsViewModel) : ListA
return HeaderVH(ChapterHeaderItemBinding.inflate(inflater, parent, false), viewModel)
}

override fun onBindViewHolder(holder: HeaderVH, position: Int, payloads: MutableList<Any>) {
super.onBindViewHolder(holder, position, payloads)
}

override fun onBindViewHolder(holder: HeaderVH, position: Int) {
holder.onBind(getItem(position))
}

class DiffCallback : DiffUtil.ItemCallback<HeaderItem>() {
override fun areItemsTheSame(oldItem: HeaderItem, newItem: HeaderItem): Boolean {
return newItem == oldItem
return true
}

override fun areContentsTheSame(oldItem: HeaderItem, newItem: HeaderItem): Boolean {
return newItem == oldItem
}

override fun getChangePayload(oldItem: HeaderItem, newItem: HeaderItem): Any? {
return if (newItem.descendingSort != oldItem.descendingSort) newItem.descendingSort else null
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.lifecycle.viewModelScope
import com.vianh.blogtruyen.data.model.Favorite
import com.vianh.blogtruyen.features.base.BaseVM
import com.vianh.blogtruyen.features.base.list.items.EmptyItem
import com.vianh.blogtruyen.features.base.list.items.LoadingItem
import com.vianh.blogtruyen.features.favorites.data.FavoriteRepository
import com.vianh.blogtruyen.features.list.MangaItem
import com.vianh.blogtruyen.utils.ifEmpty
Expand All @@ -16,14 +15,16 @@ import kotlinx.coroutines.flow.*
class FavoriteViewModel(private val favoriteRepository: FavoriteRepository) : BaseVM() {

private val searchQuery = MutableStateFlow<String?>(null)
private val searchQueryDebounce
get() = searchQuery.debounce(500)
.stateIn(viewModelScope, SharingStarted.Eagerly, null)

val content = combine(
favoriteRepository.observeAll(),
searchQuery.debounce(500).distinctUntilChanged().onStart { emit("") }
searchQueryDebounce
) { favorites, query -> filterContent(favorites, query) }
.mapList { mapFavoriteToFeedItem(it) }
.ifEmpty { listOf(EmptyItem(message = "No favorite manga found")) }
.onStart { emit(listOf(LoadingItem)) }
.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default)

private fun filterContent(favorites: List<Favorite>, query: String?): List<Favorite> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ class HistoryViewModel(private val historyRepository: HistoryRepository) : BaseV

private val historyItems = historyRepository.observeHistory()
private val query = MutableStateFlow("")
private val debounceQueryFlow
get() = query.debounce(500)
.stateIn(viewModelScope, SharingStarted.Eagerly, "")

val toInfoCommand = SingleLiveEvent<Manga>()

val content = combine(
historyItems,
// Debounce delay combine somehow, so we emit empty string on start
query.debounce(500).distinctUntilChanged()
.onStart { emit("") }
debounceQueryFlow
) { items, query -> filterItems(items, query) }
.map { mapHistoryToListItem(it) }
.ifEmpty { listOf(EmptyItem(message = "Empty history")) }
.onStart { emit(listOf(LoadingItem)) }
.distinctUntilChanged()
.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ abstract class Reader(@LayoutRes layoutRes: Int): Fragment(layoutRes) {

abstract fun toPage(pos: Int, animate: Boolean = true)

fun onPageChange(pos: Int) {
readerViewModel.currentPage.value = pos
}

interface ReaderContract {
val readerViewModel: ReaderViewModel
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import android.os.Bundle
import android.view.*
import androidx.appcompat.widget.Toolbar
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit
Expand Down Expand Up @@ -39,7 +37,7 @@ class ReaderFragment : BaseFragment<ReaderFragmentBinding>(), Reader.ReaderContr
override val readerViewModel by viewModel<ReaderViewModel> { parametersOf(getRestoreState()) }

private val currentReader
get() = childFragmentManager.findFragmentById(R.id.reader_container)
get() = childFragmentManager.findFragmentById(R.id.reader_container) as? Reader

override fun getToolbar(): Toolbar? {
return requireBinding.toolbar
Expand All @@ -56,7 +54,7 @@ class ReaderFragment : BaseFragment<ReaderFragmentBinding>(), Reader.ReaderContr
readerViewModel.uiState.observe(viewLifecycleOwner, ::onContentChange)
readerViewModel.toast.observe(viewLifecycleOwner, this::showToast)
readerViewModel.controllerVisibility.observe(viewLifecycleOwner, ::setReaderControlVisibility)
readerViewModel.pageString.observe(viewLifecycleOwner) { requireBinding.pageText.text = it }
readerViewModel.controllerState.observe(viewLifecycleOwner, ::bindControllerState)
}

private fun setup() {
Expand All @@ -69,6 +67,13 @@ class ReaderFragment : BaseFragment<ReaderFragmentBinding>(), Reader.ReaderContr
readerViewModel.toPreviousChapter()
}

pageSlider.addOnChangeListener { slider, value, fromUser ->
pageText.text = "${value.toInt()}/${slider.valueTo.toInt()}"
if (fromUser) {
currentReader?.toPage(value.toInt(), false)
}
}

readerContainer.callback = this@ReaderFragment
chapterController.setBackgroundColor(requireContext().getSurfaceColorPrimary())
}
Expand All @@ -78,7 +83,7 @@ class ReaderFragment : BaseFragment<ReaderFragmentBinding>(), Reader.ReaderContr
}

private fun getReader(mode: ReaderMode): Reader {
return when(mode) {
return when (mode) {
ReaderMode.HORIZON -> PagerReader.newInstance()
ReaderMode.VERTICAL -> VerticalReader.newInstance()
ReaderMode.CONTINUOUS_VERTICAL -> VerticalReader.newInstance(false)
Expand Down Expand Up @@ -125,15 +130,19 @@ class ReaderFragment : BaseFragment<ReaderFragmentBinding>(), Reader.ReaderContr
}
}

private fun showSettingMenu(anchor: View) {
SettingPopupWindow.show(anchor, appSettings, this)
private fun bindControllerState(controllerState: ControllerState) {
requireBinding.pageSlider.apply {
value = controllerState.page.toFloat()
valueTo = controllerState.pageSize.toFloat()
isEnabled = controllerState.enable
}
}

override fun onMenuItemClick(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.setting_item -> {
val anchor = requireView().findViewById<View>(R.id.setting_item) ?: return false
showSettingMenu(anchor)
SettingPopupWindow.show(anchor, appSettings, this)
true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ data class ReaderState(
val isOffline: Boolean = false
) : Parcelable {

}
}

data class ControllerState(
val enable: Boolean = true,
val page: Int,
val pageSize: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,20 @@ class ReaderViewModel(
ReaderModel(manga, chapter, items)
}.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default)

val pageString = combine(currentPage, currentChapter) { page, chapter ->
"${page + 1}/${chapter.pages.size}"
val controllerState = combine(currentPage, listItems) { page, list ->
val isEnable = when (list.firstOrNull()) {
null -> false
is LoadingItem -> false
is ErrorItem -> false
else -> true
}

var validPage = page
if (page > list.size) {
validPage = 0
}

ControllerState(isEnable, validPage + 1, list.size)
}.asLiveData(Dispatchers.Default)

val controllerVisibility = MutableLiveData(true)
Expand All @@ -52,7 +64,7 @@ class ReaderViewModel(

fun loadPages() {
loadPageJob?.cancel()
loadPageJob = launchJob {
loadPageJob = launchLoading {
listItems.value = listOf(LoadingItem)
val chapter = currentChapter.value
val pages = if (isOffline) {
Expand Down Expand Up @@ -117,9 +129,3 @@ class ReaderViewModel(
}
}
}

//var listImageCaption = [{"url":"https://i5.truyen-hay.com/415/415633/00-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/01.jpg","speechs":[{"coords":"508,7,512,89,651,105,785,104,786,18","text":"Ranga crimson"},{"coords":"539,214,529,305,616,361,744,349,804,295,807,213,683,137","text":"Blogtruyen vô đối"}]},{"url":"https://i5.truyen-hay.com/415/415633/02-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/03-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/04-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/05-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/06-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/07-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/08-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/09-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/10-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/11-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/12-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/13-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/14-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/15-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/16-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/17-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/18-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/19-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/20-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/21-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/22-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/23-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/24-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/25-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/26-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/27-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/28-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/29-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/30-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/31-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/32-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/33-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/34-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/35-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/36-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/37-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/38-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/39-p2j.jpg","speechs":[]},{"url":"https://i5.truyen-hay.com/415/415633/40-p2j.jpg","speechs":[]}];
//var app = angular.module('showImageApp', []);
//app.controller('showImageController', function ($scope, $http) {
// $scope.listImageCaption = listImageCaption;
//});
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
package com.vianh.blogtruyen.features.reader.type.vertical
package com.vianh.blogtruyen.features.reader.list

import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
import com.vianh.blogtruyen.R
import com.vianh.blogtruyen.data.prefs.ReaderMode
import com.vianh.blogtruyen.databinding.TransitionPageBinding
import com.vianh.blogtruyen.features.base.list.AbstractBindingHolder
import com.vianh.blogtruyen.features.base.list.AbstractViewHolder
import com.vianh.blogtruyen.features.reader.ReaderViewModel
import com.vianh.blogtruyen.features.reader.list.ReaderItem
import com.vianh.blogtruyen.utils.gone
import com.vianh.blogtruyen.utils.visible
import me.everything.android.ui.overscroll.IOverScrollState
import kotlin.math.min

class TransitionPageVH(val parent: ViewGroup, val viewModel: ReaderViewModel) :
class TransitionPageVH(val parent: ViewGroup, val viewModel: ReaderViewModel, val readerMode: ReaderMode) :
AbstractBindingHolder<ReaderItem.TransitionItem, Unit, TransitionPageBinding>(R.layout.transition_page, parent) {

init {
if (readerMode == ReaderMode.HORIZON) {
itemView.updateLayoutParams { height = ViewGroup.LayoutParams.MATCH_PARENT }
binding.description.setText(R.string.swipe_guide)
} else {
itemView.updateLayoutParams { height = context.resources.getDimensionPixelSize(R.dimen.transition_page_height) }
binding.description.setText(R.string.pull_down_guide)
}
}

private var canProcess = false

override fun onBind(data: ReaderItem.TransitionItem, extra: Unit) {
Expand Down Expand Up @@ -44,20 +55,28 @@ class TransitionPageVH(val parent: ViewGroup, val viewModel: ReaderViewModel) :
description.setText(R.string.next_chapter_guide)
} else {
canProcess = false
description.text = context.getString(R.string.pull_down_guild, boundData?.chapter?.name)
description.text = context.getString(getGuideRes(), boundData?.chapter?.name)
}
}
}

private fun setupTransitionPage() {
with(binding) {
description.text = context.getString(R.string.pull_down_guild, boundData?.chapter?.number.toString())
description.text = context.getString(getGuideRes(), boundData?.chapter?.number.toString())
nextIcon.visible()
progressCircular.show()
progressCircular.progress = 0
}
}

private fun getGuideRes(): Int {
return if (readerMode == ReaderMode.HORIZON) {
R.string.swipe_guide
} else {
R.string.pull_down_guide
}
}

private fun endNoNextChapter() {
with(binding) {
description.text = context.getString(R.string.no_next_chapter, boundData?.chapter?.number.toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class PagerItemViewHolder(parent: ViewGroup, val requestManager: RequestManager)

init {
with(binding.page) {
setMaxTileSize(getMaxTextureSize())
setMaxTileSize(maxTileSize)
setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE)
}
}
Expand Down
Loading

0 comments on commit 87c61b4

Please sign in to comment.