OpenWithIDDialog
This commit is contained in:
tom5079
2021-12-17 20:39:30 +09:00
parent 62d0de3ef6
commit e7debfec46
19 changed files with 677 additions and 266 deletions

View File

@@ -12,6 +12,6 @@
</deviceKey> </deviceKey>
</Target> </Target>
</runningDeviceTargetSelectedWithDropDown> </runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2021-12-16T03:48:05.512086Z" /> <timeTargetWasSelectedWithDropDown value="2021-12-17T11:08:36.835795Z" />
</component> </component>
</project> </project>

View File

@@ -131,7 +131,7 @@ dependencies {
implementation("xyz.quaver:libpupil:2.1.11") implementation("xyz.quaver:libpupil:2.1.11")
implementation("xyz.quaver:documentfilex:0.7.1") implementation("xyz.quaver:documentfilex:0.7.1")
implementation("xyz.quaver:subsampledimage:0.0.1-alpha10-SNAPSHOT") implementation("xyz.quaver:subsampledimage:0.0.1-alpha11-SNAPSHOT")
implementation("org.kodein.log:kodein-log:0.11.1") implementation("org.kodein.log:kodein-log:0.11.1")
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.7") debugImplementation("com.squareup.leakcanary:leakcanary-android:2.7")

View File

@@ -43,7 +43,6 @@ data class SearchResultEvent(val type: Type, val itemID: String, val payload: Pa
abstract class Source { abstract class Source {
abstract val name: String abstract val name: String
abstract val iconResID: Int abstract val iconResID: Int
abstract val preferenceID: Int
abstract val availableSortMode: List<String> abstract val availableSortMode: List<String>
abstract suspend fun search(query: String, range: IntRange, sortMode: Int): Pair<Channel<ItemInfo>, Int> abstract suspend fun search(query: String, range: IntRange, sortMode: Int): Pair<Channel<ItemInfo>, Int>

View File

@@ -36,8 +36,6 @@ class History(override val di: DI) : Source(), DIAware {
get() = "history" get() = "history"
override val iconResID: Int override val iconResID: Int
get() = 0 //TODO get() = 0 //TODO
override val preferenceID: Int
get() = 0 //TODO
override val availableSortMode: List<String> = emptyList() override val availableSortMode: List<String> = emptyList()
private val history = direct.database().historyDao() private val history = direct.database().historyDao()

View File

@@ -122,7 +122,6 @@ class Hitomi(app: Application) : Source(), DIAware {
override val name: String = "hitomi.la" override val name: String = "hitomi.la"
override val iconResID: Int = R.drawable.hitomi override val iconResID: Int = R.drawable.hitomi
override val preferenceID: Int = R.xml.hitomi_preferences
override val availableSortMode: List<String> = app.resources.getStringArray(R.array.hitomi_sort_mode).toList() override val availableSortMode: List<String> = app.resources.getStringArray(R.array.hitomi_sort_mode).toList()
var cachedQuery: String? = null var cachedQuery: String? = null

View File

@@ -153,7 +153,6 @@ class Hiyobi_io(app: Application): Source(), DIAware {
override val name = "hiyobi.io" override val name = "hiyobi.io"
override val iconResID = R.drawable.hitomi override val iconResID = R.drawable.hitomi
override val preferenceID = 0
override val availableSortMode = emptyList<String>() override val availableSortMode = emptyList<String>()
private val client: HttpClient by instance() private val client: HttpClient by instance()

View File

@@ -1,111 +0,0 @@
/*
* Pupil, Hitomi.la viewer for Android
* Copyright (C) 2019 tom5079
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package xyz.quaver.pupil.types
import kotlinx.serialization.Serializable
@Serializable
data class Tag(val area: String?, val tag: String, val isNegative: Boolean = false) {
companion object {
fun parse(tag: String) : Tag {
if (tag.firstOrNull() == '-') {
tag.substring(1).split(Regex(":"), 2).let {
return when(it.size) {
2 -> Tag(it[0], it[1], true)
else -> Tag(null, tag, true)
}
}
}
tag.split(Regex(":"), 2).let {
return when(it.size) {
2 -> Tag(it[0], it[1])
else -> Tag(null, tag)
}
}
}
}
override fun toString(): String {
return (if (isNegative) "-" else "") + when(area) {
null -> tag
else -> "$area:$tag"
}
}
fun toQuery(): String {
return toString().replace(' ', '_')
}
override fun equals(other: Any?): Boolean {
if (other !is Tag)
return false
if (other.area == area && other.tag == tag)
return true
return false
}
override fun hashCode() = toString().hashCode()
}
class Tags(val tags: MutableSet<Tag> = mutableSetOf()) : MutableSet<Tag> by tags {
companion object {
fun parse(tags: String) : Tags {
return Tags(
tags.split(' ').mapNotNull {
if (it.isNotEmpty())
Tag.parse(it)
else
null
}.toMutableSet()
)
}
}
fun contains(element: String): Boolean {
tags.forEach {
if (it.toString() == element)
return true
}
return false
}
fun add(element: String): Boolean {
return tags.add(Tag.parse(element))
}
fun remove(element: String) {
tags.filter { it.toString() == element }.forEach {
tags.remove(it)
}
}
fun removeByArea(area: String, isNegative: Boolean? = null) {
tags.filter { it.area == area && (if(isNegative == null) true else (it.isNegative == isNegative)) }.forEach {
tags.remove(it)
}
}
override fun toString(): String {
return tags.joinToString(" ") { it.toString() }
}
}

View File

@@ -58,7 +58,6 @@ import org.kodein.log.newLogger
import xyz.quaver.pupil.* import xyz.quaver.pupil.*
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.sources.SearchResultEvent import xyz.quaver.pupil.sources.SearchResultEvent
import xyz.quaver.pupil.types.*
import xyz.quaver.pupil.ui.composable.FloatingActionButtonState import xyz.quaver.pupil.ui.composable.FloatingActionButtonState
import xyz.quaver.pupil.ui.composable.FloatingSearchBar import xyz.quaver.pupil.ui.composable.FloatingSearchBar
import xyz.quaver.pupil.ui.composable.MultipleFloatingActionButton import xyz.quaver.pupil.ui.composable.MultipleFloatingActionButton
@@ -66,6 +65,7 @@ import xyz.quaver.pupil.ui.composable.SubFabItem
import xyz.quaver.pupil.ui.dialog.SourceSelectDialog import xyz.quaver.pupil.ui.dialog.SourceSelectDialog
import xyz.quaver.pupil.ui.theme.PupilTheme import xyz.quaver.pupil.ui.theme.PupilTheme
import xyz.quaver.pupil.ui.composable.ProgressCard import xyz.quaver.pupil.ui.composable.ProgressCard
import xyz.quaver.pupil.ui.dialog.OpenWithItemIDDialog
import xyz.quaver.pupil.ui.viewmodel.MainViewModel import xyz.quaver.pupil.ui.viewmodel.MainViewModel
import xyz.quaver.pupil.util.* import xyz.quaver.pupil.util.*
import kotlin.math.* import kotlin.math.*
@@ -108,21 +108,51 @@ class MainActivity : ComponentActivity(), DIAware {
} }
} }
var openSourceSelectDialog by remember { mutableStateOf(false) } val onSearchResultEvent: (SearchResultEvent) -> Unit = { event ->
when (event.type) {
SearchResultEvent.Type.OPEN_READER -> {
startActivity(
Intent(
this@MainActivity,
ReaderActivity::class.java
).apply {
putExtra("source", model.source.name)
putExtra("id", event.itemID)
putExtra("payload", event.payload)
})
}
else -> TODO("")
}
}
var sourceSelectDialog by remember { mutableStateOf(false) }
var openWithItemIDDialog by remember { mutableStateOf(false) }
LaunchedEffect(navigationIconProgress) { LaunchedEffect(navigationIconProgress) {
navigationIcon.progress = navigationIconProgress navigationIcon.progress = navigationIconProgress
} }
if (openSourceSelectDialog) if (sourceSelectDialog)
SourceSelectDialog( SourceSelectDialog(
currentSource = model.source.name, currentSource = model.source.name,
onDismissRequest = { openSourceSelectDialog = false } onDismissRequest = { sourceSelectDialog = false }
) { source -> ) { source ->
openSourceSelectDialog = false sourceSelectDialog = false
model.setSourceAndReset(source.name) model.setSourceAndReset(source.name)
} }
if (openWithItemIDDialog)
OpenWithItemIDDialog {
openWithItemIDDialog = false
it?.let {
onSearchResultEvent(SearchResultEvent(
SearchResultEvent.Type.OPEN_READER,
it
))
}
}
Scaffold( Scaffold(
floatingActionButton = { floatingActionButton = {
MultipleFloatingActionButton( MultipleFloatingActionButton(
@@ -142,7 +172,9 @@ class MainActivity : ComponentActivity(), DIAware {
SubFabItem( SubFabItem(
painterResource(R.drawable.numeric), painterResource(R.drawable.numeric),
stringResource(R.string.main_open_gallery_by_id) stringResource(R.string.main_open_gallery_by_id)
), ) {
openWithItemIDDialog = true
}
), ),
visible = isFabVisible, visible = isFabVisible,
targetState = isFabExpanded, targetState = isFabExpanded,
@@ -178,22 +210,7 @@ class MainActivity : ComponentActivity(), DIAware {
ProgressCard( ProgressCard(
progress = 0.5f progress = 0.5f
) { ) {
model.source.SearchResult(itemInfo = itemInfo) { event -> model.source.SearchResult(itemInfo = itemInfo, onEvent = onSearchResultEvent)
when (event.type) {
SearchResultEvent.Type.OPEN_READER -> {
startActivity(
Intent(
this@MainActivity,
ReaderActivity::class.java
).apply {
putExtra("source", model.source.name)
putExtra("id", event.itemID)
putExtra("payload", event.payload)
})
}
else -> TODO("")
}
}
} }
} }
} }
@@ -224,7 +241,7 @@ class MainActivity : ComponentActivity(), DIAware {
painterResource(model.source.iconResID), painterResource(model.source.iconResID),
contentDescription = null, contentDescription = null,
modifier = Modifier.size(24.dp).clickable { modifier = Modifier.size(24.dp).clickable {
openSourceSelectDialog = true sourceSelectDialog = true
} }
) )
Icon( Icon(

View File

@@ -19,12 +19,16 @@
package xyz.quaver.pupil.ui package xyz.quaver.pupil.ui
import android.content.Intent import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
@@ -33,21 +37,18 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BrokenImage import androidx.compose.material.icons.filled.BrokenImage
import androidx.compose.material.icons.filled.Fullscreen import androidx.compose.material.icons.filled.Fullscreen
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.res.colorResource import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import coil.annotation.ExperimentalCoilApi import coil.annotation.ExperimentalCoilApi
import com.google.accompanist.appcompattheme.AppCompatTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
@@ -71,7 +72,7 @@ class ReaderActivity : ComponentActivity(), DIAware {
private val logger = newLogger(LoggerFactory.default) private val logger = newLogger(LoggerFactory.default)
@OptIn(ExperimentalCoilApi::class) @OptIn(ExperimentalCoilApi::class, ExperimentalFoundationApi::class)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -80,24 +81,20 @@ class ReaderActivity : ComponentActivity(), DIAware {
setContent { setContent {
var isFABExpanded by remember { mutableStateOf(FloatingActionButtonState.COLLAPSED) } var isFABExpanded by remember { mutableStateOf(FloatingActionButtonState.COLLAPSED) }
val isFullscreen by model.isFullscreen.observeAsState(false)
val imageSources = remember { mutableStateListOf<ImageSource?>() } val imageSources = remember { mutableStateListOf<ImageSource?>() }
val imageHeights = remember { mutableStateListOf<Float?>() }
val states = remember { mutableStateListOf<SubSampledImageState>() } val states = remember { mutableStateListOf<SubSampledImageState>() }
val scaffoldState = rememberScaffoldState()
val snackbarCoroutineScope = rememberCoroutineScope()
LaunchedEffect(model.imageList.count { it != null }) { LaunchedEffect(model.imageList.count { it != null }) {
if (imageSources.isEmpty() && model.imageList.isNotEmpty()) if (imageSources.isEmpty() && model.imageList.isNotEmpty())
imageSources.addAll(List(model.imageList.size) { null }) imageSources.addAll(List(model.imageList.size) { null })
if (states.isEmpty() && model.imageList.isNotEmpty()) if (states.isEmpty() && model.imageList.isNotEmpty())
states.addAll(List(model.imageList.size) { SubSampledImageState(ScaleTypes.FIT_WIDTH, Bounds.FORCE_OVERLAP_OR_CENTER) }) states.addAll(List(model.imageList.size) { SubSampledImageState(ScaleTypes.FIT_WIDTH, Bounds.FORCE_OVERLAP_OR_CENTER).apply {
isGestureEnabled = true
if (imageHeights.isEmpty() && model.imageList.isNotEmpty()) } })
imageHeights.addAll(List(model.imageList.size) { null })
logger.info {
"${model.imageList.count { it == null }} nulls"
}
model.imageList.forEachIndexed { i, image -> model.imageList.forEachIndexed { i, image ->
if (imageSources[i] == null && image != null) if (imageSources[i] == null && image != null)
@@ -108,24 +105,27 @@ class ReaderActivity : ComponentActivity(), DIAware {
model.error(i) model.error(i)
}.getOrNull() }.getOrNull()
} }
logger.info {
"${imageSources.count { it == null }} nulls"
}
} }
WindowInsetsControllerCompat(window, window.decorView).run { WindowInsetsControllerCompat(window, window.decorView).run {
if (isFullscreen) { if (model.isFullscreen) {
hide(WindowInsetsCompat.Type.systemBars()) hide(WindowInsetsCompat.Type.systemBars())
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} else } else
show(WindowInsetsCompat.Type.systemBars()) show(WindowInsetsCompat.Type.systemBars())
} }
if (model.error)
stringResource(R.string.reader_failed_to_find_gallery).let {
snackbarCoroutineScope.launch {
scaffoldState.snackbarHostState.showSnackbar(it, duration = SnackbarDuration.Indefinite)
}
}
PupilTheme { PupilTheme {
Scaffold( Scaffold(
topBar = { topBar = {
if (!isFullscreen) if (!model.isFullscreen)
TopAppBar( TopAppBar(
title = { title = {
Text( Text(
@@ -145,14 +145,14 @@ class ReaderActivity : ComponentActivity(), DIAware {
) )
}, },
floatingActionButton = { floatingActionButton = {
if (!isFullscreen) if (!model.isFullscreen)
MultipleFloatingActionButton( MultipleFloatingActionButton(
items = listOf( items = listOf(
SubFabItem( SubFabItem(
icon = Icons.Default.Fullscreen, icon = Icons.Default.Fullscreen,
label = stringResource(id = R.string.reader_fab_fullscreen) label = stringResource(id = R.string.reader_fab_fullscreen)
) { ) {
model.isFullscreen.postValue(true) model.isFullscreen = true
} }
), ),
targetState = isFABExpanded, targetState = isFABExpanded,
@@ -160,61 +160,76 @@ class ReaderActivity : ComponentActivity(), DIAware {
isFABExpanded = it isFABExpanded = it
} }
) )
} },
scaffoldState = scaffoldState,
snackbarHost = { scaffoldState.snackbarHostState }
) { ) {
LazyColumn( Box {
Modifier.fillMaxSize(), LazyColumn(
verticalArrangement = Arrangement.spacedBy(4.dp) Modifier.fillMaxSize(),
) { verticalArrangement = Arrangement.spacedBy(4.dp)
itemsIndexed(imageSources) { i, imageSource -> ) {
LaunchedEffect(states[i].canvasSize, states[i].imageSize) { itemsIndexed(imageSources) { i, imageSource ->
if (imageHeights.isNotEmpty() && imageHeights[i] == null) Box(
states[i].canvasSize?.let { canvasSize -> Modifier
states[i].imageSize?.let { imageSize -> .wrapContentHeight(states[i], 500.dp)
imageHeights[i] = imageSize.height * canvasSize.width / imageSize.width .fillMaxWidth()
} } .border(1.dp, Color.Gray),
} contentAlignment = Alignment.Center
) {
if (imageSource == null)
model.progressList.getOrNull(i)?.let { progress ->
if (progress < 0f)
Icon(Icons.Filled.BrokenImage, null)
else
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
LinearProgressIndicator(progress)
Text((i + 1).toString())
}
}
else {
val haptic = LocalHapticFeedback.current
Box( SubSampledImage(
Modifier modifier = Modifier
.height( .fillMaxSize()
imageHeights .run {
.getOrNull(i) if (model.isFullscreen)
?.let { with(LocalDensity.current) { it.toDp() } } doubleClickCycleZoom(states[i], 2f)
?: 500.dp) else
.fillMaxWidth() combinedClickable(
.border(1.dp, Color.Gray), onLongClick = {
contentAlignment = Alignment.Center haptic.performHapticFeedback(HapticFeedbackType.LongPress)
) { }
if (imageSource == null) ) {
model.progressList.getOrNull(i)?.let { progress -> model.isFullscreen = true
if (progress < 0f) }
Icon(Icons.Filled.BrokenImage, null) },
else imageSource = imageSource,
Column( state = states[i]
horizontalAlignment = Alignment.CenterHorizontally )
) {
LinearProgressIndicator(progress)
Text((i + 1).toString())
}
} }
else {
SubSampledImage(
modifier = Modifier.fillMaxSize(),
imageSource = imageSource,
state = states[i]
)
} }
} }
} }
}
if (model.totalProgress != model.imageCount) if (model.totalProgress != model.imageCount)
LinearProgressIndicator( LinearProgressIndicator(
modifier = Modifier.fillMaxWidth(), modifier = Modifier
progress = model.progressList.map { abs(it) }.sum() / model.progressList.size, .fillMaxWidth()
color = colorResource(id = R.color.colorAccent) .align(Alignment.TopCenter),
progress = model.progressList.map { abs(it) }
.sum() / model.progressList.size,
color = MaterialTheme.colors.secondary
)
SnackbarHost(
scaffoldState.snackbarHostState,
modifier = Modifier.align(Alignment.BottomCenter)
) )
}
} }
} }
} }
@@ -227,7 +242,7 @@ class ReaderActivity : ComponentActivity(), DIAware {
override fun onBackPressed() { override fun onBackPressed() {
when { when {
model.isFullscreen.value == true -> model.isFullscreen.postValue(false) model.isFullscreen -> model.isFullscreen = false
else -> super.onBackPressed() else -> super.onBackPressed()
} }
} }

View File

@@ -0,0 +1,74 @@
/*
* Pupil, Hitomi.la viewer for Android
* Copyright (C) 2021 tom5079
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package xyz.quaver.pupil.ui.dialog
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import xyz.quaver.pupil.R
@Composable
fun OpenWithItemIDDialog(onDismissRequest: (String?) -> Unit = { }) {
var itemID by remember { mutableStateOf("") }
Dialog(onDismissRequest = { onDismissRequest(null) }) {
Card(
elevation = 8.dp,
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
stringResource(R.string.main_open_gallery_by_id),
style = MaterialTheme.typography.h6
)
TextField(
modifier = Modifier.fillMaxWidth(),
value = itemID,
onValueChange = {
itemID = it
},
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Go),
keyboardActions = KeyboardActions(
onGo = { onDismissRequest(itemID) }
)
)
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { onDismissRequest(itemID) }
) {
Text(stringResource(android.R.string.ok))
}
}
}
}
}

View File

@@ -26,6 +26,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
private val DarkColorPalette = darkColors( private val DarkColorPalette = darkColors(
primary = LightBlue300,
primaryVariant = LightBlue700,
secondary = Pink600, secondary = Pink600,
onSecondary = Color.White onSecondary = Color.White
) )

View File

@@ -53,13 +53,16 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
private val logger = newLogger(LoggerFactory.default) private val logger = newLogger(LoggerFactory.default)
val isFullscreen = MutableLiveData(false) var isFullscreen by mutableStateOf(false)
private val database: AppDatabase by instance() private val database: AppDatabase by instance()
private val historyDao = database.historyDao() private val historyDao = database.historyDao()
private val bookmarkDao = database.bookmarkDao() private val bookmarkDao = database.bookmarkDao()
var error by mutableStateOf(false)
private set
var source by mutableStateOf<Source?>(null) var source by mutableStateOf<Source?>(null)
private set private set
var itemID by mutableStateOf<String?>(null) var itemID by mutableStateOf<String?>(null)
@@ -121,14 +124,20 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
viewModelScope.launch { viewModelScope.launch {
if (title == null) if (title == null)
title = withContext(Dispatchers.IO) { title = withContext(Dispatchers.IO) {
source.info(itemID) kotlin.runCatching {
}.title source.info(itemID)
}.getOrNull()
}?.title
} }
viewModelScope.launch { viewModelScope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
source.images(itemID) kotlin.runCatching {
}.let { images -> source.images(itemID)
}.onFailure {
error = true
}.getOrNull()
}?.let { images ->
this@ReaderViewModel.images = images this@ReaderViewModel.images = images
imageCount = images.size imageCount = images.size

View File

@@ -149,7 +149,7 @@ fun View.show() {
visibility = View.VISIBLE visibility = View.VISIBLE
} }
class FileXImageSource(file: FileX): ImageSource { class FileXImageSource(val file: FileX): ImageSource {
private val decoder = newBitmapRegionDecoder(file.inputStream()!!) private val decoder = newBitmapRegionDecoder(file.inputStream()!!)
override val imageSize by lazy { Size(decoder.width.toFloat(), decoder.height.toFloat()) } override val imageSize by lazy { Size(decoder.width.toFloat(), decoder.height.toFloat()) }

View File

@@ -150,7 +150,7 @@ fun checkUpdate(context: Context, force: Boolean = false) {
Preferences["update_download_id"] = it Preferences["update_download_id"] = it
} }
} }
setNegativeButton(if (force) android.R.string.cancel else R.string.ignore_update) { _, _ -> setNegativeButton(if (force) android.R.string.cancel else R.string.ignore) { _, _ ->
if (!force) if (!force)
preferences.edit() preferences.edit()
.putLong("ignore_update_until", System.currentTimeMillis() + 604800000) .putLong("ignore_update_until", System.currentTimeMillis() + 604800000)

View File

@@ -1,4 +0,0 @@
<!--drawable/swap_horizontal.xml-->
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="?attr/colorControlNormal" android:pathData="M21 9l-4-4v3h-7v2h7v3M7 11l-4 4 4 4v-3h7v-2H7v-3z"/>
</vector>

View File

@@ -3,25 +3,158 @@
<string name="galleryblock_language">言語: %1$s</string> <string name="galleryblock_language">言語: %1$s</string>
<string name="galleryblock_series">シリーズ: %1$s</string> <string name="galleryblock_series">シリーズ: %1$s</string>
<string name="galleryblock_type">タイプ: %1$s</string> <string name="galleryblock_type">タイプ: %1$s</string>
<string name="search_hint">ギャラリー検索</string> <string name="main_no_result">結果なし</string>
<string name="search_hint">検索…</string>
<string name="settings_clear_cache">キャッシュクリア</string>
<string name="settings_clear_cache_alert_message">キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?</string>
<string name="settings_storage_usage">%s使用中</string>
<string name="settings_storage_usage_loading">ストレージ使用量読み込み中…</string>
<string name="settings_default_query">デフォルトキーワード</string> <string name="settings_default_query">デフォルトキーワード</string>
<string name="settings_galleries_per_page">一回にロードするギャラリー数</string>
<string name="settings_search_title">検索設定</string>
<string name="settings_title">設定</string>
<string name="update_notification_description">アップデートダウンロード中</string> <string name="update_notification_description">アップデートダウンロード中</string>
<string name="update_title">新しいアップデートがあります</string> <string name="update_title">新しいアップデートがあります</string>
<string name="warning">注意</string>
<string name="settings_miscellaneous_title">その他</string>
<string name="settings_mirror_title">ミラーサーバー</string>
<string name="settings_clear_history">履歴を削除</string>
<string name="settings_clear_history_alert_message">履歴を削除しますか?</string>
<string name="settings_clear_history_summary">履歴数: %1$d</string>
<string name="main_drawer_history">履歴</string>
<string name="main_drawer_home">トップ</string>
<string name="update_release_note"># リリースノート(v%1$s)\n%2$s</string> <string name="update_release_note"># リリースノート(v%1$s)\n%2$s</string>
<string name="settings_security_mode_title">セキュリティーモード</string>
<string name="settings_security_mode_summary">アプリ履歴でアプリの画面を表示しない</string>
<string name="reader_go_to_page">移動</string>
<string name="default_query_dialog_language_selector_none">非選択</string>
<string name="default_query_dialog_filter_BL">BLフィルター</string>
<string name="default_query_dialog_filter_guro">グロフィルター</string>
<string name="default_query_dialog_language">"言語: "</string>
<string name="default_query_dialog_title">デフォルトキーワード設定</string>
<string name="main_drawer_group_contact_title">お問い合わせ先</string>
<string name="main_drawer_group_contact_homepage">ホームページ</string>
<string name="main_drawer_group_contact_help">ヘルプ</string>
<string name="main_drawer_group_contact_github">Github</string>
<string name="main_drawer_group_contact_email">メールを送る</string>
<string name="reader_fab_fullscreen">フルスクリーン</string> <string name="reader_fab_fullscreen">フルスクリーン</string>
<string name="channel_download">ダウンロード</string> <string name="channel_download">ダウンロード</string>
<string name="channel_download_description">ダウンロードの進行を通知</string> <string name="channel_download_description">ダウンロードの進行を通知</string>
<string name="reader_fab_download">バックグラウンドダウンロード</string>
<string name="reader_notification_text">ダウンロード中…</string>
<string name="reader_notification_complete">ダウンロード完了</string>
<string name="reader_fab_download_cancel">バックグラウンドダウンロード中止</string>
<string name="main_drawer_downloads">ダウンロード</string>
<string name="main_jump_title">ページ移動</string> <string name="main_jump_title">ページ移動</string>
<string name="main_jump_message">現ページ番号: %1$d\nページ数: %2$d</string>
<string name="unable_to_connect">hitomi.laに接続できません</string>
<string name="main_move_to_page">%1$dページへ移動</string>
<string name="settings_clear_downloads">ダウンロード削除</string>
<string name="settings_clear_downloads_alert_message">ダウンロードしたギャラリーを全て削除します。\n実行しますか</string>
<string name="settings_mirror_summary">ミラーサーバからイメージをロード</string>
<string name="main_drawer_favorite">ブックマーク</string>
<string name="main_open_gallery_by_id">ギャラリー番号で見る</string> <string name="main_open_gallery_by_id">ギャラリー番号で見る</string>
<string name="reader_failed_to_find_gallery">エラーが発生しました</string>
<string name="settings_storage">ストレージ</string>
<string name="main_drawer_grouop_contact_discord">ディスコード</string>
<string name="settings_app_lock">アプリロック</string>
<string name="settings_app_lock_type">アップロックの種類</string>
<string name="settings_app_version_title">バージョン(アップデート確認)</string>
<string name="settings_lock_biometrics">生体認識</string>
<string name="settings_lock_confirm">ロック確認のためもう一回入力してください。</string>
<string name="settings_lock_enabled">有効</string>
<string name="settings_lock_fingerprint">指紋</string>
<string name="settings_lock_password">パスワード</string>
<string name="settings_lock_pattern">パターン</string>
<string name="settings_lock_wrong_confirm">ロックが一致しません。やり直してください。</string>
<string name="settings_lock_none">なし</string>
<string name="settings_lock_remove_message">ロックを無効にしますか?</string>
<string name="reader_loading">ロード中</string> <string name="reader_loading">ロード中</string>
<string name="ignore_update">無視</string> <string name="main_menu_sort">ソート</string>
<string name="main_menu_sort_newest">投稿日時順</string>
<string name="main_menu_sort_popular">人気順</string>
<string name="ignore">無視</string>
<string name="lock_corrupted">ロックファイルが破損されています。Pupilを再再インストールしてください。</string>
<string name="settings_dark_mode_title">ダークモード</string>
<string name="settings_dark_mode_summary">夜にシコりたい方々へ</string>
<string name="gallery_details">ギャラリー情報</string>
<string name="gallery_artists">アーティスト</string>
<string name="gallery_characters">キャラクター</string>
<string name="gallery_groups">グループ</string>
<string name="gallery_language">言語</string>
<string name="gallery_series">シリーズ</string>
<string name="gallery_tags">タグ</string>
<string name="gallery_thumbnails">サムネイル</string>
<string name="gallery_related">おすすめ</string>
<string name="settings_nomedia_title">イメージを隠す</string>
<string name="main_delete">削除</string>
<string name="main_download">ダウンロード</string>
<string name="settings_backup_title">ブックマークバックアップ</string>
<string name="settings_restore_title">ブックマーク復元</string>
<string name="settings_backup_file_created">バックアップファイルを作成しました</string>
<string name="settings_restore_failed">復元に失敗しました</string>
<string name="settings_restore_success">%1$d項目を復元しました</string>
<string name="settings_download_folder">ダウンロード場所</string>
<string name="settings_download_folder_internal">内部ストレージ</string>
<string name="settings_download_folder_removable">外部SDカード</string>
<string name="settings_download_folder_available">%s 使用可能</string>
<string name="update_download_completed">ダウンロードが完了しました</string> <string name="update_download_completed">ダウンロードが完了しました</string>
<string name="update_download_completed_description">ここをクリックしてアップデートを行えます</string> <string name="update_download_completed_description">ここをクリックしてアップデートを行えます</string>
<string name="settings_beta">ベータチャンネルでアップデートを受信</string>
<string name="settings_app_version_description">v%s</string>
<string name="settings_low_quality">低解像度イメージ</string>
<string name="settings_low_quality_summary">ロード速度とデータ使用料を改善するため低解像度イメージをロード</string>
<string name="settings_download_folder_custom">手動で設定</string>
<string name="settings_download_folder_not_writable">このフォルダにアクセスできません。他のフォルダを選択してください。</string>
<string name="settings_proxy_title">プロクシ</string>
<string name="proxy_dialog_username_hint">ID</string>
<string name="proxy_dialog_type">プロクシタイプ</string>
<string name="proxy_dialog_port_hint">ポート</string>
<string name="proxy_dialog_password_hint">パスワード</string>
<string name="proxy_dialog_error">エラー</string>
<string name="proxy_dialog_addr_hint">サーバーアドレス</string>
<string name="proxy_dialog_server">サーバー</string>
<string name="main_menu_thin">簡単モード</string>
<string name="main_fab_cancel">すべてのダウンロードキャンセル</string> <string name="main_fab_cancel">すべてのダウンロードキャンセル</string>
<string name="channel_update">アップデート</string> <string name="channel_update">アップデート</string>
<string name="channel_update_description">アップデートの進行状態を表示</string> <string name="channel_update_description">アップデートの進行状態を表示</string>
<string name="settings_import_old_galleries">旧ギャラリーインポート</string>
<string name="import_old_galleries_folder_not_readable">フォルダを読めません</string>
<string name="import_old_galleries_notification">旧ギャラリーインポート中…</string>
<string name="import_old_galleries_notification_done">インポート完了</string>
<string name="main_fab_random">ランダムギャラリーを開く</string> <string name="main_fab_random">ランダムギャラリーを開く</string>
<string name="settings_lock_fingerprint_without_lock">予備のロックが設定されていないと指紋ロックは使用できません</string>
<string name="settings_lock_fingerprint_prompt">Pupil指紋ロック™</string>
<string name="settings_lock_fingerprint_prompt_subtitle">こうかはばつぐんだ!</string>
<string name="default_query_dialog_filter_loli">登場人物を全て18歳以上にする</string>
<string name="settings_user_id">ユーザーID</string>
<string name="copied_to_clipboard">クリップボードにコピーしました</string>
<string name="reader_fab_retry">リトライ</string>
<string name="reader_fab_auto">まばたき検知スクロール</string>
<string name="search_all">全てのギャラリーを対象に検索</string>
<string name="settings_rtl">綴じ方向を左にする</string>
<string name="settings_manage_favorites">ブックマーク管理</string>
<string name="settings_backup_failed">エラーが発生しました</string>
<string name="settings_backup_share">バックアップ共有</string>
<string name="channel_downloader">ダウンローダ</string> <string name="channel_downloader">ダウンローダ</string>
<string name="channel_downloader_description">ダウンローダの状態を表示</string> <string name="channel_downloader_description">ダウンローダの状態を表示</string>
<string name="downloader_running">ダウンローダー起動中</string>
<string name="settings_download_folder_name">フォルダ名パターン</string>
<string name="settings_invalid_download_folder_name">フォルダ名に使用できない文字が含まれています</string>
<string name="settings_download_folder_name_message">%sに含まれている文字列を対応する変数に置換します\n\n%s</string>
<string name="settings_manage_storage">ストレージ管理</string>
<string name="settings_oss">オープンソースライセンス</string>
<string name="search_show_tags">お気に入りのタグを見る</string>
<string name="search_show_histories">履歴を見る</string>
<string name="reader_fab_auto_cancel">まばたき検知を中止</string>
<string name="camera_denied">カメラ権限が拒否されているため、まばたき検知使用できません</string>
<string name="no_camera">この機器には前面カメラが装着されていません</string>
<string name="error">エラー</string>
<string name="settings_cache_limit">キャッシュサイズ制限</string>
<string name="unlimited">制限なし</string>
<string name="settings_tag_translation">タグ言語</string> <string name="settings_tag_translation">タグ言語</string>
<string name="settings_tag_translation_message">Githubにて翻訳に参加できます</string>
<string name="settings_max_concurrent_download">並列ダウンロード</string>
<string name="unaccessible_download_folder">アンドロイド11以上では外部からのアプリ内部空間接近が不可能です。ダウンロードフォルダを変更しますか</string>
<string name="settings_networking">ネットワーク</string>
</resources> </resources>

View File

@@ -3,25 +3,158 @@
<string name="galleryblock_language">언어: %1$s</string> <string name="galleryblock_language">언어: %1$s</string>
<string name="galleryblock_series">시리즈: %1$s</string> <string name="galleryblock_series">시리즈: %1$s</string>
<string name="galleryblock_type">종류: %1$s</string> <string name="galleryblock_type">종류: %1$s</string>
<string name="search_hint">갤러리 검색</string> <string name="search_hint">검색</string>
<string name="settings_default_query">기본 검색어</string> <string name="settings_default_query">기본 검색어</string>
<string name="settings_clear_cache">캐시 정리하기</string>
<string name="settings_clear_cache_alert_message">캐시를 정리하면 이미지 로딩속도가 느려질 수 있습니다. 계속하시겠습니까?</string>
<string name="settings_storage_usage">%s 사용중</string>
<string name="settings_storage_usage_loading">저장공간 사용량 계산 중…</string>
<string name="settings_galleries_per_page">한 번에 로드할 갤러리 수</string>
<string name="settings_search_title">검색 설정</string>
<string name="settings_title">설정</string>
<string name="update_notification_description">업데이트 다운로드중&#8230;</string> <string name="update_notification_description">업데이트 다운로드중&#8230;</string>
<string name="update_title">업데이트가 있습니다!</string> <string name="update_title">업데이트가 있습니다!</string>
<string name="warning">경고</string>
<string name="main_no_result">결과 없음\n해결법</string>
<string name="settings_miscellaneous_title">기타</string>
<string name="settings_clear_history">기록 삭제</string>
<string name="settings_clear_history_alert_message">기록을 삭제하시겠습니까?</string>
<string name="settings_clear_history_summary">기록 %1$d개 저장됨</string>
<string name="main_drawer_history">기록</string>
<string name="main_drawer_home"></string>
<string name="update_release_note"># 릴리즈 노트(v%1$s)\n%2$s</string> <string name="update_release_note"># 릴리즈 노트(v%1$s)\n%2$s</string>
<string name="settings_security_mode_summary">최근 앱 목록 창에서 앱 화면을 보이지 않게 합니다</string>
<string name="settings_security_mode_title">보안 모드 활성화</string>
<string name="reader_go_to_page">이동</string>
<string name="default_query_dialog_language_selector_none">미선택</string>
<string name="default_query_dialog_filter_BL">BL물 필터</string>
<string name="default_query_dialog_filter_guro">고어물 필터</string>
<string name="default_query_dialog_language">"언어: "</string>
<string name="default_query_dialog_title">기본 검색어 설정</string>
<string name="main_drawer_group_contact_email">메일 보내기!</string>
<string name="main_drawer_group_contact_github">Github</string>
<string name="main_drawer_group_contact_help">도움말</string>
<string name="main_drawer_group_contact_homepage">홈페이지</string>
<string name="main_drawer_group_contact_title">문의</string>
<string name="reader_fab_fullscreen">전체 화면</string> <string name="reader_fab_fullscreen">전체 화면</string>
<string name="channel_download">다운로드</string> <string name="channel_download">다운로드</string>
<string name="channel_download_description">다운로드 상태 알림</string> <string name="channel_download_description">다운로드 상태 알림</string>
<string name="reader_fab_download">백그라운드 다운로드</string>
<string name="reader_notification_text">다운로드 중…</string>
<string name="reader_notification_complete">다운로드 완료</string>
<string name="reader_fab_download_cancel">백그라운드 다운로드 취소</string>
<string name="main_drawer_downloads">다운로드</string>
<string name="main_jump_title">페이지 이동</string> <string name="main_jump_title">페이지 이동</string>
<string name="main_jump_message">현재 페이지: %1$d\n페이지 수: %2$d</string>
<string name="unable_to_connect">hitomi.la에 연결할 수 없습니다</string>
<string name="main_move_to_page">%1$d 페이지로 이동</string>
<string name="settings_clear_downloads">다운로드 삭제</string>
<string name="settings_clear_downloads_alert_message">다운로드 된 만화를 모두 삭제합니다.\n계속하시겠습니까?</string>
<string name="main_drawer_favorite">즐겨찾기</string>
<string name="main_open_gallery_by_id">갤러리 번호로 열기</string> <string name="main_open_gallery_by_id">갤러리 번호로 열기</string>
<string name="reader_failed_to_find_gallery">갤러리를 찾지 못했습니다</string>
<string name="settings_storage">저장 공간</string>
<string name="main_drawer_grouop_contact_discord">디스코드</string>
<string name="settings_app_lock">앱 잠금</string>
<string name="settings_app_lock_type">앱 잠금 종류</string>
<string name="settings_app_version_title">앱 버전(업데이트 확인)</string>
<string name="settings_lock_biometrics">생체 인식</string>
<string name="settings_lock_confirm">잠금 확인을 위해 한번 더 입력해주세요</string>
<string name="settings_lock_enabled">사용 중</string>
<string name="settings_lock_fingerprint">지문</string>
<string name="settings_lock_password">비밀번호</string>
<string name="settings_lock_pattern">패턴</string>
<string name="settings_lock_wrong_confirm">잠금이 일치하지 않습니다. 다시 시도하세요.</string>
<string name="settings_lock_none">없음</string>
<string name="settings_lock_remove_message">잠금을 해제할까요?</string>
<string name="reader_loading">로딩중</string> <string name="reader_loading">로딩중</string>
<string name="ignore_update">무시</string> <string name="main_menu_sort">정렬</string>
<string name="main_menu_sort_popular">인기순</string>
<string name="main_menu_sort_newest">시간순</string>
<string name="ignore">무시</string>
<string name="lock_corrupted">잠금 파일이 손상되었습니다! 앱을 재설치 해 주시기 바랍니다.</string>
<string name="settings_dark_mode_title">다크 모드</string>
<string name="settings_dark_mode_summary">딥 다크한 모오드</string>
<string name="gallery_details">갤러리 정보</string>
<string name="gallery_artists">작가</string>
<string name="gallery_characters">캐릭터</string>
<string name="gallery_groups">그룹</string>
<string name="gallery_language">언어</string>
<string name="gallery_series">시리즈</string>
<string name="gallery_tags">태그</string>
<string name="gallery_related">관련 갤러리</string>
<string name="gallery_thumbnails">미리보기</string>
<string name="settings_nomedia_title">이미지 숨기기</string>
<string name="main_delete">삭제</string>
<string name="main_download">다운로드</string>
<string name="settings_backup_title">즐겨찾기 백업</string>
<string name="settings_restore_title">즐겨찾기 복원</string>
<string name="settings_backup_file_created">백업 파일을 생성하였습니다</string>
<string name="settings_restore_failed">복원에 실패했습니다</string>
<string name="settings_restore_success">%1$d개 항목을 복원했습니다</string>
<string name="settings_download_folder">다운로드 위치</string>
<string name="settings_download_folder_internal">내부 저장공간</string>
<string name="settings_download_folder_removable">외부 SD카드</string>
<string name="settings_download_folder_available">%s 사용 가능</string>
<string name="update_download_completed">다운로드가 완료되었습니다</string> <string name="update_download_completed">다운로드가 완료되었습니다</string>
<string name="update_download_completed_description">여기를 클릭해서 업데이트를 진행할 수 있습니다</string> <string name="update_download_completed_description">여기를 클릭해서 업데이트를 진행할 수 있습니다</string>
<string name="settings_beta">베타 채널에서 업데이트</string>
<string name="settings_app_version_description">v%s</string>
<string name="settings_low_quality">저해상도 이미지</string>
<string name="settings_low_quality_summary">로드 속도와 데이터 사용량을 줄이기 위해 저해상도 이미지를 로드</string>
<string name="settings_mirror_summary">미러 서버에서 이미지 로드</string>
<string name="settings_mirror_title">미러 설정</string>
<string name="settings_download_folder_custom">직접 설정</string>
<string name="settings_download_folder_not_writable">이 폴더에 접근할 수 없습니다. 다른 폴더를 선택해주세요.</string>
<string name="settings_proxy_title">프록시</string>
<string name="proxy_dialog_username_hint">ID</string>
<string name="proxy_dialog_type">프록시 타입</string>
<string name="proxy_dialog_port_hint">포트</string>
<string name="proxy_dialog_password_hint">비밀번호</string>
<string name="proxy_dialog_error">잘못된 값</string>
<string name="proxy_dialog_addr_hint">서버 주소</string>
<string name="proxy_dialog_server">서버</string>
<string name="main_menu_thin">간단히 보기</string>
<string name="main_fab_cancel">다운로드 모두 취소</string> <string name="main_fab_cancel">다운로드 모두 취소</string>
<string name="channel_update">업데이트</string> <string name="channel_update">업데이트</string>
<string name="channel_update_description">업데이트 진행상황 표시</string> <string name="channel_update_description">업데이트 진행상황 표시</string>
<string name="settings_import_old_galleries">이전 버전 갤러리 가져오기</string>
<string name="import_old_galleries_folder_not_readable">폴더를 읽을 수 없습니다</string>
<string name="import_old_galleries_notification">이전 버전 갤러리 가져오는 중…</string>
<string name="import_old_galleries_notification_done">가져오기 완료</string>
<string name="main_fab_random">무작위 갤러리 열기</string> <string name="main_fab_random">무작위 갤러리 열기</string>
<string name="settings_lock_fingerprint_without_lock">지문 잠금은 다른 잠금 방식이 활성화 되어 있을 때만 사용 가능합니다</string>
<string name="settings_lock_fingerprint_prompt">Pupil 지문 인식™</string>
<string name="settings_lock_fingerprint_prompt_subtitle">힘세고 강한 지문 인식</string>
<string name="default_query_dialog_filter_loli">판사님 저는 페도가 아닙니다</string>
<string name="settings_user_id">유저 ID</string>
<string name="copied_to_clipboard">클립보드에 복사됨</string>
<string name="reader_fab_retry">재시도</string>
<string name="reader_fab_auto">눈 깜빡임 감지 스크롤</string>
<string name="search_all">모든 갤러리 검색</string>
<string name="settings_rtl">좌측으로 페이지 넘기기</string>
<string name="settings_manage_favorites">즐겨찾기 관리</string>
<string name="settings_backup_failed">업로드 실패</string>
<string name="settings_backup_share">백업 공유</string>
<string name="channel_downloader">다운로더</string> <string name="channel_downloader">다운로더</string>
<string name="channel_downloader_description">다운로더 작동 여부 표시</string> <string name="channel_downloader_description">다운로더 작동 여부 표시</string>
<string name="downloader_running">다운로더 작동중…</string>
<string name="settings_download_folder_name">폴더명 패턴</string>
<string name="settings_invalid_download_folder_name">폴더 패턴에 사용할 수 없는 문자가 포함되어 있습니다</string>
<string name="settings_download_folder_name_message">지원되는 변수는 %s 입니다\n\n%s</string>
<string name="settings_manage_storage">저장소 관리</string>
<string name="settings_oss">오픈 소스 라이선스</string>
<string name="search_show_histories">검색 기록 보기</string>
<string name="search_show_tags">즐겨찾기 태그 보기</string>
<string name="reader_fab_auto_cancel">눈 깜빡임 감지 중지</string>
<string name="camera_denied">카메라 권한이 거부되었기 때문에 눈 깜빡임 감지가 불가능합니다</string>
<string name="no_camera">이 장치에는 전면 카메라가 없습니다</string>
<string name="error">오류</string>
<string name="settings_cache_limit">캐시 크기 제한</string>
<string name="unlimited">무제한</string>
<string name="settings_tag_translation">태그 언어</string> <string name="settings_tag_translation">태그 언어</string>
<string name="settings_tag_translation_message">Github에서 번역에 참여하세요</string>
<string name="settings_max_concurrent_download">병렬 다운로드</string>
<string name="unaccessible_download_folder">안드로이드 11 이상에서는 외부에서 현재 다운로드 폴더에 접근할 수 없습니다. 변경하시겠습니까?</string>
<string name="settings_networking">네트워크</string>
</resources> </resources>

View File

@@ -1,13 +1,38 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name" translatable="false" tools:override="true">Pupil-BETA</string> <string name="app_name" translatable="false" tools:override="true">Pupil</string>
<string name="release_url" translatable="false">https://api.github.com/repos/tom5079/Pupil/releases</string> <string name="release_url" translatable="false">https://api.github.com/repos/tom5079/Pupil/releases</string>
<string name="home_page" translatable="false">http://bit.ly/2EZDClw</string>
<string name="help" translatable="false">http://bit.ly/2Z7lNZE</string>
<string name="github" translatable="false">https://github.com/tom5079/Pupil/</string>
<string name="email" translatable="false">mailto:pupil.hentai@gmail.com</string>
<string name="discord" translatable="false">https://discord.gg/Stj4b5v</string>
<!-- Korean only --> <!-- Korean only -->
<string name="https_text" translatable="false">해결법</string>
<string name="https" translatable="false">https://bit.ly/34dUBwy</string>
<string name="backup_url" translatable="false">http://ix.io/</string>
<string name="main_settings" translatable="false">Settings</string>
<string name="galleryblock_thumbnail_description" translatable="false">Thumbnail</string>
<string name="reader_imageview_description" translatable="false">Content ImageView</string>
<string name="page_indicator_placeholder" translatable="false">-/-</string>
<string name="galleryblock_artist_with_group" translatable="false">%s (%s)</string>
<!-- Translate needed down here --> <!-- Translate needed down here -->
<string name="ignore_update">Ignore</string> <string name="warning">Warning</string>
<string name="error">Error</string>
<string name="ignore">Ignore</string>
<string name="unlimited">Unlimited</string>
<string name="copied_to_clipboard">Copied to clipboard</string>
<string name="channel_download">Download</string> <string name="channel_download">Download</string>
<string name="channel_download_description">Shows download status</string> <string name="channel_download_description">Shows download status</string>
@@ -18,56 +43,210 @@
<string name="channel_update">Update</string> <string name="channel_update">Update</string>
<string name="channel_update_description">Shows update progress</string> <string name="channel_update_description">Shows update progress</string>
<string name="unable_to_connect">Unable to connect to hitomi.la</string>
<string name="lock_corrupted">Lock file corrupted! Please re-install Pupil</string>
<string name="main_no_result">No result</string>
<string name="unaccessible_download_folder">From Android 11 and above, current Download folder cannot be accessed by outside apps. Would you like to change the download folder?</string>
<string name="main_drawer_home">Home</string>
<string name="main_drawer_history">History</string>
<string name="main_drawer_downloads">Downloads</string>
<string name="main_drawer_favorite">Favorites</string>
<string name="main_drawer_group_contact_title">Contact</string>
<string name="main_drawer_group_contact_help">Help</string>
<string name="main_drawer_group_contact_homepage">Visit homepage</string>
<string name="main_drawer_group_contact_github">Visit github</string>
<string name="main_drawer_group_contact_email">Email me!</string>
<string name="main_drawer_grouop_contact_discord">Discord</string>
<string name="main_menu_thin">Thin Mode</string>
<string name="main_menu_sort">Sort</string>
<string name="main_menu_sort_newest">Newest</string>
<string name="main_menu_sort_popular">Popular</string>
<string name="main_jump_title">Jump to page</string> <string name="main_jump_title">Jump to page</string>
<string name="main_jump_message">Current page: %1$d\nMaximum page: %2$d</string>
<string name="main_open_gallery_by_id">Open Gallery by ID</string> <string name="main_open_gallery_by_id">Open Gallery by ID</string>
<string name="reader_failed_to_find_gallery">Failed to open gallery</string>
<string name="main_fab_random">Open a random gallery</string> <string name="main_fab_random">Open a random gallery</string>
<string name="main_fab_cancel">Cancel all downloads</string> <string name="main_fab_cancel">Cancel all downloads</string>
<string name="main_move_to_page">Move to page %1$d</string>
<string name="main_download">DOWNLOAD</string>
<string name="main_delete">DELETE</string>
<string name="update_title">Update available</string> <string name="update_title">Update available</string>
<string name="update_download_completed">Download Completed</string> <string name="update_download_completed">Download Completed</string>
<string name="update_download_completed_description">Click here to update</string> <string name="update_download_completed_description">Click here to update</string>
<string name="update_notification_description">Downloading update&#8230;</string> <string name="update_notification_description">Downloading update&#8230;</string>
<string name="update_release_note"># Release Note(v%1$s)\n%2$s</string> <string name="update_release_note"># Release Note(v%1$s)\n%2$s</string>
<string name="search_hint">Search galleries</string> <string name="search_hint">Search</string>
<string name="search_all">Search all galleries</string>
<string name="search_show_histories">Show histories</string>
<string name="search_show_tags">Show favorite tags</string>
<string name="gallery_details">Details</string>
<string name="gallery_thumbnails">Thumbnails</string>
<string name="gallery_related">Related Galleries</string>
<string name="gallery_artists">Artists</string>
<string name="gallery_groups">Groups</string>
<string name="gallery_language">Language</string>
<string name="gallery_series">Series</string>
<string name="gallery_characters">Characters</string>
<string name="gallery_tags">Tags</string>
<string name="galleryblock_series">Series: %1$s</string> <string name="galleryblock_series">Series: %1$s</string>
<string name="galleryblock_type">Type: %1$s</string> <string name="galleryblock_type">Type: %1$s</string>
<string name="galleryblock_language">Language: %1$s</string> <string name="galleryblock_language">Language: %1$s</string>
<string name="galleryblock_pagecount" translatable="false">%dP</string>
<!-- READER --> <!-- READER -->
<string name="reader_loading">Loading</string> <string name="reader_loading">Loading</string>
<string name="reader_fab_fullscreen">Fullscreen</string><![CDATA[> <string name="reader_go_to_page">Go to page</string>
<string name="reader_fab_fullscreen">Fullscreen</string>>
<string name="reader_fab_retry">Retry</string>
<string name="reader_fab_auto">Scroll with eye blink</string>
<string name="reader_fab_auto_cancel">Stop scroll with eye blink</string>
<string name="reader_fab_download">Background download</string>
<string name="reader_fab_download_cancel">Cancel background download</string>
<string name="reader_notification_text">Downloading&#8230;</string>
<string name="reader_notification_complete">Download complete</string>
]]><!-- DOWNLOADER --> <string name="camera_denied">Eye blink detection cannot be used without a permission</string>
<string name="no_camera">There is no front facing camera in this device</string>
<!-- DOWNLOADER -->
<string name="downloader_running">Downloader running…</string>
<!-- SETTINGS --> <!-- SETTINGS -->
<string name="settings_title">Settings</string>
<string name="settings_app_version_title">App version(Click to check update)</string>
<string name="settings_app_version_description">v%s</string>
<string name="settings_beta">Update from beta channel</string>
<!-- SEARCH --> <!-- SEARCH -->
<string name="settings_search_title">Search Settings</string>
<string name="settings_galleries_per_page">Galleries per page</string>
<string name="settings_default_query">Default query</string> <string name="settings_default_query">Default query</string>
<!-- SETTINGS/STORAGE --> <!-- SETTINGS/STORAGE -->
<string name="settings_storage">Storage</string>
<!-- SETTINGS/STORAGE / MANAGE STORAGE --> <!-- SETTINGS/STORAGE / MANAGE STORAGE -->
<string name="settings_manage_storage">Manage Storage</string>
<string name="settings_storage_usage">Currently using %s</string>
<string name="settings_storage_usage_loading">Calculating storage usage…</string>
<string name="settings_clear_cache">Clear cache</string>
<string name="settings_clear_cache_alert_message">Deleting cache can affect image loading speed. Do you want to continue?</string>
<string name="settings_clear_downloads">Clear downloads</string>
<string name="settings_clear_downloads_alert_message">Delete all downloaded galleries.\nDo you want to continue?</string>
<string name="settings_clear_history">Clear history</string>
<string name="settings_clear_history_alert_message">Do you want to clear histories?</string>
<string name="settings_clear_history_summary">%1$d histories saved</string>
<!-- SETTINGS/STORAGE / MISCELLANEOUS --> <!-- SETTINGS/STORAGE / MISCELLANEOUS -->
<string name="settings_download_folder_name">Folder naming pattern</string>
<string name="settings_invalid_download_folder_name">Folder naming pattern is containing invalid characters</string>
<string name="settings_download_folder_name_message">%s will be replaced to its corresponding value\n\n%s</string>
<string name="settings_download_folder">Download folder</string>
<string name="settings_download_folder_removable">Removable Storage</string>
<string name="settings_download_folder_internal">Internal Storage</string>
<string name="settings_download_folder_available">%s available</string>
<string name="settings_download_folder_custom">Custom Location</string>
<string name="settings_download_folder_not_writable">This folder is not writable. Please select another folder.</string>
<string name="settings_cache_limit">Cache Limit</string>
<string name="settings_nomedia_title">Hide image from gallery</string>
<string name="settings_low_quality">Low quality images</string>
<string name="settings_low_quality_summary">Load low quality images to improve load speed and data usage</string>
<!-- SETTINGS/APP LOCK --> <!-- SETTINGS/APP LOCK -->
<string name="settings_app_lock">App lock</string>
<string name="settings_app_lock_type">App lock type</string>
<!-- SETTINGS/NETWORKING -->
<string name="settings_networking">Networking</string>
<string name="settings_mirror_summary">Load images from mirrors</string>
<string name="settings_proxy_title">Proxy</string>
<string name="settings_max_concurrent_download">Concurrent Download</string>
<!-- SETTINGS/MISCELLANEOUS --> <!-- SETTINGS/MISCELLANEOUS -->
<string name="settings_miscellaneous_title">Miscellaneous</string>
<string name="settings_tag_translation">Tag Language</string> <string name="settings_tag_translation">Tag Language</string>
<string name="settings_tag_translation_message">Participate in translation on Github</string>
<string name="settings_rtl">Turn pages Right-to-Left</string>
<string name="settings_security_mode_title">Enable security mode</string>
<string name="settings_security_mode_summary">Enable security mode to make the screen invisible on recent app window</string>
<string name="settings_dark_mode_title">Dark mode</string>
<string name="settings_dark_mode_summary">Protect yourself against light attacks!</string>
<string name="settings_import_old_galleries">Import old galleries</string>
<string name="settings_user_id">User ID</string>
<string name="settings_oss">Open Source Notice</string>
<!-- MANAGE FAVORITES --> <!-- MANAGE FAVORITES -->
<string name="settings_manage_favorites">Manage favorites</string>
<string name="settings_backup_title">Backup favorites</string>
<string name="settings_backup_failed">Upload Failed</string>
<string name="settings_backup_share">Share Backup</string>
<string name="settings_backup_file_created">Backup file created</string>
<string name="settings_restore_title">Restore favorites</string>
<string name="settings_restore_failed">Restore failed</string>
<string name="settings_restore_success">%1$d entries restored</string>
<!-- SETTINGS/APP LOCK ACTIVITY --> <!-- SETTINGS/APP LOCK ACTIVITY -->
<string name="settings_lock_none">None</string>
<string name="settings_lock_pattern">Pattern</string>
<string name="settings_lock_pin" translatable="false">PIN</string>
<string name="settings_lock_password">Password</string>
<string name="settings_lock_biometrics">Biometrics</string>
<string name="settings_lock_fingerprint">Fingerprint</string>
<string name="settings_lock_fingerprint_without_lock">Fingerprint can be only enabled if one of the other locks are enabled</string>
<string name="settings_lock_fingerprint_prompt">Pupil Fingerprint Lock™</string>
<string name="settings_lock_enabled">Enabled</string>
<string name="settings_lock_confirm">Input same lock once more to confirm Lock</string>
<string name="settings_lock_remove_message">Do you want to remove lock?</string>
<string name="settings_lock_wrong_confirm">Lock is different from last one. Please try again.</string>
<!-- SETTINGS/DEFAULT QUERY DIALOG --> <!-- SETTINGS/DEFAULT QUERY DIALOG -->
<string name="default_query_dialog_title">Set default query</string>
<string name="default_query_dialog_language">Language: </string>
<string name="default_query_dialog_filter_BL">Filter BL</string>
<string name="default_query_dialog_filter_guro">Filter Guro</string>
<string name="default_query_dialog_filter_loli">I\'m not a pedophile</string>
<string name="default_query_dialog_language_selector_none">Any</string>
<string name="settings_mirror_title">Mirrors</string>
<!-- PROXY DIALOG --> <!-- PROXY DIALOG -->
<string name="proxy_dialog_type">type</string>
<string name="proxy_dialog_addr_hint">address</string>
<string name="proxy_dialog_port_hint">port</string>
<string name="proxy_dialog_username_hint">username</string>
<string name="proxy_dialog_password_hint">password</string>
<string name="proxy_dialog_error">Wrong value</string>
<string name="proxy_dialog_server">server</string>
<!-- IMPORT OLD GALLERIES --> <!-- IMPORT OLD GALLERIES -->
<string name="import_old_galleries_folder_not_readable">This folder is not readable</string>
<string name="import_old_galleries_notification">Importing old galleries…</string>
<string name="import_old_galleries_notification_text" translatable="false">%1$d/%2$d</string>
<string name="import_old_galleries_notification_done">Importing completed</string>
<string name="settings_lock_fingerprint_prompt_subtitle">Ah Shit, Here we go again</string>
</resources> </resources>

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Pupil, Hitomi.la viewer for Android
~ Copyright (C) 2021 tom5079
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
app:key="hitomi.default_query"
app:title="@string/settings_default_query"
app:useSimpleSummaryProvider="true"/>
<ListPreference
app:key="hitomi.tag_translation"
app:title="@string/settings_tag_translation"
app:useSimpleSummaryProvider="true"/>
</PreferenceScreen>