From f08d641fbeef4fdf70f5a6af669d372330f0c54b Mon Sep 17 00:00:00 2001 From: jaqxues <32979131+jaqxues@users.noreply.github.com> Date: Sat, 16 May 2020 00:02:35 +0200 Subject: [PATCH 01/28] Rewrite PackSelectorFragment --- app/build.gradle | 10 + .../Fragments/PackSelectorFragmentKt.kt | 173 ++++++++++++++++++ .../Framework/MetaData/LocalPackMetaData.java | 18 +- .../Framework/MetaData/PackMetaData.java | 7 + .../MetaData/ServerPackMetaData.java | 15 +- .../andre/snaptools/Utils/LiveDataUtils.kt | 42 +++++ .../com/ljmu/andre/snaptools/Utils/Result.kt | 26 +++ .../snaptools/repository/PackRepository.kt | 140 ++++++++++++++ .../snaptools/viewmodel/PackViewModel.kt | 75 ++++++++ 9 files changed, 495 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt create mode 100644 app/src/main/java/com/ljmu/andre/snaptools/Utils/LiveDataUtils.kt create mode 100644 app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.kt create mode 100644 app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt create mode 100644 app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt diff --git a/app/build.gradle b/app/build.gradle index b97d1a4..ef9aed2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,6 +119,16 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.exifinterface:exifinterface:1.2.0' testImplementation 'junit:junit:4.12' + + + def lifecycle_version = "2.2.0" + + // ViewModel and LiveData + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" + + // SU library implementation 'com.jaredrummler:android-shell:1.0.0' // Xposed diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt new file mode 100644 index 0000000..0ca79a1 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt @@ -0,0 +1,173 @@ +package com.ljmu.andre.snaptools.Fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewTreeObserver +import android.widget.Toast +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.ljmu.andre.snaptools.Dialogs.DialogFactory +import com.ljmu.andre.snaptools.Dialogs.ThemedDialog +import com.ljmu.andre.snaptools.EventBus.Events.PackDeleteEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest +import com.ljmu.andre.snaptools.EventBus.Events.PackLoadEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackUnloadEvent +import com.ljmu.andre.snaptools.Framework.FrameworkManager +import com.ljmu.andre.snaptools.Framework.MetaData.FailedPackMetaData +import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData +import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData +import com.ljmu.andre.snaptools.R +import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter +import com.ljmu.andre.snaptools.Utils.* +import com.ljmu.andre.snaptools.viewmodel.PackViewModel +import kotlinx.android.synthetic.main.frag_faq.* +import kotlinx.android.synthetic.main.frag_pack_selector.* +import timber.log.Timber + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 14:23. + */ + +class PackSelectorFragmentKt : FragmentHelper() { + val recycler: RecyclerView + get() { + check(runningTutorial) { "Only allowing getting PackView for Tutorials" } + return recycler_pack_selector + } + private lateinit var viewModel: PackViewModel + + override fun getMenuId() = null + + override fun getName() = TAG + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val layoutContainer = inflater.inflate(R.layout.frag_pack_selector, container, false) + viewModel = ViewModelProvider(this).get(PackViewModel::class.java) + + recycler_pack_selector.layoutManager = LinearLayoutManager(requireContext()) + + val adapter = ExpandableItemAdapter(emptyList()).apply { + bindToRecyclerView(recycler_pack_selector) + addType(PackMetaData.type, PackMetaData.layoutRes) + addType(ExpandableItemAdapter.TextItemEntity.type, ExpandableItemAdapter.TextItemEntity.layoutRes) + addType(LocalPackMetaData.type, LocalPackMetaData.layoutRes) + addType(FailedPackMetaData.FailedPackToolbar.type, FailedPackMetaData.layoutRes) + setEmptyView(R.layout.layout_empty_packs) + } + + // Listening to Packs in ViewModel + viewModel.localMetadata.observe(viewLifecycleOwner, Observer { packs -> + + // Animating + recycler_pack_selector.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + //At this point the layout is complete and the + //dimensions of recyclerView and any child views are known. + AnimationUtils.sequentGroup(recycler_pack_selector) + recycler_pack_selector.viewTreeObserver.removeOnGlobalLayoutListener(this) + } + }) + adapter.setNewData(packs) + swipe_refresh_layout.isRefreshing = false + }) + + swipe_refresh_layout.setOnRefreshListener { + if (runningTutorial) { + swipe_refresh_layout.isRefreshing = false + return@setOnRefreshListener + } + viewModel.refreshLocalPacks() + } + + viewModel.eventDispatcher.addEventObserver(viewLifecycleOwner, this::handlePackStateEvents) + return layoutContainer + } + + override fun onPause() { + super.onPause() + viewModel.clearPacks() + } + + override fun onResume() { + super.onResume() + + if (runningTutorial) viewModel.setTutorialPacks() + else viewModel.refreshLocalPacks() + } + + private fun handlePackStateEvents(packEvents: Any) { + when(packEvents) { + is PackLoadEvent -> updatePackState(packEvents.packName) + + is PackUnloadEvent -> updatePackState(packEvents.packMetaData.name) + + is PackDeleteEvent -> { + val idx = viewModel.getInfoFromName(packEvents.packName)!!.second + val adapter = recycler_pack_selector.adapter!! as ExpandableItemAdapter<*> + adapter.collapse(idx) + adapter.remove(idx) + } + + is PackEventRequest -> handlePackActions(packEvents) + } + } + + private fun handlePackActions(packRequest: PackEventRequest) { + when(packRequest.request) { + PackEventRequest.EventRequest.UNLOAD -> { + viewModel.unloadPack(packRequest.packName, requireActivity()) + } + PackEventRequest.EventRequest.LOAD -> { + viewModel.enablePack(packRequest.packName, requireActivity()).consumeResult { + if (it is Result.Error) { + FrameworkManager.addFailReason(packRequest.packName, it.exception.message) + updatePackState(packRequest.packName) + } + } + } + PackEventRequest.EventRequest.DELETE -> { + DialogFactory.createConfirmation( + requireActivity(), + "Confirm Action", + "Are you sure you wish to delete this pack?", + object: ThemedDialog.ThemedClickListener() { + override fun clicked(themedDialog: ThemedDialog) { + if (viewModel.deletePack(packRequest.packName, requireActivity()) is Result.Error) { + SafeToast.show(activity, "Failed to disable Pack: ${packRequest.packName}", Toast.LENGTH_LONG) + } + themedDialog.dismiss() + } + } + ) + } + else -> Timber.d("Ignoring unhandled request") + } + } + + private fun updatePackState(packName: String) { + var (_, idx) = viewModel.getInfoFromName(packName) ?: return + val adapter = recycler_pack_selector.adapter!! as ExpandableItemAdapter<*> + adapter.notifyItemChanged(idx) + var el = adapter.getItem(idx) + + if (el == null || !el.isExpanded) return + + while (++idx < adapter.itemCount) { + el = adapter.getItem(idx) + + if (el !is PackMetaData) + adapter.notifyItemChanged(idx) + else break + } + } + + companion object { + const val TAG = "Pack Selector" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java index 246aea6..682e8a8 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java @@ -17,6 +17,7 @@ import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter; import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.ExpandableItemEntity; import com.ljmu.andre.snaptools.Utils.PreferenceHelpers; +import kotlin.jvm.functions.Function1; import static android.view.View.GONE; import static com.ljmu.andre.snaptools.Utils.ContextHelper.getModuleResources; @@ -27,6 +28,10 @@ * It and its contents are free to use by all */ public class LocalPackMetaData extends PackMetaData { + public LocalPackMetaData(Function1 dispatcher) { + super(dispatcher); + } + @Override public void updateHeaderStateHolder(TextView stateHolder) { if (isActive()) { @@ -83,7 +88,7 @@ public int getLevel() { } public static LocalPackMetaData getTutorialPack(String scVersion) { - return (LocalPackMetaData) new LocalPackMetaData() + return (LocalPackMetaData) new LocalPackMetaData(null) .setScVersion(scVersion) .setPackVersion("1.0.0.0") .setLatest(true) @@ -95,8 +100,8 @@ public static LocalPackMetaData getTutorialPack(String scVersion) { .completedBinding(); } - public static LocalPackMetaData from(PackMetaData metaData) { - LocalPackMetaData localMetaData = new LocalPackMetaData(); + public LocalPackMetaData from(PackMetaData metaData, Function1 dispatcher) { + LocalPackMetaData localMetaData = new LocalPackMetaData(dispatcher); localMetaData.setName(metaData.getName()); localMetaData.setDevelopment(metaData.isDeveloper()); localMetaData.setPackVersion(metaData.getPackVersion()); @@ -107,7 +112,7 @@ public static LocalPackMetaData from(PackMetaData metaData) { return localMetaData; } - public static class LocalPackToolbarItem extends ExpandableItemEntity { + public class LocalPackToolbarItem extends ExpandableItemEntity { public static final int layoutRes = R.layout.pack_toolbar_local; public static final int type = 2; public final int level; @@ -147,7 +152,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { )); delete.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.invoke( new PackEventRequest( EventRequest.DELETE, linkedMeta.getName() @@ -162,7 +167,8 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { )); toggle.setOnCheckedChangeListener( - (buttonView, isChecked) -> EventBus.getInstance().post( + + (buttonView, isChecked) -> eventDispatcher.invoke( new PackEventRequest( isChecked ? EventRequest.LOAD : EventRequest.UNLOAD, linkedMeta.getName() diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java index 9dfac1a..0619b57 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java @@ -10,6 +10,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.gson.annotations.SerializedName; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Framework.FrameworkManager; import com.ljmu.andre.snaptools.Framework.ModulePack; import com.ljmu.andre.snaptools.R; @@ -21,6 +22,7 @@ import com.ljmu.andre.snaptools.Utils.Assert; import com.ljmu.andre.snaptools.Utils.RequiresFramework; +import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -38,6 +40,11 @@ public abstract class PackMetaData extends ExpandableItemEntity implements StatefulListable, Comparable { public static final int layoutRes = R.layout.item_listable_head_stateful; public static final int type = 0; + protected final Function1 eventDispatcher; + + public PackMetaData(Function1 dispatcher) { + eventDispatcher = dispatcher; + } /** * =========================================================================== diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java index 044adfe..5e1a35e 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java @@ -21,6 +21,7 @@ import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.TextItemEntity; import com.ljmu.andre.snaptools.Utils.RequiresFramework; +import kotlin.jvm.functions.Function1; import timber.log.Timber; import static com.ljmu.andre.snaptools.Utils.ContextHelper.getModuleResources; @@ -45,8 +46,12 @@ public class ServerPackMetaData extends PackMetaData { @SerializedName("is_purchased") private Boolean isPurchased; + public ServerPackMetaData(Function1 dispatcher) { + super(dispatcher); + } + public static ServerPackMetaData getTutorialPack(String scVersion) { - return (ServerPackMetaData) new ServerPackMetaData() + return (ServerPackMetaData) new ServerPackMetaData(null) .setPurchased(false) .setDescription(htmlHighlight("Tutorial Item")) .setHasUpdate(false) @@ -203,7 +208,7 @@ public ServerPackMetaData setPurchased(@Nullable Boolean isPurchased) { return this; } - public static class ServerPackToolbarItem extends ExpandableItemEntity { + public class ServerPackToolbarItem extends ExpandableItemEntity { public static final int layoutRes = R.layout.pack_toolbar_server; public static final int type = 2; public final int level; @@ -236,7 +241,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { download.setImageTintList(ContextCompat.getColorStateList(holder.itemView.getContext(), R.color.textPrimary)); download.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.invoke( new PackEventRequest( eventType, linkedMeta.getName() @@ -249,7 +254,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { if (!linkedMeta.isTutorial()) { rollback.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.invoke( new PackEventRequest( EventRequest.SHOW_ROLLBACK, linkedMeta.getName() @@ -258,7 +263,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { ); changelog.setOnClickListener( - v -> EventBus.getInstance().post( + v -> eventDispatcher.invoke( new PackEventRequest( EventRequest.SHOW_CHANGELOG, linkedMeta.getName() diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/LiveDataUtils.kt b/app/src/main/java/com/ljmu/andre/snaptools/Utils/LiveDataUtils.kt new file mode 100644 index 0000000..93ca718 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/LiveDataUtils.kt @@ -0,0 +1,42 @@ +package com.ljmu.andre.snaptools.Utils + +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 15.05.20 - Time 15:20. + * + * Allows to handle Events in multiple observers, without handling an Event twice + */ +abstract class EventObserver : Observer { + var lastChecked = 0 + final override fun onChanged(t: T) { + // Only handle event once + if (lastChecked == t.hashCode()) + return + handleEvent(t) + lastChecked = t.hashCode() + } + + abstract fun handleEvent(t: T) +} + +inline fun LiveData.addEventObserver(lifecycleOwner: LifecycleOwner, crossinline handler: (T) -> Unit) { + observe(lifecycleOwner, object: EventObserver() { + override fun handleEvent(t: T) { + handler(t) + } + }) +} + +inline fun LiveData.consumeResult(crossinline action: (T) -> Unit) { + observeForever(object: Observer { + override fun onChanged(t: T) { + removeObserver(this) + action(t) + } + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.kt b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.kt new file mode 100644 index 0000000..13d6125 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.kt @@ -0,0 +1,26 @@ +package com.ljmu.andre.snaptools.Utils + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import timber.log.Timber + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 14:20. + */ + +sealed class Result { + data class Success(val data: T) : Result() + data class Error(val exception: Exception) : Result() +} + +sealed class Request { + object Pending : Request() + class Loaded(val result: Result) : Request() +} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt new file mode 100644 index 0000000..7dc9aa1 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt @@ -0,0 +1,140 @@ +package com.ljmu.andre.snaptools.repository + +import android.app.Activity +import androidx.annotation.WorkerThread +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.ljmu.andre.GsonPreferences.Preferences.getPref +import com.ljmu.andre.snaptools.EventBus.Events.PackDeleteEvent +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest +import com.ljmu.andre.snaptools.EventBus.Events.PackUnloadEvent +import com.ljmu.andre.snaptools.Framework.FrameworkManager +import com.ljmu.andre.snaptools.Framework.MetaData.FailedPackMetaData +import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData +import com.ljmu.andre.snaptools.Framework.Utils.PackLoadState +import com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.MODULES_PATH +import com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS +import com.ljmu.andre.snaptools.Utils.PackUtils.getPackMetaData +import com.ljmu.andre.snaptools.Utils.PreferenceHelpers +import com.ljmu.andre.snaptools.Utils.Result +import timber.log.Timber +import java.io.File + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 10:01. + */ +class PackRepository { + // Private Mutable LiveData + private val _eventDispatcher = MutableLiveData() + private val _localMetadata = MutableLiveData>() + // Exposed public LiveData + val eventDispatcher: LiveData = _eventDispatcher + val localMetadata: LiveData> = _localMetadata + + private val packDirectory = File(getPref(MODULES_PATH) as String) + + fun fireFromMetadata(evt: PackEventRequest) { + _eventDispatcher.value = evt + } + + fun refreshLocalMetadata() { + val jarFileList = packDirectory.listFiles { _, name -> name.endsWith(".jar") } + if (jarFileList.isNullOrEmpty()) _localMetadata.postValue(emptyList()) + + val packs = jarFileList.associate { file -> + val metadata = try { + getPackMetaData(file) + } catch (t: Throwable) { + FailedPackMetaData().run { + reason = t.message + name = file.name.replace(".jar", "") + completedBinding() + } + } + metadata.name to metadata + } + + val packsList = packs.values.toMutableList() + + // Selected Packs that have been deleted or cannot be found for some reason + getPref>(SELECTED_PACKS).forEach { packName -> + if (packName in packs) return@forEach + + val failedMetadata = FailedPackMetaData().run { + reason = "Pack is enabled but cannot be found in the installed list" + name = packName + completedBinding() + } + packsList.add(failedMetadata) + } + + _localMetadata.postValue(packsList.sorted()) + } + + fun unloadPack(packName: String, activity: Activity): Result { + val modPack = FrameworkManager.getModulePack(packName) + if (modPack == null) { + val e = IllegalStateException("Pack was not loaded. Could not unload it") + Timber.e(e) + return Result.Error(e) + } + if (FrameworkManager.unloadModPack(packName)) { + _eventDispatcher.value = PackUnloadEvent(modPack.packMetaData) + return Result.Success(packName) + } + return Result.Error(Exception("Unknown Exception while trying to unload the Pack $packName")) + } + + fun disablePack(packName: String, activity: Activity): Result { + val result = unloadPack(packName, activity) + if (result is Result.Error) + return result + FrameworkManager.disableModPack(packName) + return Result.Success(packName) + } + + /** + * Unloads, disables and deletes the pack + */ + fun deletePack(packName: String, activity: Activity): Result { + val result = disablePack(packName, activity) + if (result is Result.Error) + return result + FrameworkManager.deleteModPack(packName, activity) + + if (PreferenceHelpers.collectionContains(SELECTED_PACKS, packName)) { + val e = IllegalStateException("Failed to delete Pack $packName") + Timber.e(e) + return Result.Error(e) + } + _eventDispatcher.value = PackDeleteEvent(packName) + refreshLocalMetadata() + return Result.Success(packName) + } + + /** + * Download Pack and update LiveData + */ + fun downloadPack() { + } + + fun setTutorialPacks() { + _localMetadata.value = + listOf("10.0.0.0", "10.1.0.1", "10.12.1.0", "10.16.0.0").map { + LocalPackMetaData.getTutorialPack(it) + } + } + + fun clear() { + _localMetadata.value = emptyList() + } + + @WorkerThread + fun enablePack(packName: String, activity: Activity) { + PreferenceHelpers.addToCollection(SELECTED_PACKS, packName, activity) + val packLoadEvent = FrameworkManager.loadModPack(activity, packName, PackLoadState(packName)) + _eventDispatcher.postValue(packLoadEvent) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt b/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt new file mode 100644 index 0000000..e3efbe8 --- /dev/null +++ b/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt @@ -0,0 +1,75 @@ +package com.ljmu.andre.snaptools.viewmodel + +import android.app.Activity +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData +import com.ljmu.andre.snaptools.Utils.Result +import com.ljmu.andre.snaptools.repository.PackRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import timber.log.Timber + + +/** + * This file was created by Jacques Hoffmann (jaqxues) in the Project SnapTools.
+ * Date: 13.05.20 - Time 10:40. + */ +class PackViewModel : ViewModel() { + val localMetadata: LiveData> + get() = packRepo.localMetadata + val eventDispatcher: LiveData + get() = packRepo.eventDispatcher + + fun refreshLocalPacks() { + viewModelScope.launch(Dispatchers.IO) { + packRepo.refreshLocalMetadata() + } + } + + fun setTutorialPacks() { + packRepo.setTutorialPacks() + } + + fun clearPacks() { + packRepo.clear() + } + + fun getInfoFromName(packName: String): Pair? { + val packs = localMetadata.value + return packs?.find { it.name == packName }?.let { + it to packs.indexOf(it) + } + } + + fun enablePack(packName: String, activity: Activity): LiveData> { + val liveData = MutableLiveData>() + viewModelScope.launch(Dispatchers.Default) { + liveData.postValue( + try { + packRepo.enablePack(packName, activity) + Result.Success(packName) + } catch (e: Exception) { + Timber.e(e, "Could not load Pack") + Result.Error(e) + }) + } + return liveData + } + + fun unloadPack(packName: String, activity: Activity) = packRepo.unloadPack(packName, activity) + + fun deletePack(packName: String, activity: Activity) = packRepo.deletePack(packName, activity) + + fun downloadPack() { + viewModelScope.launch(Dispatchers.IO) { + packRepo.downloadPack() + } + } + + companion object { + private val packRepo by lazy { PackRepository() } + } +} \ No newline at end of file From df67a83f151ce1f251d3b99e930f5b7fbd074efd Mon Sep 17 00:00:00 2001 From: jaqxues <32979131+jaqxues@users.noreply.github.com> Date: Sat, 16 May 2020 23:48:34 +0200 Subject: [PATCH 02/28] Add PackEventRequest.EventHandler --- app/build.gradle | 2 +- .../EventBus/Events/PackEventRequest.java | 7 +++ .../Fragments/PackDownloaderFragment.java | 2 +- .../Fragments/PackSelectorFragmentKt.kt | 23 +++++-- .../MetaData/FailedPackMetaData.java | 13 ++-- .../Framework/MetaData/LocalPackMetaData.java | 9 +-- .../Framework/MetaData/PackMetaData.java | 7 +-- .../MetaData/PackUpdateMetaData.java | 2 + .../MetaData/ServerPackMetaData.java | 13 ++-- .../andre/snaptools/Framework/ModulePack.java | 3 +- .../Helpers/DownloadModulePack.java | 3 +- .../Networking/Helpers/GetServerPacks.java | 3 +- .../ljmu/andre/snaptools/Utils/PackUtils.java | 14 +++-- .../ljmu/andre/snaptools/Utils/Result.java | 63 ------------------- .../snaptools/repository/PackRepository.kt | 16 ++--- .../snaptools/viewmodel/PackViewModel.kt | 9 ++- 16 files changed, 75 insertions(+), 114 deletions(-) delete mode 100644 app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.java diff --git a/app/build.gradle b/app/build.gradle index ef9aed2..525fd76 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,7 +37,7 @@ android { } compileSdkVersion 28 - buildToolsVersion '30.0.0-rc3' + buildToolsVersion '30.0.0-rc4' android { lintOptions { abortOnError false diff --git a/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java b/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java index 9c06291..6280219 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/EventBus/Events/PackEventRequest.java @@ -1,6 +1,7 @@ package com.ljmu.andre.snaptools.EventBus.Events; import com.google.common.base.MoreObjects; +import timber.log.Timber; /** * This class was created by Andre R M (SID: 701439) @@ -46,4 +47,10 @@ public String toString() { public enum EventRequest { UNLOAD, LOAD, DELETE, DOWNLOAD, DOWNLOAD_TUTORIAL, SHOW_ROLLBACK, SHOW_CHANGELOG } + + public interface EventHandler { + void handleEvent(PackEventRequest packEventRequest); + + EventHandler ignoreEvents = packEventRequest -> Timber.d("Ignoring event #%d", packEventRequest.request.ordinal()); + } } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java index b488508..4c9a2c7 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackDownloaderFragment.java @@ -262,7 +262,7 @@ public void generateTutorialData() { List tutorialDataList = new ArrayList<>(tutorialVersions.size()); for (String tutorialVersion : tutorialVersions) - tutorialDataList.add(ServerPackMetaData.getTutorialPack(tutorialVersion)); + tutorialDataList.add(ServerPackMetaData.getTutorialPack(tutorialVersion, PackEventRequest.EventHandler.ignoreEvents)); setPacks(tutorialDataList); } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt index 0ca79a1..160cc23 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt @@ -40,6 +40,7 @@ class PackSelectorFragmentKt : FragmentHelper() { check(runningTutorial) { "Only allowing getting PackView for Tutorials" } return recycler_pack_selector } + private val evtHandler = PackEventRequest.EventHandler { handlePackActions(it) } private lateinit var viewModel: PackViewModel override fun getMenuId() = null @@ -82,10 +83,9 @@ class PackSelectorFragmentKt : FragmentHelper() { swipe_refresh_layout.isRefreshing = false return@setOnRefreshListener } - viewModel.refreshLocalPacks() + viewModel.refreshLocalPacks(evtHandler) } - viewModel.eventDispatcher.addEventObserver(viewLifecycleOwner, this::handlePackStateEvents) return layoutContainer } @@ -98,7 +98,7 @@ class PackSelectorFragmentKt : FragmentHelper() { super.onResume() if (runningTutorial) viewModel.setTutorialPacks() - else viewModel.refreshLocalPacks() + else viewModel.refreshLocalPacks(evtHandler) } private fun handlePackStateEvents(packEvents: Any) { @@ -132,15 +132,26 @@ class PackSelectorFragmentKt : FragmentHelper() { } } PackEventRequest.EventRequest.DELETE -> { + fun deletePack() { + if (viewModel.deletePack(packRequest.packName, requireActivity(), evtHandler) is Result.Error) { + SafeToast.show(activity, "Failed to disable Pack: ${packRequest.packName}", Toast.LENGTH_LONG) + } + } + val pack = viewModel.localMetadata.value?.find { packRequest.packName == it.name } + ?: throw IllegalStateException("Pack to delete was not found") + + // If the Pack has failed to load, delete without confirmation + if (pack is FailedPackMetaData) { + deletePack() + return + } DialogFactory.createConfirmation( requireActivity(), "Confirm Action", "Are you sure you wish to delete this pack?", object: ThemedDialog.ThemedClickListener() { override fun clicked(themedDialog: ThemedDialog) { - if (viewModel.deletePack(packRequest.packName, requireActivity()) is Result.Error) { - SafeToast.show(activity, "Failed to disable Pack: ${packRequest.packName}", Toast.LENGTH_LONG) - } + deletePack() themedDialog.dismiss() } } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java index 6c9c039..10725c9 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/FailedPackMetaData.java @@ -20,6 +20,10 @@ public class FailedPackMetaData extends LocalPackMetaData { private String reason; + public FailedPackMetaData(PackEventRequest.EventHandler dispatcher) { + super(dispatcher); + } + @Override public String getDisplayName() { return getName(); @@ -44,7 +48,7 @@ public FailedPackMetaData setReason(String reason) { return this; } - public static class FailedPackToolbar extends ExpandableItemEntity { + public class FailedPackToolbar extends ExpandableItemEntity { public static final int layoutRes = R.layout.failed_pack_toolbar; public static final int type = 3; private FailedPackMetaData linkedMeta; @@ -69,14 +73,15 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { ImageButton disableBtn = (ImageButton) holder.itemView.findViewById(R.id.btn_delete); disableBtn.setOnClickListener( v -> { - EventBus.getInstance().post( + eventDispatcher.handleEvent( new PackEventRequest( EventRequest.UNLOAD, linkedMeta.getName() )); - EventBus.getInstance().post( - new PackDeleteEvent( + eventDispatcher.handleEvent( + new PackEventRequest( + EventRequest.DELETE, linkedMeta.getName() )); } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java index 682e8a8..2956f32 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/LocalPackMetaData.java @@ -28,7 +28,8 @@ * It and its contents are free to use by all */ public class LocalPackMetaData extends PackMetaData { - public LocalPackMetaData(Function1 dispatcher) { + + public LocalPackMetaData(PackEventRequest.EventHandler dispatcher) { super(dispatcher); } @@ -100,7 +101,7 @@ public static LocalPackMetaData getTutorialPack(String scVersion) { .completedBinding(); } - public LocalPackMetaData from(PackMetaData metaData, Function1 dispatcher) { + public LocalPackMetaData from(PackMetaData metaData, PackEventRequest.EventHandler dispatcher) { LocalPackMetaData localMetaData = new LocalPackMetaData(dispatcher); localMetaData.setName(metaData.getName()); localMetaData.setDevelopment(metaData.isDeveloper()); @@ -152,7 +153,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { )); delete.setOnClickListener( - v -> eventDispatcher.invoke( + v -> eventDispatcher.handleEvent( new PackEventRequest( EventRequest.DELETE, linkedMeta.getName() @@ -168,7 +169,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { toggle.setOnCheckedChangeListener( - (buttonView, isChecked) -> eventDispatcher.invoke( + (buttonView, isChecked) -> eventDispatcher.handleEvent( new PackEventRequest( isChecked ? EventRequest.LOAD : EventRequest.UNLOAD, linkedMeta.getName() diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java index 0619b57..d860712 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackMetaData.java @@ -3,7 +3,6 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; - import com.chad.library.adapter.base.BaseViewHolder; import com.chad.library.adapter.base.entity.MultiItemEntity; import com.g00fy2.versioncompare.Version; @@ -21,8 +20,6 @@ import com.ljmu.andre.snaptools.Utils.AnimationUtils; import com.ljmu.andre.snaptools.Utils.Assert; import com.ljmu.andre.snaptools.Utils.RequiresFramework; - -import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -40,9 +37,9 @@ public abstract class PackMetaData extends ExpandableItemEntity implements StatefulListable, Comparable { public static final int layoutRes = R.layout.item_listable_head_stateful; public static final int type = 0; - protected final Function1 eventDispatcher; + protected final PackEventRequest.EventHandler eventDispatcher; - public PackMetaData(Function1 dispatcher) { + public PackMetaData(PackEventRequest.EventHandler dispatcher) { eventDispatcher = dispatcher; } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java index e33637d..269f1f1 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/PackUpdateMetaData.java @@ -4,6 +4,7 @@ import android.widget.TextView; import com.chad.library.adapter.base.BaseViewHolder; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.R; import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter; @@ -25,6 +26,7 @@ public abstract class PackUpdateMetaData extends PackMetaData { private boolean hasUpdate; public PackUpdateMetaData(String name) { + super(PackEventRequest.EventHandler.ignoreEvents); setName(name); } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java index 5e1a35e..228f26c 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/MetaData/ServerPackMetaData.java @@ -7,6 +7,7 @@ import android.widget.ImageView; import android.widget.TextView; +import androidx.core.view.KeyEventDispatcher; import com.chad.library.adapter.base.BaseViewHolder; import com.google.gson.annotations.SerializedName; import com.ljmu.andre.snaptools.BuildConfig; @@ -46,12 +47,12 @@ public class ServerPackMetaData extends PackMetaData { @SerializedName("is_purchased") private Boolean isPurchased; - public ServerPackMetaData(Function1 dispatcher) { + public ServerPackMetaData(PackEventRequest.EventHandler dispatcher) { super(dispatcher); } - public static ServerPackMetaData getTutorialPack(String scVersion) { - return (ServerPackMetaData) new ServerPackMetaData(null) + public static ServerPackMetaData getTutorialPack(String scVersion, PackEventRequest.EventHandler dispatcher) { + return (ServerPackMetaData) new ServerPackMetaData(dispatcher) .setPurchased(false) .setDescription(htmlHighlight("Tutorial Item")) .setHasUpdate(false) @@ -241,7 +242,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { download.setImageTintList(ContextCompat.getColorStateList(holder.itemView.getContext(), R.color.textPrimary)); download.setOnClickListener( - v -> eventDispatcher.invoke( + v -> eventDispatcher.handleEvent( new PackEventRequest( eventType, linkedMeta.getName() @@ -254,7 +255,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { if (!linkedMeta.isTutorial()) { rollback.setOnClickListener( - v -> eventDispatcher.invoke( + v -> eventDispatcher.handleEvent( new PackEventRequest( EventRequest.SHOW_ROLLBACK, linkedMeta.getName() @@ -263,7 +264,7 @@ public void convert(BaseViewHolder holder, ExpandableItemAdapter adapter) { ); changelog.setOnClickListener( - v -> eventDispatcher.invoke( + v -> eventDispatcher.handleEvent( new PackEventRequest( EventRequest.SHOW_CHANGELOG, linkedMeta.getName() diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java b/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java index 9de66e1..7f1cb75 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Framework/ModulePack.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Context; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Exceptions.ModuleCertificateException; import com.ljmu.andre.snaptools.Exceptions.ModulePackFatalError; import com.ljmu.andre.snaptools.Exceptions.ModulePackLoadAborted; @@ -242,7 +243,7 @@ public static ModulePack getInstance( throw new ModulePackFatalError("Module pack doesn't contain meta-data"); // Load the metadata embedded into the manifest ============================== - LocalPackMetaData packMetaData = (LocalPackMetaData) new LocalPackMetaData() + LocalPackMetaData packMetaData = (LocalPackMetaData) new LocalPackMetaData(PackEventRequest.EventHandler.ignoreEvents) .setName(modulePackFile.getName().replace(".jar", "")) .setType(mainAttributes.getValue("Type")) .setPackVersion(mainAttributes.getValue("PackVersion")) diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java index 09bb41e..c14f2d2 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/DownloadModulePack.java @@ -9,6 +9,7 @@ import com.ljmu.andre.snaptools.EventBus.EventBus; import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent; import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent.DownloadState; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Exceptions.NullObjectException; import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData; import com.ljmu.andre.snaptools.Networking.Helpers.DownloadFile.DownloadListener; @@ -98,7 +99,7 @@ public void downloadFinished(boolean state, String message, @Nullable File outpu if (outputFile != null) { try { - metaData = PackUtils.getPackMetaData(outputFile); + metaData = PackUtils.getPackMetaData(outputFile, PackEventRequest.EventHandler.ignoreEvents); } catch (NullObjectException e) { state = false; message = e.getMessage(); diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java index d22990e..a6cd6ca 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Networking/Helpers/GetServerPacks.java @@ -5,6 +5,7 @@ import com.android.volley.Request.Method; import com.ljmu.andre.snaptools.Databases.CacheDatabase; import com.ljmu.andre.snaptools.Databases.Tables.ServerPackObject; +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData; import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData; import com.ljmu.andre.snaptools.Framework.MetaData.ServerPackMetaData; @@ -205,7 +206,7 @@ private static List processPacks(Collection getInstalledMetaData() { for (File file : jarFileList) { try { - LocalPackMetaData packMetaData = getPackMetaData(file); + LocalPackMetaData packMetaData = getPackMetaData(file, PackEventRequest.EventHandler.ignoreEvents); packMetaDataMap.put(packMetaData.getName(), packMetaData); } catch (Throwable t) { Timber.e(t); @@ -158,8 +160,8 @@ public static Map getInstalledMetaData() { return null; } - public static LocalPackMetaData getPackMetaData(File file) throws NullObjectException { - LocalPackMetaData packMetaData = new LocalPackMetaData(); + public static LocalPackMetaData getPackMetaData(File file, PackEventRequest.EventHandler dispatcher) throws NullObjectException { + LocalPackMetaData packMetaData = new LocalPackMetaData(dispatcher); bindPackMetaData(packMetaData, file); return packMetaData; } @@ -205,9 +207,9 @@ public static Observable> getAllMetaData() { for (File file : jarFileList) { LocalPackMetaData metaData; try { - metaData = getPackMetaData(file); + metaData = getPackMetaData(file, PackEventRequest.EventHandler.ignoreEvents); } catch (Throwable t) { - metaData = (LocalPackMetaData) new FailedPackMetaData() + metaData = (LocalPackMetaData) new FailedPackMetaData(PackEventRequest.EventHandler.ignoreEvents) .setReason(t.getMessage()) .setName(file.getName().replace(".jar", "")) .completedBinding(); @@ -220,7 +222,7 @@ public static Observable> getAllMetaData() { for (String packName : selectedPacks) { if (!packMetaDataMap.containsKey(packName)) { - FailedPackMetaData metaData = (FailedPackMetaData) new FailedPackMetaData() + FailedPackMetaData metaData = (FailedPackMetaData) new FailedPackMetaData(PackEventRequest.EventHandler.ignoreEvents) .setReason("Pack is enabled but cannot be found in the installed list") .setName(packName) .completedBinding(); diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.java b/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.java deleted file mode 100644 index 0326c2c..0000000 --- a/app/src/main/java/com/ljmu/andre/snaptools/Utils/Result.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.ljmu.andre.snaptools.Utils; - -import com.google.common.base.MoreObjects; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -public class Result { - private K key; - private V value; - - public Result(K key, V value) { - this.key = key; - this.value = value; - } - - public K getKey() { - return key; - } - - public Result setKey(K key) { - this.key = key; - return this; - } - - public V getValue() { - return value; - } - - public Result setValue(V value) { - this.value = value; - return this; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .omitNullValues() - .add("key", key == null ? null : key.toString()) - .add("value", value == null ? null : value.toString()) - .toString(); - } - - public static class BooleanResult extends Result { - public BooleanResult(Boolean key, T value) { - super(key, value); - } - } - - public static class BadResult extends BooleanResult { - public BadResult(String value) { - super(false, value); - } - } - - public static class GoodResult extends BooleanResult { - public GoodResult(String value) { - super(true, value); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt index 7dc9aa1..e9cc7ad 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt +++ b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt @@ -35,19 +35,15 @@ class PackRepository { private val packDirectory = File(getPref(MODULES_PATH) as String) - fun fireFromMetadata(evt: PackEventRequest) { - _eventDispatcher.value = evt - } - - fun refreshLocalMetadata() { + fun refreshLocalMetadata(evtHandler: PackEventRequest.EventHandler) { val jarFileList = packDirectory.listFiles { _, name -> name.endsWith(".jar") } if (jarFileList.isNullOrEmpty()) _localMetadata.postValue(emptyList()) val packs = jarFileList.associate { file -> val metadata = try { - getPackMetaData(file) + getPackMetaData(file, evtHandler) } catch (t: Throwable) { - FailedPackMetaData().run { + FailedPackMetaData(evtHandler).run { reason = t.message name = file.name.replace(".jar", "") completedBinding() @@ -62,7 +58,7 @@ class PackRepository { getPref>(SELECTED_PACKS).forEach { packName -> if (packName in packs) return@forEach - val failedMetadata = FailedPackMetaData().run { + val failedMetadata = FailedPackMetaData(evtHandler).run { reason = "Pack is enabled but cannot be found in the installed list" name = packName completedBinding() @@ -98,7 +94,7 @@ class PackRepository { /** * Unloads, disables and deletes the pack */ - fun deletePack(packName: String, activity: Activity): Result { + fun deletePack(packName: String, activity: Activity, evtHandler: PackEventRequest.EventHandler): Result { val result = disablePack(packName, activity) if (result is Result.Error) return result @@ -110,7 +106,7 @@ class PackRepository { return Result.Error(e) } _eventDispatcher.value = PackDeleteEvent(packName) - refreshLocalMetadata() + refreshLocalMetadata(evtHandler) return Result.Success(packName) } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt b/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt index e3efbe8..18ac448 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt +++ b/app/src/main/java/com/ljmu/andre/snaptools/viewmodel/PackViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData import com.ljmu.andre.snaptools.Utils.Result import com.ljmu.andre.snaptools.repository.PackRepository @@ -20,12 +21,10 @@ import timber.log.Timber class PackViewModel : ViewModel() { val localMetadata: LiveData> get() = packRepo.localMetadata - val eventDispatcher: LiveData - get() = packRepo.eventDispatcher - fun refreshLocalPacks() { + fun refreshLocalPacks(eventHandler: PackEventRequest.EventHandler) { viewModelScope.launch(Dispatchers.IO) { - packRepo.refreshLocalMetadata() + packRepo.refreshLocalMetadata(eventHandler) } } @@ -61,7 +60,7 @@ class PackViewModel : ViewModel() { fun unloadPack(packName: String, activity: Activity) = packRepo.unloadPack(packName, activity) - fun deletePack(packName: String, activity: Activity) = packRepo.deletePack(packName, activity) + fun deletePack(packName: String, activity: Activity, evtHandler: PackEventRequest.EventHandler) = packRepo.deletePack(packName, activity, evtHandler) fun downloadPack() { viewModelScope.launch(Dispatchers.IO) { From 906ac4b0c9acd37f71b1f409cf09753739027f72 Mon Sep 17 00:00:00 2001 From: jaqxues <32979131+jaqxues@users.noreply.github.com> Date: Mon, 18 May 2020 19:39:47 +0200 Subject: [PATCH 03/28] Made PackSelectorFragment Work --- .../Fragments/PackManagerFragment.java | 2 +- .../Fragments/PackSelectorFragment.java | 418 ------------------ ...rFragmentKt.kt => PackSelectorFragment.kt} | 48 +- .../snaptools/repository/PackRepository.kt | 5 +- 4 files changed, 41 insertions(+), 432 deletions(-) delete mode 100644 app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.java rename app/src/main/java/com/ljmu/andre/snaptools/Fragments/{PackSelectorFragmentKt.kt => PackSelectorFragment.kt} (82%) diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java index b87efd0..2f24a89 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackManagerFragment.java @@ -251,7 +251,7 @@ public void clicked(ThemedDialog themedDialog) { public static class PackSettingsPagerAdapter extends FragmentPagerAdapter { PackSettingsPagerAdapter(FragmentManager fm) { - super(fm); + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); } @Override diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.java b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.java deleted file mode 100644 index c96220d..0000000 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.java +++ /dev/null @@ -1,418 +0,0 @@ -package com.ljmu.andre.snaptools.Fragments; - -import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.core.util.Pair; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.Toast; - -import com.google.common.collect.ImmutableList; -import com.google.common.eventbus.Subscribe; -import com.ljmu.andre.snaptools.Dialogs.DialogFactory; -import com.ljmu.andre.snaptools.Dialogs.ThemedDialog; -import com.ljmu.andre.snaptools.Dialogs.ThemedDialog.ThemedClickListener; -import com.ljmu.andre.snaptools.EventBus.EventBus; -import com.ljmu.andre.snaptools.EventBus.Events.PackDeleteEvent; -import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent; -import com.ljmu.andre.snaptools.EventBus.Events.PackDownloadEvent.DownloadState; -import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest; -import com.ljmu.andre.snaptools.EventBus.Events.PackEventRequest.EventRequest; -import com.ljmu.andre.snaptools.EventBus.Events.PackLoadEvent; -import com.ljmu.andre.snaptools.EventBus.Events.PackUnloadEvent; -import com.ljmu.andre.snaptools.Framework.FrameworkManager; -import com.ljmu.andre.snaptools.Framework.MetaData.FailedPackMetaData.FailedPackToolbar; -import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData; -import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData; -import com.ljmu.andre.snaptools.Framework.Utils.PackLoadState; -import com.ljmu.andre.snaptools.R; -import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter; -import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.ExpandableItemEntity; -import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter.TextItemEntity; -import com.ljmu.andre.snaptools.Utils.AnimationUtils; -import com.ljmu.andre.snaptools.Utils.PackUtils; -import com.ljmu.andre.snaptools.Utils.PreferenceHelpers; -import com.ljmu.andre.snaptools.Utils.SafeToast; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.Unbinder; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; -import io.reactivex.observers.DisposableObserver; -import io.reactivex.schedulers.Schedulers; -import timber.log.Timber; - -import static com.ljmu.andre.snaptools.Utils.FrameworkPreferencesDef.SELECTED_PACKS; -import static com.ljmu.andre.snaptools.Utils.PreferenceHelpers.collectionContains; - -/** - * This class was created by Andre R M (SID: 701439) - * It and its contents are free to use by all - */ - -public class PackSelectorFragment extends FragmentHelper { - public static final String TAG = "Pack Selector"; - private final List packs = new ArrayList<>(); - - Unbinder unbinder; - @BindView(R.id.swipe_layout) - SwipeRefreshLayout swipeRefreshLayout; - @BindView(R.id.recycler_pack_selector) - RecyclerView list_packs; - private ExpandableItemAdapter adapter; - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View layoutContainer = inflater.inflate(R.layout.frag_pack_selector, container, false); - unbinder = ButterKnife.bind(this, layoutContainer); - Timber.d("Create"); - - EventBus.soleRegister(this); - - list_packs.setLayoutManager(new LinearLayoutManager(getContext())); - - adapter = new ExpandableItemAdapter(packs); - adapter.bindToRecyclerView(list_packs); - adapter.addType(PackMetaData.type, PackMetaData.layoutRes); - adapter.addType(TextItemEntity.type, TextItemEntity.layoutRes); - adapter.addType(LocalPackMetaData.LocalPackToolbarItem.type, LocalPackMetaData.LocalPackToolbarItem.layoutRes); - adapter.addType(FailedPackToolbar.type, FailedPackToolbar.layoutRes); - adapter.setEmptyView(R.layout.layout_empty_packs); - - swipeRefreshLayout.setOnRefreshListener( - () -> { - if (runningTutorial) { - swipeRefreshLayout.setRefreshing(false); - return; - } - - generateMetaData(); - } - ); - - return layoutContainer; - } - - @Override - public void onResume() { - super.onResume(); - - if (runningTutorial) - generateTutorialData(); - else - generateMetaData(); - } - - @Override - public void onPause() { - super.onPause(); - packs.clear(); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - unbinder.unbind(); - } - - public void generateMetaData() { - if (runningTutorial) { - generateTutorialData(); - - if (swipeRefreshLayout != null) - swipeRefreshLayout.setRefreshing(false); - return; - } - - PackUtils.getAllMetaData() - .subscribe(new DisposableObserver>() { - @Override - public void onNext(@NonNull Map metaDataMap) { - if (runningTutorial) - return; - - setPacks(metaDataMap.values()); - } - - @Override - public void onError(@NonNull Throwable e) { - if (swipeRefreshLayout != null) - swipeRefreshLayout.setRefreshing(false); - - if (runningTutorial) - return; - - setPacks(Collections.emptyList()); - Timber.e(e); - } - - @Override - public void onComplete() { - if (swipeRefreshLayout != null) - swipeRefreshLayout.setRefreshing(false); - } - }); - } - - public void generateTutorialData() { - List tutorialVersions = new ImmutableList.Builder() - .add("10.0.0.0") - .add("10.1.0.1") - .add("10.12.1.0") - .add("10.16.0.0") - .build(); - - List tutorialDataList = new ArrayList<>(tutorialVersions.size()); - - for (String tutorialVersion : tutorialVersions) - tutorialDataList.add(LocalPackMetaData.getTutorialPack(tutorialVersion)); - - setPacks(tutorialDataList); - } - - public void setPacks(Collection newPacks) { - if (list_packs != null) { - list_packs.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (list_packs == null) - return; - - //At this point the layout is complete and the - //dimensions of recyclerView and any child views are known. - - AnimationUtils.sequentGroup(list_packs); - - list_packs.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } - }); - } - - packs.clear(); - packs.addAll(newPacks); - Collections.sort(packs); - - if (adapter != null) { - if (packs.isEmpty()) - adapter.setEmptyView(R.layout.layout_empty_packs); - else - adapter.notifyDataSetChanged(); - } - } - - @Override - public String getName() { - return TAG; - } - - @Override - public Integer getMenuId() { - return null; - } - - @Override - public void onDestroy() { - super.onDestroy(); - EventBus.soleUnregister(this); - } - - @Override - public void progressTutorial() { - } - - @Subscribe - public void handlePackDownloadEvent(PackDownloadEvent downloadEvent) { - Timber.d("Pack Download Event: " + downloadEvent.toString()); - - if (downloadEvent.getState() == DownloadState.SUCCESS) { - if (downloadEvent.getMetaData() == null) - return; - - generateMetaData(); - } - } - - @Nullable - public LocalPackMetaData getMetaDataFromName(String packName) { - Pair result = getMetaDataAndIndexFromName(packName); - - return result == null ? null : result.first; - } - - @Nullable - public Pair getMetaDataAndIndexFromName(String packName) { - int index = -1; - for (Object packObj : packs) { - index++; - if (!(packObj instanceof LocalPackMetaData)) - continue; - - LocalPackMetaData metaData = (LocalPackMetaData) packObj; - - if (metaData.getName().equals(packName)) - return new Pair<>(metaData, index); - } - - return null; - } - - public RecyclerView getRecyclerView() { - return list_packs; - } - - public ExpandableItemAdapter getAdapter() { - return adapter; - } - - @Subscribe - public void handlePackEventRequest(PackEventRequest eventRequest) { - EventRequest request = eventRequest.getRequest(); - Timber.d("New Event Request: " + request.toString()); - - switch (request) { - case UNLOAD: - PreferenceHelpers.removeFromCollection( - SELECTED_PACKS, - eventRequest.getPackName(), - getActivity() - ); - - // If there was no pack to remove, manually update =========================== - if (!FrameworkManager.unloadModPack(eventRequest.getPackName())) - updatePackState(eventRequest.getPackName()); - break; - case LOAD: - FrameworkManager.disableAllPacks(); - - PreferenceHelpers.addToCollection( - SELECTED_PACKS, - eventRequest.getPackName(), - getActivity() - ); - - Observable.fromCallable( - () -> FrameworkManager.loadModPack( - getActivity(), - eventRequest.getPackName(), - new PackLoadState(eventRequest.getPackName()) - )) - .subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new DisposableObserver() { - @Override - public void onNext(@NonNull PackLoadEvent loadEvent) { - EventBus.getInstance().post(loadEvent); - } - - @Override - public void onError(@NonNull Throwable e) { - Timber.w(e); - FrameworkManager.addFailReason(eventRequest.getPackName(), e.getMessage()); - updatePackState(eventRequest.getPackName()); - } - - @Override - public void onComplete() { - } - }); - - break; - case DELETE: - DialogFactory.createConfirmation( - getActivity(), - "Confirm Action", - "Are you sure you wish to delete this pack?", - new ThemedClickListener() { - @Override - public void clicked(ThemedDialog themedDialog) { - FrameworkManager.deleteModPack(eventRequest.getPackName(), getActivity()); - - if (collectionContains(SELECTED_PACKS, eventRequest.getPackName())) { - String message = "Failed to disable deleted pack: " + eventRequest.getPackName(); - Timber.e(message); - SafeToast.show(getActivity(), message, Toast.LENGTH_LONG); - } - - themedDialog.dismiss(); - } - } - ).show(); - break; - default: - Timber.d("Ignoring Unhandled Request"); - } - } - - public void updatePackState(String packName) { - int packIndex = getIndexFromName(packName); - if (packIndex != -1) { - adapter.notifyItemChanged(packIndex); - ExpandableItemEntity entity = adapter.getItem(packIndex); - - if (entity == null || !entity.isExpanded()) - return; - - while (++packIndex < adapter.getItemCount()) { - entity = adapter.getItem(packIndex); - - Timber.d("Entity: " + entity); - if (!(entity instanceof PackMetaData)) { - adapter.notifyItemChanged(packIndex); - } else - break; - } - } - } - - public int getIndexFromName(String packName) { - int index = -1; - Timber.d("Adapter Count: " + adapter.getItemCount()); - - for (Object packObj : packs) { - index++; - - if (!(packObj instanceof LocalPackMetaData)) - continue; - - LocalPackMetaData metaData = (LocalPackMetaData) packObj; - - if (metaData.getName().equals(packName)) - return index; - } - - return -1; - } - - @Subscribe - public void handlePackLoadEvent(PackLoadEvent loadEvent) { - updatePackState(loadEvent.getModulePack().getPackName()); - } - - @Subscribe - public void handlePackUnloadEvent(PackUnloadEvent unloadEvent) { - updatePackState(unloadEvent.getPackMetaData().getName()); - } - - @Subscribe - public void handlePackDeleteEvent(PackDeleteEvent deleteEvent) { - int index = getIndexFromName(deleteEvent.getPackName()); - adapter.collapse(index); - adapter.remove(index); - - FrameworkManager.deleteModPack(deleteEvent.getPackName(), null); - } -} diff --git a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.kt similarity index 82% rename from app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt rename to app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.kt index 160cc23..81187cf 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragmentKt.kt +++ b/app/src/main/java/com/ljmu/andre/snaptools/Fragments/PackSelectorFragment.kt @@ -22,9 +22,11 @@ import com.ljmu.andre.snaptools.Framework.MetaData.LocalPackMetaData import com.ljmu.andre.snaptools.Framework.MetaData.PackMetaData import com.ljmu.andre.snaptools.R import com.ljmu.andre.snaptools.UIComponents.Adapters.ExpandableItemAdapter -import com.ljmu.andre.snaptools.Utils.* +import com.ljmu.andre.snaptools.Utils.AnimationUtils +import com.ljmu.andre.snaptools.Utils.Result +import com.ljmu.andre.snaptools.Utils.SafeToast +import com.ljmu.andre.snaptools.Utils.consumeResult import com.ljmu.andre.snaptools.viewmodel.PackViewModel -import kotlinx.android.synthetic.main.frag_faq.* import kotlinx.android.synthetic.main.frag_pack_selector.* import timber.log.Timber @@ -34,8 +36,14 @@ import timber.log.Timber * Date: 13.05.20 - Time 14:23. */ -class PackSelectorFragmentKt : FragmentHelper() { - val recycler: RecyclerView +class PackSelectorFragment : FragmentHelper() { +// @Suppress("UNCHECKED_CAST") + val adapter: ExpandableItemAdapter> + get() { + return recyclerView.adapter as? ExpandableItemAdapter> + ?: throw IllegalStateException("Could not be cast to expected type") + } + val recyclerView: RecyclerView get() { check(runningTutorial) { "Only allowing getting PackView for Tutorials" } return recycler_pack_selector @@ -49,7 +57,13 @@ class PackSelectorFragmentKt : FragmentHelper() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val layoutContainer = inflater.inflate(R.layout.frag_pack_selector, container, false) - viewModel = ViewModelProvider(this).get(PackViewModel::class.java) + viewModel = ViewModelProvider(requireActivity()).get(PackViewModel::class.java) + + return layoutContainer + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) recycler_pack_selector.layoutManager = LinearLayoutManager(requireContext()) @@ -68,25 +82,24 @@ class PackSelectorFragmentKt : FragmentHelper() { // Animating recycler_pack_selector.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { + val recycler = recycler_pack_selector ?: return //At this point the layout is complete and the //dimensions of recyclerView and any child views are known. - AnimationUtils.sequentGroup(recycler_pack_selector) - recycler_pack_selector.viewTreeObserver.removeOnGlobalLayoutListener(this) + AnimationUtils.sequentGroup(recycler) + recycler.viewTreeObserver.removeOnGlobalLayoutListener(this) } }) adapter.setNewData(packs) - swipe_refresh_layout.isRefreshing = false + swipe_layout.isRefreshing = false }) - swipe_refresh_layout.setOnRefreshListener { + swipe_layout.setOnRefreshListener { if (runningTutorial) { - swipe_refresh_layout.isRefreshing = false + swipe_layout.isRefreshing = false return@setOnRefreshListener } viewModel.refreshLocalPacks(evtHandler) } - - return layoutContainer } override fun onPause() { @@ -178,6 +191,17 @@ class PackSelectorFragmentKt : FragmentHelper() { } } + override fun progressTutorial() { + } + + fun generateTutorialData() { +// viewModel.setTutorialPacks() + } + + fun generateMetaData() { +// viewModel.refreshLocalPacks(evtHandler) + } + companion object { const val TAG = "Pack Selector" } diff --git a/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt index e9cc7ad..35e7649 100644 --- a/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt +++ b/app/src/main/java/com/ljmu/andre/snaptools/repository/PackRepository.kt @@ -37,7 +37,10 @@ class PackRepository { fun refreshLocalMetadata(evtHandler: PackEventRequest.EventHandler) { val jarFileList = packDirectory.listFiles { _, name -> name.endsWith(".jar") } - if (jarFileList.isNullOrEmpty()) _localMetadata.postValue(emptyList()) + if (jarFileList.isNullOrEmpty()) { + _localMetadata.postValue(emptyList()) + return + } val packs = jarFileList.associate { file -> val metadata = try { From 6e93feefa70cec3474d0113bc476e00149410c6e Mon Sep 17 00:00:00 2001 From: jaqxues <32979131+jaqxues@users.noreply.github.com> Date: Mon, 25 May 2020 13:44:13 +0200 Subject: [PATCH 04/28] Remove HangErrorActivity.java --- app/src/main/AndroidManifest.xml | 7 - .../andre/snaptools/HangErrorActivity.java | 155 ------------------ .../main/res/layout/activity_hang_error.xml | 99 ----------- 3 files changed, 261 deletions(-) delete mode 100644 app/src/main/java/com/ljmu/andre/snaptools/HangErrorActivity.java delete mode 100644 app/src/main/res/layout/activity_hang_error.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4c9c7cc..451b97d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -59,13 +59,6 @@ - - - - - - - - - - - - - - - - - - - -