Merge branch 'devel' of github.com:nv95/Kotatsu into feature/suggestions
This commit is contained in:
@@ -5,29 +5,29 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
|
||||
class MangaIntent(
|
||||
class MangaIntent private constructor(
|
||||
val manga: Manga?,
|
||||
val mangaId: Long,
|
||||
val uri: Uri?
|
||||
val uri: Uri?,
|
||||
) {
|
||||
|
||||
constructor(intent: Intent?) : this(
|
||||
manga = intent?.getParcelableExtra(KEY_MANGA),
|
||||
mangaId = intent?.getLongExtra(KEY_ID, ID_NONE) ?: ID_NONE,
|
||||
uri = intent?.data
|
||||
)
|
||||
|
||||
constructor(args: Bundle?) : this(
|
||||
manga = args?.getParcelable(KEY_MANGA),
|
||||
mangaId = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE,
|
||||
uri = null
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
fun from(intent: Intent?) = MangaIntent(
|
||||
manga = intent?.getParcelableExtra(KEY_MANGA),
|
||||
mangaId = intent?.getLongExtra(KEY_ID, ID_NONE) ?: ID_NONE,
|
||||
uri = intent?.data
|
||||
)
|
||||
|
||||
fun from(args: Bundle?) = MangaIntent(
|
||||
manga = args?.getParcelable(KEY_MANGA),
|
||||
mangaId = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE,
|
||||
uri = null
|
||||
)
|
||||
|
||||
const val ID_NONE = 0L
|
||||
|
||||
const val KEY_MANGA = "manga"
|
||||
const val KEY_ID = "id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.koitharu.kotatsu.base.domain
|
||||
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
|
||||
object MangaProviderFactory {
|
||||
|
||||
fun getSources(settings: AppSettings, includeHidden: Boolean): List<MangaSource> {
|
||||
val list = MangaSource.values().toList() - MangaSource.LOCAL
|
||||
val order = settings.sourcesOrder
|
||||
val sorted = list.sortedBy { x ->
|
||||
val e = order.indexOf(x.ordinal)
|
||||
if (e == -1) order.size + x.ordinal else e
|
||||
}
|
||||
return if (includeHidden) {
|
||||
sorted
|
||||
} else {
|
||||
val hidden = settings.hiddenSources
|
||||
sorted.filterNot { x ->
|
||||
x.name in hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import android.net.Uri
|
||||
import android.util.Size
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.koin.core.component.KoinComponent
|
||||
@@ -14,7 +13,6 @@ import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.core.model.MangaPage
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import org.koitharu.kotatsu.utils.ext.await
|
||||
import org.koitharu.kotatsu.utils.ext.medianOrNull
|
||||
import java.io.InputStream
|
||||
@@ -40,15 +38,14 @@ object MangaUtils : KoinComponent {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val client = get<OkHttpClient>()
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.get()
|
||||
.header(CommonHeaders.REFERER, page.referer)
|
||||
.cacheControl(CacheUtils.CONTROL_DISABLED)
|
||||
.cacheControl(CommonHeaders.CACHE_CONTROL_DISABLED)
|
||||
.build()
|
||||
client.newCall(request).await().use {
|
||||
withContext(Dispatchers.IO) {
|
||||
get<OkHttpClient>().newCall(request).await().use {
|
||||
runInterruptible(Dispatchers.IO) {
|
||||
getBitmapSize(it.body?.byteStream())
|
||||
}
|
||||
}
|
||||
@@ -66,10 +63,10 @@ object MangaUtils : KoinComponent {
|
||||
val options = BitmapFactory.Options().apply {
|
||||
inJustDecodeBounds = true
|
||||
}
|
||||
BitmapFactory.decodeStream(input, null, options)
|
||||
BitmapFactory.decodeStream(input, null, options)?.recycle()
|
||||
val imageHeight: Int = options.outHeight
|
||||
val imageWidth: Int = options.outWidth
|
||||
check(imageHeight > 0 && imageWidth > 0)
|
||||
return Size(imageWidth, imageHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@ abstract class AlertDialogFragment<B : ViewBinding> : DialogFragment() {
|
||||
get() = checkNotNull(viewBinding)
|
||||
|
||||
final override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val inflater = activity?.layoutInflater ?: LayoutInflater.from(requireContext())
|
||||
val binding = onInflateView(inflater, null)
|
||||
val binding = onInflateView(layoutInflater, null)
|
||||
viewBinding = binding
|
||||
return MaterialAlertDialogBuilder(requireContext(), theme)
|
||||
.setView(binding.root)
|
||||
@@ -43,4 +42,4 @@ abstract class AlertDialogFragment<B : ViewBinding> : DialogFragment() {
|
||||
protected fun bindingOrNull(): B? = viewBinding
|
||||
|
||||
protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,10 @@ abstract class BaseActivity<B : ViewBinding> : AppCompatActivity(), OnApplyWindo
|
||||
private var lastInsets: Insets = Insets.NONE
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val settings = get<AppSettings>()
|
||||
when {
|
||||
get<AppSettings>().isAmoledTheme -> setTheme(R.style.ThemeOverlay_Kotatsu_AMOLED)
|
||||
get<AppSettings>().isDynamicTheme -> setTheme(R.style.Theme_Kotatsu_Monet)
|
||||
settings.isAmoledTheme -> setTheme(R.style.ThemeOverlay_Kotatsu_AMOLED)
|
||||
settings.isDynamicTheme -> setTheme(R.style.Theme_Kotatsu_Monet)
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
@@ -130,4 +131,4 @@ abstract class BaseActivity<B : ViewBinding> : AppCompatActivity(), OnApplyWindo
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ import androidx.viewbinding.ViewBinding
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
abstract class BaseBottomSheet<B : ViewBinding> :
|
||||
BottomSheetDialogFragment() {
|
||||
abstract class BaseBottomSheet<B : ViewBinding> : BottomSheetDialogFragment() {
|
||||
|
||||
private var viewBinding: B? = null
|
||||
|
||||
@@ -40,4 +39,4 @@ abstract class BaseBottomSheet<B : ViewBinding> :
|
||||
}
|
||||
|
||||
protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import androidx.preference.PreferenceFragmentCompat
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
|
||||
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
|
||||
PreferenceFragmentCompat(), OnApplyWindowInsetsListener {
|
||||
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) : PreferenceFragmentCompat(),
|
||||
OnApplyWindowInsetsListener {
|
||||
|
||||
protected val settings by inject<AppSettings>(mode = LazyThreadSafetyMode.NONE)
|
||||
|
||||
@@ -36,4 +36,4 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
|
||||
)
|
||||
return insets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import android.widget.BaseAdapter
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.databinding.ItemStorageBinding
|
||||
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.utils.ext.getStorageName
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
import org.koitharu.kotatsu.utils.ext.inflate
|
||||
import java.io.File
|
||||
|
||||
@@ -20,15 +20,18 @@ class StorageSelectDialog private constructor(private val delegate: AlertDialog)
|
||||
|
||||
fun show() = delegate.show()
|
||||
|
||||
class Builder(context: Context, defaultValue: File?, listener: OnStorageSelectListener) {
|
||||
class Builder(context: Context, storageManager: LocalStorageManager, listener: OnStorageSelectListener) {
|
||||
|
||||
private val adapter = VolumesAdapter(context)
|
||||
private val adapter = VolumesAdapter(storageManager)
|
||||
private val delegate = MaterialAlertDialogBuilder(context)
|
||||
|
||||
init {
|
||||
if (adapter.isEmpty) {
|
||||
delegate.setMessage(R.string.cannot_find_available_storage)
|
||||
} else {
|
||||
val defaultValue = runBlocking {
|
||||
storageManager.getDefaultWriteableDir()
|
||||
}
|
||||
adapter.selectedItemPosition = adapter.volumes.indexOfFirst {
|
||||
it.first.canonicalPath == defaultValue?.canonicalPath
|
||||
}
|
||||
@@ -57,10 +60,10 @@ class StorageSelectDialog private constructor(private val delegate: AlertDialog)
|
||||
fun create() = StorageSelectDialog(delegate.create())
|
||||
}
|
||||
|
||||
private class VolumesAdapter(context: Context) : BaseAdapter() {
|
||||
private class VolumesAdapter(storageManager: LocalStorageManager) : BaseAdapter() {
|
||||
|
||||
var selectedItemPosition: Int = -1
|
||||
val volumes = getAvailableVolumes(context)
|
||||
val volumes = getAvailableVolumes(storageManager)
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = convertView ?: parent.inflate(R.layout.item_storage)
|
||||
@@ -82,9 +85,11 @@ class StorageSelectDialog private constructor(private val delegate: AlertDialog)
|
||||
|
||||
override fun hasStableIds() = true
|
||||
|
||||
private fun getAvailableVolumes(context: Context): List<Pair<File, String>> {
|
||||
return LocalMangaRepository.getAvailableStorageDirs(context).map {
|
||||
it to it.getStorageName(context)
|
||||
private fun getAvailableVolumes(storageManager: LocalStorageManager): List<Pair<File, String>> {
|
||||
return runBlocking {
|
||||
storageManager.getWriteableDirs().map {
|
||||
it to storageManager.getStorageDisplayName(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.koitharu.kotatsu.core.network
|
||||
|
||||
import okhttp3.CacheControl
|
||||
|
||||
object CommonHeaders {
|
||||
|
||||
const val REFERER = "Referer"
|
||||
@@ -7,4 +9,7 @@ object CommonHeaders {
|
||||
const val ACCEPT = "Accept"
|
||||
const val CONTENT_DISPOSITION = "Content-Disposition"
|
||||
const val COOKIE = "Cookie"
|
||||
}
|
||||
|
||||
val CACHE_CONTROL_DISABLED: CacheControl
|
||||
get() = CacheControl.Builder().noStore().build()
|
||||
}
|
||||
|
||||
@@ -2,27 +2,24 @@ package org.koitharu.kotatsu.core.network
|
||||
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.base.domain.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
import org.koitharu.kotatsu.utils.DownloadManagerHelper
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
val networkModule
|
||||
get() = module {
|
||||
single { AndroidCookieJar() } bind CookieJar::class
|
||||
single(named(CacheUtils.QUALIFIER_HTTP)) { CacheUtils.createHttpCache(androidContext()) }
|
||||
single {
|
||||
OkHttpClient.Builder().apply {
|
||||
connectTimeout(20, TimeUnit.SECONDS)
|
||||
readTimeout(60, TimeUnit.SECONDS)
|
||||
writeTimeout(20, TimeUnit.SECONDS)
|
||||
cookieJar(get())
|
||||
cache(get(named(CacheUtils.QUALIFIER_HTTP)))
|
||||
cache(get<LocalStorageManager>().createHttpCache())
|
||||
addInterceptor(UserAgentInterceptor())
|
||||
addInterceptor(CloudFlareInterceptor())
|
||||
if (BuildConfig.DEBUG) {
|
||||
@@ -32,4 +29,4 @@ val networkModule
|
||||
}
|
||||
factory { DownloadManagerHelper(get(), get()) }
|
||||
single { MangaLoaderContext(get(), get()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,10 +64,10 @@ abstract class RemoteMangaRepository(
|
||||
protected fun generateUid(url: String): Long {
|
||||
var h = 1125899906842597L
|
||||
source.name.forEach { c ->
|
||||
h = 31 * h + c.toLong()
|
||||
h = 31 * h + c.code
|
||||
}
|
||||
url.forEach { c ->
|
||||
h = 31 * h + c.toLong()
|
||||
h = 31 * h + c.code
|
||||
}
|
||||
return h
|
||||
}
|
||||
@@ -75,7 +75,7 @@ abstract class RemoteMangaRepository(
|
||||
protected fun generateUid(id: Long): Long {
|
||||
var h = 1125899906842597L
|
||||
source.name.forEach { c ->
|
||||
h = 31 * h + c.toLong()
|
||||
h = 31 * h + c.code
|
||||
}
|
||||
h = 31 * h + id
|
||||
return h
|
||||
@@ -84,4 +84,4 @@ abstract class RemoteMangaRepository(
|
||||
protected fun parseFailed(message: String? = null): Nothing {
|
||||
throw ParseException(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepositoryAuthProvider
|
||||
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -32,7 +33,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
offset: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder?
|
||||
sortOrder: SortOrder?,
|
||||
): List<Manga> {
|
||||
copyCookies()
|
||||
val domain = getDomain()
|
||||
@@ -97,9 +98,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
}
|
||||
val branchId = content.getJSONArray("branches").optJSONObject(0)
|
||||
?.getLong("id") ?: throw ParseException("No branches found")
|
||||
val chapters = loaderContext.httpGet(
|
||||
url = "https://api.$domain/api/titles/chapters/?branch_id=$branchId"
|
||||
).parseJson().getJSONArray("content")
|
||||
val chapters = grabChapters(domain, branchId)
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US)
|
||||
return manga.copy(
|
||||
description = content.getString("description"),
|
||||
@@ -118,11 +117,11 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
chapters = chapters.mapIndexed { i, jo ->
|
||||
val id = jo.getLong("id")
|
||||
val name = jo.getString("name").toTitleCase(Locale.ROOT)
|
||||
val publishers = jo.getJSONArray("publishers")
|
||||
val publishers = jo.optJSONArray("publishers")
|
||||
MangaChapter(
|
||||
id = generateUid(id),
|
||||
url = "/api/titles/chapters/$id/",
|
||||
number = chapters.length() - i,
|
||||
number = chapters.size - i,
|
||||
name = buildString {
|
||||
append("Том ")
|
||||
append(jo.optString("tome", "0"))
|
||||
@@ -135,7 +134,7 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
}
|
||||
},
|
||||
uploadDate = dateFormat.tryParse(jo.getString("upload_date")),
|
||||
scanlator = publishers.optJSONObject(0)?.getStringOrNull("name"),
|
||||
scanlator = publishers?.optJSONObject(0)?.getStringOrNull("name"),
|
||||
source = MangaSource.REMANGA,
|
||||
branch = null,
|
||||
)
|
||||
@@ -146,16 +145,28 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val referer = "https://${getDomain()}/"
|
||||
val content = loaderContext.httpGet(chapter.url.withDomain(subdomain = "api")).parseJson()
|
||||
.getJSONObject("content").getJSONArray("pages")
|
||||
val pages = ArrayList<MangaPage>(content.length())
|
||||
for (i in 0 until content.length()) {
|
||||
when (val item = content.get(i)) {
|
||||
is JSONObject -> pages += parsePage(item, referer)
|
||||
is JSONArray -> item.mapTo(pages) { parsePage(it, referer) }
|
||||
.getJSONObject("content")
|
||||
val pages = content.optJSONArray("pages")
|
||||
if (pages == null) {
|
||||
val pubDate = content.getStringOrNull("pub_date")?.let {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US).tryParse(it)
|
||||
}
|
||||
if (pubDate != null && pubDate > System.currentTimeMillis()) {
|
||||
val at = SimpleDateFormat.getDateInstance(DateFormat.LONG).format(Date(pubDate))
|
||||
parseFailed("Глава станет доступной $at")
|
||||
} else {
|
||||
parseFailed("Глава недоступна")
|
||||
}
|
||||
}
|
||||
val result = ArrayList<MangaPage>(pages.length())
|
||||
for (i in 0 until pages.length()) {
|
||||
when (val item = pages.get(i)) {
|
||||
is JSONObject -> result += parsePage(item, referer)
|
||||
is JSONArray -> item.mapTo(result) { parsePage(it, referer) }
|
||||
else -> throw ParseException("Unknown json item $item")
|
||||
}
|
||||
}
|
||||
return pages
|
||||
return result
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
@@ -198,6 +209,26 @@ class RemangaRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposito
|
||||
source = source,
|
||||
)
|
||||
|
||||
private suspend fun grabChapters(domain: String, branchId: Long): List<JSONObject> {
|
||||
val result = ArrayList<JSONObject>(100)
|
||||
var page = 1
|
||||
while (true) {
|
||||
val content = loaderContext.httpGet(
|
||||
"https://api.$domain/api/titles/chapters/?branch_id=$branchId&page=$page&count=100"
|
||||
).parseJson().getJSONArray("content")
|
||||
val len = content.length()
|
||||
if (len == 0) {
|
||||
break
|
||||
}
|
||||
result.ensureCapacity(result.size + len)
|
||||
for (i in 0 until len) {
|
||||
result.add(content.getJSONObject(i))
|
||||
}
|
||||
page++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
const val PAGE_SIZE = 30
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
@@ -12,133 +13,149 @@ import com.google.android.material.color.DynamicColors
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.trySendBlocking
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.utils.delegates.prefs.*
|
||||
import org.koitharu.kotatsu.utils.ext.toUriOrNull
|
||||
import java.io.File
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class AppSettings private constructor(private val prefs: SharedPreferences) :
|
||||
SharedPreferences by prefs {
|
||||
class AppSettings(context: Context) {
|
||||
|
||||
constructor(context: Context) : this(
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
)
|
||||
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
||||
var listMode by EnumPreferenceDelegate(
|
||||
ListMode::class.java,
|
||||
KEY_LIST_MODE,
|
||||
ListMode.DETAILED_LIST
|
||||
)
|
||||
var listMode: ListMode
|
||||
get() = prefs.getString(KEY_LIST_MODE, null)?.findEnumValue(ListMode.values()) ?: ListMode.DETAILED_LIST
|
||||
set(value) = prefs.edit { putString(KEY_LIST_MODE, value.name) }
|
||||
|
||||
var defaultSection by IntEnumPreferenceDelegate(
|
||||
AppSection::class.java,
|
||||
KEY_APP_SECTION,
|
||||
AppSection.HISTORY
|
||||
)
|
||||
var defaultSection: AppSection
|
||||
get() = prefs.getString(KEY_APP_SECTION, null)?.findEnumValue(AppSection.values()) ?: AppSection.HISTORY
|
||||
set(value) = prefs.edit { putString(KEY_APP_SECTION, value.name) }
|
||||
|
||||
val theme by StringIntPreferenceDelegate(
|
||||
KEY_THEME,
|
||||
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
)
|
||||
val theme: Int
|
||||
get() = prefs.getString(KEY_THEME, null)?.toIntOrNull() ?: AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
|
||||
val isDynamicTheme by BoolPreferenceDelegate(KEY_DYNAMIC_THEME, defaultValue = false)
|
||||
val isDynamicTheme: Boolean
|
||||
get() = prefs.getBoolean(KEY_DYNAMIC_THEME, false)
|
||||
|
||||
val isAmoledTheme by BoolPreferenceDelegate(KEY_THEME_AMOLED, defaultValue = false)
|
||||
val isAmoledTheme: Boolean
|
||||
get() = prefs.getBoolean(KEY_THEME_AMOLED, false)
|
||||
|
||||
val isToolbarHideWhenScrolling by BoolPreferenceDelegate(KEY_HIDE_TOOLBAR, defaultValue = true)
|
||||
val isToolbarHideWhenScrolling: Boolean
|
||||
get() = prefs.getBoolean(KEY_HIDE_TOOLBAR, true)
|
||||
|
||||
var gridSize by IntPreferenceDelegate(KEY_GRID_SIZE, defaultValue = 100)
|
||||
var gridSize: Int
|
||||
get() = prefs.getInt(KEY_GRID_SIZE, 100)
|
||||
set(value) = prefs.edit { putInt(KEY_GRID_SIZE, value) }
|
||||
|
||||
val readerPageSwitch by StringSetPreferenceDelegate(
|
||||
KEY_READER_SWITCHERS,
|
||||
arraySetOf(PAGE_SWITCH_TAPS)
|
||||
)
|
||||
val readerPageSwitch: Set<String>
|
||||
get() = prefs.getStringSet(KEY_READER_SWITCHERS, null) ?: setOf(PAGE_SWITCH_TAPS)
|
||||
|
||||
var isTrafficWarningEnabled by BoolPreferenceDelegate(KEY_TRAFFIC_WARNING, defaultValue = true)
|
||||
var isTrafficWarningEnabled: Boolean
|
||||
get() = prefs.getBoolean(KEY_TRAFFIC_WARNING, true)
|
||||
set(value) = prefs.edit { putBoolean(KEY_TRAFFIC_WARNING, value) }
|
||||
|
||||
val appUpdateAuto by BoolPreferenceDelegate(KEY_APP_UPDATE_AUTO, defaultValue = true)
|
||||
val appUpdateAuto: Boolean
|
||||
get() = prefs.getBoolean(KEY_APP_UPDATE_AUTO, true)
|
||||
|
||||
var appUpdate by LongPreferenceDelegate(KEY_APP_UPDATE, defaultValue = 0L)
|
||||
var appUpdate: Long
|
||||
get() = prefs.getLong(KEY_APP_UPDATE, 0L)
|
||||
set(value) = prefs.edit { putLong(KEY_APP_UPDATE, value) }
|
||||
|
||||
val trackerNotifications by BoolPreferenceDelegate(
|
||||
KEY_TRACKER_NOTIFICATIONS,
|
||||
defaultValue = true
|
||||
)
|
||||
val trackerNotifications: Boolean
|
||||
get() = prefs.getBoolean(KEY_TRACKER_NOTIFICATIONS, true)
|
||||
|
||||
var notificationSound by StringPreferenceDelegate(
|
||||
KEY_NOTIFICATIONS_SOUND,
|
||||
Settings.System.DEFAULT_NOTIFICATION_URI.toString()
|
||||
)
|
||||
var notificationSound: Uri
|
||||
get() = prefs.getString(KEY_NOTIFICATIONS_SOUND, null)?.toUriOrNull()
|
||||
?: Settings.System.DEFAULT_NOTIFICATION_URI
|
||||
set(value) = prefs.edit { putString(KEY_NOTIFICATIONS_SOUND, value.toString()) }
|
||||
|
||||
val notificationVibrate by BoolPreferenceDelegate(KEY_NOTIFICATIONS_VIBRATE, false)
|
||||
val notificationVibrate: Boolean
|
||||
get() = prefs.getBoolean(KEY_NOTIFICATIONS_VIBRATE, false)
|
||||
|
||||
val notificationLight by BoolPreferenceDelegate(KEY_NOTIFICATIONS_LIGHT, true)
|
||||
val notificationLight: Boolean
|
||||
get() = prefs.getBoolean(KEY_NOTIFICATIONS_LIGHT, true)
|
||||
|
||||
val readerAnimation by BoolPreferenceDelegate(KEY_READER_ANIMATION, false)
|
||||
val readerAnimation: Boolean
|
||||
get() = prefs.getBoolean(KEY_READER_ANIMATION, false)
|
||||
|
||||
val isPreferRtlReader by BoolPreferenceDelegate(KEY_READER_PREFER_RTL, false)
|
||||
val isPreferRtlReader: Boolean
|
||||
get() = prefs.getBoolean(KEY_READER_PREFER_RTL, false)
|
||||
|
||||
var historyGrouping by BoolPreferenceDelegate(KEY_HISTORY_GROUPING, true)
|
||||
var historyGrouping: Boolean
|
||||
get() = prefs.getBoolean(KEY_HISTORY_GROUPING, true)
|
||||
set(value) = prefs.edit { putBoolean(KEY_HISTORY_GROUPING, value) }
|
||||
|
||||
var isHistoryExcludeNsfw by BoolPreferenceDelegate(KEY_HISTORY_EXCLUDE_NSFW, false)
|
||||
val isHistoryExcludeNsfw: Boolean
|
||||
get() = prefs.getBoolean(KEY_HISTORY_EXCLUDE_NSFW, false)
|
||||
|
||||
var chaptersReverse by BoolPreferenceDelegate(KEY_REVERSE_CHAPTERS, false)
|
||||
var chaptersReverse: Boolean
|
||||
get() = prefs.getBoolean(KEY_REVERSE_CHAPTERS, false)
|
||||
set(value) = prefs.edit { putBoolean(KEY_REVERSE_CHAPTERS, value) }
|
||||
|
||||
val zoomMode by EnumPreferenceDelegate(
|
||||
ZoomMode::class.java,
|
||||
KEY_ZOOM_MODE,
|
||||
ZoomMode.FIT_CENTER
|
||||
)
|
||||
val zoomMode: ZoomMode
|
||||
get() = prefs.getString(KEY_ZOOM_MODE, null)?.findEnumValue(ZoomMode.values()) ?: ZoomMode.FIT_CENTER
|
||||
|
||||
val trackSources by StringSetPreferenceDelegate(
|
||||
KEY_TRACK_SOURCES,
|
||||
arraySetOf(TRACK_FAVOURITES, TRACK_HISTORY)
|
||||
)
|
||||
val trackSources: Set<String>
|
||||
get() = prefs.getStringSet(KEY_TRACK_SOURCES, null) ?: arraySetOf(TRACK_FAVOURITES, TRACK_HISTORY)
|
||||
|
||||
var appPassword by NullableStringPreferenceDelegate(KEY_APP_PASSWORD)
|
||||
|
||||
private var sourcesOrderStr by NullableStringPreferenceDelegate(KEY_SOURCES_ORDER)
|
||||
var appPassword: String?
|
||||
get() = prefs.getString(KEY_APP_PASSWORD, null)
|
||||
set(value) = prefs.edit { if (value != null) putString(KEY_APP_PASSWORD, value) else remove(KEY_APP_PASSWORD) }
|
||||
|
||||
var sourcesOrder: List<Int>
|
||||
get() = sourcesOrderStr?.split('|')?.mapNotNull(String::toIntOrNull).orEmpty()
|
||||
set(value) {
|
||||
sourcesOrderStr = value.joinToString("|")
|
||||
get() = prefs.getString(KEY_SOURCES_ORDER, null)
|
||||
?.split('|')
|
||||
?.mapNotNull(String::toIntOrNull)
|
||||
.orEmpty()
|
||||
set(value) = prefs.edit {
|
||||
putString(KEY_SOURCES_ORDER, value.joinToString("|"))
|
||||
}
|
||||
|
||||
var hiddenSources by StringSetPreferenceDelegate(KEY_SOURCES_HIDDEN)
|
||||
var hiddenSources: Set<String>
|
||||
get() = prefs.getStringSet(KEY_SOURCES_HIDDEN, null) ?: emptySet()
|
||||
set(value) = prefs.edit { putStringSet(KEY_SOURCES_HIDDEN, value) }
|
||||
|
||||
val isSourcesSelected: Boolean
|
||||
get() = KEY_SOURCES_HIDDEN in prefs
|
||||
|
||||
val isPagesNumbersEnabled by BoolPreferenceDelegate(KEY_PAGES_NUMBERS, false)
|
||||
val isPagesNumbersEnabled: Boolean
|
||||
get() = prefs.getBoolean(KEY_PAGES_NUMBERS, false)
|
||||
|
||||
fun getStorageDir(context: Context): File? {
|
||||
val value = prefs.getString(KEY_LOCAL_STORAGE, null)?.let {
|
||||
var mangaStorageDir: File?
|
||||
get() = prefs.getString(KEY_LOCAL_STORAGE, null)?.let {
|
||||
File(it)
|
||||
}?.takeIf { it.exists() && it.canWrite() }
|
||||
return value ?: LocalMangaRepository.getFallbackStorageDir(context)
|
||||
}
|
||||
|
||||
fun setStorageDir(context: Context, file: File?) {
|
||||
prefs.edit {
|
||||
if (file == null) {
|
||||
}?.takeIf { it.exists() }
|
||||
set(value) = prefs.edit {
|
||||
if (value == null) {
|
||||
remove(KEY_LOCAL_STORAGE)
|
||||
} else {
|
||||
putString(KEY_LOCAL_STORAGE, file.path)
|
||||
putString(KEY_LOCAL_STORAGE, value.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun dateFormat(format: String? = prefs.getString(KEY_DATE_FORMAT, "")): DateFormat =
|
||||
fun getDateFormat(format: String = prefs.getString(KEY_DATE_FORMAT, "").orEmpty()): DateFormat =
|
||||
when (format) {
|
||||
"" -> DateFormat.getDateInstance(DateFormat.SHORT)
|
||||
else -> SimpleDateFormat(format, Locale.getDefault())
|
||||
}
|
||||
|
||||
@Deprecated("Use observe()")
|
||||
fun getMangaSources(includeHidden: Boolean): List<MangaSource> {
|
||||
val list = MangaSource.values().toMutableList()
|
||||
list.remove(MangaSource.LOCAL)
|
||||
val order = sourcesOrder
|
||||
list.sortBy { x ->
|
||||
val e = order.indexOf(x.ordinal)
|
||||
if (e == -1) order.size + x.ordinal else e
|
||||
}
|
||||
if (!includeHidden) {
|
||||
val hidden = hiddenSources
|
||||
list.removeAll { x -> x.name in hidden }
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
fun subscribe(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
|
||||
prefs.registerOnSharedPreferenceChangeListener(listener)
|
||||
}
|
||||
@@ -157,6 +174,10 @@ class AppSettings private constructor(private val prefs: SharedPreferences) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun <E : Enum<E>> String.findEnumValue(values: Array<E>): E? {
|
||||
return values.find { it.name == this }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val PAGE_SWITCH_TAPS = "taps"
|
||||
@@ -166,7 +187,7 @@ class AppSettings private constructor(private val prefs: SharedPreferences) :
|
||||
const val TRACK_FAVOURITES = "favourites"
|
||||
|
||||
const val KEY_LIST_MODE = "list_mode_2"
|
||||
const val KEY_APP_SECTION = "app_section"
|
||||
const val KEY_APP_SECTION = "app_section_2"
|
||||
const val KEY_THEME = "theme"
|
||||
const val KEY_DYNAMIC_THEME = "dynamic_theme"
|
||||
const val KEY_THEME_AMOLED = "amoled_theme"
|
||||
@@ -210,14 +231,15 @@ class AppSettings private constructor(private val prefs: SharedPreferences) :
|
||||
const val KEY_APP_TRANSLATION = "about_app_translation"
|
||||
const val KEY_APP_GRATITUDES = "about_gratitudes"
|
||||
const val KEY_FEEDBACK_4PDA = "about_feedback_4pda"
|
||||
const val KEY_FEEDBACK_DISCORD = "about_feedback_discord"
|
||||
const val KEY_FEEDBACK_GITHUB = "about_feedback_github"
|
||||
const val KEY_SUPPORT_DEVELOPER = "about_support_developer"
|
||||
|
||||
val isDynamicColorAvailable: Boolean
|
||||
get() = DynamicColors.isDynamicColorAvailable() ||
|
||||
(isSamsung && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||
(isSamsung && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||
|
||||
private val isSamsung
|
||||
get() = Build.MANUFACTURER.equals("samsung", ignoreCase = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,15 @@
|
||||
package org.koitharu.kotatsu.core.prefs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import org.koitharu.kotatsu.utils.delegates.prefs.LongPreferenceDelegate
|
||||
import androidx.core.content.edit
|
||||
|
||||
class AppWidgetConfig private constructor(
|
||||
private val prefs: SharedPreferences,
|
||||
val widgetId: Int
|
||||
) : SharedPreferences by prefs {
|
||||
private const val CATEGORY_ID = "cat_id"
|
||||
|
||||
var categoryId by LongPreferenceDelegate(CATEGORY_ID, 0L)
|
||||
class AppWidgetConfig(context: Context, val widgetId: Int) {
|
||||
|
||||
companion object {
|
||||
private val prefs = context.getSharedPreferences("appwidget_$widgetId", Context.MODE_PRIVATE)
|
||||
|
||||
private const val CATEGORY_ID = "cat_id"
|
||||
|
||||
fun getInstance(context: Context, widgetId: Int) = AppWidgetConfig(
|
||||
context.getSharedPreferences(
|
||||
"appwidget_$widgetId",
|
||||
Context.MODE_PRIVATE
|
||||
), widgetId
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
var categoryId: Long
|
||||
get() = prefs.getLong(CATEGORY_ID, 0L)
|
||||
set(value) = prefs.edit { putLong(CATEGORY_ID, value) }
|
||||
}
|
||||
|
||||
@@ -10,4 +10,4 @@ enum class ReaderMode(val id: Int) {
|
||||
|
||||
fun valueOf(id: Int) = values().firstOrNull { it.id == id }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.ui
|
||||
|
||||
import coil.ComponentRegistry
|
||||
import coil.ImageLoader
|
||||
import coil.util.CoilUtils
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.dsl.module
|
||||
@@ -11,8 +12,11 @@ import org.koitharu.kotatsu.local.data.CbzFetcher
|
||||
val uiModule
|
||||
get() = module {
|
||||
single {
|
||||
val httpClient = get<OkHttpClient>().newBuilder()
|
||||
.cache(CoilUtils.createDefaultCache(androidContext()))
|
||||
.build()
|
||||
ImageLoader.Builder(androidContext())
|
||||
.okHttpClient(get<OkHttpClient>())
|
||||
.okHttpClient(httpClient)
|
||||
.componentRegistry(
|
||||
ComponentRegistry.Builder()
|
||||
.add(CbzFetcher())
|
||||
|
||||
@@ -47,7 +47,7 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
|
||||
TabLayoutMediator.TabConfigurationStrategy {
|
||||
|
||||
private val viewModel by viewModel<DetailsViewModel> {
|
||||
parametersOf(MangaIntent.from(intent))
|
||||
parametersOf(MangaIntent(intent))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -280,4 +280,4 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
|
||||
.putExtra(MangaIntent.KEY_ID, mangaId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,7 @@ import androidx.core.view.updatePadding
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
import coil.util.CoilUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
||||
import org.koitharu.kotatsu.R
|
||||
@@ -33,7 +31,7 @@ import org.koitharu.kotatsu.image.ui.ImageActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
import org.koitharu.kotatsu.search.ui.SearchActivity
|
||||
import org.koitharu.kotatsu.utils.FileSizeUtils
|
||||
import org.koitharu.kotatsu.utils.FileSize
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
|
||||
class DetailsFragment : BaseFragment<FragmentDetailsBinding>(), View.OnClickListener,
|
||||
@@ -114,10 +112,8 @@ class DetailsFragment : BaseFragment<FragmentDetailsBinding>(), View.OnClickList
|
||||
val file = manga.url.toUri().toFileOrNull()
|
||||
if (file != null) {
|
||||
viewLifecycleScope.launch {
|
||||
val size = withContext(Dispatchers.IO) {
|
||||
file.length()
|
||||
}
|
||||
textViewSize.text = FileSizeUtils.formatBytes(requireContext(), size)
|
||||
val size = file.computeSize()
|
||||
textViewSize.text = FileSize.BYTES.format(requireContext(), size)
|
||||
}
|
||||
sizeContainer.isVisible = true
|
||||
} else {
|
||||
@@ -270,4 +266,4 @@ class DetailsFragment : BaseFragment<FragmentDetailsBinding>(), View.OnClickList
|
||||
.lifecycle(viewLifecycleOwner)
|
||||
.enqueueWith(coil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ class DetailsViewModel(
|
||||
branch: String?,
|
||||
): List<ChapterListItem> {
|
||||
val result = ArrayList<ChapterListItem>(chapters.size)
|
||||
val dateFormat = settings.dateFormat()
|
||||
val dateFormat = settings.getDateFormat()
|
||||
val currentIndex = chapters.indexOfFirst { it.id == currentId }
|
||||
val firstNewIndex = chapters.size - newCount
|
||||
val downloadedIds = downloadedChapters?.mapToSet { it.id }
|
||||
@@ -196,7 +196,7 @@ class DetailsViewModel(
|
||||
val result = ArrayList<ChapterListItem>(sourceChapters.size)
|
||||
val currentIndex = sourceChapters.indexOfFirst { it.id == currentId }
|
||||
val firstNewIndex = sourceChapters.size - newCount
|
||||
val dateFormat = settings.dateFormat()
|
||||
val dateFormat = settings.getDateFormat()
|
||||
for (i in sourceChapters.indices) {
|
||||
val chapter = sourceChapters[i]
|
||||
if (chapter.branch != branch) {
|
||||
@@ -253,4 +253,4 @@ class DetailsViewModel(
|
||||
}
|
||||
return groups.maxByOrNull { it.value.size }?.key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.local.data.MangaZip
|
||||
import org.koitharu.kotatsu.local.data.PagesCache
|
||||
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import org.koitharu.kotatsu.utils.ext.await
|
||||
import org.koitharu.kotatsu.utils.ext.deleteAwait
|
||||
import org.koitharu.kotatsu.utils.ext.waitForNetwork
|
||||
@@ -30,7 +28,6 @@ import java.io.File
|
||||
|
||||
class DownloadManager(
|
||||
private val context: Context,
|
||||
private val settings: AppSettings,
|
||||
private val imageLoader: ImageLoader,
|
||||
private val okHttp: OkHttpClient,
|
||||
private val cache: PagesCache,
|
||||
@@ -50,7 +47,7 @@ class DownloadManager(
|
||||
fun downloadManga(manga: Manga, chaptersIds: Set<Long>?, startId: Int) = flow<State> {
|
||||
emit(State.Preparing(startId, manga, null))
|
||||
var cover: Drawable? = null
|
||||
val destination = settings.getStorageDir(context)
|
||||
val destination = localMangaRepository.getOutputDir()
|
||||
checkNotNull(destination) { context.getString(R.string.cannot_find_available_storage) }
|
||||
var output: MangaZip? = null
|
||||
try {
|
||||
@@ -136,7 +133,7 @@ class DownloadManager(
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.header(CommonHeaders.REFERER, referer)
|
||||
.cacheControl(CacheUtils.CONTROL_DISABLED)
|
||||
.cacheControl(CommonHeaders.CACHE_CONTROL_DISABLED)
|
||||
.get()
|
||||
.build()
|
||||
val call = okHttp.newCall(request)
|
||||
@@ -236,4 +233,4 @@ class DownloadManager(
|
||||
private const val DOWNLOAD_ERROR_DELAY = 500L
|
||||
private const val TEMP_PAGE_FILE = "page.tmp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class DownloadService : BaseService() {
|
||||
notificationManager = NotificationManagerCompat.from(this)
|
||||
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager)
|
||||
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kotatsu:downloading")
|
||||
downloadManager = DownloadManager(this, get(), get(), get(), get(), get())
|
||||
downloadManager = DownloadManager(this, get(), get(), get(), get())
|
||||
DownloadNotification.createChannel(this)
|
||||
registerReceiver(controlReceiver, IntentFilter(ACTION_DOWNLOAD_CANCEL))
|
||||
}
|
||||
|
||||
@@ -6,13 +6,15 @@ import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.local.ui.LocalListViewModel
|
||||
|
||||
val localModule
|
||||
get() = module {
|
||||
|
||||
single { LocalMangaRepository(androidContext()) }
|
||||
single { LocalStorageManager(androidContext(), get()) }
|
||||
single { LocalMangaRepository(get()) }
|
||||
factory<MangaRepository>(named(MangaSource.LOCAL)) { get<LocalMangaRepository>() }
|
||||
|
||||
viewModel { LocalListViewModel(get(), get(), get(), get()) }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.koitharu.kotatsu.local.data
|
||||
|
||||
enum class Cache(val dir: String) {
|
||||
enum class CacheDir(val dir: String) {
|
||||
|
||||
THUMBS("image_cache"),
|
||||
PAGES("pages");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package org.koitharu.kotatsu.local.data
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.os.StatFs
|
||||
import androidx.annotation.WorkerThread
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.Cache
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.utils.ext.computeSize
|
||||
import org.koitharu.kotatsu.utils.ext.getStorageName
|
||||
import java.io.File
|
||||
|
||||
private const val DIR_NAME = "manga"
|
||||
private const val CACHE_DISK_PERCENTAGE = 0.02
|
||||
private const val CACHE_SIZE_MIN: Long = 10 * 1024 * 1024 // 10MB
|
||||
private const val CACHE_SIZE_MAX: Long = 250 * 1024 * 1024 // 250MB
|
||||
|
||||
class LocalStorageManager(
|
||||
private val context: Context,
|
||||
private val settings: AppSettings,
|
||||
) {
|
||||
|
||||
val contentResolver: ContentResolver
|
||||
get() = context.contentResolver
|
||||
|
||||
fun createHttpCache(): Cache {
|
||||
val directory = File(context.externalCacheDir ?: context.cacheDir, "http")
|
||||
directory.mkdirs()
|
||||
val maxSize = calculateDiskCacheSize(directory)
|
||||
return Cache(directory, maxSize)
|
||||
}
|
||||
|
||||
suspend fun computeCacheSize(cache: CacheDir) = withContext(Dispatchers.IO) {
|
||||
getCacheDirs(cache.dir).sumOf { it.computeSize() }
|
||||
}
|
||||
|
||||
suspend fun clearCache(cache: CacheDir) = runInterruptible(Dispatchers.IO) {
|
||||
getCacheDirs(cache.dir).forEach { it.deleteRecursively() }
|
||||
}
|
||||
|
||||
suspend fun getReadableDirs(): List<File> = runInterruptible(Dispatchers.IO) {
|
||||
getConfiguredStorageDirs()
|
||||
.filter { it.isReadable() }
|
||||
}
|
||||
|
||||
suspend fun getWriteableDirs(): List<File> = runInterruptible(Dispatchers.IO) {
|
||||
getConfiguredStorageDirs()
|
||||
.filter { it.isWriteable() }
|
||||
}
|
||||
|
||||
suspend fun getDefaultWriteableDir(): File? = runInterruptible(Dispatchers.IO) {
|
||||
val preferredDir = settings.mangaStorageDir?.takeIf { it.isWriteable() }
|
||||
preferredDir ?: getFallbackStorageDir()?.takeIf { it.isWriteable() }
|
||||
}
|
||||
|
||||
fun getStorageDisplayName(file: File) = file.getStorageName(context)
|
||||
|
||||
@WorkerThread
|
||||
private fun getConfiguredStorageDirs(): MutableSet<File> {
|
||||
val set = getAvailableStorageDirs()
|
||||
settings.mangaStorageDir?.let {
|
||||
set.add(it)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getAvailableStorageDirs(): MutableSet<File> {
|
||||
val result = LinkedHashSet<File>()
|
||||
result += File(context.filesDir, DIR_NAME)
|
||||
result += context.getExternalFilesDirs(DIR_NAME)
|
||||
result.retainAll { it.exists() || it.mkdirs() }
|
||||
return result
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getFallbackStorageDir(): File? {
|
||||
return context.getExternalFilesDir(DIR_NAME) ?: File(context.filesDir, DIR_NAME).takeIf {
|
||||
it.exists() || it.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getCacheDirs(subDir: String): MutableSet<File> {
|
||||
val result = LinkedHashSet<File>()
|
||||
result += File(context.cacheDir, subDir)
|
||||
context.externalCacheDirs.mapTo(result) {
|
||||
File(it, subDir)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun calculateDiskCacheSize(cacheDirectory: File): Long {
|
||||
return try {
|
||||
val cacheDir = StatFs(cacheDirectory.absolutePath)
|
||||
val size = CACHE_DISK_PERCENTAGE * cacheDir.blockCountLong * cacheDir.blockSizeLong
|
||||
return size.toLong().coerceIn(CACHE_SIZE_MIN, CACHE_SIZE_MAX)
|
||||
} catch (_: Exception) {
|
||||
CACHE_SIZE_MIN
|
||||
}
|
||||
}
|
||||
|
||||
private fun File.isReadable() = runCatching {
|
||||
canRead()
|
||||
}.getOrDefault(false)
|
||||
|
||||
private fun File.isWriteable() = runCatching {
|
||||
canWrite()
|
||||
}.getOrDefault(false)
|
||||
}
|
||||
@@ -16,7 +16,7 @@ class MangaZip(val file: File) {
|
||||
private var index = MangaIndex(null)
|
||||
|
||||
suspend fun prepare(manga: Manga) {
|
||||
writableCbz.prepare()
|
||||
writableCbz.prepare(overwrite = true)
|
||||
index = MangaIndex(writableCbz[INDEX_ENTRY].takeIfReadable()?.readText())
|
||||
index.setMangaInfo(manga, append = true)
|
||||
}
|
||||
|
||||
@@ -2,35 +2,25 @@ package org.koitharu.kotatsu.local.data
|
||||
|
||||
import android.content.Context
|
||||
import com.tomclaw.cache.DiskLruCache
|
||||
import org.koitharu.kotatsu.utils.FileSizeUtils
|
||||
import org.koitharu.kotatsu.utils.FileSize
|
||||
import org.koitharu.kotatsu.utils.ext.longHashCode
|
||||
import org.koitharu.kotatsu.utils.ext.subdir
|
||||
import org.koitharu.kotatsu.utils.ext.takeIfReadable
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
class PagesCache(context: Context) {
|
||||
|
||||
private val cacheDir = context.externalCacheDir ?: context.cacheDir
|
||||
private val lruCache = DiskLruCache.create(
|
||||
cacheDir.subdir(Cache.PAGES.dir),
|
||||
FileSizeUtils.mbToBytes(200)
|
||||
cacheDir.subdir(CacheDir.PAGES.dir),
|
||||
FileSize.MEGABYTES.convert(200, FileSize.BYTES),
|
||||
)
|
||||
|
||||
operator fun get(url: String): File? {
|
||||
return lruCache.get(url)?.takeIfReadable()
|
||||
}
|
||||
|
||||
@Deprecated("Useless lambda")
|
||||
fun put(url: String, writer: (OutputStream) -> Unit): File {
|
||||
val file = File(cacheDir, url.longHashCode().toString())
|
||||
file.outputStream().use(writer)
|
||||
val res = lruCache.put(url, file)
|
||||
file.delete()
|
||||
return res
|
||||
}
|
||||
|
||||
fun put(url: String, inputStream: InputStream): File {
|
||||
val file = File(cacheDir, url.longHashCode().toString())
|
||||
file.outputStream().use { out ->
|
||||
@@ -40,4 +30,4 @@ class PagesCache(context: Context) {
|
||||
file.delete()
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,13 @@ class WritableCbzFile(private val file: File) {
|
||||
|
||||
private val dir = File(file.parentFile, file.nameWithoutExtension)
|
||||
|
||||
suspend fun prepare() = withContext(Dispatchers.IO) {
|
||||
check(dir.list().isNullOrEmpty()) {
|
||||
"Dir ${dir.name} is not empty"
|
||||
suspend fun prepare(overwrite: Boolean) = withContext(Dispatchers.IO) {
|
||||
if (!dir.list().isNullOrEmpty()) {
|
||||
if (overwrite) {
|
||||
dir.deleteRecursively()
|
||||
} else {
|
||||
throw IllegalStateException("Dir ${dir.name} is not empty")
|
||||
}
|
||||
}
|
||||
if (!dir.exists()) {
|
||||
dir.mkdir()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.koitharu.kotatsu.local.domain
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.collection.ArraySet
|
||||
@@ -10,19 +9,22 @@ import androidx.core.net.toUri
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
|
||||
import org.koitharu.kotatsu.core.model.*
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.local.data.CbzFilter
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
import org.koitharu.kotatsu.local.data.MangaIndex
|
||||
import org.koitharu.kotatsu.local.data.MangaZip
|
||||
import org.koitharu.kotatsu.utils.AlphanumComparator
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
class LocalMangaRepository(private val context: Context) : MangaRepository {
|
||||
class LocalMangaRepository(private val storageManager: LocalStorageManager) : MangaRepository {
|
||||
|
||||
override val source = MangaSource.LOCAL
|
||||
private val filenameFilter = CbzFilter()
|
||||
@@ -149,24 +151,26 @@ class LocalMangaRepository(private val context: Context) : MangaRepository {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun findSavedManga(remoteManga: Manga): Manga? = runInterruptible(Dispatchers.IO) {
|
||||
suspend fun findSavedManga(remoteManga: Manga): Manga? {
|
||||
val files = getAllFiles()
|
||||
for (file in files) {
|
||||
val index = ZipFile(file).use { zip ->
|
||||
val entry = zip.getEntry(MangaZip.INDEX_ENTRY)
|
||||
entry?.let(zip::readText)?.let(::MangaIndex)
|
||||
} ?: continue
|
||||
val info = index.getMangaInfo() ?: continue
|
||||
if (info.id == remoteManga.id) {
|
||||
val fileUri = file.toUri().toString()
|
||||
return@runInterruptible info.copy(
|
||||
source = MangaSource.LOCAL,
|
||||
url = fileUri,
|
||||
chapters = info.chapters?.map { c -> c.copy(url = fileUri) }
|
||||
)
|
||||
return runInterruptible(Dispatchers.IO) {
|
||||
for (file in files) {
|
||||
val index = ZipFile(file).use { zip ->
|
||||
val entry = zip.getEntry(MangaZip.INDEX_ENTRY)
|
||||
entry?.let(zip::readText)?.let(::MangaIndex)
|
||||
} ?: continue
|
||||
val info = index.getMangaInfo() ?: continue
|
||||
if (info.id == remoteManga.id) {
|
||||
val fileUri = file.toUri().toString()
|
||||
return@runInterruptible info.copy(
|
||||
source = MangaSource.LOCAL,
|
||||
url = fileUri,
|
||||
chapters = info.chapters?.map { c -> c.copy(url = fileUri) }
|
||||
)
|
||||
}
|
||||
}
|
||||
null
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
private fun zipUri(file: File, entryName: String) =
|
||||
@@ -193,32 +197,38 @@ class LocalMangaRepository(private val context: Context) : MangaRepository {
|
||||
|
||||
override suspend fun getTags() = emptySet<MangaTag>()
|
||||
|
||||
private fun getAllFiles() = getAvailableStorageDirs(context).flatMap { dir ->
|
||||
suspend fun import(uri: Uri) {
|
||||
val contentResolver = storageManager.contentResolver
|
||||
withContext(Dispatchers.IO) {
|
||||
val name = contentResolver.resolveName(uri)
|
||||
?: throw IOException("Cannot fetch name from uri: $uri")
|
||||
if (!isFileSupported(name)) {
|
||||
throw UnsupportedFileException("Unsupported file on $uri")
|
||||
}
|
||||
val dest = File(
|
||||
getOutputDir() ?: throw IOException("External files dir unavailable"),
|
||||
name,
|
||||
)
|
||||
runInterruptible {
|
||||
contentResolver.openInputStream(uri)?.use { source ->
|
||||
dest.outputStream().use { output ->
|
||||
source.copyTo(output)
|
||||
}
|
||||
}
|
||||
} ?: throw IOException("Cannot open input stream: $uri")
|
||||
}
|
||||
}
|
||||
|
||||
fun isFileSupported(name: String): Boolean {
|
||||
val ext = name.substringAfterLast('.').lowercase(Locale.ROOT)
|
||||
return ext == "cbz" || ext == "zip"
|
||||
}
|
||||
|
||||
suspend fun getOutputDir(): File? {
|
||||
return storageManager.getDefaultWriteableDir()
|
||||
}
|
||||
|
||||
private suspend fun getAllFiles() = storageManager.getReadableDirs().flatMap { dir ->
|
||||
dir.listFiles(filenameFilter)?.toList().orEmpty()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val DIR_NAME = "manga"
|
||||
|
||||
fun isFileSupported(name: String): Boolean {
|
||||
val ext = name.substringAfterLast('.').lowercase(Locale.ROOT)
|
||||
return ext == "cbz" || ext == "zip"
|
||||
}
|
||||
|
||||
fun getAvailableStorageDirs(context: Context): List<File> {
|
||||
val result = ArrayList<File?>(5)
|
||||
result += File(context.filesDir, DIR_NAME)
|
||||
result += context.getExternalFilesDirs(DIR_NAME)
|
||||
return result.filterNotNull()
|
||||
.distinctBy { it.canonicalPath }
|
||||
.filter { it.exists() || it.mkdir() }
|
||||
}
|
||||
|
||||
fun getFallbackStorageDir(context: Context): File? {
|
||||
return context.getExternalFilesDir(DIR_NAME) ?: context.filesDir.sub(DIR_NAME).takeIf {
|
||||
(it.exists() || it.mkdir()) && it.canWrite()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,16 @@ import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.download.ui.service.DownloadService
|
||||
import org.koitharu.kotatsu.list.ui.MangaListFragment
|
||||
import org.koitharu.kotatsu.utils.ext.ellipsize
|
||||
import org.koitharu.kotatsu.utils.progress.Progress
|
||||
|
||||
class LocalListFragment : MangaListFragment(), ActivityResultCallback<Uri?> {
|
||||
class LocalListFragment : MangaListFragment(), ActivityResultCallback<List<@JvmSuppressWildcards Uri>> {
|
||||
|
||||
override val viewModel by viewModel<LocalListViewModel>()
|
||||
private val importCall = registerForActivityResult(
|
||||
ActivityResultContracts.OpenDocument(),
|
||||
ActivityResultContracts.OpenMultipleDocuments(),
|
||||
this
|
||||
)
|
||||
private var importSnackbar: Snackbar? = null
|
||||
private val downloadReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (intent?.action == DownloadService.ACTION_DOWNLOAD_COMPLETE) {
|
||||
@@ -45,6 +47,12 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback<Uri?> {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
viewModel.onMangaRemoved.observe(viewLifecycleOwner, ::onItemRemoved)
|
||||
viewModel.importProgress.observe(viewLifecycleOwner, ::onImportProgressChanged)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
importSnackbar = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
@@ -84,10 +92,9 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback<Uri?> {
|
||||
return context?.getString(R.string.local_storage)
|
||||
}
|
||||
|
||||
override fun onActivityResult(result: Uri?) {
|
||||
if (result != null) {
|
||||
viewModel.importFile(context?.applicationContext ?: return, result)
|
||||
}
|
||||
override fun onActivityResult(result: List<@JvmSuppressWildcards Uri>) {
|
||||
if (result.isEmpty()) return
|
||||
viewModel.importFiles(result)
|
||||
}
|
||||
|
||||
override fun onCreatePopupMenu(inflater: MenuInflater, menu: Menu, data: Manga) {
|
||||
@@ -121,6 +128,25 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback<Uri?> {
|
||||
).show()
|
||||
}
|
||||
|
||||
private fun onImportProgressChanged(progress: Progress?) {
|
||||
if (progress == null) {
|
||||
importSnackbar?.dismiss()
|
||||
importSnackbar = null
|
||||
return
|
||||
}
|
||||
val summaryText = getString(
|
||||
R.string.importing_progress,
|
||||
progress.value + 1,
|
||||
progress.total,
|
||||
)
|
||||
importSnackbar?.setText(summaryText) ?: run {
|
||||
val snackbar =
|
||||
Snackbar.make(binding.recyclerView, summaryText, Snackbar.LENGTH_INDEFINITE)
|
||||
importSnackbar = snackbar
|
||||
snackbar.show()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance() = LocalListFragment()
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package org.koitharu.kotatsu.local.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.os.ShortcutsRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
@@ -19,21 +18,22 @@ import org.koitharu.kotatsu.list.ui.model.*
|
||||
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.resolveName
|
||||
import java.io.File
|
||||
import org.koitharu.kotatsu.utils.progress.Progress
|
||||
import java.io.IOException
|
||||
|
||||
class LocalListViewModel(
|
||||
private val repository: LocalMangaRepository,
|
||||
private val historyRepository: HistoryRepository,
|
||||
private val settings: AppSettings,
|
||||
settings: AppSettings,
|
||||
private val shortcutsRepository: ShortcutsRepository,
|
||||
) : MangaListViewModel(settings) {
|
||||
|
||||
val onMangaRemoved = SingleLiveEvent<Manga>()
|
||||
val importProgress = MutableLiveData<Progress?>(null)
|
||||
private val listError = MutableStateFlow<Throwable?>(null)
|
||||
private val mangaList = MutableStateFlow<List<Manga>?>(null)
|
||||
private val headerModel = ListHeader(null, R.string.local_storage)
|
||||
private var importJob: Job? = null
|
||||
|
||||
override val content = combine(
|
||||
mangaList,
|
||||
@@ -60,37 +60,23 @@ class LocalListViewModel(
|
||||
|
||||
override fun onRefresh() {
|
||||
launchLoadingJob(Dispatchers.Default) {
|
||||
try {
|
||||
listError.value = null
|
||||
mangaList.value = repository.getList2(0)
|
||||
} catch (e: Throwable) {
|
||||
listError.value = e
|
||||
}
|
||||
doRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRetry() = onRefresh()
|
||||
|
||||
fun importFile(context: Context, uri: Uri) {
|
||||
launchLoadingJob {
|
||||
val contentResolver = context.contentResolver
|
||||
withContext(Dispatchers.IO) {
|
||||
val name = contentResolver.resolveName(uri)
|
||||
?: throw IOException("Cannot fetch name from uri: $uri")
|
||||
if (!LocalMangaRepository.isFileSupported(name)) {
|
||||
throw UnsupportedFileException("Unsupported file on $uri")
|
||||
}
|
||||
val dest = settings.getStorageDir(context)?.let { File(it, name) }
|
||||
?: throw IOException("External files dir unavailable")
|
||||
runInterruptible {
|
||||
contentResolver.openInputStream(uri)?.use { source ->
|
||||
dest.outputStream().use { output ->
|
||||
source.copyTo(output)
|
||||
}
|
||||
}
|
||||
} ?: throw IOException("Cannot open input stream: $uri")
|
||||
fun importFiles(uris: List<Uri>) {
|
||||
val previousJob = importJob
|
||||
importJob = launchJob(Dispatchers.Default) {
|
||||
previousJob?.join()
|
||||
importProgress.postValue(Progress(0, uris.size))
|
||||
for ((i, uri) in uris.withIndex()) {
|
||||
repository.import(uri)
|
||||
importProgress.postValue(Progress(i + 1, uris.size))
|
||||
doRefresh()
|
||||
}
|
||||
onRefresh()
|
||||
importProgress.postValue(null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,4 +94,13 @@ class LocalListViewModel(
|
||||
onMangaRemoved.call(manga)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun doRefresh() {
|
||||
try {
|
||||
listError.value = null
|
||||
mangaList.value = repository.getList2(0)
|
||||
} catch (e: Throwable) {
|
||||
listError.value = e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import org.koitharu.kotatsu.base.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
@@ -25,7 +24,7 @@ class MainViewModel(
|
||||
val remoteSources = settings.observe()
|
||||
.filter { it == AppSettings.KEY_SOURCES_ORDER || it == AppSettings.KEY_SOURCES_HIDDEN }
|
||||
.onStart { emit("") }
|
||||
.map { MangaProviderFactory.getSources(settings, includeHidden = false) }
|
||||
.map { settings.getMangaSources(includeHidden = false) }
|
||||
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
fun openLastReader() {
|
||||
@@ -35,4 +34,4 @@ class MainViewModel(
|
||||
onOpenReader.call(manga)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import org.koitharu.kotatsu.core.model.MangaPage
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.local.data.PagesCache
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import org.koitharu.kotatsu.utils.ext.await
|
||||
import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf
|
||||
import java.io.File
|
||||
@@ -70,7 +69,7 @@ class PageLoader(
|
||||
.get()
|
||||
.header(CommonHeaders.REFERER, page.referer)
|
||||
.header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8")
|
||||
.cacheControl(CacheUtils.CONTROL_DISABLED)
|
||||
.cacheControl(CommonHeaders.CACHE_CONTROL_DISABLED)
|
||||
.build()
|
||||
okHttp.newCall(request).await().use { response ->
|
||||
check(response.isSuccessful) {
|
||||
@@ -103,4 +102,4 @@ class PageLoader(
|
||||
}
|
||||
|
||||
private companion object Lock
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class ChaptersDialog : AlertDialogFragment<DialogChaptersBinding>(),
|
||||
}
|
||||
val currentId = arguments?.getLong(ARG_CURRENT_ID, 0L) ?: 0L
|
||||
val currentPosition = chapters.indexOfFirst { it.id == currentId }
|
||||
val dateFormat = get<AppSettings>().dateFormat()
|
||||
val dateFormat = get<AppSettings>().getDateFormat()
|
||||
binding.recyclerViewChapters.adapter = ChaptersAdapter(this).apply {
|
||||
setItems(chapters.mapIndexed { index, chapter ->
|
||||
chapter.toListItem(
|
||||
@@ -96,4 +96,4 @@ class ChaptersDialog : AlertDialogFragment<DialogChaptersBinding>(),
|
||||
putLong(ARG_CURRENT_ID, currentId)
|
||||
}.show(fm, TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class ReaderActivity : BaseFullscreenActivity<ActivityReaderBinding>(),
|
||||
ActivityResultCallback<Boolean>, ReaderControlDelegate.OnInteractionListener {
|
||||
|
||||
private val viewModel by viewModel<ReaderViewModel> {
|
||||
parametersOf(MangaIntent.from(intent), intent?.getParcelableExtra<ReaderState>(EXTRA_STATE))
|
||||
parametersOf(MangaIntent(intent), intent?.getParcelableExtra<ReaderState>(EXTRA_STATE))
|
||||
}
|
||||
|
||||
private lateinit var touchHelper: GridTouchHelper
|
||||
@@ -371,4 +371,4 @@ class ReaderActivity : BaseFullscreenActivity<ActivityReaderBinding>(),
|
||||
.putExtra(EXTRA_STATE, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ class ReaderViewModel(
|
||||
val downloadId = downloadManagerHelper.downloadPage(page, pageUrl)
|
||||
val uri = downloadManagerHelper.awaitDownload(downloadId)
|
||||
onPageSaved.postCall(uri)
|
||||
} catch (e: CancellationException) {
|
||||
} catch (_: CancellationException) {
|
||||
} catch (e: Exception) {
|
||||
onPageSaved.postCall(null)
|
||||
}
|
||||
@@ -267,4 +267,4 @@ class ReaderViewModel(
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class RemoteListViewModel(
|
||||
when {
|
||||
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
||||
list == null -> listOf(LoadingState)
|
||||
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_book_cross, R.string.nothing_found, R.string._empty))
|
||||
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_book_cross, R.string.nothing_found, R.string.empty))
|
||||
else -> {
|
||||
val result = ArrayList<ListModel>(list.size + 3)
|
||||
result += headerModel
|
||||
@@ -128,4 +128,4 @@ class RemoteListViewModel(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koitharu.kotatsu.base.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
@@ -27,7 +26,7 @@ class MangaSearchRepository(
|
||||
) {
|
||||
|
||||
fun globalSearch(query: String, concurrency: Int = DEFAULT_CONCURRENCY): Flow<Manga> =
|
||||
MangaProviderFactory.getSources(settings, includeHidden = false).asFlow()
|
||||
settings.getMangaSources(includeHidden = false).asFlow()
|
||||
.flatMapMerge(concurrency) { source ->
|
||||
runCatching {
|
||||
MangaRepository(source).getList2(
|
||||
@@ -128,4 +127,4 @@ class MangaSearchRepository(
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.koitharu.kotatsu.core.github.AppVersion
|
||||
import org.koitharu.kotatsu.core.github.GithubRepository
|
||||
import org.koitharu.kotatsu.core.github.VersionId
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.utils.FileSizeUtils
|
||||
import org.koitharu.kotatsu.utils.FileSize
|
||||
import org.koitharu.kotatsu.utils.ext.byte2HexFormatted
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStream
|
||||
@@ -85,7 +85,7 @@ class AppUpdateChecker(private val activity: ComponentActivity) {
|
||||
append(
|
||||
activity.getString(
|
||||
R.string.size_s,
|
||||
FileSizeUtils.formatBytes(activity, version.apkSize)
|
||||
FileSize.BYTES.format(activity, version.apkSize),
|
||||
)
|
||||
)
|
||||
appendLine()
|
||||
@@ -144,4 +144,4 @@ class AppUpdateChecker(private val activity: ComponentActivity) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,20 +5,18 @@ import android.view.View
|
||||
import androidx.preference.Preference
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.get
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment
|
||||
import org.koitharu.kotatsu.core.network.AndroidCookieJar
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.local.data.Cache
|
||||
import org.koitharu.kotatsu.local.data.CacheDir
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
import org.koitharu.kotatsu.search.domain.MangaSearchRepository
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import org.koitharu.kotatsu.utils.FileSizeUtils
|
||||
import org.koitharu.kotatsu.utils.FileSize
|
||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||
|
||||
@@ -26,6 +24,7 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
|
||||
private val trackerRepo by inject<TrackingRepository>(mode = LazyThreadSafetyMode.NONE)
|
||||
private val searchRepository by inject<MangaSearchRepository>(mode = LazyThreadSafetyMode.NONE)
|
||||
private val storageManager by inject<LocalStorageManager>(mode = LazyThreadSafetyMode.NONE)
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_history)
|
||||
@@ -33,22 +32,8 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
findPreference<Preference>(AppSettings.KEY_PAGES_CACHE_CLEAR)?.let { pref ->
|
||||
viewLifecycleScope.launchWhenResumed {
|
||||
val size = withContext(Dispatchers.IO) {
|
||||
CacheUtils.computeCacheSize(pref.context, Cache.PAGES.dir)
|
||||
}
|
||||
pref.summary = FileSizeUtils.formatBytes(pref.context, size)
|
||||
}
|
||||
}
|
||||
findPreference<Preference>(AppSettings.KEY_THUMBS_CACHE_CLEAR)?.let { pref ->
|
||||
viewLifecycleScope.launchWhenResumed {
|
||||
val size = withContext(Dispatchers.IO) {
|
||||
CacheUtils.computeCacheSize(pref.context, Cache.THUMBS.dir)
|
||||
}
|
||||
pref.summary = FileSizeUtils.formatBytes(pref.context, size)
|
||||
}
|
||||
}
|
||||
findPreference<Preference>(AppSettings.KEY_PAGES_CACHE_CLEAR)?.bindSummaryToCacheSize(CacheDir.PAGES)
|
||||
findPreference<Preference>(AppSettings.KEY_THUMBS_CACHE_CLEAR)?.bindSummaryToCacheSize(CacheDir.THUMBS)
|
||||
findPreference<Preference>(AppSettings.KEY_SEARCH_HISTORY_CLEAR)?.let { pref ->
|
||||
viewLifecycleScope.launchWhenResumed {
|
||||
val items = searchRepository.getSearchHistoryCount()
|
||||
@@ -68,11 +53,11 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||
return when (preference.key) {
|
||||
AppSettings.KEY_PAGES_CACHE_CLEAR -> {
|
||||
clearCache(preference, Cache.PAGES)
|
||||
clearCache(preference, CacheDir.PAGES)
|
||||
true
|
||||
}
|
||||
AppSettings.KEY_THUMBS_CACHE_CLEAR -> {
|
||||
clearCache(preference, Cache.THUMBS)
|
||||
clearCache(preference, CacheDir.THUMBS)
|
||||
true
|
||||
}
|
||||
AppSettings.KEY_COOKIES_CLEAR -> {
|
||||
@@ -100,16 +85,14 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearCache(preference: Preference, cache: Cache) {
|
||||
private fun clearCache(preference: Preference, cache: CacheDir) {
|
||||
val ctx = preference.context.applicationContext
|
||||
viewLifecycleScope.launch {
|
||||
try {
|
||||
preference.isEnabled = false
|
||||
val size = withContext(Dispatchers.IO) {
|
||||
CacheUtils.clearCache(ctx, cache.dir)
|
||||
CacheUtils.computeCacheSize(ctx, cache.dir)
|
||||
}
|
||||
preference.summary = FileSizeUtils.formatBytes(ctx, size)
|
||||
storageManager.clearCache(cache)
|
||||
val size = storageManager.computeCacheSize(cache)
|
||||
preference.summary = FileSize.BYTES.format(ctx, size)
|
||||
} catch (e: Exception) {
|
||||
preference.summary = e.getDisplayMessage(ctx.resources)
|
||||
} finally {
|
||||
@@ -118,6 +101,11 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
}
|
||||
}
|
||||
|
||||
private fun Preference.bindSummaryToCacheSize(dir: CacheDir) = viewLifecycleScope.launch {
|
||||
val size = storageManager.computeCacheSize(dir)
|
||||
summary = FileSize.BYTES.format(context, size)
|
||||
}
|
||||
|
||||
private fun clearSearchHistory(preference: Preference) {
|
||||
MaterialAlertDialogBuilder(context ?: return)
|
||||
.setTitle(R.string.clear_search_history)
|
||||
@@ -154,4 +142,4 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,22 @@ import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.SwitchPreference
|
||||
import kotlinx.coroutines.launch
|
||||
import leakcanary.LeakCanary
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment
|
||||
import org.koitharu.kotatsu.base.ui.dialog.StorageSelectDialog
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
import org.koitharu.kotatsu.settings.protect.ProtectSetupActivity
|
||||
import org.koitharu.kotatsu.settings.utils.SliderPreference
|
||||
import org.koitharu.kotatsu.utils.ext.getStorageName
|
||||
import org.koitharu.kotatsu.utils.ext.names
|
||||
import org.koitharu.kotatsu.utils.ext.setDefaultValueCompat
|
||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@@ -32,6 +36,8 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener,
|
||||
StorageSelectDialog.OnStorageSelectListener {
|
||||
|
||||
private val storageManager by inject<LocalStorageManager>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
@@ -56,7 +62,7 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
|
||||
entryValues = arrayOf("", "MM/dd/yy", "dd/MM/yy", "yyyy-MM-dd", "dd MMM yyyy", "MMM dd, yyyy")
|
||||
val now = Date().time
|
||||
entries = entryValues.map { value ->
|
||||
val formattedDate = settings.dateFormat(value.toString()).format(now)
|
||||
val formattedDate = settings.getDateFormat(value.toString()).format(now)
|
||||
if (value == "") {
|
||||
"${context.getString(R.string.system_default)} ($formattedDate)"
|
||||
} else {
|
||||
@@ -70,10 +76,7 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
findPreference<Preference>(AppSettings.KEY_LOCAL_STORAGE)?.run {
|
||||
summary = settings.getStorageDir(context)?.getStorageName(context)
|
||||
?: getString(R.string.not_available)
|
||||
}
|
||||
findPreference<Preference>(AppSettings.KEY_LOCAL_STORAGE)?.bindStorageName()
|
||||
findPreference<SwitchPreference>(AppSettings.KEY_PROTECT_APP)?.isChecked =
|
||||
!settings.appPassword.isNullOrEmpty()
|
||||
settings.subscribe(this)
|
||||
@@ -114,10 +117,7 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
|
||||
findPreference<SwitchPreference>(key)?.setSummary(R.string.restart_required)
|
||||
}
|
||||
AppSettings.KEY_LOCAL_STORAGE -> {
|
||||
findPreference<Preference>(key)?.run {
|
||||
summary = settings.getStorageDir(context)?.getStorageName(context)
|
||||
?: getString(R.string.not_available)
|
||||
}
|
||||
findPreference<Preference>(key)?.bindStorageName()
|
||||
}
|
||||
AppSettings.KEY_APP_PASSWORD -> {
|
||||
findPreference<SwitchPreference>(AppSettings.KEY_PROTECT_APP)
|
||||
@@ -140,7 +140,7 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
|
||||
return when (preference.key) {
|
||||
AppSettings.KEY_LOCAL_STORAGE -> {
|
||||
val ctx = context ?: return false
|
||||
StorageSelectDialog.Builder(ctx, settings.getStorageDir(ctx), this)
|
||||
StorageSelectDialog.Builder(ctx, storageManager, this)
|
||||
.setTitle(preference.title ?: "")
|
||||
.setNegativeButton(android.R.string.cancel)
|
||||
.create()
|
||||
@@ -162,7 +162,13 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
|
||||
}
|
||||
|
||||
override fun onStorageSelected(file: File) {
|
||||
settings.setStorageDir(context ?: return, file)
|
||||
settings.mangaStorageDir = file
|
||||
}
|
||||
|
||||
}
|
||||
private fun Preference.bindStorageName() {
|
||||
viewLifecycleScope.launch {
|
||||
val storage = storageManager.getDefaultWriteableDir()
|
||||
summary = storage?.getStorageName(context) ?: getString(R.string.not_available)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,13 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.settings.utils.RingtonePickContract
|
||||
import org.koitharu.kotatsu.utils.ext.toUriOrNull
|
||||
|
||||
class NotificationSettingsLegacyFragment : BasePreferenceFragment(R.string.notifications) {
|
||||
|
||||
private val ringtonePickContract = registerForActivityResult(
|
||||
RingtonePickContract(get<Context>().getString(R.string.notification_sound))
|
||||
) { uri ->
|
||||
settings.notificationSound = uri?.toString() ?: return@registerForActivityResult
|
||||
settings.notificationSound = uri ?: return@registerForActivityResult
|
||||
findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SOUND)?.run {
|
||||
summary = RingtoneManager.getRingtone(context, uri)?.getTitle(context)
|
||||
?: getString(R.string.silent)
|
||||
@@ -31,7 +30,7 @@ class NotificationSettingsLegacyFragment : BasePreferenceFragment(R.string.notif
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SOUND)?.run {
|
||||
val uri = settings.notificationSound.toUriOrNull()
|
||||
val uri = settings.notificationSound
|
||||
summary = RingtoneManager.getRingtone(context, uri)?.getTitle(context)
|
||||
?: getString(R.string.silent)
|
||||
}
|
||||
@@ -40,10 +39,10 @@ class NotificationSettingsLegacyFragment : BasePreferenceFragment(R.string.notif
|
||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||
return when (preference.key) {
|
||||
AppSettings.KEY_NOTIFICATIONS_SOUND -> {
|
||||
ringtonePickContract.launch(settings.notificationSound.toUriOrNull())
|
||||
ringtonePickContract.launch(settings.notificationSound)
|
||||
true
|
||||
}
|
||||
else -> super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,12 @@ class AboutSettingsFragment : BasePreferenceFragment(R.string.about) {
|
||||
resources.getString(R.string.about_feedback_4pda)) })
|
||||
true
|
||||
}
|
||||
AppSettings.KEY_FEEDBACK_DISCORD -> {
|
||||
startActivity(context?.let { BrowserActivity.newIntent(it,
|
||||
"https://discord.gg/NNJ5RgVBC5",
|
||||
"Discord") })
|
||||
true
|
||||
}
|
||||
AppSettings.KEY_FEEDBACK_GITHUB -> {
|
||||
startActivity(context?.let { BrowserActivity.newIntent(it,
|
||||
"https://github.com/nv95/Kotatsu/issues",
|
||||
@@ -89,4 +95,4 @@ class AboutSettingsFragment : BasePreferenceFragment(R.string.about) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.koitharu.kotatsu.settings.sources
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
@@ -70,7 +69,7 @@ class SourcesSettingsViewModel(
|
||||
}
|
||||
|
||||
private fun buildList() {
|
||||
val sources = MangaProviderFactory.getSources(settings, includeHidden = true)
|
||||
val sources = settings.getMangaSources(includeHidden = true)
|
||||
val hiddenSources = settings.hiddenSources
|
||||
val query = searchQuery
|
||||
if (!query.isNullOrEmpty()) {
|
||||
@@ -155,4 +154,4 @@ class SourcesSettingsViewModel(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.koitharu.kotatsu.tracker
|
||||
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
@@ -11,5 +10,5 @@ val trackerModule
|
||||
|
||||
single { TrackingRepository(get()) }
|
||||
|
||||
viewModel { FeedViewModel(androidContext(), get()) }
|
||||
viewModel { FeedViewModel(get()) }
|
||||
}
|
||||
@@ -4,7 +4,9 @@ import android.os.Bundle
|
||||
import android.view.*
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.divider.MaterialDividerItemDecoration
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.koin.android.ext.android.get
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
@@ -50,6 +52,9 @@ class FeedFragment : BaseFragment<FragmentFeedBinding>(), PaginationScrollListen
|
||||
adapter = feedAdapter
|
||||
setHasFixedSize(true)
|
||||
addOnScrollListener(PaginationScrollListener(4, this@FeedFragment))
|
||||
val dividerDecoration = MaterialDividerItemDecoration(context, RecyclerView.VERTICAL)
|
||||
dividerDecoration.setDividerInsetStartResource(context, R.dimen.feed_dividers_offset)
|
||||
addItemDecoration(dividerDecoration)
|
||||
}
|
||||
|
||||
viewModel.content.observe(viewLifecycleOwner, this::onListChanged)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.koitharu.kotatsu.tracker.ui
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -22,7 +21,6 @@ import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import org.koitharu.kotatsu.utils.ext.mapItems
|
||||
|
||||
class FeedViewModel(
|
||||
context: Context,
|
||||
private val repository: TrackingRepository
|
||||
) : BaseViewModel() {
|
||||
|
||||
@@ -34,7 +32,7 @@ class FeedViewModel(
|
||||
val onFeedCleared = SingleLiveEvent<Unit>()
|
||||
val content = combine(
|
||||
logList.filterNotNull().mapItems {
|
||||
it.toFeedItem(context.resources)
|
||||
it.toFeedItem()
|
||||
},
|
||||
hasNextPage
|
||||
) { list, isHasNextPage ->
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.tracker.ui.model.FeedItem
|
||||
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
||||
import org.koitharu.kotatsu.utils.ext.textAndVisible
|
||||
|
||||
fun feedItemAD(
|
||||
coil: ImageLoader,
|
||||
@@ -39,6 +40,11 @@ fun feedItemAD(
|
||||
binding.textViewTitle.text = item.title
|
||||
binding.badge.text = item.subtitle
|
||||
binding.textViewChapters.text = item.chapters
|
||||
binding.textViewTruncated.textAndVisible = if (item.truncated > 0) {
|
||||
getString(R.string._and_x_more, item.truncated)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
onViewRecycled {
|
||||
|
||||
@@ -9,5 +9,6 @@ data class FeedItem(
|
||||
val title: String,
|
||||
val subtitle: String,
|
||||
val chapters: CharSequence,
|
||||
val manga: Manga
|
||||
val manga: Manga,
|
||||
val truncated: Int,
|
||||
) : ListModel
|
||||
@@ -1,19 +1,15 @@
|
||||
package org.koitharu.kotatsu.tracker.ui.model
|
||||
|
||||
import android.content.res.Resources
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.TrackingLogItem
|
||||
|
||||
fun TrackingLogItem.toFeedItem(resources: Resources): FeedItem {
|
||||
val chaptersString = if (chapters.size > MAX_CHAPTERS) {
|
||||
fun TrackingLogItem.toFeedItem(): FeedItem {
|
||||
val truncate = chapters.size > MAX_CHAPTERS
|
||||
val chaptersString = if (truncate) {
|
||||
chapters.joinToString(
|
||||
separator = "\n",
|
||||
limit = MAX_CHAPTERS - 1,
|
||||
truncated = resources.getString(
|
||||
R.string._and_x_more,
|
||||
chapters.size - MAX_CHAPTERS + 1
|
||||
)
|
||||
)
|
||||
truncated = "",
|
||||
).trimEnd()
|
||||
} else {
|
||||
chapters.joinToString("\n")
|
||||
}
|
||||
@@ -23,7 +19,8 @@ fun TrackingLogItem.toFeedItem(resources: Resources): FeedItem {
|
||||
title = manga.title,
|
||||
subtitle = chapters.size.toString(),
|
||||
chapters = chaptersString,
|
||||
manga = manga
|
||||
manga = manga,
|
||||
truncated = chapters.size - MAX_CHAPTERS + 1,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
|
||||
setShortcutId(manga.id.toString())
|
||||
priority = NotificationCompat.PRIORITY_DEFAULT
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
builder.setSound(settings.notificationSound.toUriOrNull())
|
||||
builder.setSound(settings.notificationSound)
|
||||
var defaults = if (settings.notificationLight) {
|
||||
setLights(colorPrimary, 1000, 5000)
|
||||
NotificationCompat.DEFAULT_LIGHTS
|
||||
@@ -298,4 +298,4 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.os.StatFs
|
||||
import androidx.annotation.WorkerThread
|
||||
import okhttp3.Cache
|
||||
import okhttp3.CacheControl
|
||||
import org.koitharu.kotatsu.utils.ext.computeSize
|
||||
import org.koitharu.kotatsu.utils.ext.sub
|
||||
import java.io.File
|
||||
|
||||
object CacheUtils {
|
||||
|
||||
const val QUALIFIER_HTTP = "cache_http"
|
||||
|
||||
val CONTROL_DISABLED = CacheControl.Builder()
|
||||
.noStore()
|
||||
.build()
|
||||
|
||||
fun getCacheDirs(context: Context) = (context.externalCacheDirs + context.cacheDir)
|
||||
.filterNotNull()
|
||||
.distinctBy { it.absolutePath }
|
||||
|
||||
@WorkerThread
|
||||
fun computeCacheSize(context: Context, name: String) = getCacheDirs(context)
|
||||
.map { File(it, name) }
|
||||
.sumOf { x -> x.computeSize() }
|
||||
|
||||
@WorkerThread
|
||||
fun clearCache(context: Context, name: String) = getCacheDirs(context)
|
||||
.map { File(it, name) }
|
||||
.forEach { it.deleteRecursively() }
|
||||
|
||||
// FIXME need async implementation
|
||||
fun createHttpCache(context: Context): Cache {
|
||||
val directory = (context.externalCacheDir ?: context.cacheDir).sub("http")
|
||||
directory.mkdirs()
|
||||
val maxSize = calculateDiskCacheSize(directory) // TODO blocking call
|
||||
return Cache(directory, maxSize)
|
||||
}
|
||||
|
||||
private fun calculateDiskCacheSize(cacheDirectory: File): Long {
|
||||
return try {
|
||||
val cacheDir = StatFs(cacheDirectory.absolutePath)
|
||||
val size = DISK_CACHE_PERCENTAGE * cacheDir.blockCountLong * cacheDir.blockSizeLong
|
||||
return size.toLong().coerceIn(MIN_DISK_CACHE_SIZE, MAX_DISK_CACHE_SIZE)
|
||||
} catch (_: Exception) {
|
||||
MIN_DISK_CACHE_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
private const val DISK_CACHE_PERCENTAGE = 0.02
|
||||
private const val MIN_DISK_CACHE_SIZE: Long = 10 * 1024 * 1024 // 10MB
|
||||
private const val MAX_DISK_CACHE_SIZE: Long = 250 * 1024 * 1024 // 250MB
|
||||
}
|
||||
@@ -6,14 +6,14 @@ import java.text.DecimalFormat
|
||||
import kotlin.math.log10
|
||||
import kotlin.math.pow
|
||||
|
||||
enum class FileSize(private val multiplier: Int) {
|
||||
|
||||
object FileSizeUtils {
|
||||
BYTES(1), KILOBYTES(1024), MEGABYTES(1024 * 1024);
|
||||
|
||||
fun mbToBytes(mb: Int) = 1024L * 1024L * mb
|
||||
fun convert(amount: Long, target: FileSize): Long = amount * multiplier / target.multiplier
|
||||
|
||||
fun kbToBytes(kb: Int) = 1024L * kb
|
||||
|
||||
fun formatBytes(context: Context, bytes: Long): String {
|
||||
fun format(context: Context, amount: Long): String {
|
||||
val bytes = amount * multiplier
|
||||
val units = context.getString(R.string.text_file_sizes).split('|')
|
||||
if (bytes <= 0) {
|
||||
return "0 ${units.first()}"
|
||||
@@ -23,10 +23,13 @@ object FileSizeUtils {
|
||||
append(
|
||||
DecimalFormat("#,##0.#").format(
|
||||
bytes / 1024.0.pow(digitGroups.toDouble())
|
||||
).toString()
|
||||
)
|
||||
)
|
||||
append(' ')
|
||||
append(units.getOrNull(digitGroups).orEmpty())
|
||||
val unit = units.getOrNull(digitGroups)
|
||||
if (unit != null) {
|
||||
append(' ')
|
||||
append(unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,17 @@ import android.os.Build
|
||||
|
||||
object PendingIntentCompat {
|
||||
|
||||
@JvmField
|
||||
val FLAG_IMMUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val FLAG_MUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
PendingIntent.FLAG_MUTABLE
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,4 +91,4 @@ sealed class Motion {
|
||||
anim.interpolator = DecelerateInterpolator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.fragment.app.Fragment
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class ParcelableArgumentDelegate<T : Parcelable>(private val name: String) :
|
||||
ReadOnlyProperty<Fragment, T> {
|
||||
|
||||
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
|
||||
return thisRef.requireArguments().getParcelable(name)!!
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class StringArgumentDelegate(private val name: String) : ReadOnlyProperty<Fragment, String?> {
|
||||
|
||||
override fun getValue(thisRef: Fragment, property: KProperty<*>): String? {
|
||||
return thisRef.arguments?.getString(name)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class BoolPreferenceDelegate(private val key: String, private val defaultValue: Boolean) :
|
||||
ReadWriteProperty<SharedPreferences, Boolean> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Boolean {
|
||||
return thisRef.getBoolean(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: Boolean) {
|
||||
thisRef.edit {
|
||||
putBoolean(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class EnumPreferenceDelegate<E : Enum<*>>(
|
||||
private val cls: Class<E>,
|
||||
private val key: String,
|
||||
private val defValue: E
|
||||
) : ReadWriteProperty<SharedPreferences, E> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): E {
|
||||
val name = thisRef.getString(key, null)
|
||||
if (name === null) {
|
||||
return defValue
|
||||
}
|
||||
return cls.enumConstants?.find { it.name == name } ?: defValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: E) {
|
||||
thisRef.edit {
|
||||
putString(key, value.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
@Deprecated("")
|
||||
class IntEnumPreferenceDelegate<E : Enum<*>>(
|
||||
private val cls: Class<E>,
|
||||
private val key: String,
|
||||
private val defValue: E
|
||||
) : ReadWriteProperty<SharedPreferences, E> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): E {
|
||||
val ord = thisRef.getInt(key, -1)
|
||||
if (ord == -1) {
|
||||
return defValue
|
||||
}
|
||||
return cls.enumConstants?.getOrNull(ord) ?: defValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: E) {
|
||||
thisRef.edit {
|
||||
putInt(key, value.ordinal)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class IntPreferenceDelegate(private val key: String, private val defaultValue: Int) :
|
||||
ReadWriteProperty<SharedPreferences, Int> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Int {
|
||||
return thisRef.getInt(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: Int) {
|
||||
thisRef.edit {
|
||||
putInt(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class LongPreferenceDelegate(private val key: String, private val defaultValue: Long) :
|
||||
ReadWriteProperty<SharedPreferences, Long> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Long {
|
||||
return thisRef.getLong(key, defaultValue)
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: Long) {
|
||||
thisRef.edit {
|
||||
putLong(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class NullableStringPreferenceDelegate(private val key: String) :
|
||||
ReadWriteProperty<SharedPreferences, String?> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): String? {
|
||||
return thisRef.getString(key, null)
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: String?) {
|
||||
thisRef.edit {
|
||||
putString(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class StringIntPreferenceDelegate(private val key: String, private val defValue: Int) :
|
||||
ReadWriteProperty<SharedPreferences, Int> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Int {
|
||||
return thisRef.getString(key, defValue.toString())?.toIntOrNull() ?: defValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: Int) {
|
||||
thisRef.edit {
|
||||
putString(key, value.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class StringPreferenceDelegate(private val key: String, private val defValue: String) :
|
||||
ReadWriteProperty<SharedPreferences, String> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): String {
|
||||
return thisRef.getString(key, defValue) ?: defValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: String) {
|
||||
thisRef.edit {
|
||||
putString(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class StringSetPreferenceDelegate(
|
||||
private val key: String,
|
||||
private val defValue: Set<String> = emptySet()
|
||||
) :
|
||||
ReadWriteProperty<SharedPreferences, Set<String>> {
|
||||
|
||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Set<String> {
|
||||
return thisRef.getStringSet(key, defValue) ?: defValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: Set<String>) {
|
||||
thisRef.edit {
|
||||
putStringSet(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,18 +7,16 @@ import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.storage.StorageManager
|
||||
import android.provider.OpenableColumns
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.database.getStringOrNull
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koitharu.kotatsu.R
|
||||
import java.io.File
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
@Deprecated("Useless", ReplaceWith("File(this, name)", "java.io.File"))
|
||||
inline fun File.sub(name: String) = File(this, name)
|
||||
|
||||
fun File.subdir(name: String) = File(this, name).also {
|
||||
if (!it.exists()) it.mkdirs()
|
||||
}
|
||||
@@ -29,22 +27,6 @@ fun ZipFile.readText(entry: ZipEntry) = getInputStream(entry).bufferedReader().u
|
||||
it.readText()
|
||||
}
|
||||
|
||||
fun File.computeSize(): Long = listFiles()?.sumOf { x ->
|
||||
if (x.isDirectory) {
|
||||
x.computeSize()
|
||||
} else {
|
||||
x.length()
|
||||
}
|
||||
} ?: 0L
|
||||
|
||||
inline fun File.findParent(predicate: (File) -> Boolean): File? {
|
||||
var current = this
|
||||
while (!predicate(current)) {
|
||||
current = current.parentFile ?: return null
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
fun File.getStorageName(context: Context): String = runCatching {
|
||||
val manager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
@@ -78,4 +60,18 @@ fun ContentResolver.resolveName(uri: Uri): String? {
|
||||
}
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
suspend fun File.computeSize(): Long = runInterruptible(Dispatchers.IO) {
|
||||
computeSizeInternal(this)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun computeSizeInternal(file: File): Long {
|
||||
if (file.isDirectory) {
|
||||
val files = file.listFiles() ?: return 0L
|
||||
return files.sumOf { computeSizeInternal(it) }
|
||||
} else {
|
||||
return file.length()
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,13 @@ fun String.longHashCode(): Long {
|
||||
var h = 1125899906842597L
|
||||
val len: Int = this.length
|
||||
for (i in 0 until len) {
|
||||
h = 31 * h + this[i].toLong()
|
||||
h = 31 * h + this[i].code
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
fun String.removeSurrounding(vararg chars: Char): String {
|
||||
if (length == 0) {
|
||||
if (isEmpty()) {
|
||||
return this
|
||||
}
|
||||
for (c in chars) {
|
||||
@@ -224,4 +224,4 @@ inline fun <T> StringBuilder.appendAll(
|
||||
}
|
||||
append(transform(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class ShelfConfigActivity : BaseActivity<ActivityCategoriesBinding>(),
|
||||
finishAfterTransition()
|
||||
return
|
||||
}
|
||||
config = AppWidgetConfig.getInstance(this, appWidgetId)
|
||||
config = AppWidgetConfig(this, appWidgetId)
|
||||
viewModel.checkedId = config.categoryId
|
||||
|
||||
viewModel.content.observe(this, this::onContentChanged)
|
||||
@@ -118,4 +118,4 @@ class ShelfConfigActivity : BaseActivity<ActivityCategoriesBinding>(),
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class ShelfListFactory(
|
||||
) : RemoteViewsService.RemoteViewsFactory {
|
||||
|
||||
private val dataSet = ArrayList<Manga>()
|
||||
private val config = AppWidgetConfig.getInstance(context, widgetId)
|
||||
private val config = AppWidgetConfig(context, widgetId)
|
||||
|
||||
override fun onCreate() {
|
||||
}
|
||||
@@ -73,4 +73,4 @@ class ShelfListFactory(
|
||||
override fun getViewTypeCount() = 1
|
||||
|
||||
override fun onDestroy() = Unit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?android:textColorPrimary"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M17,18V5H7V18L12,15.82L17,18M17,3A2,2 0 0,1 19,5V21L12,18L5,21V5C5,3.89 5.9,3 7,3H17M11,7H13V9H15V11H13V13H11V11H9V9H11V7Z" />
|
||||
</vector>
|
||||
android:pathData="M2,16H10V14H2M18,14V10H16V14H12V16H16V20H18V16H22V14M14,6H2V8H14M14,10H2V12H14V10Z" />
|
||||
</vector>
|
||||
11
app/src/main/res/drawable/ic_loading.xml
Normal file
11
app/src/main/res/drawable/ic_loading.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M13 2.03V4.05C17.39 4.59 20.5 8.58 19.96 12.97C19.5 16.61 16.64 19.5 13 19.93V21.93C18.5 21.38 22.5 16.5 21.95 11C21.5 6.25 17.73 2.5 13 2.03M11 2.06C9.05 2.25 7.19 3 5.67 4.26L7.1 5.74C8.22 4.84 9.57 4.26 11 4.06V2.06M4.26 5.67C3 7.19 2.25 9.04 2.05 11H4.05C4.24 9.58 4.8 8.23 5.69 7.1L4.26 5.67M2.06 13C2.26 14.96 3.03 16.81 4.27 18.33L5.69 16.9C4.81 15.77 4.24 14.42 4.06 13H2.06M7.1 18.37L5.67 19.74C7.18 21 9.04 21.79 11 22V20C9.58 19.82 8.23 19.25 7.1 18.37M20 4H44M13 18H11V16H13V18M13 15H11C11 11.75 14 12 14 10C14 8.9 13.1 8 12 8S10 8.9 10 10H8C8 7.79 9.79 6 12 6S16 7.79 16 10C16 12.5 13 12.75 13 15Z" />
|
||||
</vector>
|
||||
@@ -3,12 +3,14 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="50dp" />
|
||||
<corners android:radius="10dp" />
|
||||
|
||||
<padding
|
||||
android:paddingLeft="22dp"
|
||||
android:paddingRight="22dp" />
|
||||
android:bottom="10dp"
|
||||
android:left="10dp"
|
||||
android:right="10dp"
|
||||
android:top="10dp" />
|
||||
|
||||
<solid android:color="?colorPrimary" />
|
||||
<solid android:color="@color/scrollbar" />
|
||||
|
||||
</shape>
|
||||
@@ -1,13 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@android:color/darker_gray" />
|
||||
|
||||
<padding
|
||||
android:bottom="10dp"
|
||||
android:left="10dp"
|
||||
android:right="10dp"
|
||||
android:top="10dp" />
|
||||
</shape>
|
||||
android:shape="rectangle" />
|
||||
@@ -20,13 +20,8 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/grid_spacing_outer"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:scrollbars="vertical"
|
||||
app:fastScrollEnabled="true"
|
||||
app:fastScrollHorizontalThumbDrawable="@drawable/list_thumb"
|
||||
app:fastScrollHorizontalTrackDrawable="@drawable/list_track"
|
||||
app:fastScrollVerticalThumbDrawable="@drawable/list_thumb"
|
||||
app:fastScrollVerticalTrackDrawable="@drawable/list_track"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_manga_list" />
|
||||
|
||||
|
||||
@@ -41,16 +41,18 @@
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/fab_add"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="@string/add_new_category"
|
||||
android:src="@drawable/ic_add"
|
||||
android:text="@string/create_category"
|
||||
app:fabSize="normal"
|
||||
app:icon="@drawable/ic_add"
|
||||
app:layout_anchor="@id/recyclerView"
|
||||
app:layout_anchorGravity="bottom|end"
|
||||
app:layout_dodgeInsetEdges="bottom" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -42,6 +42,6 @@
|
||||
android:paddingEnd="?android:listPreferredItemPaddingEnd"
|
||||
android:text="@string/add_new_category"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge"
|
||||
app:drawableEndCompat="@drawable/ic_add" />
|
||||
app:drawableEndCompat="@drawable/ic_list_add" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -28,12 +28,7 @@
|
||||
android:layout_alignParentBottom="true"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
app:fastScrollEnabled="true"
|
||||
app:fastScrollHorizontalThumbDrawable="@drawable/list_thumb"
|
||||
app:fastScrollHorizontalTrackDrawable="@drawable/list_track"
|
||||
app:fastScrollVerticalThumbDrawable="@drawable/list_thumb"
|
||||
app:fastScrollVerticalTrackDrawable="@drawable/list_track"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_chapter" />
|
||||
|
||||
|
||||
@@ -18,13 +18,8 @@
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/grid_spacing_outer"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:scrollbars="vertical"
|
||||
app:fastScrollEnabled="true"
|
||||
app:fastScrollHorizontalThumbDrawable="@drawable/list_thumb"
|
||||
app:fastScrollHorizontalTrackDrawable="@drawable/list_track"
|
||||
app:fastScrollVerticalThumbDrawable="@drawable/list_thumb"
|
||||
app:fastScrollVerticalTrackDrawable="@drawable/list_track"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_manga_list" />
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp">
|
||||
android:paddingVertical="6dp"
|
||||
android:paddingHorizontal="8dp">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_cover"
|
||||
@@ -75,11 +75,26 @@
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="none"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:lineSpacingExtra="4sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/card_cover"
|
||||
app:layout_constraintTop_toBottomOf="@id/title_container"
|
||||
tools:text="@tools:sample/lorem[25]" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_truncated"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textColor="?android:textColorHint"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/card_cover"
|
||||
app:layout_constraintTop_toBottomOf="@id/textView_chapters"
|
||||
tools:text="@string/_and_x_more" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -12,13 +12,6 @@
|
||||
android:visible="false"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_bookmark_add"
|
||||
android:icon="@drawable/ic_bookmark_add"
|
||||
android:title="@string/add_bookmark"
|
||||
android:visible="false"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_pages_thumbs"
|
||||
android:icon="@drawable/ic_grid"
|
||||
@@ -27,7 +20,7 @@
|
||||
|
||||
<item
|
||||
android:id="@+id/action_reader_mode"
|
||||
android:icon="@drawable/ic_book_page"
|
||||
android:icon="@drawable/ic_loading"
|
||||
android:title="@string/read_mode"
|
||||
app:showAsAction="always" />
|
||||
|
||||
@@ -41,4 +34,4 @@
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
</menu>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -54,7 +54,7 @@
|
||||
<string name="automatic">Аўтаматычна</string>
|
||||
<string name="pages">Старонкi</string>
|
||||
<string name="clear">Ачысціць</string>
|
||||
<string name="text_clear_history_prompt">Вы ўпэўненыя, што жадаеце ачысціць гісторыю? Гэта дзеянне нельга будзе адмяніць.</string>
|
||||
<string name="text_clear_history_prompt">Вы ўпэўненыя, што жадаеце ачысціць гісторыю\? Гэта дзеянне нельга будзе адмяніць.</string>
|
||||
<string name="remove">Выдаліць</string>
|
||||
<string name="_s_removed_from_history">\"%s\" выдалена з гiсторыi</string>
|
||||
<string name="_s_deleted_from_local_storage">\"%s\" выдалена з прылады</string>
|
||||
@@ -100,7 +100,7 @@
|
||||
<string name="app_update_available">Даступна абнаўленне праграмы</string>
|
||||
<string name="show_notification_app_update">Паказваць апавяшчэнне пры наяўнасці новай версіі</string>
|
||||
<string name="open_in_browser">Адкрыць у браўзеры</string>
|
||||
<string name="large_manga_save_confirm">У гэтай манге %s. Вы ўпэўненыя, што хочаце захаваць іх усё?</string>
|
||||
<string name="large_manga_save_confirm">У гэтай манге %s. Вы ўпэўненыя, што хочаце захаваць іх усё\?</string>
|
||||
<string name="save_manga">Захаваць мангу</string>
|
||||
<string name="notifications">Паведамленні</string>
|
||||
<string name="enabled_d_of_d">Уключана %1$d з %2$d</string>
|
||||
@@ -194,7 +194,7 @@
|
||||
<string name="cookies_cleared">Усе кукi выдалены</string>
|
||||
<string name="chapters_checking_progress">Праверка новых частак: %1$d з %2$d</string>
|
||||
<string name="clear_feed">Ачысціць стужку</string>
|
||||
<string name="text_clear_updates_feed_prompt">Уся гісторыя абнаўленняў будзе ачышчана і яе нельга будзе вярнуць. Вы ўпэўненыя?</string>
|
||||
<string name="text_clear_updates_feed_prompt">Уся гісторыя абнаўленняў будзе ачышчана і яе нельга будзе вярнуць. Вы ўпэўненыя\?</string>
|
||||
<string name="new_chapters_checking">Праверка новых глаў</string>
|
||||
<string name="reverse">У адваротным парадку</string>
|
||||
<string name="sign_in">Увайсці</string>
|
||||
@@ -249,4 +249,6 @@
|
||||
<string name="show_pages_numbers">Паказваць нумары старонак</string>
|
||||
<string name="enabled_sources">Уключаныя крыніцы</string>
|
||||
<string name="available_sources">Даступныя крыніцы</string>
|
||||
<string name="dynamic_theme">Дынамічная тэма</string>
|
||||
<string name="dynamic_theme_summary">Ужывае тэму праграмы, заснаваную на каляровай палітры шпалер на прыладзе</string>
|
||||
</resources>
|
||||
@@ -1,22 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="remove">Entfernen</string>
|
||||
<string name="text_clear_history_prompt">Möchtest du wirklich deinen gesamten Leseverlauf löschen\? Diese Aktion kann nicht rückgängig gemacht werden.</string>
|
||||
<string name="text_clear_history_prompt">Möchtest du wirklich deinen gesamten Leseverlauf löschen\?</string>
|
||||
<string name="theme">Design</string>
|
||||
<string name="pages">Seiten</string>
|
||||
<string name="automatic">Automatisch</string>
|
||||
<string name="automatic">Nach System</string>
|
||||
<string name="dark">Dunkel</string>
|
||||
<string name="light">Hell</string>
|
||||
<string name="filter">Filter</string>
|
||||
<string name="genre">Genre</string>
|
||||
<string name="sort_order">Sortierung</string>
|
||||
<string name="sort_order">Sortierreihenfolge</string>
|
||||
<string name="all">Alle</string>
|
||||
<string name="by_rating">Nach Bewertung</string>
|
||||
<string name="by_rating">Bewertung</string>
|
||||
<string name="newest">Neuestes</string>
|
||||
<string name="popular">Beliebt</string>
|
||||
<string name="by_name">Nach Name</string>
|
||||
<string name="by_name">Name</string>
|
||||
<string name="downloads">Heruntergeladene</string>
|
||||
<string name="download_complete">Herunterladen abgeschlossen</string>
|
||||
<string name="download_complete">Heruntergeladen</string>
|
||||
<string name="search_manga">Manga suchen</string>
|
||||
<string name="search">Suchen</string>
|
||||
<string name="share_s">Teilen %s</string>
|
||||
@@ -24,12 +24,12 @@
|
||||
<string name="save">Speichern</string>
|
||||
<string name="enter_category_name">Gib den Name der Kategorie ein</string>
|
||||
<string name="add">Hinzufügen</string>
|
||||
<string name="add_new_category">Neue Kategorie hinzufügen</string>
|
||||
<string name="add_new_category">Neue Kategorie</string>
|
||||
<string name="add_to_favourites">Zu Favoriten hinzufügen</string>
|
||||
<string name="you_have_not_favourites_yet">Du hast noch keine Favoriten</string>
|
||||
<string name="you_have_not_favourites_yet">Noch keine Favoriten</string>
|
||||
<string name="add_bookmark">Lesezeichen hinzufügen</string>
|
||||
<string name="read">Lesen</string>
|
||||
<string name="history_is_empty">Verlauf ist leer</string>
|
||||
<string name="history_is_empty">Noch kein Verlauf</string>
|
||||
<string name="nothing_found">Nichts gefunden</string>
|
||||
<string name="clear_history">Verlauf löschen</string>
|
||||
<string name="try_again">Erneut versuchen</string>
|
||||
@@ -62,21 +62,20 @@
|
||||
<string name="categories_">Kategorien …</string>
|
||||
<string name="cancelling_">Abbrechen …</string>
|
||||
<string name="processing_">Verarbeiten …</string>
|
||||
<string name="manga_downloading_">Manga wird heruntergeladen …</string>
|
||||
<string name="manga_downloading_">Wird heruntergeladen …</string>
|
||||
<string name="create_shortcut">Verknüpfung erstellen …</string>
|
||||
<string name="loading_">Wird geladen …</string>
|
||||
<string name="category_delete_confirm">Möchtest du die Kategorie „%s“ wirklich aus deinen Favoriten entfernen\?
|
||||
\nAlle enthaltenen Manga gehen dabei verloren.</string>
|
||||
<string name="text_delete_local_manga">Möchtest du wirklich „%s“ aus dem lokalen Speicher des Telefons löschen\?
|
||||
\nDieser Vorgang kann nicht rückgängig gemacht werden.</string>
|
||||
<string name="text_delete_local_manga">\"%s\" dauerhaft vom Gerät löschen\?</string>
|
||||
<string name="_s_deleted_from_local_storage">„%s“ aus lokalem Speicher gelöscht</string>
|
||||
<string name="_s_removed_from_history">„%s“ aus dem Verlauf entfernt</string>
|
||||
<string name="detailed_list">Detaillierte Liste</string>
|
||||
<string name="list">Liste</string>
|
||||
<string name="chapters">Kapitel</string>
|
||||
<string name="details">Einzelheiten</string>
|
||||
<string name="network_error">Fehler bei der Netzwerkverbindung</string>
|
||||
<string name="error_occurred">Ein Fehler ist aufgetreten</string>
|
||||
<string name="network_error">Keine Verbindung zum Internet möglich</string>
|
||||
<string name="error_occurred">Es ist ein Fehler aufgetreten</string>
|
||||
<string name="history">Verlauf</string>
|
||||
<string name="favourites">Favoriten</string>
|
||||
<string name="local_storage">Lokaler Speicher</string>
|
||||
@@ -108,7 +107,7 @@
|
||||
<string name="default_s">Standard: %s</string>
|
||||
<string name="auth_required">Du solltest diesen Inhalt autorisieren, um ihn zu sehen</string>
|
||||
<string name="reverse">Umkehren</string>
|
||||
<string name="new_chapters_checking">Neue Kapitel prüfen</string>
|
||||
<string name="new_chapters_checking">Neue Kapitel prüfen…</string>
|
||||
<string name="clear_feed">Feed löschen</string>
|
||||
<string name="sign_in">Anmelden</string>
|
||||
<string name="password_length_hint">Das Passwort muss mindestens 4 Zeichen lang sein</string>
|
||||
@@ -116,7 +115,7 @@
|
||||
<string name="protect_application_subtitle">Gib das Passwort ein, das beim Starten der Anwendung benötigt wird</string>
|
||||
<string name="next">Nächste</string>
|
||||
<string name="other">Anderes</string>
|
||||
<string name="text_clear_search_history_prompt">Möchtest du wirklich alle letzten Suchanfragen entfernen\? Diese Aktion kann nicht rückgängig gemacht werden.</string>
|
||||
<string name="text_clear_search_history_prompt">Möchtest du wirklich alle letzten Suchanfragen entfernen\?</string>
|
||||
<string name="search_only_on_s">Nur auf %s suchen</string>
|
||||
<string name="hide_toolbar">Symbolleiste beim Blättern ausblenden</string>
|
||||
<string name="read_more">Mehr erfahren</string>
|
||||
@@ -187,14 +186,14 @@
|
||||
<string name="clear_pages_cache">Seitencache löschen</string>
|
||||
<string name="history_and_cache">Verlauf und Cache</string>
|
||||
<string name="no_description">Keine Beschreibung</string>
|
||||
<string name="text_file_not_supported">Ungültige Datei. Nur ZIP und CBZ werden unterstützt.</string>
|
||||
<string name="text_file_not_supported">Wählen Sie entweder eine ZIP- oder CBZ-Datei.</string>
|
||||
<string name="operation_not_supported">Dieser Vorgang wird nicht unterstützt</string>
|
||||
<string name="delete">Löschen</string>
|
||||
<string name="_import">Importieren</string>
|
||||
<string name="share_image">Bild teilen</string>
|
||||
<string name="page_saved">Seite erfolgreich gespeichert</string>
|
||||
<string name="page_saved">Gespeichert</string>
|
||||
<string name="save_page">Seite speichern</string>
|
||||
<string name="wait_for_loading_finish">Warte, bis der Ladevorgang beendet ist</string>
|
||||
<string name="wait_for_loading_finish">Warte, bis der Ladevorgang beendet ist…</string>
|
||||
<string name="clear">Löschen</string>
|
||||
<string name="taps_on_edges">Auf Kanten tippen</string>
|
||||
<string name="captcha_solve">Löse</string>
|
||||
@@ -228,7 +227,7 @@
|
||||
<string name="about_support_developer_summary">Wenn diese Anwendung dir gefällt, kannst du über Yoomoney (Yandex.Money) finanziell helfen</string>
|
||||
<string name="about_license">Lizenz</string>
|
||||
<string name="about_copyright_and_licenses">Urheberrecht und Lizenzen</string>
|
||||
<string name="about_gratitudes_summary">Diese Leute machen Kotatsu besser!</string>
|
||||
<string name="about_gratitudes_summary">Diese Leute machen Kotatsu besser</string>
|
||||
<string name="about_gratitudes">Danksagung</string>
|
||||
<string name="about_support_developer">Den Entwickler unterstützen</string>
|
||||
<string name="about_feedback_4pda">Thema auf 4PDA</string>
|
||||
@@ -249,4 +248,6 @@
|
||||
<string name="show_pages_numbers">Seitenzahlen anzeigen</string>
|
||||
<string name="enabled_sources">Freigegebene Quellen</string>
|
||||
<string name="available_sources">Verfügbare Quellen</string>
|
||||
<string name="dynamic_theme">Dynamisches Thema</string>
|
||||
<string name="dynamic_theme_summary">Wendet ein Thema an, das auf dem Farbschema Ihres Hintergrundbildes basiert</string>
|
||||
</resources>
|
||||
@@ -6,7 +6,7 @@
|
||||
<string name="favourites">Favoritos</string>
|
||||
<string name="history">Historial</string>
|
||||
<string name="error_occurred">Ocurrió un error</string>
|
||||
<string name="network_error">Error de red</string>
|
||||
<string name="network_error">No se pudo conectar a Internet</string>
|
||||
<string name="details">Detalles</string>
|
||||
<string name="chapters">Capítulos</string>
|
||||
<string name="list">Lista</string>
|
||||
@@ -21,12 +21,12 @@
|
||||
<string name="try_again">Reintentar</string>
|
||||
<string name="clear_history">Borrar historial</string>
|
||||
<string name="nothing_found">No se encontró nada</string>
|
||||
<string name="history_is_empty">Historial vacío</string>
|
||||
<string name="history_is_empty">Aún sin historial</string>
|
||||
<string name="read">Leer</string>
|
||||
<string name="add_bookmark">Añadir marcador</string>
|
||||
<string name="you_have_not_favourites_yet">Añade tu manga favorito primero</string>
|
||||
<string name="you_have_not_favourites_yet">Aún no hay favoritos</string>
|
||||
<string name="add_to_favourites">Añadir a favoritos</string>
|
||||
<string name="add_new_category">Añadir categoría</string>
|
||||
<string name="add_new_category">Nueva categoría</string>
|
||||
<string name="add">Añadir</string>
|
||||
<string name="enter_category_name">Introduce categoría</string>
|
||||
<string name="save">Guardar</string>
|
||||
@@ -35,40 +35,40 @@
|
||||
<string name="share_s">Compartir %s</string>
|
||||
<string name="search">Buscar</string>
|
||||
<string name="search_manga">Buscar manga</string>
|
||||
<string name="manga_downloading_">Descargar manga…</string>
|
||||
<string name="manga_downloading_">Descargando…</string>
|
||||
<string name="processing_">Procesando…</string>
|
||||
<string name="download_complete">Descarga completa</string>
|
||||
<string name="download_complete">Descargado</string>
|
||||
<string name="downloads">Descargas</string>
|
||||
<string name="by_name">Por nombre</string>
|
||||
<string name="by_name">Nombre</string>
|
||||
<string name="popular">Popularidad</string>
|
||||
<string name="updated">Actualización</string>
|
||||
<string name="newest">Recientes</string>
|
||||
<string name="by_rating">Por calificación</string>
|
||||
<string name="by_rating">Calificación</string>
|
||||
<string name="all">Todo</string>
|
||||
<string name="sort_order">Establecer orden</string>
|
||||
<string name="sort_order">Orden de clasificación</string>
|
||||
<string name="genre">Género</string>
|
||||
<string name="filter">Filtrar</string>
|
||||
<string name="theme">Tema</string>
|
||||
<string name="light">Claro</string>
|
||||
<string name="dark">Oscuro</string>
|
||||
<string name="automatic">Automático</string>
|
||||
<string name="automatic">De acuerdo al sistema</string>
|
||||
<string name="pages">Páginas</string>
|
||||
<string name="clear">Borrar</string>
|
||||
<string name="text_clear_history_prompt">¿Realmente quieres borrar todo tu historial de lectura? Esta acción no se puede deshacer.</string>
|
||||
<string name="text_clear_history_prompt">¿Realmente quieres borrar todo tu historial de lectura\? Esta acción no se puede deshacer.</string>
|
||||
<string name="remove">Eliminar</string>
|
||||
<string name="_s_removed_from_history">«%s» retirado del historial</string>
|
||||
<string name="_s_deleted_from_local_storage">«%s» borrado del almacenamiento local</string>
|
||||
<string name="wait_for_loading_finish">Espera que termine la carga</string>
|
||||
<string name="wait_for_loading_finish">Espere a que termine de cargar…</string>
|
||||
<string name="save_page">Guardar página</string>
|
||||
<string name="page_saved">Página guardada con éxito</string>
|
||||
<string name="page_saved">Guardado</string>
|
||||
<string name="share_image">Compartir imagen</string>
|
||||
<string name="_import">Importar</string>
|
||||
<string name="delete">Borrar</string>
|
||||
<string name="operation_not_supported">Esta operación no está admitida</string>
|
||||
<string name="text_file_not_supported">Archivo no válido. Sólo se admiten ZIP y CBZ.</string>
|
||||
<string name="text_file_not_supported">Elija un archivo ZIP o bien un archivo CBZ.</string>
|
||||
<string name="no_description">Sin descripción</string>
|
||||
<string name="history_and_cache">Historial y caché</string>
|
||||
<string name="clear_pages_cache">Borrar la caché de páginas</string>
|
||||
<string name="clear_pages_cache">Borrar caché de página</string>
|
||||
<string name="cache">Caché</string>
|
||||
<string name="text_file_sizes">B|kB|MB|GB|TB</string>
|
||||
<string name="standard">Estándar</string>
|
||||
@@ -77,11 +77,10 @@
|
||||
<string name="grid_size">Tamaño de la cuadrícula</string>
|
||||
<string name="search_on_s">Buscar en %s</string>
|
||||
<string name="delete_manga">Borrar manga</string>
|
||||
<string name="text_delete_local_manga">¿Realmente quieres borrar «%s» del almacenamiento local de tu teléfono\?
|
||||
\nEsta operación no se puede deshacer.</string>
|
||||
<string name="text_delete_local_manga">¿Borrar \"%s\" del dispositivo permanentemente\?</string>
|
||||
<string name="reader_settings">Ajustes del lector</string>
|
||||
<string name="switch_pages">Cambiar de página</string>
|
||||
<string name="taps_on_edges">Tapas en los bordes</string>
|
||||
<string name="taps_on_edges">Toques de borde</string>
|
||||
<string name="volume_buttons">Botones de volumen</string>
|
||||
<string name="_continue">Continuar</string>
|
||||
<string name="warning">Advertencia</string>
|
||||
@@ -96,12 +95,12 @@
|
||||
<string name="internal_storage">Almacenamiento interno</string>
|
||||
<string name="external_storage">Almacenamiento externo</string>
|
||||
<string name="domain">Dominio</string>
|
||||
<string name="application_update">Comprobar actualizaciones automáticamente</string>
|
||||
<string name="application_update">Comprobar nuevas versiones de la aplicación</string>
|
||||
<string name="app_update_available">Una nueva versión de la aplicación está disponible</string>
|
||||
<string name="show_notification_app_update">Mostrar notificación si la actualización está disponible</string>
|
||||
<string name="open_in_browser">Abrir en el navegador</string>
|
||||
<string name="large_manga_save_confirm">Este manga tiene %s. ¿Quieres guardarlo todo?</string>
|
||||
<string name="save_manga">Guardar manga</string>
|
||||
<string name="show_notification_app_update">Mostrar notificación si una nueva versión está disponible</string>
|
||||
<string name="open_in_browser">Abrir en navegador web</string>
|
||||
<string name="large_manga_save_confirm">Este manga tiene %s. ¿Quieres guardarlo todo\?</string>
|
||||
<string name="save_manga">Guardar</string>
|
||||
<string name="notifications">Notificaciones</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Activado %1$d de %2$d</string>
|
||||
<string name="new_chapters">Nuevos capítulos</string>
|
||||
@@ -111,26 +110,26 @@
|
||||
<string name="restart">Reiniciar</string>
|
||||
<string name="notifications_settings">Configuración de las notificaciones</string>
|
||||
<string name="notification_sound">Sonido de las notificaciones</string>
|
||||
<string name="light_indicator">Indicador de luz</string>
|
||||
<string name="light_indicator">Indicador LED</string>
|
||||
<string name="vibration">Vibración</string>
|
||||
<string name="favourites_categories">Categorías favoritas</string>
|
||||
<string name="categories_">Categorías…</string>
|
||||
<string name="rename">Renombrar</string>
|
||||
<string name="category_delete_confirm">¿Realmente quieres eliminar la categoría «%s» de tus favoritos\?
|
||||
\nTodo el manga en ella se perderá.</string>
|
||||
<string name="remove_category">Quitar categoría</string>
|
||||
<string name="text_categories_holder">Puedes usar categorías para organizar tus mangas favoritos. Pulsa «+» para crear una categoría</string>
|
||||
<string name="manga_shelf">Estante de manga</string>
|
||||
<string name="recent_manga">Manga reciente</string>
|
||||
<string name="pages_animation">Animación de páginas</string>
|
||||
<string name="manga_save_location">Ubicación de descarga del manga</string>
|
||||
<string name="category_delete_confirm">¿Remover la categoría \"%s\" de sus favoritos\?
|
||||
\nTodo el manga en esta se perderá.</string>
|
||||
<string name="remove_category">Remover</string>
|
||||
<string name="text_categories_holder">Puedes usar categorías para organizar tus favoritos. Pulsa «+» para crear una categoría</string>
|
||||
<string name="manga_shelf">Estante</string>
|
||||
<string name="recent_manga">Reciente</string>
|
||||
<string name="pages_animation">Animación de página</string>
|
||||
<string name="manga_save_location">Carpeta para descargas</string>
|
||||
<string name="not_available">No disponible</string>
|
||||
<string name="cannot_find_available_storage">No se puede encontrar ningún almacenamiento disponible</string>
|
||||
<string name="cannot_find_available_storage">No hay almacenamiento disponible</string>
|
||||
<string name="other_storage">Otro almacenamiento</string>
|
||||
<string name="use_ssl">Utilizar conexión segura (HTTPS)</string>
|
||||
<string name="done">Aceptar</string>
|
||||
<string name="all_favourites">Todos los favoritos</string>
|
||||
<string name="favourites_category_empty">Esta categoría está vacía</string>
|
||||
<string name="favourites_category_empty">Categoría vacía</string>
|
||||
<string name="read_later">Leer más tarde</string>
|
||||
<string name="updates">Actualizaciones</string>
|
||||
<string name="text_feed_holder">Aquí verás los nuevos episodios del manga que estás leyendo</string>
|
||||
@@ -149,7 +148,7 @@
|
||||
<string name="enter_password">Introducir contraseña</string>
|
||||
<string name="wrong_password">Contraseña incorrecta</string>
|
||||
<string name="protect_application">Proteger aplicación</string>
|
||||
<string name="protect_application_summary">Pide la contraseña al iniciar la aplicación</string>
|
||||
<string name="protect_application_summary">Pedir una contraseña al iniciar Kotatsu</string>
|
||||
<string name="repeat_password">Repite la contraseña</string>
|
||||
<string name="passwords_mismatch">Las contraseñas no coinciden</string>
|
||||
<string name="about">Acerca de</string>
|
||||
@@ -158,8 +157,8 @@
|
||||
<string name="checking_for_updates">Comprobar si hay actualizaciones…</string>
|
||||
<string name="update_check_failed">Fallo en la comprobación de actualizaciones</string>
|
||||
<string name="no_update_available">No hay actualizaciones disponibles</string>
|
||||
<string name="right_to_left">Derecha a izquierda</string>
|
||||
<string name="prefer_rtl_reader">Preferir lector de derecha a izquierda</string>
|
||||
<string name="right_to_left">Derecha a izquierda (←)</string>
|
||||
<string name="prefer_rtl_reader">Preferir lector de derecha a izquierda (→)</string>
|
||||
<string name="prefer_rtl_reader_summary">Puedes configurar el modo de lectura para cada manga por separado</string>
|
||||
<string name="create_category">Nueva categoría</string>
|
||||
<string name="report_github">Crear incidencia en GitHub</string>
|
||||
@@ -171,14 +170,14 @@
|
||||
<string name="black_dark_theme">Tema oscuro auténtico</string>
|
||||
<string name="black_dark_theme_summary">Útil para pantallas AMOLED</string>
|
||||
<string name="restart_required">Se requiere reinicio</string>
|
||||
<string name="backup_restore"><![CDATA[Respaldo y restauración]]></string>
|
||||
<string name="backup_restore">Respaldo y restauración</string>
|
||||
<string name="create_backup">Crear copia de seguridad de datos</string>
|
||||
<string name="restore_backup">Restaurar desde la copia de seguridad</string>
|
||||
<string name="data_restored">Datos restaurados</string>
|
||||
<string name="preparing_">Preparando…</string>
|
||||
<string name="file_not_found">Archivo no encontrado</string>
|
||||
<string name="data_restored_success">Todos los datos fueron restaurados con éxito</string>
|
||||
<string name="data_restored_with_errors">Los datos fueron restaurados, pero hay errores</string>
|
||||
<string name="data_restored_with_errors">Los datos fueron restaurados, pero hay errores.</string>
|
||||
<string name="backup_information">Puedes crear una copia de seguridad de tu historial y favoritos para restaurarla</string>
|
||||
<string name="just_now">Ahora mismo</string>
|
||||
<string name="yesterday">Ayer</string>
|
||||
@@ -194,7 +193,7 @@
|
||||
<string name="cookies_cleared">Se han eliminado todas las cookies</string>
|
||||
<string name="chapters_checking_progress">Buscando nuevos capítulos: %1$d de %2$d</string>
|
||||
<string name="clear_feed">Limpiar feed</string>
|
||||
<string name="text_clear_updates_feed_prompt">Todo el historial de actualizaciones se borrará y esta acción no se puede deshacer. ¿Está seguro?</string>
|
||||
<string name="text_clear_updates_feed_prompt">Todo el historial de actualizaciones se borrará y esta acción no se puede deshacer. ¿Está seguro\?</string>
|
||||
<string name="new_chapters_checking">Comprobación de nuevos capítulos</string>
|
||||
<string name="reverse">Invertir</string>
|
||||
<string name="sign_in">Iniciar sesión</string>
|
||||
@@ -207,14 +206,14 @@
|
||||
<string name="password_length_hint">La contraseña debe tener al menos 4 caracteres</string>
|
||||
<string name="text_local_holder_secondary">Puedes guardarlo desde fuentes in línea o importarlo desde un archivo.</string>
|
||||
<string name="text_local_holder_primary">Todavía no tienes ningún manga guardado</string>
|
||||
<string name="text_history_holder_secondary">Puede encontrar qué leer en el menú lateral.</string>
|
||||
<string name="text_history_holder_primary">El manga que estás leyendo se mostrará aquí</string>
|
||||
<string name="text_history_holder_secondary">Encuentra qué leer en el menú lateral.</string>
|
||||
<string name="text_history_holder_primary">Lo que leas se mostrará aquí</string>
|
||||
<string name="text_empty_holder_primary">Está un poco vacío aquí…</string>
|
||||
<string name="about_gratitudes">Agradecimientos</string>
|
||||
<string name="about_support_developer_summary">Si te gusta esta aplicación, puedes ayudar económicamente a través de Yoomoney (ex. Yandex.Money)</string>
|
||||
<string name="about_support_developer">Apoyar al desarrollador</string>
|
||||
<string name="search_only_on_s">Buscar sólo en %s</string>
|
||||
<string name="about_gratitudes_summary">¡Estas personas hacen que Kotatsu sea mejor!</string>
|
||||
<string name="about_gratitudes_summary">Todas estas personas hicieron que Kotatsu fuera mejor.</string>
|
||||
<string name="about_license">Licencia</string>
|
||||
<string name="about_copyright_and_licenses">Derechos de autor y licencias</string>
|
||||
<string name="chapter_is_missing">Falta un capítulo</string>
|
||||
@@ -237,16 +236,18 @@
|
||||
<string name="state_ongoing">En curso</string>
|
||||
<string name="hide_toolbar">Ocultar la barra de herramientas al desplazarse</string>
|
||||
<string name="chapter_is_missing_text">Este capítulo no aparece en su dispositivo. Descárguelo o léalo en línea.</string>
|
||||
<string name="auth_complete">Autorización completa</string>
|
||||
<string name="auth_complete">Autorizado</string>
|
||||
<string name="about_feedback_4pda">Tema sobre 4PDA</string>
|
||||
<string name="date_format">Formato de la fecha</string>
|
||||
<string name="system_default">Por defecto</string>
|
||||
<string name="tracker_warning">Algunos fabricantes pueden cambiar el comportamiento del sistema, lo que podría interrumpir las tareas en segundo plano.</string>
|
||||
<string name="error_empty_name">El nombre no debe estar vacío</string>
|
||||
<string name="auth_not_supported_by">Autorización en %s no es compatible</string>
|
||||
<string name="text_clear_cookies_prompt">Se cerrará la sesión de todas las fuentes en las que esté autorizado</string>
|
||||
<string name="auth_not_supported_by">No se admite iniciar sesión en %s</string>
|
||||
<string name="text_clear_cookies_prompt">Serás desconectado de todas las fuentes.</string>
|
||||
<string name="exclude_nsfw_from_history">Excluye manga NSFW del historial</string>
|
||||
<string name="show_pages_numbers">Mostrar los números de páginas</string>
|
||||
<string name="enabled_sources">Fuentes activadas</string>
|
||||
<string name="available_sources">Fuentes disponibles</string>
|
||||
<string name="dynamic_theme">Tema dinámico</string>
|
||||
<string name="dynamic_theme_summary">Aplica un tema creado a partir del esquema de colores de su fondo de pantalla</string>
|
||||
</resources>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="close_menu">بستن منو</string>
|
||||
<string name="open_menu">بازکردن منو</string>
|
||||
<string name="local_storage">محل ذخیره سازی</string>
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="wait_for_loading_finish">Attendez la fin du chargement</string>
|
||||
<string name="wait_for_loading_finish">Attendez la fin du chargement…</string>
|
||||
<string name="read_more">Lire la suite</string>
|
||||
<string name="tracker_warning">Certains fabricants peuvent modifier le comportement du système, ce qui peut interrompre les tâches d\'arrière-plan.</string>
|
||||
<string name="backup_saved">Sauvegarde enregistrée avec succès</string>
|
||||
<string name="tracker_warning">Certains appareils ont un comportement différent du système, ce qui peut interrompre les tâches d\'arrière-plan.</string>
|
||||
<string name="backup_saved">Sauvegarde enregistrée</string>
|
||||
<string name="description">Description</string>
|
||||
<string name="welcome">Bienvenue</string>
|
||||
<string name="languages">Langues</string>
|
||||
<string name="other">Autre</string>
|
||||
<string name="text_clear_search_history_prompt">Voulez-vous vraiment supprimer toutes les requêtes de recherche récentes \? Cette action ne peut pas être annulée.</string>
|
||||
<string name="text_clear_search_history_prompt">Supprimer définitivement toutes les requêtes de recherche récentes \?</string>
|
||||
<string name="search_only_on_s">Rechercher uniquement sur %s</string>
|
||||
<string name="hide_toolbar">Masquer la barre d\'outils lors du défilement</string>
|
||||
<string name="password_length_hint">Le mot de passe doit comporter au moins 4 caractères</string>
|
||||
<string name="password_length_hint">Le mot de passe doit comporter 4 caractères ou plus</string>
|
||||
<string name="confirm">Confirmer</string>
|
||||
<string name="protect_application_subtitle">Entrez le mot de passe qui sera demandé au démarrage de l\'application</string>
|
||||
<string name="protect_application_subtitle">Entrez un mot de passe pour démarrer l\'application avec</string>
|
||||
<string name="next">Suivant</string>
|
||||
<string name="_and_x_more">… et %1$d autre(s)</string>
|
||||
<string name="default_s">Par défaut : %s</string>
|
||||
<string name="auth_required">Vous devez autoriser la visualisation de ce contenu</string>
|
||||
<string name="auth_required">Connectez-vous pour voir ce contenu</string>
|
||||
<string name="sign_in">Se connecter</string>
|
||||
<string name="reverse">Inverser</string>
|
||||
<string name="new_chapters_checking">Recherche de nouveaux chapitres</string>
|
||||
<string name="text_clear_updates_feed_prompt">L\'historique des mises à jour sera effacé et cette action ne pourra pas être annulée. Êtes-vous sûr·e \?</string>
|
||||
<string name="new_chapters_checking">À la recherche de nouveaux chapitres…</string>
|
||||
<string name="text_clear_updates_feed_prompt">Effacer définitivement l\'historique des mises à jour \?</string>
|
||||
<string name="clear_feed">Effacer le flux</string>
|
||||
<string name="chapters_checking_progress">Recherche de nouveaux chapitres : %1$d sur %2$d</string>
|
||||
<string name="cookies_cleared">Tous les cookies ont été retirés</string>
|
||||
<string name="clear_cookies">Effacer les cookies</string>
|
||||
<string name="captcha_solve">Résoudre</string>
|
||||
<string name="captcha_required">CAPTCHA est requis</string>
|
||||
<string name="captcha_required">CAPTCHA requis</string>
|
||||
<string name="silent">Silencieux</string>
|
||||
<string name="reader_mode_hint">La configuration choisie sera mémorisée pour ce manga</string>
|
||||
<string name="reader_mode_hint">On se souviendra de la configuration choisie pour ce manga</string>
|
||||
<string name="tap_to_try_again">Appuyez pour réessayer</string>
|
||||
<string name="today">Aujourd\'hui</string>
|
||||
<string name="group">Groupe</string>
|
||||
@@ -38,16 +38,16 @@
|
||||
<string name="just_now">À l\'instant</string>
|
||||
<string name="backup_information">Vous pouvez créer une sauvegarde de votre historique et de vos favoris et la restaurer</string>
|
||||
<string name="data_restored_with_errors">Les données ont été restaurées, mais il y a des erreurs</string>
|
||||
<string name="data_restored_success">Toutes les données ont été restaurées avec succès</string>
|
||||
<string name="data_restored_success">Toutes les données ont été restaurées</string>
|
||||
<string name="file_not_found">Fichier introuvable</string>
|
||||
<string name="preparing_">Préparation…</string>
|
||||
<string name="data_restored">Données restaurées</string>
|
||||
<string name="data_restored">Restauré</string>
|
||||
<string name="restore_backup">Restaurer à partir d\'une sauvegarde</string>
|
||||
<string name="create_backup">Créer une sauvegarde des données</string>
|
||||
<string name="backup_restore">Sauvegarde et restauration</string>
|
||||
<string name="restart_required">Redémarrage nécessaire</string>
|
||||
<string name="black_dark_theme_summary">Utile pour les écrans AMOLED</string>
|
||||
<string name="black_dark_theme">Thème noir foncé</string>
|
||||
<string name="black_dark_theme_summary">Utilise moins d\'énergie pour les écrans AMOLED</string>
|
||||
<string name="black_dark_theme">Noir</string>
|
||||
<string name="zoom_mode_keep_start">Garder au début</string>
|
||||
<string name="zoom_mode_fit_width">Ajuster à la largeur</string>
|
||||
<string name="zoom_mode_fit_height">Ajuster à la hauteur</string>
|
||||
@@ -55,9 +55,9 @@
|
||||
<string name="scale_mode">Mode mise à l\'échelle</string>
|
||||
<string name="report_github">Signaler un problème sur GitHub</string>
|
||||
<string name="create_category">Nouvelle catégorie</string>
|
||||
<string name="prefer_rtl_reader_summary">Vous pouvez configurer le mode de lecture pour chaque manga séparément</string>
|
||||
<string name="prefer_rtl_reader">Préférer le lecteur de droite à gauche</string>
|
||||
<string name="right_to_left">De droite à gauche</string>
|
||||
<string name="prefer_rtl_reader_summary">Le mode de lecture peut être configuré séparément pour chaque série</string>
|
||||
<string name="prefer_rtl_reader">Préférer le lecteur de droite à gauche (→)</string>
|
||||
<string name="right_to_left">De droite à gauche (←)</string>
|
||||
<string name="no_update_available">Aucune mise à jour disponible</string>
|
||||
<string name="update_check_failed">Échec de la recherche de mise à jour</string>
|
||||
<string name="checking_for_updates">Recherche de mises à jour…</string>
|
||||
@@ -66,49 +66,49 @@
|
||||
<string name="about">À propos</string>
|
||||
<string name="passwords_mismatch">Les mots de passe ne correspondent pas</string>
|
||||
<string name="repeat_password">Répéter le mot de passe</string>
|
||||
<string name="protect_application_summary">Demander le mot de passe au démarrage de l\'appli</string>
|
||||
<string name="protect_application_summary">Demander le mot de passe au démarrage de Kotatsu</string>
|
||||
<string name="protect_application">Protéger l\'application</string>
|
||||
<string name="wrong_password">Mot de passe erroné</string>
|
||||
<string name="enter_password">Entrez le mot de passe</string>
|
||||
<string name="dont_check">Ne pas vérifier</string>
|
||||
<string name="track_sources">Vérifier les mises à jour pour les mangas</string>
|
||||
<string name="track_sources">Rechercher les mises à jour</string>
|
||||
<string name="feed_will_update_soon">La mise à jour des flux commencera bientôt</string>
|
||||
<string name="update">Mettre à Jour</string>
|
||||
<string name="rotate_screen">Faire pivoter l\'écran</string>
|
||||
<string name="updates_feed_cleared">Flux de mises à jour effacé</string>
|
||||
<string name="updates_feed_cleared">Effacé</string>
|
||||
<string name="clear_updates_feed">Effacer le flux des mises à jour</string>
|
||||
<string name="waiting_for_network">En attente du réseau…</string>
|
||||
<string name="size_s">Taille : %s</string>
|
||||
<string name="new_version_s">Nouvelle version : %s</string>
|
||||
<string name="related">Connexes</string>
|
||||
<string name="search_results">Résultats de la recherche</string>
|
||||
<string name="text_feed_holder">Ici, vous verrez les nouveaux chapitres du manga que vous lisez</string>
|
||||
<string name="text_feed_holder">Les nouveaux chapitres de ce que vous lisez sont présentés ici</string>
|
||||
<string name="updates">Mises à jour</string>
|
||||
<string name="read_later">Lire plus tard</string>
|
||||
<string name="favourites_category_empty">Cette catégorie est vide</string>
|
||||
<string name="favourites_category_empty">Catégorie vide</string>
|
||||
<string name="all_favourites">Tous les favoris</string>
|
||||
<string name="done">Terminé</string>
|
||||
<string name="use_ssl">Utiliser une connexion sécurisée (HTTPS)</string>
|
||||
<string name="other_storage">Autre stockage</string>
|
||||
<string name="cannot_find_available_storage">Impossible de trouver un stockage disponible</string>
|
||||
<string name="cannot_find_available_storage">Pas de stockage disponible</string>
|
||||
<string name="not_available">Non disponible</string>
|
||||
<string name="manga_save_location">Emplacement des téléchargements de mangas</string>
|
||||
<string name="pages_animation">Animation des pages</string>
|
||||
<string name="recent_manga">Mangas récents</string>
|
||||
<string name="manga_shelf">Étagère à mangas</string>
|
||||
<string name="text_local_holder_secondary">Vous pouvez l\'enregistrer à partir de sources en ligne ou l\'importer à partir d\'un fichier.</string>
|
||||
<string name="text_local_holder_primary">Vous n\'avez pas encore enregistré de manga</string>
|
||||
<string name="text_history_holder_secondary">Vous pouvez trouver ce qu\'il faut lire dans le menu latéral.</string>
|
||||
<string name="text_history_holder_primary">Les mangas que vous lisez seront affichés ici</string>
|
||||
<string name="manga_save_location">Dossier pour les téléchargements</string>
|
||||
<string name="pages_animation">Animation de page</string>
|
||||
<string name="recent_manga">Récents</string>
|
||||
<string name="manga_shelf">Étagère</string>
|
||||
<string name="text_local_holder_secondary">Enregistrez-le à partir de sources en ligne ou importez des fichiers.</string>
|
||||
<string name="text_local_holder_primary">Sauvegardez d\'abord quelque chose</string>
|
||||
<string name="text_history_holder_secondary">Trouvez ce que vous voulez lire dans le menu latéral.</string>
|
||||
<string name="text_history_holder_primary">Ce que vous lisez sera affiché ici</string>
|
||||
<string name="text_search_holder_secondary">Essayez de reformuler la requête.</string>
|
||||
<string name="text_categories_holder">Vous pouvez utiliser des catégories pour organiser vos mangas préférés. Appuyez sur « + » pour créer une catégorie</string>
|
||||
<string name="text_categories_holder">Vous pouvez utiliser des catégories pour organiser vos favoris. Appuyez sur « + » pour créer une catégorie</string>
|
||||
<string name="text_empty_holder_primary">C\'est un peu vide ici…</string>
|
||||
<string name="remove_category">Retirer la catégorie</string>
|
||||
<string name="category_delete_confirm">Voulez-vous vraiment supprimer la catégorie « %s » de vos favoris \?
|
||||
<string name="remove_category">Retirer</string>
|
||||
<string name="category_delete_confirm">Retirer la catégorie « %s » de vos favoris \?
|
||||
\nTous les mangas qu\'elle contient seront perdus.</string>
|
||||
<string name="rename">Renommer</string>
|
||||
<string name="categories_">Catégories…</string>
|
||||
<string name="favourites_categories">Catégories de favoris</string>
|
||||
<string name="favourites_categories">Catégories favorites</string>
|
||||
<string name="vibration">Vibration</string>
|
||||
<string name="light_indicator">Indicateur lumineux</string>
|
||||
<string name="notification_sound">Son de notification</string>
|
||||
@@ -118,33 +118,32 @@
|
||||
<string name="download">Télécharger</string>
|
||||
<string name="show_notification_new_chapters">Avertir des mises à jour des mangas que vous lisez</string>
|
||||
<string name="new_chapters">Nouveaux chapitres</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Activé %1$d sur %2$d</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">%1$d de %2$d activé(s)</string>
|
||||
<string name="notifications">Notifications</string>
|
||||
<string name="large_manga_save_confirm">Ce manga a %s. Voulez-vous l\'enregistrer en entier \?</string>
|
||||
<string name="save_manga">Enregistrer le manga</string>
|
||||
<string name="large_manga_save_confirm">Ce manga a %s. Tout sauvegarder \?</string>
|
||||
<string name="save_manga">Enregistrer</string>
|
||||
<string name="open_in_browser">Ouvrir dans le navigateur</string>
|
||||
<string name="show_notification_app_update">Afficher une notification si une mise à jour est disponible</string>
|
||||
<string name="app_update_available">Une mise à jour de l\'application est disponible</string>
|
||||
<string name="application_update">Vérifier les mises à jour automatiquement</string>
|
||||
<string name="show_notification_app_update">Afficher une notification si une nouvelle version est disponible</string>
|
||||
<string name="app_update_available">Une nouvelle version de l\'application est disponible</string>
|
||||
<string name="application_update">Vérifier les nouvelles versions de l\'application</string>
|
||||
<string name="domain">Domaine</string>
|
||||
<string name="external_storage">Stockage externe</string>
|
||||
<string name="internal_storage">Stockage interne</string>
|
||||
<string name="gestures_only">Gestes uniquement</string>
|
||||
<string name="search_history_cleared">Historique des recherches effacé</string>
|
||||
<string name="search_history_cleared">Effacé</string>
|
||||
<string name="clear_search_history">Effacer l\'historique de recherche</string>
|
||||
<string name="clear_thumbs_cache">Vider le cache des miniatures</string>
|
||||
<string name="error">Erreur</string>
|
||||
<string name="cancelling_">Annulation…</string>
|
||||
<string name="dont_ask_again">Ne plus demander</string>
|
||||
<string name="network_consumption_warning">Cette opération peut consommer beaucoup de trafic réseau</string>
|
||||
<string name="network_consumption_warning">Ceci peut transférer beaucoup de données</string>
|
||||
<string name="warning">Avertissement</string>
|
||||
<string name="_continue">Continuer</string>
|
||||
<string name="volume_buttons">Boutons de volume</string>
|
||||
<string name="taps_on_edges">Appuis sur les bords</string>
|
||||
<string name="taps_on_edges">Appuis au bord</string>
|
||||
<string name="switch_pages">Changer de pages</string>
|
||||
<string name="reader_settings">Paramètres du lecteur</string>
|
||||
<string name="text_delete_local_manga">Voulez-vous vraiment supprimer « %s » de la mémoire locale de votre téléphone \?
|
||||
\nCette opération ne peut pas être annulée.</string>
|
||||
<string name="text_delete_local_manga">Supprimer « %s » de l\'appareil de façon permanente \?</string>
|
||||
<string name="delete_manga">Supprimer le manga</string>
|
||||
<string name="search_on_s">Rechercher sur %s</string>
|
||||
<string name="grid_size">Taille de la grille</string>
|
||||
@@ -153,23 +152,23 @@
|
||||
<string name="standard">Standard</string>
|
||||
<string name="text_file_sizes">o|ko|Mo|Go|To</string>
|
||||
<string name="cache">Cache</string>
|
||||
<string name="clear_pages_cache">Vider le cache des pages</string>
|
||||
<string name="clear_pages_cache">Vider le cache de la page</string>
|
||||
<string name="history_and_cache">Historique et cache</string>
|
||||
<string name="no_description">Aucune description</string>
|
||||
<string name="text_file_not_supported">Fichier invalide. Seuls les fichiers ZIP et CBZ sont pris en charge.</string>
|
||||
<string name="text_file_not_supported">Choisissez un fichier ZIP ou CBZ.</string>
|
||||
<string name="operation_not_supported">Cette opération n\'est pas prise en charge</string>
|
||||
<string name="delete">Supprimer</string>
|
||||
<string name="_import">Importer</string>
|
||||
<string name="share_image">Partager l\'image</string>
|
||||
<string name="page_saved">Page sauvegardée avec succès</string>
|
||||
<string name="page_saved">Sauvegardé</string>
|
||||
<string name="save_page">Sauvegarder la page</string>
|
||||
<string name="_s_deleted_from_local_storage">« %s » supprimé du stockage local</string>
|
||||
<string name="_s_removed_from_history">« %s » retiré de l\'historique</string>
|
||||
<string name="remove">Retirer</string>
|
||||
<string name="text_clear_history_prompt">Voulez-vous vraiment effacer tout votre historique de lecture \? Cette action ne peut pas être annulée.</string>
|
||||
<string name="text_clear_history_prompt">Effacer définitivement l\'historique de lecture \?</string>
|
||||
<string name="clear">Effacer</string>
|
||||
<string name="pages">Pages</string>
|
||||
<string name="automatic">Automatique</string>
|
||||
<string name="automatic">Suivre le système</string>
|
||||
<string name="dark">Sombre</string>
|
||||
<string name="light">Clair</string>
|
||||
<string name="theme">Thème</string>
|
||||
@@ -177,15 +176,15 @@
|
||||
<string name="genre">Genre</string>
|
||||
<string name="sort_order">Ordre de tri</string>
|
||||
<string name="all">Tous</string>
|
||||
<string name="by_rating">Par évaluation</string>
|
||||
<string name="by_rating">Évaluation</string>
|
||||
<string name="newest">Le plus récent</string>
|
||||
<string name="updated">Mis à jour</string>
|
||||
<string name="popular">Populaire</string>
|
||||
<string name="by_name">Par nom</string>
|
||||
<string name="by_name">Nom</string>
|
||||
<string name="downloads">Téléchargements</string>
|
||||
<string name="download_complete">Téléchargement terminé</string>
|
||||
<string name="download_complete">Téléchargé</string>
|
||||
<string name="processing_">Traitement…</string>
|
||||
<string name="manga_downloading_">Téléchargement de mangas…</string>
|
||||
<string name="manga_downloading_">Téléchargement…</string>
|
||||
<string name="search_manga">Rechercher un manga</string>
|
||||
<string name="search">Rechercher</string>
|
||||
<string name="share_s">Partager %s</string>
|
||||
@@ -194,12 +193,12 @@
|
||||
<string name="save">Enregistrer</string>
|
||||
<string name="enter_category_name">Entrez le nom de la catégorie</string>
|
||||
<string name="add">Ajouter</string>
|
||||
<string name="add_new_category">Ajouter une nouvelle catégorie</string>
|
||||
<string name="add_new_category">Nouvelle catégorie</string>
|
||||
<string name="add_to_favourites">Ajouter aux favoris</string>
|
||||
<string name="you_have_not_favourites_yet">Vous n\'avez pas encore de favoris</string>
|
||||
<string name="you_have_not_favourites_yet">Aucun favori pour le moment</string>
|
||||
<string name="add_bookmark">Ajouter un marque-page</string>
|
||||
<string name="read">Lire</string>
|
||||
<string name="history_is_empty">L\'historique est vide</string>
|
||||
<string name="history_is_empty">Pas encore d\'historique</string>
|
||||
<string name="nothing_found">Rien n\'a été trouvé</string>
|
||||
<string name="clear_history">Effacer l\'historique</string>
|
||||
<string name="try_again">Réessayer</string>
|
||||
@@ -214,22 +213,22 @@
|
||||
<string name="list">Liste</string>
|
||||
<string name="chapters">Chapitres</string>
|
||||
<string name="details">Détails</string>
|
||||
<string name="network_error">Erreur de connexion au réseau</string>
|
||||
<string name="network_error">Impossible de se connecter à Internet</string>
|
||||
<string name="error_occurred">Une erreur s\'est produite</string>
|
||||
<string name="history">Historique</string>
|
||||
<string name="favourites">Favoris</string>
|
||||
<string name="local_storage">Stockage local</string>
|
||||
<string name="open_menu">Ouvrir le menu</string>
|
||||
<string name="close_menu">Fermer le menu</string>
|
||||
<string name="chapter_is_missing">Chapitre manquant</string>
|
||||
<string name="chapter_is_missing_text">Ce chapitre est manquant sur votre appareil. Téléchargez-le ou lisez-le en ligne.</string>
|
||||
<string name="text_downloads_holder">Il n\'y a actuellement aucun téléchargement actif</string>
|
||||
<string name="chapter_is_missing">Le chapitre est manquant</string>
|
||||
<string name="chapter_is_missing_text">Téléchargez ou lisez ce chapitre manquant en ligne.</string>
|
||||
<string name="text_downloads_holder">Aucun téléchargement actif</string>
|
||||
<string name="queued">En file d\'attente</string>
|
||||
<string name="about_support_developer_summary">Si vous aimez cette application, vous pouvez aider financièrement par le biais de Yoomoney (Yandex.Money)</string>
|
||||
<string name="about_support_developer_summary">Si vous aimez cette application, vous pouvez envoyer de l\'argent via Yoomoney (ex. Yandex.Money)</string>
|
||||
<string name="about_support_developer">Soutenir le concepteur</string>
|
||||
<string name="about_license">Licence</string>
|
||||
<string name="about_copyright_and_licenses">Droits d\'auteur et licences</string>
|
||||
<string name="about_gratitudes_summary">Ces gens font que Kotatsu s\'améliore !</string>
|
||||
<string name="about_gratitudes_summary">Ces personnes ont toutes rendu Kotatsu meilleur</string>
|
||||
<string name="about_gratitudes">Remerciements</string>
|
||||
<string name="about_feedback_4pda">Sujet sur 4PDA</string>
|
||||
<string name="about_feedback">Remarques</string>
|
||||
@@ -237,16 +236,18 @@
|
||||
<string name="about_app_translation">Traduction</string>
|
||||
<string name="about_app_translation_summary">Traduire cette application</string>
|
||||
<string name="genres">Genres</string>
|
||||
<string name="text_clear_cookies_prompt">Vous serez déconnecté·e de toutes les sources pour lesquelles vous avez une autorisation</string>
|
||||
<string name="auth_not_supported_by">L\'autorisation sur %s n\'est pas prise en charge</string>
|
||||
<string name="auth_complete">Autorisation complète</string>
|
||||
<string name="text_clear_cookies_prompt">Vous serez déconnecté de toutes les sources</string>
|
||||
<string name="auth_not_supported_by">La connexion sur %s n\'est pas prise en charge</string>
|
||||
<string name="auth_complete">Autorisé</string>
|
||||
<string name="state_finished">Terminé</string>
|
||||
<string name="state_ongoing">En cours</string>
|
||||
<string name="date_format">Format de la date</string>
|
||||
<string name="system_default">Par défaut</string>
|
||||
<string name="exclude_nsfw_from_history">Exclure les mangas osés de l\'historique</string>
|
||||
<string name="error_empty_name">Le nom ne doit pas être vide</string>
|
||||
<string name="show_pages_numbers">Afficher les numéros de pages</string>
|
||||
<string name="enabled_sources">Sources activées</string>
|
||||
<string name="error_empty_name">Vous devez entrer un nom</string>
|
||||
<string name="show_pages_numbers">Pages numérotées</string>
|
||||
<string name="enabled_sources">Sources utilisées</string>
|
||||
<string name="available_sources">Sources disponibles</string>
|
||||
<string name="dynamic_theme">Thème dynamique</string>
|
||||
<string name="dynamic_theme_summary">Applique un thème créé d\'après la palette de couleurs de votre fond d\'écran</string>
|
||||
</resources>
|
||||
253
app/src/main/res/values-ja/strings.xml
Normal file
253
app/src/main/res/values-ja/strings.xml
Normal file
@@ -0,0 +1,253 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="history">履歴</string>
|
||||
<string name="loading_">ロード中…</string>
|
||||
<string name="chapter_d_of_d">チャプター %1$d of %2$d</string>
|
||||
<string name="share">共有</string>
|
||||
<string name="clear_history">履歴を削除</string>
|
||||
<string name="search">検索</string>
|
||||
<string name="search_manga">漫画を検索</string>
|
||||
<string name="close">閉じる</string>
|
||||
<string name="favourites">お気に入り</string>
|
||||
<string name="error_occurred">エラーが発生しました</string>
|
||||
<string name="details">詳細</string>
|
||||
<string name="chapters">チャプター</string>
|
||||
<string name="list">リスト</string>
|
||||
<string name="detailed_list">詳細リスト</string>
|
||||
<string name="grid">グリッド</string>
|
||||
<string name="list_mode">リストモード</string>
|
||||
<string name="remote_sources">リモートソース</string>
|
||||
<string name="try_again">再試行</string>
|
||||
<string name="nothing_found">何も見つかりませんでした</string>
|
||||
<string name="history_is_empty">まだ履歴はありません</string>
|
||||
<string name="read">読む</string>
|
||||
<string name="you_have_not_favourites_yet">お気に入りの本はありません</string>
|
||||
<string name="add_to_favourites">お気に入りの本</string>
|
||||
<string name="add_new_category">新たなカテゴリー</string>
|
||||
<string name="add">追加</string>
|
||||
<string name="save">保存</string>
|
||||
<string name="create_shortcut">ショートカットを作成します…</string>
|
||||
<string name="share_s">共有する%s</string>
|
||||
<string name="manga_downloading_">ダウンロード中…</string>
|
||||
<string name="processing_">処理中…</string>
|
||||
<string name="download_complete">ダウンロードした本</string>
|
||||
<string name="downloads">ダウンロード</string>
|
||||
<string name="by_name">名前</string>
|
||||
<string name="popular">人気</string>
|
||||
<string name="local_storage">ローカルストレージ</string>
|
||||
<string name="newest">最新</string>
|
||||
<string name="by_rating">評価</string>
|
||||
<string name="all">全て</string>
|
||||
<string name="sort_order">ソート順に並べ替え</string>
|
||||
<string name="genre">ジャンル</string>
|
||||
<string name="automatic">フォローシステム</string>
|
||||
<string name="clear">クリア</string>
|
||||
<string name="text_clear_history_prompt">すべての履歴を永久にクリアしますか?</string>
|
||||
<string name="remove">削除</string>
|
||||
<string name="_s_removed_from_history">\"%s\"が履歴から削除されました</string>
|
||||
<string name="_s_deleted_from_local_storage">\"%s \"がローカルストレージから削除されました</string>
|
||||
<string name="wait_for_loading_finish">読み込みが完了するまでお待ちください…</string>
|
||||
<string name="save_page">ページを保存</string>
|
||||
<string name="page_saved">保存しました</string>
|
||||
<string name="share_image">画像を共有する</string>
|
||||
<string name="_import">インポート</string>
|
||||
<string name="delete">消去</string>
|
||||
<string name="operation_not_supported">この操作はサポートされていません</string>
|
||||
<string name="no_description">説明がありません</string>
|
||||
<string name="history_and_cache">履歴とキャッシュ</string>
|
||||
<string name="clear_pages_cache">ページのキャッシュをクリアする</string>
|
||||
<string name="text_file_sizes">B|kB|MB|GB|TB</string>
|
||||
<string name="close_menu">閉じる</string>
|
||||
<string name="open_menu">開く</string>
|
||||
<string name="settings">設定</string>
|
||||
<string name="light">ライトテーマ</string>
|
||||
<string name="filter">フィルター</string>
|
||||
<string name="dark">ダークテーマ</string>
|
||||
<string name="pages">ページ</string>
|
||||
<string name="theme">テーマ</string>
|
||||
<string name="network_error">インターネットに接続出来ませんでした</string>
|
||||
<string name="add_bookmark">ブックマークに追加</string>
|
||||
<string name="enter_category_name">カテゴリー名を入力してください</string>
|
||||
<string name="updated">アップデート</string>
|
||||
<string name="cache">キャッシュ</string>
|
||||
<string name="text_file_not_supported">ZIPファイルまたはCBZファイルを選択してください。</string>
|
||||
<string name="standard">標準</string>
|
||||
<string name="webtoon">ウェブトゥーン</string>
|
||||
<string name="read_mode">読み取りモード</string>
|
||||
<string name="grid_size">グリッドのサイズ</string>
|
||||
<string name="search_on_s">%sで検索</string>
|
||||
<string name="delete_manga">漫画を削除</string>
|
||||
<string name="text_delete_local_manga">お使いのデバイスから「%s」を完全に削除しますか?</string>
|
||||
<string name="reader_settings">リーダーの設定</string>
|
||||
<string name="switch_pages">ページを変更</string>
|
||||
<string name="taps_on_edges">エッジタップ</string>
|
||||
<string name="volume_buttons">ボリュームボタン</string>
|
||||
<string name="_continue">続ける</string>
|
||||
<string name="warning">警告</string>
|
||||
<string name="network_consumption_warning">これにより大量のデータが転送される可能性があります</string>
|
||||
<string name="dont_ask_again">二度と表示しない</string>
|
||||
<string name="cancelling_">キャンセル…</string>
|
||||
<string name="error">エラー</string>
|
||||
<string name="clear_thumbs_cache">サムネイルキャッシュをクリア</string>
|
||||
<string name="search_history_cleared">クリア</string>
|
||||
<string name="gestures_only">ジェスチャーのみ</string>
|
||||
<string name="internal_storage">内部ストレージ</string>
|
||||
<string name="domain">ドメイン</string>
|
||||
<string name="application_update">Kotatsuの新しい更新を確認</string>
|
||||
<string name="show_notification_app_update">新しい更新が利用可能かどうか通知を表示</string>
|
||||
<string name="open_in_browser">ブラウザーで開く</string>
|
||||
<string name="large_manga_save_confirm">この漫画には%sがあります。 すべて保存しますか?</string>
|
||||
<string name="save_manga">保存</string>
|
||||
<string name="notifications">通知</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">%2$dの%1$d</string>
|
||||
<string name="new_chapters">新しいチャプター</string>
|
||||
<string name="download">ダウンロード</string>
|
||||
<string name="read_from_start">最初から読む</string>
|
||||
<string name="restart">再開</string>
|
||||
<string name="notifications_settings">通知の設定</string>
|
||||
<string name="notification_sound">通知音</string>
|
||||
<string name="light_indicator">LEDインジケータ</string>
|
||||
<string name="vibration">バイブレーション</string>
|
||||
<string name="favourites_categories">お気に入りのカテゴリー</string>
|
||||
<string name="categories_">カテゴリー…</string>
|
||||
<string name="rename">名前を変更</string>
|
||||
<string name="remove_category">削除</string>
|
||||
<string name="text_search_holder_secondary">クエリを再定式化してみてください。</string>
|
||||
<string name="text_history_holder_primary">読んだ内容がここに表示されます</string>
|
||||
<string name="text_history_holder_secondary">サイドメニューで何を読むかを見つけてください。</string>
|
||||
<string name="text_local_holder_primary">最初に何かを保存する</string>
|
||||
<string name="manga_shelf">本棚</string>
|
||||
<string name="recent_manga">最近</string>
|
||||
<string name="pages_animation">ページアニメーション</string>
|
||||
<string name="manga_save_location">ダウンロード用のフォルダ</string>
|
||||
<string name="not_available">利用出来ません</string>
|
||||
<string name="cannot_find_available_storage">使用可能なストレージがありません</string>
|
||||
<string name="other_storage">その他のストレージ</string>
|
||||
<string name="use_ssl">安全な(HTTPS)接続を使用する</string>
|
||||
<string name="done">完了</string>
|
||||
<string name="all_favourites">全てのお気に入り</string>
|
||||
<string name="read_later">後で読む</string>
|
||||
<string name="updates">更新</string>
|
||||
<string name="text_feed_holder">あなたが読んでいるものの新しいチャプターがここに示されています</string>
|
||||
<string name="search_results">の検索結果</string>
|
||||
<string name="related">関連している本</string>
|
||||
<string name="size_s">サイズ:%s</string>
|
||||
<string name="waiting_for_network">ネットワークに接続されていません…</string>
|
||||
<string name="clear_updates_feed">更新フィードをクリア</string>
|
||||
<string name="updates_feed_cleared">クリア</string>
|
||||
<string name="update">アップデート</string>
|
||||
<string name="feed_will_update_soon">フィードの更新はまもなく開始されます</string>
|
||||
<string name="track_sources">更新を探す</string>
|
||||
<string name="dont_check">チェックしない</string>
|
||||
<string name="protect_application_summary">Kotatsuを起動したときにパスワードを入力する</string>
|
||||
<string name="repeat_password">パスワードを繰り返す</string>
|
||||
<string name="passwords_mismatch">パスワードが違います</string>
|
||||
<string name="about">この本の詳細</string>
|
||||
<string name="app_version">現在のバージョン%s</string>
|
||||
<string name="clear_search_history">検索履歴をクリア</string>
|
||||
<string name="external_storage">外部ストレージ</string>
|
||||
<string name="app_update_available">Kotatsuの新しい更新が利用可能です</string>
|
||||
<string name="show_notification_new_chapters">あなたが読んでいる漫画の更新について通知</string>
|
||||
<string name="text_empty_holder_primary">ここは空っぽです…</string>
|
||||
<string name="text_categories_holder">カテゴリーを使用してお気に入りを整理できます。 «+»を押してカテゴリーを作成出来ます</string>
|
||||
<string name="favourites_category_empty">空のカテゴリー</string>
|
||||
<string name="category_delete_confirm">お気に入りから「%s」カテゴリーを削除しますか?
|
||||
\nその中のすべての漫画は失われます。</string>
|
||||
<string name="text_local_holder_secondary">オンラインソースから保存するかファイルをインポートします。</string>
|
||||
<string name="new_version_s">新しいバージョン:%s</string>
|
||||
<string name="rotate_screen">画面を回転させる</string>
|
||||
<string name="checking_for_updates">アップデートを確認しています…</string>
|
||||
<string name="enter_password">パスワードを入力してください</string>
|
||||
<string name="wrong_password">パスワードが間違っています</string>
|
||||
<string name="protect_application">アプリを保護する</string>
|
||||
<string name="check_for_updates">最新のアップデートを確認する</string>
|
||||
<string name="update_check_failed">アップデートを見つける事が出来ませんでした</string>
|
||||
<string name="no_update_available">利用可能なアップデートはありません</string>
|
||||
<string name="right_to_left">右から左(←)</string>
|
||||
<string name="prefer_rtl_reader">右から左(→)の読書を好む</string>
|
||||
<string name="about_feedback">フィードバック</string>
|
||||
<string name="about_feedback_4pda">4PDAに関する話題</string>
|
||||
<string name="about_support_developer">開発者をサポートします(Yoomoneyが開きます)</string>
|
||||
<string name="about_support_developer_summary">このアプリが気に入ったら、Yoomoney(Yandex.Moneyなど)からサポートできます</string>
|
||||
<string name="about_license">ライセンス</string>
|
||||
<string name="auth_complete">承認済み</string>
|
||||
<string name="auth_not_supported_by">%sへのログインはサポートされていません</string>
|
||||
<string name="state_finished">完成</string>
|
||||
<string name="state_ongoing">進行中</string>
|
||||
<string name="system_default">デフォルト</string>
|
||||
<string name="show_pages_numbers">ナンバリングページ</string>
|
||||
<string name="enabled_sources">使用したソース</string>
|
||||
<string name="available_sources">利用可能なソース</string>
|
||||
<string name="dynamic_theme">ダイナミックなテーマ</string>
|
||||
<string name="dynamic_theme_summary">壁紙の配色に合わせて作成したテーマを適用する</string>
|
||||
<string name="chapters_checking_progress">新しいチャプターの確認:%1$dの%2$d</string>
|
||||
<string name="create_category">新しいカテゴリー</string>
|
||||
<string name="zoom_mode_fit_height">高さを合わせる</string>
|
||||
<string name="hide_toolbar">スクロール時にツールバーを非表示にする</string>
|
||||
<string name="chapter_is_missing">チャプターがありません</string>
|
||||
<string name="text_clear_updates_feed_prompt">すべての更新履歴を完全に消去しますか?</string>
|
||||
<string name="chapter_is_missing_text">この不足した章をダウンロードしたり、オンラインで読んだりすることができます。</string>
|
||||
<string name="auth_required">このコンテンツを表示するにはサインインしてください</string>
|
||||
<string name="file_not_found">ファイルが見つかりません</string>
|
||||
<string name="password_length_hint">パスワードは4文字以上である必要があります</string>
|
||||
<string name="just_now">ちょうど今</string>
|
||||
<string name="long_ago">ずっと前</string>
|
||||
<string name="backup_saved">バックアップを保存</string>
|
||||
<string name="group">グループ</string>
|
||||
<string name="clear_feed">フィードをクリア</string>
|
||||
<string name="restore_backup">バックアップから復元</string>
|
||||
<string name="confirm">確認</string>
|
||||
<string name="backup_information">履歴とお気に入りのバックアップを作成して復元できます</string>
|
||||
<string name="search_only_on_s">%sでのみ検索</string>
|
||||
<string name="read_more">続きを読む</string>
|
||||
<string name="_and_x_more">...そして%1$dさらに</string>
|
||||
<string name="black_dark_theme">ブラック</string>
|
||||
<string name="other">その他</string>
|
||||
<string name="data_restored_with_errors">データは復元されましたがエラーが発生しました</string>
|
||||
<string name="text_clear_search_history_prompt">最近の検索クエリを全て完全に削除しますか?</string>
|
||||
<string name="zoom_mode_fit_width">幅を合わせる</string>
|
||||
<string name="new_chapters_checking">新しいチャプターを探しています…</string>
|
||||
<string name="languages">言語</string>
|
||||
<string name="protect_application_subtitle">アプリを起動するためのパスワードを入力してください</string>
|
||||
<string name="create_backup">データバックアップを作成</string>
|
||||
<string name="captcha_solve">解決しました</string>
|
||||
<string name="tap_to_try_again">タップして再試行してください</string>
|
||||
<string name="captcha_required">CAPTCHAが必要です</string>
|
||||
<string name="default_s">デフォルト:%s</string>
|
||||
<string name="yesterday">昨日</string>
|
||||
<string name="about_app_translation">翻訳</string>
|
||||
<string name="data_restored_success">全てのデータが復元されました</string>
|
||||
<string name="data_restored">復元</string>
|
||||
<string name="about_author">著者</string>
|
||||
<string name="about_gratitudes">感謝の気持ち</string>
|
||||
<string name="preparing_">準備中…</string>
|
||||
<string name="zoom_mode_keep_start">開始時に維持</string>
|
||||
<string name="description">説明</string>
|
||||
<string name="backup_restore">バックアップと復元</string>
|
||||
<string name="about_copyright_and_licenses">著作権とライセンス</string>
|
||||
<string name="reverse">リバース</string>
|
||||
<string name="reader_mode_hint">選択した構成はこの漫画のために記憶されます</string>
|
||||
<string name="clear_cookies">クッキーを削除</string>
|
||||
<string name="report_github">GitHubでissueを作成する(GitHubのアカウントが必要です)</string>
|
||||
<string name="zoom_mode_fit_center">フィットセンター</string>
|
||||
<string name="text_downloads_holder">アクティブなダウンロードはありません</string>
|
||||
<string name="text_clear_cookies_prompt">全てのソースからログアウトされます</string>
|
||||
<string name="date_format">日付をフォーマット</string>
|
||||
<string name="exclude_nsfw_from_history">NSFW漫画を履歴から除外する</string>
|
||||
<string name="queued">キュー</string>
|
||||
<string name="cookies_cleared">全てのCookieが削除されました</string>
|
||||
<string name="prefer_rtl_reader_summary">読み取りモードはシリーズごとに設定できます</string>
|
||||
<string name="restart_required">再起動が必要です</string>
|
||||
<string name="tracker_warning">一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。</string>
|
||||
<string name="genres">ジャンル</string>
|
||||
<string name="scale_mode">スケールモード</string>
|
||||
<string name="error_empty_name">名前を入力する必要があります</string>
|
||||
<string name="today">今日</string>
|
||||
<string name="about_gratitudes_summary">この人達のお陰でKotatsuがより良くなりました</string>
|
||||
<string name="about_app_translation_summary">Kotatsuを翻訳する(Weblateのサイトを開きます)</string>
|
||||
<string name="next">次のページ</string>
|
||||
<string name="silent">サイレント</string>
|
||||
<string name="sign_in">サインイン</string>
|
||||
<string name="welcome">ようこそ</string>
|
||||
<string name="black_dark_theme_summary">AMOLEDスクリーンでさらに少ない電力を使用</string>
|
||||
</resources>
|
||||
@@ -1,24 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="text_file_sizes">B|kB|MB|GB|TB</string>
|
||||
<string name="cannot_find_available_storage">Finner ikke noen tilgjengelig lagring</string>
|
||||
<string name="manga_save_location">Nedlastingssted</string>
|
||||
<string name="text_local_holder_secondary">Du kan lagre fra nettbaserte kilder, eller importere filer.</string>
|
||||
<string name="cannot_find_available_storage">Ingen tilgjengelig lagring</string>
|
||||
<string name="manga_save_location">Mappe for nedlastninger</string>
|
||||
<string name="text_local_holder_secondary">Lagre fra nettbaserte kilder, eller importer filer.</string>
|
||||
<string name="tracker_warning">Noen enheter endrer systemoppførselen, noe som kan ødelegge for bakgrunnsoppgaver.</string>
|
||||
<string name="text_clear_search_history_prompt">Fjern alle nylige søkespørringer for godt\?</string>
|
||||
<string name="hide_toolbar">Skjul verktøylinje under rulling</string>
|
||||
<string name="password_length_hint">Passord må være minst fire tegn</string>
|
||||
<string name="password_length_hint">Passordet må være minst fire tegn</string>
|
||||
<string name="protect_application_subtitle">Skriv inn passord å kreve for å starte programmet</string>
|
||||
<string name="_and_x_more">… og %1$d til</string>
|
||||
<string name="auth_required">Autoriser visning av innholdet</string>
|
||||
<string name="auth_required">Logg inn for å se dette innholdet</string>
|
||||
<string name="reverse">Inverter</string>
|
||||
<string name="new_chapters_checking">Sjekk etter nye kapitler</string>
|
||||
<string name="new_chapters_checking">Sjekker etter nye kapitler…</string>
|
||||
<string name="text_clear_updates_feed_prompt">Tøm all oppdateringshistorikk for godt\?</string>
|
||||
<string name="clear_feed">Tøm flyt</string>
|
||||
<string name="chapters_checking_progress">Ser etter nye kapitler: %1$d av %2$d</string>
|
||||
<string name="reader_mode_hint">Valgt oppsett vil bli husket for denne filen</string>
|
||||
<string name="backup_information">Du kan opprette en sikkerhetskopi av din historikk og favoritter å gjenopprette senere</string>
|
||||
<string name="data_restored_with_errors">Data gjenopprettet, men med feil</string>
|
||||
<string name="data_restored_with_errors">Dataene ble gjenopprettet, men med feil</string>
|
||||
<string name="file_not_found">Fant ikke filen</string>
|
||||
<string name="backup_restore">Sikkerhetskopiering og gjenoppretting</string>
|
||||
<string name="zoom_mode_keep_start">Behold ved oppstart</string>
|
||||
@@ -27,46 +27,47 @@
|
||||
<string name="zoom_mode_fit_center">Tilpass sentrum</string>
|
||||
<string name="scale_mode">Skaleringsmodus</string>
|
||||
<string name="report_github">Opprett feilrapport på GitHub</string>
|
||||
<string name="prefer_rtl_reader_summary">Du kan sette opp lesemodus for hver fil</string>
|
||||
<string name="right_to_left">Høyre-til-venstre ←</string>
|
||||
<string name="prefer_rtl_reader">Foretrekk høyre-til-venstre -leser</string>
|
||||
<string name="prefer_rtl_reader_summary">Lesemodus kan settes opp for hver serie</string>
|
||||
<string name="right_to_left">Høyre-til-venstre (←)</string>
|
||||
<string name="prefer_rtl_reader">Foretrekk høyre-til-venstre (→)-leser</string>
|
||||
<string name="no_update_available">Ingen tilgjengelige oppdateringer</string>
|
||||
<string name="update_check_failed">Kunne ikke se etter oppdateringer</string>
|
||||
<string name="checking_for_updates">Ser etter oppdateringer …</string>
|
||||
<string name="check_for_updates">Se etter oppdateringer</string>
|
||||
<string name="protect_application_summary">Passord ved programoppstart</string>
|
||||
<string name="track_sources">Se etter leseoppdateringer</string>
|
||||
<string name="protect_application_summary">Spør om passord ved programoppstart</string>
|
||||
<string name="track_sources">Se etter oppdateringer</string>
|
||||
<string name="feed_will_update_soon">Flytoppdatering starter snart</string>
|
||||
<string name="update">Oppdater</string>
|
||||
<string name="updates_feed_cleared">Tømt</string>
|
||||
<string name="clear_updates_feed">Tøm oppdateringsflyt</string>
|
||||
<string name="waiting_for_network">Venter på nettverkstilknytning …</string>
|
||||
<string name="waiting_for_network">Venter på nettverk …</string>
|
||||
<string name="new_version_s">Ny versjon: %s</string>
|
||||
<string name="text_feed_holder">Her kan du se nye kapitler av det du leser</string>
|
||||
<string name="text_feed_holder">Nye kapitler av det du leser vises her</string>
|
||||
<string name="updates">Oppdatering</string>
|
||||
<string name="use_ssl">Bruk sikker (HTTPS)-tilkobling</string>
|
||||
<string name="other_storage">Annen lagring</string>
|
||||
<string name="manga_shelf">Hylle</string>
|
||||
<string name="text_local_holder_primary">Du har ikke lagret noe enda.</string>
|
||||
<string name="text_history_holder_secondary">Du kan finne ting å lese i sidemenyen.</string>
|
||||
<string name="text_local_holder_primary">Lagre noe først</string>
|
||||
<string name="text_history_holder_secondary">Finn lesestoff i sidemenyen.</string>
|
||||
<string name="text_history_holder_primary">Det du leser vil vises her</string>
|
||||
<string name="text_search_holder_secondary">Prøv å reformulere spørringen.</string>
|
||||
<string name="text_categories_holder">Bruk kategorier til å organisere mapper. Trykk «+» for å opprette en kategori.</string>
|
||||
<string name="text_categories_holder">Du kan bruke kategorier til å organisere mapper. Trykk «+» for å opprette en kategori</string>
|
||||
<string name="text_empty_holder_primary">Det er ganske tomt her …</string>
|
||||
<string name="category_delete_confirm">Fjern «%s»-kategorien fra favoritter og alt i den\?</string>
|
||||
<string name="category_delete_confirm">Fjern «%s»-kategorien fra favorittene\?
|
||||
\nAlle mangaer i den vil bli tapt.</string>
|
||||
<string name="restart">Programomstart</string>
|
||||
<string name="show_notification_new_chapters">Gi merknad om oppdateringer av det du leser</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Skrudde på %1$d av %2$d</string>
|
||||
<string name="large_manga_save_confirm">Denne managaen har %s. Ønsker du å lagre hele\?</string>
|
||||
<string name="open_in_browser">Åpne i filutforsker</string>
|
||||
<string name="show_notification_app_update">Vis merknad hvis ny versjon er tilgjengelig</string>
|
||||
<string name="app_update_available">Ny programversjon tilgjengelig</string>
|
||||
<string name="application_update">Se etter oppdateringer automatisk</string>
|
||||
<string name="search_history_cleared">Søkehistorikk tømt</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">%1$d av %2$d påskrudd</string>
|
||||
<string name="large_manga_save_confirm">Denne mangaen har %s. Lagre hele\?</string>
|
||||
<string name="open_in_browser">Åpne i nettleser</string>
|
||||
<string name="show_notification_app_update">Vis merknad hvis en ny versjon er tilgjengelig</string>
|
||||
<string name="app_update_available">En ny versjon av programmet er tilgjengelig</string>
|
||||
<string name="application_update">Se etter nye versjoner av programmet</string>
|
||||
<string name="search_history_cleared">Tømt</string>
|
||||
<string name="clear_thumbs_cache">Tøm miniatyrbildehurtiglager</string>
|
||||
<string name="network_consumption_warning">Kan laste ned mye data</string>
|
||||
<string name="taps_on_edges">Trykk på kanter</string>
|
||||
<string name="text_delete_local_manga">Slett «%s» fra enhetsminne for godt\?</string>
|
||||
<string name="network_consumption_warning">Dette kan overføre mye data</string>
|
||||
<string name="taps_on_edges">Kanttrykk</string>
|
||||
<string name="text_delete_local_manga">Slett «%s» fra enheten for godt\?</string>
|
||||
<string name="webtoon">Nettserie</string>
|
||||
<string name="standard">Forvalg</string>
|
||||
<string name="cache">Hurtiglager</string>
|
||||
@@ -76,7 +77,7 @@
|
||||
<string name="operation_not_supported">Ustøttet handling</string>
|
||||
<string name="_import">Importer</string>
|
||||
<string name="page_saved">Lagret</string>
|
||||
<string name="wait_for_loading_finish">Vent på at innlastingen fullføres</string>
|
||||
<string name="wait_for_loading_finish">Vent på at innlastingen fullføres…</string>
|
||||
<string name="text_clear_history_prompt">Fjern all lesehistorikk for godt\?</string>
|
||||
<string name="read">Les</string>
|
||||
<string name="nothing_found">Resultatløst</string>
|
||||
@@ -90,9 +91,9 @@
|
||||
<string name="search_only_on_s">Kun søk på %s</string>
|
||||
<string name="confirm">Bekreft</string>
|
||||
<string name="next">Neste</string>
|
||||
<string name="default_s">Forvalg: %s</string>
|
||||
<string name="default_s">Standard: %s</string>
|
||||
<string name="sign_in">Logg inn</string>
|
||||
<string name="cookies_cleared">Alle kaker ble fjernet</string>
|
||||
<string name="cookies_cleared">Alle cookies ble fjernet</string>
|
||||
<string name="clear_cookies">Tøm kaker</string>
|
||||
<string name="captcha_solve">Løs</string>
|
||||
<string name="captcha_required">CAPTCHA kreves</string>
|
||||
@@ -103,19 +104,19 @@
|
||||
<string name="long_ago">Lenge siden</string>
|
||||
<string name="yesterday">I går</string>
|
||||
<string name="just_now">Akkurat nå</string>
|
||||
<string name="data_restored_success">All data gjenopprettet</string>
|
||||
<string name="data_restored_success">All data ble gjenopprettet</string>
|
||||
<string name="preparing_">Forbereder …</string>
|
||||
<string name="data_restored">Data gjenopprettet</string>
|
||||
<string name="restore_backup">Gjenopprett fra sikkerhetskopi</string>
|
||||
<string name="create_backup">Opprett sikkerhetskopi</string>
|
||||
<string name="restart_required">Omstart kreves</string>
|
||||
<string name="black_dark_theme_summary">Nyttig for AMOLED-skjermer</string>
|
||||
<string name="black_dark_theme">Nattsvart drakt</string>
|
||||
<string name="black_dark_theme_summary">Bruker mindre strøm på AMOLED-skjermer</string>
|
||||
<string name="black_dark_theme">Svart</string>
|
||||
<string name="create_category">Ny kategori</string>
|
||||
<string name="app_version">Versjon %s</string>
|
||||
<string name="about">Om</string>
|
||||
<string name="passwords_mismatch">Passordene samsvarer ikke</string>
|
||||
<string name="repeat_password">Gjenta passord</string>
|
||||
<string name="repeat_password">Gjenta passordet</string>
|
||||
<string name="protect_application">Beskytt programmet</string>
|
||||
<string name="wrong_password">Feil passord</string>
|
||||
<string name="enter_password">Skriv inn passord</string>
|
||||
@@ -125,17 +126,17 @@
|
||||
<string name="related">Relatert</string>
|
||||
<string name="search_results">Søkeresultater</string>
|
||||
<string name="read_later">Les senere</string>
|
||||
<string name="favourites_category_empty">Denne kategorien er tom</string>
|
||||
<string name="favourites_category_empty">Tom kategori</string>
|
||||
<string name="all_favourites">Alle favoritter</string>
|
||||
<string name="done">Ferdig</string>
|
||||
<string name="not_available">Ikke tilgjengelig</string>
|
||||
<string name="pages_animation">Sideanimasjon</string>
|
||||
<string name="recent_manga">Nylig manga</string>
|
||||
<string name="remove_category">Fjern kategori</string>
|
||||
<string name="recent_manga">Nylig</string>
|
||||
<string name="remove_category">Fjern</string>
|
||||
<string name="rename">Gi nytt navn</string>
|
||||
<string name="categories_">Kategorier …</string>
|
||||
<string name="favourites_categories">Favorittkategorier</string>
|
||||
<string name="light_indicator">Lysindikator</string>
|
||||
<string name="light_indicator">LED-indikator</string>
|
||||
<string name="vibration">Vibrasjon</string>
|
||||
<string name="notification_sound">Merknadslyd</string>
|
||||
<string name="notifications_settings">Merknadsinnstillinger</string>
|
||||
@@ -143,7 +144,7 @@
|
||||
<string name="download">Last ned</string>
|
||||
<string name="new_chapters">Nye kapittel</string>
|
||||
<string name="notifications">Merknader</string>
|
||||
<string name="save_manga">Lagre manga</string>
|
||||
<string name="save_manga">Lagre</string>
|
||||
<string name="domain">Domene</string>
|
||||
<string name="external_storage">Eksternlagring</string>
|
||||
<string name="internal_storage">Internlagring</string>
|
||||
@@ -170,7 +171,7 @@
|
||||
<string name="remove">Fjern</string>
|
||||
<string name="clear">Tøm</string>
|
||||
<string name="pages">Sider</string>
|
||||
<string name="automatic">Automatisk</string>
|
||||
<string name="automatic">Følg systemet</string>
|
||||
<string name="dark">Mørk</string>
|
||||
<string name="light">Lys</string>
|
||||
<string name="by_name">Navn</string>
|
||||
@@ -186,7 +187,7 @@
|
||||
<string name="downloads">Nedlastinger</string>
|
||||
<string name="download_complete">Nedlastet</string>
|
||||
<string name="processing_">Behandler …</string>
|
||||
<string name="manga_downloading_">Laster ned manga …</string>
|
||||
<string name="manga_downloading_">Laster ned …</string>
|
||||
<string name="search_manga">Søk manga</string>
|
||||
<string name="search">Søk</string>
|
||||
<string name="share_s">Del %s</string>
|
||||
@@ -195,11 +196,11 @@
|
||||
<string name="save">Lagre</string>
|
||||
<string name="enter_category_name">Skriv inn kategorinavn</string>
|
||||
<string name="add">Legg til</string>
|
||||
<string name="add_new_category">Legg til ny kategori</string>
|
||||
<string name="add_to_favourites">Legg til i favoritter</string>
|
||||
<string name="you_have_not_favourites_yet">Du har ingen favoritter enda.</string>
|
||||
<string name="add_new_category">Ny kategori</string>
|
||||
<string name="add_to_favourites">Favorittmerk dette</string>
|
||||
<string name="you_have_not_favourites_yet">Ingen favoritter enda</string>
|
||||
<string name="add_bookmark">Legg til bokmerke</string>
|
||||
<string name="history_is_empty">Historikken er tom</string>
|
||||
<string name="history_is_empty">Ingen historikk enda</string>
|
||||
<string name="clear_history">Tøm historikk</string>
|
||||
<string name="try_again">Prøv igjen</string>
|
||||
<string name="close">Lukk</string>
|
||||
@@ -212,16 +213,16 @@
|
||||
<string name="list">Liste</string>
|
||||
<string name="chapters">Kapittel</string>
|
||||
<string name="details">Detaljer</string>
|
||||
<string name="network_error">Nettverktilkoblingsfeil</string>
|
||||
<string name="network_error">Kunne ikke koble til Internet</string>
|
||||
<string name="error_occurred">En feil inntraff</string>
|
||||
<string name="history">Historikk</string>
|
||||
<string name="favourites">Favoritter</string>
|
||||
<string name="local_storage">Lokallagring</string>
|
||||
<string name="open_menu">Åpne meny</string>
|
||||
<string name="close_menu">Lukk meny</string>
|
||||
<string name="chapter_is_missing_text">Dette kapitlet mangler på din enhet. Last det ned eller les det på nett.</string>
|
||||
<string name="chapter_is_missing">Kapittel mangler</string>
|
||||
<string name="text_downloads_holder">Det er ingen aktive nedlastinger</string>
|
||||
<string name="chapter_is_missing_text">Last ned eller les dette manglende kapittelet på nett.</string>
|
||||
<string name="chapter_is_missing">Kapittelet mangler</string>
|
||||
<string name="text_downloads_holder">Ingen aktive nedlastinger</string>
|
||||
<string name="queued">I kø</string>
|
||||
<string name="state_finished">Fullført</string>
|
||||
<string name="state_ongoing">Pågående</string>
|
||||
@@ -233,18 +234,20 @@
|
||||
<string name="about_support_developer">Støtt utvikleren</string>
|
||||
<string name="about_support_developer_summary">Hvis du liker programmet kan du kronerulle det på Yoomoney (tidligere Yandex.Money)</string>
|
||||
<string name="about_gratitudes">Takk rettes til</string>
|
||||
<string name="about_gratitudes_summary">Folk som gjorde Kotatsu enda bedre.</string>
|
||||
<string name="about_gratitudes_summary">Folk som gjorde Kotatsu enda bedre</string>
|
||||
<string name="about_copyright_and_licenses">Opphavsrett og lisenser</string>
|
||||
<string name="about_license">Lisens</string>
|
||||
<string name="auth_complete">Identitetsbekreftelse fullført</string>
|
||||
<string name="auth_not_supported_by">Identitetsbekreftelse på %s støttes ikke</string>
|
||||
<string name="text_clear_cookies_prompt">Du vil bli utlogget fra alle kilder du pålogget i</string>
|
||||
<string name="auth_complete">Identitetsbekreftet</string>
|
||||
<string name="auth_not_supported_by">Innlogging på %s støttes ikke</string>
|
||||
<string name="text_clear_cookies_prompt">Du vil bli utlogget fra alle kilder</string>
|
||||
<string name="genres">Sjangere</string>
|
||||
<string name="exclude_nsfw_from_history">Utelat NSFW-manga fra historikk</string>
|
||||
<string name="date_format">Datoformat</string>
|
||||
<string name="system_default">Forvalg</string>
|
||||
<string name="error_empty_name">Navn må angis</string>
|
||||
<string name="error_empty_name">Du må angi ett navn</string>
|
||||
<string name="available_sources">Tilgjengelige kilder</string>
|
||||
<string name="show_pages_numbers">Vis sidenummerering</string>
|
||||
<string name="enabled_sources">Påskrudde kilder</string>
|
||||
<string name="show_pages_numbers">Sidenummerering</string>
|
||||
<string name="enabled_sources">Brukte kilder</string>
|
||||
<string name="dynamic_theme">Dynamisk tema</string>
|
||||
<string name="dynamic_theme_summary">Bruker et tema basert på fargene til bakgrunnen din</string>
|
||||
</resources>
|
||||
@@ -8,5 +8,6 @@
|
||||
<color name="errorContainer">#930006</color>
|
||||
<color name="onError">#680003</color>
|
||||
<color name="onErrorContainer">#FFDAD4</color>
|
||||
<color name="scrollbar">#66FFFFFF</color>
|
||||
|
||||
</resources>
|
||||
@@ -3,8 +3,8 @@
|
||||
<string name="open_menu">Abrir menu</string>
|
||||
<string name="local_storage">Armazenamento local</string>
|
||||
<string name="favourites">Favoritos</string>
|
||||
<string name="error_occurred">Ocorreu um erro</string>
|
||||
<string name="network_error">Erro de conexão de rede</string>
|
||||
<string name="error_occurred">Um erro ocorreu</string>
|
||||
<string name="network_error">Não foi possível conectar à Internet</string>
|
||||
<string name="details">Detalhes</string>
|
||||
<string name="list">Lista</string>
|
||||
<string name="detailed_list">Lista detalhada</string>
|
||||
@@ -16,11 +16,11 @@
|
||||
<string name="try_again">Tente novamente</string>
|
||||
<string name="clear_history">Limpar histórico</string>
|
||||
<string name="nothing_found">Nada encontrado</string>
|
||||
<string name="history_is_empty">Histórico vazio</string>
|
||||
<string name="add_bookmark">Add marca páginas</string>
|
||||
<string name="you_have_not_favourites_yet">Você não tem favoritos ainda</string>
|
||||
<string name="add_to_favourites">Adicionar aos favoritos</string>
|
||||
<string name="add">Add</string>
|
||||
<string name="history_is_empty">Sem histórico ainda</string>
|
||||
<string name="add_bookmark">Adicionar marca páginas</string>
|
||||
<string name="you_have_not_favourites_yet">Ainda não há favoritos</string>
|
||||
<string name="add_to_favourites">Favoritar isso</string>
|
||||
<string name="add">Adicionar</string>
|
||||
<string name="enter_category_name">Nomeie a categoria</string>
|
||||
<string name="save">Salvar</string>
|
||||
<string name="share">Compartilhar</string>
|
||||
@@ -28,62 +28,62 @@
|
||||
<string name="share_s">Compartilhar %s</string>
|
||||
<string name="search">Pesquisar</string>
|
||||
<string name="search_manga">Pesquisar mangá</string>
|
||||
<string name="manga_downloading_">Baixando mangá…</string>
|
||||
<string name="download_complete">Download completo</string>
|
||||
<string name="manga_downloading_">Baixando…</string>
|
||||
<string name="download_complete">Baixado</string>
|
||||
<string name="downloads">Downloads</string>
|
||||
<string name="by_name">Por nome</string>
|
||||
<string name="by_name">Nome</string>
|
||||
<string name="popular">Populares</string>
|
||||
<string name="by_rating">Por avaliação</string>
|
||||
<string name="by_rating">Avaliação</string>
|
||||
<string name="all">Todos</string>
|
||||
<string name="sort_order">Ordem de classificação</string>
|
||||
<string name="genre">Gênero</string>
|
||||
<string name="filter">Filtro</string>
|
||||
<string name="dark">Escuro</string>
|
||||
<string name="automatic">Automático</string>
|
||||
<string name="automatic">Siga o sistema</string>
|
||||
<string name="pages">Páginas</string>
|
||||
<string name="clear">Limpar</string>
|
||||
<string name="text_clear_history_prompt">Você realmente quer limpar todo o seu histórico de leitura\? Essa ação não pode ser desfeita.</string>
|
||||
<string name="text_clear_history_prompt">Limpar todo o histórico de leitura permanentemente\?</string>
|
||||
<string name="remove">Remover</string>
|
||||
<string name="_s_removed_from_history">\"%s\" removido do histórico</string>
|
||||
<string name="_s_deleted_from_local_storage">\"%s\" deletado do armazenamento local</string>
|
||||
<string name="wait_for_loading_finish">Aguarde o carregamento para finalizar</string>
|
||||
<string name="wait_for_loading_finish">Aguarde o carregamento terminar…</string>
|
||||
<string name="save_page">Salvar página</string>
|
||||
<string name="page_saved">Página salva com sucesso</string>
|
||||
<string name="page_saved">Salvou</string>
|
||||
<string name="share_image">Compartilhar imagem</string>
|
||||
<string name="_import">Importar</string>
|
||||
<string name="updated">Utualizado</string>
|
||||
<string name="delete">Deletar</string>
|
||||
<string name="operation_not_supported">Essa operação não é suportada</string>
|
||||
<string name="history_and_cache">Histórico e cache</string>
|
||||
<string name="clear_pages_cache">Limpar cache de páginas</string>
|
||||
<string name="clear_pages_cache">Limpar cache de página</string>
|
||||
<string name="cache">Cache</string>
|
||||
<string name="text_file_sizes">B|kB|MB|GB|TB</string>
|
||||
<string name="standard">Padrão</string>
|
||||
<string name="webtoon">Webtoon</string>
|
||||
<string name="read_mode">Modo leitura</string>
|
||||
<string name="grid_size">Tamanho de grade</string>
|
||||
<string name="grid_size">Tamanho da grade</string>
|
||||
<string name="search_on_s">Pesquisar em %s</string>
|
||||
<string name="delete_manga">Deletar mangá</string>
|
||||
<string name="reader_settings">Configurações de leitura</string>
|
||||
<string name="switch_pages">Mudar páginas</string>
|
||||
<string name="taps_on_edges">Cliques na borda</string>
|
||||
<string name="taps_on_edges">Toques de borda</string>
|
||||
<string name="volume_buttons">Botões de volume</string>
|
||||
<string name="network_consumption_warning">Essa operação pode consumir muito tráfego de rede</string>
|
||||
<string name="network_consumption_warning">Isso pode transferir muitos dados</string>
|
||||
<string name="dont_ask_again">Não pergunte novamente</string>
|
||||
<string name="cancelling_">Cancelando…</string>
|
||||
<string name="error">Erro</string>
|
||||
<string name="clear_thumbs_cache">Limpar cache de thumbnails</string>
|
||||
<string name="search_history_cleared">Histórico de pesquisa limpo</string>
|
||||
<string name="search_history_cleared">Limpo</string>
|
||||
<string name="gestures_only">Apenas gestos</string>
|
||||
<string name="internal_storage">Armazenamento interno</string>
|
||||
<string name="external_storage">Armazenamento externo</string>
|
||||
<string name="domain">Domínio</string>
|
||||
<string name="application_update">Verificar automaticamente se há actualizações</string>
|
||||
<string name="app_update_available">Actualização da aplicação está disponível</string>
|
||||
<string name="show_notification_app_update">Mostrar notificação se a actualização estiver disponível</string>
|
||||
<string name="open_in_browser">Aberto no navegador</string>
|
||||
<string name="large_manga_save_confirm">Esta manga tem %s. Quer salvar tudo isto\?</string>
|
||||
<string name="save_manga">Salvar mangá</string>
|
||||
<string name="application_update">Verifique se há novas versões do aplicativo</string>
|
||||
<string name="app_update_available">Uma nova versão do aplicativo está disponível</string>
|
||||
<string name="show_notification_app_update">Mostrar notificação se uma nova versão estiver disponível</string>
|
||||
<string name="open_in_browser">Abrir no navegador da web</string>
|
||||
<string name="large_manga_save_confirm">Este mangá tem %s. Salvar tudo isso\?</string>
|
||||
<string name="save_manga">Salve</string>
|
||||
<string name="notifications">Notificações</string>
|
||||
<string name="new_chapters">Novos capítulos</string>
|
||||
<string name="show_notification_new_chapters">Notifique sobre atualizações do mangá que está lendo</string>
|
||||
@@ -91,11 +91,11 @@
|
||||
<string name="read_from_start">Ler desde o início</string>
|
||||
<string name="restart">Reiniciar</string>
|
||||
<string name="notifications_settings">Configurações das notificações</string>
|
||||
<string name="light_indicator">Indicador luminoso</string>
|
||||
<string name="light_indicator">Indicador LED</string>
|
||||
<string name="close_menu">Fechar menu</string>
|
||||
<string name="remote_sources">Fontes remotas</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="light">Brilho</string>
|
||||
<string name="light">Claro</string>
|
||||
<string name="history">Histórico</string>
|
||||
<string name="read">Ler</string>
|
||||
<string name="processing_">Processando…</string>
|
||||
@@ -104,54 +104,53 @@
|
||||
<string name="no_description">Sem descrição</string>
|
||||
<string name="_continue">Continuar</string>
|
||||
<string name="chapters">Capítulos</string>
|
||||
<string name="add_new_category">Add nova categoria</string>
|
||||
<string name="add_new_category">Nova categoria</string>
|
||||
<string name="warning">Aviso</string>
|
||||
<string name="text_delete_local_manga">Você realmente quer deletar \"%s\" do armazenamento local de seu celular\?
|
||||
\nEssa operação não pode ser desfeita.</string>
|
||||
<string name="text_file_not_supported">Arquivo inválido. Apenas ZIP e CBZ são suportados.</string>
|
||||
<string name="text_delete_local_manga">Excluir \"%s\" do dispositivo permanentemente\?</string>
|
||||
<string name="text_file_not_supported">Escolha um arquivo ZIP ou CBZ.</string>
|
||||
<string name="clear_search_history">Limpar histórico de pesquisa</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Activado %1$d de %2$d</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Ativado %1$d de %2$d</string>
|
||||
<string name="notification_sound">Som de notificação</string>
|
||||
<string name="show_pages_numbers">Mostrar números de páginas</string>
|
||||
<string name="show_pages_numbers">Páginas numeradas</string>
|
||||
<string name="state_finished">Concluído</string>
|
||||
<string name="state_ongoing">em andamento</string>
|
||||
<string name="state_ongoing">Em andamento</string>
|
||||
<string name="categories_">Categorias…</string>
|
||||
<string name="rename">Renomear</string>
|
||||
<string name="remove_category">Remover categoria</string>
|
||||
<string name="remove_category">Remover</string>
|
||||
<string name="text_empty_holder_primary">Está meio vazio aqui…</string>
|
||||
<string name="manga_shelf">Prateleira de manga</string>
|
||||
<string name="manga_shelf">Estante</string>
|
||||
<string name="done">Feito</string>
|
||||
<string name="related">Relacionado</string>
|
||||
<string name="zoom_mode_keep_start">Manter no início</string>
|
||||
<string name="clear_updates_feed">Limpar feed de atualizações</string>
|
||||
<string name="updates_feed_cleared">Feed de atualizações limpo</string>
|
||||
<string name="updates_feed_cleared">Limpo</string>
|
||||
<string name="update">Atualizar</string>
|
||||
<string name="feed_will_update_soon">A atualização do feed começará em breve</string>
|
||||
<string name="track_sources">Confira as atualizações do mangá</string>
|
||||
<string name="track_sources">Procure atualizações</string>
|
||||
<string name="dont_check">Não verifique</string>
|
||||
<string name="enter_password">Digite a senha</string>
|
||||
<string name="wrong_password">Senha incorreta</string>
|
||||
<string name="repeat_password">Repita a senha</string>
|
||||
<string name="passwords_mismatch">As senhas não coincidem</string>
|
||||
<string name="passwords_mismatch">Senhas incompatíveis</string>
|
||||
<string name="about">Cerca de</string>
|
||||
<string name="app_version">Versão %s</string>
|
||||
<string name="check_for_updates">Verifique se há atualizações</string>
|
||||
<string name="checking_for_updates">Verificando atualizações…</string>
|
||||
<string name="no_update_available">Nenhuma atualização disponível</string>
|
||||
<string name="right_to_left">Direita para esquerda</string>
|
||||
<string name="right_to_left">Da direita para a esquerda (←)</string>
|
||||
<string name="create_category">Nova categoria</string>
|
||||
<string name="report_github">Criar problema no GitHub</string>
|
||||
<string name="scale_mode">Modo de escala</string>
|
||||
<string name="zoom_mode_fit_center">Centro de ajuste</string>
|
||||
<string name="zoom_mode_fit_width">Ajustar à largura</string>
|
||||
<string name="restart_required">É necessário reiniciar</string>
|
||||
<string name="backup_restore">Restauração de backup</string>
|
||||
<string name="backup_restore">Backup e restauração</string>
|
||||
<string name="create_backup">Criar backup de dados</string>
|
||||
<string name="restore_backup">Restaurar do backup</string>
|
||||
<string name="data_restored">Dados restaurados</string>
|
||||
<string name="data_restored">Restaurado</string>
|
||||
<string name="preparing_">Preparando…</string>
|
||||
<string name="file_not_found">Arquivo não encontrado</string>
|
||||
<string name="data_restored_success">Todos os dados restaurados com sucesso</string>
|
||||
<string name="data_restored_success">Todos os dados foram restaurados</string>
|
||||
<string name="data_restored_with_errors">Os dados foram restaurados, mas há erros</string>
|
||||
<string name="just_now">Agora mesmo</string>
|
||||
<string name="yesterday">Ontem</string>
|
||||
@@ -160,13 +159,13 @@
|
||||
<string name="today">Hoje</string>
|
||||
<string name="tap_to_try_again">Toque para tentar novamente</string>
|
||||
<string name="silent">Silencioso</string>
|
||||
<string name="captcha_required">O CAPTCHA é obrigatório</string>
|
||||
<string name="captcha_required">CAPTCHA obrigatório</string>
|
||||
<string name="captcha_solve">Resolver</string>
|
||||
<string name="cookies_cleared">Todos os cookies foram removidos</string>
|
||||
<string name="chapters_checking_progress">Verificando novos capítulos: %1$d de %2$d</string>
|
||||
<string name="clear_feed">Limpar feed</string>
|
||||
<string name="text_clear_updates_feed_prompt">Todo o histórico de atualizações será apagado e esta ação não poderá ser desfeita. Tem certeza\?</string>
|
||||
<string name="new_chapters_checking">Verificação de novos capítulos</string>
|
||||
<string name="text_clear_updates_feed_prompt">Limpar todo o histórico de atualizações permanentemente\?</string>
|
||||
<string name="new_chapters_checking">Em busca de novos capítulos…</string>
|
||||
<string name="reverse">Reverter</string>
|
||||
<string name="sign_in">Entrar</string>
|
||||
<string name="default_s">Padrão: %s</string>
|
||||
@@ -174,10 +173,10 @@
|
||||
<string name="next">Próximo</string>
|
||||
<string name="protect_application_subtitle">Digite a senha que será necessária quando o aplicativo for iniciado</string>
|
||||
<string name="confirm">Confirme</string>
|
||||
<string name="password_length_hint">A senha deve ter pelo menos 4 caracteres</string>
|
||||
<string name="password_length_hint">A senha deve ter 4 caracteres ou mais</string>
|
||||
<string name="description">Descrição</string>
|
||||
<string name="backup_saved">Cópias de segurança salvas com sucesso</string>
|
||||
<string name="tracker_warning">Alguns fabricantes podem alterar o comportamento do sistema, o que pode quebrar as tarefas de fundo.</string>
|
||||
<string name="backup_saved">Backup salvo</string>
|
||||
<string name="tracker_warning">Alguns dispositivos têm um comportamento de sistema diferente, o que pode interromper as tarefas em segundo plano.</string>
|
||||
<string name="read_more">Leia mais</string>
|
||||
<string name="hide_toolbar">Ocultar a barra de ferramentas ao rolar</string>
|
||||
<string name="search_only_on_s">Pesquise apenas em %s</string>
|
||||
@@ -185,68 +184,70 @@
|
||||
<string name="languages">Línguas</string>
|
||||
<string name="welcome">Bem vindo</string>
|
||||
<string name="available_sources">Fontes disponíveis</string>
|
||||
<string name="enabled_sources">Fontes ativadas</string>
|
||||
<string name="enabled_sources">Fontes usadas</string>
|
||||
<string name="queued">Enfileirado</string>
|
||||
<string name="text_downloads_holder">No momento, não há downloads ativos</string>
|
||||
<string name="error_empty_name">O nome não deve estar vazio</string>
|
||||
<string name="text_downloads_holder">Nenhum download ativo</string>
|
||||
<string name="error_empty_name">Você deve inserir um nome</string>
|
||||
<string name="about_app_translation_summary">Traduzir esta aplicação</string>
|
||||
<string name="about_author">Autor</string>
|
||||
<string name="about_feedback">Comentar</string>
|
||||
<string name="about_feedback_4pda">Tópico no 4PDA</string>
|
||||
<string name="about_support_developer">Apoiar o desenvolvedor</string>
|
||||
<string name="about_support_developer_summary">Se gostar desta aplicação, pode ajudar financeiramente através de Yoomoney (ex. Yandex.Money)</string>
|
||||
<string name="about_gratitudes">agradecimento</string>
|
||||
<string name="about_gratitudes_summary">Estas pessoas fazem o Kotatsu tornar-se melhor!</string>
|
||||
<string name="about_support_developer_summary">Se você gosta deste aplicativo, você pode enviar dinheiro através do Yoomoney (ex. Yandex.Money)</string>
|
||||
<string name="about_gratitudes">Agradecimentos</string>
|
||||
<string name="about_gratitudes_summary">Todas essas pessoas tornaram o Kotatsu melhor</string>
|
||||
<string name="about_copyright_and_licenses">Direitos de autor e licenças</string>
|
||||
<string name="about_license">Licença</string>
|
||||
<string name="chapter_is_missing_text">Este capítulo está em falta no seu dispositivo. Descarregue ou leia-o online.</string>
|
||||
<string name="chapter_is_missing">Falta um capítulo</string>
|
||||
<string name="auth_complete">Autorização completa</string>
|
||||
<string name="auth_not_supported_by">A autorização em %s não é suportada</string>
|
||||
<string name="chapter_is_missing_text">Baixe ou leia este capítulo perdido online.</string>
|
||||
<string name="chapter_is_missing">O capítulo está em falta</string>
|
||||
<string name="auth_complete">Autorizado</string>
|
||||
<string name="auth_not_supported_by">O login em %s não é suportado</string>
|
||||
<string name="genres">Géneros</string>
|
||||
<string name="about_app_translation">Tradução</string>
|
||||
<string name="text_clear_cookies_prompt">Será desconectado de todas as fontes em que estiver autorizado</string>
|
||||
<string name="text_clear_cookies_prompt">Você será desconectado de todas as fontes</string>
|
||||
<string name="vibration">Vibração</string>
|
||||
<string name="cannot_find_available_storage">Não é possível encontrar nenhum armazenamento disponível</string>
|
||||
<string name="cannot_find_available_storage">Sem armazenamento disponível</string>
|
||||
<string name="favourites_categories">Categorias favoritas</string>
|
||||
<string name="category_delete_confirm">Quer realmente remover a categoria \"%s\" dos seus favoritos\?
|
||||
\nSerá perdido todos os mangas contidos.</string>
|
||||
<string name="text_history_holder_secondary">Pode encontrar o que ler no menu lateral.</string>
|
||||
<string name="text_local_holder_secondary">Pode salvá-lo a partir de fontes online ou importá-lo a partir de ficheiro.</string>
|
||||
<string name="recent_manga">Manga recente</string>
|
||||
<string name="category_delete_confirm">Remover a categoria \"%s\" dos seus favoritos\?
|
||||
\nTodos os mangás nela serão perdidos..</string>
|
||||
<string name="text_history_holder_secondary">Encontre o que ler no menu lateral.</string>
|
||||
<string name="text_local_holder_secondary">Salve-o de fontes online ou importe arquivos.</string>
|
||||
<string name="recent_manga">Recente</string>
|
||||
<string name="other_storage">Outro armazenamento</string>
|
||||
<string name="text_search_holder_secondary">Tente reformular a consulta.</string>
|
||||
<string name="prefer_rtl_reader">Prefira o leitor da direita para a esquerda</string>
|
||||
<string name="prefer_rtl_reader">Prefira o leitor da direita para a esquerda (→)</string>
|
||||
<string name="not_available">Não disponível</string>
|
||||
<string name="size_s">Tamanho: %s</string>
|
||||
<string name="text_history_holder_primary">Mangá que está a ler será afixada aqui</string>
|
||||
<string name="text_local_holder_primary">Ainda não tem nenhuma mangá salvo</string>
|
||||
<string name="pages_animation">Animação de páginas</string>
|
||||
<string name="favourites_category_empty">Esta categoria está vazia</string>
|
||||
<string name="text_history_holder_primary">O que você ler será exibido aqui</string>
|
||||
<string name="text_local_holder_primary">Salve algo primeiro</string>
|
||||
<string name="pages_animation">Animação de página</string>
|
||||
<string name="favourites_category_empty">Categoria vazia</string>
|
||||
<string name="read_later">Leia mais tarde</string>
|
||||
<string name="updates">atualizações</string>
|
||||
<string name="updates">Atualizações</string>
|
||||
<string name="all_favourites">Todos os favoritos</string>
|
||||
<string name="waiting_for_network">À espera de rede…</string>
|
||||
<string name="use_ssl">Utilizar ligação segura (HTTPS)</string>
|
||||
<string name="use_ssl">Usar conexão segura (HTTPS)</string>
|
||||
<string name="search_results">Resultados da pesquisa</string>
|
||||
<string name="text_feed_holder">Aqui verá os novos capítulos do mangá que está a ler</string>
|
||||
<string name="text_feed_holder">Novos capítulos do que você está lendo são mostrados aqui</string>
|
||||
<string name="new_version_s">Nova versão: %s</string>
|
||||
<string name="rotate_screen">Girar a tela</string>
|
||||
<string name="update_check_failed">Falha na verificação de atualização</string>
|
||||
<string name="protect_application">Proteger aplicativo</string>
|
||||
<string name="protect_application_summary">Pedir senha no início do aplicativo</string>
|
||||
<string name="update_check_failed">Não foi possível procurar atualizações</string>
|
||||
<string name="protect_application">Proteja o aplicativo</string>
|
||||
<string name="protect_application_summary">Peça a senha ao iniciar o Kotatsu</string>
|
||||
<string name="zoom_mode_fit_height">Ajustar à altura</string>
|
||||
<string name="black_dark_theme">Tema Black dark</string>
|
||||
<string name="black_dark_theme_summary">Útil para telas AMOLED</string>
|
||||
<string name="black_dark_theme">Escuro</string>
|
||||
<string name="black_dark_theme_summary">Usa menos energia em telas AMOLED</string>
|
||||
<string name="reader_mode_hint">A configuração escolhida será lembrada para este mangá</string>
|
||||
<string name="backup_information">Você pode criar backup de seu histórico e favoritos e restaurá-lo</string>
|
||||
<string name="clear_cookies">Limpar cookies</string>
|
||||
<string name="text_clear_search_history_prompt">Você realmente deseja remover todas as consultas de pesquisa recentes\? Essa ação não pode ser desfeita.</string>
|
||||
<string name="auth_required">Você deve autorizar a visualização deste conteúdo</string>
|
||||
<string name="text_categories_holder">Pode usar categorias para organizar seu mangá favorito. Pressione <<+>> para criar uma categoria</string>
|
||||
<string name="prefer_rtl_reader_summary">Você pode configurar o modo de leitura para cada mangá separadamente</string>
|
||||
<string name="manga_save_location">Local onde serão armazenados os mangás baixados</string>
|
||||
<string name="exclude_nsfw_from_history">Excluir manga NSFW da história</string>
|
||||
<string name="text_clear_search_history_prompt">Remover todas as consultas de pesquisa recentes permanentemente\?</string>
|
||||
<string name="auth_required">Faça login para ver este conteúdo</string>
|
||||
<string name="text_categories_holder">Você pode usar categorias para organizar seus favoritos. Pressione «+» para criar uma categoria</string>
|
||||
<string name="prefer_rtl_reader_summary">O modo de leitura pode ser configurado separadamente para cada série</string>
|
||||
<string name="manga_save_location">Pasta para downloads</string>
|
||||
<string name="exclude_nsfw_from_history">Excluir mangá NSFW do histórico</string>
|
||||
<string name="date_format">Formato da data</string>
|
||||
<string name="system_default">Padrão</string>
|
||||
<string name="dynamic_theme">Tema dinâmico</string>
|
||||
<string name="dynamic_theme_summary">Aplica um tema criado no esquema de cores do seu papel de parede</string>
|
||||
</resources>
|
||||
@@ -6,7 +6,7 @@
|
||||
<string name="favourites">Избранное</string>
|
||||
<string name="history">История</string>
|
||||
<string name="error_occurred">Произошла ошибка</string>
|
||||
<string name="network_error">Ошибка сетевого подключения</string>
|
||||
<string name="network_error">Не удалось подключиться к Интернету</string>
|
||||
<string name="details">Подробности</string>
|
||||
<string name="chapters">Главы</string>
|
||||
<string name="list">Список</string>
|
||||
@@ -21,12 +21,12 @@
|
||||
<string name="try_again">Повторить</string>
|
||||
<string name="clear_history">Очистить историю</string>
|
||||
<string name="nothing_found">Ничего не найдено</string>
|
||||
<string name="history_is_empty">История пуста</string>
|
||||
<string name="history_is_empty">Истории еще нет</string>
|
||||
<string name="read">Читать</string>
|
||||
<string name="add_bookmark">Добавить закладку</string>
|
||||
<string name="you_have_not_favourites_yet">Добавьте интересующую Вас мангу в избранное, чтобы не потерять её</string>
|
||||
<string name="you_have_not_favourites_yet">Избранного пока нет</string>
|
||||
<string name="add_to_favourites">В избранное</string>
|
||||
<string name="add_new_category">Создать категорию</string>
|
||||
<string name="add_new_category">Новая категория</string>
|
||||
<string name="add">Добавить</string>
|
||||
<string name="enter_category_name">Введите название</string>
|
||||
<string name="save">Сохранить</string>
|
||||
@@ -35,37 +35,37 @@
|
||||
<string name="share_s">Поделиться %s</string>
|
||||
<string name="search">Поиск</string>
|
||||
<string name="search_manga">Поиск манги</string>
|
||||
<string name="manga_downloading_">Загрузка манги…</string>
|
||||
<string name="manga_downloading_">Загрузка…</string>
|
||||
<string name="processing_">Обработка…</string>
|
||||
<string name="download_complete">Загрузка завершена</string>
|
||||
<string name="download_complete">Загружено</string>
|
||||
<string name="downloads">Загрузки</string>
|
||||
<string name="by_name">По имени</string>
|
||||
<string name="by_name">Имя</string>
|
||||
<string name="popular">Популярная</string>
|
||||
<string name="updated">Обновлённая</string>
|
||||
<string name="newest">Новая</string>
|
||||
<string name="by_rating">По рейтингу</string>
|
||||
<string name="by_rating">Рейтинг</string>
|
||||
<string name="all">Все</string>
|
||||
<string name="sort_order">Сортировка</string>
|
||||
<string name="sort_order">Порядок сортировки</string>
|
||||
<string name="genre">Жанр</string>
|
||||
<string name="filter">Фильтр</string>
|
||||
<string name="theme">Тема</string>
|
||||
<string name="light">Светлая</string>
|
||||
<string name="dark">Тёмная</string>
|
||||
<string name="automatic">Автоматически</string>
|
||||
<string name="automatic">Следовать системе</string>
|
||||
<string name="pages">Страницы</string>
|
||||
<string name="clear">Очистить</string>
|
||||
<string name="text_clear_history_prompt">Вы уверены, что хотите очистить историю? Это действие нельзя будет отменить.</string>
|
||||
<string name="text_clear_history_prompt">Очистить всю историю чтения полностью\?</string>
|
||||
<string name="remove">Удалить</string>
|
||||
<string name="_s_removed_from_history">«%s» удалено из истории</string>
|
||||
<string name="_s_deleted_from_local_storage">«%s» удалено с устройства</string>
|
||||
<string name="wait_for_loading_finish">Дождитесь окончания загрузки</string>
|
||||
<string name="wait_for_loading_finish">Дождитесь завершения загрузки…</string>
|
||||
<string name="save_page">Сохранить страницу</string>
|
||||
<string name="page_saved">Страница сохранена</string>
|
||||
<string name="page_saved">Сохранено</string>
|
||||
<string name="share_image">Поделиться изображением</string>
|
||||
<string name="_import">Импорт</string>
|
||||
<string name="delete">Удалить</string>
|
||||
<string name="operation_not_supported">Операция не поддерживается</string>
|
||||
<string name="text_file_not_supported">Неподдерживаемый файл. Поддерживаются только ZIP и CBZ.</string>
|
||||
<string name="text_file_not_supported">Выберите ZIP-файл, либо файл CBZ.</string>
|
||||
<string name="no_description">Нет описания</string>
|
||||
<string name="history_and_cache">История и кэш</string>
|
||||
<string name="clear_pages_cache">Очистить кэш страниц</string>
|
||||
@@ -77,31 +77,30 @@
|
||||
<string name="grid_size">Размер таблицы</string>
|
||||
<string name="search_on_s">Поиск по %s</string>
|
||||
<string name="delete_manga">Удалить мангу</string>
|
||||
<string name="text_delete_local_manga">Вы уверены, что хотите удалить «%s» с устройства\?
|
||||
\nЭто действие нельзя будет отменить.</string>
|
||||
<string name="text_delete_local_manga">Удалить \"%s\" с устройства навсегда\?</string>
|
||||
<string name="reader_settings">Настройки чтения</string>
|
||||
<string name="switch_pages">Листание страниц</string>
|
||||
<string name="taps_on_edges">Нажатия по краям</string>
|
||||
<string name="volume_buttons">Кнопки громкости</string>
|
||||
<string name="_continue">Продолжить</string>
|
||||
<string name="warning">Предупреждение</string>
|
||||
<string name="network_consumption_warning">Данная операция может привести к большому расходу траффика</string>
|
||||
<string name="network_consumption_warning">Это может привести к расходу большого количества трафика</string>
|
||||
<string name="dont_ask_again">Больше не спрашивать</string>
|
||||
<string name="cancelling_">Отмена…</string>
|
||||
<string name="error">Ошибка</string>
|
||||
<string name="clear_thumbs_cache">Очистить кэш миниатюр</string>
|
||||
<string name="clear_search_history">Очистить историю поиска</string>
|
||||
<string name="search_history_cleared">История поиска очищена</string>
|
||||
<string name="search_history_cleared">Очищено</string>
|
||||
<string name="gestures_only">Только жесты</string>
|
||||
<string name="internal_storage">Внутренний накопитель</string>
|
||||
<string name="external_storage">Внешнее хранилище</string>
|
||||
<string name="domain">Домен</string>
|
||||
<string name="application_update">Проверять обновление приложения</string>
|
||||
<string name="app_update_available">Доступно обновление приложения</string>
|
||||
<string name="show_notification_app_update">Показывать уведомление при наличии новой версии</string>
|
||||
<string name="open_in_browser">Открыть в браузере</string>
|
||||
<string name="large_manga_save_confirm">В этой манге %s. Вы уверены, что хотите сохранить их все?</string>
|
||||
<string name="save_manga">Сохранить мангу</string>
|
||||
<string name="application_update">Проверять наличие новых версий приложения</string>
|
||||
<string name="app_update_available">Доступна новая версия приложения</string>
|
||||
<string name="show_notification_app_update">Показывать уведомление, если доступна новая версия</string>
|
||||
<string name="open_in_browser">Открыть в веб-браузере</string>
|
||||
<string name="large_manga_save_confirm">В этой манге %s. Сохранить их все\?</string>
|
||||
<string name="save_manga">Сохранить</string>
|
||||
<string name="notifications">Уведомления</string>
|
||||
<string name="enabled_d_of_d">Включено %1$d из %2$d</string>
|
||||
<string name="new_chapters">Новые главы</string>
|
||||
@@ -111,79 +110,79 @@
|
||||
<string name="restart">Перезапустить</string>
|
||||
<string name="notifications_settings">Настройки уведомлений</string>
|
||||
<string name="notification_sound">Звук уведомления</string>
|
||||
<string name="light_indicator">Световая индикация</string>
|
||||
<string name="light_indicator">Светодиодная индикация</string>
|
||||
<string name="vibration">Вибросигнал</string>
|
||||
<string name="favourites_categories">Категории избранного</string>
|
||||
<string name="categories_">Категории…</string>
|
||||
<string name="rename">Переименовать</string>
|
||||
<string name="category_delete_confirm">Вы уверены, что хотите удалить категорию «%s»\?
|
||||
\nВся манга из данной категории будет утеряна.</string>
|
||||
<string name="remove_category">Удалить категорию</string>
|
||||
<string name="category_delete_confirm">Удалить категорию \"%s\" из избранного\?
|
||||
\nВся манга в ней будет потеряна.</string>
|
||||
<string name="remove_category">Удалить</string>
|
||||
<string name="text_empty_holder_primary">Как-то здесь пусто…</string>
|
||||
<string name="text_search_holder_secondary">Попробуйте переформулировать запрос.</string>
|
||||
<string name="text_categories_holder">Категории помогают упорядочивать избранную мангу. Нажмите «+», чтобы создать категорию</string>
|
||||
<string name="text_history_holder_primary">Здесь будет отображаться манга, которую Вы читаете</string>
|
||||
<string name="text_history_holder_secondary">Вы можете найти, что почитать, в боковом меню.</string>
|
||||
<string name="text_local_holder_primary">У Вас пока нет сохранённой манги</string>
|
||||
<string name="text_local_holder_secondary">Вы можете сохранить мангу из онлайн каталога или импортировать из файла.</string>
|
||||
<string name="manga_shelf">Полка с мангой</string>
|
||||
<string name="recent_manga">Недавняя манга</string>
|
||||
<string name="text_categories_holder">Вы можете использовать категории для организации своих избранных. Нажмите «+», чтобы создать категорию</string>
|
||||
<string name="text_history_holder_primary">То, что вы прочитаете, будет отображено здесь</string>
|
||||
<string name="text_history_holder_secondary">Найдите, что почитать, в боковом меню.</string>
|
||||
<string name="text_local_holder_primary">Сохраните что-нибудь</string>
|
||||
<string name="text_local_holder_secondary">Сохраните что-нибудь из онлайн-каталога или импортируйте из файла.</string>
|
||||
<string name="manga_shelf">Полка</string>
|
||||
<string name="recent_manga">Недавнее</string>
|
||||
<string name="pages_animation">Анимация листания</string>
|
||||
<string name="manga_save_location">Место сохранения манги</string>
|
||||
<string name="manga_save_location">Папка для загрузок</string>
|
||||
<string name="not_available">Недоступно</string>
|
||||
<string name="cannot_find_available_storage">Не удалось найти ни одного доступного хранилища</string>
|
||||
<string name="cannot_find_available_storage">Нет доступного хранилища</string>
|
||||
<string name="other_storage">Другое хранилище</string>
|
||||
<string name="use_ssl">Защищённое соединение (HTTPS)</string>
|
||||
<string name="use_ssl">Использовать безопасное (HTTPS) соединение</string>
|
||||
<string name="done">Готово</string>
|
||||
<string name="all_favourites">Всё избранное</string>
|
||||
<string name="favourites_category_empty">В этой категории ничего нет</string>
|
||||
<string name="favourites_category_empty">Категория пуста</string>
|
||||
<string name="read_later">Прочитать позже</string>
|
||||
<string name="updates">Обновления</string>
|
||||
<string name="text_feed_holder">Здесь будут отображаться обновления манги, которую Вы читаете</string>
|
||||
<string name="text_feed_holder">Новые главы из того, что вы читаете, будут показаны здесь</string>
|
||||
<string name="search_results">Результаты поиска</string>
|
||||
<string name="related">Похожие</string>
|
||||
<string name="new_version_s">Новая версия: %s</string>
|
||||
<string name="size_s">Размер: %s</string>
|
||||
<string name="waiting_for_network">Ожидание подключения…</string>
|
||||
<string name="clear_updates_feed">Очистить ленту обновлений</string>
|
||||
<string name="updates_feed_cleared">Лента обновлений очищена</string>
|
||||
<string name="updates_feed_cleared">Очищено</string>
|
||||
<string name="rotate_screen">Повернуть экран</string>
|
||||
<string name="update">Обновить</string>
|
||||
<string name="feed_will_update_soon">Обновление скоро начнётся</string>
|
||||
<string name="track_sources">Проверять обновления манги</string>
|
||||
<string name="track_sources">Следить за обновлениями</string>
|
||||
<string name="dont_check">Не проверять</string>
|
||||
<string name="enter_password">Введите пароль</string>
|
||||
<string name="wrong_password">Неверный пароль</string>
|
||||
<string name="protect_application">Защитить приложение</string>
|
||||
<string name="protect_application_summary">Запрашивать пароль при запуске приложения</string>
|
||||
<string name="protect_application_summary">Запрашивать пароль при запуске Kotatsu</string>
|
||||
<string name="repeat_password">Повторите пароль</string>
|
||||
<string name="passwords_mismatch">Пароли не совпадают</string>
|
||||
<string name="about">О программе</string>
|
||||
<string name="app_version">Версия %s</string>
|
||||
<string name="check_for_updates">Проверить обновления</string>
|
||||
<string name="checking_for_updates">Проверка обновления…</string>
|
||||
<string name="update_check_failed">Ошибка при проверке обновления</string>
|
||||
<string name="update_check_failed">Не удалось проверить обновления</string>
|
||||
<string name="no_update_available">Нет доступных обновлений</string>
|
||||
<string name="right_to_left">Справа налево</string>
|
||||
<string name="prefer_rtl_reader">Предпочитать режим Справа налево</string>
|
||||
<string name="prefer_rtl_reader_summary">Вы можете настроить режим чтения для каждой манги отдельно</string>
|
||||
<string name="right_to_left">Справа налево (←)</string>
|
||||
<string name="prefer_rtl_reader">Предпочитать читать справа налево (←)</string>
|
||||
<string name="prefer_rtl_reader_summary">Режим чтения может быть настроен отдельно для каждой серии</string>
|
||||
<string name="create_category">Создать категорию</string>
|
||||
<string name="scale_mode">Масштабирование</string>
|
||||
<string name="zoom_mode_fit_center">Вписать в экран</string>
|
||||
<string name="zoom_mode_fit_height">Подогнать по высоте</string>
|
||||
<string name="zoom_mode_fit_width">Подогнать по ширине</string>
|
||||
<string name="zoom_mode_keep_start">Исходный размер</string>
|
||||
<string name="black_dark_theme">Чёрная тёмная тема</string>
|
||||
<string name="black_dark_theme_summary">Полезно для AMOLED экранов</string>
|
||||
<string name="black_dark_theme">Чёрная</string>
|
||||
<string name="black_dark_theme_summary">Потребляет меньше энергии на экранах AMOLED</string>
|
||||
<string name="restart_required">Требуется перезапуск</string>
|
||||
<string name="backup_restore">Резервное копирование и восстановление</string>
|
||||
<string name="create_backup">Создать резервную копию</string>
|
||||
<string name="restore_backup">Восстановить данные</string>
|
||||
<string name="data_restored">Данные восстановлены</string>
|
||||
<string name="data_restored">Восстановлено</string>
|
||||
<string name="preparing_">Подготовка…</string>
|
||||
<string name="file_not_found">Файл не найден</string>
|
||||
<string name="data_restored_success">Все данные успешно восстановлены</string>
|
||||
<string name="data_restored_with_errors">Данные восстановлены, но возникли некоторые ошибки</string>
|
||||
<string name="data_restored_success">Все данные были восстановлены</string>
|
||||
<string name="data_restored_with_errors">Данные были восстановлены, но возникли некоторые ошибки</string>
|
||||
<string name="backup_information">Вы можете создать резервную копию избранного и истории и потом восстановить их</string>
|
||||
<string name="just_now">Только что</string>
|
||||
<string name="yesterday">Вчера</string>
|
||||
@@ -196,34 +195,34 @@
|
||||
<string name="captcha_required">Необходимо пройти CAPTCHA</string>
|
||||
<string name="captcha_solve">Пройти</string>
|
||||
<string name="clear_cookies">Очистить куки</string>
|
||||
<string name="cookies_cleared">Все куки удалены</string>
|
||||
<string name="cookies_cleared">Все файлы cookie были удалены</string>
|
||||
<string name="chapters_checking_progress">Проверка новых глав: %1$d из %2$d</string>
|
||||
<string name="clear_feed">Очистить ленту</string>
|
||||
<string name="text_clear_updates_feed_prompt">Вся история обновлений будет очищена и её нельзя будет вернуть. Вы уверены?</string>
|
||||
<string name="new_chapters_checking">Проверка новых глав</string>
|
||||
<string name="text_clear_updates_feed_prompt">Удалить всю историю обновлений навсегда\?</string>
|
||||
<string name="new_chapters_checking">Проверка новых глав…</string>
|
||||
<string name="reverse">В обратном порядке</string>
|
||||
<string name="sign_in">Войти</string>
|
||||
<string name="auth_required">Для просмотра этого контента требуется авторизация</string>
|
||||
<string name="auth_required">Авторизуйтесь, чтобы просмотреть этот контент</string>
|
||||
<string name="default_s">По умолчанию: %s</string>
|
||||
<string name="_and_x_more">…и ещё %1$d</string>
|
||||
<string name="next">Далее</string>
|
||||
<string name="protect_application_subtitle">Введите пароль, который вам понадобится при запуске приложения</string>
|
||||
<string name="protect_application_subtitle">Введите пароль для запуска приложения</string>
|
||||
<string name="confirm">Подтвердить</string>
|
||||
<string name="password_length_hint">Пароль должен содержать не менее 4 символов</string>
|
||||
<string name="password_length_hint">Пароль должен состоять из 4 символов или более</string>
|
||||
<string name="hide_toolbar">Прятать заголовок при прокрутке</string>
|
||||
<string name="search_only_on_s">Поиск только по %s</string>
|
||||
<string name="other">Другие</string>
|
||||
<string name="description">Описание</string>
|
||||
<string name="languages">Языки</string>
|
||||
<string name="welcome">Добро пожаловать</string>
|
||||
<string name="text_clear_search_history_prompt">Вы действительно хотите удалить все недавние поисковые запросы? Это действие не может быть отменено.</string>
|
||||
<string name="backup_saved">Резервная копия успешно сохранена</string>
|
||||
<string name="tracker_warning">Некоторые производители могут изменять поведение системы, нарушая работу фоновых задач.</string>
|
||||
<string name="text_clear_search_history_prompt">Удалить все последние поисковые запросы навсегда\?</string>
|
||||
<string name="backup_saved">Резервная копия сохранена</string>
|
||||
<string name="tracker_warning">Некоторые устройства имеют различное поведение системы, что может привести к нарушению фоновых задач.</string>
|
||||
<string name="read_more">Подробнее</string>
|
||||
<string name="queued">В очереди</string>
|
||||
<string name="text_downloads_holder">На данный момент нет активных загрузок</string>
|
||||
<string name="text_downloads_holder">Нет активных загрузок</string>
|
||||
<string name="chapter_is_missing">Глава отсутствует</string>
|
||||
<string name="chapter_is_missing_text">Эта глава отсутствует на вашем устройстве. Загрузите её или читайте онлайн.</string>
|
||||
<string name="chapter_is_missing_text">Скачайте или прочитайте эту недостающую главу онлайн.</string>
|
||||
<string name="about_app_translation_summary">Помочь с переводом приложения</string>
|
||||
<string name="about_app_translation">Перевод</string>
|
||||
<string name="about_author">Автор</string>
|
||||
@@ -232,20 +231,20 @@
|
||||
<string name="about_support_developer">Поддержать разработчика</string>
|
||||
<string name="about_support_developer_summary">Если вам нравится это приложение, вы можете помочь финансово с помощью ЮMoney (бывш. Яндекс.Деньги)</string>
|
||||
<string name="about_gratitudes">Благодарности</string>
|
||||
<string name="about_gratitudes_summary">Эти люди помогают Kotatsu стать лучше!</string>
|
||||
<string name="about_gratitudes_summary">Все эти люди сделали Kotatsu лучше</string>
|
||||
<string name="about_copyright_and_licenses">Авторские права и лицензии</string>
|
||||
<string name="about_license">Лицензия</string>
|
||||
<string name="auth_complete">Авторизация выполнена</string>
|
||||
<string name="auth_not_supported_by">Авторизация в %s не поддерживается</string>
|
||||
<string name="text_clear_cookies_prompt">Вы выйдете из всех источников, в которых Вы авторизованы</string>
|
||||
<string name="auth_not_supported_by">Вход в %s не поддерживается</string>
|
||||
<string name="text_clear_cookies_prompt">Вы выйдете из всех источников</string>
|
||||
<string name="genres">Жанры</string>
|
||||
<string name="state_finished">Завершено</string>
|
||||
<string name="state_ongoing">Онгоинг</string>
|
||||
<string name="date_format">Формат даты</string>
|
||||
<string name="system_default">По умолчанию</string>
|
||||
<string name="exclude_nsfw_from_history">Исключить NSFW мангу из истории</string>
|
||||
<string name="error_empty_name">Имя не может быть пустым</string>
|
||||
<string name="show_pages_numbers">Показывать номера страниц</string>
|
||||
<string name="error_empty_name">Вы должны ввести имя</string>
|
||||
<string name="show_pages_numbers">Пронумерованные страницы</string>
|
||||
<string name="enabled_sources">Включенные источники</string>
|
||||
<string name="available_sources">Доступные источники</string>
|
||||
<string name="dynamic_theme">Динамическая тема</string>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="loading_">පූරණය වෙමින්…</string>
|
||||
<string name="settings">සැකසුම්</string>
|
||||
<string name="chapters">පරිච්ඡේද</string>
|
||||
|
||||
60
app/src/main/res/values-tr/strings.xml
Normal file
60
app/src/main/res/values-tr/strings.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="network_error">İnternete bağlı olduğunuzdan emin olunuz</string>
|
||||
<string name="close_menu">Menüyü kapat</string>
|
||||
<string name="open_menu">Menüyü aç</string>
|
||||
<string name="local_storage">Dahili Depolama</string>
|
||||
<string name="favourites">Favoriler</string>
|
||||
<string name="history">Geçmiş</string>
|
||||
<string name="chapters">Bölümler</string>
|
||||
<string name="list">Liste</string>
|
||||
<string name="detailed_list">Detaylı liste</string>
|
||||
<string name="grid">Izgara</string>
|
||||
<string name="list_mode">Liste modu</string>
|
||||
<string name="loading_">Yükleniyor…</string>
|
||||
<string name="close">Kapat</string>
|
||||
<string name="try_again">Tekrar dene</string>
|
||||
<string name="clear_history">Geçmişi temizle</string>
|
||||
<string name="nothing_found">Hiçbir şey bulunamadı</string>
|
||||
<string name="history_is_empty">Sen geçmişiniz yok</string>
|
||||
<string name="read">Oku</string>
|
||||
<string name="add_bookmark">Favorilere ekle</string>
|
||||
<string name="you_have_not_favourites_yet">Henüz favorileriniz yok</string>
|
||||
<string name="add_to_favourites">Favoriniz</string>
|
||||
<string name="add_new_category">Yeni kategori</string>
|
||||
<string name="add">Ekle</string>
|
||||
<string name="enter_category_name">Kategori ismi girin</string>
|
||||
<string name="save">Kaydet</string>
|
||||
<string name="share">Paylaş</string>
|
||||
<string name="share_s">%s Paylaş</string>
|
||||
<string name="search">Ara</string>
|
||||
<string name="search_manga">Manga ara</string>
|
||||
<string name="manga_downloading_">İndiriliyor…</string>
|
||||
<string name="processing_">İşleniyor…</string>
|
||||
<string name="download_complete">İndirildi</string>
|
||||
<string name="downloads">İndirilenler</string>
|
||||
<string name="by_name">İsim</string>
|
||||
<string name="updated">Güncellenme</string>
|
||||
<string name="newest">Yeniler</string>
|
||||
<string name="by_rating">Puanlama</string>
|
||||
<string name="all">Hepsi</string>
|
||||
<string name="genre">Tür</string>
|
||||
<string name="filter">Litre</string>
|
||||
<string name="theme">Tema</string>
|
||||
<string name="light">Açık</string>
|
||||
<string name="dark">Koyu</string>
|
||||
<string name="automatic">Takip sistemi</string>
|
||||
<string name="pages">Sayfalar</string>
|
||||
<string name="clear">Temizle</string>
|
||||
<string name="text_clear_history_prompt">Tüm okuma geçmişi kalıcı olarak silinsin mi\?</string>
|
||||
<string name="remove">Kaldır</string>
|
||||
<string name="_s_removed_from_history">\"%s\" geçmişinden kaldırıldı</string>
|
||||
<string name="_s_deleted_from_local_storage">\"%s\" yerel depolama alanından sil</string>
|
||||
<string name="wait_for_loading_finish">Lütfen bitmesini bekleyin…</string>
|
||||
<string name="save_page">Sayfayı kaydet</string>
|
||||
<string name="share_image">Resmi paylaş</string>
|
||||
<string name="popular">Popüler</string>
|
||||
<string name="details">Detaylar</string>
|
||||
<string name="settings">Ayarlar</string>
|
||||
<string name="page_saved">Kaydet</string>
|
||||
</resources>
|
||||
@@ -22,5 +22,6 @@
|
||||
<color name="grey_dark">#212121</color>
|
||||
<color name="dim">#99000000</color>
|
||||
<color name="shadow">#99000000</color>
|
||||
<color name="scrollbar">#66000000</color>
|
||||
|
||||
</resources>
|
||||
@@ -1,22 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="values_theme">
|
||||
<string name="empty" translatable="false" />
|
||||
<string-array name="values_theme" translatable="false">
|
||||
<item>-1</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</string-array>
|
||||
<string-array name="values_reader_switchers">
|
||||
<string-array name="values_reader_switchers" translatable="false">
|
||||
<item>taps</item>
|
||||
<item>volume</item>
|
||||
</string-array>
|
||||
<string-array name="values_reader_switchers_default">
|
||||
<string-array name="values_reader_switchers_default" translatable="false">
|
||||
<item>taps</item>
|
||||
</string-array>
|
||||
<string-array name="values_track_sources">
|
||||
<string-array name="values_track_sources" translatable="false">
|
||||
<item>favourites</item>
|
||||
<item>history</item>
|
||||
</string-array>
|
||||
<string-array name="values_track_sources_default">
|
||||
<string-array name="values_track_sources_default" translatable="false">
|
||||
<item>favourites</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<dimen name="list_footer_height_inner">36dp</dimen>
|
||||
<dimen name="list_footer_height_outer">48dp</dimen>
|
||||
<dimen name="screen_padding">16dp</dimen>
|
||||
<dimen name="feed_dividers_offset">72dp</dimen>
|
||||
|
||||
<!--Text dimens-->
|
||||
<dimen name="text_size_h1">22sp</dimen>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name" translatable="false">Kotatsu</string>
|
||||
<string name="_empty" translatable="false"/>
|
||||
<string name="close_menu">Close menu</string>
|
||||
<string name="open_menu">Open menu</string>
|
||||
<string name="local_storage">Local storage</string>
|
||||
@@ -18,6 +16,7 @@
|
||||
<string name="settings">Settings</string>
|
||||
<string name="remote_sources">Remote sources</string>
|
||||
<string name="loading_">Loading…</string>
|
||||
<string name="computing_">Computing…</string>
|
||||
<string name="chapter_d_of_d">Chapter %1$d of %2$d</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="try_again">Try again</string>
|
||||
@@ -104,7 +103,7 @@
|
||||
<string name="large_manga_save_confirm">This manga has %s. Save all of it?</string>
|
||||
<string name="save_manga">Save</string>
|
||||
<string name="notifications">Notifications</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Turned on %1$d of %2$d</string>
|
||||
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">%1$d of %2$d on</string>
|
||||
<string name="new_chapters">New chapters</string>
|
||||
<string name="show_notification_new_chapters">Notify about updates of manga you are reading</string>
|
||||
<string name="download">Download</string>
|
||||
@@ -168,7 +167,6 @@
|
||||
<string name="prefer_rtl_reader">Prefer right-to-left (→) reader</string>
|
||||
<string name="prefer_rtl_reader_summary">Reading mode can be set up separately for each series</string>
|
||||
<string name="create_category">New category</string>
|
||||
<string name="report_github">Create issue on GitHub</string>
|
||||
<string name="scale_mode">Scale mode</string>
|
||||
<string name="zoom_mode_fit_center">Fit center</string>
|
||||
<string name="zoom_mode_fit_height">Fit to height</string>
|
||||
@@ -177,11 +175,12 @@
|
||||
<string name="black_dark_theme">Black</string>
|
||||
<string name="black_dark_theme_summary">Uses less power on AMOLED screens</string>
|
||||
<string name="restart_required">Restart required</string>
|
||||
<string name="backup_restore"><![CDATA[Backup and restore]]></string>
|
||||
<string name="backup_restore">Backup and restore</string>
|
||||
<string name="create_backup">Create data backup</string>
|
||||
<string name="restore_backup">Restore from backup</string>
|
||||
<string name="data_restored">Restored</string>
|
||||
<string name="preparing_">Preparing…</string>
|
||||
<string name="report_github">Create issue on GitHub</string>
|
||||
<string name="file_not_found">File not found</string>
|
||||
<string name="data_restored_success">All data was restored</string>
|
||||
<string name="data_restored_with_errors">The data was restored, but there are errors</string>
|
||||
@@ -251,6 +250,7 @@
|
||||
<string name="available_sources">Available sources</string>
|
||||
<string name="dynamic_theme">Dynamic theme</string>
|
||||
<string name="dynamic_theme_summary">Applies a theme created on the color scheme of your wallpaper</string>
|
||||
<string name="suggestions">Suggestions</string>
|
||||
<string name="text_suggestion_holder">Start reading manga and you will get personalized suggestions</string>
|
||||
<string name="importing_progress">Importing manga: %1$d of %2$d</string>
|
||||
<string name="suggestions">Suggestions</string>
|
||||
<string name="text_suggestion_holder">Start reading manga and you will get personalized suggestions</string>
|
||||
</resources>
|
||||
@@ -84,6 +84,14 @@
|
||||
<item name="rippleColor">@null</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Kotatsu.RecyclerView" parent="">
|
||||
<item name="fastScrollHorizontalThumbDrawable">@drawable/list_thumb</item>
|
||||
<item name="fastScrollVerticalThumbDrawable">@drawable/list_thumb</item>
|
||||
<item name="fastScrollHorizontalTrackDrawable">@drawable/list_track</item>
|
||||
<item name="fastScrollVerticalTrackDrawable">@drawable/list_track</item>
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.Kotatsu.Switch" parent="">
|
||||
<item name="elevationOverlayEnabled">@bool/elevation_overlay_enabled</item>
|
||||
</style>
|
||||
@@ -140,4 +148,4 @@
|
||||
<item name="android:layout">@layout/pref_slider</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<item name="tabStyle">@style/Widget.Kotatsu.Tabs</item>
|
||||
<item name="switchStyle">@style/Widget.Kotatsu.Switch</item>
|
||||
<item name="materialCardViewStyle">@style/Widget.Material3.CardView.Elevated</item>
|
||||
<item name="recyclerViewStyle">@style/Widget.Kotatsu.RecyclerView</item>
|
||||
|
||||
<!-- Preference text appearance -->
|
||||
<item name="android:textAppearanceListItem">?attr/textAppearanceBodyLarge</item>
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
<external-files-path
|
||||
name="manga-ext"
|
||||
path="/manga" />
|
||||
<files-path
|
||||
name="manga"
|
||||
path="/manga" />
|
||||
<external-files-path
|
||||
name="backups-ext"
|
||||
path="/backups" />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user