Fixed layout

[Hitomi] Fixed image not loading
This commit is contained in:
tom5079
2021-12-26 12:28:52 +09:00
parent 3abd015505
commit 193db578f0
7 changed files with 110 additions and 114 deletions

View File

@@ -25,8 +25,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Stop
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -35,12 +33,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.scale import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -58,9 +51,9 @@ enum class FloatingActionButtonState(private val isExpanded: Boolean) {
} }
data class SubFabItem( data class SubFabItem(
val icon: Any, // ImageVector | Painter | ImageBitmap
val label: String? = null, val label: String? = null,
val onClick: ((SubFabItem) -> Unit)? = null val onClick: ((SubFabItem) -> Unit)? = null,
val icon: @Composable () -> Unit
) )
@Composable @Composable
@@ -99,33 +92,15 @@ fun MiniFloatingActionButton(
.scale(buttonScale), .scale(buttonScale),
onClick = { onClick?.invoke(item) }, onClick = { onClick?.invoke(item) },
elevation = elevation, elevation = elevation,
interactionSource = interactionSource interactionSource = interactionSource,
) { content = item.icon
when (item.icon) { )
is ImageVector ->
Icon(item.icon, contentDescription = null)
is Painter ->
Icon(item.icon, contentDescription = null)
is ImageBitmap ->
Icon(item.icon, contentDescription = null)
else -> error("Icon is not ImageVector | Painter | ImageBitmap")
}
}
} }
} }
private class FloatingActionButtonItemProvider : PreviewParameterProvider<SubFabItem> {
override val values: Sequence<SubFabItem>
get() = sequenceOf(
SubFabItem(Icons.Default.PlayArrow, "Play"),
SubFabItem(Icons.Default.Stop, "Stop")
)
}
@Preview
@Composable @Composable
fun MultipleFloatingActionButton( fun MultipleFloatingActionButton(
@PreviewParameter(provider = FloatingActionButtonItemProvider::class) items: List<SubFabItem>, items: List<SubFabItem>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
fabIcon: ImageVector = Icons.Default.Add, fabIcon: ImageVector = Icons.Default.Add,
visible: Boolean = true, visible: Boolean = true,

View File

@@ -242,11 +242,17 @@ open class ReaderBaseViewModel(app: Application) : AndroidViewModel(app), DIAwar
} }
progressList[index] = flow.value progressList[index] = flow.value
totalProgressMutex.withLock {
totalProgress++
}
} }
} }
"content" -> { "content" -> {
imageList[index] = Uri.parse(url) imageList[index] = Uri.parse(url)
progressList[index] = Float.POSITIVE_INFINITY progressList[index] = Float.POSITIVE_INFINITY
totalProgressMutex.withLock {
totalProgress++
}
} }
else -> throw IllegalArgumentException("Expected URL scheme 'http(s)' or 'content' but was '$scheme'") else -> throw IllegalArgumentException("Expected URL scheme 'http(s)' or 'content' but was '$scheme'")
} }
@@ -274,9 +280,10 @@ val ReaderOptions.Orientation.isReverse: Boolean
this == ReaderOptions.Orientation.VERTICAL_UP || this == ReaderOptions.Orientation.VERTICAL_UP ||
this == ReaderOptions.Orientation.HORIZONTAL_LEFT this == ReaderOptions.Orientation.HORIZONTAL_LEFT
@ExperimentalMaterialApi
@Composable @Composable
fun ReaderOptionsSheet(readerOptions: ReaderOptions, onOptionsChange: (ReaderOptions.Builder.() -> Unit) -> Unit) { fun ReaderOptionsSheet(readerOptions: ReaderOptions, onOptionsChange: (ReaderOptions.Builder.() -> Unit) -> Unit) {
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.h6) { CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.h6, LocalMinimumTouchTargetEnforcement provides false) {
Column(Modifier.padding(16.dp, 0.dp)) { Column(Modifier.padding(16.dp, 0.dp)) {
val layout = readerOptions.layout val layout = readerOptions.layout
val snap = readerOptions.snap val snap = readerOptions.snap
@@ -296,18 +303,20 @@ fun ReaderOptionsSheet(readerOptions: ReaderOptions, onOptionsChange: (ReaderOpt
ReaderOptions.Layout.DOUBLE_PAGE to DoubleImage, ReaderOptions.Layout.DOUBLE_PAGE to DoubleImage,
ReaderOptions.Layout.AUTO to Icons.Default.AutoFixHigh ReaderOptions.Layout.AUTO to Icons.Default.AutoFixHigh
).forEach { (option, icon) -> ).forEach { (option, icon) ->
IconButton(onClick = { CompositionLocalProvider(LocalMinimumTouchTargetEnforcement provides true) {
onOptionsChange { IconButton(onClick = {
setLayout(option) onOptionsChange {
} setLayout(option)
}) { }
Icon( }) {
icon, Icon(
contentDescription = null, icon,
tint = contentDescription = null,
tint =
if (layout == option) MaterialTheme.colors.secondary if (layout == option) MaterialTheme.colors.secondary
else LocalContentColor.current else LocalContentColor.current
) )
}
} }
} }
} }
@@ -464,7 +473,6 @@ fun BoxScope.ReaderLazyList(
.align(Alignment.TopStart) .align(Alignment.TopStart)
.nestedScroll(nestedScrollConnection), .nestedScroll(nestedScrollConnection),
state = state, state = state,
verticalArrangement = Arrangement.spacedBy(4.dp),
contentPadding = rememberInsetsPaddingValues(LocalWindowInsets.current.navigationBars), contentPadding = rememberInsetsPaddingValues(LocalWindowInsets.current.navigationBars),
reverseLayout = isReverse, reverseLayout = isReverse,
content = content content = content
@@ -477,7 +485,6 @@ fun BoxScope.ReaderLazyList(
.align(Alignment.CenterStart) .align(Alignment.CenterStart)
.nestedScroll(nestedScrollConnection), .nestedScroll(nestedScrollConnection),
state = state, state = state,
horizontalArrangement = Arrangement.spacedBy(4.dp),
reverseLayout = isReverse, reverseLayout = isReverse,
content = content content = content
) )
@@ -716,7 +723,7 @@ fun ReaderBase(
val imageSources = remember { mutableStateListOf<ImageSource?>() } val imageSources = remember { mutableStateListOf<ImageSource?>() }
val imageSizes = remember { mutableStateListOf<Size?>() } val imageSizes = remember { mutableStateListOf<Size?>() }
LaunchedEffect(model.progressList.count { it.isFinite() }) { LaunchedEffect(model.totalProgress) {
val size = model.progressList.size val size = model.progressList.size
if (imageSources.size != size) if (imageSources.size != size)
@@ -734,7 +741,7 @@ fun ReaderBase(
if (imageSizes[i] == null && model.progressList[i] == Float.POSITIVE_INFINITY) if (imageSizes[i] == null && model.progressList[i] == Float.POSITIVE_INFINITY)
imageSources[i]?.let { imageSources[i]?.let {
imageSizes[i] = it.imageSize imageSizes[i] = runCatching { it.imageSize }.getOrNull()
} }
} }
} }

View File

@@ -25,6 +25,7 @@ import androidx.compose.material.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Settings
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
@@ -35,6 +36,7 @@ import org.kodein.di.compose.rememberInstance
import xyz.quaver.pupil.sources.Source import xyz.quaver.pupil.sources.Source
import xyz.quaver.pupil.sources.SourceEntries import xyz.quaver.pupil.sources.SourceEntries
@ExperimentalMaterialApi
@Composable @Composable
fun SourceSelectDialog(navController: NavController, currentSource: String? = null, onDismissRequest: () -> Unit = { }) { fun SourceSelectDialog(navController: NavController, currentSource: String? = null, onDismissRequest: () -> Unit = { }) {
SourceSelectDialog(currentSource = currentSource, onDismissRequest = onDismissRequest) { SourceSelectDialog(currentSource = currentSource, onDismissRequest = onDismissRequest) {
@@ -45,42 +47,46 @@ fun SourceSelectDialog(navController: NavController, currentSource: String? = nu
} }
} }
@ExperimentalMaterialApi
@Composable @Composable
fun SourceSelectDialogItem(source: Source, isSelected: Boolean, onSelected: (Source) -> Unit = { }) { fun SourceSelectDialogItem(source: Source, isSelected: Boolean, onSelected: (Source) -> Unit = { }) {
Row( CompositionLocalProvider(LocalMinimumTouchTargetEnforcement provides false) {
modifier = Modifier.padding(16.dp), Row(
verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp) verticalAlignment = Alignment.CenterVertically,
) { horizontalArrangement = Arrangement.spacedBy(16.dp)
Image(
painter = painterResource(source.iconResID),
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Text(
source.name,
modifier = Modifier.weight(1f)
)
Icon(
Icons.Default.Settings,
contentDescription = null,
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.5f)
)
Button(
enabled = !isSelected,
onClick = {
onSelected(source)
}
) { ) {
Text("GO") Image(
} painter = painterResource(source.iconResID),
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Text(
source.name,
modifier = Modifier.weight(1f)
)
Icon(
Icons.Default.Settings,
contentDescription = null,
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.5f)
)
Button(
enabled = !isSelected,
onClick = {
onSelected(source)
}
) {
Text("GO")
}
}
} }
} }
@ExperimentalMaterialApi
@Composable @Composable
fun SourceSelectDialog(currentSource: String? = null, onDismissRequest: () -> Unit = { }, onSelected: (Source) -> Unit = { }) { fun SourceSelectDialog(currentSource: String? = null, onDismissRequest: () -> Unit = { }, onSelected: (Source) -> Unit = { }) {
val sourceEntries: SourceEntries by rememberInstance() val sourceEntries: SourceEntries by rememberInstance()

View File

@@ -126,17 +126,20 @@ class Hitomi(app: Application) : Source(), DIAware {
model, model,
fabSubMenu = listOf( fabSubMenu = listOf(
SubFabItem( SubFabItem(
painterResource(R.drawable.ic_jump),
stringResource(R.string.main_jump_title) stringResource(R.string.main_jump_title)
), ) {
Icon(painterResource(R.drawable.ic_jump), contentDescription = null)
},
SubFabItem( SubFabItem(
Icons.Default.Shuffle,
stringResource(R.string.main_fab_random) stringResource(R.string.main_fab_random)
), ) {
Icon(Icons.Default.Shuffle, contentDescription = null)
},
SubFabItem( SubFabItem(
painterResource(R.drawable.numeric),
stringResource(R.string.main_open_gallery_by_id) stringResource(R.string.main_open_gallery_by_id)
) ) {
Icon(painterResource(R.drawable.numeric), contentDescription = null)
}
), ),
actions = { actions = {
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
@@ -205,9 +208,6 @@ class Hitomi(app: Application) : Source(), DIAware {
} }
} }
) { result -> ) { result ->
logger.info {
result.toString()
}
navController.navigate("hitomi.la/reader/${result.itemID}") navController.navigate("hitomi.la/reader/${result.itemID}")
} }
} }

View File

@@ -97,6 +97,7 @@ private fun String.wordCapitalize() : String {
return result.joinToString(" ") return result.joinToString(" ")
} }
@ExperimentalMaterialApi
@Composable @Composable
fun DetailedSearchResult( fun DetailedSearchResult(
result: HitomiSearchResult, result: HitomiSearchResult,
@@ -178,7 +179,9 @@ fun DetailedSearchResult(
Divider() Divider()
Row( Row(
modifier = Modifier.fillMaxWidth().padding(8.dp), modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween horizontalArrangement = Arrangement.SpaceBetween
) { ) {
@@ -192,16 +195,18 @@ fun DetailedSearchResult(
if (result.itemID in bookmarks) Icons.Default.Star else Icons.Default.StarOutline, if (result.itemID in bookmarks) Icons.Default.Star else Icons.Default.StarOutline,
contentDescription = null, contentDescription = null,
tint = Orange500, tint = Orange500,
modifier = Modifier.size(24.dp).clickable { modifier = Modifier
onBookmarkToggle(result.itemID) .size(24.dp)
} .clickable {
onBookmarkToggle(result.itemID)
}
) )
} }
} }
} }
} }
@OptIn(ExperimentalMaterialApi::class) @ExperimentalMaterialApi
@Composable @Composable
fun TagGroup( fun TagGroup(
tags: List<String>, tags: List<String>,
@@ -212,30 +217,33 @@ fun TagGroup(
val bookmarkedTagsInList = bookmarks intersect tags.toSet() val bookmarkedTagsInList = bookmarks intersect tags.toSet()
FlowRow(Modifier.padding(0.dp, 16.dp)) { CompositionLocalProvider(LocalMinimumTouchTargetEnforcement provides false) {
tags.sortedBy { if (bookmarkedTagsInList.contains(it)) 0 else 1 }.let { (if (isFolded) it.take(10) else it) }.forEach { tag -> FlowRow(Modifier.padding(0.dp, 16.dp)) {
TagChip( tags.sortedBy { if (bookmarkedTagsInList.contains(it)) 0 else 1 }
tag = tag, .let { (if (isFolded) it.take(10) else it) }.forEach { tag ->
isFavorite = bookmarkedTagsInList.contains(tag), TagChip(
onFavoriteClick = onBookmarkToggle tag = tag,
) isFavorite = bookmarkedTagsInList.contains(tag),
} onFavoriteClick = onBookmarkToggle
if (isFolded && tags.size > 10)
Surface(
modifier = Modifier.padding(2.dp),
color = MaterialTheme.colors.background,
shape = RoundedCornerShape(16.dp),
elevation = 2.dp,
onClick = { isFolded = false }
) {
Text(
"",
modifier = Modifier.padding(16.dp, 8.dp),
color = MaterialTheme.colors.onBackground,
style = MaterialTheme.typography.body2
) )
} }
if (isFolded && tags.size > 10)
Surface(
modifier = Modifier.padding(2.dp),
color = MaterialTheme.colors.background,
shape = RoundedCornerShape(16.dp),
elevation = 2.dp,
onClick = { isFolded = false }
) {
Text(
"",
modifier = Modifier.padding(16.dp, 8.dp),
color = MaterialTheme.colors.onBackground,
style = MaterialTheme.typography.body2
)
}
}
} }
} }

View File

@@ -100,7 +100,7 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
val misoPostList = doc.select(".miso-post-list") val misoPostList = doc.select(".miso-post-list")
misoPostList[4] misoPostList[4]
.select(".post-row > a").also { logger.info { it.size.toString() } } .select(".post-row > a")
.forEach { entry -> .forEach { entry ->
yield() yield()
val itemID = entry.attr("href").takeLastWhile { it != '/' } val itemID = entry.attr("href").takeLastWhile { it != '/' }

View File

@@ -22,6 +22,7 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
@@ -46,7 +47,7 @@ import xyz.quaver.pupil.sources.SourceEntries
import xyz.quaver.pupil.sources.composable.SourceSelectDialog import xyz.quaver.pupil.sources.composable.SourceSelectDialog
import xyz.quaver.pupil.ui.theme.PupilTheme import xyz.quaver.pupil.ui.theme.PupilTheme
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterialApi::class)
class MainActivity : ComponentActivity(), DIAware { class MainActivity : ComponentActivity(), DIAware {
override val di by closestDI() override val di by closestDI()
@@ -54,7 +55,6 @@ class MainActivity : ComponentActivity(), DIAware {
private val logger = newLogger(LoggerFactory.default) private val logger = newLogger(LoggerFactory.default)
@OptIn(ExperimentalAnimationApi::class)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)