[Manatoki] Implemented next episode button in reader

[Hitomi] Adjusted Search result padding
This commit is contained in:
tom5079
2021-12-26 21:19:51 +09:00
parent 0ff91d76b1
commit c3c5761ffa
4 changed files with 112 additions and 70 deletions

View File

@@ -520,9 +520,16 @@ fun ReaderItem(
}
val modifier = when {
imageSize == null -> Modifier.weight(1f).height(heightDp)
readerOptions.padding -> Modifier.fillMaxHeight().widthIn(0.dp, widthDp/images.size).aspectRatio(imageSize.width/imageSize.height)
readerOptions.orientation.isVertical -> Modifier.weight(1f).aspectRatio(imageSize.width/imageSize.height)
imageSize == null -> Modifier
.weight(1f)
.height(heightDp)
readerOptions.padding -> Modifier
.fillMaxHeight()
.widthIn(0.dp, widthDp / images.size)
.aspectRatio(imageSize.width / imageSize.height)
readerOptions.orientation.isVertical -> Modifier
.weight(1f)
.aspectRatio(imageSize.width / imageSize.height)
else -> Modifier.aspectRatio(imageSize.width/imageSize.height)
}
@@ -627,6 +634,7 @@ fun LazyListScope.ReaderLazyListContent(
fun ReaderBase(
modifier: Modifier = Modifier,
model: ReaderBaseViewModel,
listState: LazyListState = rememberLazyListState(),
onScroll: (direction: Float) -> Unit = { }
) {
val context = LocalContext.current
@@ -687,7 +695,6 @@ fun ReaderBase(
}
) {
var listSize: Size? by remember { mutableStateOf(null) }
val listState = rememberLazyListState()
val nestedScrollConnection = remember { object: NestedScrollConnection {
override suspend fun onPreFling(available: Velocity): Velocity {

View File

@@ -109,7 +109,7 @@ fun DetailedSearchResult(
Card(
modifier = Modifier
.padding(8.dp)
.padding(8.dp, 4.dp)
.fillMaxWidth()
.clickable { onClick(result) },
elevation = 4.dp

View File

@@ -18,9 +18,7 @@
package xyz.quaver.pupil.sources.manatoki.composable
import android.util.Log
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.ExperimentalFoundationApi
@@ -30,15 +28,11 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyListItemInfo
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.List
import androidx.compose.material.icons.filled.NavigateBefore
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.filled.StarOutline
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.saveable.rememberSaveable
@@ -115,7 +109,8 @@ fun Reader(navController: NavController) {
).calculateBottomPadding().toPx()
}
val listState = rememberLazyListState()
val bottomSheetListState = rememberLazyListState()
val readerListState = rememberLazyListState()
var scrollDirection by remember { mutableStateOf(0f) }
@@ -140,17 +135,10 @@ fun Reader(navController: NavController) {
mangaListingListSize = it
},
rippleInteractionSource = mangaListingRippleInteractionSource,
listState = listState
listState = bottomSheetListState
) {
coroutineScope.launch {
client.getItem(
it,
onReader = {
navController.navigate("manatoki.net/reader/${it.itemID}") {
popUpTo("manatoki.net/")
}
}
)
navController.navigate("manatoki.net/reader/$it") {
popUpTo("manatoki.net/")
}
}
}
@@ -205,70 +193,96 @@ fun Reader(navController: NavController) {
)
},
floatingActionButton = {
val scale by animateFloatAsState(if (model.fullscreen || scrollDirection < 0f) 0f else 1f)
val showNextButton by derivedStateOf {
(readerInfo?.nextItemID?.isNotEmpty() == true) && with (readerListState.layoutInfo) {
visibleItemsInfo.lastOrNull()?.index == totalItemsCount-1
}
}
val scale by animateFloatAsState(if (!showNextButton && (model.fullscreen || scrollDirection < 0f)) 0f else 1f)
if (scale > 0f)
FloatingActionButton(
modifier = Modifier.navigationBarsPadding().scale(scale),
modifier = Modifier
.navigationBarsPadding()
.scale(scale),
onClick = {
readerInfo?.let {
coroutineScope.launch {
sheetState.show()
}
if (showNextButton) {
navController.navigate("manatoki.net/reader/${it.nextItemID}") {
popUpTo("manatoki.net/")
}
} else {
coroutineScope.launch {
sheetState.show()
}
coroutineScope.launch {
if (mangaListing?.itemID != it.listingItemID)
client.getItem(it.listingItemID, onListing = {
mangaListing = it
coroutineScope.launch {
if (mangaListing?.itemID != it.listingItemID)
client.getItem(it.listingItemID, onListing = {
mangaListing = it
mangaListingRippleInteractionSource.addAll(
List(max(it.entries.size - mangaListingRippleInteractionSource.size, 0)) {
MutableInteractionSource()
}
)
coroutineScope.launch {
while (listState.layoutInfo.totalItemsCount != it.entries.size) {
delay(100)
}
val targetIndex = it.entries.indexOfFirst { it.itemID == itemID }
listState.scrollToItem(targetIndex)
mangaListingListSize?.let { sheetSize ->
val targetItem = listState.layoutInfo.visibleItemsInfo.first {
it.key == itemID
}
if (targetItem.offset == 0) {
listState.animateScrollBy(
-(sheetSize.height - navigationBarsPadding - targetItem.size)
mangaListingRippleInteractionSource.addAll(
List(
max(
it.entries.size - mangaListingRippleInteractionSource.size,
0
)
) {
MutableInteractionSource()
}
)
coroutineScope.launch {
while (bottomSheetListState.layoutInfo.totalItemsCount != it.entries.size) {
delay(100)
}
delay(200)
val targetIndex =
it.entries.indexOfFirst { it.itemID == itemID }
with (mangaListingRippleInteractionSource[targetIndex]) {
val interaction = PressInteraction.Press(
Offset(sheetSize.width/2, targetItem.size/2f)
)
bottomSheetListState.scrollToItem(targetIndex)
mangaListingListSize?.let { sheetSize ->
val targetItem =
bottomSheetListState.layoutInfo.visibleItemsInfo.first {
it.key == itemID
}
if (targetItem.offset == 0) {
bottomSheetListState.animateScrollBy(
-(sheetSize.height - navigationBarsPadding - targetItem.size)
)
}
delay(200)
with(mangaListingRippleInteractionSource[targetIndex]) {
val interaction =
PressInteraction.Press(
Offset(
sheetSize.width / 2,
targetItem.size / 2f
)
)
emit(interaction)
emit(PressInteraction.Release(interaction))
emit(interaction)
emit(
PressInteraction.Release(
interaction
)
)
}
}
}
}
})
})
}
}
}
}
) {
Icon(
Icons.Default.List,
if (showNextButton) Icons.Default.NavigateNext else Icons.Default.List,
contentDescription = null
)
}
@@ -277,6 +291,7 @@ fun Reader(navController: NavController) {
ReaderBase(
Modifier.padding(contentPadding),
model = model,
listState = readerListState,
onScroll = { scrollDirection = it }
)
}

View File

@@ -85,7 +85,9 @@ data class ReaderInfo(
val itemID: String,
val title: String,
val urls: List<String>,
val listingItemID: String
val listingItemID: String,
val prevItemID: String,
val nextItemID: String
): Parcelable
@ExperimentalMaterialApi
@@ -142,7 +144,7 @@ suspend fun HttpClient.getItem(
}.toString()
val urls = Jsoup.parse(htmlData)
.select("img[^data-]:not([style])")
.select("img[^data-]:not([style]):not([src*=loading])").also { Log.d("PUPILD", it.size.toString()) }
.map {
it.attributes()
.first { it.key.startsWith("data-") }
@@ -154,11 +156,29 @@ suspend fun HttpClient.getItem(
val listingItemID = doc.select("a:contains(전체목록)").first()!!.attr("href")
.takeLastWhile { it != '/' }
val prevItemID = doc.getElementById("goPrevBtn")!!.attr("href")
.let {
if (it.contains('?'))
it.dropLastWhile { it != '?' }.drop(1)
else it
}
.takeLastWhile { it != '/' }
val nextItemID = doc.getElementById("goNextBtn")!!.attr("href")
.let {
if (it.contains('?'))
it.dropLastWhile { it != '?' }.drop(1)
else it
}
.takeLastWhile { it != '/' }
val readerInfo = ReaderInfo(
itemID,
title,
urls,
listingItemID
listingItemID,
prevItemID,
nextItemID
)
synchronized(cache) {