Fix in-app update checking
This commit is contained in:
@@ -11,8 +11,10 @@ import java.security.cert.CertificateFactory
|
|||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.koitharu.kotatsu.BuildConfig
|
import org.koitharu.kotatsu.BuildConfig
|
||||||
@@ -53,11 +55,11 @@ class AppUpdateRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchUpdate(): AppVersion? {
|
suspend fun fetchUpdate(): AppVersion? = withContext(Dispatchers.Default) {
|
||||||
if (!isUpdateSupported()) {
|
if (!isUpdateSupported()) {
|
||||||
return null
|
return@withContext null
|
||||||
}
|
}
|
||||||
return runCatching {
|
runCatching {
|
||||||
val currentVersion = VersionId(BuildConfig.VERSION_NAME)
|
val currentVersion = VersionId(BuildConfig.VERSION_NAME)
|
||||||
val available = getAvailableVersions().asArrayList()
|
val available = getAvailableVersions().asArrayList()
|
||||||
available.sortBy { it.versionId }
|
available.sortBy { it.versionId }
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ import androidx.core.content.edit
|
|||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import java.io.File
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
import org.koitharu.kotatsu.BuildConfig
|
import org.koitharu.kotatsu.BuildConfig
|
||||||
import org.koitharu.kotatsu.core.model.ZoomMode
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
import org.koitharu.kotatsu.core.network.DoHProvider
|
import org.koitharu.kotatsu.core.network.DoHProvider
|
||||||
@@ -19,12 +25,6 @@ import org.koitharu.kotatsu.utils.ext.getEnumValue
|
|||||||
import org.koitharu.kotatsu.utils.ext.observe
|
import org.koitharu.kotatsu.utils.ext.observe
|
||||||
import org.koitharu.kotatsu.utils.ext.putEnumValue
|
import org.koitharu.kotatsu.utils.ext.putEnumValue
|
||||||
import org.koitharu.kotatsu.utils.ext.toUriOrNull
|
import org.koitharu.kotatsu.utils.ext.toUriOrNull
|
||||||
import java.io.File
|
|
||||||
import java.text.DateFormat
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||||
@@ -73,13 +73,6 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
get() = prefs.getBoolean(KEY_ALL_FAVOURITES_VISIBLE, true)
|
get() = prefs.getBoolean(KEY_ALL_FAVOURITES_VISIBLE, true)
|
||||||
set(value) = prefs.edit { putBoolean(KEY_ALL_FAVOURITES_VISIBLE, value) }
|
set(value) = prefs.edit { putBoolean(KEY_ALL_FAVOURITES_VISIBLE, value) }
|
||||||
|
|
||||||
val isUpdateCheckingEnabled: Boolean
|
|
||||||
get() = prefs.getBoolean(KEY_APP_UPDATE_AUTO, true)
|
|
||||||
|
|
||||||
var lastUpdateCheckTimestamp: Long
|
|
||||||
get() = prefs.getLong(KEY_APP_UPDATE, 0L)
|
|
||||||
set(value) = prefs.edit { putLong(KEY_APP_UPDATE, value) }
|
|
||||||
|
|
||||||
val isTrackerEnabled: Boolean
|
val isTrackerEnabled: Boolean
|
||||||
get() = prefs.getBoolean(KEY_TRACKER_ENABLED, true)
|
get() = prefs.getBoolean(KEY_TRACKER_ENABLED, true)
|
||||||
|
|
||||||
@@ -327,7 +320,6 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
|
|
||||||
// About
|
// About
|
||||||
const val KEY_APP_UPDATE = "app_update"
|
const val KEY_APP_UPDATE = "app_update"
|
||||||
const val KEY_APP_UPDATE_AUTO = "app_update_auto"
|
|
||||||
const val KEY_APP_TRANSLATION = "about_app_translation"
|
const val KEY_APP_TRANSLATION = "about_app_translation"
|
||||||
|
|
||||||
private const val NETWORK_NEVER = 0
|
private const val NETWORK_NEVER = 0
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.util.SparseIntArray
|
|||||||
import androidx.core.util.set
|
import androidx.core.util.set
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
@@ -16,12 +17,10 @@ import org.koitharu.kotatsu.parsers.model.Manga
|
|||||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||||
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class MainViewModel @Inject constructor(
|
class MainViewModel @Inject constructor(
|
||||||
private val historyRepository: HistoryRepository,
|
private val historyRepository: HistoryRepository,
|
||||||
private val settings: AppSettings,
|
|
||||||
private val appUpdateRepository: AppUpdateRepository,
|
private val appUpdateRepository: AppUpdateRepository,
|
||||||
private val trackingRepository: TrackingRepository,
|
private val trackingRepository: TrackingRepository,
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
@@ -43,7 +42,7 @@ class MainViewModel @Inject constructor(
|
|||||||
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, SparseIntArray(0))
|
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, SparseIntArray(0))
|
||||||
|
|
||||||
init {
|
init {
|
||||||
launchJob(Dispatchers.Default) {
|
launchJob {
|
||||||
appUpdateRepository.fetchUpdate()
|
appUpdateRepository.fetchUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.settings
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.annotation.MainThread
|
|
||||||
import androidx.core.net.toUri
|
|
||||||
import com.google.android.material.R as materialR
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.security.MessageDigest
|
|
||||||
import java.security.cert.CertificateFactory
|
|
||||||
import java.security.cert.X509Certificate
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.koitharu.kotatsu.BuildConfig
|
|
||||||
import org.koitharu.kotatsu.R
|
|
||||||
import org.koitharu.kotatsu.core.github.AppUpdateRepository
|
|
||||||
import org.koitharu.kotatsu.core.github.AppVersion
|
|
||||||
import org.koitharu.kotatsu.core.github.VersionId
|
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
|
||||||
import org.koitharu.kotatsu.parsers.util.byte2HexFormatted
|
|
||||||
import org.koitharu.kotatsu.utils.FileSize
|
|
||||||
import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
|
|
||||||
|
|
||||||
@Deprecated("")
|
|
||||||
class AppUpdateChecker(private val activity: ComponentActivity) {
|
|
||||||
|
|
||||||
private val settings: AppSettings = TODO()
|
|
||||||
private val repo: AppUpdateRepository = TODO()
|
|
||||||
|
|
||||||
suspend fun checkIfNeeded(): Boolean? = if (
|
|
||||||
settings.isUpdateCheckingEnabled &&
|
|
||||||
settings.lastUpdateCheckTimestamp + PERIOD < System.currentTimeMillis()
|
|
||||||
) {
|
|
||||||
checkNow()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun checkNow() = runCatching {
|
|
||||||
val version = repo.fetchUpdate() ?: return@runCatching false
|
|
||||||
val newVersionId = VersionId(version.name)
|
|
||||||
val currentVersionId = VersionId(BuildConfig.VERSION_NAME)
|
|
||||||
val result = newVersionId > currentVersionId
|
|
||||||
if (result) {
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
showUpdateDialog(version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings.lastUpdateCheckTimestamp = System.currentTimeMillis()
|
|
||||||
result
|
|
||||||
}.onFailure {
|
|
||||||
it.printStackTraceDebug()
|
|
||||||
}.getOrNull()
|
|
||||||
|
|
||||||
@MainThread
|
|
||||||
private fun showUpdateDialog(version: AppVersion) {
|
|
||||||
val message = buildString {
|
|
||||||
append(activity.getString(R.string.new_version_s, version.name))
|
|
||||||
appendLine()
|
|
||||||
append(activity.getString(R.string.size_s, FileSize.BYTES.format(activity, version.apkSize)))
|
|
||||||
appendLine()
|
|
||||||
appendLine()
|
|
||||||
append(version.description)
|
|
||||||
}
|
|
||||||
MaterialAlertDialogBuilder(activity, materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered)
|
|
||||||
.setTitle(R.string.app_update_available)
|
|
||||||
.setMessage(message)
|
|
||||||
.setIcon(R.drawable.ic_app_update)
|
|
||||||
.setPositiveButton(R.string.download) { _, _ ->
|
|
||||||
val intent = Intent(Intent.ACTION_VIEW, version.apkUrl.toUri())
|
|
||||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.open_in_browser)))
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.close, null)
|
|
||||||
.setCancelable(false)
|
|
||||||
.create()
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val CERT_SHA1 = "2C:19:C7:E8:07:61:2B:8E:94:51:1B:FD:72:67:07:64:5D:C2:58:AE"
|
|
||||||
private val PERIOD = TimeUnit.HOURS.toMillis(6)
|
|
||||||
|
|
||||||
fun isUpdateSupported(context: Context): Boolean {
|
|
||||||
return BuildConfig.DEBUG || getCertificateSHA1Fingerprint(context) == CERT_SHA1
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
@SuppressLint("PackageManagerGetSignatures")
|
|
||||||
private fun getCertificateSHA1Fingerprint(context: Context): String? = runCatching {
|
|
||||||
val packageInfo = context.packageManager.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES)
|
|
||||||
val signatures = requireNotNull(packageInfo?.signatures)
|
|
||||||
val cert: ByteArray = signatures.first().toByteArray()
|
|
||||||
val input: InputStream = ByteArrayInputStream(cert)
|
|
||||||
val cf = CertificateFactory.getInstance("X509")
|
|
||||||
val c = cf.generateCertificate(input) as X509Certificate
|
|
||||||
val md: MessageDigest = MessageDigest.getInstance("SHA1")
|
|
||||||
val publicKey: ByteArray = md.digest(c.encoded)
|
|
||||||
return publicKey.byte2HexFormatted()
|
|
||||||
}.onFailure { error ->
|
|
||||||
error.printStackTraceDebug()
|
|
||||||
}.getOrNull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,34 +2,41 @@ package org.koitharu.kotatsu.settings.about
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import kotlinx.coroutines.launch
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import org.koitharu.kotatsu.BuildConfig
|
import org.koitharu.kotatsu.BuildConfig
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment
|
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment
|
||||||
|
import org.koitharu.kotatsu.core.github.AppVersion
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.settings.AppUpdateChecker
|
|
||||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
|
||||||
|
|
||||||
class AboutSettingsFragment : BasePreferenceFragment(R.string.about) {
|
class AboutSettingsFragment : BasePreferenceFragment(R.string.about) {
|
||||||
|
|
||||||
|
private val viewModel by viewModels<AboutSettingsViewModel>()
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
addPreferencesFromResource(R.xml.pref_about)
|
addPreferencesFromResource(R.xml.pref_about)
|
||||||
val isUpdateSupported = AppUpdateChecker.isUpdateSupported(requireContext())
|
|
||||||
findPreference<Preference>(AppSettings.KEY_APP_UPDATE_AUTO)?.run {
|
|
||||||
isVisible = isUpdateSupported
|
|
||||||
}
|
|
||||||
findPreference<Preference>(AppSettings.KEY_APP_VERSION)?.run {
|
findPreference<Preference>(AppSettings.KEY_APP_VERSION)?.run {
|
||||||
title = getString(R.string.app_version, BuildConfig.VERSION_NAME)
|
title = getString(R.string.app_version, BuildConfig.VERSION_NAME)
|
||||||
isEnabled = isUpdateSupported
|
isEnabled = viewModel.isUpdateSupported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
viewModel.isLoading.observe(viewLifecycleOwner) {
|
||||||
|
findPreference<Preference>(AppSettings.KEY_APP_UPDATE)?.isEnabled = !it
|
||||||
|
}
|
||||||
|
viewModel.onUpdateAvailable.observe(viewLifecycleOwner, ::onUpdateAvailable)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||||
return when (preference.key) {
|
return when (preference.key) {
|
||||||
AppSettings.KEY_APP_VERSION -> {
|
AppSettings.KEY_APP_VERSION -> {
|
||||||
checkForUpdates()
|
viewModel.checkForUpdates()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
AppSettings.KEY_APP_TRANSLATION -> {
|
AppSettings.KEY_APP_TRANSLATION -> {
|
||||||
@@ -40,24 +47,12 @@ class AboutSettingsFragment : BasePreferenceFragment(R.string.about) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkForUpdates() {
|
private fun onUpdateAvailable(version: AppVersion?) {
|
||||||
viewLifecycleScope.launch {
|
if (version == null) {
|
||||||
findPreference<Preference>(AppSettings.KEY_APP_VERSION)?.run {
|
Snackbar.make(listView, R.string.no_update_available, Snackbar.LENGTH_SHORT).show()
|
||||||
setSummary(R.string.checking_for_updates)
|
return
|
||||||
isSelectable = false
|
|
||||||
}
|
|
||||||
val result = AppUpdateChecker(activity ?: return@launch).checkNow()
|
|
||||||
findPreference<Preference>(AppSettings.KEY_APP_VERSION)?.run {
|
|
||||||
setSummary(
|
|
||||||
when (result) {
|
|
||||||
true -> R.string.check_for_updates
|
|
||||||
false -> R.string.no_update_available
|
|
||||||
null -> R.string.update_check_failed
|
|
||||||
}
|
|
||||||
)
|
|
||||||
isSelectable = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
AppUpdateDialog(context ?: return).show(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openLink(url: String, title: CharSequence?) {
|
private fun openLink(url: String, title: CharSequence?) {
|
||||||
@@ -68,7 +63,7 @@ class AboutSettingsFragment : BasePreferenceFragment(R.string.about) {
|
|||||||
Intent.createChooser(intent, title)
|
Intent.createChooser(intent, title)
|
||||||
} else {
|
} else {
|
||||||
intent
|
intent
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.about
|
||||||
|
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.github.AppUpdateRepository
|
||||||
|
import org.koitharu.kotatsu.core.github.AppVersion
|
||||||
|
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class AboutSettingsViewModel @Inject constructor(
|
||||||
|
private val appUpdateRepository: AppUpdateRepository,
|
||||||
|
) : BaseViewModel() {
|
||||||
|
|
||||||
|
val isUpdateSupported = appUpdateRepository.isUpdateSupported()
|
||||||
|
val onUpdateAvailable = SingleLiveEvent<AppVersion?>()
|
||||||
|
|
||||||
|
fun checkForUpdates() {
|
||||||
|
launchLoadingJob {
|
||||||
|
val update = appUpdateRepository.fetchUpdate()
|
||||||
|
onUpdateAvailable.call(update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.about
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import com.google.android.material.R as materialR
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.github.AppVersion
|
||||||
|
import org.koitharu.kotatsu.utils.FileSize
|
||||||
|
|
||||||
|
class AppUpdateDialog(private val context: Context) {
|
||||||
|
|
||||||
|
fun show(version: AppVersion) {
|
||||||
|
val message = buildString {
|
||||||
|
append(context.getString(R.string.new_version_s, version.name))
|
||||||
|
appendLine()
|
||||||
|
append(context.getString(R.string.size_s, FileSize.BYTES.format(context, version.apkSize)))
|
||||||
|
appendLine()
|
||||||
|
appendLine()
|
||||||
|
append(version.description)
|
||||||
|
}
|
||||||
|
MaterialAlertDialogBuilder(
|
||||||
|
context,
|
||||||
|
materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
|
||||||
|
)
|
||||||
|
.setTitle(R.string.app_update_available)
|
||||||
|
.setMessage(message)
|
||||||
|
.setIcon(R.drawable.ic_app_update)
|
||||||
|
.setPositiveButton(R.string.download) { _, _ ->
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, version.apkUrl.toUri())
|
||||||
|
context.startActivity(Intent.createChooser(intent, context.getString(R.string.open_in_browser)))
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.close, null)
|
||||||
|
.setCancelable(false)
|
||||||
|
.create()
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import org.koitharu.kotatsu.core.github.AppVersion
|
|||||||
import org.koitharu.kotatsu.databinding.FragmentToolsBinding
|
import org.koitharu.kotatsu.databinding.FragmentToolsBinding
|
||||||
import org.koitharu.kotatsu.download.ui.DownloadsActivity
|
import org.koitharu.kotatsu.download.ui.DownloadsActivity
|
||||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||||
|
import org.koitharu.kotatsu.settings.about.AppUpdateDialog
|
||||||
import org.koitharu.kotatsu.settings.tools.model.StorageUsage
|
import org.koitharu.kotatsu.settings.tools.model.StorageUsage
|
||||||
import org.koitharu.kotatsu.utils.FileSize
|
import org.koitharu.kotatsu.utils.FileSize
|
||||||
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
||||||
@@ -68,6 +69,10 @@ class ToolsFragment :
|
|||||||
intent.data = url.toUri()
|
intent.data = url.toUri()
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.open_in_browser)))
|
startActivity(Intent.createChooser(intent, getString(R.string.open_in_browser)))
|
||||||
}
|
}
|
||||||
|
R.id.card_update -> {
|
||||||
|
val version = viewModel.appUpdate.value ?: return
|
||||||
|
AppUpdateDialog(v.context).show(version)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/card_update"
|
android:id="@+id/card_update"
|
||||||
style="@style/Widget.Material3.CardView.Filled"
|
style="@style/Widget.Material3.CardView.Filled"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -53,7 +52,7 @@
|
|||||||
style="@style/Widget.Material3.Button"
|
style="@style/Widget.Material3.Button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/margin_small"
|
android:layout_marginTop="12dp"
|
||||||
android:text="@string/download"
|
android:text="@string/download"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/textSecondary" />
|
app:layout_constraintTop_toBottomOf="@id/textSecondary" />
|
||||||
@@ -61,4 +60,4 @@
|
|||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|||||||
@@ -9,12 +9,6 @@
|
|||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:summary="@string/check_for_updates" />
|
android:summary="@string/check_for_updates" />
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="app_update_auto"
|
|
||||||
android:summary="@string/show_notification_app_update"
|
|
||||||
android:title="@string/application_update" />
|
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="about_app_translation"
|
android:key="about_app_translation"
|
||||||
android:summary="@string/about_app_translation_summary"
|
android:summary="@string/about_app_translation_summary"
|
||||||
|
|||||||
Reference in New Issue
Block a user