diff --git a/app/build.gradle b/app/build.gradle index 9cb129bae..f77b16b51 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,12 +38,12 @@ android { packagingOptions { exclude '/META-INF/*.version' - exclude '/META-INF/*.kotlin_module' - exclude '/META-INF/rxkotlin.properties' + //exclude '/META-INF/*.kotlin_module' + //exclude '/META-INF/rxkotlin.properties' exclude '/androidsupportmultidexversion.txt' exclude '/org/**' - exclude '/kotlin/**' - exclude '/kotlinx/**' + //exclude '/kotlin/**' + //exclude '/kotlinx/**' } } @@ -62,6 +62,9 @@ dependencies { implementation 'com.github.skoumalcz:teanity:0.3.3' implementation 'com.ncapdevi:frag-nav:3.2.0' + def vRoom = "2.1.0-alpha05" + implementation "androidx.room:room-rxjava2:${vRoom}" + def markwonVersion = '3.0.0' implementation "ru.noties.markwon:core:${markwonVersion}" implementation "ru.noties.markwon:html:${markwonVersion}" @@ -87,6 +90,9 @@ dependencies { implementation "com.squareup.moshi:moshi:${vMoshi}" implementation "com.squareup.moshi:moshi-kotlin:${vMoshi}" + kapt "com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}" + kapt "androidx.room:room-compiler:${vRoom}" + def vKotpref = "2.8.0" implementation "com.chibatching.kotpref:kotpref:${vKotpref}" diff --git a/app/src/main/java/com/topjohnwu/magisk/App.kt b/app/src/main/java/com/topjohnwu/magisk/App.kt index e34bfaacc..84150191e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/App.kt +++ b/app/src/main/java/com/topjohnwu/magisk/App.kt @@ -11,6 +11,7 @@ import android.os.Build import android.os.Bundle import androidx.appcompat.app.AppCompatDelegate import androidx.multidex.MultiDex +import com.chibatching.kotpref.Kotpref import com.topjohnwu.magisk.data.database.MagiskDB import com.topjohnwu.magisk.data.database.RepoDatabaseHelper import com.topjohnwu.magisk.di.koinModules @@ -39,6 +40,12 @@ open class App : Application(), Application.ActivityLifecycleCallbacks { @Volatile private var foreground: Activity? = null + override fun onCreate() { + super.onCreate() + + Kotpref.init(this) + } + override fun attachBaseContext(base: Context) { super.attachBaseContext(base) if (BuildConfig.DEBUG) diff --git a/app/src/main/java/com/topjohnwu/magisk/di/DatabaseModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/DatabaseModule.kt index 0f79c302c..92d68d2b4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/DatabaseModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/DatabaseModule.kt @@ -1,12 +1,24 @@ package com.topjohnwu.magisk.di +import android.content.Context +import androidx.room.Room import com.topjohnwu.magisk.App -import com.topjohnwu.magisk.data.database.MagiskDB -import com.topjohnwu.magisk.data.database.RepoDatabaseHelper +import com.topjohnwu.magisk.data.database.* import org.koin.dsl.module val databaseModule = module { single { MagiskDB(get().protectedContext) } single { RepoDatabaseHelper(get()) } + single { createDatabase(get()) } + single { LogDao() } + single { PolicyDao(get()) } + single { SettingsDao() } + single { StringsDao() } + single { createRepositoryDao(get()) } } + +fun createDatabase(context: Context): AppDatabase = + Room.databaseBuilder(context, AppDatabase::class.java, AppDatabase.NAME).build() + +fun createRepositoryDao(db: AppDatabase) = db.repoDao() \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/di/NetworkingModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/NetworkingModule.kt index f485acc3c..cbdeb2bc3 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/NetworkingModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/NetworkingModule.kt @@ -1,6 +1,7 @@ package com.topjohnwu.magisk.di import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.topjohnwu.magisk.Constants import com.topjohnwu.magisk.data.network.GithubApiServices import com.topjohnwu.magisk.data.network.GithubRawApiServices @@ -38,7 +39,9 @@ fun createOkHttpClient(): OkHttpClient { } fun createConverterFactory(): Converter.Factory { - val moshi = Moshi.Builder().build() + val moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() return MoshiConverterFactory.create(moshi) } diff --git a/app/src/main/java/com/topjohnwu/magisk/di/RepositoryModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/RepositoryModule.kt index 0d55b410c..79349f63e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/RepositoryModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/RepositoryModule.kt @@ -1,6 +1,13 @@ package com.topjohnwu.magisk.di +import com.topjohnwu.magisk.data.repository.LogRepository +import com.topjohnwu.magisk.data.repository.MagiskRepository +import com.topjohnwu.magisk.data.repository.ModuleRepository import org.koin.dsl.module -val repositoryModule = module {} +val repositoryModule = module { + single { MagiskRepository(get(), get()) } + single { ModuleRepository(get(), get(), get(), get()) } + single { LogRepository(get()) } +} 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 9983734a8..8b0f22d4c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt @@ -15,7 +15,7 @@ import org.koin.dsl.module val viewModelModules = module { viewModel { MainViewModel() } - viewModel { HomeViewModel(get(), get()) } + viewModel { HomeViewModel(get(), get(), get()) } viewModel { SuperuserViewModel(get(), get(), get(), get()) } viewModel { HideViewModel(get(), get()) } viewModel { ModuleViewModel(get(), get()) } diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskApp.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskApp.kt new file mode 100644 index 000000000..6fc7d3cfd --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskApp.kt @@ -0,0 +1,11 @@ +package com.topjohnwu.magisk.model.entity + +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class MagiskApp( + val version: String, + val versionCode: String, + val link: String, + val note: String +) \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskConfig.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskConfig.kt index 6fffed3df..e028d2273 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskConfig.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskConfig.kt @@ -1,32 +1,7 @@ package com.topjohnwu.magisk.model.entity -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - data class MagiskConfig( val app: MagiskApp, val uninstaller: MagiskLink, val magisk: MagiskFlashable ) - -@JsonClass(generateAdapter = true) -data class MagiskApp( - val version: String, - val versionCode: String, - val link: String, - val note: String -) - -@JsonClass(generateAdapter = true) -data class MagiskLink( - val link: String -) - -@JsonClass(generateAdapter = true) -data class MagiskFlashable( - val version: String, - val versionCode: String, - val link: String, - val note: String, - @Json(name = "md5") val hash: String -) \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskFlashable.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskFlashable.kt new file mode 100644 index 000000000..bc7323021 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskFlashable.kt @@ -0,0 +1,13 @@ +package com.topjohnwu.magisk.model.entity + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class MagiskFlashable( + val version: String, + val versionCode: String, + val link: String, + val note: String, + @Json(name = "md5") val hash: String +) \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskLink.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskLink.kt new file mode 100644 index 000000000..28df1788e --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskLink.kt @@ -0,0 +1,8 @@ +package com.topjohnwu.magisk.model.entity + +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class MagiskLink( + val link: String +) \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/Module.java b/app/src/main/java/com/topjohnwu/magisk/model/entity/OldModule.java similarity index 73% rename from app/src/main/java/com/topjohnwu/magisk/model/entity/Module.java rename to app/src/main/java/com/topjohnwu/magisk/model/entity/OldModule.java index ed04b2830..f4780c83b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/Module.java +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/OldModule.java @@ -6,16 +6,33 @@ import android.os.Parcelable; import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.io.SuFile; -public class Module extends BaseModule { +public class OldModule extends BaseModule { - private SuFile mRemoveFile, mDisableFile, mUpdateFile; - private boolean mEnable, mRemove, mUpdated; + public static final Parcelable.Creator CREATOR = new Creator() { + /* It won't be used at any place */ + @Override + public OldModule createFromParcel(Parcel source) { + return null; + } - public Module(String path) { + @Override + public OldModule[] newArray(int size) { + return null; + } + }; + private final SuFile mRemoveFile; + private final SuFile mDisableFile; + private final SuFile mUpdateFile; + private final boolean mUpdated; + private boolean mEnable; + private boolean mRemove; + + public OldModule(String path) { try { parseProps(Shell.su("dos2unix < " + path + "/module.prop").exec().getOut()); - } catch (NumberFormatException ignored) {} + } catch (NumberFormatException ignored) { + } mRemoveFile = new SuFile(path, "remove"); mDisableFile = new SuFile(path, "disable"); @@ -35,19 +52,6 @@ public class Module extends BaseModule { mUpdated = mUpdateFile.exists(); } - public static final Parcelable.Creator CREATOR = new Creator() { - /* It won't be used at any place */ - @Override - public Module createFromParcel(Parcel source) { - return null; - } - - @Override - public Module[] newArray(int size) { - return null; - } - }; - public void createDisableFile() { mEnable = !mDisableFile.createNewFile(); } diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt index 74c90a814..d4a722956 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt @@ -6,12 +6,12 @@ import com.skoumal.teanity.databinding.ComparableRvItem import com.skoumal.teanity.extensions.addOnPropertyChangedCallback import com.skoumal.teanity.util.KObservableField import com.topjohnwu.magisk.R -import com.topjohnwu.magisk.model.entity.Module +import com.topjohnwu.magisk.model.entity.OldModule import com.topjohnwu.magisk.model.entity.Repo import com.topjohnwu.magisk.utils.get import com.topjohnwu.magisk.utils.toggle -class ModuleRvItem(val item: Module) : ComparableRvItem() { +class ModuleRvItem(val item: OldModule) : ComparableRvItem() { override val layoutRes: Int = R.layout.item_module 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 db7d6fc98..2b449bfb7 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 @@ -14,7 +14,10 @@ import timber.log.Timber abstract class MagiskViewModel : LoadingViewModel(), Event.AutoListener { + @Deprecated("") override fun onEvent(event: Int) = Timber.i("Event of $event was not handled") + + @Deprecated("") override fun getListeningEvents(): IntArray = intArrayOf() fun withView(action: Activity.() -> Unit) { 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 index f5d16d2ab..9681027c1 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt @@ -2,22 +2,24 @@ package com.topjohnwu.magisk.ui.home import android.content.res.Resources import com.skoumal.teanity.extensions.addOnPropertyChangedCallback +import com.skoumal.teanity.extensions.doOnSubscribeUi +import com.skoumal.teanity.extensions.subscribeK import com.skoumal.teanity.util.KObservableField import com.topjohnwu.magisk.* +import com.topjohnwu.magisk.data.repository.MagiskRepository import com.topjohnwu.magisk.model.events.* import com.topjohnwu.magisk.model.observer.Observer -import com.topjohnwu.magisk.tasks.CheckUpdates import com.topjohnwu.magisk.ui.base.MagiskViewModel import com.topjohnwu.magisk.utils.Event import com.topjohnwu.magisk.utils.ISafetyNetHelper import com.topjohnwu.magisk.utils.toggle -import com.topjohnwu.net.Networking import com.topjohnwu.superuser.Shell class HomeViewModel( private val resources: Resources, - private val app: App + private val app: App, + private val magiskRepo: MagiskRepository ) : MagiskViewModel() { val isAdvancedExpanded = KObservableField(false) @@ -163,20 +165,26 @@ class HomeViewModel( } fun refresh() { - state = State.LOADING - magiskState.value = MagiskState.LOADING - managerState.value = MagiskState.LOADING - Event.reset(this) - Config.remoteMagiskVersionString = null - Config.remoteMagiskVersionCode = -1 + magiskRepo.fetchConfig() + .applyViewModel(this) + .doOnSubscribeUi { + magiskState.value = MagiskState.LOADING + managerState.value = MagiskState.LOADING + } + .subscribeK { + it.app.let { + Config.remoteManagerVersionCode = it.versionCode.toIntOrNull() ?: -1 + Config.remoteManagerVersionString = it.version + } + it.magisk.let { + Config.remoteMagiskVersionCode = it.versionCode.toIntOrNull() ?: -1 + Config.remoteMagiskVersionString = it.version + } + updateSelf() + ensureEnv() + } hasRoot.value = Shell.rootAccess() - - if (Networking.checkNetworkStatus(app)) { - CheckUpdates.check() - } else { - state = State.LOADING_FAILED - } } private fun updateSelf() { diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt index 031d67c3c..180b4091f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt @@ -11,7 +11,7 @@ import com.skoumal.teanity.util.KObservableField import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.R import com.topjohnwu.magisk.data.database.RepoDatabaseHelper -import com.topjohnwu.magisk.model.entity.Module +import com.topjohnwu.magisk.model.entity.OldModule import com.topjohnwu.magisk.model.entity.Repo import com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem import com.topjohnwu.magisk.model.entity.recycler.RepoRvItem @@ -76,7 +76,7 @@ class ModuleViewModel( UpdateRepos().exec(true) } - private fun updateModules(result: Map) = result.values + private fun updateModules(result: Map) = result.values .map { ModuleRvItem(it) } .let { itemsInstalled.update(it) } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 83c686696..9ae151e8c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -7,24 +7,16 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; -import android.database.Cursor; import android.net.Uri; -import android.provider.OpenableColumns; import android.widget.Toast; -import androidx.work.Constraints; -import androidx.work.ExistingPeriodicWorkPolicy; -import androidx.work.NetworkType; -import androidx.work.PeriodicWorkRequest; -import androidx.work.WorkManager; - import com.topjohnwu.magisk.App; import com.topjohnwu.magisk.BuildConfig; import com.topjohnwu.magisk.ClassMap; import com.topjohnwu.magisk.Config; import com.topjohnwu.magisk.Const; import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.model.entity.Module; +import com.topjohnwu.magisk.model.entity.OldModule; import com.topjohnwu.magisk.model.update.UpdateCheckService; import com.topjohnwu.net.Networking; import com.topjohnwu.superuser.Shell; @@ -35,6 +27,12 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; +import androidx.work.Constraints; +import androidx.work.ExistingPeriodicWorkPolicy; +import androidx.work.NetworkType; +import androidx.work.PeriodicWorkRequest; +import androidx.work.WorkManager; + public class Utils { public static void toast(CharSequence msg, int duration) { @@ -93,13 +91,13 @@ public class Utils { public static void loadModules(boolean async) { Event.reset(Event.MODULE_LOAD_DONE); Runnable run = () -> { - Map moduleMap = new ValueSortedMap<>(); + Map moduleMap = new ValueSortedMap<>(); SuFile path = new SuFile(Const.MAGISK_PATH); SuFile[] modules = path.listFiles( (file, name) -> !name.equals("lost+found") && !name.equals(".core")); for (SuFile file : modules) { if (file.isFile()) continue; - Module module = new Module(Const.MAGISK_PATH + "/" + file.getName()); + OldModule module = new OldModule(Const.MAGISK_PATH + "/" + file.getName()); moduleMap.put(module.getId(), module); } Event.trigger(Event.MODULE_LOAD_DONE, moduleMap); diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt b/app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt index 279161887..f6bbede0b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/XNetwork.kt @@ -5,7 +5,7 @@ import android.content.Intent import androidx.browser.customtabs.CustomTabsIntent import androidx.core.content.ContextCompat import androidx.core.net.toUri -import com.topjohnwu.magisk.Config +import com.topjohnwu.magisk.KConfig import com.topjohnwu.magisk.R import okhttp3.ResponseBody import java.io.File @@ -20,7 +20,7 @@ fun ResponseBody.writeToFile(context: Context, fileName: String): File { fun ResponseBody.writeToString() = string() -fun String.launch() = if (Config.useCustomTabs) { +fun String.launch() = if (KConfig.useCustomTabs) { launchWithCustomTabs() } else { launchWithIntent()