From bd00ae8eded4804713e73212784ddf71c2985b68 Mon Sep 17 00:00:00 2001 From: Viktor De Pasquale Date: Sat, 13 Apr 2019 00:14:37 +0200 Subject: [PATCH] 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 --- .../topjohnwu/magisk/di/ApplicationModule.kt | 2 + .../topjohnwu/magisk/di/ViewModelsModule.kt | 2 + .../magisk/model/events/ViewEvents.kt | 14 + .../magisk/model/observer/Observer.kt | 31 + .../magisk/ui/base/MagiskActivity.kt | 8 +- .../magisk/ui/base/MagiskFragment.kt | 10 +- .../magisk/ui/base/MagiskViewModel.kt | 4 +- .../topjohnwu/magisk/ui/home/HomeViewModel.kt | 91 ++ .../magisk/ui/home/MagiskFragment.java | 332 ------- .../magisk/ui/home/MagiskFragment.kt | 279 ++++++ .../topjohnwu/magisk/ui/home/MagiskItem.kt | 6 + .../topjohnwu/magisk/ui/home/MagiskState.kt | 6 + .../magisk/utils/DataBindingAdapters.kt | 7 + .../com/topjohnwu/magisk/utils/XBinding.kt | 8 + app/src/main/res/layout/fragment_magisk.xml | 870 +++++++++--------- .../main/res/layout/include_update_card.xml | 160 ++++ app/src/main/res/layout/update_card.xml | 3 - 17 files changed, 1083 insertions(+), 750 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt create mode 100644 app/src/main/java/com/topjohnwu/magisk/model/observer/Observer.kt create mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.java create mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.kt create mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskItem.kt create mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskState.kt create mode 100644 app/src/main/java/com/topjohnwu/magisk/utils/XBinding.kt create mode 100644 app/src/main/res/layout/include_update_card.xml diff --git a/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt index 09fd26d68..dd5e7bebc 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt @@ -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().resources } + single { get() as App } } diff --git a/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt index 523a7bdfc..e4df34487 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt @@ -1,10 +1,12 @@ 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()) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt b/app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt new file mode 100644 index 000000000..bf405b0b3 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt @@ -0,0 +1,14 @@ +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() diff --git a/app/src/main/java/com/topjohnwu/magisk/model/observer/Observer.kt b/app/src/main/java/com/topjohnwu/magisk/model/observer/Observer.kt new file mode 100644 index 000000000..3f675dded --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/observer/Observer.kt @@ -0,0 +1,31 @@ +package com.topjohnwu.magisk.model.observer + +import androidx.databinding.Observable +import androidx.databinding.ObservableField +import java.io.Serializable + + +class Observer(vararg dependencies: Observable, private val observer: () -> T) : + ObservableField(*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 diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt index f93e766e0..d9b0a8c16 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt @@ -1,8 +1,14 @@ 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 : - TeanityActivity() + TeanityActivity() { + + fun openUrl(url: String) = Utils.openLink(this, url.toUri()) + +} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskFragment.kt index 024b00492..8d186a228 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskFragment.kt @@ -5,4 +5,12 @@ import com.skoumal.teanity.view.TeanityFragment abstract class MagiskFragment : - TeanityFragment() + TeanityFragment() { + + protected val magiskActivity get() = activity as MagiskActivity<*, *> + + fun openLink(url: String) { + magiskActivity.openUrl(url) + } + +} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskViewModel.kt index ca82d4039..c6f6ad86e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskViewModel.kt @@ -1,6 +1,6 @@ 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() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt new file mode 100644 index 000000000..f223c1087 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt @@ -0,0 +1,91 @@ +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(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() + } + +} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.java b/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.java deleted file mode 100644 index 4a1864214..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.java +++ /dev/null @@ -1,332 +0,0 @@ -package com.topjohnwu.magisk.ui.home; - -import android.net.Uri; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import com.topjohnwu.magisk.BuildConfig; -import com.topjohnwu.magisk.Config; -import com.topjohnwu.magisk.Const; -import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.tasks.CheckUpdates; -import com.topjohnwu.magisk.ui.MainActivity; -import com.topjohnwu.magisk.ui.base.BaseActivity; -import com.topjohnwu.magisk.ui.base.BaseFragment; -import com.topjohnwu.magisk.utils.Event; -import com.topjohnwu.magisk.utils.Utils; -import com.topjohnwu.magisk.view.ArrowExpandable; -import com.topjohnwu.magisk.view.Expandable; -import com.topjohnwu.magisk.view.ExpandableViewHolder; -import com.topjohnwu.magisk.view.MarkDownWindow; -import com.topjohnwu.magisk.view.SafetyNet; -import com.topjohnwu.magisk.view.UpdateCardHolder; -import com.topjohnwu.magisk.view.dialogs.EnvFixDialog; -import com.topjohnwu.magisk.view.dialogs.MagiskInstallDialog; -import com.topjohnwu.magisk.view.dialogs.ManagerInstallDialog; -import com.topjohnwu.magisk.view.dialogs.UninstallDialog; -import com.topjohnwu.net.Networking; -import com.topjohnwu.superuser.Shell; - -import java.util.Locale; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.cardview.widget.CardView; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import androidx.transition.ChangeBounds; -import androidx.transition.Fade; -import androidx.transition.Transition; -import androidx.transition.TransitionManager; -import androidx.transition.TransitionSet; -import butterknife.BindColor; -import butterknife.BindView; -import butterknife.OnClick; - -public class MagiskFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener { - - private static boolean shownDialog = false; - - @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; - @BindView(R.id.linearLayout) LinearLayout root; - - @BindView(R.id.install_option_card) CardView installOptionCard; - @BindView(R.id.keep_force_enc) CheckBox keepEncChkbox; - @BindView(R.id.keep_verity) CheckBox keepVerityChkbox; - @BindView(R.id.install_option_expand) ViewGroup optionExpandLayout; - @BindView(R.id.arrow) ImageView arrow; - - @BindView(R.id.uninstall_button) CardView uninstallButton; - - @BindColor(R.color.red500) int colorBad; - @BindColor(R.color.green500) int colorOK; - @BindColor(R.color.yellow500) int colorWarn; - @BindColor(R.color.green500) int colorNeutral; - @BindColor(R.color.blue500) int colorInfo; - - private UpdateCardHolder magisk; - private UpdateCardHolder manager; - private SafetyNet safetyNet; - private Transition transition; - private Expandable optionExpand; - - private void magiskInstall(View v) { - // Show Manager update first - if (Config.remoteManagerVersionCode > BuildConfig.VERSION_CODE) { - new ManagerInstallDialog(requireActivity()).show(); - return; - } - new MagiskInstallDialog((BaseActivity) requireActivity()).show(); - } - - private void managerInstall(View v) { - new ManagerInstallDialog(requireActivity()).show(); - } - - private void openLink(String url) { - Utils.openLink(requireActivity(), Uri.parse(url)); - } - - @OnClick(R.id.paypal) - void paypal() { - openLink(Const.Url.PAYPAL_URL); - } - - @OnClick(R.id.patreon) - void patreon() { - openLink(Const.Url.PATREON_URL); - } - - @OnClick(R.id.twitter) - void twitter() { - openLink(Const.Url.TWITTER_URL); - } - - @OnClick(R.id.github) - void github() { - openLink(Const.Url.SOURCE_CODE_URL); - } - - @OnClick(R.id.xda) - void xda() { - openLink(Const.Url.XDA_THREAD); - } - - @OnClick(R.id.uninstall_button) - void uninstall() { - new UninstallDialog(requireActivity()).show(); - } - - @OnClick(R.id.arrow) - void expandOptions() { - if (optionExpand.isExpanded()) - optionExpand.collapse(); - else optionExpand.expand(); - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_magisk, container, false); - unbinder = new MagiskFragment_ViewBinding(this, v); - requireActivity().setTitle(R.string.magisk); - - optionExpand = new ArrowExpandable(new ExpandableViewHolder(optionExpandLayout), arrow); - safetyNet = new SafetyNet(v); - magisk = new UpdateCardHolder(inflater, root); - manager = new UpdateCardHolder(inflater, root); - manager.setClickable(vv -> - MarkDownWindow.show(requireActivity(), null, - getResources().openRawResource(R.raw.changelog))); - root.addView(magisk.itemView, 1); - root.addView(manager.itemView, 2); - - keepVerityChkbox.setChecked(Config.keepVerity); - keepVerityChkbox.setOnCheckedChangeListener((view, checked) -> Config.keepVerity = checked); - keepEncChkbox.setChecked(Config.keepEnc); - keepEncChkbox.setOnCheckedChangeListener((view, checked) -> Config.keepEnc = checked); - - mSwipeRefreshLayout.setOnRefreshListener(this); - - magisk.install.setOnClickListener(this::magiskInstall); - manager.install.setOnClickListener(this::managerInstall); - if (Config.get(Config.Key.COREONLY)) { - magisk.additional.setText(R.string.core_only_enabled); - magisk.additional.setVisibility(View.VISIBLE); - } - if (!app.getPackageName().equals(BuildConfig.APPLICATION_ID)) { - manager.additional.setText("(" + app.getPackageName() + ")"); - manager.additional.setVisibility(View.VISIBLE); - } - - transition = new TransitionSet() - .setOrdering(TransitionSet.ORDERING_TOGETHER) - .addTransition(new Fade(Fade.OUT)) - .addTransition(new ChangeBounds()) - .addTransition(new Fade(Fade.IN)); - - updateUI(); - return v; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - safetyNet.unbinder.unbind(); - magisk.unbinder.unbind(); - manager.unbinder.unbind(); - } - - @Override - public void onRefresh() { - mSwipeRefreshLayout.setRefreshing(false); - TransitionManager.beginDelayedTransition(root, transition); - safetyNet.reset(); - magisk.reset(); - manager.reset(); - - Config.loadMagiskInfo(); - updateUI(); - - Event.reset(this); - Config.remoteMagiskVersionString = null; - Config.remoteMagiskVersionCode = -1; - - shownDialog = false; - - // Trigger state check - if (Networking.checkNetworkStatus(app)) { - CheckUpdates.check(); - } - } - - @Override - public int[] getListeningEvents() { - return new int[] {Event.UPDATE_CHECK_DONE}; - } - - @Override - public void onEvent(int event) { - updateCheckUI(); - } - - private void updateUI() { - ((MainActivity) requireActivity()).checkHideSection(); - int image, color; - String status; - if (Config.magiskVersionCode < 0) { - color = colorBad; - image = R.drawable.ic_cancel; - status = getString(R.string.magisk_version_error); - magisk.status.setText(status); - magisk.currentVersion.setVisibility(View.GONE); - } else { - color = colorOK; - image = R.drawable.ic_check_circle; - status = getString(R.string.magisk); - magisk.currentVersion.setText(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.setText(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.setText(status); - manager.status.setText(R.string.app_name); - magisk.setValid(false); - manager.setValid(false); - } - } - - private void updateCheckUI() { - int image, color; - String status, button = ""; - - TransitionManager.beginDelayedTransition(root, transition); - - if (Config.remoteMagiskVersionCode < 0) { - color = colorNeutral; - image = R.drawable.ic_help; - status = getString(R.string.invalid_update_channel); - } else { - magisk.latestVersion.setText(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.setText(status); - magisk.install.setText(button); - } - - if (Config.remoteManagerVersionCode < 0) { - color = colorNeutral; - image = R.drawable.ic_help; - status = getString(R.string.invalid_update_channel); - } else { - manager.latestVersion.setText(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.setText(status); - - magisk.setValid(Config.remoteMagiskVersionCode > 0); - manager.setValid(Config.remoteManagerVersionCode > 0); - - if (Config.remoteMagiskVersionCode < 0) { - // Hide install related components - installOptionCard.setVisibility(View.GONE); - uninstallButton.setVisibility(View.GONE); - } else { - // Show install related components - installOptionCard.setVisibility(View.VISIBLE); - uninstallButton.setVisibility(Shell.rootAccess() ? View.VISIBLE : View.GONE); - } - - if (!shownDialog && Config.magiskVersionCode > 0 && - !Shell.su("env_check").exec().isSuccess()) { - shownDialog = true; - new EnvFixDialog(requireActivity()).show(); - } - } -} - diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.kt new file mode 100644 index 000000000..77f435eea --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskFragment.kt @@ -0,0 +1,279 @@ +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() { + + /*@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 + } +} + diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskItem.kt b/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskItem.kt new file mode 100644 index 000000000..8f26b0c1d --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskItem.kt @@ -0,0 +1,6 @@ +package com.topjohnwu.magisk.ui.home + + +enum class MagiskItem { + MANAGER, MAGISK +} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskState.kt b/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskState.kt new file mode 100644 index 000000000..8d880001d --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/ui/home/MagiskState.kt @@ -0,0 +1,6 @@ +package com.topjohnwu.magisk.ui.home + + +enum class MagiskState { + NO_ROOT, NOT_INSTALLED, UP_TO_DATE, OBSOLETE, LOADING +} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt b/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt index f160e46ba..61d27118b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt @@ -1,6 +1,8 @@ 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) +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/XBinding.kt b/app/src/main/java/com/topjohnwu/magisk/utils/XBinding.kt new file mode 100644 index 000000000..ff9307a9e --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/utils/XBinding.kt @@ -0,0 +1,8 @@ +package com.topjohnwu.magisk.utils + +import com.skoumal.teanity.util.KObservableField + + +fun KObservableField.toggle() { + value = !value +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_magisk.xml b/app/src/main/res/layout/fragment_magisk.xml index a83e96333..10c6dd845 100644 --- a/app/src/main/res/layout/fragment_magisk.xml +++ b/app/src/main/res/layout/fragment_magisk.xml @@ -1,472 +1,520 @@ - + - + + + + + + + + + + + android:layout_height="fill_parent" + android:orientation="vertical" + app:onRefreshListener="@{() -> viewModel.refresh()}" + app:refreshing="@{viewModel.loading}"> - - - - - - - - - - - - - - + android:orientation="vertical"> - + - - + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_marginBottom="5dp"> + + + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toEndOf="@+id/icon" + app:layout_constraintTop_toTopOf="parent" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + android:layout_height="wrap_content"> - + + + + + + + + + + + + + + + android:paddingBottom="10dp"> + + + + + + + + + + + - - + - - - + android:layout_height="match_parent" + android:layout_marginStart="5dp" + android:layout_marginTop="4dp" + android:layout_marginEnd="5dp" + android:layout_marginBottom="4dp" + app:cardCornerRadius="@dimen/card_corner_radius" + app:cardElevation="@dimen/card_elevation"> - - - - - - - - - - - - - - - - - - - - - + app:layout_constraintTop_toBottomOf="@+id/paypal"> - + + + + + + + + + + + app:layout_constraintStart_toEndOf="@id/github"> + + + + + + + + + + + + + + + + + - + - - - - - + android:layout_height="match_parent" + android:layout_gravity="center" + android:layout_marginStart="5dp" + android:layout_marginTop="4dp" + android:layout_marginEnd="5dp" + android:layout_marginBottom="4dp" + android:clickable="true" + android:focusable="true" + android:foreground="?android:attr/selectableItemBackground" + android:onClick="@{() -> viewModel.uninstallPressed()}" + app:cardCornerRadius="@dimen/card_corner_radius" + app:cardElevation="@dimen/card_elevation"> - + android:layout_marginTop="10dp" + android:layout_marginBottom="10dp" + android:ems="10" + android:fontFamily="sans-serif" + android:gravity="center" + android:text="@string/uninstall" + android:textAllCaps="false" + android:textSize="20sp" + android:textStyle="bold" /> - + - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/app/src/main/res/layout/include_update_card.xml b/app/src/main/res/layout/include_update_card.xml new file mode 100644 index 000000000..03a6d003f --- /dev/null +++ b/app/src/main/res/layout/include_update_card.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/update_card.xml b/app/src/main/res/layout/update_card.xml index 103f62725..2fd143493 100644 --- a/app/src/main/res/layout/update_card.xml +++ b/app/src/main/res/layout/update_card.xml @@ -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"