Compare commits

...
9 Commits
Author SHA1 Message Date
tarsin afbe0a4de5 Release 1.8.8.3
Releases / Build (push) Has been cancelled
2023-05-26 15:46:41 +08:00
tarsin 0a5cdf7c80 Fixup aa1e2102fc 2023-05-26 15:46:11 +08:00
tarsin 9d689923ac Fixup unsafe Composable behaviour 2023-05-26 15:45:58 +08:00
tarsin 98c5ae7490 Workaround aspect is NaN, Resolve #1116 2023-05-26 15:45:48 +08:00
tarsin 868ac22c69 Fix wrong thumb crop behaviour 2023-05-26 15:45:38 +08:00
tarsin 636ac64692 Release 1.8.8.2
Releases / Build (push) Has been cancelled
2023-05-26 14:35:53 +08:00
tarsin a9eec6a783 Fixup! Resolve #1113 2023-05-26 14:35:30 +08:00
tarsin 00867c7dc1 Release 1.8.8.1 bugfix version
Releases / Build (push) Has been cancelled
2023-05-26 13:46:38 +08:00
tarsin cf79cdc7c1 Resolve #1113 2023-05-26 13:45:49 +08:00
7 changed files with 80 additions and 59 deletions

No files matched your search

+2 -2
View File
@@ -57,8 +57,8 @@ android {
applicationId = "moe.tarsin.ehviewer" applicationId = "moe.tarsin.ehviewer"
minSdk = 28 minSdk = 28
targetSdk = 33 targetSdk = 33
versionCode = 180039 versionCode = 180042
versionName = "1.8.8.0" versionName = "1.8.8.3"
resourceConfigurations.addAll( resourceConfigurations.addAll(
listOf( listOf(
"zh", "zh",
@@ -55,9 +55,7 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) {
set(value) { set(value) {
field = value field = value
if (field == SpiderQueen.MODE_DOWNLOAD && downloadDir == null) { if (field == SpiderQueen.MODE_DOWNLOAD && downloadDir == null) {
val title = getSuitableTitle(mGalleryInfo) mGalleryInfo.putToDownloadDir()
val dirname = FileUtils.sanitizeFilename("$mGid-$title")
EhDB.putDownloadDirname(mGid, dirname)
downloadDir = getGalleryDownloadDir(mGid)!!.apply { check(ensureDir()) { "Download directory $uri is not valid directory!" } } downloadDir = getGalleryDownloadDir(mGid)!!.apply { check(ensureDir()) { "Download directory $uri is not valid directory!" } }
} }
} }
@@ -286,3 +284,9 @@ private fun fixExtension(extension: String): String {
private fun findImageFile(dir: UniFile, index: Int): UniFile? { private fun findImageFile(dir: UniFile, index: Int): UniFile? {
return COMPAT_IMAGE_EXTENSIONS.firstNotNullOfOrNull { dir.findFile(perFilename(index, it)) } return COMPAT_IMAGE_EXTENSIONS.firstNotNullOfOrNull { dir.findFile(perFilename(index, it)) }
} }
fun GalleryInfo.putToDownloadDir() {
val title = getSuitableTitle(this)
val dirname = FileUtils.sanitizeFilename("$gid-$title")
EhDB.putDownloadDirname(gid, dirname)
}
@@ -41,7 +41,7 @@ fun SpiderInfo.write(file: UniFile) {
suspend fun SpiderInfo.saveToCache() { suspend fun SpiderInfo.saveToCache() {
runSuspendCatching { runSuspendCatching {
spiderInfoCache.edit(gid.toString()) { spiderInfoCache.edit(gid.toString()) {
data.toFile().writeBytes(Cbor.encodeToByteArray(this)) data.toFile().writeBytes(Cbor.encodeToByteArray(this@saveToCache))
} }
}.onFailure { }.onFailure {
it.printStackTrace() it.printStackTrace()
@@ -39,7 +39,7 @@ fun EhAsyncCropThumb(
key: GalleryInfo, key: GalleryInfo,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
var contentScale by remember { mutableStateOf(ContentScale.Fit) } var contentScale by remember(key.gid) { mutableStateOf(ContentScale.Fit) }
AsyncImage( AsyncImage(
model = requestOf(key), model = requestOf(key),
contentDescription = null, contentDescription = null,
@@ -129,7 +129,7 @@ fun GalleryInfoGridItem(
info: GalleryInfo, info: GalleryInfo,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val aspect = (info.thumbWidth.toFloat() / info.thumbHeight).coerceIn(0.33F, 1.5F) val aspect = (info.thumbWidth.toFloat() / info.thumbHeight).coerceIn(0.33F, 1.5F).takeUnless { it.isNaN() } ?: 1F
val color = EhUtils.getCategoryColor(info.category) val color = EhUtils.getCategoryColor(info.category)
val simpleLang = info.simpleLanguage val simpleLang = info.simpleLanguage
ElevatedCard( ElevatedCard(
@@ -44,7 +44,7 @@ fun EhAsyncPreview(
model: GalleryPreview, model: GalleryPreview,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
var contentScale by remember { mutableStateOf(ContentScale.Fit) } var contentScale by remember(model.imageKey) { mutableStateOf(ContentScale.Fit) }
AsyncImage( AsyncImage(
model = requestOf(model), model = requestOf(model),
contentDescription = null, contentDescription = null,
@@ -32,6 +32,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -39,6 +40,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.GravityCompat import androidx.core.view.GravityCompat
@@ -58,6 +60,7 @@ import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.R import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhUtils import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.coil.imageRequest import com.hippo.ehviewer.coil.imageRequest
import com.hippo.ehviewer.coil.read import com.hippo.ehviewer.coil.read
import com.hippo.ehviewer.dao.DownloadInfo import com.hippo.ehviewer.dao.DownloadInfo
@@ -70,6 +73,7 @@ import com.hippo.ehviewer.download.DownloadManager.DownloadInfoListener
import com.hippo.ehviewer.download.DownloadService import com.hippo.ehviewer.download.DownloadService
import com.hippo.ehviewer.download.DownloadService.Companion.clear import com.hippo.ehviewer.download.DownloadService.Companion.clear
import com.hippo.ehviewer.spider.SpiderDen import com.hippo.ehviewer.spider.SpiderDen
import com.hippo.ehviewer.spider.putToDownloadDir
import com.hippo.ehviewer.ui.compose.CropDefaults import com.hippo.ehviewer.ui.compose.CropDefaults
import com.hippo.ehviewer.ui.compose.data.requestOf import com.hippo.ehviewer.ui.compose.data.requestOf
import com.hippo.ehviewer.ui.compose.setMD3Content import com.hippo.ehviewer.ui.compose.setMD3Content
@@ -879,63 +883,18 @@ class DownloadsScene :
fun bind(info: DownloadInfo) { fun bind(info: DownloadInfo) {
lifecycleScope.launchIO { lifecycleScope.launchIO {
val downloadDir = SpiderDen.getGalleryDownloadDir(info.gid) ?: run { val downloadDir = SpiderDen.getGalleryDownloadDir(info.gid) ?: run {
val title = EhUtils.getSuitableTitle(info) info.putToDownloadDir()
val dirname = FileUtils.sanitizeFilename("${info.gid}-$title")
EhDB.putDownloadDirname(info.gid, dirname)
SpiderDen.getGalleryDownloadDir(info.gid)!! SpiderDen.getGalleryDownloadDir(info.gid)!!
} }
check(downloadDir.ensureDir()) downloadDir.ensureDir()
val thumbLocation = downloadDir.subFile(".thumb")!! val thumbLocation = downloadDir.subFile(".thumb")!!
val localReq = thumbLocation.takeIf { it.exists() }?.uri?.let {
context?.imageRequest {
data(it.toString())
memoryCacheKey(info.thumbKey)
}
}
withUIContext { withUIContext {
binding.thumb.setMD3Content { binding.thumb.setMD3Content {
Card(onClick = ::onClick.partially1(binding.thumb)) { Card(onClick = ::onClick.partially1(binding.thumb)) {
var contentScale by remember { mutableStateOf(ContentScale.Fit) } CompanionAsyncThumb(
val coroutineScope = rememberCoroutineScope { Dispatchers.IO } info = info,
AsyncImage( path = thumbLocation,
model = localReq ?: requestOf(info),
contentDescription = null,
modifier = Modifier.height(height).aspectRatio(0.6666667F), modifier = Modifier.height(height).aspectRatio(0.6666667F),
onState = { state ->
if (state is AsyncImagePainter.State.Success) {
state.result.drawable.run {
if (CropDefaults.shouldCrop(intrinsicWidth, intrinsicHeight)) {
contentScale = ContentScale.Crop
}
}
coroutineScope.launch {
runCatching {
if (!thumbLocation.exists()) {
thumbLocation.ensureFile()
val key = info.thumbKey!!
imageCache.read(key) {
UniFile.fromFile(data.toFile())!!.openFileDescriptor("r").use { src ->
thumbLocation.openFileDescriptor("w").use { dst ->
src sendTo dst
}
}
}
}
}
}
}
if (state is AsyncImagePainter.State.Error) {
if (thumbLocation.exists()) {
coroutineScope.launch {
thumbLocation.delete()
withUIContext {
bind(info)
}
}
}
}
},
contentScale = contentScale,
) )
} }
} }
@@ -1287,3 +1246,61 @@ class DownloadsScene :
private const val PAYLOAD_STATE = 0 private const val PAYLOAD_STATE = 0
} }
} }
@Composable
private fun CompanionAsyncThumb(
info: GalleryInfo,
path: UniFile,
modifier: Modifier = Modifier,
) {
var contentScale by remember(info.gid) { mutableStateOf(ContentScale.Fit) }
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
val context = LocalContext.current
var localReq by remember(info.gid) {
path.takeIf { it.isFile }?.uri?.let {
context.imageRequest {
data(it.toString())
memoryCacheKey(info.thumbKey)
}
}.let { mutableStateOf(it) }
}
AsyncImage(
model = localReq ?: requestOf(info),
contentDescription = null,
modifier = modifier,
onState = { state ->
if (state is AsyncImagePainter.State.Success) {
state.result.drawable.run {
if (CropDefaults.shouldCrop(intrinsicWidth, intrinsicHeight)) {
contentScale = ContentScale.Crop
}
}
coroutineScope.launch {
runCatching {
if (!path.exists() && path.ensureFile()) {
val key = info.thumbKey!!
imageCache.read(key) {
UniFile.fromFile(data.toFile())!!.openFileDescriptor("r").use { src ->
path.openFileDescriptor("w").use { dst ->
src sendTo dst
}
}
}
}
}.onFailure {
it.printStackTrace()
}
}
}
if (state is AsyncImagePainter.State.Error) {
coroutineScope.launch {
if (path.exists()) {
path.delete()
localReq = null
}
}
}
},
contentScale = contentScale,
)
}