Commit bd00ae8e authored by Viktor De Pasquale's avatar Viktor De Pasquale

Updated Magisk fragment to Kotlin

Exported old update card to special xml include where binding takes care of everything that had to be done in code beforehand.
Added several easing functions and enums.
Backported some classes and functions from the old fork

Expect major breakage. Literally nothing works as the functionality needs to be implemented
parent f3095222
......@@ -2,10 +2,12 @@ package com.topjohnwu.magisk.di
import android.content.Context
import com.skoumal.teanity.rxbus.RxBus
import com.topjohnwu.magisk.App
import org.koin.dsl.module
val applicationModule = module {
single { RxBus() }
single { get<Context>().resources }
single { get<Context>() as App }
}
package com.topjohnwu.magisk.di
import com.topjohnwu.magisk.ui.MainViewModel
import com.topjohnwu.magisk.ui.home.HomeViewModel
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module
val viewModelModules = module {
viewModel { MainViewModel() }
viewModel { HomeViewModel(get(), get()) }
}
package com.topjohnwu.magisk.model.events
import com.skoumal.teanity.viewevents.ViewEvent
data class OpenLinkEvent(val url: String) : ViewEvent()
object ManagerInstallEvent : ViewEvent()
object MagiskInstallEvent : ViewEvent()
object ManagerChangelogEvent : ViewEvent()
object MagiskChangelogEvent : ViewEvent()
object UninstallEvent : ViewEvent()
package com.topjohnwu.magisk.model.observer
import androidx.databinding.Observable
import androidx.databinding.ObservableField
import java.io.Serializable
class Observer<T>(vararg dependencies: Observable, private val observer: () -> T) :
ObservableField<T>(*dependencies), Serializable {
val value: T get() = observer()
@Deprecated(
message = "Use KObservableField.value syntax from code",
replaceWith = ReplaceWith("value")
)
override fun get(): T {
return value
}
@Deprecated(
message = "Observer cannot be set",
level = DeprecationLevel.HIDDEN
)
override fun set(newValue: T) {
}
override fun toString(): String {
return "Observer(value=$value)"
}
}
\ No newline at end of file
package com.topjohnwu.magisk.ui.base
import androidx.core.net.toUri
import androidx.databinding.ViewDataBinding
import com.skoumal.teanity.view.TeanityActivity
import com.topjohnwu.magisk.utils.Utils
abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBinding> :
TeanityActivity<ViewModel, Binding>()
TeanityActivity<ViewModel, Binding>() {
fun openUrl(url: String) = Utils.openLink(this, url.toUri())
}
......@@ -5,4 +5,12 @@ import com.skoumal.teanity.view.TeanityFragment
abstract class MagiskFragment<ViewModel : MagiskViewModel, Binding : ViewDataBinding> :
TeanityFragment<ViewModel, Binding>()
TeanityFragment<ViewModel, Binding>() {
protected val magiskActivity get() = activity as MagiskActivity<*, *>
fun openLink(url: String) {
magiskActivity.openUrl(url)
}
}
package com.topjohnwu.magisk.ui.base
import com.skoumal.teanity.viewmodel.TeanityViewModel
import com.skoumal.teanity.viewmodel.LoadingViewModel
abstract class MagiskViewModel : TeanityViewModel()
abstract class MagiskViewModel : LoadingViewModel()
package com.topjohnwu.magisk.ui.home
import android.content.res.Resources
import com.skoumal.teanity.util.KObservableField
import com.topjohnwu.magisk.App
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.events.*
import com.topjohnwu.magisk.model.observer.Observer
import com.topjohnwu.magisk.ui.base.MagiskViewModel
import com.topjohnwu.magisk.utils.toggle
class HomeViewModel(
private val resources: Resources,
private val app: App
) : MagiskViewModel() {
val isAdvancedExpanded = KObservableField(false)
val isForceEncryption = KObservableField(false /*todo*/)
val isKeepVerity = KObservableField(false /*todo*/)
private val prefsObserver = Observer(isForceEncryption, isKeepVerity) {
Config.keepEnc = isForceEncryption.value
Config.keepVerity = isKeepVerity.value
}
val magiskState = KObservableField(MagiskState.LOADING)
val magiskStateText = Observer(magiskState) {
@Suppress("WhenWithOnlyElse")
when (magiskState.value) {
MagiskState.NO_ROOT -> TODO()
MagiskState.NOT_INSTALLED -> TODO()
MagiskState.UP_TO_DATE -> TODO()
MagiskState.LOADING -> TODO()
MagiskState.OBSOLETE -> TODO()
}
}
val magiskCurrentVersion = KObservableField("")
val magiskLatestVersion = KObservableField("")
val magiskAdditionalInfo = Observer(magiskState) {
if (Config.get<Boolean>(Config.Key.COREONLY))
resources.getString(R.string.core_only_enabled)
else
""
}
val managerState = KObservableField(MagiskState.LOADING)
val managerStateText = Observer(managerState) {
@Suppress("WhenWithOnlyElse")
when (managerState.value) {
MagiskState.NO_ROOT -> TODO()
MagiskState.NOT_INSTALLED -> TODO()
MagiskState.UP_TO_DATE -> TODO()
MagiskState.LOADING -> TODO()
MagiskState.OBSOLETE -> TODO()
}
}
val managerCurrentVersion = KObservableField("")
val managerLatestVersion = KObservableField("")
val managerAdditionalInfo = Observer(managerState) {
if (app.packageName != BuildConfig.APPLICATION_ID)
"(${app.packageName})"
else
""
}
fun paypalPressed() = OpenLinkEvent(Const.Url.PAYPAL_URL).publish()
fun patreonPressed() = OpenLinkEvent(Const.Url.PATREON_URL).publish()
fun twitterPressed() = OpenLinkEvent(Const.Url.TWITTER_URL).publish()
fun githubPressed() = OpenLinkEvent(Const.Url.REPO_URL).publish()
fun xdaPressed() = OpenLinkEvent(Const.Url.XDA_THREAD).publish()
fun uninstallPressed() = UninstallEvent.publish()
fun refresh() {}
fun advancedPressed() = isAdvancedExpanded.toggle()
fun installPressed(item: MagiskItem) = when (item) {
MagiskItem.MANAGER -> ManagerInstallEvent.publish()
MagiskItem.MAGISK -> MagiskInstallEvent.publish()
}
fun cardPressed(item: MagiskItem) = when (item) {
MagiskItem.MANAGER -> ManagerChangelogEvent.publish()
MagiskItem.MAGISK -> MagiskChangelogEvent.publish()
}
}
package com.topjohnwu.magisk.ui.home
import com.skoumal.teanity.viewevents.ViewEvent
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.events.MagiskInstallEvent
import com.topjohnwu.magisk.model.events.ManagerInstallEvent
import com.topjohnwu.magisk.model.events.OpenLinkEvent
import com.topjohnwu.magisk.model.events.UninstallEvent
import com.topjohnwu.magisk.utils.Event
import com.topjohnwu.magisk.view.MarkDownWindow
import com.topjohnwu.magisk.view.dialogs.ManagerInstallDialog
import com.topjohnwu.magisk.view.dialogs.UninstallDialog
import org.koin.androidx.viewmodel.ext.android.viewModel
import com.topjohnwu.magisk.ui.base.MagiskFragment as NewMagiskFragment
class MagiskFragment : NewMagiskFragment<HomeViewModel, com.topjohnwu.magisk.databinding.FragmentMagiskBinding>() {
/*@BindView(R.id.swipeRefreshLayout)
internal var mSwipeRefreshLayout: SwipeRefreshLayout? = null
@BindView(R.id.linearLayout)
internal var root: LinearLayout? = null
@BindView(R.id.install_option_card)
internal var installOptionCard: CardView? = null
@BindView(R.id.keep_force_enc)
internal var keepEncChkbox: CheckBox? = null
@BindView(R.id.keep_verity)
internal var keepVerityChkbox: CheckBox? = null
@BindView(R.id.install_option_expand)
internal var optionExpandLayout: ViewGroup? = null
@BindView(R.id.arrow)
internal var arrow: ImageView? = null
@BindView(R.id.uninstall_button)
internal var uninstallButton: CardView? = null
@BindColor(R.color.red500)
internal var colorBad: Int = 0
@BindColor(R.color.green500)
internal var colorOK: Int = 0
@BindColor(R.color.yellow500)
internal var colorWarn: Int = 0
@BindColor(R.color.green500)
internal var colorNeutral: Int = 0
@BindColor(R.color.blue500)
internal var colorInfo: Int = 0*/
/*private var magisk: UpdateCardHolder? = null
private var manager: UpdateCardHolder? = null
private var safetyNet: SafetyNet? = null
private var transition: Transition? = null
private var optionExpand: Expandable? = null*/
override val layoutRes: Int = R.layout.fragment_magisk
override val viewModel: HomeViewModel by viewModel()
override fun onEventDispatched(event: ViewEvent) {
super.onEventDispatched(event)
when (event) {
is OpenLinkEvent -> openLink(event.url)
is ManagerInstallEvent -> installManager()
is MagiskInstallEvent -> installMagisk()
is UninstallEvent -> uninstall()
}
}
private fun installMagisk() {
// Show Manager update first
if (Config.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
ManagerInstallDialog(requireActivity()).show()
return
}
//FIXME dialog requires old base
//MagiskInstallDialog(requireActivity()).show()
}
private fun installManager() = ManagerInstallDialog(requireActivity()).show()
private fun uninstall() {
UninstallDialog(requireActivity()).show()
}
private fun changelogManager() {
MarkDownWindow.show(
requireActivity(), null,
resources.openRawResource(R.raw.changelog)
)
}
/*override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val v = inflater.inflate(R.layout.fragment_magisk, container, false)
requireActivity().setTitle(R.string.magisk)
//safetyNet = SafetyNet(v)
*//*transition = TransitionSet()
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.addTransition(Fade(Fade.OUT))
.addTransition(ChangeBounds())
.addTransition(Fade(Fade.IN))*//*
updateUI()
return v
}*/
private fun onRefresh() {
/*mSwipeRefreshLayout!!.isRefreshing = false
TransitionManager.beginDelayedTransition(root!!, transition)
safetyNet!!.reset()
magisk!!.reset()
manager!!.reset()*/
Config.loadMagiskInfo()
updateUI()
//FIXME requires old base
/*Event.reset(this)
Config.remoteMagiskVersionString = null
Config.remoteMagiskVersionCode = -1*/
shownDialog = false
// Trigger state check
/*if (Networking.checkNetworkStatus(app)) {
CheckUpdates.check()
}*/
}
private fun getListeningEvents(): IntArray {
return intArrayOf(Event.UPDATE_CHECK_DONE)
}
private fun onEvent(event: Int) {
updateCheckUI()
}
private fun updateUI() {
/*(requireActivity() as MainActivity).checkHideSection()
val image: Int
val color: Int
val status: String
if (Config.magiskVersionCode < 0) {
color = colorBad
image = R.drawable.ic_cancel
status = getString(R.string.magisk_version_error)
magisk!!.status.text = status
magisk!!.currentVersion.visibility = View.GONE
} else {
color = colorOK
image = R.drawable.ic_check_circle
status = getString(R.string.magisk)
magisk!!.currentVersion.text = getString(
R.string.current_installed,
String.format(
Locale.US, "v%s (%d)",
Config.magiskVersionString, Config.magiskVersionCode
)
)
}
magisk!!.statusIcon.setColorFilter(color)
magisk!!.statusIcon.setImageResource(image)
manager!!.statusIcon.setColorFilter(colorOK)
manager!!.statusIcon.setImageResource(R.drawable.ic_check_circle)
manager!!.currentVersion.text = getString(
R.string.current_installed,
String.format(
Locale.US, "v%s (%d)",
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE
)
)
if (!Networking.checkNetworkStatus(app)) {
// No network, updateCheckUI will not be triggered
magisk!!.status.text = status
manager!!.status.setText(R.string.app_name)
magisk!!.setValid(false)
manager!!.setValid(false)
}*/
}
private fun updateCheckUI() {
/*var image: Int
var color: Int
var status: String
var button = ""
if (Config.remoteMagiskVersionCode < 0) {
color = colorNeutral
image = R.drawable.ic_help
status = getString(R.string.invalid_update_channel)
} else {
magisk!!.latestVersion.text = getString(
R.string.latest_version,
String.format(
Locale.US, "v%s (%d)",
Config.remoteMagiskVersionString, Config.remoteMagiskVersionCode
)
)
if (Config.remoteMagiskVersionCode > Config.magiskVersionCode) {
color = colorInfo
image = R.drawable.ic_update
status = getString(R.string.magisk_update_title)
button = getString(R.string.update)
} else {
color = colorOK
image = R.drawable.ic_check_circle
status = getString(R.string.magisk_up_to_date)
button = getString(R.string.install)
}
}
if (Config.magiskVersionCode > 0) {
// Only override status if Magisk is installed
magisk!!.statusIcon.setImageResource(image)
magisk!!.statusIcon.setColorFilter(color)
magisk!!.status.text = status
magisk!!.install.text = button
}
if (Config.remoteManagerVersionCode < 0) {
color = colorNeutral
image = R.drawable.ic_help
status = getString(R.string.invalid_update_channel)
} else {
manager!!.latestVersion.text = getString(
R.string.latest_version,
String.format(
Locale.US, "v%s (%d)",
Config.remoteManagerVersionString, Config.remoteManagerVersionCode
)
)
if (Config.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
color = colorInfo
image = R.drawable.ic_update
status = getString(R.string.manager_update_title)
manager!!.install.setText(R.string.update)
} else {
color = colorOK
image = R.drawable.ic_check_circle
status = getString(R.string.manager_up_to_date)
manager!!.install.setText(R.string.install)
}
}
manager!!.statusIcon.setImageResource(image)
manager!!.statusIcon.setColorFilter(color)
manager!!.status.text = status
magisk!!.setValid(Config.remoteMagiskVersionCode > 0)
manager!!.setValid(Config.remoteManagerVersionCode > 0)
if (Config.remoteMagiskVersionCode < 0) {
// Hide install related components
installOptionCard!!.visibility = View.GONE
uninstallButton!!.visibility = View.GONE
} else {
// Show install related components
installOptionCard!!.visibility = View.VISIBLE
uninstallButton!!.visibility = if (Shell.rootAccess()) View.VISIBLE else View.GONE
}
if (!shownDialog && Config.magiskVersionCode > 0 &&
!Shell.su("env_check").exec().isSuccess
) {
shownDialog = true
EnvFixDialog(requireActivity()).show()
}*/
}
companion object {
private var shownDialog = false
}
}
package com.topjohnwu.magisk.ui.home
enum class MagiskItem {
MANAGER, MAGISK
}
package com.topjohnwu.magisk.ui.home
enum class MagiskState {
NO_ROOT, NOT_INSTALLED, UP_TO_DATE, OBSOLETE, LOADING
}
\ No newline at end of file
package com.topjohnwu.magisk.utils
import android.view.View
import androidx.annotation.DrawableRes
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.Toolbar
import androidx.databinding.BindingAdapter
......@@ -9,3 +11,8 @@ import androidx.databinding.BindingAdapter
fun setOnNavigationClickedListener(view: Toolbar, listener: View.OnClickListener) {
view.setNavigationOnClickListener(listener)
}
@BindingAdapter("srcCompat")
fun setImageResource(view: AppCompatImageView, @DrawableRes resId: Int) {
view.setImageResource(resId)
}
package com.topjohnwu.magisk.utils
import com.skoumal.teanity.util.KObservableField
fun KObservableField<Boolean>.toggle() {
value = !value
}
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.topjohnwu.magisk.ui.home.MagiskState" />
<import type="com.topjohnwu.magisk.R" />
<variable
name="item"
type="com.topjohnwu.magisk.ui.home.MagiskItem" />
<variable
name="state"
type="com.topjohnwu.magisk.ui.home.MagiskState" />
<variable
name="text"
type="String" />
<variable
name="currentVersion"
type="String" />
<variable
name="latestVersion"
type="String" />
<variable
name="additionalInfo"
type="String" />
<variable
name="viewModel"
type="com.topjohnwu.magisk.ui.home.HomeViewModel" />
</data>
<androidx.cardview.widget.CardView
style="?attr/cardStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="4dp"
android:foreground="?android:attr/selectableItemBackground"
android:onClick="@{() -> viewModel.cardPressed(item)}"
app:cardCornerRadius="@dimen/card_corner_radius"
app:cardElevation="@dimen/card_elevation">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="12dp"
android:paddingBottom="12dp">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/install"
gone="@{state == MagiskState.LOADING}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:onClick="@{() -> viewModel.installPressed(item)}"
android:text="@{state != MagiskState.OBSOLETE ? @string/install : @string/update}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/install" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/status_icon"
invisible="@{state == MagiskState.LOADING}"
srcCompat="@{state == MagiskState.UP_TO_DATE ? R.drawable.ic_check_circle : (state == MagiskState.OBSOLETE ? R.drawable.ic_update : R.drawable.ic_help)}"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/status"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/progress"
gone="state != MagiskState.LOADING"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="@+id/status_icon"
app:layout_constraintEnd_toEndOf="@+id/status_icon"
app:layout_constraintStart_toStartOf="@+id/status_icon"
app:layout_constraintTop_toTopOf="@+id/status_icon" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/current_version"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@{state != MagiskState.LOADING ? currentVersion : @string/checking_for_updates}"
app:autoSizeMinTextSize="1sp"
app:autoSizeTextType="uniform"
app:layout_constraintEnd_toEndOf="@+id/status"
app:layout_constraintStart_toStartOf="@+id/status"
app:layout_constraintTop_toBottomOf="@+id/status"
tools:text="@string/checking_for_updates" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/latest_version"
gone="@{currentVersion == latestVersion}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@{state != MagiskState.LOADING ? latestVersion : @string/checking_for_updates}"
app:autoSizeMinTextSize="1sp"
app:autoSizeTextType="uniform"
app:layout_constraintEnd_toEndOf="@+id/status"
app:layout_constraintStart_toStartOf="@+id/status"
app:layout_constraintTop_toBottomOf="@+id/current_version"
tools:text="@string/checking_for_updates" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/additional"
gone="@{additionalInfo.length == 0}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@{additionalInfo}"
app:autoSizeMinTextSize="1sp"
app:autoSizeTextType="uniform"
app:layout_constraintEnd_toEndOf="@+id/status"
app:layout_constraintStart_toStartOf="@+id/status"
app:layout_constraintTop_toBottomOf="@+id/latest_version"
tools:text="@string/checking_for_updates" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/status"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:maxLines="1"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@{text}"
android:textAppearance="?android:attr/textAppearanceMedium"
app:autoSizeMinTextSize="1sp"
app:autoSizeTextType="uniform"
app:layout_constraintEnd_toStartOf="@+id/install"
app:layout_constraintStart_toEndOf="@+id/status_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="Magisk is up to date" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</layout>
......@@ -75,7 +75,6 @@
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@string/checking_for_updates"
android:visibility="gone"
app:autoSizeMinTextSize="1sp"
app:autoSizeTextType="uniform"
app:layout_constraintEnd_toEndOf="@+id/status"
......@@ -87,7 +86,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:visibility="gone"
app:autoSizeMinTextSize="1sp"
app:autoSizeTextType="uniform"
app:layout_constraintEnd_toEndOf="@+id/status"
......@@ -101,7 +99,6 @@
android:layout_marginEnd="8dp"
android:maxLines="1"
android:text="@string/install"
android:visibility="gone"
app:autoSizeMaxTextSize="14sp"
app:autoSizeTextType="uniform"
app:layout_constraintBottom_toBottomOf="parent"
......
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