Commit 094c3d55 authored by topjohnwu's avatar topjohnwu

Minor fixes and cleanups

parent 6fb032b3
...@@ -2,6 +2,7 @@ package com.topjohnwu.magisk ...@@ -2,6 +2,7 @@ package com.topjohnwu.magisk
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Environment
import android.util.Xml import android.util.Xml
import androidx.core.content.edit import androidx.core.content.edit
import com.topjohnwu.magisk.data.database.SettingsDao import com.topjohnwu.magisk.data.database.SettingsDao
...@@ -97,10 +98,8 @@ object Config : PreferenceModel, DBConfig { ...@@ -97,10 +98,8 @@ object Config : PreferenceModel, DBConfig {
if (Utils.isCanary) Value.CANARY_DEBUG_CHANNEL if (Utils.isCanary) Value.CANARY_DEBUG_CHANNEL
else Value.DEFAULT_CHANNEL else Value.DEFAULT_CHANNEL
private val defaultDownloadPath get() = Const.EXTERNAL_PATH.toRelativeString(Const.EXTERNAL_PATH.parentFile)
var isDownloadCacheEnabled by preference(Key.DOWNLOAD_CACHE, true) var isDownloadCacheEnabled by preference(Key.DOWNLOAD_CACHE, true)
var downloadPath by preference(Key.DOWNLOAD_PATH, defaultDownloadPath) var downloadPath by preference(Key.DOWNLOAD_PATH, Environment.DIRECTORY_DOWNLOADS)
var repoOrder by preference(Key.REPO_ORDER, Value.ORDER_DATE) var repoOrder by preference(Key.REPO_ORDER, Value.ORDER_DATE)
var suDefaultTimeout by preferenceStrInt(Key.SU_REQUEST_TIMEOUT, 10) var suDefaultTimeout by preferenceStrInt(Key.SU_REQUEST_TIMEOUT, 10)
...@@ -128,14 +127,9 @@ object Config : PreferenceModel, DBConfig { ...@@ -128,14 +127,9 @@ object Config : PreferenceModel, DBConfig {
@JvmStatic @JvmStatic
var suManager by dbStrings(Key.SU_MANAGER, "") var suManager by dbStrings(Key.SU_MANAGER, "")
fun downloadsFile(path: String = downloadPath) = // Always return a path in external storage where we can write
File(Const.EXTERNAL_PATH.parentFile, path).run { val downloadDirectory get() =
if (exists()) { Utils.ensureDownloadPath(downloadPath) ?: get<Context>().getExternalFilesDir(null)!!
if (isDirectory) this else null
} else {
if (mkdirs()) this else null
}
}
fun initialize() = prefs.edit { fun initialize() = prefs.edit {
parsePrefs(this) parsePrefs(this)
......
...@@ -6,13 +6,13 @@ import android.app.PendingIntent ...@@ -6,13 +6,13 @@ import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Environment
import android.webkit.MimeTypeMap import android.webkit.MimeTypeMap
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.topjohnwu.magisk.ClassMap import com.topjohnwu.magisk.ClassMap
import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.entity.internal.Configuration.* import com.topjohnwu.magisk.model.entity.internal.Configuration.*
import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary
...@@ -31,7 +31,7 @@ import kotlin.random.Random.Default.nextInt ...@@ -31,7 +31,7 @@ import kotlin.random.Random.Default.nextInt
open class DownloadService : RemoteFileService() { open class DownloadService : RemoteFileService() {
private val context get() = this private val context get() = this
private val String.downloadsFile get() = Config.downloadsFile()?.let { File(it, this) } private val String.downloadsFile get() = File(Config.downloadDirectory, this)
private val File.type private val File.type
get() = MimeTypeMap.getSingleton() get() = MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(extension) .getMimeTypeFromExtension(extension)
...@@ -40,7 +40,6 @@ open class DownloadService : RemoteFileService() { ...@@ -40,7 +40,6 @@ open class DownloadService : RemoteFileService() {
override fun onFinished(file: File, subject: DownloadSubject) = when (subject) { override fun onFinished(file: File, subject: DownloadSubject) = when (subject) {
is Magisk -> onFinishedInternal(file, subject) is Magisk -> onFinishedInternal(file, subject)
is Module -> onFinishedInternal(file, subject) is Module -> onFinishedInternal(file, subject)
else -> Unit
} }
private fun onFinishedInternal( private fun onFinishedInternal(
...@@ -71,7 +70,6 @@ open class DownloadService : RemoteFileService() { ...@@ -71,7 +70,6 @@ open class DownloadService : RemoteFileService() {
) = when (subject) { ) = when (subject) {
is Magisk -> addActionsInternal(file, subject) is Magisk -> addActionsInternal(file, subject)
is Module -> addActionsInternal(file, subject) is Module -> addActionsInternal(file, subject)
else -> this
} }
private fun NotificationCompat.Builder.addActionsInternal( private fun NotificationCompat.Builder.addActionsInternal(
...@@ -109,13 +107,7 @@ open class DownloadService : RemoteFileService() { ...@@ -109,13 +107,7 @@ open class DownloadService : RemoteFileService() {
// --- // ---
private fun moveToDownloads(file: File) { private fun moveToDownloads(file: File) {
val destination = file.name.downloadsFile ?: let { val destination = file.name.downloadsFile
Utils.toast(
getString(R.string.download_file_folder_error),
Toast.LENGTH_LONG
)
return
}
if (file != destination) { if (file != destination) {
destination.deleteRecursively() destination.deleteRecursively()
...@@ -125,32 +117,18 @@ open class DownloadService : RemoteFileService() { ...@@ -125,32 +117,18 @@ open class DownloadService : RemoteFileService() {
Utils.toast( Utils.toast(
getString( getString(
R.string.internal_storage, R.string.internal_storage,
"/" + destination.toRelativeString(Const.EXTERNAL_PATH.parentFile) "/" + destination.toRelativeString(Environment.getExternalStorageDirectory())
), ),
Toast.LENGTH_LONG Toast.LENGTH_LONG
) )
} }
private fun fileIntent(fileName: String): Intent { private fun fileIntent(fileName: String): Intent {
val file = fileName.downloadsFile ?: let { return fileIntent(fileName.downloadsFile)
Utils.toast(
getString(R.string.download_file_folder_error),
Toast.LENGTH_LONG
)
return Intent()
}
return fileIntent(file)
} }
private fun fileParentIntent(fileName: String): Intent { private fun fileParentIntent(fileName: String): Intent {
val file = fileName.downloadsFile?.parentFile ?: let { return fileIntent(fileName.downloadsFile.parentFile!!)
Utils.toast(
getString(R.string.download_file_folder_error),
Toast.LENGTH_LONG
)
return Intent()
}
return fileIntent(file)
} }
private fun fileIntent(file: File): Intent { private fun fileIntent(file: File): Intent {
......
...@@ -8,7 +8,8 @@ import com.topjohnwu.magisk.Const ...@@ -8,7 +8,8 @@ import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.repository.FileRepository import com.topjohnwu.magisk.data.repository.FileRepository
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.* import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.Magisk
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject.Module
import com.topjohnwu.magisk.utils.ProgInputStream import com.topjohnwu.magisk.utils.ProgInputStream
import com.topjohnwu.magisk.utils.cachedFile import com.topjohnwu.magisk.utils.cachedFile
import com.topjohnwu.magisk.utils.firstMap import com.topjohnwu.magisk.utils.firstMap
...@@ -30,8 +31,7 @@ abstract class RemoteFileService : NotificationService() { ...@@ -30,8 +31,7 @@ abstract class RemoteFileService : NotificationService() {
private val supportedFolders private val supportedFolders
get() = listOfNotNull( get() = listOfNotNull(
cacheDir, cacheDir,
Config.downloadsFile(), Config.downloadDirectory
Const.EXTERNAL_PATH
) )
override val defaultNotification: NotificationCompat.Builder override val defaultNotification: NotificationCompat.Builder
...@@ -46,31 +46,27 @@ abstract class RemoteFileService : NotificationService() { ...@@ -46,31 +46,27 @@ abstract class RemoteFileService : NotificationService() {
// --- // ---
private fun startInternal(subject: DownloadSubject): Single<File> = search(subject) private fun start(subject: DownloadSubject) = search(subject)
.onErrorResumeNext(download(subject)) .onErrorResumeNext(download(subject))
.doOnSubscribe { update(subject.hashCode()) { it.setContentTitle(subject.fileName) } } .doOnSubscribe { update(subject.hashCode()) { it.setContentTitle(subject.fileName) } }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnSuccess { .doOnSuccess {
runCatching { onFinished(it, subject) }.onFailure { Timber.e(it) } runCatching { onFinished(it, subject) }.onFailure { Timber.e(it) }
finish(it, subject) finish(it, subject)
} }.subscribeK()
private fun start(subject: DownloadSubject) = startInternal(subject).subscribeK()
private fun search(subject: DownloadSubject) = Single.fromCallable { private fun search(subject: DownloadSubject) = Single.fromCallable {
if (!Config.isDownloadCacheEnabled) { if (!Config.isDownloadCacheEnabled) {
throw IllegalStateException("The download cache is disabled") throw IllegalStateException("The download cache is disabled")
} }
val file = supportedFolders.firstMap { it.find(subject.fileName) } supportedFolders.firstMap { it.find(subject.fileName) }.also {
if (subject is Magisk) { if (subject is Magisk) {
if (!ShellUtils.checkSum("MD5", file, subject.magisk.hash)) { if (!ShellUtils.checkSum("MD5", it, subject.magisk.hash)) {
throw IllegalStateException("The given file doesn't match the hash") throw IllegalStateException("The given file doesn't match the hash")
} }
} }
}
file
} }
private fun download(subject: DownloadSubject) = repo.downloadFile(subject.url) private fun download(subject: DownloadSubject) = repo.downloadFile(subject.url)
...@@ -107,8 +103,6 @@ abstract class RemoteFileService : NotificationService() { ...@@ -107,8 +103,6 @@ abstract class RemoteFileService : NotificationService() {
} }
private fun finish(file: File, subject: DownloadSubject) = finishWork(subject.hashCode()) { private fun finish(file: File, subject: DownloadSubject) = finishWork(subject.hashCode()) {
if (subject is Installer) return@finishWork null
it.addActions(file, subject) it.addActions(file, subject)
.setContentText(getString(R.string.download_complete)) .setContentText(getString(R.string.download_complete))
.setSmallIcon(android.R.drawable.stat_sys_download_done) .setSmallIcon(android.R.drawable.stat_sys_download_done)
......
...@@ -14,10 +14,6 @@ sealed class Configuration : Parcelable { ...@@ -14,10 +14,6 @@ sealed class Configuration : Parcelable {
@Parcelize @Parcelize
object Secondary : Flash() object Secondary : Flash()
companion object {
operator fun invoke(): Flash = Primary
}
} }
@Parcelize @Parcelize
......
package com.topjohnwu.magisk.model.entity.internal
import com.skoumal.teanity.util.KObservableField
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.model.observer.Observer
class DownloadDialogData(initialValue: String) {
val text = KObservableField(initialValue)
val path = Observer(text) { Config.downloadsFile(text.value)?.absolutePath.orEmpty() }
}
\ No newline at end of file
package com.topjohnwu.magisk.model.entity.internal package com.topjohnwu.magisk.model.entity.internal
import android.os.Parcelable import android.os.Parcelable
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.Info import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.model.entity.MagiskJson import com.topjohnwu.magisk.model.entity.MagiskJson
import com.topjohnwu.magisk.model.entity.Repo import com.topjohnwu.magisk.model.entity.Repo
...@@ -39,10 +37,4 @@ sealed class DownloadSubject : Parcelable { ...@@ -39,10 +37,4 @@ sealed class DownloadSubject : Parcelable {
} }
@Parcelize
object Installer : DownloadSubject() {
override val fileName: String get() = "module_installer(${BuildConfig.VERSION_CODE}).sh"
override val url: String get() = Const.Url.MODULE_INSTALLER
}
} }
\ No newline at end of file
...@@ -18,7 +18,7 @@ open class FlashActivity : MagiskActivity<FlashViewModel, ActivityFlashBinding>( ...@@ -18,7 +18,7 @@ open class FlashActivity : MagiskActivity<FlashViewModel, ActivityFlashBinding>(
override val layoutRes: Int = R.layout.activity_flash override val layoutRes: Int = R.layout.activity_flash
override val viewModel: FlashViewModel by viewModel { override val viewModel: FlashViewModel by viewModel {
val uri = intent.data ?: let { finish(); Uri.EMPTY } val uri = intent.data ?: let { finish(); Uri.EMPTY }
val additionalUri = intent.getParcelableExtra<Uri>(Const.Key.FLASH_DATA) ?: uri val additionalUri = intent.getParcelableExtra(Const.Key.FLASH_DATA) ?: uri
val action = intent.getStringExtra(Const.Key.FLASH_ACTION) ?: let { finish();"" } val action = intent.getStringExtra(Const.Key.FLASH_ACTION) ?: let { finish();"" }
parametersOf(action, uri, additionalUri) parametersOf(action, uri, additionalUri)
} }
......
...@@ -99,7 +99,7 @@ class ReposFragment : MagiskFragment<ModuleViewModel, FragmentReposBinding>(), ...@@ -99,7 +99,7 @@ class ReposFragment : MagiskFragment<ModuleViewModel, FragmentReposBinding>(),
fun download(install: Boolean) = context.withExternalRW { fun download(install: Boolean) = context.withExternalRW {
onSuccess { onSuccess {
DownloadService(context) { DownloadService(context) {
val config = if (install) Configuration.Flash() else Configuration.Download val config = if (install) Configuration.Flash.Primary else Configuration.Download
subject = DownloadSubject.Module(item, config) subject = DownloadSubject.Module(item, config)
} }
} }
......
...@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.settings ...@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.settings
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.EditText import android.widget.EditText
import android.widget.Toast import android.widget.Toast
...@@ -14,19 +15,21 @@ import androidx.preference.Preference ...@@ -14,19 +15,21 @@ import androidx.preference.Preference
import androidx.preference.PreferenceCategory import androidx.preference.PreferenceCategory
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import com.skoumal.teanity.extensions.subscribeK import com.skoumal.teanity.extensions.subscribeK
import com.skoumal.teanity.util.KObservableField
import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.database.RepoDatabaseHelper import com.topjohnwu.magisk.data.database.RepoDatabaseHelper
import com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding import com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding
import com.topjohnwu.magisk.model.entity.internal.DownloadDialogData import com.topjohnwu.magisk.model.observer.Observer
import com.topjohnwu.magisk.ui.base.BasePreferenceFragment import com.topjohnwu.magisk.ui.base.BasePreferenceFragment
import com.topjohnwu.magisk.utils.* import com.topjohnwu.magisk.utils.*
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
import com.topjohnwu.net.Networking import com.topjohnwu.net.Networking
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import java.io.File
class SettingsFragment : BasePreferenceFragment() { class SettingsFragment : BasePreferenceFragment() {
...@@ -297,6 +300,13 @@ class SettingsFragment : BasePreferenceFragment() { ...@@ -297,6 +300,13 @@ class SettingsFragment : BasePreferenceFragment() {
.show() .show()
} }
inner class DownloadDialogData(initialValue: String) {
val text = KObservableField(initialValue)
val path = Observer(text) {
File(Environment.getExternalStorageDirectory(), text.value).absolutePath
}
}
private inline fun showDownloadDialog( private inline fun showDownloadDialog(
initialValue: String = Config.downloadPath, initialValue: String = Config.downloadPath,
crossinline onSuccess: (String) -> Unit crossinline onSuccess: (String) -> Unit
...@@ -310,7 +320,7 @@ class SettingsFragment : BasePreferenceFragment() { ...@@ -310,7 +320,7 @@ class SettingsFragment : BasePreferenceFragment() {
.setTitle(R.string.settings_download_path_title) .setTitle(R.string.settings_download_path_title)
.setView(binding.root) .setView(binding.root)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
Config.downloadsFile(data.text.value)?.let { onSuccess(data.text.value) } Utils.ensureDownloadPath(data.text.value)?.let { onSuccess(data.text.value) }
?: Utils.toast(R.string.settings_download_path_error, Toast.LENGTH_SHORT) ?: Utils.toast(R.string.settings_download_path_error, Toast.LENGTH_SHORT)
} }
.setNegativeButton(R.string.close, null) .setNegativeButton(R.string.close, null)
......
...@@ -8,6 +8,7 @@ import android.content.pm.PackageManager ...@@ -8,6 +8,7 @@ import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.net.Uri import android.net.Uri
import android.os.Environment
import android.widget.Toast import android.widget.Toast
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import androidx.work.* import androidx.work.*
...@@ -19,6 +20,7 @@ import com.topjohnwu.net.Networking ...@@ -19,6 +20,7 @@ import com.topjohnwu.net.Networking
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.internal.UiThreadHandler import com.topjohnwu.superuser.internal.UiThreadHandler
import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFile
import java.io.File
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
...@@ -120,4 +122,9 @@ object Utils { ...@@ -120,4 +122,9 @@ object Utils {
} }
} }
fun ensureDownloadPath(path : String) =
File(Environment.getExternalStorageDirectory(), path).run {
if ((exists() && isDirectory) || mkdirs()) this else null
}
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<variable <variable
name="data" name="data"
type="com.topjohnwu.magisk.model.entity.internal.DownloadDialogData" /> type="com.topjohnwu.magisk.ui.settings.SettingsFragment.DownloadDialogData" />
</data> </data>
......
...@@ -3,4 +3,6 @@ ...@@ -3,4 +3,6 @@
<files-path name="internal_files" path="."/> <files-path name="internal_files" path="."/>
<cache-path name="cache_files" path="." /> <cache-path name="cache_files" path="." />
<external-path name="external_files" path="."/> <external-path name="external_files" path="."/>
<external-cache-path name="external_cache_files" path="."/>
<external-files-path name="private_external_files" path="."/>
</paths> </paths>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment