diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt index 2b27305e49..8a8671e00d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt @@ -56,8 +56,6 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), setHasOptionsMenu(true) } - private var titleText = "Migrate manga" - private var adapter: MigrationProcessAdapter? = null override val coroutineContext: CoroutineContext = Job() + Dispatchers.Default @@ -78,11 +76,12 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), return inflater.inflate(R.layout.migration_list_controller, container, false) } - override fun getTitle(): String { - return titleText + override fun getTitle(): String? { + return resources?.getString(R.string.migration) } override fun onViewCreated(view: View) { + super.onViewCreated(view) setTitle() val config = this.config ?: return diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutController.kt index 4e9ce3f6b5..f47d6762fc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutController.kt @@ -49,26 +49,6 @@ class SettingsAboutController : SettingsController() { summaryRes = R.string.pref_acra_summary defaultValue = true } - switchPreference { - key = Keys.automaticUpdates - titleRes = R.string.pref_enable_automatic_updates - summaryRes = R.string.pref_enable_automatic_updates_summary - defaultValue = false - - if (isUpdaterEnabled) { - onChange { newValue -> - val checked = newValue as Boolean - if (checked) { - UpdaterJob.setupTask() - } else { - UpdaterJob.cancelTask() - } - true - } - } else { - isVisible = false - } - } preference { title = "Discord" val url = "https://discord.gg/tachiyomi" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt index 34f8006799..7395f259a8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt @@ -7,12 +7,14 @@ import android.view.View import androidx.biometric.BiometricManager import androidx.preference.PreferenceScreen import com.afollestad.materialdialogs.MaterialDialog +import eu.kanade.tachiyomi.BuildConfig 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.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault +import eu.kanade.tachiyomi.data.updater.UpdaterJob import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.util.LocaleHelper import eu.kanade.tachiyomi.widget.preference.IntListPreference @@ -24,7 +26,7 @@ import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsGeneralController : SettingsController() { - private val db: DatabaseHelper = Injekt.get() + private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { titleRes = R.string.pref_category_general @@ -67,156 +69,37 @@ class SettingsGeneralController : SettingsController() { true } } - preference { - titleRes = R.string.pref_library_columns - onClick { - LibraryColumnsDialog().showDialog(router) - } - fun getColumnValue(value: Int): String { - return if (value == 0) - context.getString(R.string.default_columns) - else - value.toString() - } - - Observable.combineLatest( - preferences.portraitColumns().asObservable(), - preferences.landscapeColumns().asObservable(), - { portraitCols, landscapeCols -> Pair(portraitCols, landscapeCols) }) - .subscribeUntilDestroy { (portraitCols, landscapeCols) -> - val portrait = getColumnValue(portraitCols) - val landscape = getColumnValue(landscapeCols) - summary = "${context.getString(R.string.portrait)}: $portrait, " + - "${context.getString(R.string.landscape)}: $landscape" - } - } intListPreference { key = Keys.startScreen titleRes = R.string.pref_start_screen entriesRes = arrayOf(R.string.label_library, R.string.label_recent_manga, - R.string.label_recent_updates) + R.string.label_recent_updates) entryValues = arrayOf("1", "2", "3") defaultValue = "1" summary = "%s" } - intListPreference { - 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) - entryValues = arrayOf("0", "1", "2", "3", "6", "12", "24", "48") - defaultValue = "0" - summary = "%s" - - onChange { newValue -> - // Always cancel the previous task, it seems that sometimes they are not updated. - LibraryUpdateJob.cancelTask() - - val interval = (newValue as String).toInt() - if (interval > 0) { - LibraryUpdateJob.setupTask(interval) - } - true - } - } - multiSelectListPreference { - key = Keys.libraryUpdateRestriction - titleRes = R.string.pref_library_update_restriction - entriesRes = arrayOf(R.string.wifi, R.string.charging) - entryValues = arrayOf("wifi", "ac") - summaryRes = R.string.pref_library_update_restriction_summary - - preferences.libraryUpdateInterval().asObservable() - .subscribeUntilDestroy { isVisible = it > 0 } - - onChange { - // Post to event looper to allow the preference to be updated. - Handler().post { LibraryUpdateJob.setupTask() } - true - } - } switchPreference { - key = Keys.updateOnlyNonCompleted - titleRes = R.string.pref_update_only_non_completed + key = eu.kanade.tachiyomi.data.preference.PreferenceKeys.automaticUpdates + titleRes = R.string.pref_enable_automatic_updates + summaryRes = R.string.pref_enable_automatic_updates_summary defaultValue = false - } - val dbCategories = db.getCategories().executeAsBlocking() - - multiSelectListPreference { - key = Keys.libraryUpdateCategories - titleRes = R.string.pref_library_update_categories - entries = dbCategories.map { it.name }.toTypedArray() - entryValues = dbCategories.map { it.id.toString() }.toTypedArray() - - preferences.libraryUpdateCategories().asObservable() - .subscribeUntilDestroy { - val selectedCategories = it - .mapNotNull { id -> dbCategories.find { it.id == id.toInt() } } - .sortedBy { it.order } - - summary = if (selectedCategories.isEmpty()) - context.getString(R.string.all) - else - selectedCategories.joinToString { it.name } + if (isUpdaterEnabled) { + onChange { newValue -> + val checked = newValue as Boolean + if (checked) { + UpdaterJob.setupTask() + } else { + UpdaterJob.cancelTask() } - } - intListPreference{ - key = Keys.libraryUpdatePrioritization - titleRes = R.string.pref_library_update_prioritization - // The following arrays are to be lined up with the list rankingScheme in: - // ../../data/library/LibraryUpdateRanker.kt - entriesRes = arrayOf( - R.string.action_sort_alpha, - R.string.action_sort_last_updated - ) - entryValues = arrayOf( - "0", - "1" - ) - defaultValue = "0" - summaryRes = R.string.pref_library_update_prioritization_summary - } - intListPreference { - key = Keys.defaultCategory - titleRes = R.string.default_category - - val categories = listOf(Category.createDefault()) + dbCategories - - val selectedCategory = categories.find { it.id == preferences.defaultCategory() } - entries = arrayOf(context.getString(R.string.default_category_summary)) + - categories.map { it.name }.toTypedArray() - entryValues = arrayOf("-1") + categories.map { it.id.toString() }.toTypedArray() - defaultValue = "-1" - summary = selectedCategory?.name ?: context.getString(R.string.default_category_summary) - - onChange { newValue -> - summary = categories.find { - it.id == (newValue as String).toInt() - }?.name ?: context.getString(R.string.default_category_summary) - true + true + } + } else { + isVisible = false } } - if (preferences.skipPreMigration().getOrDefault() || preferences.migrationSources() - .getOrDefault().isNotEmpty()) { - switchPreference { - key = Keys.skipPreMigration - titleRes = R.string.pref_skip_pre_migration - summaryRes = R.string.pref_skip_pre_migration_summary - defaultValue = false - } - } - - switchPreference { - key = Keys.removeArticles - titleRes = R.string.pref_remove_articles - summaryRes = R.string.pref_remove_articles_summary - defaultValue = false - } - val biometricManager = BiometricManager.from(context) if (biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) { var preference:IntListPreference? = null @@ -248,51 +131,4 @@ class SettingsGeneralController : SettingsController() { } } } - - class LibraryColumnsDialog : DialogController() { - - private val preferences: PreferencesHelper = Injekt.get() - - private var portrait = preferences.portraitColumns().getOrDefault() - private var landscape = preferences.landscapeColumns().getOrDefault() - - override fun onCreateDialog(savedViewState: Bundle?): Dialog { - val dialog = MaterialDialog.Builder(activity!!) - .title(R.string.pref_library_columns) - .customView(R.layout.pref_library_columns, false) - .positiveText(android.R.string.ok) - .negativeText(android.R.string.cancel) - .onPositive { _, _ -> - preferences.portraitColumns().set(portrait) - preferences.landscapeColumns().set(landscape) - } - .build() - - onViewCreated(dialog.view) - return dialog - } - - fun onViewCreated(view: View) { - with(view.portrait_columns) { - displayedValues = arrayOf(context.getString(R.string.default_columns)) + - IntRange(1, 10).map(Int::toString) - value = portrait - - setOnValueChangedListener { _, _, newValue -> - portrait = newValue - } - } - with(view.landscape_columns) { - displayedValues = arrayOf(context.getString(R.string.default_columns)) + - IntRange(1, 10).map(Int::toString) - value = landscape - - setOnValueChangedListener { _, _, newValue -> - landscape = newValue - } - } - } - - } - } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt new file mode 100644 index 0000000000..0b4b9f1574 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -0,0 +1,221 @@ +package eu.kanade.tachiyomi.ui.setting + +import android.app.Dialog +import android.os.Bundle +import android.os.Handler +import android.view.View +import androidx.biometric.BiometricManager +import androidx.preference.PreferenceScreen +import com.afollestad.materialdialogs.MaterialDialog +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.PreferencesHelper +import eu.kanade.tachiyomi.data.preference.getOrDefault +import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.util.LocaleHelper +import eu.kanade.tachiyomi.widget.preference.IntListPreference +import kotlinx.android.synthetic.main.pref_library_columns.view.* +import rx.Observable +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys + +class SettingsLibraryController : SettingsController() { + + private val db: DatabaseHelper = Injekt.get() + + override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { + titleRes = R.string.pref_category_library + + preference { + titleRes = R.string.pref_library_columns + onClick { + LibraryColumnsDialog().showDialog(router) + } + + fun getColumnValue(value: Int): String { + return if (value == 0) + context.getString(R.string.default_columns) + else + value.toString() + } + + Observable.combineLatest( + preferences.portraitColumns().asObservable(), + preferences.landscapeColumns().asObservable(), + { portraitCols, landscapeCols -> Pair(portraitCols, landscapeCols) }) + .subscribeUntilDestroy { (portraitCols, landscapeCols) -> + val portrait = getColumnValue(portraitCols) + val landscape = getColumnValue(landscapeCols) + summary = "${context.getString(R.string.portrait)}: $portrait, " + + "${context.getString(R.string.landscape)}: $landscape" + } + } + intListPreference { + 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) + entryValues = arrayOf("0", "1", "2", "3", "6", "12", "24", "48") + defaultValue = "0" + summary = "%s" + + onChange { newValue -> + // Always cancel the previous task, it seems that sometimes they are not updated. + LibraryUpdateJob.cancelTask() + + val interval = (newValue as String).toInt() + if (interval > 0) { + LibraryUpdateJob.setupTask(interval) + } + true + } + } + multiSelectListPreference { + key = Keys.libraryUpdateRestriction + titleRes = R.string.pref_library_update_restriction + entriesRes = arrayOf(R.string.wifi, R.string.charging) + entryValues = arrayOf("wifi", "ac") + summaryRes = R.string.pref_library_update_restriction_summary + + preferences.libraryUpdateInterval().asObservable() + .subscribeUntilDestroy { isVisible = it > 0 } + + onChange { + // Post to event looper to allow the preference to be updated. + Handler().post { LibraryUpdateJob.setupTask() } + true + } + } + switchPreference { + key = Keys.updateOnlyNonCompleted + titleRes = R.string.pref_update_only_non_completed + defaultValue = false + } + + val dbCategories = db.getCategories().executeAsBlocking() + + multiSelectListPreference { + key = Keys.libraryUpdateCategories + titleRes = R.string.pref_library_update_categories + entries = dbCategories.map { it.name }.toTypedArray() + entryValues = dbCategories.map { it.id.toString() }.toTypedArray() + + preferences.libraryUpdateCategories().asObservable() + .subscribeUntilDestroy { + val selectedCategories = it + .mapNotNull { id -> dbCategories.find { it.id == id.toInt() } } + .sortedBy { it.order } + + summary = if (selectedCategories.isEmpty()) + context.getString(R.string.all) + else + selectedCategories.joinToString { it.name } + } + } + intListPreference{ + key = Keys.libraryUpdatePrioritization + titleRes = R.string.pref_library_update_prioritization + // The following arrays are to be lined up with the list rankingScheme in: + // ../../data/library/LibraryUpdateRanker.kt + entriesRes = arrayOf( + R.string.action_sort_alpha, + R.string.action_sort_last_updated + ) + entryValues = arrayOf( + "0", + "1" + ) + defaultValue = "0" + summaryRes = R.string.pref_library_update_prioritization_summary + } + intListPreference { + key = Keys.defaultCategory + titleRes = R.string.default_category + + val categories = listOf(Category.createDefault()) + dbCategories + + val selectedCategory = categories.find { it.id == preferences.defaultCategory() } + entries = arrayOf(context.getString(R.string.default_category_summary)) + + categories.map { it.name }.toTypedArray() + entryValues = arrayOf("-1") + categories.map { it.id.toString() }.toTypedArray() + defaultValue = "-1" + summary = selectedCategory?.name ?: context.getString(R.string.default_category_summary) + + onChange { newValue -> + summary = categories.find { + it.id == (newValue as String).toInt() + }?.name ?: context.getString(R.string.default_category_summary) + true + } + } + + // Only show this if someone has mass migrated manga once + if (preferences.skipPreMigration().getOrDefault() || preferences.migrationSources() + .getOrDefault().isNotEmpty()) { + switchPreference { + key = Keys.skipPreMigration + titleRes = R.string.pref_skip_pre_migration + summaryRes = R.string.pref_skip_pre_migration_summary + defaultValue = false + } + } + + switchPreference { + key = Keys.removeArticles + titleRes = R.string.pref_remove_articles + summaryRes = R.string.pref_remove_articles_summary + defaultValue = false + } + } + + class LibraryColumnsDialog : DialogController() { + + private val preferences: PreferencesHelper = Injekt.get() + + private var portrait = preferences.portraitColumns().getOrDefault() + private var landscape = preferences.landscapeColumns().getOrDefault() + + override fun onCreateDialog(savedViewState: Bundle?): Dialog { + val dialog = MaterialDialog.Builder(activity!!) + .title(R.string.pref_library_columns) + .customView(R.layout.pref_library_columns, false) + .positiveText(android.R.string.ok) + .negativeText(android.R.string.cancel) + .onPositive { _, _ -> + preferences.portraitColumns().set(portrait) + preferences.landscapeColumns().set(landscape) + } + .build() + + onViewCreated(dialog.view) + return dialog + } + + fun onViewCreated(view: View) { + with(view.portrait_columns) { + displayedValues = arrayOf(context.getString(R.string.default_columns)) + + IntRange(1, 10).map(Int::toString) + value = portrait + + setOnValueChangedListener { _, _, newValue -> + portrait = newValue + } + } + with(view.landscape_columns) { + displayedValues = arrayOf(context.getString(R.string.default_columns)) + + IntRange(1, 10).map(Int::toString) + value = landscape + + setOnValueChangedListener { _, _, newValue -> + landscape = newValue + } + } + } + + } + +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index b45755054d..fd469f35e1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -1,7 +1,10 @@ package eu.kanade.tachiyomi.ui.setting import androidx.preference.PreferenceScreen +import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.preference.PreferenceKeys +import eu.kanade.tachiyomi.data.updater.UpdaterJob import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.util.getResourceColor @@ -17,6 +20,12 @@ class SettingsMainController : SettingsController() { titleRes = R.string.pref_category_general onClick { navigateTo(SettingsGeneralController()) } } + preference { + iconRes = R.drawable.ic_in_library_24dp + iconTint = tintColor + titleRes = R.string.pref_category_library + onClick { navigateTo(SettingsLibraryController()) } + } preference { iconRes = R.drawable.ic_chrome_reader_mode_black_24dp iconTint = tintColor diff --git a/app/src/main/res/layout/manga_info_controller.xml b/app/src/main/res/layout/manga_info_controller.xml index 9dd0567227..662142a19d 100644 --- a/app/src/main/res/layout/manga_info_controller.xml +++ b/app/src/main/res/layout/manga_info_controller.xml @@ -72,35 +72,33 @@ android:id="@+id/info_scrollview" android:layout_width="0dp" android:layout_height="0dp" - android:layout_marginTop="0dp" - android:layout_marginBottom="0dp" - android:layout_marginStart="0dp" - android:layout_marginRight="16dp" + android:layout_marginEnd="16dp" android:paddingTop="16dp" - android:paddingBottom="24dp" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/guideline" + android:paddingBottom="20dp" + android:clipToPadding="false" + app:layout_constraintBottom_toBottomOf="@+id/backdrop" app:layout_constraintLeft_toLeftOf="@+id/guideline2" - app:layout_constraintRight_toRightOf="parent"> + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent"> + app:autoSizeMinTextSize="12sp" + app:autoSizeStepGranularity="2sp" + app:autoSizeTextType="uniform" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/manga_full_title" /> + app:layout_constraintRight_toRightOf="parent" /> + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/manga_author_label" /> + app:layout_constraintRight_toRightOf="parent" /> + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/manga_artist_label" /> + app:layout_constraintRight_toRightOf="parent" /> + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/manga_chapters_label" /> + app:layout_constraintRight_toRightOf="parent" /> + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/manga_last_update_label" /> + app:layout_constraintRight_toRightOf="parent" /> + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/manga_status_label" /> + app:layout_constraintRight_toRightOf="parent" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c90628cffd..b9ebe5f69b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -119,6 +119,7 @@ General + Library Reader Downloads Sources @@ -422,8 +423,8 @@ Download all Download unread Are you sure you want to delete selected chapters? - Migrate %1$d%2$s mangas? - Copy %1$d%2$s mangas? + Migrate %1$d%2$s manga? + Copy %1$d%2$s manga? (skipping %1$d) No manga migrated No chapters found, this manga cannot be used for @@ -499,6 +500,7 @@ Migrate Copy Migrating… + Migration Latest: %1$s @@ -574,6 +576,6 @@ Use source with the most chapters (slower) Use first source with alternative Skip this step next time - To show this screen again, go to Settings -> General. + To show this screen again, go to Settings -> Library.