Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
e37455e790
|
|||
|
|
36259ba901 | ||
|
|
5b041b9a49 | ||
|
1734e888d6
|
|||
|
9108646cea
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@
|
||||
/.idea/compiler.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/ktlint-plugin.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
/.idea/kotlinScripting.xml
|
||||
/.idea/kotlinc.xml
|
||||
|
||||
@@ -16,8 +16,8 @@ android {
|
||||
applicationId 'org.koitharu.kotatsu'
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
versionCode = 608
|
||||
versionName = '6.5.2'
|
||||
versionCode = 609
|
||||
versionName = '6.5.3'
|
||||
generatedDensities = []
|
||||
testInstrumentationRunner 'org.koitharu.kotatsu.HiltTestRunner'
|
||||
ksp {
|
||||
@@ -82,7 +82,7 @@ afterEvaluate {
|
||||
}
|
||||
dependencies {
|
||||
//noinspection GradleDependency
|
||||
implementation('com.github.KotatsuApp:kotatsu-parsers:4a0e7221b0') {
|
||||
implementation('com.github.KotatsuApp:kotatsu-parsers:a228d71d57') {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@JvmName("mangaIds")
|
||||
fun Collection<Manga>.ids() = mapToSet { it.id }
|
||||
@@ -42,15 +43,17 @@ val MangaState.titleResId: Int
|
||||
MangaState.FINISHED -> R.string.state_finished
|
||||
MangaState.ABANDONED -> R.string.state_abandoned
|
||||
MangaState.PAUSED -> R.string.state_paused
|
||||
MangaState.UPCOMING -> R.string.state_upcoming
|
||||
}
|
||||
|
||||
@get:DrawableRes
|
||||
val MangaState.iconResId: Int
|
||||
get() = when (this) {
|
||||
MangaState.ONGOING -> R.drawable.ic_state_ongoing
|
||||
MangaState.ONGOING -> R.drawable.ic_play
|
||||
MangaState.FINISHED -> R.drawable.ic_state_finished
|
||||
MangaState.ABANDONED -> R.drawable.ic_state_abandoned
|
||||
MangaState.PAUSED -> R.drawable.ic_action_pause
|
||||
MangaState.UPCOMING -> materialR.drawable.ic_clock_black_24dp
|
||||
}
|
||||
|
||||
fun Manga.findChapter(id: Long): MangaChapter? {
|
||||
|
||||
@@ -12,4 +12,5 @@ val SortOrder.titleRes: Int
|
||||
SortOrder.RATING -> R.string.by_rating
|
||||
SortOrder.NEWEST -> R.string.newest
|
||||
SortOrder.ALPHABETICAL -> R.string.by_name
|
||||
SortOrder.ALPHABETICAL_DESC -> R.string.by_name_reverse
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||
import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter
|
||||
import org.koitharu.kotatsu.bookmarks.ui.sheet.BookmarksSheet
|
||||
import org.koitharu.kotatsu.core.model.countChaptersByBranch
|
||||
import org.koitharu.kotatsu.core.model.iconResId
|
||||
import org.koitharu.kotatsu.core.model.titleResId
|
||||
import org.koitharu.kotatsu.core.ui.BaseFragment
|
||||
import org.koitharu.kotatsu.core.ui.BaseListAdapter
|
||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||
@@ -66,7 +68,6 @@ import org.koitharu.kotatsu.list.ui.size.StaticItemSizeResolver
|
||||
import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo
|
||||
@@ -181,28 +182,13 @@ class DetailsFragment :
|
||||
ratingBar.isVisible = false
|
||||
}
|
||||
|
||||
when (manga.state) {
|
||||
MangaState.FINISHED -> infoLayout.textViewState.apply {
|
||||
textAndVisible = resources.getString(R.string.state_finished)
|
||||
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_state_finished)
|
||||
infoLayout.textViewState.apply {
|
||||
manga.state?.let { state ->
|
||||
textAndVisible = resources.getString(state.titleResId)
|
||||
drawableTop = ContextCompat.getDrawable(context, state.iconResId)
|
||||
} ?: run {
|
||||
isVisible = false
|
||||
}
|
||||
|
||||
MangaState.ONGOING -> infoLayout.textViewState.apply {
|
||||
textAndVisible = resources.getString(R.string.state_ongoing)
|
||||
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_state_ongoing)
|
||||
}
|
||||
|
||||
MangaState.ABANDONED -> infoLayout.textViewState.apply {
|
||||
textAndVisible = resources.getString(R.string.state_abandoned)
|
||||
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_state_abandoned)
|
||||
}
|
||||
|
||||
MangaState.PAUSED -> infoLayout.textViewState.apply {
|
||||
textAndVisible = resources.getString(R.string.state_paused)
|
||||
drawableTop = ContextCompat.getDrawable(context, R.drawable.ic_action_pause)
|
||||
}
|
||||
|
||||
null -> infoLayout.textViewState.isVisible = false
|
||||
}
|
||||
if (manga.source == MangaSource.LOCAL) {
|
||||
infoLayout.textViewSource.isVisible = false
|
||||
|
||||
@@ -111,7 +111,7 @@ class ExploreFragment :
|
||||
}
|
||||
|
||||
override fun onListHeaderClick(item: ListHeader, view: View) {
|
||||
startActivity(SettingsActivity.newManageSourcesIntent(view.context))
|
||||
startActivity(Intent(view.context, SourcesCatalogActivity::class.java))
|
||||
}
|
||||
|
||||
override fun onPrimaryButtonClick(tipView: TipView) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.koitharu.kotatsu.list.ui.model.EmptyHint
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.TipModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
@@ -126,24 +125,18 @@ class ExploreViewModel @Inject constructor(
|
||||
randomLoading: Boolean,
|
||||
newSources: Set<MangaSource>,
|
||||
): List<ListModel> {
|
||||
val result = ArrayList<ListModel>(sources.size + 4)
|
||||
val result = ArrayList<ListModel>(sources.size + 3)
|
||||
result += ExploreButtons(randomLoading)
|
||||
if (recommendation != null) {
|
||||
result += ListHeader(R.string.suggestions)
|
||||
result += RecommendationsItem(recommendation)
|
||||
}
|
||||
if (sources.isNotEmpty()) {
|
||||
result += ListHeader(R.string.remote_sources, R.string.manage)
|
||||
if (newSources.isNotEmpty()) {
|
||||
result += TipModel(
|
||||
key = TIP_NEW_SOURCES,
|
||||
title = R.string.new_sources_text,
|
||||
text = R.string.new_sources_text,
|
||||
icon = R.drawable.ic_explore_normal,
|
||||
primaryButtonText = R.string.manage,
|
||||
secondaryButtonText = R.string.discard,
|
||||
)
|
||||
}
|
||||
result += ListHeader(
|
||||
textRes = R.string.remote_sources,
|
||||
buttonTextRes = R.string.catalog,
|
||||
badge = if (newSources.isNotEmpty()) "" else null,
|
||||
)
|
||||
sources.mapTo(result) { MangaSourceItem(it, isGrid) }
|
||||
} else {
|
||||
result += EmptyHint(
|
||||
|
||||
@@ -14,22 +14,37 @@ import com.google.android.material.R as materialR
|
||||
|
||||
@CheckResult
|
||||
fun View.bindBadge(badge: BadgeDrawable?, counter: Int): BadgeDrawable? {
|
||||
return if (counter > 0) {
|
||||
val badgeDrawable = badge ?: initBadge(this)
|
||||
badgeDrawable.number = counter
|
||||
badgeDrawable.isVisible = true
|
||||
badgeDrawable.align(this)
|
||||
badgeDrawable
|
||||
} else {
|
||||
badge?.isVisible = false
|
||||
badge
|
||||
}
|
||||
return bindBadgeImpl(badge, null, counter)
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
fun View.bindBadge(badge: BadgeDrawable?, text: String?): BadgeDrawable? {
|
||||
return bindBadgeImpl(badge, text, 0)
|
||||
}
|
||||
|
||||
fun View.clearBadge(badge: BadgeDrawable?) {
|
||||
BadgeUtils.detachBadgeDrawable(badge, this)
|
||||
}
|
||||
|
||||
private fun View.bindBadgeImpl(
|
||||
badge: BadgeDrawable?,
|
||||
text: String?,
|
||||
counter: Int,
|
||||
): BadgeDrawable? = if (text != null || counter > 0) {
|
||||
val badgeDrawable = badge ?: initBadge(this)
|
||||
if (counter > 0) {
|
||||
badgeDrawable.number = counter
|
||||
} else {
|
||||
badgeDrawable.text = text?.takeUnless { it.isEmpty() }
|
||||
}
|
||||
badgeDrawable.isVisible = true
|
||||
badgeDrawable.align(this)
|
||||
badgeDrawable
|
||||
} else {
|
||||
badge?.isVisible = false
|
||||
badge
|
||||
}
|
||||
|
||||
private fun initBadge(anchor: View): BadgeDrawable {
|
||||
val badge = BadgeDrawable.create(anchor.context)
|
||||
val resources = anchor.resources
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.list.ui.adapter
|
||||
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import org.koitharu.kotatsu.databinding.ItemHeaderButtonBinding
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
@@ -12,6 +13,8 @@ fun listHeaderAD(
|
||||
) = adapterDelegateViewBinding<ListHeader, ListModel, ItemHeaderButtonBinding>(
|
||||
{ inflater, parent -> ItemHeaderButtonBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
var badge: BadgeDrawable? = null
|
||||
|
||||
if (listener != null) {
|
||||
binding.buttonMore.setOnClickListener {
|
||||
listener.onListHeaderClick(item, it)
|
||||
@@ -23,9 +26,11 @@ fun listHeaderAD(
|
||||
if (item.buttonTextRes == 0) {
|
||||
binding.buttonMore.isInvisible = true
|
||||
binding.buttonMore.text = null
|
||||
binding.buttonMore.clearBadge(badge)
|
||||
} else {
|
||||
binding.buttonMore.setText(item.buttonTextRes)
|
||||
binding.buttonMore.isVisible = true
|
||||
badge = itemView.bindBadge(badge, item.badge)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,38 +6,41 @@ import org.koitharu.kotatsu.core.ui.model.DateTimeAgo
|
||||
|
||||
@Suppress("DataClassPrivateConstructor")
|
||||
data class ListHeader private constructor(
|
||||
private val text: CharSequence?,
|
||||
@StringRes private val textRes: Int,
|
||||
private val dateTimeAgo: DateTimeAgo?,
|
||||
private val textRaw: Any,
|
||||
@StringRes val buttonTextRes: Int,
|
||||
val payload: Any?,
|
||||
val badge: String?,
|
||||
) : ListModel {
|
||||
|
||||
constructor(
|
||||
text: CharSequence,
|
||||
@StringRes buttonTextRes: Int = 0,
|
||||
payload: Any? = null,
|
||||
) : this(text, 0, null, buttonTextRes, payload)
|
||||
badge: String? = null,
|
||||
) : this(textRaw = text, buttonTextRes, payload, badge)
|
||||
|
||||
constructor(
|
||||
@StringRes textRes: Int,
|
||||
@StringRes buttonTextRes: Int = 0,
|
||||
payload: Any? = null,
|
||||
) : this(null, textRes, null, buttonTextRes, payload)
|
||||
badge: String? = null,
|
||||
) : this(textRaw = textRes, buttonTextRes, payload, badge)
|
||||
|
||||
constructor(
|
||||
dateTimeAgo: DateTimeAgo,
|
||||
@StringRes buttonTextRes: Int = 0,
|
||||
payload: Any? = null,
|
||||
) : this(null, 0, dateTimeAgo, buttonTextRes, payload)
|
||||
badge: String? = null,
|
||||
) : this(textRaw = dateTimeAgo, buttonTextRes, payload, badge)
|
||||
|
||||
fun getText(context: Context): CharSequence? = when {
|
||||
text != null -> text
|
||||
textRes != 0 -> context.getString(textRes)
|
||||
else -> dateTimeAgo?.format(context.resources)
|
||||
fun getText(context: Context): CharSequence? = when (textRaw) {
|
||||
is CharSequence -> textRaw
|
||||
is Int -> if (textRaw != 0) context.getString(textRaw) else null
|
||||
is DateTimeAgo -> textRaw.format(context.resources)
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
return other is ListHeader && text == other.text && dateTimeAgo == other.dateTimeAgo && textRes == other.textRes
|
||||
return other is ListHeader && textRaw == other.textRaw
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
|
||||
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.container, null))
|
||||
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
|
||||
viewModel.isResumeEnabled.observe(this, this::onResumeEnabledChanged)
|
||||
viewModel.counters.observe(this, ::onCountersChanged)
|
||||
viewModel.feedCounter.observe(this, ::onFeedCounterChanged)
|
||||
viewModel.appUpdate.observe(this, MenuInvalidator(this))
|
||||
viewModel.onFirstStart.observeEvent(this) {
|
||||
WelcomeSheet.show(supportFragmentManager)
|
||||
@@ -278,10 +278,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
|
||||
startActivity(IntentBuilder(this).manga(manga).build(), options)
|
||||
}
|
||||
|
||||
private fun onCountersChanged(counters: Map<NavItem, Int>) {
|
||||
counters.forEach { (navItem, counter) ->
|
||||
navigationDelegate.setCounter(navItem, counter)
|
||||
}
|
||||
private fun onFeedCounterChanged(counter: Int) {
|
||||
navigationDelegate.setCounter(NavItem.FEED, counter)
|
||||
}
|
||||
|
||||
private fun onIncognitoModeChanged(isIncognito: Boolean) {
|
||||
|
||||
@@ -4,15 +4,11 @@ import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
import org.koitharu.kotatsu.core.github.AppUpdateRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.NavItem
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsStateFlow
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
@@ -22,7 +18,6 @@ import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.main.domain.ReadingResumeEnabledUseCase
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import java.util.EnumMap
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
@@ -52,19 +47,8 @@ class MainViewModel @Inject constructor(
|
||||
|
||||
val appUpdate = appUpdateRepository.observeAvailableUpdate()
|
||||
|
||||
val counters = combine(
|
||||
trackingRepository.observeUpdatedMangaCount(),
|
||||
observeNewSourcesCount(),
|
||||
) { tracks, newSources ->
|
||||
val em = EnumMap<NavItem, Int>(NavItem::class.java)
|
||||
em[NavItem.EXPLORE] = newSources
|
||||
em[NavItem.FEED] = tracks
|
||||
em
|
||||
}.stateIn(
|
||||
scope = viewModelScope + Dispatchers.Default,
|
||||
started = SharingStarted.WhileSubscribed(5000),
|
||||
initialValue = emptyMap<NavItem, Int>(),
|
||||
)
|
||||
val feedCounter = trackingRepository.observeUpdatedMangaCount()
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, 0)
|
||||
|
||||
init {
|
||||
launchJob {
|
||||
@@ -87,8 +71,4 @@ class MainViewModel @Inject constructor(
|
||||
fun setIncognitoMode(isEnabled: Boolean) {
|
||||
settings.isIncognitoModeEnabled = isEnabled
|
||||
}
|
||||
|
||||
private fun observeNewSourcesCount() = sourcesRepository.observeNewSources()
|
||||
.map { if (sourcesRepository.isSetupRequired()) 0 else it.size }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@ import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import coil.ImageLoader
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
||||
@@ -21,6 +23,7 @@ import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
import org.koitharu.kotatsu.core.util.ext.toLocale
|
||||
import org.koitharu.kotatsu.databinding.ActivitySourcesCatalogBinding
|
||||
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
||||
import org.koitharu.kotatsu.settings.newsources.NewSourcesDialogFragment
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@@ -31,6 +34,8 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
@Inject
|
||||
lateinit var coil: ImageLoader
|
||||
|
||||
private var newSourcesSnackbar: Snackbar? = null
|
||||
|
||||
override val appBar: AppBarLayout
|
||||
get() = viewBinding.appbar
|
||||
|
||||
@@ -45,6 +50,7 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
val tabMediator = TabLayoutMediator(viewBinding.tabs, viewBinding.pager, pagerAdapter)
|
||||
tabMediator.attach()
|
||||
viewModel.content.observe(this, pagerAdapter)
|
||||
viewModel.hasNewSources.observe(this, ::onHasNewSourcesChanged)
|
||||
viewModel.onActionDone.observeEvent(
|
||||
this,
|
||||
ReversibleActionObserver(viewBinding.pager),
|
||||
@@ -80,4 +86,31 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
viewModel.performSearch(null)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun onHasNewSourcesChanged(hasNewSources: Boolean) {
|
||||
if (hasNewSources) {
|
||||
if (newSourcesSnackbar?.isShownOrQueued == true) {
|
||||
return
|
||||
}
|
||||
val snackbar = Snackbar.make(viewBinding.pager, R.string.new_sources_text, Snackbar.LENGTH_INDEFINITE)
|
||||
snackbar.setAction(R.string.explore) {
|
||||
NewSourcesDialogFragment.show(supportFragmentManager)
|
||||
}
|
||||
snackbar.addCallback(
|
||||
object : Snackbar.Callback() {
|
||||
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
|
||||
super.onDismissed(transientBottomBar, event)
|
||||
if (event == DISMISS_EVENT_SWIPE) {
|
||||
viewModel.skipNewSources()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
snackbar.show()
|
||||
newSourcesSnackbar = snackbar
|
||||
} else {
|
||||
newSourcesSnackbar?.dismiss()
|
||||
newSourcesSnackbar = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ class SourcesCatalogViewModel @Inject constructor(
|
||||
val locales = repository.allMangaSources.mapToSet { it.locale }
|
||||
val locale = MutableStateFlow(Locale.getDefault().language.takeIf { it in locales })
|
||||
|
||||
val hasNewSources = repository.observeNewSources()
|
||||
.map { it.isNotEmpty() }
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, false)
|
||||
|
||||
private val listProducers = locale.map { lc ->
|
||||
createListProducers(lc)
|
||||
}.stateIn(viewModelScope, SharingStarted.Eagerly, createListProducers(locale.value))
|
||||
@@ -71,6 +75,12 @@ class SourcesCatalogViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun skipNewSources() {
|
||||
launchJob {
|
||||
repository.assimilateNewSources()
|
||||
}
|
||||
}
|
||||
|
||||
@MainThread
|
||||
private fun createListProducers(lc: String?): Map<ContentType, SourcesCatalogListProducer> {
|
||||
val types = EnumSet.allOf(ContentType::class.java)
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
<string name="show_reading_indicators">Mostrare gli indicatori di progresso della lettura</string>
|
||||
<string name="data_deletion">Eliminazione dei dati</string>
|
||||
<string name="show_reading_indicators_summary">Mostra la percentuale di lettura nella cronologia e nei preferiti</string>
|
||||
<string name="exclude_nsfw_from_history_summary">I manga contrassegnati come per adulti non verranno mai aggiunti alla cronologia e i vostri progressi non verranno salvati</string>
|
||||
<string name="exclude_nsfw_from_history_summary">I manga contrassegnati come per adulti non verranno mai aggiunti alla cronologia e i progressi non saranno salvati</string>
|
||||
<string name="clear_cookies_summary">Può aiutare in caso di problemi. Tutte le autorizzazioni saranno invalidate</string>
|
||||
<string name="show_all">Mostra tutto</string>
|
||||
<string name="logout">Esci</string>
|
||||
@@ -345,12 +345,12 @@
|
||||
\n Tutti i manga in esso contenuti andranno persi e questo non può essere annullato.</string>
|
||||
<string name="history_shortcuts_summary">Rendere disponibili i manga recenti premendo a lungo sull\'icona dell\'applicazione</string>
|
||||
<string name="reader_info_bar">Mostra la barra delle informazioni nel lettore</string>
|
||||
<string name="manga_error_description_pattern">Dettagli dell\'errore:<br><tt>%1$s</tt><br>1. Prova ad <a href=%2$s>aprire il manga in un browser web</a> per assicurarsi che sia disponibile sulla sua fonte<br>2. Se è disponibile, inviare una segnalazione di errore agli sviluppatori.</string>
|
||||
<string name="manga_error_description_pattern">Dettagli dell\'errore:<br><tt>%1$s</tt><br><br>1. Prova ad <a href=%2$s>aprire il manga in un browser web</a> per assicurarsi che sia disponibile sulla sua fonte<br>2. Controllare di stare usando la <a href=kotatsu://about>versione più recente di Kotatsu</a><br>3. Se è disponibile, inviare una segnalazione di errore agli sviluppatori.</string>
|
||||
<string name="text_unsaved_changes_prompt">Salvare o eliminare le modifiche non salvate\?</string>
|
||||
<string name="discard">Abbandona</string>
|
||||
<string name="language">Lingua</string>
|
||||
<string name="share_logs">Condividi i registri</string>
|
||||
<string name="enable_logging_summary">Registra alcune azioni a scopo di debug</string>
|
||||
<string name="enable_logging_summary">Registra alcune azioni a scopo di debug. Non attivare se non si è sicuri di cosa si stia facendo</string>
|
||||
<string name="enable_logging">Abilita la registrazione</string>
|
||||
<string name="show_suspicious_content">Mostra il contenuto sospetto</string>
|
||||
<string name="theme_name_dynamic">Dinamico</string>
|
||||
@@ -366,7 +366,181 @@
|
||||
<string name="theme_name_rikka">Rikka</string>
|
||||
<string name="theme_name_miku">Miku</string>
|
||||
<string name="allow_unstable_updates">Permetti aggiornamenti instabili</string>
|
||||
<string name="allow_unstable_updates_summary">Proponi aggiornamenti alle versioni beta dell\'app</string>
|
||||
<string name="allow_unstable_updates_summary">Ricevi notifiche riguardo versioni instabili</string>
|
||||
<string name="download_started">Scaricamento iniziato</string>
|
||||
<string name="theme_name_sakura">Sakura</string>
|
||||
<string name="languages">Lingue</string>
|
||||
<string name="zoom_in">Ingrandire</string>
|
||||
<string name="captcha_required_summary">%s richiede il completamento di un captcha per funzionare correttamente</string>
|
||||
<string name="sources_catalog">Catalogo fonti</string>
|
||||
<string name="download_option_all_unread">Tutti i capitoli non letti</string>
|
||||
<string name="frequency_every_day">Ogni giorno</string>
|
||||
<string name="categories">Categorie</string>
|
||||
<string name="progress">Progresso</string>
|
||||
<string name="cancel_all">Annulla tutti</string>
|
||||
<string name="sync_host_description">Puoi usare un server di sincronizzazione self-hosted oppure uno di default. Non cambiare se non si è sicuri di cosa si stia facendo.</string>
|
||||
<string name="error_corrupted_file">Dati non validi in ritorno o file corrotto</string>
|
||||
<string name="pick_custom_directory">Seleziona cartella personalizzata</string>
|
||||
<string name="list_options">Mostra lista opzioni</string>
|
||||
<string name="related_manga_summary">Mostra una lista di manga correlati. In alcuni casi potrebbe essere imprecisa o mancante</string>
|
||||
<string name="remove_completed_downloads_confirm">La tua cronologia dei download sarà permanentemente cancellata</string>
|
||||
<string name="reader_zoom_buttons_summary">Se mostrare o no i tasti di controllo dello zoom in basso a destra</string>
|
||||
<string name="content_type_manga">Manga</string>
|
||||
<string name="tracker_wifi_only_summary">Non controllare nuovi capitoli mentre è in uso una connessione a consumo</string>
|
||||
<string name="error_multiple_states_not_supported">Questa fonte di manga non supporta il filtraggio per multipli stati</string>
|
||||
<string name="order_added">Aggiunto</string>
|
||||
<string name="source_summary_pattern">%1$s, %2$s</string>
|
||||
<string name="on_device">Su dispositivo</string>
|
||||
<string name="password">Password</string>
|
||||
<string name="download_option_whole_manga">L\'intero manga</string>
|
||||
<string name="settings_apply_restart_required">Riavviare l\'applicazione per applicare queste modifiche</string>
|
||||
<string name="backup_frequency">Frequenza creazione backup</string>
|
||||
<string name="data_and_privacy">Dati e privacy</string>
|
||||
<string name="content_type_hentai">Hentai</string>
|
||||
<string name="clear_source_cookies_summary">Pulisci cookies solo per dominio specifico. Nella maggior parte dei casi invaliderà l\'autorizzazione</string>
|
||||
<string name="downloads_wifi_only_summary">Smetti di scaricare quando si passa a rete mobile</string>
|
||||
<string name="suggest_new_sources">Suggerisci nuove fonti dopo aggiornamento dell\'app</string>
|
||||
<string name="user_agent">Intestazione UserAgent</string>
|
||||
<string name="error_filter_states_genre_not_supported">Questa fonte non supporta il filtraggio per sia genere che stato</string>
|
||||
<string name="ignore_ssl_errors">Ignora errori SSL</string>
|
||||
<string name="error_filter_locale_genre_not_supported">Questa fonte non supporta il filtraggio per sia genere che localizzazione</string>
|
||||
<string name="periodic_backups_enable">Abilita backup periodici</string>
|
||||
<string name="server_address">Indirizzo server</string>
|
||||
<string name="content_type_comics">Fumetti</string>
|
||||
<string name="moved_to_top">Spostato in cima</string>
|
||||
<string name="find_similar">Trova simili</string>
|
||||
<string name="data_not_restored_text">Assicurati di aver selezionato il file di backup corretto</string>
|
||||
<string name="catalog">Catalogo</string>
|
||||
<string name="view_list">Vedi lista</string>
|
||||
<string name="welcome_text">Selezionare le fonti di contenuti da abilitare. Si può configurare anche successivamente nelle impostazioni</string>
|
||||
<string name="unknown">Sconosciuto</string>
|
||||
<string name="in_progress">In progresso</string>
|
||||
<string name="download_option_manual_selection">Selezione manuale capitoli</string>
|
||||
<string name="enhanced_colors_summary">Riduce il banding, ma può impattare la performance</string>
|
||||
<string name="pause">Pausa</string>
|
||||
<string name="remove_completed">Rimuovi completati</string>
|
||||
<string name="items_limit_exceeded">Impossibile aggiungere altri oggetti</string>
|
||||
<string name="frequency_every_2_days">Ogni 2 giorni</string>
|
||||
<string name="suggestions_notifications_summary">A volte mostra le notifiche sui manga suggeriti</string>
|
||||
<string name="invalid_value_message">Valore non valido</string>
|
||||
<string name="downloads_cancelled">I download sono stati annullati</string>
|
||||
<string name="reader_optimize">Riduci consumo di memoria (beta)</string>
|
||||
<string name="apply">Applica</string>
|
||||
<string name="restore">Ripristina</string>
|
||||
<string name="data_not_restored">Dati non ripristinati</string>
|
||||
<string name="manage_sources">Gestisci fonti</string>
|
||||
<string name="directories">Cartelle</string>
|
||||
<string name="local_manga_directories">Cartelle manga locali</string>
|
||||
<string name="manage_categories">Gestisci categorie</string>
|
||||
<string name="no_manga_sources_found">Nessuna fonte manga trovata in base alla tua query</string>
|
||||
<string name="color_light">Chiaro</string>
|
||||
<string name="web_view_unavailable">WebView non disponibile: controlla se è installato un provider di WebView</string>
|
||||
<string name="genres_search_hint">Inizia a scrivere il nome del genere</string>
|
||||
<string name="port">Porta</string>
|
||||
<string name="type">Tipo</string>
|
||||
<string name="search_hint">Inserisci titolo manga, genere o nome fonte</string>
|
||||
<string name="frequency_once_per_week">Una volta a settimana</string>
|
||||
<string name="description">Descrizione</string>
|
||||
<string name="periodic_backups">Backup periodici</string>
|
||||
<string name="reader_zoom_buttons">Mostra tasti zoom</string>
|
||||
<string name="sources_reorder_tip">Tocca e tieni premuto su un elemento per riordinarlo</string>
|
||||
<string name="globally">Globalmente</string>
|
||||
<string name="resume">Riprendi</string>
|
||||
<string name="images_proxy_title">Proxy ottimizzazione immagini</string>
|
||||
<string name="username">Nome utente</string>
|
||||
<string name="frequency_twice_per_month">Due volte al mese</string>
|
||||
<string name="main_screen_sections">Sezioni principali schermo</string>
|
||||
<string name="advanced">Avanzate</string>
|
||||
<string name="downloads_settings_info">Se stai avendo problemi di blocco dal server, puoi abilitare il rallentamento dei download per ogni fonte di manga nelle impostazioni delle fonti</string>
|
||||
<string name="sync_settings">Impostazioni di sincronizzazione</string>
|
||||
<string name="online_variant">Variante online</string>
|
||||
<string name="disable_battery_optimization_summary_downloads">Potrebbe aiutare a far iniziare il download in caso di problemi</string>
|
||||
<string name="error_multiple_genres_not_supported">Questa fonte di manga non supporta il filtraggio per multipli generi</string>
|
||||
<string name="download_option_all_unread_b">Tutti i capitoli non letti (%s)</string>
|
||||
<string name="authorization_optional">Autorizzazione (opzionale)</string>
|
||||
<string name="color_dark">Scuro</string>
|
||||
<string name="this_manga">Questo manga</string>
|
||||
<string name="reader_info_bar_summary">Mostra l\'orario attuale e il progresso di lettura in cima allo schermo</string>
|
||||
<string name="translations">Traduzioni</string>
|
||||
<string name="downloads_paused">I download sono stati messi in pausa</string>
|
||||
<string name="too_many_requests_message">Troppe richieste. Riprova più tardi</string>
|
||||
<string name="downloads_wifi_only">Scarica solo via Wi-Fi</string>
|
||||
<string name="lock_screen_rotation">Blocca rotazione schermo</string>
|
||||
<string name="cancel_all_downloads_confirm">Tutti i download attivi saranno annullati, i dati scaricati parzialmente saranno persi</string>
|
||||
<string name="by_relevance">Rilevanza</string>
|
||||
<string name="related_manga">Manga correlati</string>
|
||||
<string name="state_abandoned">Abbandonato</string>
|
||||
<string name="download_option_first_n_chapters">Primo %s</string>
|
||||
<string name="keep_screen_on">Tieni schermo acceso</string>
|
||||
<string name="paused">In pausa</string>
|
||||
<string name="text_downloads_list_holder">Non hai alcun download</string>
|
||||
<string name="skip">Salta</string>
|
||||
<string name="error_search_not_supported">Questa fonte di manga non supporta la ricerca</string>
|
||||
<string name="invalid_port_number">Numero di porta non valido</string>
|
||||
<string name="suggestions_wifi_only_summary">Non aggiornare suggerimenti mentre è in uso una connessione a consumo</string>
|
||||
<string name="webtoon_zoom_summary">Consenti gesto di zoom in modalità webtoon</string>
|
||||
<string name="frequency_once_per_month">Una volta al mese</string>
|
||||
<string name="network">Rete</string>
|
||||
<string name="downloaded">Scaricato</string>
|
||||
<string name="suggestions_enable_prompt">Vuoi ricevere suggerimenti personalizzati di manga?</string>
|
||||
<string name="manual">Manuale</string>
|
||||
<string name="custom_directory">Cartella personalizzata</string>
|
||||
<string name="more">Di più</string>
|
||||
<string name="reader_optimize_summary">Riduci la qualità delle pagine fuori schermo per usare meno memoria</string>
|
||||
<string name="address">Indirizzo</string>
|
||||
<string name="color_correction_apply_text">Queste impostazioni possono essere applicate globalmente o per solo questo manga. Le applicazioni globali non sovrascrivono quelle individuali.</string>
|
||||
<string name="source_enabled">Fonte abilitata</string>
|
||||
<string name="enhanced_colors">Modalità colori 32-bit</string>
|
||||
<string name="folder_with_images_import_description">Puoi selezionare una cartella contenente archivi o immagini. Ogni archivio (o sottocartella) sarà riconosciuto come singolo capitolo.</string>
|
||||
<string name="default_section">Sezione default</string>
|
||||
<string name="background">Sfondo</string>
|
||||
<string name="disable_nsfw_summary">Disabilita fonti per adulti e nascondi manga per adulti dalla lista se possibile</string>
|
||||
<string name="speed_value">x%.1f</string>
|
||||
<string name="downloads_removed">I download sono stati rimossi</string>
|
||||
<string name="pages_animation_summary">Animazioni cambio pagina</string>
|
||||
<string name="no_access_to_file">Non hai accesso a questo file o cartella</string>
|
||||
<string name="mirror_switching">Scegli mirror automaticamente</string>
|
||||
<string name="restore_summary">Ripristina backup creato in precedenza</string>
|
||||
<string name="show_pages_numbers_summary">Mostra numeri di pagina nell\'angolo inferiore</string>
|
||||
<string name="zoom_out">Rimpicciolire</string>
|
||||
<string name="keep_screen_on_summary">Non spegnere lo schermo durante la lettura di manga</string>
|
||||
<string name="download_option_next_unread_n_chapters">Prossimo %s non letto</string>
|
||||
<string name="clear_network_cache">Pulisci cache di rete</string>
|
||||
<string name="voice_search">Ricerca vocale</string>
|
||||
<string name="enable">Abilita</string>
|
||||
<string name="backup_date_">Data del backup: %s</string>
|
||||
<string name="images_procy_description">Usa il servizio wsrv.nl per ridurre i consumi di rete e velocizzare il caricamento delle immagini, se possibile</string>
|
||||
<string name="no_manga_sources_catalog_text">Non sono disponibili fonti in questa sezione, o potrebbero essere state aggiunte tutte.
|
||||
\nRimani sintonizzato</string>
|
||||
<string name="available_d">Disponibile: %1$d</string>
|
||||
<string name="manga_branch_title_template">%1$s (%2$s)</string>
|
||||
<string name="state">Stato</string>
|
||||
<string name="manga_list">Lista manga</string>
|
||||
<string name="grayscale">Bianco e nero</string>
|
||||
<string name="disable_nsfw">Disabilita contenuti per adulti</string>
|
||||
<string name="last_successful_backup">Ultimo backup completato: %s</string>
|
||||
<string name="color_white">Bianco</string>
|
||||
<string name="downloads_resumed">I download sono stati ripresi</string>
|
||||
<string name="details_button_tip">Tocca e tieni premuto il tasto Leggi per vedere più opzioni</string>
|
||||
<string name="state_paused">In pausa</string>
|
||||
<string name="to_top">Va in cima</string>
|
||||
<string name="show">Mostra</string>
|
||||
<string name="sync_auth_hint">Puoi accedere ad un account esistente o crearne uno nuovo</string>
|
||||
<string name="backups_output_directory">Cartella salvataggio backup</string>
|
||||
<string name="invert_colors">Inverti colori</string>
|
||||
<string name="mirror_switching_summary">Cambiare dominio di fonte del manga automaticamente in caso di errore se sono disponibili mirror</string>
|
||||
<string name="no_thanks">No grazie</string>
|
||||
<string name="suggest_new_sources_summary">Chiedi se aggiungere nuove fonti dopo aggiornamento dell\'applicazione</string>
|
||||
<string name="speed">Velocità</string>
|
||||
<string name="download_option_all_chapters">Tutti i capitoli con traduzioni %s</string>
|
||||
<string name="content_type_other">Altro</string>
|
||||
<string name="suggestion_manga">Consigliato: %s</string>
|
||||
<string name="color_black">Nero</string>
|
||||
<string name="this_month">Questo mese</string>
|
||||
<string name="sync_auth">Accedi per sincronizzare l\'account</string>
|
||||
<string name="proxy">Proxy</string>
|
||||
<string name="restore_backup_description">Importa un backup di dati utente creato precedentemente</string>
|
||||
<string name="got_it">Ho capito</string>
|
||||
<string name="comics_archive_import_description">Puoi selezionare uno o più file .cbz o .zip, ogni file sarà riconosciuto come un manga a parte.</string>
|
||||
<string name="show_on_shelf">Mostra sullo Scaffale</string>
|
||||
</resources>
|
||||
@@ -548,4 +548,6 @@
|
||||
<string name="sync_auth">Login to sync account</string>
|
||||
<string name="restore">Restore</string>
|
||||
<string name="backup_date_">Backup date: %s</string>
|
||||
<string name="state_upcoming">Upcoming</string>
|
||||
<string name="by_name_reverse">Name reversed</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user