mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-10 20:15:09 +01:00
Updated Extensions Settings view
Some changes from upstream plus: Settings in same view (collapsible) Sorted by enabled languages Disabled languages show as off Disabled sources due to language can be turned on via tapping on them then the snackbar
This commit is contained in:
parent
5afb2461e5
commit
9a220073b9
@ -98,7 +98,7 @@ dependencies {
|
|||||||
implementation("androidx.appcompat:appcompat:1.2.0")
|
implementation("androidx.appcompat:appcompat:1.2.0")
|
||||||
implementation("androidx.cardview:cardview:1.0.0")
|
implementation("androidx.cardview:cardview:1.0.0")
|
||||||
implementation("com.google.android.material:material:1.3.0")
|
implementation("com.google.android.material:material:1.3.0")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.1.0")
|
implementation("androidx.recyclerview:recyclerview:1.2.0-beta02")
|
||||||
implementation("androidx.preference:preference:1.1.1")
|
implementation("androidx.preference:preference:1.1.1")
|
||||||
implementation("androidx.annotation:annotation:1.1.0")
|
implementation("androidx.annotation:annotation:1.1.0")
|
||||||
implementation("androidx.browser:browser:1.3.0")
|
implementation("androidx.browser:browser:1.3.0")
|
||||||
|
@ -43,6 +43,14 @@ private class DateFormatConverter : Preference.Adapter<DateFormat> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator fun <T> com.tfcporciuncula.flow.Preference<Set<T>>.plusAssign(item: T) {
|
||||||
|
set(get() + item)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T> com.tfcporciuncula.flow.Preference<Set<T>>.minusAssign(item: T) {
|
||||||
|
set(get() - item)
|
||||||
|
}
|
||||||
|
|
||||||
class PreferencesHelper(val context: Context) {
|
class PreferencesHelper(val context: Context) {
|
||||||
|
|
||||||
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
@ -135,7 +143,7 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun browseAsList() = rxPrefs.getBoolean(Keys.catalogueAsList, false)
|
fun browseAsList() = rxPrefs.getBoolean(Keys.catalogueAsList, false)
|
||||||
|
|
||||||
fun enabledLanguages() = rxPrefs.getStringSet(Keys.enabledLanguages, setOf("en", Locale.getDefault().language))
|
fun enabledLanguages() = flowPrefs.getStringSet(Keys.enabledLanguages, setOf("en", Locale.getDefault().language))
|
||||||
|
|
||||||
fun sourceSorting() = rxPrefs.getInteger(Keys.sourcesSort, 0)
|
fun sourceSorting() = rxPrefs.getInteger(Keys.sourcesSort, 0)
|
||||||
|
|
||||||
@ -211,7 +219,7 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun collapsedCategories() = rxPrefs.getStringSet("collapsed_categories", mutableSetOf())
|
fun collapsedCategories() = rxPrefs.getStringSet("collapsed_categories", mutableSetOf())
|
||||||
|
|
||||||
fun hiddenSources() = rxPrefs.getStringSet("hidden_catalogues", mutableSetOf())
|
fun hiddenSources() = flowPrefs.getStringSet("hidden_catalogues", mutableSetOf())
|
||||||
|
|
||||||
fun pinnedCatalogues() = rxPrefs.getStringSet("pinned_catalogues", emptySet())
|
fun pinnedCatalogues() = rxPrefs.getStringSet("pinned_catalogues", emptySet())
|
||||||
|
|
||||||
|
@ -97,3 +97,5 @@ interface Source : tachiyomi.source.Source {
|
|||||||
|
|
||||||
fun Source.icon(): Drawable? =
|
fun Source.icon(): Drawable? =
|
||||||
Injekt.get<ExtensionManager>().getAppIconForSource(this)
|
Injekt.get<ExtensionManager>().getAppIconForSource(this)
|
||||||
|
|
||||||
|
fun Source.getPreferenceKey(): String = "source_$id"
|
||||||
|
@ -146,7 +146,7 @@ class ExtensionBottomPresenter(
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
private fun toItems(tuple: ExtensionTuple): List<ExtensionItem> {
|
private fun toItems(tuple: ExtensionTuple): List<ExtensionItem> {
|
||||||
val context = bottomSheet.context
|
val context = bottomSheet.context
|
||||||
val activeLangs = preferences.enabledLanguages().getOrDefault()
|
val activeLangs = preferences.enabledLanguages().get()
|
||||||
|
|
||||||
val (installed, untrusted, available) = tuple
|
val (installed, untrusted, available) = tuple
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ class ExtensionBottomPresenter(
|
|||||||
}
|
}
|
||||||
if (availableSorted.isNotEmpty()) {
|
if (availableSorted.isNotEmpty()) {
|
||||||
val availableGroupedByLang = availableSorted
|
val availableGroupedByLang = availableSorted
|
||||||
.groupBy { LocaleHelper.getDisplayName(it.lang, context) }
|
.groupBy { LocaleHelper.getSourceDisplayName(it.lang, context) }
|
||||||
.toSortedMap()
|
.toSortedMap()
|
||||||
|
|
||||||
availableGroupedByLang
|
availableGroupedByLang
|
||||||
|
@ -2,38 +2,30 @@ package eu.kanade.tachiyomi.ui.extension
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.core.view.get
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.extension.model.Extension
|
import eu.kanade.tachiyomi.extension.model.Extension
|
||||||
|
import eu.kanade.tachiyomi.ui.extension.details.ExtensionDetailsController
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.migration.MangaAdapter
|
import eu.kanade.tachiyomi.ui.migration.MangaAdapter
|
||||||
import eu.kanade.tachiyomi.ui.migration.MangaItem
|
import eu.kanade.tachiyomi.ui.migration.MangaItem
|
||||||
import eu.kanade.tachiyomi.ui.migration.SourceAdapter
|
import eu.kanade.tachiyomi.ui.migration.SourceAdapter
|
||||||
import eu.kanade.tachiyomi.ui.migration.SourceItem
|
import eu.kanade.tachiyomi.ui.migration.SourceItem
|
||||||
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
||||||
import eu.kanade.tachiyomi.ui.recents.RecentMangaHolder
|
|
||||||
import eu.kanade.tachiyomi.ui.source.SourceController
|
import eu.kanade.tachiyomi.ui.source.SourceController
|
||||||
import eu.kanade.tachiyomi.util.system.await
|
|
||||||
import eu.kanade.tachiyomi.util.system.launchUI
|
|
||||||
import eu.kanade.tachiyomi.util.view.collapse
|
import eu.kanade.tachiyomi.util.view.collapse
|
||||||
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
||||||
import eu.kanade.tachiyomi.util.view.expand
|
import eu.kanade.tachiyomi.util.view.expand
|
||||||
import eu.kanade.tachiyomi.util.view.isExpanded
|
import eu.kanade.tachiyomi.util.view.isExpanded
|
||||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
|
||||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||||
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
|
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
|
||||||
@ -42,9 +34,6 @@ import kotlinx.android.synthetic.main.main_activity.*
|
|||||||
import kotlinx.android.synthetic.main.migration_controller.*
|
import kotlinx.android.synthetic.main.migration_controller.*
|
||||||
import kotlinx.android.synthetic.main.recents_controller.*
|
import kotlinx.android.synthetic.main.recents_controller.*
|
||||||
import kotlinx.android.synthetic.main.recycler_with_scroller.view.*
|
import kotlinx.android.synthetic.main.recycler_with_scroller.view.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import rx.schedulers.Schedulers
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
@ -244,9 +233,11 @@ class ExtensionBottomSheet @JvmOverloads constructor(context: Context, attrs: At
|
|||||||
.showDialog(controller.router)
|
.showDialog(controller.router)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setExtensions(extensions: List<ExtensionItem>) {
|
fun setExtensions(extensions: List<ExtensionItem>, updateController: Boolean = true) {
|
||||||
this.extensions = extensions
|
this.extensions = extensions
|
||||||
controller.presenter.updateSources()
|
if (updateController) {
|
||||||
|
controller.presenter.updateSources()
|
||||||
|
}
|
||||||
drawExtensions()
|
drawExtensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
|
|||||||
// Set source name
|
// Set source name
|
||||||
ext_title.text = extension.name
|
ext_title.text = extension.name
|
||||||
version.text = extension.versionName
|
version.text = extension.versionName
|
||||||
lang.text = LocaleHelper.getDisplayName(extension.lang, itemView.context)
|
lang.text = LocaleHelper.getDisplayName(extension.lang)
|
||||||
warning.text = when {
|
warning.text = when {
|
||||||
extension is Extension.Untrusted -> itemView.context.getString(R.string.untrusted)
|
extension is Extension.Untrusted -> itemView.context.getString(R.string.untrusted)
|
||||||
extension is Extension.Installed && extension.isObsolete -> itemView.context.getString(R.string.obsolete)
|
extension is Extension.Installed && extension.isObsolete -> itemView.context.getString(R.string.obsolete)
|
||||||
|
@ -17,7 +17,7 @@ class SettingsExtensionsController : SettingsController() {
|
|||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
||||||
titleRes = R.string.filter
|
titleRes = R.string.filter
|
||||||
|
|
||||||
val activeLangs = preferences.enabledLanguages().getOrDefault()
|
val activeLangs = preferences.enabledLanguages().get()
|
||||||
|
|
||||||
val availableLangs =
|
val availableLangs =
|
||||||
Injekt.get<ExtensionManager>().availableExtensions.groupBy {
|
Injekt.get<ExtensionManager>().availableExtensions.groupBy {
|
||||||
@ -31,13 +31,13 @@ class SettingsExtensionsController : SettingsController() {
|
|||||||
availableLangs.forEach {
|
availableLangs.forEach {
|
||||||
SwitchPreference(context).apply {
|
SwitchPreference(context).apply {
|
||||||
preferenceScreen.addPreference(this)
|
preferenceScreen.addPreference(this)
|
||||||
title = LocaleHelper.getDisplayName(it, context)
|
title = LocaleHelper.getSourceDisplayName(it, context)
|
||||||
isPersistent = false
|
isPersistent = false
|
||||||
isChecked = it in activeLangs
|
isChecked = it in activeLangs
|
||||||
|
|
||||||
onChange { newValue ->
|
onChange { newValue ->
|
||||||
val checked = newValue as Boolean
|
val checked = newValue as Boolean
|
||||||
val currentActiveLangs = preferences.enabledLanguages().getOrDefault()
|
val currentActiveLangs = preferences.enabledLanguages().get()
|
||||||
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
preferences.enabledLanguages().set(currentActiveLangs + it)
|
preferences.enabledLanguages().set(currentActiveLangs + it)
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
package eu.kanade.tachiyomi.ui.extension
|
package eu.kanade.tachiyomi.ui.extension.details
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.preference.DialogPreference
|
import androidx.preference.DialogPreference
|
||||||
@ -19,20 +25,33 @@ import androidx.preference.Preference
|
|||||||
import androidx.preference.PreferenceGroupAdapter
|
import androidx.preference.PreferenceGroupAdapter
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import com.jakewharton.rxbinding.view.clicks
|
import androidx.recyclerview.widget.ConcatAdapter
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore
|
import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
||||||
|
import eu.kanade.tachiyomi.data.preference.minusAssign
|
||||||
|
import eu.kanade.tachiyomi.data.preference.plusAssign
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
import eu.kanade.tachiyomi.source.getPreferenceKey
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||||
import eu.kanade.tachiyomi.ui.setting.preferenceCategory
|
import eu.kanade.tachiyomi.ui.setting.DSL
|
||||||
|
import eu.kanade.tachiyomi.ui.setting.onChange
|
||||||
|
import eu.kanade.tachiyomi.ui.setting.switchPreference
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
import eu.kanade.tachiyomi.util.view.openInBrowser
|
||||||
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForController
|
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
||||||
|
import eu.kanade.tachiyomi.util.view.snack
|
||||||
import eu.kanade.tachiyomi.widget.preference.ListMatPreference
|
import eu.kanade.tachiyomi.widget.preference.ListMatPreference
|
||||||
import kotlinx.android.synthetic.main.extension_detail_controller.*
|
import kotlinx.android.synthetic.main.extension_detail_controller.*
|
||||||
|
import kotlinx.coroutines.MainScope
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
class ExtensionDetailsController(bundle: Bundle? = null) :
|
class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||||
@ -44,6 +63,13 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||||||
|
|
||||||
private var preferenceScreen: PreferenceScreen? = null
|
private var preferenceScreen: PreferenceScreen? = null
|
||||||
|
|
||||||
|
private val preferences: PreferencesHelper = Injekt.get()
|
||||||
|
|
||||||
|
private val viewScope = MainScope()
|
||||||
|
init {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
}
|
||||||
|
|
||||||
constructor(pkgName: String) : this(
|
constructor(pkgName: String) : this(
|
||||||
Bundle().apply {
|
Bundle().apply {
|
||||||
putString(PKGNAME_KEY, pkgName)
|
putString(PKGNAME_KEY, pkgName)
|
||||||
@ -67,24 +93,11 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||||||
@SuppressLint("PrivateResource")
|
@SuppressLint("PrivateResource")
|
||||||
override fun onViewCreated(view: View) {
|
override fun onViewCreated(view: View) {
|
||||||
super.onViewCreated(view)
|
super.onViewCreated(view)
|
||||||
view.applyWindowInsetsForController()
|
scrollViewWith(extension_prefs_recycler, padBottom = true)
|
||||||
|
|
||||||
val extension = presenter.extension ?: return
|
val extension = presenter.extension ?: return
|
||||||
val context = view.context
|
val context = view.context
|
||||||
|
|
||||||
extension_title.text = extension.name
|
|
||||||
extension_version.text = context.getString(R.string.version_, extension.versionName)
|
|
||||||
extension_lang.text = context.getString(R.string.language_, LocaleHelper.getDisplayName(extension.lang, context))
|
|
||||||
extension_pkg.text = extension.pkgName
|
|
||||||
extension.getApplicationIcon(context)?.let { extension_icon.setImageDrawable(it) }
|
|
||||||
extension_uninstall_button.clicks().subscribeUntilDestroy {
|
|
||||||
presenter.uninstallExtension()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extension.isObsolete) {
|
|
||||||
extension_obsolete.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
val themedContext by lazy { getPreferenceThemeContext() }
|
val themedContext by lazy { getPreferenceThemeContext() }
|
||||||
val manager = PreferenceManager(themedContext)
|
val manager = PreferenceManager(themedContext)
|
||||||
manager.preferenceDataStore = EmptyPreferenceDataStore()
|
manager.preferenceDataStore = EmptyPreferenceDataStore()
|
||||||
@ -93,10 +106,12 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||||||
preferenceScreen = screen
|
preferenceScreen = screen
|
||||||
|
|
||||||
val multiSource = extension.sources.size > 1
|
val multiSource = extension.sources.size > 1
|
||||||
|
val isMultiLangSingleSource = multiSource && extension.sources.map { it.name }.distinct().size == 1
|
||||||
|
val langauges = preferences.enabledLanguages().get()
|
||||||
|
|
||||||
for (source in extension.sources) {
|
for (source in extension.sources.sortedByDescending { it.isLangEnabled(langauges) }) {
|
||||||
if (source is ConfigurableSource) {
|
if (source is ConfigurableSource) {
|
||||||
addPreferencesForSource(screen, source, multiSource)
|
addPreferencesForSource(screen, source, multiSource, isMultiLangSingleSource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,16 +119,17 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||||||
|
|
||||||
extension_prefs_recycler.layoutManager =
|
extension_prefs_recycler.layoutManager =
|
||||||
androidx.recyclerview.widget.LinearLayoutManager(context)
|
androidx.recyclerview.widget.LinearLayoutManager(context)
|
||||||
extension_prefs_recycler.adapter = PreferenceGroupAdapter(screen)
|
val concatAdapterConfig = ConcatAdapter.Config.Builder()
|
||||||
extension_prefs_recycler.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(context, VERTICAL))
|
.setStableIdMode(ConcatAdapter.Config.StableIdMode.ISOLATED_STABLE_IDS)
|
||||||
extension_prefs_recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
|
.build()
|
||||||
|
screen.setShouldUseGeneratedIds(true)
|
||||||
if (screen.preferenceCount == 0) {
|
val extHeaderAdapter = ExtensionDetailsHeaderAdapter(presenter)
|
||||||
extension_prefs_empty_view.show(
|
extHeaderAdapter.setHasStableIds(true)
|
||||||
R.drawable.ic_no_settings_24dp,
|
extension_prefs_recycler.adapter = ConcatAdapter(concatAdapterConfig,
|
||||||
R.string.empty_preferences_for_extension
|
extHeaderAdapter,
|
||||||
)
|
PreferenceGroupAdapter(screen)
|
||||||
}
|
)
|
||||||
|
extension_prefs_recycler.addItemDecoration(ExtensionSettingsDividerItemDecoration(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
override fun onDestroyView(view: View) {
|
||||||
@ -135,41 +151,113 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||||||
lastOpenPreferencePosition = savedInstanceState.get(LASTOPENPREFERENCE_KEY) as? Int
|
lastOpenPreferencePosition = savedInstanceState.get(LASTOPENPREFERENCE_KEY) as? Int
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addPreferencesForSource(screen: PreferenceScreen, source: Source, multiSource: Boolean) {
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
inflater.inflate(R.menu.extension_details, menu)
|
||||||
|
|
||||||
|
menu.findItem(R.id.action_history).isVisible = presenter.extension?.isUnofficial == false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.action_history -> openCommitHistory()
|
||||||
|
R.id.action_app_info -> openInSettings()
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openCommitHistory() {
|
||||||
|
val pkgName = presenter.extension!!.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
|
||||||
|
val pkgFactory = presenter.extension!!.pkgFactory
|
||||||
|
val url = when {
|
||||||
|
!pkgFactory.isNullOrEmpty() -> "$URL_EXTENSION_COMMITS/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/$pkgFactory"
|
||||||
|
else -> "$URL_EXTENSION_COMMITS/src/${pkgName.replace(".", "/")}"
|
||||||
|
}
|
||||||
|
openInBrowser(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openInSettings() {
|
||||||
|
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||||
|
data = Uri.fromParts("package", presenter.pkgName, null)
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addPreferencesForSource(screen: PreferenceScreen, source: Source, isMultiSource: Boolean, isMultiLangSingleSource: Boolean) {
|
||||||
val context = screen.context
|
val context = screen.context
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
val dataStore = SharedPreferencesDataStore(/*if (source is HttpSource) {
|
val dataStore = SharedPreferencesDataStore(
|
||||||
source.preferences
|
|
||||||
} else {*/
|
|
||||||
context.getSharedPreferences("source_${source.id}", Context.MODE_PRIVATE)
|
context.getSharedPreferences("source_${source.id}", Context.MODE_PRIVATE)
|
||||||
/*}*/
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (source is ConfigurableSource) {
|
if (source is ConfigurableSource) {
|
||||||
if (multiSource) {
|
val prefs = mutableListOf<Preference>()
|
||||||
screen.preferenceCategory {
|
val block: (@DSL SwitchPreferenceCompat).() -> Unit = {
|
||||||
title = source.toString()
|
key = source.getPreferenceKey()
|
||||||
|
title = when {
|
||||||
|
isMultiSource && !isMultiLangSingleSource -> source.toString()
|
||||||
|
else -> LocaleHelper.getSourceDisplayName(source.lang, context)
|
||||||
}
|
}
|
||||||
|
isPersistent = false
|
||||||
|
isChecked = source.isEnabled()
|
||||||
|
|
||||||
|
onChange { newValue ->
|
||||||
|
if (source.isLangEnabled()) {
|
||||||
|
val checked = newValue as Boolean
|
||||||
|
toggleSource(source, checked)
|
||||||
|
prefs.forEach { it.isVisible = checked }
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
coordinator.snack(context.getString(R.string._must_be_enabled_first, title), Snackbar.LENGTH_LONG) {
|
||||||
|
setAction(R.string.enable) {
|
||||||
|
preferences.enabledLanguages() += source.lang
|
||||||
|
isChecked = true
|
||||||
|
toggleSource(source, true)
|
||||||
|
prefs.forEach { it.isVisible = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// React to enable/disable all changes
|
||||||
|
preferences.hiddenSources().asFlow()
|
||||||
|
.onEach {
|
||||||
|
val enabled = source.isEnabled()
|
||||||
|
isChecked = enabled
|
||||||
|
}
|
||||||
|
.launchIn(viewScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
val newScreen = screen.preferenceManager.createPreferenceScreen(context)
|
val newScreen = screen.preferenceManager.createPreferenceScreen(context)
|
||||||
|
screen.switchPreference(block)
|
||||||
source.setupPreferenceScreen(newScreen)
|
source.setupPreferenceScreen(newScreen)
|
||||||
|
|
||||||
// Reparent the preferences
|
// Reparent the preferences
|
||||||
while (newScreen.preferenceCount != 0) {
|
while (newScreen.preferenceCount != 0) {
|
||||||
val pref = newScreen.getPreference(0)
|
val pref = newScreen.getPreference(0)
|
||||||
pref.isIconSpaceReserved = false
|
pref.isIconSpaceReserved = true
|
||||||
pref.preferenceDataStore = dataStore
|
pref.preferenceDataStore = dataStore
|
||||||
pref.fragment = "source_${source.id}"
|
pref.fragment = "source_${source.id}"
|
||||||
pref.order = Int.MAX_VALUE // reset to default order
|
pref.order = Int.MAX_VALUE
|
||||||
|
pref.isVisible = source.isEnabled()
|
||||||
|
prefs.add(pref)
|
||||||
newScreen.removePreference(pref)
|
newScreen.removePreference(pref)
|
||||||
screen.addPreference(pref)
|
screen.addPreference(pref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun toggleSource(source: Source, enable: Boolean) {
|
||||||
|
if (enable) {
|
||||||
|
preferences.hiddenSources() -= source.id.toString()
|
||||||
|
} else {
|
||||||
|
preferences.hiddenSources() += source.id.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getPreferenceThemeContext(): Context {
|
private fun getPreferenceThemeContext(): Context {
|
||||||
val tv = TypedValue()
|
val tv = TypedValue()
|
||||||
activity!!.theme.resolveAttribute(R.attr.preferenceTheme, tv, true)
|
activity!!.theme.resolveAttribute(R.attr.preferenceTheme, tv, true)
|
||||||
@ -216,6 +304,15 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||||||
f.showDialog(router)
|
f.showDialog(router)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Source.isEnabled(): Boolean {
|
||||||
|
return id.toString() !in preferences.hiddenSources().get() && isLangEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun Source.isLangEnabled(langs: Set<String>? = null): Boolean {
|
||||||
|
return (lang in langs ?: preferences.enabledLanguages().get())
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T : Preference> findPreference(key: CharSequence): T? {
|
override fun <T : Preference> findPreference(key: CharSequence): T? {
|
||||||
// We track [lastOpenPreferencePosition] when displaying the dialog
|
// We track [lastOpenPreferencePosition] when displaying the dialog
|
||||||
@ -226,5 +323,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||||||
private companion object {
|
private companion object {
|
||||||
const val PKGNAME_KEY = "pkg_name"
|
const val PKGNAME_KEY = "pkg_name"
|
||||||
const val LASTOPENPREFERENCE_KEY = "last_open_preference"
|
const val LASTOPENPREFERENCE_KEY = "last_open_preference"
|
||||||
|
private const val URL_EXTENSION_COMMITS =
|
||||||
|
"https://github.com/tachiyomiorg/tachiyomi-extensions/commits/master"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.extension.details
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.ui.extension.getApplicationIcon
|
||||||
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
|
import eu.kanade.tachiyomi.util.view.inflate
|
||||||
|
import kotlinx.android.synthetic.main.extension_detail_header.view.*
|
||||||
|
|
||||||
|
class ExtensionDetailsHeaderAdapter(private val presenter: ExtensionDetailsPresenter) :
|
||||||
|
RecyclerView.Adapter<ExtensionDetailsHeaderAdapter.HeaderViewHolder>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HeaderViewHolder {
|
||||||
|
val view = parent.inflate(R.layout.extension_detail_header)
|
||||||
|
return HeaderViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = 1
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: HeaderViewHolder, position: Int) {
|
||||||
|
holder.bind()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
return R.layout.extension_detail_header
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemId(position: Int): Long {
|
||||||
|
return presenter.pkgName.hashCode().toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class HeaderViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
fun bind() {
|
||||||
|
val extension = presenter.extension ?: return
|
||||||
|
val context = view.context
|
||||||
|
|
||||||
|
extension.getApplicationIcon(context)?.let { view.extension_icon.setImageDrawable(it) }
|
||||||
|
view.extension_title.text = extension.name
|
||||||
|
view.extension_version.text = context.getString(R.string.version_, extension.versionName)
|
||||||
|
view.extension_lang.text = context.getString(R.string.language_, LocaleHelper.getSourceDisplayName(extension.lang, context))
|
||||||
|
view.extension_nsfw.isVisible = extension.isNsfw
|
||||||
|
view.extension_pkg.text = extension.pkgName
|
||||||
|
|
||||||
|
view.extension_uninstall_button.setOnClickListener {
|
||||||
|
presenter.uninstallExtension()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension.isObsolete) {
|
||||||
|
view.extension_warning_banner.isVisible = true
|
||||||
|
view.extension_warning_banner.setText(R.string.obsolete_extension_message)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension.isUnofficial) {
|
||||||
|
view.extension_warning_banner.isVisible = true
|
||||||
|
view.extension_warning_banner.setText(R.string.unofficial_extension_message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.ui.extension
|
package eu.kanade.tachiyomi.ui.extension.details
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
import eu.kanade.tachiyomi.extension.ExtensionManager
|
@ -0,0 +1,54 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.extension.details
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.view.View
|
||||||
|
import androidx.preference.PreferenceGroupAdapter
|
||||||
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
|
import androidx.recyclerview.widget.ConcatAdapter
|
||||||
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
|
import eu.kanade.tachiyomi.util.system.isLTR
|
||||||
|
|
||||||
|
class ExtensionSettingsDividerItemDecoration(context: Context) : androidx.recyclerview.widget.RecyclerView.ItemDecoration() {
|
||||||
|
|
||||||
|
private val divider: Drawable
|
||||||
|
|
||||||
|
init {
|
||||||
|
val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.listDivider))
|
||||||
|
divider = a.getDrawable(0)!!
|
||||||
|
a.recycle()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
override fun onDraw(c: Canvas, parent: androidx.recyclerview.widget.RecyclerView, state: androidx.recyclerview.widget.RecyclerView.State) {
|
||||||
|
val childCount = parent.childCount
|
||||||
|
for (i in 0 until childCount - 1) {
|
||||||
|
val child = parent.getChildAt(i)
|
||||||
|
val index = parent.getChildAdapterPosition(child)
|
||||||
|
val adapter = (parent.adapter as? ConcatAdapter)?.adapters?.lastOrNull() as? PreferenceGroupAdapter
|
||||||
|
if (index > 0 && adapter?.getItem(index) is SwitchPreferenceCompat) {
|
||||||
|
val params = child.layoutParams as androidx.recyclerview.widget.RecyclerView.LayoutParams
|
||||||
|
val top = child.bottom + params.bottomMargin
|
||||||
|
val bottom = top + divider.intrinsicHeight
|
||||||
|
val left = parent.paddingStart + if (parent.context.resources.isLTR) 12.dpToPx else 0
|
||||||
|
val right =
|
||||||
|
parent.width - parent.paddingEnd - if (!parent.context.resources.isLTR) 12.dpToPx else 0
|
||||||
|
|
||||||
|
divider.setBounds(left, top, right, bottom)
|
||||||
|
divider.draw(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemOffsets(
|
||||||
|
outRect: Rect,
|
||||||
|
view: View,
|
||||||
|
parent: androidx.recyclerview.widget.RecyclerView,
|
||||||
|
state: androidx.recyclerview.widget.RecyclerView.State
|
||||||
|
) {
|
||||||
|
outRect.set(0, 0, 0, divider.intrinsicHeight)
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ class MigrationSourceHolder(view: View, val adapter: MigrationSourceAdapter) :
|
|||||||
|
|
||||||
fun bind(source: HttpSource, sourceEnabled: Boolean) {
|
fun bind(source: HttpSource, sourceEnabled: Boolean) {
|
||||||
val preferences by injectLazy<PreferencesHelper>()
|
val preferences by injectLazy<PreferencesHelper>()
|
||||||
val isMultiLanguage = preferences.enabledLanguages().getOrDefault().size > 1
|
val isMultiLanguage = preferences.enabledLanguages().get().size > 1
|
||||||
// Set capitalized title.
|
// Set capitalized title.
|
||||||
val sourceName = if (isMultiLanguage) source.toString() else source.name.capitalize()
|
val sourceName = if (isMultiLanguage) source.toString() else source.name.capitalize()
|
||||||
title.text = sourceName
|
title.text = sourceName
|
||||||
|
@ -142,7 +142,7 @@ class PreMigrationController(bundle: Bundle? = null) :
|
|||||||
* @return list containing enabled sources.
|
* @return list containing enabled sources.
|
||||||
*/
|
*/
|
||||||
private fun getEnabledSources(): List<HttpSource> {
|
private fun getEnabledSources(): List<HttpSource> {
|
||||||
val languages = prefs.enabledLanguages().getOrDefault()
|
val languages = prefs.enabledLanguages().get()
|
||||||
val sourcesSaved = prefs.migrationSources().get().split("/")
|
val sourcesSaved = prefs.migrationSources().get().split("/")
|
||||||
var sources = sourceManager.getCatalogueSources()
|
var sources = sourceManager.getCatalogueSources()
|
||||||
.filterIsInstance<HttpSource>()
|
.filterIsInstance<HttpSource>()
|
||||||
@ -162,7 +162,7 @@ class PreMigrationController(bundle: Bundle? = null) :
|
|||||||
|
|
||||||
fun isEnabled(id: String): Boolean {
|
fun isEnabled(id: String): Boolean {
|
||||||
val sourcesSaved = prefs.migrationSources().get()
|
val sourcesSaved = prefs.migrationSources().get()
|
||||||
val hiddenCatalogues = prefs.hiddenSources().getOrDefault()
|
val hiddenCatalogues = prefs.hiddenSources().get()
|
||||||
return if (sourcesSaved.isEmpty()) id !in hiddenCatalogues
|
return if (sourcesSaved.isEmpty()) id !in hiddenCatalogues
|
||||||
else sourcesSaved.split("/").contains(id)
|
else sourcesSaved.split("/").contains(id)
|
||||||
}
|
}
|
||||||
@ -181,7 +181,7 @@ class PreMigrationController(bundle: Bundle? = null) :
|
|||||||
}
|
}
|
||||||
R.id.action_match_enabled, R.id.action_match_pinned -> {
|
R.id.action_match_enabled, R.id.action_match_pinned -> {
|
||||||
val enabledSources = if (item.itemId == R.id.action_match_enabled) {
|
val enabledSources = if (item.itemId == R.id.action_match_enabled) {
|
||||||
prefs.hiddenSources().getOrDefault().mapNotNull { it.toLongOrNull() }
|
prefs.hiddenSources().get().mapNotNull { it.toLongOrNull() }
|
||||||
} else {
|
} else {
|
||||||
prefs.pinnedCatalogues().get()?.mapNotNull { it.toLongOrNull() } ?: emptyList()
|
prefs.pinnedCatalogues().get()?.mapNotNull { it.toLongOrNull() } ?: emptyList()
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ class AboutController : SettingsController() {
|
|||||||
}
|
}
|
||||||
preferenceCategory {
|
preferenceCategory {
|
||||||
preference {
|
preference {
|
||||||
titleRes = R.string.whats_new
|
titleRes = R.string.whats_new_this_release
|
||||||
onClick {
|
onClick {
|
||||||
val intent = Intent(
|
val intent = Intent(
|
||||||
Intent.ACTION_VIEW,
|
Intent.ACTION_VIEW,
|
||||||
|
@ -89,6 +89,10 @@ inline fun PreferenceScreen.preferenceCategory(block: (@DSL PreferenceCategory).
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun PreferenceScreen.switchPreference(block: (@DSL SwitchPreferenceCompat).() -> Unit): SwitchPreferenceCompat {
|
||||||
|
return initThenAdd(SwitchPreferenceCompat(context), block)
|
||||||
|
}
|
||||||
|
|
||||||
inline fun PreferenceGroup.infoPreference(@StringRes infoRes: Int): Preference {
|
inline fun PreferenceGroup.infoPreference(@StringRes infoRes: Int): Preference {
|
||||||
return initThenAdd(
|
return initThenAdd(
|
||||||
Preference(context),
|
Preference(context),
|
||||||
|
@ -88,8 +88,8 @@ class SettingsBrowseController : SettingsController() {
|
|||||||
summaryRes = R.string.only_enable_enabled_for_migration
|
summaryRes = R.string.only_enable_enabled_for_migration
|
||||||
onClick {
|
onClick {
|
||||||
val ogSources = preferences.migrationSources().get()
|
val ogSources = preferences.migrationSources().get()
|
||||||
val languages = preferences.enabledLanguages().getOrDefault()
|
val languages = preferences.enabledLanguages().get()
|
||||||
val hiddenCatalogues = preferences.hiddenSources().getOrDefault()
|
val hiddenCatalogues = preferences.hiddenSources().get()
|
||||||
val enabledSources =
|
val enabledSources =
|
||||||
sourceManager.getCatalogueSources().filter { it.lang in languages }
|
sourceManager.getCatalogueSources().filter { it.lang in languages }
|
||||||
.filterNot { it.id.toString() in hiddenCatalogues }
|
.filterNot { it.id.toString() in hiddenCatalogues }
|
||||||
|
@ -11,6 +11,8 @@ import androidx.preference.PreferenceScreen
|
|||||||
import com.jakewharton.rxbinding.support.v7.widget.queryTextChanges
|
import com.jakewharton.rxbinding.support.v7.widget.queryTextChanges
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
|
import eu.kanade.tachiyomi.data.preference.minusAssign
|
||||||
|
import eu.kanade.tachiyomi.data.preference.plusAssign
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.icon
|
import eu.kanade.tachiyomi.source.icon
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
@ -39,7 +41,7 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
sorting = SourcesSort.from(preferences.sourceSorting().getOrDefault()) ?: SourcesSort.Alpha
|
sorting = SourcesSort.from(preferences.sourceSorting().getOrDefault()) ?: SourcesSort.Alpha
|
||||||
activity?.invalidateOptionsMenu()
|
activity?.invalidateOptionsMenu()
|
||||||
// Get the list of active language codes.
|
// Get the list of active language codes.
|
||||||
val activeLangsCodes = preferences.enabledLanguages().getOrDefault()
|
val activeLangsCodes = preferences.enabledLanguages().get()
|
||||||
|
|
||||||
// Get a map of sources grouped by language.
|
// Get a map of sources grouped by language.
|
||||||
sourcesByLang = onlineSources.groupByTo(TreeMap(), { it.lang })
|
sourcesByLang = onlineSources.groupByTo(TreeMap(), { it.lang })
|
||||||
@ -55,7 +57,7 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
lang,
|
lang,
|
||||||
SwitchPreferenceCategory(context).apply {
|
SwitchPreferenceCategory(context).apply {
|
||||||
preferenceScreen.addPreference(this)
|
preferenceScreen.addPreference(this)
|
||||||
title = LocaleHelper.getDisplayName(lang, context)
|
title = LocaleHelper.getSourceDisplayName(lang, context)
|
||||||
isPersistent = false
|
isPersistent = false
|
||||||
if (lang in activeLangsCodes) {
|
if (lang in activeLangsCodes) {
|
||||||
setChecked(true)
|
setChecked(true)
|
||||||
@ -64,12 +66,12 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
|
|
||||||
onChange { newValue ->
|
onChange { newValue ->
|
||||||
val checked = newValue as Boolean
|
val checked = newValue as Boolean
|
||||||
val current = preferences.enabledLanguages().getOrDefault()
|
val current = preferences.enabledLanguages().get()
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
preferences.enabledLanguages().set(current - lang)
|
preferences.enabledLanguages() -= lang
|
||||||
removeAll()
|
removeAll()
|
||||||
} else {
|
} else {
|
||||||
preferences.enabledLanguages().set(current + lang)
|
preferences.enabledLanguages() += lang
|
||||||
addLanguageSources(this, sortedSources(sourcesByLang[lang]))
|
addLanguageSources(this, sortedSources(sourcesByLang[lang]))
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@ -90,7 +92,7 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
* @param group the language category.
|
* @param group the language category.
|
||||||
*/
|
*/
|
||||||
private fun addLanguageSources(group: PreferenceGroup, sources: List<HttpSource>) {
|
private fun addLanguageSources(group: PreferenceGroup, sources: List<HttpSource>) {
|
||||||
val hiddenCatalogues = preferences.hiddenSources().getOrDefault()
|
val hiddenCatalogues = preferences.hiddenSources().get()
|
||||||
|
|
||||||
val selectAllPreference = CheckBoxPreference(group.context).apply {
|
val selectAllPreference = CheckBoxPreference(group.context).apply {
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
|
|
||||||
onChange { newValue ->
|
onChange { newValue ->
|
||||||
val checked = newValue as Boolean
|
val checked = newValue as Boolean
|
||||||
val current = preferences.hiddenSources().get() ?: mutableSetOf()
|
val current = preferences.hiddenSources().get().toMutableSet()
|
||||||
if (checked)
|
if (checked)
|
||||||
current.removeAll(sources.map { it.id.toString() })
|
current.removeAll(sources.map { it.id.toString() })
|
||||||
else
|
else
|
||||||
@ -131,7 +133,7 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
|
|
||||||
onChange { newValue ->
|
onChange { newValue ->
|
||||||
val checked = newValue as Boolean
|
val checked = newValue as Boolean
|
||||||
val current = preferences.hiddenSources().getOrDefault()
|
val current = preferences.hiddenSources().get()
|
||||||
|
|
||||||
preferences.hiddenSources().set(
|
preferences.hiddenSources().set(
|
||||||
if (checked) current - id
|
if (checked) current - id
|
||||||
@ -215,7 +217,7 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun drawSources() {
|
private fun drawSources() {
|
||||||
val activeLangsCodes = preferences.enabledLanguages().getOrDefault()
|
val activeLangsCodes = preferences.enabledLanguages().get()
|
||||||
langPrefs.forEach { group ->
|
langPrefs.forEach { group ->
|
||||||
if (group.first in activeLangsCodes) {
|
if (group.first in activeLangsCodes) {
|
||||||
group.second.removeAll()
|
group.second.removeAll()
|
||||||
@ -227,7 +229,7 @@ class SettingsSourcesController : SettingsController() {
|
|||||||
private fun sortedSources(sources: List<HttpSource>?): List<HttpSource> {
|
private fun sortedSources(sources: List<HttpSource>?): List<HttpSource> {
|
||||||
val sourceAlpha = sources.orEmpty().sortedBy { it.name }
|
val sourceAlpha = sources.orEmpty().sortedBy { it.name }
|
||||||
return if (sorting == SourcesSort.Enabled) {
|
return if (sorting == SourcesSort.Enabled) {
|
||||||
val hiddenCatalogues = preferences.hiddenSources().getOrDefault()
|
val hiddenCatalogues = preferences.hiddenSources().get()
|
||||||
sourceAlpha.filter { it.id.toString() !in hiddenCatalogues } +
|
sourceAlpha.filter { it.id.toString() !in hiddenCatalogues } +
|
||||||
sourceAlpha.filterNot { it.id.toString() !in hiddenCatalogues }
|
sourceAlpha.filterNot { it.id.toString() !in hiddenCatalogues }
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,6 +12,6 @@ class LangHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.Vie
|
|||||||
BaseFlexibleViewHolder(view, adapter) {
|
BaseFlexibleViewHolder(view, adapter) {
|
||||||
|
|
||||||
fun bind(item: LangItem) {
|
fun bind(item: LangItem) {
|
||||||
title.text = LocaleHelper.getDisplayName(item.code, itemView.context)
|
title.text = LocaleHelper.getDisplayName(item.code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,9 +315,10 @@ class SourceController :
|
|||||||
|
|
||||||
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||||
super.onChangeStarted(handler, type)
|
super.onChangeStarted(handler, type)
|
||||||
if (!type.isPush && handler is SettingsSourcesFadeChangeHandler) {
|
if (!type.isPush) {
|
||||||
ext_bottom_sheet.updateExtTitle()
|
ext_bottom_sheet.updateExtTitle()
|
||||||
ext_bottom_sheet.presenter.refreshExtensions()
|
ext_bottom_sheet.presenter.refreshExtensions()
|
||||||
|
presenter.updateSources()
|
||||||
}
|
}
|
||||||
if (!type.isEnter) {
|
if (!type.isEnter) {
|
||||||
ext_bottom_sheet.canExpand = false
|
ext_bottom_sheet.canExpand = false
|
||||||
@ -358,7 +359,7 @@ class SourceController :
|
|||||||
|
|
||||||
fun hideCatalogue(position: Int) {
|
fun hideCatalogue(position: Int) {
|
||||||
val source = (adapter?.getItem(position) as? SourceItem)?.source ?: return
|
val source = (adapter?.getItem(position) as? SourceItem)?.source ?: return
|
||||||
val current = preferences.hiddenSources().getOrDefault()
|
val current = preferences.hiddenSources().get()
|
||||||
preferences.hiddenSources().set(current + source.id.toString())
|
preferences.hiddenSources().set(current + source.id.toString())
|
||||||
|
|
||||||
presenter.updateSources()
|
presenter.updateSources()
|
||||||
@ -366,7 +367,7 @@ class SourceController :
|
|||||||
snackbar = view?.snack(R.string.source_hidden, Snackbar.LENGTH_INDEFINITE) {
|
snackbar = view?.snack(R.string.source_hidden, Snackbar.LENGTH_INDEFINITE) {
|
||||||
anchorView = ext_bottom_sheet
|
anchorView = ext_bottom_sheet
|
||||||
setAction(R.string.undo) {
|
setAction(R.string.undo) {
|
||||||
val newCurrent = preferences.hiddenSources().getOrDefault()
|
val newCurrent = preferences.hiddenSources().get()
|
||||||
preferences.hiddenSources().set(newCurrent - source.id.toString())
|
preferences.hiddenSources().set(newCurrent - source.id.toString())
|
||||||
presenter.updateSources()
|
presenter.updateSources()
|
||||||
}
|
}
|
||||||
|
@ -111,8 +111,8 @@ class SourcePresenter(
|
|||||||
* @return list containing enabled sources.
|
* @return list containing enabled sources.
|
||||||
*/
|
*/
|
||||||
private fun getEnabledSources(): List<CatalogueSource> {
|
private fun getEnabledSources(): List<CatalogueSource> {
|
||||||
val languages = preferences.enabledLanguages().getOrDefault()
|
val languages = preferences.enabledLanguages().get()
|
||||||
val hiddenCatalogues = preferences.hiddenSources().getOrDefault()
|
val hiddenCatalogues = preferences.hiddenSources().get()
|
||||||
|
|
||||||
return sourceManager.getCatalogueSources()
|
return sourceManager.getCatalogueSources()
|
||||||
.filter { it.lang in languages }
|
.filter { it.lang in languages }
|
||||||
|
@ -101,8 +101,8 @@ open class GlobalSearchPresenter(
|
|||||||
* @return list containing enabled sources.
|
* @return list containing enabled sources.
|
||||||
*/
|
*/
|
||||||
protected open fun getEnabledSources(): List<CatalogueSource> {
|
protected open fun getEnabledSources(): List<CatalogueSource> {
|
||||||
val languages = preferencesHelper.enabledLanguages().getOrDefault()
|
val languages = preferencesHelper.enabledLanguages().get()
|
||||||
val hiddenCatalogues = preferencesHelper.hiddenSources().getOrDefault()
|
val hiddenCatalogues = preferencesHelper.hiddenSources().get()
|
||||||
val pinnedCatalogues = preferencesHelper.pinnedCatalogues().getOrDefault()
|
val pinnedCatalogues = preferencesHelper.pinnedCatalogues().getOrDefault()
|
||||||
|
|
||||||
val list = sourceManager.getCatalogueSources()
|
val list = sourceManager.getCatalogueSources()
|
||||||
|
@ -53,13 +53,25 @@ object LocaleHelper {
|
|||||||
/**
|
/**
|
||||||
* Returns Display name of a string language code
|
* Returns Display name of a string language code
|
||||||
*/
|
*/
|
||||||
fun getDisplayName(lang: String?, context: Context): String {
|
fun getSourceDisplayName(lang: String?, context: Context): String {
|
||||||
|
return when (lang) {
|
||||||
|
"" -> context.getString(R.string.other)
|
||||||
|
SourcePresenter.LAST_USED_KEY -> context.getString(R.string.last_used)
|
||||||
|
SourcePresenter.PINNED_KEY -> context.getString(R.string.pinned)
|
||||||
|
"all" -> context.getString(R.string.all)
|
||||||
|
else -> getDisplayName(lang)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Display name of a string language code
|
||||||
|
*/
|
||||||
|
fun getDisplayName(lang: String?): String {
|
||||||
return when (lang) {
|
return when (lang) {
|
||||||
null -> ""
|
null -> ""
|
||||||
"" -> context.getString(R.string.other)
|
"" -> {
|
||||||
SourcePresenter.PINNED_KEY -> context.getString(R.string.pinned)
|
systemLocale!!.getDisplayName(systemLocale).capitalize()
|
||||||
SourcePresenter.LAST_USED_KEY -> context.getString(R.string.last_used)
|
}
|
||||||
"all" -> context.getString(R.string.all)
|
|
||||||
else -> {
|
else -> {
|
||||||
val locale = getLocale(lang)
|
val locale = getLocale(lang)
|
||||||
locale.getDisplayName(locale).capitalize()
|
locale.getDisplayName(locale).capitalize()
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.util.view
|
|||||||
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -11,6 +12,7 @@ import android.view.inputmethod.InputMethodManager
|
|||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.math.MathUtils
|
import androidx.core.math.MathUtils
|
||||||
|
import androidx.core.net.toUri
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
@ -24,6 +26,7 @@ import eu.kanade.tachiyomi.ui.main.BottomSheetController
|
|||||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.android.synthetic.main.main_activity.*
|
import kotlinx.android.synthetic.main.main_activity.*
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
@ -120,6 +123,11 @@ fun Controller.scrollViewWith(
|
|||||||
val randomTag = Random.nextLong()
|
val randomTag = Random.nextLong()
|
||||||
var lastY = 0f
|
var lastY = 0f
|
||||||
var fakeToolbarView: View? = null
|
var fakeToolbarView: View? = null
|
||||||
|
if (!customPadding) {
|
||||||
|
recycler.updatePaddingRelative(
|
||||||
|
top = activity!!.toolbar.y.toInt() + appBarHeight
|
||||||
|
)
|
||||||
|
}
|
||||||
recycler.doOnApplyWindowInsets { view, insets, _ ->
|
recycler.doOnApplyWindowInsets { view, insets, _ ->
|
||||||
val headerHeight = insets.systemWindowInsetTop + appBarHeight
|
val headerHeight = insets.systemWindowInsetTop + appBarHeight
|
||||||
if (!customPadding) view.updatePaddingRelative(
|
if (!customPadding) view.updatePaddingRelative(
|
||||||
@ -295,3 +303,13 @@ fun Controller.withFadeTransaction(): RouterTransaction {
|
|||||||
.pushChangeHandler(FadeChangeHandler())
|
.pushChangeHandler(FadeChangeHandler())
|
||||||
.popChangeHandler(FadeChangeHandler())
|
.popChangeHandler(FadeChangeHandler())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Controller.openInBrowser(url: String) {
|
||||||
|
try {
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
|
||||||
|
startActivity(intent)
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
activity?.toast(e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,122 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
android:id="@+id/coordinator"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:fitsSystemWindows="true"
|
android:layout_height="wrap_content" >
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/extension_icon"
|
|
||||||
android:layout_width="56dp"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/extension_title"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/extension_pkg"
|
|
||||||
android:src="@mipmap/ic_launcher"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/extension_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
style="@style/TextAppearance.Regular.SubHeading"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/extension_icon"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="Tachiyomi: Extension"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/extension_version"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/extension_title"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/extension_title"
|
|
||||||
tools:text="Version: 1.0.0" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/extension_lang"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/extension_version"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/extension_title"
|
|
||||||
tools:text="Language: English" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/extension_pkg"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="middle"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/extension_lang"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/extension_title"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
tools:text="eu.kanade.tachiyomi.extension.en.myext"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/extension_obsolete"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:text="@string/obsolete_extension_message"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/extension_pkg" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/extension_uninstall_button"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:text="@string/uninstall"
|
|
||||||
style="@style/Theme.Widget.Button.Colored"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/guideline"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/extension_obsolete" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/extension_prefs_recycler"
|
android:id="@+id/extension_prefs_recycler"
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:layout_width="match_parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:layout_height="wrap_content" />
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
app:layout_constraintTop_toBottomOf="@id/extension_uninstall_button"/>
|
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.EmptyView
|
|
||||||
android:id="@+id/extension_prefs_empty_view"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/extension_uninstall_button"/>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
|
||||||
android:id="@+id/guideline"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintGuide_percent="0.5" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
114
app/src/main/res/layout/extension_detail_header.xml
Normal file
114
app/src/main/res/layout/extension_detail_header.xml
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extension_warning_banner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorError"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:textColor="?attr/colorOnError"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/colorBackground"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/extension_icon"
|
||||||
|
android:layout_width="56dp"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:src="@mipmap/ic_launcher"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/extension_pkg"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extension_title"
|
||||||
|
style="@style/TextAppearance.Regular.SubHeading"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:elevation="3dp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/extension_icon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Tachiyomi: Extension" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extension_version"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:elevation="3dp"
|
||||||
|
android:gravity="center"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/extension_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/extension_title"
|
||||||
|
tools:text="Version: 1.0.0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extension_lang"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:elevation="3dp"
|
||||||
|
android:gravity="center"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/extension_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/extension_version"
|
||||||
|
tools:text="Language: English" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extension_nsfw"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:elevation="3dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/may_contain_nsfw"
|
||||||
|
android:textColor="?attr/colorError"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/extension_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/extension_lang"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extension_pkg"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="3dp"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
android:singleLine="true"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/extension_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/extension_nsfw"
|
||||||
|
tools:text="eu.kanade.tachiyomi.extension.en.myext" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/extension_uninstall_button"
|
||||||
|
style="@style/Theme.Widget.Button.Colored"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:paddingStart="32dp"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:paddingEnd="32dp"
|
||||||
|
android:text="@string/uninstall"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/extension_pkg" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
15
app/src/main/res/menu/extension_details.xml
Normal file
15
app/src/main/res/menu/extension_details.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_history"
|
||||||
|
android:icon="@drawable/ic_history_24dp"
|
||||||
|
android:title="@string/whats_new"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_app_info"
|
||||||
|
android:title="@string/app_info"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
</menu>
|
@ -260,12 +260,15 @@
|
|||||||
<string name="untrusted_extension">Untrusted extension</string>
|
<string name="untrusted_extension">Untrusted extension</string>
|
||||||
<string name="untrusted_extension_message">This extension was signed with an untrusted certificate and wasn\'t activated.\n\nA malicious extension could read any login credentials stored in Tachiyomi or execute arbitrary code.\n\nBy trusting this certificate you accept these risks.</string>
|
<string name="untrusted_extension_message">This extension was signed with an untrusted certificate and wasn\'t activated.\n\nA malicious extension could read any login credentials stored in Tachiyomi or execute arbitrary code.\n\nBy trusting this certificate you accept these risks.</string>
|
||||||
<string name="obsolete_extension_message">This extension is no longer available.</string>
|
<string name="obsolete_extension_message">This extension is no longer available.</string>
|
||||||
|
<string name="unofficial_extension_message">This extension is not from the official Tachiyomi extensions list.</string>
|
||||||
<string name="version_">Version: %1$s</string>
|
<string name="version_">Version: %1$s</string>
|
||||||
<string name="language_">Language: %1$s</string>
|
<string name="language_">Language: %1$s</string>
|
||||||
<string name="empty_preferences_for_extension">No preferences to edit for this extension</string>
|
<string name="empty_preferences_for_extension">No preferences to edit for this extension</string>
|
||||||
<string name="nsfw_short">18+</string>
|
<string name="nsfw_short">18+</string>
|
||||||
<string name="unofficial">Unofficial</string>
|
<string name="unofficial">Unofficial</string>
|
||||||
<string name="may_contain_nsfw">May contain NSFW (18+) content</string>
|
<string name="may_contain_nsfw">May contain NSFW (18+) content</string>
|
||||||
|
<string name="app_info">App info</string>
|
||||||
|
<string name="_must_be_enabled_first">%1$s must be enabled first</string>
|
||||||
<plurals name="extension_updates_available">
|
<plurals name="extension_updates_available">
|
||||||
<item quantity="one">Extension update available</item>
|
<item quantity="one">Extension update available</item>
|
||||||
<item quantity="other">%d extension updates available</item>
|
<item quantity="other">%d extension updates available</item>
|
||||||
@ -636,7 +639,8 @@
|
|||||||
<string name="build_time">Build time</string>
|
<string name="build_time">Build time</string>
|
||||||
<string name="send_crash_report">Send crash reports</string>
|
<string name="send_crash_report">Send crash reports</string>
|
||||||
<string name="helps_fix_bugs">Helps fix any bugs. No sensitive data will be sent</string>
|
<string name="helps_fix_bugs">Helps fix any bugs. No sensitive data will be sent</string>
|
||||||
<string name="whats_new">What\'s new in this release</string>
|
<string name="whats_new">What\'s new</string>
|
||||||
|
<string name="whats_new_this_release">What\'s new in this release</string>
|
||||||
<string name="website">Website</string>
|
<string name="website">Website</string>
|
||||||
<string name="open_source_licenses">Open source licenses</string>
|
<string name="open_source_licenses">Open source licenses</string>
|
||||||
|
|
||||||
@ -756,6 +760,7 @@
|
|||||||
<string name="download_unread">Download unread</string>
|
<string name="download_unread">Download unread</string>
|
||||||
<string name="drag_handle">Drag handle</string>
|
<string name="drag_handle">Drag handle</string>
|
||||||
<string name="edit">Edit</string>
|
<string name="edit">Edit</string>
|
||||||
|
<string name="enable">Enable</string>
|
||||||
<string name="enabled">Enabled</string>
|
<string name="enabled">Enabled</string>
|
||||||
<string name="fast">Fast</string>
|
<string name="fast">Fast</string>
|
||||||
<string name="filter">Filter</string>
|
<string name="filter">Filter</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user