Workaround for image search (#768)
* Workaround for image search * Cleanup
This commit is contained in:
1 parent
953e216dde
commit
84299b4db7
21 files changed
+44
-142
No files matched your search
@@ -25,6 +25,8 @@ import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.FileUtils
|
||||
import com.hippo.ehviewer.util.StatusCodeException
|
||||
import com.hippo.ehviewer.util.copyTo
|
||||
import com.hippo.unifile.asUniFile
|
||||
import com.hippo.unifile.sha1
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.prepareGet
|
||||
@@ -42,8 +44,6 @@ import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import moe.tarsin.coroutines.runSuspendCatching
|
||||
import okio.BufferedSource
|
||||
import okio.HashingSink.Companion.sha1
|
||||
import okio.blackholeSink
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import splitties.init.appCtx
|
||||
@@ -163,19 +163,8 @@ object EhTagDatabase : CoroutineScope {
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
private fun getFileSha1(file: File): String? {
|
||||
return runCatching {
|
||||
file.source().buffer().use { source ->
|
||||
sha1(blackholeSink()).use {
|
||||
source.readAll(it)
|
||||
it.hash.hex()
|
||||
}
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
private fun checkData(sha1: String?, data: File): Boolean {
|
||||
return sha1 != null && sha1 == getFileSha1(data)
|
||||
return sha1 != null && sha1 == data.asUniFile().sha1()
|
||||
}
|
||||
|
||||
private suspend fun save(client: HttpClient, url: String, file: File) {
|
||||
|
||||
@@ -139,7 +139,7 @@ object EhUrl {
|
||||
fun getTagDefinitionUrl(tag: String) = "https://ehwiki.org/wiki/" + tag.replace(' ', '_')
|
||||
}
|
||||
|
||||
inline fun ehUrl(path: String?, host: String = EhUrl.domain, builder: ParametersBuilder.() -> Unit) = ehUrl(
|
||||
inline fun ehUrl(path: String? = null, host: String = EhUrl.domain, builder: ParametersBuilder.() -> Unit) = ehUrl(
|
||||
path = if (path.isNullOrBlank()) emptyList() else listOf(path),
|
||||
host = host,
|
||||
parameters = Parameters.build(builder),
|
||||
|
||||
@@ -47,8 +47,6 @@ data class ListUrlBuilder(
|
||||
var pageFrom: Int = -1,
|
||||
var pageTo: Int = -1,
|
||||
var imagePath: String? = null,
|
||||
var isUseSimilarityScan: Boolean = false,
|
||||
var isOnlySearchCovers: Boolean = false,
|
||||
) : Parcelable {
|
||||
|
||||
fun setIndex(index: String, isNext: Boolean = true) {
|
||||
@@ -274,7 +272,6 @@ data class ListUrlBuilder(
|
||||
} ?: it
|
||||
}
|
||||
addQueryParameterIfNotBlank("f_search", query)
|
||||
addQueryParameterIfNotBlank("f_shash", hash)
|
||||
addQueryParameterIfNotBlank("prev", mPrev)
|
||||
addQueryParameterIfNotBlank("next", mNext)
|
||||
addQueryParameterIfNotBlank("seek", mJumpTo)
|
||||
@@ -328,7 +325,9 @@ data class ListUrlBuilder(
|
||||
}
|
||||
|
||||
MODE_WHATS_HOT -> EhUrl.popularUrl
|
||||
MODE_IMAGE_SEARCH -> EhUrl.imageSearchUrl
|
||||
MODE_IMAGE_SEARCH -> ehUrl {
|
||||
addQueryParameter("f_shash", requireNotNull(hash))
|
||||
}.buildString()
|
||||
MODE_TOPLIST -> {
|
||||
ehUrl("toplist.php", EhUrl.DOMAIN_E) {
|
||||
addQueryParameter("tl", requireNotNull(mKeyword))
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
*/
|
||||
package com.hippo.ehviewer.image
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.ColorSpace
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import arrow.core.Either
|
||||
@@ -40,7 +38,6 @@ import coil3.request.allowHardware
|
||||
import coil3.request.colorSpace
|
||||
import coil3.size.Precision
|
||||
import coil3.size.Scale
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.jni.isGif
|
||||
import com.hippo.ehviewer.jni.mmap
|
||||
@@ -96,7 +93,6 @@ class Image private constructor(image: CoilImage, private val src: AutoCloseable
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val imageSearchMaxSize = appCtx.resources.getDimensionPixelOffset(R.dimen.image_search_max_size)
|
||||
private val targetWidth = appCtx.resources.displayMetrics.widthPixels * 2
|
||||
private val targetHeight = appCtx.resources.displayMetrics.heightPixels * 2
|
||||
|
||||
@@ -166,20 +162,6 @@ class Image private constructor(image: CoilImage, private val src: AutoCloseable
|
||||
logcat(it)
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
suspend fun Context.decodeBitmap(uri: Uri): Bitmap {
|
||||
val req = imageRequest {
|
||||
memoryCachePolicy(CachePolicy.DISABLED)
|
||||
data(uri)
|
||||
size(imageSearchMaxSize)
|
||||
scale(Scale.FILL)
|
||||
}
|
||||
val image = when (val result = appCtx.imageLoader.execute(req)) {
|
||||
is SuccessResult -> result.image
|
||||
is ErrorResult -> throw result.throwable
|
||||
}
|
||||
return (image as BitmapImage).bitmap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.app.assist.AssistContent
|
||||
import android.content.Intent
|
||||
import android.content.pm.verify.domain.DomainVerificationManager
|
||||
import android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_NONE
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
@@ -104,7 +103,6 @@ import com.hippo.ehviewer.download.DownloadService
|
||||
import com.hippo.ehviewer.download.downloadLocation
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.filled.Subscriptions
|
||||
import com.hippo.ehviewer.image.Image.Companion.decodeBitmap
|
||||
import com.hippo.ehviewer.ui.destinations.DownloadScreenDestination
|
||||
import com.hippo.ehviewer.ui.destinations.DownloadsScreenDestination
|
||||
import com.hippo.ehviewer.ui.destinations.FavouritesScreenDestination
|
||||
@@ -127,20 +125,18 @@ import com.hippo.ehviewer.ui.tools.LocalDialogState
|
||||
import com.hippo.ehviewer.ui.tools.LocalTouchSlopProvider
|
||||
import com.hippo.ehviewer.ui.tools.LocalWindowSizeClass
|
||||
import com.hippo.ehviewer.updater.AppUpdater
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.ExceptionUtils
|
||||
import com.hippo.ehviewer.util.addTextToClipboard
|
||||
import com.hippo.ehviewer.util.getParcelableExtraCompat
|
||||
import com.hippo.ehviewer.util.getUrlFromClipboard
|
||||
import com.hippo.ehviewer.util.isAtLeastQ
|
||||
import com.hippo.ehviewer.util.isAtLeastS
|
||||
import com.hippo.unifile.asUniFile
|
||||
import com.hippo.unifile.sha1
|
||||
import com.ramcosta.composedestinations.DestinationsNavHost
|
||||
import com.ramcosta.composedestinations.rememberNavHostEngine
|
||||
import com.ramcosta.composedestinations.utils.currentDestinationAsState
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -190,18 +186,6 @@ class MainActivity : EhActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveImageToTempFile(uri: Uri): File? {
|
||||
return runSuspendCatching {
|
||||
val bitmap = decodeBitmap(uri)
|
||||
val temp = AppConfig.createTempFile()
|
||||
FileOutputStream(temp).use { bitmap.compress(Bitmap.CompressFormat.JPEG, 90, it) }
|
||||
temp
|
||||
}.getOrElse {
|
||||
logcat(it)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
intentChannel.trySend(intent)
|
||||
@@ -280,13 +264,11 @@ class MainActivity : EhActivity() {
|
||||
} else if (type != null && type.startsWith("image/")) {
|
||||
val uri = intent.getParcelableExtraCompat<Uri>(Intent.EXTRA_STREAM)
|
||||
if (null != uri) {
|
||||
val temp = withIOContext { saveImageToTempFile(uri) }
|
||||
if (null != temp) {
|
||||
withIOContext { uri.asUniFile().sha1() }?.let {
|
||||
navController.navigate(
|
||||
ListUrlBuilder(
|
||||
mode = ListUrlBuilder.MODE_IMAGE_SEARCH,
|
||||
imagePath = temp.path,
|
||||
isUseSimilarityScan = true,
|
||||
hash = it,
|
||||
).asDst(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package com.hippo.ehviewer.ui.main
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ProvideTextStyle
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -19,25 +17,20 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.AsyncImage
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.ui.tools.LabeledCheckbox
|
||||
|
||||
@Composable
|
||||
fun ImageSearch(
|
||||
imagePath: String,
|
||||
image: Uri?,
|
||||
onSelectImage: () -> Unit,
|
||||
uss: Boolean,
|
||||
onUssChecked: (Boolean) -> Unit,
|
||||
osc: Boolean,
|
||||
onOscChecked: (Boolean) -> Unit,
|
||||
) = Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
AnimatedVisibility(visible = imagePath.isNotBlank(), modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
AnimatedVisibility(visible = image != null, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
Card {
|
||||
val maxSize = dimensionResource(id = R.dimen.image_search_max_size)
|
||||
AsyncImage(
|
||||
model = imagePath,
|
||||
model = image,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.sizeIn(maxWidth = maxSize, maxHeight = maxSize),
|
||||
)
|
||||
@@ -49,18 +42,4 @@ fun ImageSearch(
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.select_image))
|
||||
}
|
||||
ProvideTextStyle(MaterialTheme.typography.bodyMedium) {
|
||||
Row {
|
||||
LabeledCheckbox(
|
||||
checked = uss,
|
||||
onCheckedChange = onUssChecked,
|
||||
label = stringResource(id = R.string.search_uss),
|
||||
)
|
||||
LabeledCheckbox(
|
||||
checked = osc,
|
||||
onCheckedChange = onOscChecked,
|
||||
label = stringResource(id = R.string.search_osc),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -593,10 +593,10 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: DestinationsNa
|
||||
icon = Icons.Default.ImageSearch,
|
||||
text = stringResource(id = R.string.search_cover),
|
||||
onClick = {
|
||||
val key = galleryDetail.thumbKey.orEmpty()
|
||||
val key = galleryDetail.thumbKey!!
|
||||
navigator.navigate(
|
||||
ListUrlBuilder(
|
||||
mode = ListUrlBuilder.MODE_NORMAL,
|
||||
mode = ListUrlBuilder.MODE_IMAGE_SEARCH,
|
||||
hash = key.substringAfterLast('/').substringBefore('-'),
|
||||
).asDst(),
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.hippo.ehviewer.ui.screen
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.view.ViewConfiguration
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
@@ -110,7 +109,6 @@ import com.hippo.ehviewer.collectAsState
|
||||
import com.hippo.ehviewer.dao.QuickSearch
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.filled.GoTo
|
||||
import com.hippo.ehviewer.image.Image.Companion.decodeBitmap
|
||||
import com.hippo.ehviewer.ui.LocalSideSheetState
|
||||
import com.hippo.ehviewer.ui.LocalSnackBarHostState
|
||||
import com.hippo.ehviewer.ui.MainActivity
|
||||
@@ -135,17 +133,17 @@ import com.hippo.ehviewer.ui.tools.draggingHapticFeedback
|
||||
import com.hippo.ehviewer.ui.tools.foldToLoadResult
|
||||
import com.hippo.ehviewer.ui.tools.observed
|
||||
import com.hippo.ehviewer.ui.tools.rememberInVM
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.FavouriteStatusRouter
|
||||
import com.hippo.ehviewer.util.findActivity
|
||||
import com.hippo.ehviewer.util.pickVisualMedia
|
||||
import com.hippo.unifile.asUniFile
|
||||
import com.hippo.unifile.sha1
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import com.ramcosta.composedestinations.spec.Direction
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import java.io.File
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.random.Random
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -186,9 +184,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) {
|
||||
var category by rememberSaveable { mutableIntStateOf(Settings.searchCategory) }
|
||||
var searchMethod by rememberSaveable { mutableIntStateOf(1) }
|
||||
var advancedSearchOption by rememberSaveable { mutableStateOf(AdvancedSearchOption()) }
|
||||
var useSimilarityScan by rememberSaveable { mutableStateOf(false) }
|
||||
var searchCoverOnly by rememberSaveable { mutableStateOf(false) }
|
||||
var imagePath by rememberSaveable { mutableStateOf("") }
|
||||
var imageUri by rememberSaveable { mutableStateOf<Uri?>(null) }
|
||||
|
||||
LaunchedEffect(urlBuilder) {
|
||||
if (urlBuilder.mode == MODE_SUBSCRIPTION) searchMethod = 2
|
||||
@@ -261,16 +257,8 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) {
|
||||
}
|
||||
}
|
||||
runSuspendCatching {
|
||||
if (MODE_IMAGE_SEARCH == urlBuilder.mode) {
|
||||
EhEngine.imageSearch(
|
||||
File(urlBuilder.imagePath!!),
|
||||
urlBuilder.isUseSimilarityScan,
|
||||
urlBuilder.isOnlySearchCovers,
|
||||
)
|
||||
} else {
|
||||
val url = urlBuilder.build()
|
||||
EhEngine.getGalleryList(url)
|
||||
}
|
||||
val url = urlBuilder.build()
|
||||
EhEngine.getGalleryList(url)
|
||||
}.foldToLoadResult { result ->
|
||||
urlBuilder.mJumpTo = null
|
||||
LoadResult.Page(result.galleryInfoList, result.prev, result.next)
|
||||
@@ -551,18 +539,12 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) {
|
||||
builder.pageFrom = advancedSearchOption.fromPage
|
||||
builder.pageTo = advancedSearchOption.toPage
|
||||
} else {
|
||||
builder.mode = MODE_IMAGE_SEARCH
|
||||
if (imagePath.isBlank()) {
|
||||
if (imageUri == null) {
|
||||
snackbarState.showSnackbar(selectImageFirst)
|
||||
return@ret
|
||||
}
|
||||
val uri = Uri.parse(imagePath)
|
||||
val temp = AppConfig.createTempFile() ?: return@ret
|
||||
val bitmap = context.decodeBitmap(uri)
|
||||
temp.outputStream().use { bitmap.compress(Bitmap.CompressFormat.JPEG, 90, it) }
|
||||
builder.imagePath = temp.path
|
||||
builder.isUseSimilarityScan = useSimilarityScan
|
||||
builder.isOnlySearchCovers = searchCoverOnly
|
||||
builder.mode = MODE_IMAGE_SEARCH
|
||||
builder.hash = imageUri!!.asUniFile().sha1() ?: return@ret
|
||||
}
|
||||
when (oldMode) {
|
||||
MODE_TOPLIST, MODE_WHATS_HOT -> {
|
||||
@@ -648,17 +630,12 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) {
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
)
|
||||
ImageSearch(
|
||||
imagePath = imagePath,
|
||||
image = imageUri,
|
||||
onSelectImage = {
|
||||
coroutineScope.launch {
|
||||
val image = context.pickVisualMedia(ActivityResultContracts.PickVisualMedia.ImageOnly)
|
||||
if (image != null) imagePath = image.toString()
|
||||
imageUri = context.pickVisualMedia(ActivityResultContracts.PickVisualMedia.ImageOnly)
|
||||
}
|
||||
},
|
||||
uss = useSimilarityScan,
|
||||
onUssChecked = { useSimilarityScan = it },
|
||||
osc = searchCoverOnly,
|
||||
onOscChecked = { searchCoverOnly = it },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,15 @@ import android.os.Environment
|
||||
import android.os.ParcelFileDescriptor.AutoCloseInputStream
|
||||
import android.os.ParcelFileDescriptor.AutoCloseOutputStream
|
||||
import android.provider.DocumentsContract
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import okio.HashingSink
|
||||
import okio.Path
|
||||
import okio.blackholeSink
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
|
||||
/**
|
||||
* Use Native IO/NIO directly if possible, unless you need process file content on JVM!
|
||||
@@ -24,6 +29,18 @@ fun UniFile.openOutputStream(): FileOutputStream {
|
||||
return AutoCloseOutputStream(openFileDescriptor("w"))
|
||||
}
|
||||
|
||||
fun UniFile.sha1() = runCatching {
|
||||
openInputStream().source().buffer().use { source ->
|
||||
HashingSink.sha1(blackholeSink()).use {
|
||||
source.readAll(it)
|
||||
it.hash.hex()
|
||||
}
|
||||
}
|
||||
}.getOrElse {
|
||||
logcat(it)
|
||||
null
|
||||
}
|
||||
|
||||
fun File.asUniFile() = UniFile.fromFile(this)
|
||||
|
||||
fun Path.asUniFile() = toFile().asUniFile()
|
||||
|
||||
@@ -65,8 +65,6 @@
|
||||
<string name="search_sfu">Uploader</string>
|
||||
<string name="search_sft">Etikett</string>
|
||||
<string name="select_image">Bild wählen</string>
|
||||
<string name="search_uss">Ähnlichkeitscan aktivieren</string>
|
||||
<string name="search_osc">Nur nach Umschläge suchen</string>
|
||||
<string name="select_image_first">Wähle ein Bild</string>
|
||||
<string name="add_to_favourites">Zu den Favoriten hinzufügen</string>
|
||||
<string name="remove_from_favourites">Aus den Favoriten entfernen</string>
|
||||
|
||||
@@ -76,8 +76,6 @@
|
||||
<string name="search_sto">Mostrar solo galerías con torrents</string>
|
||||
<string name="search_sr">Valoración mínima:</string>
|
||||
<string name="select_image">Seleccionar imagen</string>
|
||||
<string name="search_uss">Usar búsqueda similar</string>
|
||||
<string name="search_osc">Buscar solo portadas</string>
|
||||
<string name="select_image_first">Seleccione la imagen primero</string>
|
||||
<string name="search_sp_to">hasta</string>
|
||||
<string name="search_sf">Deshabilitar filtros para:</string>
|
||||
|
||||
@@ -86,8 +86,6 @@
|
||||
<string name="search_sft">Tag</string>
|
||||
|
||||
<string name="select_image">Sélectionner une image</string>
|
||||
<string name="search_uss">Activer le scannage de similarité</string>
|
||||
<string name="search_osc">Chercher seulement les couverture</string>
|
||||
<string name="select_image_first">Sélectionnez une image</string>
|
||||
|
||||
<string name="add_to_favourites">Ajouter à favori</string>
|
||||
|
||||
@@ -85,8 +85,6 @@
|
||||
<string name="search_sft">タグ</string>
|
||||
|
||||
<string name="select_image">画像を選択</string>
|
||||
<string name="search_uss">類似検索を有効化</string>
|
||||
<string name="search_osc">カバーのみを検索</string>
|
||||
<string name="select_image_first">画像を選択してください</string>
|
||||
|
||||
<string name="add_to_favourites">お気に入りに追加</string>
|
||||
|
||||
@@ -82,8 +82,6 @@
|
||||
<string name="search_sr">최소 평점:</string>
|
||||
|
||||
<string name="select_image">이미지 선택</string>
|
||||
<string name="search_uss">유사한 이미지 검색</string>
|
||||
<string name="search_osc">커버만 검색</string>
|
||||
<string name="select_image_first">먼저 이미지를 선택해 주세요.</string>
|
||||
|
||||
<string name="add_to_favourites">즐겨찾기에 추가</string>
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
<string name="star_4">4 stjerner</string>
|
||||
<string name="no_torrents">Ingen torrenter</string>
|
||||
<string name="search_sfl">Språk</string>
|
||||
<string name="search_osc">Kun søk i omslag</string>
|
||||
<string name="guest_mode">Fortsett uten å logge inn</string>
|
||||
<string name="favored_times">♥ %d</string>
|
||||
<string name="torrent_count">Torrent (%d)</string>
|
||||
|
||||
@@ -82,8 +82,6 @@
|
||||
<string name="search_sr">เรตติ้งขั้นต่ำ:</string>
|
||||
|
||||
<string name="select_image">เลือกรูปภาพ</string>
|
||||
<string name="search_uss">ใช้สแกนหาความเหมือน</string>
|
||||
<string name="search_osc">ค้นหาเฉพาะหน้าปก</string>
|
||||
<string name="select_image_first">โปรดเลือกรูปภาพก่อน</string>
|
||||
|
||||
<string name="add_to_favourites">เพิ่มเข้าในรายการโปรด</string>
|
||||
|
||||
@@ -52,8 +52,6 @@
|
||||
<string name="search_sfu">Yükleyen</string>
|
||||
<string name="search_sft">Etiketler</string>
|
||||
<string name="select_image">Görsel Seç</string>
|
||||
<string name="search_uss">Benzerlik taramasını kullan</string>
|
||||
<string name="search_osc">Yalnızca kapak ara</string>
|
||||
<string name="select_image_first">Lütfen önce görsel seç</string>
|
||||
<string name="add_to_favourites">Favorilere ekle</string>
|
||||
<string name="remove_from_favourites">Favorilerden kaldır</string>
|
||||
|
||||
@@ -78,8 +78,6 @@
|
||||
<string name="search_sfu">上传者</string>
|
||||
<string name="search_sft">标签</string>
|
||||
<string name="select_image">选择图片</string>
|
||||
<string name="search_uss">使用相似搜索</string>
|
||||
<string name="search_osc">只搜索封面</string>
|
||||
<string name="select_image_first">请先选择图片</string>
|
||||
<string name="add_to_favourites">收藏</string>
|
||||
<string name="remove_from_favourites">移除收藏</string>
|
||||
|
||||
@@ -90,8 +90,6 @@
|
||||
<string name="search_sft">標籤</string>
|
||||
|
||||
<string name="select_image">選擇圖片</string>
|
||||
<string name="search_uss">使用相似搜索</string>
|
||||
<string name="search_osc">只搜索封面</string>
|
||||
<string name="select_image_first">請先選擇圖片</string>
|
||||
|
||||
<string name="add_to_favourites">收藏</string>
|
||||
|
||||
@@ -78,8 +78,6 @@
|
||||
<string name="search_sfu">上傳者</string>
|
||||
<string name="search_sft">標籤</string>
|
||||
<string name="select_image">選擇圖片</string>
|
||||
<string name="search_uss">使用相似性搜尋</string>
|
||||
<string name="search_osc">只搜尋封面</string>
|
||||
<string name="select_image_first">請先選擇圖片</string>
|
||||
<string name="add_to_favourites">收藏</string>
|
||||
<string name="remove_from_favourites">移除收藏</string>
|
||||
|
||||
@@ -118,8 +118,6 @@
|
||||
<string name="search_sfu">Uploader</string>
|
||||
<string name="search_sft">Tags</string>
|
||||
<string name="select_image">Select image</string>
|
||||
<string name="search_uss">Use similarity scan</string>
|
||||
<string name="search_osc">Only search covers</string>
|
||||
<string name="select_image_first">Please select image first</string>
|
||||
<string name="add_to_favourites">Add to favourites</string>
|
||||
<string name="remove_from_favourites">Remove from favourites</string>
|
||||
|
||||
Reference in new issue
Block a user