Merge branch 'dev' into dev-settings-search

This commit is contained in:
mpm11011
2020-09-16 14:56:34 -04:00
committed by GitHub
207 changed files with 2415 additions and 1427 deletions

View File

@@ -7,11 +7,11 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.LocaleHelper
import uy.kohesive.injekt.injectLazy
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {

View File

@@ -22,27 +22,29 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
lateinit var binding: VB
init {
addLifecycleListener(object : LifecycleListener() {
override fun postCreateView(controller: Controller, view: View) {
onViewCreated(view)
}
addLifecycleListener(
object : LifecycleListener() {
override fun postCreateView(controller: Controller, view: View) {
onViewCreated(view)
}
override fun preCreateView(controller: Controller) {
Timber.d("Create view for ${controller.instance()}")
}
override fun preCreateView(controller: Controller) {
Timber.d("Create view for ${controller.instance()}")
}
override fun preAttach(controller: Controller, view: View) {
Timber.d("Attach view for ${controller.instance()}")
}
override fun preAttach(controller: Controller, view: View) {
Timber.d("Attach view for ${controller.instance()}")
}
override fun preDetach(controller: Controller, view: View) {
Timber.d("Detach view for ${controller.instance()}")
}
override fun preDetach(controller: Controller, view: View) {
Timber.d("Detach view for ${controller.instance()}")
}
override fun preDestroyView(controller: Controller, view: View) {
Timber.d("Destroy view for ${controller.instance()}")
override fun preDestroyView(controller: Controller, view: View) {
Timber.d("Destroy view for ${controller.instance()}")
}
}
})
)
}
override val containerView: View?
@@ -98,17 +100,19 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
var expandActionViewFromInteraction = false
fun MenuItem.fixExpand(onExpand: ((MenuItem) -> Boolean)? = null, onCollapse: ((MenuItem) -> Boolean)? = null) {
setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
return onExpand?.invoke(item) ?: true
}
setOnActionExpandListener(
object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
return onExpand?.invoke(item) ?: true
}
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
activity?.invalidateOptionsMenu()
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
activity?.invalidateOptionsMenu()
return onCollapse?.invoke(item) ?: true
return onCollapse?.invoke(item) ?: true
}
}
})
)
if (expandActionViewFromInteraction) {
expandActionViewFromInteraction = false

View File

@@ -10,12 +10,12 @@ import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.system.LocaleHelper
import java.util.concurrent.TimeUnit
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
private typealias ExtensionTuple =
Triple<List<Extension.Installed>, List<Extension.Untrusted>, List<Extension.Available>>

View File

@@ -20,8 +20,6 @@ import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL
import androidx.recyclerview.widget.LinearLayoutManager
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore
@@ -92,7 +90,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
ExtensionDetailsHeaderAdapter(presenter),
initPreferencesAdapter(context, extension)
)
binding.extensionPrefsRecycler.addItemDecoration(DividerItemDecoration(context, VERTICAL))
}
private fun initPreferencesAdapter(context: Context, extension: Extension.Installed): PreferenceGroupAdapter {
@@ -112,7 +109,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
.forEach {
val preferenceBlock = {
it.value
.sortedWith(compareBy({ !it.isEnabled() }, { it.name }))
.sortedWith(compareBy({ !it.isEnabled() }, { it.name.toLowerCase() }))
.forEach { source ->
val sourcePrefs = mutableListOf<Preference>()

View File

@@ -19,8 +19,6 @@ import androidx.preference.Preference
import androidx.preference.PreferenceGroupAdapter
import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL
import androidx.recyclerview.widget.LinearLayoutManager
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore
@@ -86,7 +84,6 @@ class SourcePreferencesController(bundle: Bundle? = null) :
binding.recycler.layoutManager = LinearLayoutManager(context)
binding.recycler.adapter = PreferenceGroupAdapter(screen)
binding.recycler.addItemDecoration(DividerItemDecoration(context, VERTICAL))
}
override fun onDestroyView(view: View) {

View File

@@ -13,10 +13,10 @@ import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchCardItem
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchItem
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import java.util.Date
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import java.util.Date
class SearchPresenter(
initialQuery: String? = "",

View File

@@ -29,7 +29,7 @@ class MigrationSourcesPresenter(
val header = SelectionHeader()
return library.map { it.source }.toSet()
.mapNotNull { if (it != LocalSource.ID) sourceManager.getOrStub(it) else null }
.sortedBy { it.name }
.sortedBy { it.name.toLowerCase() }
.map { SourceItem(it, header) }
}
}

View File

@@ -16,9 +16,9 @@ import eu.kanade.tachiyomi.util.preference.onChange
import eu.kanade.tachiyomi.util.preference.switchPreferenceCategory
import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.LocaleHelper
import java.util.TreeMap
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.TreeMap
class SourceFilterController : SettingsController() {
@@ -42,7 +42,7 @@ class SourceFilterController : SettingsController() {
)
orderedLangs.forEach { lang ->
val sources = sourcesByLang[lang].orEmpty().sortedBy { it.name }
val sources = sourcesByLang[lang].orEmpty().sortedBy { it.name.toLowerCase() }
// Create a preference group and set initial state and change listener
switchPreferenceCategory {

View File

@@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import java.util.TreeMap
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -21,6 +20,7 @@ import rx.Observable
import rx.Subscription
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.TreeMap
/**
* Presenter of [SourceController]
@@ -128,7 +128,7 @@ class SourcePresenter(
return sourceManager.getCatalogueSources()
.filter { it.lang in languages }
.filterNot { it.id.toString() in disabledSourceIds }
.sortedBy { "(${it.lang}) ${it.name}" } +
.sortedBy { "(${it.lang}) ${it.name.toLowerCase()}" } +
sourceManager.get(LocalSource.ID) as LocalSource
}

View File

@@ -10,7 +10,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -216,7 +215,6 @@ open class BrowseSourceController(bundle: Bundle) :
id = R.id.recycler
layoutManager = LinearLayoutManager(context)
layoutParams = RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
}
} else {
(binding.catalogueView.inflate(R.layout.source_recycler_autofit) as AutofitRecyclerView).apply {

View File

@@ -28,9 +28,8 @@ import eu.kanade.tachiyomi.ui.browse.source.filter.TextItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TextSectionItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.removeCovers
import java.util.Date
import kotlinx.coroutines.flow.subscribe
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@@ -39,6 +38,7 @@ import rx.subjects.PublishSubject
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date
/**
* Presenter of [BrowseSourceController].
@@ -268,6 +268,8 @@ open class BrowseSourcePresenter(
if (!manga.favorite) {
manga.removeCovers(coverCache)
} else {
ChapterSettingsHelper.applySettingDefaults(manga)
}
db.insertManga(manga).executeAsBlocking()

View File

@@ -38,10 +38,13 @@ class SourceItem(val manga: Manga, private val displayMode: Preference<DisplayMo
val coverHeight = parent.itemWidth / 3 * 4
view.apply {
card.layoutParams = FrameLayout.LayoutParams(
MATCH_PARENT, coverHeight
MATCH_PARENT,
coverHeight
)
gradient.layoutParams = FrameLayout.LayoutParams(
MATCH_PARENT, coverHeight / 2, Gravity.BOTTOM
MATCH_PARENT,
coverHeight / 2,
Gravity.BOTTOM
)
}
SourceGridHolder(view, adapter)
@@ -51,7 +54,8 @@ class SourceItem(val manga: Manga, private val displayMode: Preference<DisplayMo
val coverHeight = parent.itemWidth / 3 * 4
view.apply {
card.layoutParams = ConstraintLayout.LayoutParams(
MATCH_PARENT, coverHeight
MATCH_PARENT,
coverHeight
)
}
SourceComfortableGridHolder(view, adapter)

View File

@@ -30,7 +30,8 @@ open class SelectItem(val filter: Filter.Select<*>) : AbstractFlexibleItem<Selec
spinner.prompt = filter.name
spinner.adapter = ArrayAdapter<Any>(
holder.itemView.context,
android.R.layout.simple_spinner_item, filter.values
android.R.layout.simple_spinner_item,
filter.values
).apply {
setDropDownViewResource(R.layout.common_spinner_item)
}

View File

@@ -9,10 +9,10 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R as TR
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.R as TR
open class TriStateItem(val filter: Filter.TriState) : AbstractFlexibleItem<TriStateItem.Holder>() {

View File

@@ -108,17 +108,19 @@ open class GlobalSearchController(
val searchView = searchItem.actionView as SearchView
searchView.maxWidth = Int.MAX_VALUE
searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
searchView.onActionViewExpanded() // Required to show the query in the view
searchView.setQuery(presenter.query, false)
return true
}
searchItem.setOnActionExpandListener(
object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
searchView.onActionViewExpanded() // Required to show the query in the view
searchView.setQuery(presenter.query, false)
return true
}
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
return true
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
return true
}
}
})
)
searchView.queryTextEvents()
.filterIsInstance<QueryTextEvent.QuerySubmitted>()

View File

@@ -108,7 +108,7 @@ open class GlobalSearchPresenter(
return sourceManager.getCatalogueSources()
.filter { it.lang in languages }
.filterNot { it.id.toString() in disabledSourceIds }
.sortedWith(compareBy({ it.id.toString() !in pinnedSourceIds }, { "${it.name} (${it.lang})" }))
.sortedWith(compareBy({ it.id.toString() !in pinnedSourceIds }, { "${it.name.toLowerCase()} (${it.lang})" }))
}
private fun getSourcesToQuery(): List<CatalogueSource> {
@@ -188,7 +188,7 @@ open class GlobalSearchPresenter(
{ it.results.isNullOrEmpty() },
// Same as initial sort, i.e. pinned first then alphabetically
{ it.source.id.toString() !in pinnedSourceIds },
{ "${it.source.name} (${it.source.lang})" }
{ "${it.source.name.toLowerCase()} (${it.source.lang})" }
)
)
}

View File

@@ -198,8 +198,11 @@ class CategoryController :
R.id.action_delete -> {
undoHelper = UndoHelper(adapter, this)
undoHelper?.start(
adapter.selectedPositions, activity!!.root_coordinator,
R.string.snack_categories_deleted, R.string.action_undo, 3000
adapter.selectedPositions,
activity!!.root_coordinator,
R.string.snack_categories_deleted,
R.string.action_undo,
3000
)
mode.finish()

View File

@@ -18,13 +18,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.base.controller.FabController
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import java.util.concurrent.TimeUnit
/**
* Controller that shows the currently active downloads.

View File

@@ -183,7 +183,7 @@ class LibraryController(
createActionModeIfNeeded()
}
settingsSheet = LibrarySettingsSheet(activity!!) { group ->
settingsSheet = LibrarySettingsSheet(router) { group ->
when (group) {
is LibrarySettingsSheet.Filter.FilterGroup -> onFilterChanged()
is LibrarySettingsSheet.Sort.SortGroup -> onSortChanged()

View File

@@ -45,7 +45,9 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe
view.apply {
card.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight)
gradient.layoutParams = FrameLayout.LayoutParams(
MATCH_PARENT, coverHeight / 2, Gravity.BOTTOM
MATCH_PARENT,
coverHeight / 2,
Gravity.BOTTOM
)
}
LibraryCompactGridHolder(view, adapter)
@@ -55,7 +57,8 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe
val coverHeight = parent.itemWidth / 3 * 4
view.apply {
card.layoutParams = ConstraintLayout.LayoutParams(
MATCH_PARENT, coverHeight
MATCH_PARENT,
coverHeight
)
}
LibraryComfortableGridHolder(view, adapter)

View File

@@ -19,14 +19,16 @@ import eu.kanade.tachiyomi.util.lang.combineLatest
import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.removeCovers
import java.util.Collections
import java.util.Comparator
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Collections
import java.util.Comparator
/**
* Class containing library information.
@@ -110,34 +112,45 @@ class LibraryPresenter(
* @param map the map to filter.
*/
private fun applyFilters(map: LibraryMap): LibraryMap {
val filterDownloaded = preferences.downloadedOnly().get() || preferences.filterDownloaded().get()
val downloadedOnly = preferences.downloadedOnly().get()
val filterDownloaded = preferences.filterDownloaded().get()
val filterUnread = preferences.filterUnread().get()
val filterCompleted = preferences.filterCompleted().get()
val filterFn: (LibraryItem) -> Boolean = f@{ item ->
// Filter when there isn't unread chapters.
if (filterUnread && item.manga.unread == 0) {
return@f false
val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item ->
if (filterUnread == STATE_IGNORE) return@unread true
val isUnread = item.manga.unread != 0
return@unread if (filterUnread == STATE_INCLUDE) isUnread
else !isUnread
}
val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ item ->
if (filterCompleted == STATE_IGNORE) return@completed true
val isCompleted = item.manga.status == SManga.COMPLETED
return@completed if (filterCompleted == STATE_INCLUDE) isCompleted
else !isCompleted
}
val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item ->
if (!downloadedOnly && filterDownloaded == STATE_IGNORE) return@downloaded true
val isDownloaded = when {
item.manga.isLocal() -> true
item.downloadCount != -1 -> item.downloadCount > 0
else -> downloadManager.getDownloadCount(item.manga) > 0
}
if (filterCompleted && item.manga.status != SManga.COMPLETED) {
return@f false
}
return@downloaded if (downloadedOnly || filterDownloaded == STATE_INCLUDE) isDownloaded
else !isDownloaded
}
// Filter when there are no downloads.
if (filterDownloaded) {
// Local manga are always downloaded
if (item.manga.isLocal()) {
return@f true
}
// Don't bother with directory checking if download count has been set.
if (item.downloadCount != -1) {
return@f item.downloadCount > 0
}
return@f downloadManager.getDownloadCount(item.manga) > 0
}
true
val filterFn: (LibraryItem) -> Boolean = filter@{ item ->
return@filter !(
!filterFnUnread(item) ||
!filterFnCompleted(item) ||
!filterFnDownloaded(item)
)
}
return map.mapValues { entry -> entry.value.filter(filterFn) }

View File

@@ -1,33 +1,36 @@
package eu.kanade.tachiyomi.ui.library
import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.View
import com.bluelinelabs.conductor.Router
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_EXCLUDE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
import uy.kohesive.injekt.injectLazy
class LibrarySettingsSheet(
activity: Activity,
router: Router,
onGroupClickListener: (ExtendedNavigationView.Group) -> Unit
) : TabbedBottomSheetDialog(activity) {
) : TabbedBottomSheetDialog(router) {
val filters: Filter
private val sort: Sort
private val display: Display
init {
filters = Filter(activity)
filters = Filter(router.activity!!)
filters.onGroupClicked = onGroupClickListener
sort = Sort(activity)
sort = Sort(router.activity!!)
sort.onGroupClicked = onGroupClickListener
display = Display(activity)
display = Display(router.activity!!)
display.onGroupClicked = onGroupClickListener
}
@@ -59,33 +62,43 @@ class LibrarySettingsSheet(
* Returns true if there's at least one filter from [FilterGroup] active.
*/
fun hasActiveFilters(): Boolean {
return filterGroup.items.any { it.checked }
return filterGroup.items.any { it.state != Item.TriStateGroup.STATE_IGNORE }
}
inner class FilterGroup : Group {
private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this)
private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this)
private val completed = Item.CheckboxGroup(R.string.completed, this)
private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
private val completed = Item.TriStateGroup(R.string.completed, this)
override val header = null
override val items = listOf(downloaded, unread, completed)
override val footer = null
override fun initModels() {
downloaded.checked = preferences.downloadedOnly().get() || preferences.filterDownloaded().get()
downloaded.enabled = !preferences.downloadedOnly().get()
unread.checked = preferences.filterUnread().get()
completed.checked = preferences.filterCompleted().get()
if (preferences.downloadedOnly().get()) {
downloaded.state = STATE_INCLUDE
downloaded.enabled = false
} else {
downloaded.state = preferences.filterDownloaded().get()
}
unread.state = preferences.filterUnread().get()
completed.state = preferences.filterCompleted().get()
}
override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup
item.checked = !item.checked
item as Item.TriStateGroup
val newState = when (item.state) {
STATE_IGNORE -> STATE_INCLUDE
STATE_INCLUDE -> STATE_EXCLUDE
STATE_EXCLUDE -> STATE_IGNORE
else -> throw Exception("Unknown State")
}
item.state = newState
when (item) {
downloaded -> preferences.filterDownloaded().set(item.checked)
unread -> preferences.filterUnread().set(item.checked)
completed -> preferences.filterCompleted().set(item.checked)
downloaded -> preferences.filterDownloaded().set(newState)
unread -> preferences.filterUnread().set(newState)
completed -> preferences.filterCompleted().set(newState)
}
adapter.notifyItemChanged(item)

View File

@@ -44,13 +44,13 @@ import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.system.toast
import java.util.Date
import java.util.concurrent.TimeUnit
import kotlinx.android.synthetic.main.main_activity.appbar
import kotlinx.android.synthetic.main.main_activity.tabs
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import timber.log.Timber
import java.util.Date
import java.util.concurrent.TimeUnit
class MainActivity : BaseActivity<MainActivityBinding>() {
@@ -126,26 +126,28 @@ class MainActivity : BaseActivity<MainActivityBinding>() {
onBackPressed()
}
router.addChangeListener(object : ControllerChangeHandler.ControllerChangeListener {
override fun onChangeStarted(
to: Controller?,
from: Controller?,
isPush: Boolean,
container: ViewGroup,
handler: ControllerChangeHandler
) {
syncActivityViewWithController(to, from)
}
router.addChangeListener(
object : ControllerChangeHandler.ControllerChangeListener {
override fun onChangeStarted(
to: Controller?,
from: Controller?,
isPush: Boolean,
container: ViewGroup,
handler: ControllerChangeHandler
) {
syncActivityViewWithController(to, from)
}
override fun onChangeCompleted(
to: Controller?,
from: Controller?,
isPush: Boolean,
container: ViewGroup,
handler: ControllerChangeHandler
) {
override fun onChangeCompleted(
to: Controller?,
from: Controller?,
isPush: Boolean,
container: ViewGroup,
handler: ControllerChangeHandler
) {
}
}
})
)
syncActivityViewWithController(router.backstack.lastOrNull()?.controller())

View File

@@ -52,7 +52,6 @@ import eu.kanade.tachiyomi.ui.library.ChangeMangaCoverDialog
import eu.kanade.tachiyomi.ui.library.LibraryController
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.main.offsetAppbarHeight
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterDividerItemDecoration
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersSettingsSheet
@@ -65,13 +64,13 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.chapter.NoChaptersException
import eu.kanade.tachiyomi.util.hasCustomCover
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.getCoordinates
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
import eu.kanade.tachiyomi.util.view.snack
import kotlin.math.min
import kotlinx.android.synthetic.main.main_activity.root_coordinator
import kotlinx.android.synthetic.main.main_activity.toolbar
import kotlinx.coroutines.flow.launchIn
@@ -83,6 +82,7 @@ import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import kotlin.math.min
class MangaController :
NucleusController<MangaControllerBinding, MangaPresenter>,
@@ -207,7 +207,6 @@ class MangaController :
binding.recycler.adapter = ConcatAdapter(mangaInfoAdapter, chaptersHeaderAdapter, chaptersAdapter)
binding.recycler.layoutManager = LinearLayoutManager(view.context)
binding.recycler.addItemDecoration(ChapterDividerItemDecoration(view.context))
binding.recycler.setHasFixedSize(true)
chaptersAdapter?.fastScroller = binding.fastScroller
@@ -238,7 +237,7 @@ class MangaController :
binding.actionToolbar.offsetAppbarHeight(activity!!)
settingsSheet = ChaptersSettingsSheet(activity!!, presenter) { group ->
settingsSheet = ChaptersSettingsSheet(router, presenter) { group ->
if (group is ChaptersSettingsSheet.Filter.FilterGroup) {
updateFilterIconState()
chaptersAdapter?.notifyDataSetChanged()
@@ -292,10 +291,10 @@ class MangaController :
// Get coordinates and start animation
actionFab?.getCoordinates()?.let { coordinates ->
if (!binding.revealView.showRevealEffect(
coordinates.x,
coordinates.y,
revealAnimationListener
)
coordinates.x,
coordinates.y,
revealAnimationListener
)
) {
openChapter(item.chapter)
}
@@ -343,7 +342,8 @@ class MangaController :
}
override fun onPrepareOptionsMenu(menu: Menu) {
// Hide download options for local manga
// Hide options for local manga
menu.findItem(R.id.action_share).isVisible = !isLocalSource
menu.findItem(R.id.download_group).isVisible = !isLocalSource
// Hide options for non-library manga
@@ -354,6 +354,7 @@ class MangaController :
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_share -> shareManga()
R.id.download_next, R.id.download_next_5, R.id.download_next_10,
R.id.download_custom, R.id.download_unread, R.id.download_all
-> downloadChapters(item.itemId)
@@ -694,7 +695,11 @@ class MangaController :
fun onFetchChaptersError(error: Throwable) {
isRefreshingChapters = false
updateRefreshing()
activity?.toast(error.message)
if (error is NoChaptersException) {
activity?.toast(activity?.getString(R.string.no_chapters_error))
} else {
activity?.toast(error.message)
}
}
fun onChapterStatusChange(download: Download) {

View File

@@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.isLocal
import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed
@@ -26,7 +27,6 @@ import eu.kanade.tachiyomi.util.prepUpdateCover
import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import eu.kanade.tachiyomi.util.updateCoverLastModified
import java.util.Date
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@@ -34,6 +34,7 @@ import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date
class MangaPresenter(
val manga: Manga,
@@ -82,6 +83,10 @@ class MangaPresenter(
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
if (!manga.favorite) {
ChapterSettingsHelper.applySettingDefaults(manga)
}
// Manga info - start
getMangaObservable()

View File

@@ -1,59 +0,0 @@
package eu.kanade.tachiyomi.ui.manga.chapter
import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import androidx.core.view.forEach
import androidx.core.view.marginBottom
import androidx.recyclerview.widget.RecyclerView
/**
* Mimics a DividerItemDecoration that doesn't draw between the first two items.
*
* Used in MangaController since the manga info header and chapters header are the first two
* items in the list using a ConcatAdapter.
*/
class ChapterDividerItemDecoration(context: Context) : RecyclerView.ItemDecoration() {
private val divider: Drawable
init {
val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.listDivider))
divider = a.getDrawable(0)!!
a.recycle()
}
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (parent.layoutManager == null) {
return
}
canvas.save()
parent.forEach {
val top = it.bottom + it.marginBottom
val bottom = top + divider.intrinsicHeight
val left = parent.paddingStart
val right = parent.width - parent.paddingEnd
divider.setBounds(left, top, right, bottom)
divider.draw(canvas)
}
canvas.restore()
}
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val position = parent.getChildAdapterPosition(view)
if (position == 0) {
outRect.setEmpty()
} else {
outRect.set(0, 0, 0, divider.intrinsicHeight)
}
}
}

View File

@@ -9,11 +9,11 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import java.util.Date
import kotlinx.android.synthetic.main.chapters_item.bookmark_icon
import kotlinx.android.synthetic.main.chapters_item.chapter_description
import kotlinx.android.synthetic.main.chapters_item.chapter_title
import kotlinx.android.synthetic.main.chapters_item.download_text
import java.util.Date
class ChapterHolder(
view: View,

View File

@@ -6,10 +6,10 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.util.system.getResourceColor
import uy.kohesive.injekt.injectLazy
import java.text.DateFormat
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import uy.kohesive.injekt.injectLazy
class ChaptersAdapter(
controller: MangaController,

View File

@@ -1,34 +1,39 @@
package eu.kanade.tachiyomi.ui.manga.chapter
import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.core.view.isVisible
import com.bluelinelabs.conductor.Router
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.ui.manga.MangaPresenter
import eu.kanade.tachiyomi.util.view.popupMenu
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
class ChaptersSettingsSheet(
activity: Activity,
private val router: Router,
private val presenter: MangaPresenter,
onGroupClickListener: (ExtendedNavigationView.Group) -> Unit
) : TabbedBottomSheetDialog(activity) {
) : TabbedBottomSheetDialog(router) {
val filters: Filter
private val sort: Sort
private val display: Display
init {
filters = Filter(activity)
filters = Filter(router.activity!!)
filters.onGroupClicked = onGroupClickListener
sort = Sort(activity)
sort = Sort(router.activity!!)
sort.onGroupClicked = onGroupClickListener
display = Display(activity)
display = Display(router.activity!!)
display.onGroupClicked = onGroupClickListener
binding.menu.isVisible = true
binding.menu.setOnClickListener { it.post { showPopupMenu(it) } }
}
override fun getTabViews(): List<View> = listOf(
@@ -43,6 +48,23 @@ class ChaptersSettingsSheet(
R.string.action_display
)
private fun showPopupMenu(view: View) {
view.popupMenu(
R.menu.default_chapter_filter,
{
},
{
when (this.itemId) {
R.id.set_as_default -> {
SetChapterSettingsDialog(presenter.manga).showDialog(router)
true
}
else -> true
}
}
)
}
/**
* Filters group (unread, downloaded, ...).
*/

View File

@@ -66,7 +66,7 @@ class MangaChaptersHeaderAdapter(
} else {
view.context.getResourceColor(R.attr.colorOnPrimary)
}
DrawableCompat.setTint(binding.btnChaptersFilter.icon, filterColor)
DrawableCompat.setTint(binding.btnChaptersFilter.drawable, filterColor)
merge(view.clicks(), binding.btnChaptersFilter.clicks())
.onEach { controller.showSettingsSheet() }

View File

@@ -0,0 +1,48 @@
package eu.kanade.tachiyomi.ui.manga.chapter
import android.app.Dialog
import android.os.Bundle
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.widget.DialogCheckboxView
class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle) {
constructor(manga: Manga) : this(
Bundle().apply {
putSerializable(MANGA_KEY, manga)
}
)
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
val view = DialogCheckboxView(activity!!).apply {
setDescription(R.string.confirm_set_chapter_settings)
setOptionDescription(R.string.also_set_chapter_settings_for_library)
}
return MaterialDialog(activity!!)
.title(R.string.chapter_settings)
.customView(
view = view,
horizontalPadding = true
)
.positiveButton(android.R.string.ok) {
ChapterSettingsHelper.setGlobalSettings(args.getSerializable(MANGA_KEY)!! as Manga)
if (view.isChecked()) {
ChapterSettingsHelper.updateAllMangasWithGlobalDefaults()
}
activity?.toast(activity!!.getString(R.string.chapter_settings_updated))
}
.negativeButton(android.R.string.cancel)
}
private companion object {
const val MANGA_KEY = "manga"
}
}

View File

@@ -105,13 +105,27 @@ class MangaInfoHeaderAdapter(
isVisible = true
if (trackCount > 0) {
setIconResource(R.drawable.ic_done_24dp)
text = view.context.resources.getQuantityString(R.plurals.num_trackers, trackCount, trackCount)
isChecked = true
setCompoundDrawablesWithIntrinsicBounds(
null,
ContextCompat.getDrawable(context, R.drawable.ic_done_24dp),
null,
null
)
text = view.context.resources.getQuantityString(
R.plurals.num_trackers,
trackCount,
trackCount
)
isSelected = true
} else {
setIconResource(R.drawable.ic_sync_24dp)
setCompoundDrawablesWithIntrinsicBounds(
null,
ContextCompat.getDrawable(context, R.drawable.ic_sync_24dp),
null,
null
)
text = view.context.getString(R.string.manga_tracking_tab)
isChecked = false
isSelected = false
}
clicks()
@@ -128,12 +142,6 @@ class MangaInfoHeaderAdapter(
.onEach { controller.openMangaInWebView() }
.launchIn(scope)
binding.btnWebview.setTooltip(R.string.action_open_in_web_view)
binding.btnShare.isVisible = true
binding.btnShare.clicks()
.onEach { controller.shareManga() }
.launchIn(scope)
binding.btnShare.setTooltip(R.string.action_share)
}
binding.mangaFullTitle.longClicks()
@@ -285,14 +293,24 @@ class MangaInfoHeaderAdapter(
// Update genres list
if (!manga.genre.isNullOrBlank()) {
binding.mangaGenresTagsCompactChips.setChips(manga.getGenres(), controller::performSearch)
binding.mangaGenresTagsFullChips.setChips(manga.getGenres(), controller::performSearch)
binding.mangaGenresTagsCompactChips.setChips(
manga.getGenres(),
controller::performSearch
)
binding.mangaGenresTagsFullChips.setChips(
manga.getGenres(),
controller::performSearch
)
} else {
binding.mangaGenresTagsWrapper.isVisible = false
}
// Handle showing more or less info
merge(binding.mangaSummarySection.clicks(), binding.mangaSummaryText.clicks(), binding.mangaInfoToggle.clicks())
merge(
binding.mangaSummarySection.clicks(),
binding.mangaSummaryText.clicks(),
binding.mangaInfoToggle.clicks()
)
.onEach { toggleMangaInfo(view.context) }
.launchIn(scope)
@@ -310,20 +328,22 @@ class MangaInfoHeaderAdapter(
private fun toggleMangaInfo(context: Context) {
val isExpanded =
binding.mangaInfoToggle.text == context.getString(R.string.manga_info_collapse)
binding.mangaInfoToggle.contentDescription == context.getString(R.string.manga_info_collapse)
with(binding.mangaInfoToggle) {
text = if (isExpanded) {
contentDescription = if (isExpanded) {
context.getString(R.string.manga_info_expand)
} else {
context.getString(R.string.manga_info_collapse)
}
icon = if (isExpanded) {
context.getDrawable(R.drawable.ic_baseline_expand_more_24dp)
} else {
context.getDrawable(R.drawable.ic_baseline_expand_less_24dp)
}
setImageDrawable(
if (isExpanded) {
context.getDrawable(R.drawable.ic_baseline_expand_more_24dp)
} else {
context.getDrawable(R.drawable.ic_baseline_expand_less_24dp)
}
)
}
with(binding.mangaSummaryText) {
@@ -355,13 +375,18 @@ class MangaInfoHeaderAdapter(
// Set the Favorite drawable to the correct one.
// Border drawable if false, filled drawable if true.
binding.btnFavorite.apply {
icon = ContextCompat.getDrawable(
context,
if (isFavorite) R.drawable.ic_favorite_24dp else R.drawable.ic_favorite_border_24dp
setCompoundDrawablesWithIntrinsicBounds(
null,
ContextCompat.getDrawable(
context,
if (isFavorite) R.drawable.ic_favorite_24dp else R.drawable.ic_favorite_border_24dp
),
null,
null
)
text =
context.getString(if (isFavorite) R.string.in_library else R.string.add_to_library)
isChecked = isFavorite
isSelected = isFavorite
}
}
}

View File

@@ -9,9 +9,9 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import java.util.Calendar
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Calendar
class SetTrackReadingDatesDialog<T> : DialogController
where T : Controller, T : SetTrackReadingDatesDialog.Listener {

View File

@@ -5,8 +5,8 @@ import androidx.core.view.isVisible
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.TrackItemBinding
import eu.kanade.tachiyomi.ui.base.holder.BaseViewHolder
import java.text.DateFormat
import uy.kohesive.injekt.injectLazy
import java.text.DateFormat
class TrackHolder(private val binding: TrackItemBinding, adapter: TrackAdapter) : BaseViewHolder(binding.root) {

View File

@@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import java.util.concurrent.TimeUnit
import kotlinx.android.synthetic.main.track_search_dialog.view.progress
import kotlinx.android.synthetic.main.track_search_dialog.view.track_search
import kotlinx.android.synthetic.main.track_search_dialog.view.track_search_list
@@ -26,6 +25,7 @@ import reactivecircus.flowbinding.android.widget.itemClicks
import reactivecircus.flowbinding.android.widget.textChanges
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
class TrackSearchDialog : DialogController {

View File

@@ -10,9 +10,9 @@ import com.afollestad.materialdialogs.MaterialDialog
import com.mikepenz.aboutlibraries.LibsBuilder
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.updater.UpdateChecker
import eu.kanade.tachiyomi.data.updater.UpdateResult
import eu.kanade.tachiyomi.data.updater.UpdaterService
import eu.kanade.tachiyomi.data.updater.github.GithubUpdateChecker
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.setting.SettingsController
import eu.kanade.tachiyomi.util.lang.launchNow
@@ -23,19 +23,19 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.copyToClipboard
import eu.kanade.tachiyomi.util.system.toast
import timber.log.Timber
import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.TimeZone
import timber.log.Timber
class AboutController : SettingsController() {
/**
* Checks for new releases
*/
private val updateChecker by lazy { UpdateChecker.getUpdateChecker() }
private val updateChecker by lazy { GithubUpdateChecker() }
private val dateFormat: DateFormat = preferences.dateFormat()
@@ -234,7 +234,9 @@ class AboutController : SettingsController() {
val buildTime = inputDf.parse(BuildConfig.BUILD_TIME)
val outputDf = DateFormat.getDateTimeInstance(
DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault()
DateFormat.MEDIUM,
DateFormat.SHORT,
Locale.getDefault()
)
outputDf.timeZone = TimeZone.getDefault()

View File

@@ -7,7 +7,6 @@ import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController
import eu.kanade.tachiyomi.ui.base.controller.RootController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
@@ -28,6 +27,7 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.openInBrowser
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.injectLazy
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class MoreController :
SettingsController(),

View File

@@ -21,6 +21,7 @@ import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.SeekBar
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
@@ -56,8 +57,6 @@ import eu.kanade.tachiyomi.util.view.showBar
import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.widget.SimpleAnimationListener
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
import java.io.File
import kotlin.math.abs
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.drop
@@ -67,6 +66,8 @@ import kotlinx.coroutines.flow.sample
import nucleus.factory.RequiresPresenter
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
import kotlin.math.abs
/**
* Activity containing the reader of Tachiyomi. This activity is mostly a container of the
@@ -290,24 +291,27 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
ViewCompat.setOnApplyWindowInsetsListener(binding.readerMenu) { _, insets ->
if (!window.isDefaultBar()) {
val systemInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
binding.readerMenu.setPadding(
insets.systemWindowInsetLeft,
insets.systemWindowInsetTop,
insets.systemWindowInsetRight,
insets.systemWindowInsetBottom
systemInsets.left,
systemInsets.top,
systemInsets.right,
systemInsets.bottom
)
}
insets
}
// Init listeners on bottom menu
binding.pageSeekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (viewer != null && fromUser) {
moveToPageIndex(value)
binding.pageSeekbar.setOnSeekBarChangeListener(
object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (viewer != null && fromUser) {
moveToPageIndex(value)
}
}
}
})
)
binding.leftChapter.setOnClickListener {
if (viewer != null) {
if (viewer is R2LPagerViewer) {
@@ -347,12 +351,14 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
if (animate) {
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() {
override fun onAnimationStart(animation: Animation) {
// Fix status bar being translucent the first time it's opened.
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
toolbarAnimation.setAnimationListener(
object : SimpleAnimationListener() {
override fun onAnimationStart(animation: Animation) {
// Fix status bar being translucent the first time it's opened.
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
}
}
})
)
binding.toolbar.startAnimation(toolbarAnimation)
val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom)
@@ -371,11 +377,13 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
if (animate) {
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top)
toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() {
override fun onAnimationEnd(animation: Animation) {
binding.readerMenu.isVisible = false
toolbarAnimation.setAnimationListener(
object : SimpleAnimationListener() {
override fun onAnimationEnd(animation: Animation) {
binding.readerMenu.isVisible = false
}
}
})
)
binding.toolbar.startAnimation(toolbarAnimation)
val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom)
@@ -572,9 +580,13 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
* Called from the presenter when a page is ready to be shared. It shows Android's default
* sharing tool.
*/
fun onShareImageResult(file: File) {
fun onShareImageResult(file: File, page: ReaderPage) {
val manga = presenter.manga ?: return
val chapter = page.chapter.chapter
val stream = file.getUriCompat(this)
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_TEXT, getString(R.string.share_page_info, manga.title, chapter.name, page.number))
putExtra(Intent.EXTRA_STREAM, stream)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
type = "image/*"

View File

@@ -74,45 +74,55 @@ class ReaderColorFilterSheet(private val activity: ReaderActivity) : BottomSheet
}
binding.colorFilterMode.setSelection(preferences.colorFilterMode().get(), false)
binding.seekbarColorFilterAlpha.setOnSeekBarChangeListener(object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, ALPHA_MASK, 24)
binding.seekbarColorFilterAlpha.setOnSeekBarChangeListener(
object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, ALPHA_MASK, 24)
}
}
}
})
)
binding.seekbarColorFilterRed.setOnSeekBarChangeListener(object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, RED_MASK, 16)
binding.seekbarColorFilterRed.setOnSeekBarChangeListener(
object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, RED_MASK, 16)
}
}
}
})
)
binding.seekbarColorFilterGreen.setOnSeekBarChangeListener(object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, GREEN_MASK, 8)
binding.seekbarColorFilterGreen.setOnSeekBarChangeListener(
object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, GREEN_MASK, 8)
}
}
}
})
)
binding.seekbarColorFilterBlue.setOnSeekBarChangeListener(object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, BLUE_MASK, 0)
binding.seekbarColorFilterBlue.setOnSeekBarChangeListener(
object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
setColorValue(value, BLUE_MASK, 0)
}
}
}
})
)
binding.brightnessSeekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
preferences.customBrightnessValue().set(value)
binding.brightnessSeekbar.setOnSeekBarChangeListener(
object : SimpleSeekBarListener() {
override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) {
if (fromUser) {
preferences.customBrightnessValue().set(value)
}
}
}
})
)
}
override fun onStart() {

View File

@@ -27,9 +27,6 @@ import eu.kanade.tachiyomi.util.lang.takeBytes
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.updateCoverLastModified
import java.io.File
import java.util.Date
import java.util.concurrent.TimeUnit
import rx.Completable
import rx.Observable
import rx.Subscription
@@ -38,6 +35,9 @@ import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
import java.util.Date
import java.util.concurrent.TimeUnit
/**
* Presenter used by the activity to perform background operations.
@@ -569,7 +569,7 @@ class ReaderPresenter(
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeFirst(
{ view, file -> view.onShareImageResult(file) },
{ view, file -> view.onShareImageResult(file, page) },
{ _, _ -> /* Empty */ }
)
}

View File

@@ -4,9 +4,9 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import eu.kanade.tachiyomi.util.system.ImageUtil
import rx.Observable
import java.io.File
import java.io.FileInputStream
import rx.Observable
/**
* Loader used to load a chapter from a directory given on [file].

View File

@@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.ui.reader.loader
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.storage.EpubFile
import java.io.File
import rx.Observable
import java.io.File
/**
* Loader used to load a chapter from a .epub file.

View File

@@ -6,9 +6,6 @@ import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.lang.plusAssign
import java.util.concurrent.PriorityBlockingQueue
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.min
import rx.Completable
import rx.Observable
import rx.schedulers.Schedulers
@@ -18,6 +15,9 @@ import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.PriorityBlockingQueue
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.min
/**
* Loader used to load chapters from an online source.

View File

@@ -4,14 +4,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import eu.kanade.tachiyomi.util.system.ImageUtil
import junrar.Archive
import junrar.rarfile.FileHeader
import rx.Observable
import java.io.File
import java.io.InputStream
import java.io.PipedInputStream
import java.io.PipedOutputStream
import java.util.concurrent.Executors
import junrar.Archive
import junrar.rarfile.FileHeader
import rx.Observable
/**
* Loader used to load a chapter from a .rar or .cbr file.

View File

@@ -5,11 +5,11 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import eu.kanade.tachiyomi.util.system.ImageUtil
import rx.Observable
import java.io.File
import java.nio.charset.StandardCharsets
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import rx.Observable
/**
* Loader used to load a chapter from a .zip or .cbz file.

View File

@@ -0,0 +1,15 @@
package eu.kanade.tachiyomi.ui.reader.viewer
import eu.kanade.tachiyomi.data.database.models.Chapter
import kotlin.math.floor
object MissingChapters {
fun hasMissingChapters(higher: Chapter, lower: Chapter): Boolean {
return hasMissingChapters(higher.chapter_number, lower.chapter_number)
}
fun hasMissingChapters(higherChapterNumber: Float, lowerChapterNumber: Float): Boolean {
return floor(higherChapterNumber) - floor(lowerChapterNumber) - 1f > 0f
}
}

View File

@@ -63,9 +63,12 @@ class ReaderProgressBar @JvmOverloads constructor(
*/
private val rotationAnimation by lazy {
RotateAnimation(
0f, 360f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f
0f,
360f,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f
).apply {
interpolator = LinearInterpolator()
repeatCount = Animation.INFINITE

View File

@@ -0,0 +1,103 @@
package eu.kanade.tachiyomi.ui.reader.viewer
import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.isVisible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import kotlinx.android.synthetic.main.reader_transition_view.view.lower_text
import kotlinx.android.synthetic.main.reader_transition_view.view.upper_text
import kotlinx.android.synthetic.main.reader_transition_view.view.warning
import kotlinx.android.synthetic.main.reader_transition_view.view.warning_text
import kotlin.math.floor
class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
LinearLayout(context, attrs) {
init {
inflate(context, R.layout.reader_transition_view, this)
}
fun bind(transition: ChapterTransition) {
when (transition) {
is ChapterTransition.Prev -> bindPrevChapterTransition(transition)
is ChapterTransition.Next -> bindNextChapterTransition(transition)
}
missingChapterWarning(transition)
}
/**
* Binds a previous chapter transition on this view and subscribes to the page load status.
*/
private fun bindPrevChapterTransition(transition: ChapterTransition) {
val prevChapter = transition.to
val hasPrevChapter = prevChapter != null
lower_text.isVisible = hasPrevChapter
if (hasPrevChapter) {
upper_text.textAlignment = TEXT_ALIGNMENT_TEXT_START
upper_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_current)) }
append("\n${transition.from.chapter.name}")
}
lower_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_previous)) }
append("\n${prevChapter!!.chapter.name}")
}
} else {
upper_text.textAlignment = TEXT_ALIGNMENT_CENTER
upper_text.text = context.getString(R.string.transition_no_previous)
}
}
/**
* Binds a next chapter transition on this view and subscribes to the load status.
*/
private fun bindNextChapterTransition(transition: ChapterTransition) {
val nextChapter = transition.to
val hasNextChapter = nextChapter != null
lower_text.isVisible = hasNextChapter
if (hasNextChapter) {
upper_text.textAlignment = TEXT_ALIGNMENT_TEXT_START
upper_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_finished)) }
append("\n${transition.from.chapter.name}")
}
lower_text.text = buildSpannedString {
bold { append(context.getString(R.string.transition_next)) }
append("\n${nextChapter!!.chapter.name}")
}
} else {
upper_text.textAlignment = TEXT_ALIGNMENT_CENTER
upper_text.text = context.getString(R.string.transition_no_next)
}
}
private fun missingChapterWarning(transition: ChapterTransition) {
if (transition.to == null) {
warning.isVisible = false
return
}
val fromChapterNumber: Float = floor(transition.from.chapter.chapter_number)
val toChapterNumber: Float = floor(transition.to!!.chapter.chapter_number)
val chapterDifference = when (transition) {
is ChapterTransition.Prev -> fromChapterNumber - toChapterNumber - 1f
is ChapterTransition.Next -> toChapterNumber - fromChapterNumber - 1f
}
val hasMissingChapters = when (transition) {
is ChapterTransition.Prev -> MissingChapters.hasMissingChapters(fromChapterNumber, toChapterNumber)
is ChapterTransition.Next -> MissingChapters.hasMissingChapters(toChapterNumber, fromChapterNumber)
}
warning_text.text = resources.getQuantityString(R.plurals.missing_chapters_warning, chapterDifference.toInt(), chapterDifference.toInt())
warning.isVisible = hasMissingChapters
}
}

View File

@@ -35,12 +35,12 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
import java.io.InputStream
import java.util.concurrent.TimeUnit
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import java.io.InputStream
import java.util.concurrent.TimeUnit
/**
* View of the ViewPager that contains a page of a chapter.
@@ -307,20 +307,22 @@ class PagerPageHolder(
setMinimumDpi(90)
setMinimumTileDpi(180)
setCropBorders(config.imageCropBorders)
setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() {
override fun onReady() {
when (config.imageZoomType) {
ZoomType.Left -> setScaleAndCenter(scale, PointF(0f, 0f))
ZoomType.Right -> setScaleAndCenter(scale, PointF(sWidth.toFloat(), 0f))
ZoomType.Center -> setScaleAndCenter(scale, center.also { it?.y = 0f })
setOnImageEventListener(
object : SubsamplingScaleImageView.DefaultOnImageEventListener() {
override fun onReady() {
when (config.imageZoomType) {
ZoomType.Left -> setScaleAndCenter(scale, PointF(0f, 0f))
ZoomType.Right -> setScaleAndCenter(scale, PointF(sWidth.toFloat(), 0f))
ZoomType.Center -> setScaleAndCenter(scale, center.also { it?.y = 0f })
}
onImageDecoded()
}
onImageDecoded()
}
override fun onImageLoadError(e: Exception) {
onImageDecodeError()
override fun onImageLoadError(e: Exception) {
onImageDecodeError()
}
}
})
)
}
addView(subsamplingImageView)
return subsamplingImageView!!
@@ -338,16 +340,18 @@ class PagerPageHolder(
setZoomTransitionDuration(viewer.config.doubleTapAnimDuration)
setScaleLevels(1f, 2f, 3f)
// Force 2 scale levels on double tap
setOnDoubleTapListener(object : GestureDetector.SimpleOnGestureListener() {
override fun onDoubleTap(e: MotionEvent): Boolean {
if (scale > 1f) {
setScale(1f, e.x, e.y, true)
} else {
setScale(2f, e.x, e.y, true)
setOnDoubleTapListener(
object : GestureDetector.SimpleOnGestureListener() {
override fun onDoubleTap(e: MotionEvent): Boolean {
if (scale > 1f) {
setScale(1f, e.x, e.y, true)
} else {
setScale(2f, e.x, e.y, true)
}
return true
}
return true
}
})
)
}
addView(imageView)
return imageView!!
@@ -437,31 +441,33 @@ class PagerPageHolder(
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.transition(DrawableTransitionOptions.with(NoTransition.getFactory()))
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
onImageDecodeError()
return false
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
if (resource is GifDrawable) {
resource.setLoopCount(GifDrawable.LOOP_INTRINSIC)
.listener(
object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
onImageDecodeError()
return false
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
if (resource is GifDrawable) {
resource.setLoopCount(GifDrawable.LOOP_INTRINSIC)
}
onImageDecoded()
return false
}
onImageDecoded()
return false
}
})
)
.into(this)
}
}

View File

@@ -8,13 +8,11 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderTransitionView
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
import rx.Subscription
@@ -40,14 +38,6 @@ class PagerTransitionHolder(
*/
private var statusSubscription: Subscription? = null
/**
* Text view used to display the text of the current and next/prev chapters.
*/
private var textView = TextView(context).apply {
textSize = 17.5F
wrapContent()
}
/**
* View container of the current status of the transition page. Child views will be added
* dynamically.
@@ -63,13 +53,14 @@ class PagerTransitionHolder(
gravity = Gravity.CENTER
val sidePadding = 64.dpToPx
setPadding(sidePadding, 0, sidePadding, 0)
addView(textView)
val transitionView = ReaderTransitionView(context)
addView(transitionView)
addView(pagesContainer)
when (transition) {
is ChapterTransition.Prev -> bindPrevChapterTransition()
is ChapterTransition.Next -> bindNextChapterTransition()
}
transitionView.bind(transition)
transition.to?.let { observeStatus(it) }
}
/**
@@ -81,50 +72,6 @@ class PagerTransitionHolder(
statusSubscription = null
}
/**
* Binds a next chapter transition on this view and subscribes to the load status.
*/
private fun bindNextChapterTransition() {
val nextChapter = transition.to
textView.text = if (nextChapter != null) {
buildSpannedString {
bold { append(context.getString(R.string.transition_finished)) }
append("\n${transition.from.chapter.name}\n\n")
bold { append(context.getString(R.string.transition_next)) }
append("\n${nextChapter.chapter.name}\n\n")
}
} else {
context.getString(R.string.transition_no_next)
}
if (nextChapter != null) {
observeStatus(nextChapter)
}
}
/**
* Binds a previous chapter transition on this view and subscribes to the page load status.
*/
private fun bindPrevChapterTransition() {
val prevChapter = transition.to
textView.text = if (prevChapter != null) {
buildSpannedString {
bold { append(context.getString(R.string.transition_current)) }
append("\n${transition.from.chapter.name}\n\n")
bold { append(context.getString(R.string.transition_previous)) }
append("\n${prevChapter.chapter.name}\n\n")
}
} else {
context.getString(R.string.transition_no_previous)
}
if (prevChapter != null) {
observeStatus(prevChapter)
}
}
/**
* Observes the status of the page list of the next/previous chapter. Whenever there's a new
* state, the pages container is cleaned up before setting the new state.

View File

@@ -71,15 +71,17 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
pager.offscreenPageLimit = 1
pager.id = R.id.reader_pager
pager.adapter = adapter
pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) {
onPageChange(position)
}
pager.addOnPageChangeListener(
object : ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) {
onPageChange(position)
}
override fun onPageScrollStateChanged(state: Int) {
isIdle = state == ViewPager.SCROLL_STATE_IDLE
override fun onPageScrollStateChanged(state: Int) {
isIdle = state == ViewPager.SCROLL_STATE_IDLE
}
}
})
)
pager.tapListener = f@{ event ->
if (!config.tappingEnabled) {
activity.toggleMenu()

View File

@@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.MissingChapters
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
import timber.log.Timber
@@ -33,6 +34,10 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
fun setChapters(chapters: ViewerChapters, forceTransition: Boolean) {
val newItems = mutableListOf<Any>()
// Forces chapter transition if there is missing chapters
val prevHasMissingChapters = if (chapters.prevChapter != null) MissingChapters.hasMissingChapters(chapters.currChapter.chapter, chapters.prevChapter.chapter) else false
val nextHasMissingChapters = if (chapters.nextChapter != null) MissingChapters.hasMissingChapters(chapters.nextChapter.chapter, chapters.currChapter.chapter) else false
// Add previous chapter pages and transition.
if (chapters.prevChapter != null) {
// We only need to add the last few pages of the previous chapter, because it'll be
@@ -44,7 +49,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
}
// Skip transition page if the chapter is loaded & current page is not a transition page
if (forceTransition || chapters.prevChapter?.state !is ReaderChapter.State.Loaded) {
if (prevHasMissingChapters || forceTransition || chapters.prevChapter?.state !is ReaderChapter.State.Loaded) {
newItems.add(ChapterTransition.Prev(chapters.currChapter, chapters.prevChapter))
}
@@ -59,7 +64,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
// Add next chapter transition and pages.
nextTransition = ChapterTransition.Next(chapters.currChapter, chapters.nextChapter)
.also {
if (forceTransition ||
if (nextHasMissingChapters || forceTransition ||
chapters.nextChapter?.state !is ReaderChapter.State.Loaded
) {
newItems.add(it)

View File

@@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.MissingChapters
/**
* RecyclerView Adapter used by this [viewer] to where [ViewerChapters] updates are posted.
@@ -29,6 +30,10 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
fun setChapters(chapters: ViewerChapters, forceTransition: Boolean) {
val newItems = mutableListOf<Any>()
// Forces chapter transition if there is missing chapters
val prevHasMissingChapters = if (chapters.prevChapter != null) MissingChapters.hasMissingChapters(chapters.currChapter.chapter, chapters.prevChapter.chapter) else false
val nextHasMissingChapters = if (chapters.nextChapter != null) MissingChapters.hasMissingChapters(chapters.nextChapter.chapter, chapters.currChapter.chapter) else false
// Add previous chapter pages and transition.
if (chapters.prevChapter != null) {
// We only need to add the last few pages of the previous chapter, because it'll be
@@ -40,7 +45,7 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
}
// Skip transition page if the chapter is loaded & current page is not a transition page
if (forceTransition || chapters.prevChapter?.state !is ReaderChapter.State.Loaded) {
if (prevHasMissingChapters || forceTransition || chapters.prevChapter?.state !is ReaderChapter.State.Loaded) {
newItems.add(ChapterTransition.Prev(chapters.currChapter, chapters.prevChapter))
}
@@ -53,7 +58,7 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
currentChapter = chapters.currChapter
// Add next chapter transition and pages.
if (forceTransition || chapters.nextChapter?.state !is ReaderChapter.State.Loaded) {
if (nextHasMissingChapters || forceTransition || chapters.nextChapter?.state !is ReaderChapter.State.Loaded) {
newItems.add(ChapterTransition.Next(chapters.currChapter, chapters.nextChapter))
}

View File

@@ -32,12 +32,12 @@ import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.dpToPx
import java.io.InputStream
import java.util.concurrent.TimeUnit
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import java.io.InputStream
import java.util.concurrent.TimeUnit
/**
* Holder of the webtoon reader for a single page of a chapter.
@@ -362,15 +362,17 @@ class WebtoonPageHolder(
setMinimumDpi(90)
setMinimumTileDpi(180)
setCropBorders(config.imageCropBorders)
setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() {
override fun onReady() {
onImageDecoded()
}
setOnImageEventListener(
object : SubsamplingScaleImageView.DefaultOnImageEventListener() {
override fun onReady() {
onImageDecoded()
}
override fun onImageLoadError(e: Exception) {
onImageDecodeError()
override fun onImageLoadError(e: Exception) {
onImageDecodeError()
}
}
})
)
}
frame.addView(subsamplingImageView, MATCH_PARENT, MATCH_PARENT)
return subsamplingImageView!!
@@ -492,31 +494,33 @@ class WebtoonPageHolder(
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.transition(DrawableTransitionOptions.with(NoTransition.getFactory()))
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
onImageDecodeError()
return false
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
if (resource is GifDrawable) {
resource.setLoopCount(GifDrawable.LOOP_INTRINSIC)
.listener(
object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
onImageDecodeError()
return false
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
if (resource is GifDrawable) {
resource.setLoopCount(GifDrawable.LOOP_INTRINSIC)
}
onImageDecoded()
return false
}
onImageDecoded()
return false
}
})
)
.into(this)
}
}

View File

@@ -5,16 +5,14 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.isNotEmpty
import androidx.core.view.isVisible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderTransitionView
import eu.kanade.tachiyomi.util.system.dpToPx
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@@ -32,13 +30,7 @@ class WebtoonTransitionHolder(
*/
private var statusSubscription: Subscription? = null
/**
* Text view used to display the text of the current and next/prev chapters.
*/
private var textView = TextView(context).apply {
textSize = 17.5F
wrapContent()
}
private val transitionView = ReaderTransitionView(context)
/**
* View container of the current status of the transition page. Child views will be added
@@ -63,7 +55,7 @@ class WebtoonTransitionHolder(
setMargins(0, childMargins, 0, childMargins)
}
layout.addView(textView, childParams)
layout.addView(transitionView)
layout.addView(pagesContainer, childParams)
}
@@ -71,10 +63,9 @@ class WebtoonTransitionHolder(
* Binds the given [transition] with this view holder, subscribing to its state.
*/
fun bind(transition: ChapterTransition) {
when (transition) {
is ChapterTransition.Prev -> bindPrevChapterTransition(transition)
is ChapterTransition.Next -> bindNextChapterTransition(transition)
}
transitionView.bind(transition)
transition.to?.let { observeStatus(it, transition) }
}
/**
@@ -84,50 +75,6 @@ class WebtoonTransitionHolder(
unsubscribeStatus()
}
/**
* Binds a next chapter transition on this view and subscribes to the load status.
*/
private fun bindNextChapterTransition(transition: ChapterTransition.Next) {
val nextChapter = transition.to
textView.text = if (nextChapter != null) {
buildSpannedString {
bold { append(context.getString(R.string.transition_finished)) }
append("\n${transition.from.chapter.name}\n\n")
bold { append(context.getString(R.string.transition_next)) }
append("\n${nextChapter.chapter.name}\n\n")
}
} else {
context.getString(R.string.transition_no_next)
}
if (nextChapter != null) {
observeStatus(nextChapter, transition)
}
}
/**
* Binds a previous chapter transition on this view and subscribes to the page load status.
*/
private fun bindPrevChapterTransition(transition: ChapterTransition.Prev) {
val prevChapter = transition.to
textView.text = if (prevChapter != null) {
buildSpannedString {
bold { append(context.getString(R.string.transition_current)) }
append("\n${transition.from.chapter.name}\n\n")
bold { append(context.getString(R.string.transition_previous)) }
append("\n${prevChapter.chapter.name}\n\n")
}
} else {
context.getString(R.string.transition_no_previous)
}
if (prevChapter != null) {
observeStatus(prevChapter, transition)
}
}
/**
* Observes the status of the page list of the next/previous chapter. Whenever there's a new
* state, the pages container is cleaned up before setting the new state.

View File

@@ -15,10 +15,10 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
import kotlin.math.max
import kotlin.math.min
import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import kotlin.math.max
import kotlin.math.min
/**
* Implementation of a [BaseViewer] to display pages with a [RecyclerView].
@@ -71,28 +71,30 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
recycler.itemAnimator = null
recycler.layoutManager = layoutManager
recycler.adapter = adapter
recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val position = layoutManager.findLastEndVisibleItemPosition()
val item = adapter.items.getOrNull(position)
val allowPreload = checkAllowPreload(item as? ReaderPage)
if (item != null && currentPage != item) {
currentPage = item
when (item) {
is ReaderPage -> onPageSelected(item, allowPreload)
is ChapterTransition -> onTransitionSelected(item)
recycler.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val position = layoutManager.findLastEndVisibleItemPosition()
val item = adapter.items.getOrNull(position)
val allowPreload = checkAllowPreload(item as? ReaderPage)
if (item != null && currentPage != item) {
currentPage = item
when (item) {
is ReaderPage -> onPageSelected(item, allowPreload)
is ChapterTransition -> onTransitionSelected(item)
}
}
}
if (dy < 0) {
val firstIndex = layoutManager.findFirstVisibleItemPosition()
val firstItem = adapter.items.getOrNull(firstIndex)
if (firstItem is ChapterTransition.Prev && firstItem.to != null) {
activity.requestPreloadChapter(firstItem.to)
if (dy < 0) {
val firstIndex = layoutManager.findFirstVisibleItemPosition()
val firstItem = adapter.items.getOrNull(firstIndex)
if (firstItem is ChapterTransition.Prev && firstItem.to != null) {
activity.requestPreloadChapter(firstItem.to)
}
}
}
}
})
)
recycler.tapListener = f@{ event ->
if (!config.tappingEnabled) {
activity.toggleMenu()

View File

@@ -2,9 +2,9 @@ package eu.kanade.tachiyomi.ui.recent.history
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.source.SourceManager
import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import uy.kohesive.injekt.injectLazy
/**
* Adapter of HistoryHolder.

View File

@@ -8,13 +8,13 @@ import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.data.glide.toMangaThumbnail
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.lang.toTimestampString
import java.util.Date
import kotlinx.android.synthetic.main.history_item.cover
import kotlinx.android.synthetic.main.history_item.holder
import kotlinx.android.synthetic.main.history_item.manga_subtitle
import kotlinx.android.synthetic.main.history_item.manga_title
import kotlinx.android.synthetic.main.history_item.remove
import kotlinx.android.synthetic.main.history_item.resume
import java.util.Date
/**
* Holder that contains recent manga item

View File

@@ -9,13 +9,13 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.recent.DateSectionItem
import eu.kanade.tachiyomi.util.lang.toDateKey
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.injectLazy
import java.util.Calendar
import java.util.Comparator
import java.util.Date
import java.util.TreeMap
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.injectLazy
/**
* Presenter of HistoryFragment.

View File

@@ -8,7 +8,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
@@ -89,7 +88,6 @@ class UpdatesController :
// Init RecyclerView and adapter
val layoutManager = LinearLayoutManager(view.context)
binding.recycler.layoutManager = layoutManager
binding.recycler.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL))
binding.recycler.setHasFixedSize(true)
adapter = UpdatesAdapter(this@UpdatesController)
binding.recycler.adapter = adapter

View File

@@ -10,15 +10,15 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.recent.DateSectionItem
import eu.kanade.tachiyomi.util.lang.toDateKey
import java.util.Calendar
import java.util.Date
import java.util.TreeMap
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Calendar
import java.util.Date
import java.util.TreeMap
class UpdatesPresenter(
val preferences: PreferencesHelper = Injekt.get(),

View File

@@ -5,9 +5,9 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricPrompt
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import uy.kohesive.injekt.injectLazy
import java.util.Date
import java.util.concurrent.Executors
import uy.kohesive.injekt.injectLazy
/**
* Blank activity with a BiometricPrompt.
@@ -21,7 +21,8 @@ class BiometricUnlockActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
val biometricPrompt = BiometricPrompt(
this, executor,
this,
executor,
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)

View File

@@ -6,10 +6,10 @@ import androidx.biometric.BiometricManager
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import java.util.Date
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.injectLazy
import java.util.Date
class SecureActivityDelegate(private val activity: FragmentActivity) {

View File

@@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Target
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.preference.defaultValue
@@ -31,6 +30,7 @@ import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import uy.kohesive.injekt.injectLazy
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsAdvancedController : SettingsController() {
private val network: NetworkHelper by injectLazy()

View File

@@ -19,7 +19,6 @@ import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
import eu.kanade.tachiyomi.data.backup.BackupRestoreValidator
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
@@ -36,6 +35,7 @@ import eu.kanade.tachiyomi.util.system.getFilePicker
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsBackupController : SettingsController() {
@@ -92,9 +92,12 @@ class SettingsBackupController : SettingsController() {
key = Keys.backupInterval
titleRes = R.string.pref_backup_interval
entriesRes = arrayOf(
R.string.update_never, R.string.update_6hour,
R.string.update_12hour, R.string.update_24hour,
R.string.update_48hour, R.string.update_weekly
R.string.update_never,
R.string.update_6hour,
R.string.update_12hour,
R.string.update_24hour,
R.string.update_48hour,
R.string.update_weekly
)
entryValues = arrayOf("0", "6", "12", "24", "48", "168")
defaultValue = "0"
@@ -213,8 +216,11 @@ class SettingsBackupController : SettingsController() {
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
val activity = activity!!
val options = arrayOf(
R.string.manga, R.string.categories, R.string.chapters,
R.string.track, R.string.history
R.string.manga,
R.string.categories,
R.string.chapters,
R.string.track,
R.string.history
)
.map { activity.getString(it) }

View File

@@ -2,13 +2,13 @@ package eu.kanade.tachiyomi.ui.setting
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.onChange
import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.switchPreference
import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsBrowseController : SettingsController() {

View File

@@ -15,7 +15,6 @@ import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.ui.base.controller.DialogController
@@ -29,12 +28,13 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.switchPreference
import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.getFilePicker
import java.io.File
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.File
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsDownloadController : SettingsController() {
@@ -76,8 +76,11 @@ class SettingsDownloadController : SettingsController() {
key = Keys.removeAfterReadSlots
titleRes = R.string.pref_remove_after_read
entriesRes = arrayOf(
R.string.disabled, R.string.last_read_chapter,
R.string.second_to_last, R.string.third_to_last, R.string.fourth_to_last,
R.string.disabled,
R.string.last_read_chapter,
R.string.second_to_last,
R.string.third_to_last,
R.string.fourth_to_last,
R.string.fifth_to_last
)
entryValues = arrayOf("-1", "0", "1", "2", "3", "4")

View File

@@ -5,8 +5,6 @@ import android.os.Build
import android.provider.Settings
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.entriesRes
@@ -19,8 +17,10 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.switchPreference
import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.LocaleHelper
import java.util.Date
import kotlinx.coroutines.flow.launchIn
import java.util.Date
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
class SettingsGeneralController : SettingsController() {

View File

@@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.ui.base.controller.DialogController
@@ -35,6 +34,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsLibraryController : SettingsController() {
@@ -123,9 +123,14 @@ class SettingsLibraryController : SettingsController() {
key = Keys.libraryUpdateInterval
titleRes = R.string.pref_library_update_interval
entriesRes = arrayOf(
R.string.update_never, R.string.update_1hour,
R.string.update_2hour, R.string.update_3hour, R.string.update_6hour,
R.string.update_12hour, R.string.update_24hour, R.string.update_48hour
R.string.update_never,
R.string.update_1hour,
R.string.update_2hour,
R.string.update_3hour,
R.string.update_6hour,
R.string.update_12hour,
R.string.update_24hour,
R.string.update_48hour
)
entryValues = arrayOf("0", "1", "2", "3", "6", "12", "24", "48")
defaultValue = "24"

View File

@@ -2,14 +2,14 @@ package eu.kanade.tachiyomi.ui.setting
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.entriesRes
import eu.kanade.tachiyomi.util.preference.infoPreference
import eu.kanade.tachiyomi.util.preference.listPreference
import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
class SettingsParentalControlsController : SettingsController() {

View File

@@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.setting
import android.os.Build
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues.TappingInvertMode
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.util.preference.defaultValue
@@ -16,6 +15,7 @@ import eu.kanade.tachiyomi.util.preference.switchPreference
import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
import kotlinx.coroutines.flow.launchIn
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsReaderController : SettingsController() {
@@ -26,8 +26,11 @@ class SettingsReaderController : SettingsController() {
key = Keys.defaultViewer
titleRes = R.string.pref_viewer_type
entriesRes = arrayOf(
R.string.left_to_right_viewer, R.string.right_to_left_viewer,
R.string.vertical_viewer, R.string.webtoon_viewer, R.string.vertical_plus_viewer
R.string.left_to_right_viewer,
R.string.right_to_left_viewer,
R.string.vertical_viewer,
R.string.webtoon_viewer,
R.string.vertical_plus_viewer
)
entryValues = arrayOf("1", "2", "3", "4", "5")
defaultValue = "2"
@@ -68,8 +71,10 @@ class SettingsReaderController : SettingsController() {
key = Keys.rotation
titleRes = R.string.pref_rotation_type
entriesRes = arrayOf(
R.string.rotation_free, R.string.rotation_lock,
R.string.rotation_force_portrait, R.string.rotation_force_landscape
R.string.rotation_free,
R.string.rotation_lock,
R.string.rotation_force_portrait,
R.string.rotation_force_landscape
)
entryValues = arrayOf("1", "2", "3", "4")
defaultValue = "1"
@@ -136,9 +141,12 @@ class SettingsReaderController : SettingsController() {
key = Keys.imageScaleType
titleRes = R.string.pref_image_scale_type
entriesRes = arrayOf(
R.string.scale_type_fit_screen, R.string.scale_type_stretch,
R.string.scale_type_fit_width, R.string.scale_type_fit_height,
R.string.scale_type_original_size, R.string.scale_type_smart_fit
R.string.scale_type_fit_screen,
R.string.scale_type_stretch,
R.string.scale_type_fit_width,
R.string.scale_type_fit_height,
R.string.scale_type_original_size,
R.string.scale_type_smart_fit
)
entryValues = arrayOf("1", "2", "3", "4", "5", "6")
defaultValue = "1"
@@ -148,8 +156,10 @@ class SettingsReaderController : SettingsController() {
key = Keys.zoomStart
titleRes = R.string.pref_zoom_start
entriesRes = arrayOf(
R.string.zoom_start_automatic, R.string.zoom_start_left,
R.string.zoom_start_right, R.string.zoom_start_center
R.string.zoom_start_automatic,
R.string.zoom_start_left,
R.string.zoom_start_right,
R.string.zoom_start_center
)
entryValues = arrayOf("1", "2", "3", "4")
defaultValue = "1"

View File

@@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.setting
import androidx.biometric.BiometricManager
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.intListPreference
@@ -11,6 +10,7 @@ import eu.kanade.tachiyomi.util.preference.summaryRes
import eu.kanade.tachiyomi.util.preference.switchPreference
import eu.kanade.tachiyomi.util.preference.titleRes
import kotlinx.coroutines.flow.launchIn
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsSecurityController : SettingsController() {

View File

@@ -5,7 +5,6 @@ import android.content.Intent
import androidx.browser.customtabs.CustomTabsIntent
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.anilist.AnilistApi
@@ -23,6 +22,7 @@ import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.widget.preference.LoginPreference
import uy.kohesive.injekt.injectLazy
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsTrackingController :
SettingsController(),