SettingsAdvancedController.kt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. package eu.kanade.tachiyomi.ui.setting
  2. import android.annotation.SuppressLint
  3. import android.content.ActivityNotFoundException
  4. import android.content.Intent
  5. import android.provider.Settings
  6. import androidx.core.net.toUri
  7. import androidx.preference.PreferenceScreen
  8. import com.google.android.material.dialog.MaterialAlertDialogBuilder
  9. import eu.kanade.tachiyomi.BuildConfig
  10. import eu.kanade.tachiyomi.R
  11. import eu.kanade.tachiyomi.data.cache.ChapterCache
  12. import eu.kanade.tachiyomi.data.database.DatabaseHelper
  13. import eu.kanade.tachiyomi.data.library.LibraryUpdateService
  14. import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Target
  15. import eu.kanade.tachiyomi.data.preference.PreferenceValues
  16. import eu.kanade.tachiyomi.network.NetworkHelper
  17. import eu.kanade.tachiyomi.network.PREF_DOH_ADGUARD
  18. import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
  19. import eu.kanade.tachiyomi.network.PREF_DOH_GOOGLE
  20. import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
  21. import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
  22. import eu.kanade.tachiyomi.ui.setting.database.ClearDatabaseController
  23. import eu.kanade.tachiyomi.util.CrashLogUtil
  24. import eu.kanade.tachiyomi.util.lang.launchIO
  25. import eu.kanade.tachiyomi.util.lang.withUIContext
  26. import eu.kanade.tachiyomi.util.preference.defaultValue
  27. import eu.kanade.tachiyomi.util.preference.entriesRes
  28. import eu.kanade.tachiyomi.util.preference.intListPreference
  29. import eu.kanade.tachiyomi.util.preference.listPreference
  30. import eu.kanade.tachiyomi.util.preference.onChange
  31. import eu.kanade.tachiyomi.util.preference.onClick
  32. import eu.kanade.tachiyomi.util.preference.preference
  33. import eu.kanade.tachiyomi.util.preference.preferenceCategory
  34. import eu.kanade.tachiyomi.util.preference.summaryRes
  35. import eu.kanade.tachiyomi.util.preference.switchPreference
  36. import eu.kanade.tachiyomi.util.preference.titleRes
  37. import eu.kanade.tachiyomi.util.system.MiuiUtil
  38. import eu.kanade.tachiyomi.util.system.isPackageInstalled
  39. import eu.kanade.tachiyomi.util.system.powerManager
  40. import eu.kanade.tachiyomi.util.system.toast
  41. import uy.kohesive.injekt.injectLazy
  42. import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
  43. class SettingsAdvancedController : SettingsController() {
  44. private val network: NetworkHelper by injectLazy()
  45. private val chapterCache: ChapterCache by injectLazy()
  46. private val db: DatabaseHelper by injectLazy()
  47. @SuppressLint("BatteryLife")
  48. override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
  49. titleRes = R.string.pref_category_advanced
  50. if (BuildConfig.FLAVOR != "dev") {
  51. switchPreference {
  52. key = "acra.enable"
  53. titleRes = R.string.pref_enable_acra
  54. summaryRes = R.string.pref_acra_summary
  55. defaultValue = true
  56. }
  57. }
  58. preference {
  59. key = "dump_crash_logs"
  60. titleRes = R.string.pref_dump_crash_logs
  61. summaryRes = R.string.pref_dump_crash_logs_summary
  62. onClick {
  63. CrashLogUtil(context).dumpLogs()
  64. }
  65. }
  66. switchPreference {
  67. key = Keys.verboseLogging
  68. titleRes = R.string.pref_verbose_logging
  69. summaryRes = R.string.pref_verbose_logging_summary
  70. defaultValue = false
  71. onChange {
  72. activity?.toast(R.string.requires_app_restart)
  73. true
  74. }
  75. }
  76. preferenceCategory {
  77. titleRes = R.string.label_background_activity
  78. preference {
  79. key = "pref_disable_battery_optimization"
  80. titleRes = R.string.pref_disable_battery_optimization
  81. summaryRes = R.string.pref_disable_battery_optimization_summary
  82. onClick {
  83. val packageName: String = context.packageName
  84. if (!context.powerManager.isIgnoringBatteryOptimizations(packageName)) {
  85. try {
  86. val intent = Intent().apply {
  87. action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
  88. data = "package:$packageName".toUri()
  89. }
  90. startActivity(intent)
  91. } catch (e: ActivityNotFoundException) {
  92. context.toast(R.string.battery_optimization_setting_activity_not_found)
  93. }
  94. } else {
  95. context.toast(R.string.battery_optimization_disabled)
  96. }
  97. }
  98. }
  99. preference {
  100. key = "pref_dont_kill_my_app"
  101. title = "Don't kill my app!"
  102. summaryRes = R.string.about_dont_kill_my_app
  103. onClick {
  104. openInBrowser("https://dontkillmyapp.com/")
  105. }
  106. }
  107. }
  108. preferenceCategory {
  109. titleRes = R.string.label_data
  110. preference {
  111. key = CLEAR_CACHE_KEY
  112. titleRes = R.string.pref_clear_chapter_cache
  113. summary = context.getString(R.string.used_cache, chapterCache.readableSize)
  114. onClick { clearChapterCache() }
  115. }
  116. switchPreference {
  117. key = Keys.autoClearChapterCache
  118. titleRes = R.string.pref_auto_clear_chapter_cache
  119. defaultValue = false
  120. }
  121. preference {
  122. key = "pref_clear_database"
  123. titleRes = R.string.pref_clear_database
  124. summaryRes = R.string.pref_clear_database_summary
  125. onClick {
  126. router.pushController(ClearDatabaseController().withFadeTransaction())
  127. }
  128. }
  129. }
  130. preferenceCategory {
  131. titleRes = R.string.label_network
  132. preference {
  133. key = "pref_clear_cookies"
  134. titleRes = R.string.pref_clear_cookies
  135. onClick {
  136. network.cookieManager.removeAll()
  137. activity?.toast(R.string.cookies_cleared)
  138. }
  139. }
  140. intListPreference {
  141. key = Keys.dohProvider
  142. titleRes = R.string.pref_dns_over_https
  143. entries = arrayOf(
  144. context.getString(R.string.disabled),
  145. "Cloudflare",
  146. "Google",
  147. "AdGuard",
  148. )
  149. entryValues = arrayOf(
  150. "-1",
  151. PREF_DOH_CLOUDFLARE.toString(),
  152. PREF_DOH_GOOGLE.toString(),
  153. PREF_DOH_ADGUARD.toString(),
  154. )
  155. defaultValue = "-1"
  156. summary = "%s"
  157. onChange {
  158. activity?.toast(R.string.requires_app_restart)
  159. true
  160. }
  161. }
  162. }
  163. preferenceCategory {
  164. titleRes = R.string.label_library
  165. preference {
  166. key = "pref_refresh_library_covers"
  167. titleRes = R.string.pref_refresh_library_covers
  168. onClick { LibraryUpdateService.start(context, target = Target.COVERS) }
  169. }
  170. preference {
  171. key = "pref_refresh_library_tracking"
  172. titleRes = R.string.pref_refresh_library_tracking
  173. summaryRes = R.string.pref_refresh_library_tracking_summary
  174. onClick { LibraryUpdateService.start(context, target = Target.TRACKING) }
  175. }
  176. }
  177. preferenceCategory {
  178. titleRes = R.string.label_extensions
  179. listPreference {
  180. key = Keys.extensionInstaller
  181. titleRes = R.string.ext_installer_pref
  182. summary = "%s"
  183. entriesRes = arrayOf(
  184. R.string.ext_installer_legacy,
  185. R.string.ext_installer_packageinstaller,
  186. R.string.ext_installer_shizuku,
  187. )
  188. entryValues = PreferenceValues.ExtensionInstaller.values().map { it.name }.toTypedArray()
  189. defaultValue = if (MiuiUtil.isMiui()) {
  190. PreferenceValues.ExtensionInstaller.LEGACY
  191. } else {
  192. PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER
  193. }.name
  194. onChange {
  195. if (it == PreferenceValues.ExtensionInstaller.SHIZUKU.name &&
  196. !context.isPackageInstalled("moe.shizuku.privileged.api")
  197. ) {
  198. MaterialAlertDialogBuilder(context)
  199. .setTitle(R.string.ext_installer_shizuku)
  200. .setMessage(R.string.ext_installer_shizuku_unavailable_dialog)
  201. .setPositiveButton(android.R.string.ok) { _, _ ->
  202. openInBrowser("https://shizuku.rikka.app/download")
  203. }
  204. .setNegativeButton(android.R.string.cancel, null)
  205. .show()
  206. false
  207. } else {
  208. true
  209. }
  210. }
  211. }
  212. }
  213. preferenceCategory {
  214. titleRes = R.string.pref_category_display
  215. listPreference {
  216. key = Keys.tabletUiMode
  217. titleRes = R.string.pref_tablet_ui_mode
  218. summary = "%s"
  219. entriesRes = arrayOf(R.string.automatic_background, R.string.lock_always, R.string.landscape, R.string.lock_never)
  220. entryValues = PreferenceValues.TabletUiMode.values().map { it.name }.toTypedArray()
  221. defaultValue = PreferenceValues.TabletUiMode.AUTOMATIC.name
  222. onChange {
  223. activity?.toast(R.string.requires_app_restart)
  224. true
  225. }
  226. }
  227. }
  228. }
  229. private fun clearChapterCache() {
  230. if (activity == null) return
  231. launchIO {
  232. try {
  233. val deletedFiles = chapterCache.clear()
  234. withUIContext {
  235. activity?.toast(resources?.getString(R.string.cache_deleted, deletedFiles))
  236. findPreference(CLEAR_CACHE_KEY)?.summary =
  237. resources?.getString(R.string.used_cache, chapterCache.readableSize)
  238. }
  239. } catch (e: Throwable) {
  240. withUIContext { activity?.toast(R.string.cache_delete_error) }
  241. }
  242. }
  243. }
  244. }
  245. private const val CLEAR_CACHE_KEY = "pref_clear_cache_key"