Commit 14494869 authored by topjohnwu's avatar topjohnwu

Replace old design with redesign (p3)

parent 9094cf7c
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
-assumenosideeffects class timber.log.Timber.Tree { *; } -assumenosideeffects class timber.log.Timber.Tree { *; }
# Excessive obfuscation # Excessive obfuscation
-repackageclasses 'a' -repackageclasses a
-allowaccessmodification -allowaccessmodification
# QOL # QOL
......
package com.topjohnwu.magisk.base
import android.annotation.SuppressLint
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.preference.*
import androidx.recyclerview.widget.RecyclerView
import org.koin.android.ext.android.inject
abstract class BasePreferenceFragment : PreferenceFragmentCompat(),
SharedPreferences.OnSharedPreferenceChangeListener {
protected val prefs: SharedPreferences by inject()
protected val activity get() = requireActivity() as BaseActivity<*, *>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val v = super.onCreateView(inflater, container, savedInstanceState)
prefs.registerOnSharedPreferenceChangeListener(this)
return v
}
override fun onDestroyView() {
prefs.unregisterOnSharedPreferenceChangeListener(this)
super.onDestroyView()
}
private fun setAllPreferencesToAvoidHavingExtraSpace(preference: Preference) {
preference.isIconSpaceReserved = false
if (preference is PreferenceGroup)
for (i in 0 until preference.preferenceCount)
setAllPreferencesToAvoidHavingExtraSpace(preference.getPreference(i))
}
override fun setPreferenceScreen(preferenceScreen: PreferenceScreen?) {
if (preferenceScreen != null)
setAllPreferencesToAvoidHavingExtraSpace(preferenceScreen)
super.setPreferenceScreen(preferenceScreen)
}
override fun onCreateAdapter(preferenceScreen: PreferenceScreen?): RecyclerView.Adapter<*> =
object : PreferenceGroupAdapter(preferenceScreen) {
@SuppressLint("RestrictedApi")
override fun onPreferenceHierarchyChange(preference: Preference?) {
if (preference != null)
setAllPreferencesToAvoidHavingExtraSpace(preference)
super.onPreferenceHierarchyChange(preference)
}
}
}
...@@ -5,7 +5,7 @@ import androidx.databinding.PropertyChangeRegistry ...@@ -5,7 +5,7 @@ import androidx.databinding.PropertyChangeRegistry
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
/** /**
* Copy of [android.databinding.BaseObservable] which extends [ViewModel] * Copy of [androidx.databinding.BaseObservable] which extends [ViewModel]
*/ */
abstract class ObservableViewModel : TeanityViewModel(), Observable { abstract class ObservableViewModel : TeanityViewModel(), Observable {
...@@ -35,7 +35,7 @@ abstract class ObservableViewModel : TeanityViewModel(), Observable { ...@@ -35,7 +35,7 @@ abstract class ObservableViewModel : TeanityViewModel(), Observable {
/** /**
* Notifies listeners that a specific property has changed. The getter for the property * Notifies listeners that a specific property has changed. The getter for the property
* that changes should be marked with [android.databinding.Bindable] to generate a field in * that changes should be marked with [androidx.databinding.Bindable] to generate a field in
* `BR` to be used as `fieldId`. * `BR` to be used as `fieldId`.
* *
* @param fieldId The generated BR id for the Bindable field. * @param fieldId The generated BR id for the Bindable field.
...@@ -43,4 +43,4 @@ abstract class ObservableViewModel : TeanityViewModel(), Observable { ...@@ -43,4 +43,4 @@ abstract class ObservableViewModel : TeanityViewModel(), Observable {
fun notifyPropertyChanged(fieldId: Int) { fun notifyPropertyChanged(fieldId: Int) {
callbacks?.notifyCallbacks(this, fieldId, null) callbacks?.notifyCallbacks(this, fieldId, null)
} }
} }
\ No newline at end of file
...@@ -3,20 +3,16 @@ package com.topjohnwu.magisk.data.repository ...@@ -3,20 +3,16 @@ package com.topjohnwu.magisk.data.repository
import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.data.database.SuLogDao import com.topjohnwu.magisk.data.database.SuLogDao
import com.topjohnwu.magisk.model.entity.MagiskLog import com.topjohnwu.magisk.model.entity.MagiskLog
import com.topjohnwu.magisk.model.entity.WrappedMagiskLog
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Single import io.reactivex.Single
import java.util.concurrent.TimeUnit
class LogRepository( class LogRepository(
private val logDao: SuLogDao private val logDao: SuLogDao
) { ) {
fun fetchLogsNowrap() = logDao.fetchAll() fun fetchLogs() = logDao.fetchAll()
fun fetchLogs() = fetchLogsNowrap().map { it.wrap() }
fun fetchMagiskLogs() = Single.fromCallable { fun fetchMagiskLogs() = Single.fromCallable {
Shell.su("tail -n 5000 ${Const.MAGISK_LOG}").exec().out Shell.su("tail -n 5000 ${Const.MAGISK_LOG}").exec().out
...@@ -30,11 +26,4 @@ class LogRepository( ...@@ -30,11 +26,4 @@ class LogRepository(
fun insert(log: MagiskLog) = logDao.insert(log) fun insert(log: MagiskLog) = logDao.insert(log)
private fun List<MagiskLog>.wrap(): List<WrappedMagiskLog> {
val day = TimeUnit.DAYS.toMillis(1)
return groupBy { it.time / day }
.map { WrappedMagiskLog(it.key * day, it.value) }
}
} }
...@@ -286,7 +286,7 @@ fun Context.drawableCompat(@DrawableRes id: Int) = ContextCompat.getDrawable(thi ...@@ -286,7 +286,7 @@ fun Context.drawableCompat(@DrawableRes id: Int) = ContextCompat.getDrawable(thi
* with respect to RTL layout direction * with respect to RTL layout direction
*/ */
fun Context.startEndToLeftRight(start: Int, end: Int): Pair<Int, Int> { fun Context.startEndToLeftRight(start: Int, end: Int): Pair<Int, Int> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && if (SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
) { ) {
return end to start return end to start
...@@ -330,7 +330,7 @@ val isDeviceSecure: Boolean ...@@ -330,7 +330,7 @@ val isDeviceSecure: Boolean
} }
val securityLevelDate get() = securityLevelFormatter.parseOrNull(securityLevel) ?: Date(0) val securityLevelDate get() = securityLevelFormatter.parseOrNull(securityLevel) ?: Date(0)
val securityLevel val securityLevel
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { get() = if (SDK_INT >= Build.VERSION_CODES.M) {
Build.VERSION.SECURITY_PATCH Build.VERSION.SECURITY_PATCH
} else { } else {
null null
......
...@@ -114,13 +114,15 @@ open class DownloadService : RemoteFileService() { ...@@ -114,13 +114,15 @@ open class DownloadService : RemoteFileService() {
@Suppress("ReplaceSingleLineLet") @Suppress("ReplaceSingleLineLet")
private fun Notification.Builder.setContentIntent(intent: Intent) = private fun Notification.Builder.setContentIntent(intent: Intent) =
PendingIntent.getActivity(context, nextInt(), intent, PendingIntent.FLAG_ONE_SHOT) setContentIntent(
.let { setContentIntent(it) } PendingIntent.getActivity(context, nextInt(), intent, PendingIntent.FLAG_ONE_SHOT)
)
@Suppress("ReplaceSingleLineLet") @Suppress("ReplaceSingleLineLet")
private fun Notification.Builder.addAction(icon: Int, title: Int, intent: Intent) = private fun Notification.Builder.addAction(icon: Int, title: Int, intent: Intent) =
PendingIntent.getActivity(context, nextInt(), intent, PendingIntent.FLAG_ONE_SHOT) addAction(icon, getString(title),
.let { addAction(icon, getString(title), it) } PendingIntent.getActivity(context, nextInt(), intent, PendingIntent.FLAG_ONE_SHOT)
)
// --- // ---
......
...@@ -11,7 +11,6 @@ import com.topjohnwu.magisk.ui.flash.FlashActivity ...@@ -11,7 +11,6 @@ import com.topjohnwu.magisk.ui.flash.FlashActivity
class InstallExternalModuleEvent : ViewEvent(), ActivityExecutor { class InstallExternalModuleEvent : ViewEvent(), ActivityExecutor {
override fun invoke(activity: BaseActivity<*, *>) { override fun invoke(activity: BaseActivity<*, *>) {
activity as BaseActivity<*, *>
activity.withExternalRW { activity.withExternalRW {
onSuccess { onSuccess {
val intent = Intent(Intent.ACTION_GET_CONTENT) val intent = Intent(Intent.ACTION_GET_CONTENT)
......
...@@ -35,17 +35,6 @@ abstract class ViewEvent { ...@@ -35,17 +35,6 @@ abstract class ViewEvent {
var handled = false var handled = false
} }
data class OpenLinkEvent(val url: String) : ViewEvent()
class ManagerInstallEvent : ViewEvent()
class MagiskInstallEvent : ViewEvent()
class ManagerChangelogEvent : ViewEvent()
class MagiskChangelogEvent : ViewEvent()
class UninstallEvent : ViewEvent()
class EnvFixEvent : ViewEvent()
class UpdateSafetyNetEvent : ViewEvent(), ContextExecutor, KoinComponent, SafetyNetHelper.Callback { class UpdateSafetyNetEvent : ViewEvent(), ContextExecutor, KoinComponent, SafetyNetHelper.Callback {
private val magiskRepo by inject<MagiskRepository>() private val magiskRepo by inject<MagiskRepository>()
...@@ -130,21 +119,15 @@ class UpdateSafetyNetEvent : ViewEvent(), ContextExecutor, KoinComponent, Safety ...@@ -130,21 +119,15 @@ class UpdateSafetyNetEvent : ViewEvent(), ContextExecutor, KoinComponent, Safety
} }
class ViewActionEvent(val action: BaseActivity<*, *>.() -> Unit) : ViewEvent(), ActivityExecutor { class ViewActionEvent(val action: BaseActivity<*, *>.() -> Unit) : ViewEvent(), ActivityExecutor {
override fun invoke(activity: BaseActivity<*, *>) = (activity as BaseActivity<*, *>).run(action) override fun invoke(activity: BaseActivity<*, *>) = activity.run(action)
} }
class OpenFilePickerEvent : ViewEvent()
class OpenChangelogEvent(val item: Repo) : ViewEvent(), ContextExecutor { class OpenChangelogEvent(val item: Repo) : ViewEvent(), ContextExecutor {
override fun invoke(context: Context) { override fun invoke(context: Context) {
MarkDownWindow.show(context, null, item.readme) MarkDownWindow.show(context, null, item.readme)
} }
} }
class InstallModuleEvent(val item: Repo) : ViewEvent()
class PageChangedEvent : ViewEvent()
class PermissionEvent( class PermissionEvent(
val permissions: List<String>, val permissions: List<String>,
val callback: PublishSubject<Boolean> val callback: PublishSubject<Boolean>
......
...@@ -47,7 +47,7 @@ class LogViewModel( ...@@ -47,7 +47,7 @@ class LogViewModel(
val itemConsoleBinding = itemBindingOf<ComparableRvItem<*>> {} val itemConsoleBinding = itemBindingOf<ComparableRvItem<*>> {}
override fun refresh(): Disposable { override fun refresh(): Disposable {
val logs = repo.fetchLogsNowrap() val logs = repo.fetchLogs()
.map { it.map { LogItem(it) } } .map { it.map { LogItem(it) } }
.observeOn(Schedulers.computation()) .observeOn(Schedulers.computation())
.map { it to items.calculateDiff(it) } .map { it to items.calculateDiff(it) }
...@@ -110,4 +110,4 @@ class LogViewModel( ...@@ -110,4 +110,4 @@ class LogViewModel(
} }
.add() .add()
} }
\ No newline at end of file
...@@ -63,6 +63,7 @@ class RepoUpdater( ...@@ -63,6 +63,7 @@ class RepoUpdater(
private fun String.trimEtag() = substring(indexOf('\"'), lastIndexOf('\"') + 1) private fun String.trimEtag() = substring(indexOf('\"'), lastIndexOf('\"') + 1)
@Suppress("RedundantLambdaArrow")
operator fun invoke(forced: Boolean = false) : Single<Unit> { operator fun invoke(forced: Boolean = false) : Single<Unit> {
val cached = Collections.synchronizedSet(HashSet(repoDB.repoIDList)) val cached = Collections.synchronizedSet(HashSet(repoDB.repoIDList))
return loadPage(cached, etag = repoDB.etagKey).doOnComplete { return loadPage(cached, etag = repoDB.etagKey).doOnComplete {
......
...@@ -10,6 +10,7 @@ import androidx.core.view.get ...@@ -10,6 +10,7 @@ import androidx.core.view.get
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.topjohnwu.magisk.extensions.drawableCompat import com.topjohnwu.magisk.extensions.drawableCompat
import kotlin.math.roundToInt
class KItemDecoration( class KItemDecoration(
private val context: Context, private val context: Context,
...@@ -63,7 +64,7 @@ class KItemDecoration( ...@@ -63,7 +64,7 @@ class KItemDecoration(
.map { parent[it] } .map { parent[it] }
.forEach { child -> .forEach { child ->
parent.getDecoratedBoundsWithMargins(child, bounds) parent.getDecoratedBoundsWithMargins(child, bounds)
val bottom = bounds.bottom + Math.round(child.translationY) val bottom = bounds.bottom + child.translationY.roundToInt()
val top = bottom - drawable.intrinsicHeight val top = bottom - drawable.intrinsicHeight
drawable.setBounds(left, top, right, bottom) drawable.setBounds(left, top, right, bottom)
drawable.draw(canvas) drawable.draw(canvas)
...@@ -93,7 +94,7 @@ class KItemDecoration( ...@@ -93,7 +94,7 @@ class KItemDecoration(
.map { parent[it] } .map { parent[it] }
.forEach { child -> .forEach { child ->
parent.layoutManager!!.getDecoratedBoundsWithMargins(child, bounds) parent.layoutManager!!.getDecoratedBoundsWithMargins(child, bounds)
val right = bounds.right + Math.round(child.translationX) val right = bounds.right + child.translationX.roundToInt()
val left = right - drawable.intrinsicWidth val left = right - drawable.intrinsicWidth
drawable.setBounds(left, top, right, bottom) drawable.setBounds(left, top, right, bottom)
drawable.draw(canvas) drawable.draw(canvas)
...@@ -114,4 +115,4 @@ class KItemDecoration( ...@@ -114,4 +115,4 @@ class KItemDecoration(
} }
} }
} }
\ No newline at end of file
...@@ -12,10 +12,10 @@ interface SafetyNetHelper { ...@@ -12,10 +12,10 @@ interface SafetyNetHelper {
companion object { companion object {
val RESPONSE_ERR = 0x01 const val RESPONSE_ERR = 0x01
val CONNECTION_FAIL = 0x02 const val CONNECTION_FAIL = 0x02
val BASIC_PASS = 0x10 const val BASIC_PASS = 0x10
val CTS_PASS = 0x20 const val CTS_PASS = 0x20
} }
} }
package com.topjohnwu.magisk.view.dialogs
import android.content.Context
import android.content.DialogInterface
import android.view.LayoutInflater
import android.view.View
import androidx.annotation.StringRes
import androidx.annotation.StyleRes
import androidx.appcompat.app.AlertDialog
import com.topjohnwu.magisk.databinding.AlertDialogBinding
open class CustomAlertDialog : AlertDialog.Builder {
private var positiveListener: DialogInterface.OnClickListener? = null
private var negativeListener: DialogInterface.OnClickListener? = null
private var neutralListener: DialogInterface.OnClickListener? = null
protected var dialog: AlertDialog? = null
protected var binding: AlertDialogBinding =
AlertDialogBinding.inflate(LayoutInflater.from(context))
init {
super.setView(binding.root)
binding.message.visibility = View.GONE
binding.negative.visibility = View.GONE
binding.positive.visibility = View.GONE
binding.neutral.visibility = View.GONE
binding.buttonPanel.visibility = View.GONE
}
constructor(context: Context) : super(context)
constructor(context: Context, @StyleRes themeResId: Int) : super(context, themeResId)
override fun setView(layoutResId: Int): CustomAlertDialog {
return this
}
override fun setView(view: View): CustomAlertDialog {
return this
}
override fun setMessage(message: CharSequence?): CustomAlertDialog {
binding.message.visibility = View.VISIBLE
binding.message.text = message
return this
}
override fun setMessage(@StringRes messageId: Int): CustomAlertDialog {
return setMessage(context.getString(messageId))
}
override fun setPositiveButton(text: CharSequence, listener: DialogInterface.OnClickListener?): CustomAlertDialog {
binding.buttonPanel.visibility = View.VISIBLE
binding.positive.visibility = View.VISIBLE
binding.positive.text = text
positiveListener = listener
binding.positive.setOnClickListener {
positiveListener?.onClick(dialog, DialogInterface.BUTTON_POSITIVE)
dialog?.dismiss()
}
return this
}
override fun setPositiveButton(@StringRes textId: Int, listener: DialogInterface.OnClickListener?): CustomAlertDialog {
return setPositiveButton(context.getString(textId), listener)
}
override fun setNegativeButton(text: CharSequence, listener: DialogInterface.OnClickListener?): CustomAlertDialog {
binding.buttonPanel.visibility = View.VISIBLE
binding.negative.visibility = View.VISIBLE
binding.negative.text = text
negativeListener = listener
binding.negative.setOnClickListener {
negativeListener?.onClick(dialog, DialogInterface.BUTTON_NEGATIVE)
dialog?.dismiss()
}
return this
}
override fun setNegativeButton(@StringRes textId: Int, listener: DialogInterface.OnClickListener?): CustomAlertDialog {
return setNegativeButton(context.getString(textId), listener)
}
override fun setNeutralButton(text: CharSequence, listener: DialogInterface.OnClickListener?): CustomAlertDialog {
binding.buttonPanel.visibility = View.VISIBLE
binding.neutral.visibility = View.VISIBLE
binding.neutral.text = text
neutralListener = listener
binding.neutral.setOnClickListener {
neutralListener?.onClick(dialog, DialogInterface.BUTTON_NEUTRAL)
dialog?.dismiss()
}
return this
}
override fun setNeutralButton(@StringRes textId: Int, listener: DialogInterface.OnClickListener?): CustomAlertDialog {
return setNeutralButton(context.getString(textId), listener)
}
override fun create(): AlertDialog {
return super.create().apply { dialog = this }
}
override fun show(): AlertDialog {
return create().apply { show() }
}
fun dismiss() {
dialog?.dismiss()
}
}
package com.topjohnwu.magisk.view.dialogs
import android.app.Activity
import android.app.ProgressDialog
import android.widget.Toast
import androidx.core.net.toUri
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.cachedFile
import com.topjohnwu.magisk.extensions.reboot
import com.topjohnwu.magisk.net.Networking
import com.topjohnwu.magisk.tasks.MagiskInstaller
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils
import com.topjohnwu.superuser.internal.UiThreadHandler
import com.topjohnwu.superuser.io.SuFile
import java.io.File
class EnvFixDialog(activity: Activity) : CustomAlertDialog(activity) {
init {
setTitle(R.string.env_fix_title)
setMessage(R.string.env_fix_msg)
setCancelable(true)
setPositiveButton(android.R.string.yes) { _, _ ->
val pd = ProgressDialog.show(activity,
activity.getString(R.string.setup_title),
activity.getString(R.string.setup_msg))
object : MagiskInstaller() {
override fun operations(): Boolean {
installDir = SuFile("/data/adb/magisk")
Shell.su("rm -rf /data/adb/magisk/*").exec()
val zip : File = activity.cachedFile("magisk.zip")
if (!ShellUtils.checkSum("MD5", zip, Info.remote.magisk.md5))
Networking.get(Info.remote.magisk.link).execForFile(zip)
zipUri = zip.toUri()
return extractZip() && Shell.su("fix_env").exec().isSuccess
}
override fun onResult(success: Boolean) {
pd.dismiss()
Utils.toast(if (success) R.string.reboot_delay_toast else R.string.setup_fail, Toast.LENGTH_LONG)
if (success)
UiThreadHandler.handler.postDelayed({ reboot() }, 5000)
}
}.exec()
}
setNegativeButton(android.R.string.no, null)
}
}
package com.topjohnwu.magisk.view.dialogs
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.base.BaseActivity
import com.topjohnwu.magisk.model.download.DownloadService
import com.topjohnwu.magisk.model.entity.internal.Configuration
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.utils.Utils
internal class InstallMethodDialog(activity: BaseActivity<*, *>, options: List<String>) :
AlertDialog.Builder(activity) {
init {
setTitle(R.string.select_method)
setItems(options.toTypedArray()) { _, idx ->
when (idx) {
0 -> downloadOnly(activity)
1 -> patchBoot(activity)
2 -> flash(activity)
3 -> installInactiveSlot(activity)
}
}
}
private fun flash(activity: BaseActivity<*, *>) = DownloadService(activity) {
subject = DownloadSubject.Magisk(Configuration.Flash.Primary)
}
private fun patchBoot(activity: BaseActivity<*, *>) = activity.withExternalRW {
onSuccess {
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
val intent = Intent(Intent.ACTION_GET_CONTENT)
.setType("*/*")
.addCategory(Intent.CATEGORY_OPENABLE)
activity.startActivityForResult(intent, Const.ID.SELECT_BOOT) { resultCode, data ->
if (resultCode == Activity.RESULT_OK && data != null) {
DownloadService(activity) {
val safeData = data.data ?: Uri.EMPTY
subject = DownloadSubject.Magisk(Configuration.Patch(safeData))
}
}
}
}
}
private fun downloadOnly(activity: BaseActivity<*, *>) = activity.withExternalRW {
onSuccess {
DownloadService(activity) {
subject = DownloadSubject.Magisk(Configuration.Download)
}
}
}
private fun installInactiveSlot(activity: BaseActivity<*, *>) {
CustomAlertDialog(activity)
.setTitle(R.string.warning)
.setMessage(R.string.install_inactive_slot_msg)
.setCancelable(true)
.setPositiveButton(android.R.string.yes) { _, _ ->
DownloadService(activity) {
subject = DownloadSubject.Magisk(Configuration.Flash.Secondary)
}
}
.setNegativeButton(android.R.string.no, null)
.show()
}
}
package com.topjohnwu.magisk.view.dialogs
import android.net.Uri
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.base.BaseActivity
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.view.MarkDownWindow
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils
import java.util.*
class MagiskInstallDialog(a: BaseActivity<*, *>) : CustomAlertDialog(a) {
init {
val filename = "Magisk v${Info.remote.magisk.version}" +
"(${Info.remote.magisk.versionCode})"
setTitle(a.getString(R.string.repo_install_title, a.getString(R.string.magisk)))
setMessage(a.getString(R.string.repo_install_msg, filename))
setCancelable(true)
setPositiveButton(R.string.install) { _, _ ->
val options = ArrayList<String>()
options.add(a.getString(R.string.download_zip_only))
options.add(a.getString(R.string.select_patch_file))
if (Shell.rootAccess()) {
options.add(a.getString(R.string.direct_install))
val s = ShellUtils.fastCmd("grep_prop ro.build.ab_update")
if (s.isNotEmpty() && s.toBoolean()) {
options.add(a.getString(R.string.install_inactive_slot))
}
}
InstallMethodDialog(a, options).show()
}
if (Info.remote.magisk.note.isNotEmpty()) {
setNeutralButton(R.string.release_notes) { _, _ ->
if (Info.remote.magisk.note.contains("forum.xda-developers")) {
// Open forum links in browser
Utils.openLink(a, Uri.parse(Info.remote.magisk.note))
} else {
MarkDownWindow.show(a, null, Info.remote.magisk.note)
}
}
}
}
}
package com.topjohnwu.magisk.view.dialogs
import android.app.Activity
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.download.DownloadService
import com.topjohnwu.magisk.model.entity.internal.Configuration
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.view.MarkDownWindow
class ManagerInstallDialog(a: Activity) : CustomAlertDialog(a) {
init {
val subject = DownloadSubject.Manager(Configuration.APK.Upgrade)
setTitle(a.getString(R.string.repo_install_title, a.getString(R.string.app_name)))
setMessage(a.getString(R.string.repo_install_msg, subject.title))
setCancelable(true)
setPositiveButton(R.string.install) { _, _ ->
DownloadService(a) { this.subject = subject }
}
if (Info.remote.app.note.isNotEmpty()) {
setNeutralButton(R.string.app_changelog) { _, _ ->
MarkDownWindow.show(a, null, Info.remote.app.note) }
}
}
}
package com.topjohnwu.magisk.view.dialogs
import android.app.Activity
import android.app.ProgressDialog
import android.widget.Toast
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.download.DownloadService
import com.topjohnwu.magisk.model.entity.internal.Configuration
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.superuser.Shell
class UninstallDialog(activity: Activity) : CustomAlertDialog(activity) {
init {
setTitle(R.string.uninstall_magisk_title)
setMessage(R.string.uninstall_magisk_msg)
setNeutralButton(R.string.restore_img) { _, _ ->
val dialog = ProgressDialog.show(activity,
activity.getString(R.string.restore_img),
activity.getString(R.string.restore_img_msg))
Shell.su("restore_imgs").submit { result ->
dialog.cancel()
if (result.isSuccess) {
Utils.toast(R.string.restore_done, Toast.LENGTH_SHORT)
} else {
Utils.toast(R.string.restore_fail, Toast.LENGTH_LONG)
}
}
}
if (Info.remote.uninstaller.link.isNotEmpty()) {
setPositiveButton(R.string.complete_uninstall) { _, _ ->
DownloadService(activity) {
subject = DownloadSubject.Magisk(Configuration.Uninstall)
}
}
}
}
}
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