diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index b75d5ea..64a8afb 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -4,10 +4,12 @@ import java.io.PrintStream
import java.util.*
plugins {
+ kotlin("android")
id("com.android.application")
id("com.google.gms.google-services")
+ id("dev.rikka.tools.materialthemebuilder")
id("dev.rikka.tools.refine")
- kotlin("android")
+ id("androidx.navigation.safeargs.kotlin")
}
android {
@@ -71,18 +73,23 @@ dependencies {
implementation(projects.common)
runtimeOnly(projects.xposed)
- implementation("androidx.appcompat:appcompat:1.4.2")
- implementation("androidx.fragment:fragment-ktx:1.4.1")
- implementation("androidx.preference:preference-ktx:1.2.0")
+ implementation("androidx.navigation:navigation-fragment-ktx:2.5.0")
+ implementation("androidx.navigation:navigation-ui-ktx:2.5.0")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
- implementation("androidx.work:work-runtime-ktx:2.7.1")
implementation("com.drakeet.about:about:2.5.1")
implementation("com.drakeet.multitype:multitype:4.3.0")
+ implementation("com.github.kirich1409:viewbindingpropertydelegate:1.5.6")
implementation("com.github.topjohnwu.libsu:core:3.1.2")
implementation("com.google.android.material:material:1.6.1")
- implementation("com.google.android.gms:play-services-ads:21.0.0")
- implementation("com.google.firebase:firebase-analytics-ktx:21.0.0")
- implementation("com.squareup.okhttp3:okhttp:4.9.1")
+ implementation("com.google.android.gms:play-services-ads:21.1.0")
+ implementation("com.google.firebase:firebase-analytics-ktx:21.1.0")
+ implementation("com.squareup.okhttp3:okhttp:4.10.0")
implementation("dev.rikka.hidden:compat:2.3.1")
+ implementation("dev.rikka.rikkax.material:material:2.5.0")
+ implementation("dev.rikka.rikkax.material:material-preference:2.0.0")
compileOnly("dev.rikka.hidden:stub:2.3.1")
}
+
+configurations.all {
+ exclude("androidx.appcompat", "appcompat")
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 0aee042..971a41d 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -1,17 +1,9 @@
# Magic
-keep class com.tsng.hidemyapplist.Magic { *; }
--keep class com.tsng.hidemyapplist.app.MyApplication {
- static final com.tsng.hidemyapplist.app.MyApplication$Companion Companion;
-}
--keep class com.tsng.hidemyapplist.app.MyApplication$Companion { *; }
-
-# Views
--keep class com.tsng.hidemyapplist.app.ui.activities.ModuleActivity$Fragment { *; }
--keep class com.tsng.hidemyapplist.app.ui.views.FilterRulesView{ *; }
# Xposed
--keepclassmembers class com.tsng.hidemyapplist.app.MyApplication {
- static final boolean isModuleActivated;
+-keepclassmembers class icu.nullptr.hidemyapplist.MyApp {
+ boolean isHooked;
}
# Enum class
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7ba8ca4..92cb00c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -10,7 +10,7 @@
-
-
-
-
-
-
-
-
-
@@ -54,7 +35,7 @@
android:name=".MainActivityLauncher"
android:exported="true"
android:label="@string/app_name"
- android:targetActivity=".app.ui.activities.MainActivity">
+ android:targetActivity="icu.nullptr.hidemyapplist.ui.activity.MainActivity">
@@ -77,5 +58,4 @@
android:name="xposedscope"
android:resource="@array/xposed_scope" />
-
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/AppUtils.kt b/app/src/main/java/com/tsng/hidemyapplist/app/AppUtils.kt
deleted file mode 100644
index 6cd3afc..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/AppUtils.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.tsng.hidemyapplist.app
-
-import android.widget.Toast
-import androidx.annotation.StringRes
-import androidx.appcompat.app.AppCompatActivity
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentTransaction
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.MyApplication.Companion.appContext
-
-fun makeToast(@StringRes resId: Int) {
- Toast.makeText(appContext, resId, Toast.LENGTH_SHORT).show()
-}
-
-fun makeToast(text: CharSequence) {
- Toast.makeText(appContext, text, Toast.LENGTH_SHORT).show()
-}
-
-fun AppCompatActivity.startFragment(fragment: Fragment, addToBackStack: Boolean = true) {
- val transaction = supportFragmentManager
- .beginTransaction()
- .replace(R.id.fragment_container, fragment)
- .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
- if (addToBackStack) transaction.addToBackStack(null)
- transaction.commit()
-}
-
-fun Fragment.startFragment(fragment: Fragment, addToBackStack: Boolean = true) {
- val transaction = parentFragmentManager
- .beginTransaction()
- .hide(this)
- .add(R.id.fragment_container, fragment)
- .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
- if (addToBackStack) transaction.addToBackStack(null)
- transaction.commit()
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/JsonConfigManager.kt b/app/src/main/java/com/tsng/hidemyapplist/app/JsonConfigManager.kt
deleted file mode 100644
index 33ced9d..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/JsonConfigManager.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.tsng.hidemyapplist.app
-
-
-import com.tsng.hidemyapplist.BuildConfig
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.MyApplication.Companion.appContext
-import icu.nullptr.hidemyapplist.common.JsonConfig
-import java.io.File
-
-object JsonConfigManager {
-
- val configFile = File("${appContext.filesDir.absolutePath}/config.json")
- val globalConfig: JsonConfig
-
- init {
- if (!configFile.exists())
- configFile.writeText(JsonConfig().toString())
- try {
- globalConfig = JsonConfig.parse(configFile.readText())
- val configVersion = globalConfig.configVersion
- if (configVersion < 49) throw RuntimeException("Config version too old")
- if (configVersion < 65) migrateFromPre65()
- globalConfig.configVersion = BuildConfig.VERSION_CODE
- } catch (e: Exception) {
- makeToast(R.string.config_damaged)
- throw RuntimeException("Config file too old or damaged").apply { addSuppressed(e) }
- }
- }
-
- @Synchronized
- private fun save() {
- configFile.writeText(globalConfig.toString())
- }
-
- @Synchronized
- fun edit(block: JsonConfig.() -> Unit) {
- globalConfig.block()
- save()
- }
-
- private fun migrateFromPre65() {
- globalConfig.templates.forEach { (_, data) ->
- JsonConfig.Template::class.java.getDeclaredField("queryParamRules").apply {
- isAccessible = true
- set(data, mutableSetOf())
- }
- }
- globalConfig.scope.forEach { (_, data) ->
- JsonConfig.AppConfig::class.java.getDeclaredField("extraQueryParamRules").apply {
- isAccessible = true
- set(data, mutableSetOf())
- }
- }
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/MyApplication.kt b/app/src/main/java/com/tsng/hidemyapplist/app/MyApplication.kt
deleted file mode 100644
index 336632e..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/MyApplication.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.tsng.hidemyapplist.app
-
-import android.annotation.SuppressLint
-import android.app.Application
-import android.content.Context
-import com.google.android.material.color.DynamicColors
-import com.tsng.hidemyapplist.BuildConfig
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.helpers.AppInfoHelper
-import kotlin.concurrent.thread
-import kotlin.system.exitProcess
-
-class MyApplication : Application() {
- companion object {
- @SuppressLint("StaticFieldLeak")
- lateinit var appContext: Context
- val isModuleActivated = false
- }
-
- @SuppressLint("SdCardPath")
- override fun onCreate() {
- super.onCreate()
- DynamicColors.applyToActivitiesIfAvailable(this);
- appContext = applicationContext
- if (!appContext.filesDir.absolutePath.startsWith("/data/user/0/")) {
- makeToast(R.string.do_not_dual)
- exitProcess(0)
- }
- JsonConfigManager.edit {
- scope.remove(BuildConfig.APPLICATION_ID)
- }
- thread {
- AppInfoHelper.getAppInfoList()
- }
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/SubmitConfigService.kt b/app/src/main/java/com/tsng/hidemyapplist/app/SubmitConfigService.kt
deleted file mode 100644
index c38acd0..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/SubmitConfigService.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.tsng.hidemyapplist.app
-
-import android.app.Service
-import android.content.Intent
-import android.os.IBinder
-import com.tsng.hidemyapplist.app.JsonConfigManager.globalConfig
-import com.tsng.hidemyapplist.app.helpers.ServiceHelper
-import kotlin.concurrent.thread
-
-class SubmitConfigService : Service() {
- override fun onBind(intent: Intent): IBinder? {
- return null
- }
-
- override fun onCreate() {
- thread {
- while (true) {
- ServiceHelper.submitConfig(globalConfig.toString())
- Thread.sleep(1000)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/helpers/AppInfoHelper.kt b/app/src/main/java/com/tsng/hidemyapplist/app/helpers/AppInfoHelper.kt
deleted file mode 100644
index 8581a09..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/helpers/AppInfoHelper.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.tsng.hidemyapplist.app.helpers
-
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import com.tsng.hidemyapplist.app.MyApplication
-
-object AppInfoHelper {
- data class MyAppInfo(
- val appName: String,
- val packageName: String,
- val icon: Drawable,
- val isSystemApp: Boolean
- )
-
- private lateinit var mAppInfoList: MutableList
-
- fun getAppInfoList(): MutableList {
- if (AppInfoHelper::mAppInfoList.isInitialized) return mAppInfoList.toMutableList()
- mAppInfoList = mutableListOf()
- val pm = MyApplication.appContext.packageManager
- for (appInfo in pm.getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES)) {
- MyAppInfo(
- appInfo.loadLabel(pm).toString(),
- appInfo.packageName,
- appInfo.loadIcon(pm),
- appInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0
- ).also { mAppInfoList.add(it) }
- }
- return mAppInfoList.toMutableList()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/helpers/PreferenceDataStorage.kt b/app/src/main/java/com/tsng/hidemyapplist/app/helpers/PreferenceDataStorage.kt
deleted file mode 100644
index f73da34..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/helpers/PreferenceDataStorage.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.tsng.hidemyapplist.app.helpers
-
-import androidx.preference.PreferenceDataStore
-import com.tsng.hidemyapplist.app.JsonConfigManager.globalConfig
-import icu.nullptr.hidemyapplist.common.JsonConfig
-
-class AppConfigDataStorage(
- private val packageName: String,
- private val appConfig: JsonConfig.AppConfig
-) : PreferenceDataStore() {
- var isEnabled = globalConfig.scope.containsKey(packageName)
- set(value) {
- field = value
- if (value) {
- globalConfig.scope[packageName] = appConfig
- } else {
- globalConfig.scope.remove(packageName)
- }
- }
-
- override fun getBoolean(key: String, defValue: Boolean): Boolean {
- return if (key == "isEnabled") isEnabled
- else JsonConfig.AppConfig::class.java.getDeclaredField(key)
- .also { it.isAccessible = true }
- .getBoolean(appConfig)
- }
-
- override fun putBoolean(key: String, value: Boolean) {
- if (key == "isEnabled") isEnabled = value
- else JsonConfig.AppConfig::class.java.getDeclaredField(key)
- .also { it.isAccessible = true }
- .setBoolean(appConfig, value)
- }
-
- override fun getStringSet(key: String, defValues: MutableSet?): MutableSet {
- return JsonConfig.AppConfig::class.java.getDeclaredField(key)
- .also { it.isAccessible = true }
- .get(appConfig) as MutableSet
- }
-
- override fun putStringSet(key: String, values: MutableSet?) {
- JsonConfig.AppConfig::class.java.getDeclaredField(key)
- .also { it.isAccessible = true }
- .set(appConfig, values)
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/LogActivity.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/LogActivity.kt
deleted file mode 100644
index 535e927..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/LogActivity.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.activities
-
-import android.content.Intent
-import android.os.Build
-import android.os.Bundle
-import android.view.*
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.content.FileProvider
-import androidx.fragment.app.Fragment
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.helpers.ServiceHelper
-import com.tsng.hidemyapplist.databinding.ActivityLogBinding
-import com.tsng.hidemyapplist.databinding.FragmentLogRawBinding
-import java.io.File
-import java.text.SimpleDateFormat
-import java.util.*
-
-class LogActivity : AppCompatActivity() {
- private lateinit var binding: ActivityLogBinding
- var rawLogs: String? = null
- var showRawLogs: Boolean = true
-
- override fun onSupportNavigateUp(): Boolean {
- onBackPressed()
- return true
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- menuInflater.inflate(R.menu.log, menu)
- return true
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- R.id.toolbar_refresh -> {
- rawLogs = ServiceHelper.getLogs()
-
- replaceFragment(RawFragment())
- // replaceFragment(if (showRawLogs) BuiltifulFragment() else RawFragment())
- true
- }
- R.id.toolbar_export -> {
- val date = SimpleDateFormat("MM-dd_HH-mm-ss", Locale.getDefault()).format(Date())
- File(cacheDir.path + "/logs").mkdirs()
- val tmp = File(cacheDir.path + "/logs/hma_logs_$date.log")
- rawLogs?.let { tmp.writeText(it) }
- val intent = Intent(Intent.ACTION_SEND).apply {
- type = "text/*"
- val uri = FileProvider.getUriForFile(
- this@LogActivity,
- "com.tsng.hidemyapplist.fileprovider",
- tmp
- )
- putExtra(Intent.EXTRA_STREAM, uri)
- }
- startActivity(Intent.createChooser(intent, title))
- true
- }
- R.id.toolbar_clean -> {
- ServiceHelper.cleanLogs()
- rawLogs = null
-
- replaceFragment(RawFragment())
- // replaceFragment(if (showRawLogs) BuiltifulFragment() else RawFragment())
- true
- }
- /*
- R.id.toolbar_raw_logs -> {
- item.isChecked = !item.isChecked
- showRawLogs = item.isChecked
- replaceFragment(if (showRawLogs) BuiltifulFragment() else RawFragment())
- true
- }
- */
- else -> super.onOptionsItemSelected(item)
- }
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding = ActivityLogBinding.inflate(layoutInflater)
- setContentView(binding.root)
- setSupportActionBar(findViewById(R.id.toolbar))
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
- rawLogs = ServiceHelper.getLogs()
- replaceFragment(RawFragment())
- }
-
- private fun replaceFragment(fragment: Fragment) {
- supportFragmentManager
- .beginTransaction()
- .replace(R.id.log_container, fragment)
- .commit()
- }
-
- class RawFragment : Fragment() {
- private lateinit var binding: FragmentLogRawBinding
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- binding = FragmentLogRawBinding.inflate(inflater, container, false)
- return binding.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- binding.rawLogText.text = (requireActivity() as LogActivity).rawLogs
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/MainActivity.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/MainActivity.kt
deleted file mode 100644
index e2dfdb0..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/MainActivity.kt
+++ /dev/null
@@ -1,197 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.activities
-
-import android.annotation.SuppressLint
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.net.Uri
-import android.os.Build
-import android.os.Bundle
-import android.text.Html
-import android.view.View
-import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.content.res.AppCompatResources
-import androidx.preference.PreferenceManager
-import com.google.android.gms.ads.AdRequest
-import com.google.android.gms.ads.MobileAds
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.tsng.hidemyapplist.BuildConfig
-import com.tsng.hidemyapplist.Magic
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.MyApplication
-import com.tsng.hidemyapplist.app.MyApplication.Companion.appContext
-import com.tsng.hidemyapplist.app.SubmitConfigService
-import com.tsng.hidemyapplist.app.helpers.ServiceHelper
-import com.tsng.hidemyapplist.app.makeToast
-import com.tsng.hidemyapplist.databinding.ActivityMainBinding
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import org.json.JSONObject
-import java.util.*
-import kotlin.concurrent.thread
-
-class MainActivity : AppCompatActivity(), View.OnClickListener {
- private lateinit var binding: ActivityMainBinding
-
- @SuppressLint("PackageManagerGetSignatures")
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- val sig = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- val s = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES).signingInfo
- s.apkContentsSigners[0].toByteArray()
- } else {
- val s = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures
- s[0].toByteArray()
- }
- if (sig.contentEquals(Magic.magicNumbers)) {
- startService(Intent(this, SubmitConfigService::class.java))
- }
-
- binding = ActivityMainBinding.inflate(layoutInflater)
-
- binding.menuDetectionTest.setOnClickListener(this)
- binding.menuTemplateManage.setOnClickListener(this)
- binding.menuScopeManage.setOnClickListener(this)
- binding.menuLogs.setOnClickListener(this)
- binding.menuSettings.setOnClickListener(this)
- binding.menuAbout.setOnClickListener(this)
-
- setContentView(binding.root)
- setSupportActionBar(findViewById(R.id.toolbar))
- MobileAds.initialize(appContext)
- binding.adBanner.loadAd(AdRequest.Builder().build())
- makeUpdateAlert()
- }
-
- @SuppressLint("SetTextI18n")
- override fun onResume() {
- super.onResume()
- val serviceVersion = ServiceHelper.getServiceVersion()
- if (MyApplication.isModuleActivated) {
- if (serviceVersion != 0) {
- binding.moduleStatusCard.setCardBackgroundColor(getColor(run {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) android.R.color.system_accent1_600
- else R.color.primary
- }))
- binding.moduleStatusIcon.setImageDrawable(AppCompatResources.getDrawable(this, R.drawable.ic_activited))
- binding.moduleStatusText.text = getString(R.string.xposed_activated)
- } else {
- binding.moduleStatusCard.setCardBackgroundColor(getColor(R.color.error))
- binding.moduleStatusIcon.setImageDrawable(AppCompatResources.getDrawable(this, R.drawable.ic_service_not_running))
- binding.moduleStatusText.text = getString(R.string.xposed_activated)
- }
- } else {
- binding.moduleStatusCard.setCardBackgroundColor(getColor(R.color.gray))
- binding.moduleStatusIcon.setImageDrawable(AppCompatResources.getDrawable(this, R.drawable.ic_not_activated))
- binding.moduleStatusText.text = getString(R.string.xposed_not_activated)
- }
-
- if (serviceVersion != 0) {
- binding.serviceStatusText.text =
- if (serviceVersion != icu.nullptr.hidemyapplist.common.BuildConfig.SERVICE_VERSION)
- getString(R.string.xposed_service_old)
- else
- getString(R.string.xposed_service_on) + " [$serviceVersion]"
- val text = getString(R.string.xposed_serve_times).split("#")
-
- binding.serveTimes.visibility = View.VISIBLE
- binding.serveTimes.text = text[0] + ServiceHelper.getServeTimes() + text[2]
- } else {
- binding.serveTimes.visibility = View.GONE
- binding.serviceStatusText.text = getString(R.string.xposed_service_off)
- }
- }
-
- override fun onClick(v: View) {
- when (v.id) {
- R.id.menu_detection_test -> {
- val intent = packageManager.getLaunchIntentForPackage("icu.nullptr.applistdetector")
- if (intent == null) {
- MaterialAlertDialogBuilder(this)
- .setTitle(R.string.download_test_app_title)
- .setMessage(R.string.download_test_app_message)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok) { _, _ ->
- startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/Dr-TSNG/ApplistDetector/releases")))
- }
- .show()
- } else startActivity(intent)
- }
- R.id.menu_template_manage ->
- startActivity(
- Intent(this, ModuleActivity::class.java)
- .putExtra("Fragment", ModuleActivity.Fragment.TEMPLATE_MANAGE)
- )
- R.id.menu_scope_manage ->
- startActivity(
- Intent(this, ModuleActivity::class.java)
- .putExtra("Fragment", ModuleActivity.Fragment.SCOPE_MANAGE)
- )
- R.id.menu_logs ->
- if (ServiceHelper.getServiceVersion() == 0) makeToast(R.string.xposed_service_off)
- else startActivity(Intent(this, LogActivity::class.java))
- R.id.menu_settings -> startActivity(
- Intent(this, ModuleActivity::class.java)
- .putExtra("Fragment", ModuleActivity.Fragment.SETTINGS)
- )
- R.id.menu_about -> startActivity(Intent(this, AboutActivity::class.java))
- }
- }
-
- private fun makeUpdateAlert() {
- if (getSharedPreferences("settings", MODE_PRIVATE).getBoolean("disableUpdate", false)) return
- val pref = PreferenceManager.getDefaultSharedPreferences(this)
- val oldVersion = pref.getInt("lastVersion", 0)
- thread {
- try {
- val client = OkHttpClient()
- val responseData = client.newCall(
- Request.Builder()
- .url("https://cdn.jsdelivr.net/gh/Dr-TSNG/Hide-My-Applist@updates/updates/latest_version.json")
- .build()
- ).execute().body?.string()
- if (responseData != null) {
- val json = JSONObject(responseData)
- var data = json["Stable"] as JSONObject
- var updateLogURL = "https://cdn.jsdelivr.net/gh/Dr-TSNG/Hide-My-Applist@updates/updates/stable-"
- if (getSharedPreferences("settings", MODE_PRIVATE).getBoolean("receiveBetaUpdate", false))
- if (json["Beta"] != false) {
- data = json["Beta"] as JSONObject
- updateLogURL = "https://cdn.jsdelivr.net/gh/Dr-TSNG/Hide-My-Applist@updates/updates/beta-"
- }
- updateLogURL += if (Locale.getDefault().language.contains("zh")) "zh" else "en"
- updateLogURL += ".html"
- val updateLog = client.newCall(
- Request.Builder()
- .url(updateLogURL)
- .build()
- ).execute().body?.string()
- val githubDownloadUri = Uri.parse(data["DownloadURL"] as String)
- if (data.getInt("VersionCode") > BuildConfig.VERSION_CODE) runOnUiThread {
- MaterialAlertDialogBuilder(this)
- .setTitle(getString(R.string.new_update) + data["VersionName"])
- .setMessage(Html.fromHtml(updateLog, Html.FROM_HTML_MODE_COMPACT))
- .setPositiveButton("GitHub") { _, _ ->
- startActivity(Intent(Intent.ACTION_VIEW, githubDownloadUri))
- }
- .setNegativeButton("TG Channel") { _, _ ->
- startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/HideMyApplist")))
- }
- .setNeutralButton(android.R.string.cancel, null)
- .setCancelable(false).show()
- } else if (oldVersion < BuildConfig.VERSION_CODE) runOnUiThread {
- MaterialAlertDialogBuilder(this)
- .setTitle(R.string.update_logs)
- .setMessage(Html.fromHtml(updateLog, Html.FROM_HTML_MODE_COMPACT))
- .setPositiveButton(android.R.string.ok, null)
- .setCancelable(false)
- .show()
- }
- pref.edit().putInt("lastVersion", BuildConfig.VERSION_CODE).apply()
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/ModuleActivity.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/ModuleActivity.kt
deleted file mode 100644
index 0f92cae..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/activities/ModuleActivity.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.activities
-
-import android.os.Build
-import android.os.Bundle
-import android.view.WindowManager
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.view.WindowCompat
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.startFragment
-import com.tsng.hidemyapplist.app.ui.fragments.ScopeManageFragment
-import com.tsng.hidemyapplist.app.ui.fragments.SettingsFragment
-import com.tsng.hidemyapplist.app.ui.fragments.TemplateManageFragment
-import com.tsng.hidemyapplist.databinding.ActivityModuleBinding
-
-class ModuleActivity : AppCompatActivity() {
- enum class Fragment {
- TEMPLATE_MANAGE,
- SCOPE_MANAGE,
- SETTINGS
- }
-
- private lateinit var binding: ActivityModuleBinding
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- WindowCompat.setDecorFitsSystemWindows(window, true)
- binding = ActivityModuleBinding.inflate(layoutInflater)
- setContentView(binding.root)
- setSupportActionBar(findViewById(R.id.toolbar))
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
- when (intent.extras?.get("Fragment") as Fragment) {
- Fragment.TEMPLATE_MANAGE -> {
- setTitle(R.string.title_template_manage)
- startFragment(TemplateManageFragment(), false)
- }
- Fragment.SCOPE_MANAGE -> {
- setTitle(R.string.title_scope_manage)
- startFragment(ScopeManageFragment(), false)
- }
- Fragment.SETTINGS -> {
- setTitle(R.string.title_settings)
- startFragment(SettingsFragment(), false)
- }
- }
- }
-
- override fun onSupportNavigateUp(): Boolean {
- onBackPressed()
- return true
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/adapters/AppSelectAdapter.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/adapters/AppSelectAdapter.kt
deleted file mode 100644
index 8ff2574..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/adapters/AppSelectAdapter.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.adapters
-
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.*
-import androidx.recyclerview.widget.RecyclerView
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.MyApplication.Companion.appContext
-import com.tsng.hidemyapplist.app.helpers.AppInfoHelper.MyAppInfo
-import java.util.*
-
-class AppSelectAdapter(
- var isShowSystemApp: Boolean,
- private val hasCheckBox: Boolean,
- private val appList: List,
- private val selectedApps: MutableSet,
- private val onClick: (ViewHolder.() -> Unit)? = null
-) : Filterable,
- RecyclerView.Adapter() {
- inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
- val imageView: ImageView = view.findViewById(R.id.app_icon)
- val appNameTextView: TextView = view.findViewById(R.id.app_name)
- val packageNameTextView: TextView = view.findViewById(R.id.app_package_name)
- val summaryTextView: TextView = view.findViewById(R.id.app_summary)
- val checkBox: CheckBox = view.findViewById(R.id.checkbox)
- }
-
- private var mFilteredList: List = listOf()
-
- init {
- filter.filter("")
- }
-
- override fun getFilter() = object : Filter() {
- override fun performFiltering(constraint: CharSequence): FilterResults {
- val filteredList = mutableListOf()
- for (appInfo in appList) {
- if (!appInfo.isSystemApp || isShowSystemApp)
- if (constraint.isEmpty() ||
- appInfo.appName.lowercase(Locale.getDefault()).contains(constraint) ||
- appInfo.packageName.lowercase(Locale.getDefault()).contains(constraint)
- ) filteredList.add(appInfo)
- }
- return FilterResults().apply { values = filteredList }
- }
-
- override fun publishResults(constraint: CharSequence, results: FilterResults) {
- mFilteredList = results.values as List
- notifyDataSetChanged()
- }
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- val view = LayoutInflater.from(parent.context)
- .inflate(R.layout.recycler_app_select, parent, false)
- val viewHolder = ViewHolder(view)
- onClick?.let { viewHolder.it() }
- if (!hasCheckBox) viewHolder.checkBox.visibility = View.GONE
- return viewHolder
- }
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val appInfo = mFilteredList[position]
- holder.imageView.setImageDrawable(appInfo.icon)
- holder.appNameTextView.text = appInfo.appName
- holder.packageNameTextView.text = appInfo.packageName
- if (!hasCheckBox && selectedApps.contains(appInfo.packageName))
- holder.appNameTextView.setTextColor(appContext.resources.getColor(android.R.color.holo_green_light))
- else
- holder.appNameTextView.setTextColor(appContext.resources.getColor(android.R.color.black))
- if (appInfo.isSystemApp) {
- holder.summaryTextView.visibility = View.VISIBLE
- holder.summaryTextView.setText(R.string.system_app)
- } else holder.summaryTextView.visibility = View.INVISIBLE
-
- if (hasCheckBox) {
- holder.checkBox.setOnCheckedChangeListener { _, isChecked ->
- if (isChecked) selectedApps.add(appInfo.packageName)
- else selectedApps.remove(appInfo.packageName)
- }
- holder.checkBox.isChecked = selectedApps.contains(appInfo.packageName)
- }
- }
-
- override fun getItemCount() = mFilteredList.size
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/adapters/TemplateListAdapter.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/adapters/TemplateListAdapter.kt
deleted file mode 100644
index 0223a76..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/adapters/TemplateListAdapter.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.adapters
-
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.recyclerview.widget.RecyclerView
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.startFragment
-import com.tsng.hidemyapplist.app.ui.fragments.TemplateSettingsFragment
-
-class TemplateListAdapter(
- private val templateList: List>,
- private val mFragment: Fragment
-) : RecyclerView.Adapter() {
- inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
- var isWhitelist = false
- lateinit var templateName: String
-
- val imageView: ImageView = view.findViewById(R.id.template_icon)
- val textView: TextView = view.findViewById(R.id.template_name)
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- val view = LayoutInflater.from(parent.context)
- .inflate(R.layout.recycler_templates, parent, false)
- val viewHolder = ViewHolder(view)
- viewHolder.itemView.setOnClickListener {
- mFragment.startFragment(
- TemplateSettingsFragment.newInstance(
- viewHolder.isWhitelist,
- viewHolder.templateName
- )
- )
- }
- return viewHolder
- }
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val pair = templateList[position]
- holder.templateName = pair.first
- holder.isWhitelist = pair.second
-
- holder.imageView.setImageResource(
- if (pair.second) R.drawable.ic_file_white
- else R.drawable.ic_file_black
- )
- holder.textView.text = pair.first
- }
-
- override fun getItemCount() = templateList.size
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/AppSelectFragment.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/AppSelectFragment.kt
deleted file mode 100644
index bf74244..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/AppSelectFragment.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.fragments
-
-import android.os.Bundle
-import android.view.*
-import androidx.appcompat.widget.SearchView
-import androidx.core.os.bundleOf
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.setFragmentResult
-import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.LinearLayoutManager
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.helpers.AppInfoHelper
-import com.tsng.hidemyapplist.app.ui.adapters.AppSelectAdapter
-import com.tsng.hidemyapplist.app.ui.views.Ads
-import com.tsng.hidemyapplist.databinding.FragmentAppSelectBinding
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.text.Collator
-import java.util.*
-import kotlin.concurrent.thread
-
-class AppSelectFragment : Fragment() {
-
- companion object {
-
- @JvmStatic
- fun newInstance(selectedApps: Array, requestKey: String? = null) =
- AppSelectFragment().apply {
- arguments = bundleOf(
- "selectedApps" to selectedApps,
- "requestKey" to requestKey
- )
- }
- }
-
- private lateinit var binding: FragmentAppSelectBinding
- private lateinit var selectedApps: MutableSet
- private lateinit var requestKey: String
- private var adapter: AppSelectAdapter? = null
- private var isShowSystemApp = false
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setHasOptionsMenu(true)
- selectedApps = arguments?.getStringArray("selectedApps")?.toHashSet() ?: mutableSetOf()
- requestKey = arguments?.getString("requestKey", null) ?: "appSelectResult"
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- binding = FragmentAppSelectBinding.inflate(inflater, container, false)
- binding.adBanner.loadAd(Ads.appSelectAd)
- binding.refreshLayout.setOnRefreshListener {
- lifecycleScope.launch { refresh() }
- }
- binding.refreshLayout.isRefreshing = true
- lifecycleScope.launch { refresh() }
- return binding.root
- }
-
- override fun onDestroyView() {
- setFragmentResult(
- requestKey,
- bundleOf("selectedApps" to selectedApps.toTypedArray())
- )
- super.onDestroyView()
- }
-
- override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
- inflater.inflate(R.menu.appselect, menu)
- val searchView = menu.findItem(R.id.toolbar_search).actionView as SearchView
- searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
- override fun onQueryTextSubmit(query: String) = false
-
- override fun onQueryTextChange(newText: String): Boolean {
- adapter?.filter?.filter(newText.lowercase(Locale.getDefault()))
- return true
- }
- })
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- when (item.itemId) {
- R.id.toolbar_show_system_apps -> {
- isShowSystemApp = !isShowSystemApp
- item.isChecked = isShowSystemApp
- adapter?.isShowSystemApp = isShowSystemApp
- adapter?.filter?.filter("")
- }
- else -> return false
- }
- return true
- }
-
- private suspend fun refresh() {
- initAppListView()
- withContext(Dispatchers.Main) {
- binding.refreshLayout.isRefreshing = false
- }
- }
-
- private suspend fun initAppListView() {
- val appInfoList = AppInfoHelper.getAppInfoList()
- appInfoList.sortWith { o1, o2 ->
- val c1 = selectedApps.contains(o1.packageName)
- val c2 = selectedApps.contains(o2.packageName)
- if (c1 != c2) return@sortWith if (c1) -1 else 1
- Collator.getInstance(Locale.getDefault()).compare(o1.appName, o2.appName)
- }
- withContext(Dispatchers.Main) {
- binding.appSelect.layoutManager = LinearLayoutManager(activity)
- adapter = AppSelectAdapter(isShowSystemApp, true, appInfoList, selectedApps)
- binding.appSelect.adapter = adapter
- }
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/AppSettingsFragment.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/AppSettingsFragment.kt
deleted file mode 100644
index de8830c..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/AppSettingsFragment.kt
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.fragments
-
-import android.content.DialogInterface
-import android.content.pm.PackageManager
-import android.os.Bundle
-import androidx.core.os.bundleOf
-import androidx.fragment.app.setFragmentResultListener
-import androidx.preference.Preference
-import androidx.preference.PreferenceFragmentCompat
-import androidx.preference.SwitchPreferenceCompat
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.JsonConfigManager
-import com.tsng.hidemyapplist.app.JsonConfigManager.globalConfig
-import com.tsng.hidemyapplist.app.MyApplication.Companion.appContext
-import com.tsng.hidemyapplist.app.helpers.AppConfigDataStorage
-import com.tsng.hidemyapplist.app.makeToast
-import com.tsng.hidemyapplist.app.startFragment
-import com.tsng.hidemyapplist.app.ui.views.FilterRulesView
-import icu.nullptr.hidemyapplist.common.JsonConfig
-
-class AppSettingsFragment : PreferenceFragmentCompat() {
- companion object {
- @JvmStatic
- fun newInstance(packageName: String) =
- AppSettingsFragment().apply {
- arguments = bundleOf("packageName" to packageName)
- }
- }
-
- private lateinit var packageName: String
- private lateinit var appConfig: JsonConfig.AppConfig
-
- override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- packageName = requireArguments().getString("packageName")!!
- appConfig = globalConfig.scope.getOrDefault(packageName, JsonConfig.AppConfig())
- preferenceManager.preferenceDataStore = AppConfigDataStorage(packageName, appConfig)
- setPreferencesFromResource(R.xml.app_preferences, rootKey)
-
- preferenceScreen.findPreference("appInfo")?.let {
- val appInfo = appContext.packageManager.getApplicationInfo(
- packageName,
- PackageManager.MATCH_UNINSTALLED_PACKAGES or PackageManager.MATCH_DISABLED_COMPONENTS
- )
- it.icon = appInfo.loadIcon(appContext.packageManager)
- it.title = appInfo.loadLabel(appContext.packageManager)
- it.summary = packageName
- }
-
- preferenceScreen.findPreference("copyConfig")
- ?.setOnPreferenceClickListener {
- startFragment(AppSelectFragment.newInstance(arrayOf(packageName), "copyConfig"))
- true
- }
-
- setFragmentResultListener("copyConfig") { _, bundle ->
- bundle.getStringArray("selectedApps")?.let { arr ->
- JsonConfigManager.edit {
- arr.forEach { scope[it] = appConfig }
- }
- makeToast(R.string.copied)
- }
- }
-
- preferenceScreen.findPreference("useWhitelist")
- ?.setOnPreferenceClickListener {
- appConfig.applyTemplates.clear()
- appConfig.extraAppList.clear()
- updateView()
- true
- }
-
- preferenceScreen.findPreference("applyTemplates")
- ?.setOnPreferenceClickListener {
- val list = mutableListOf()
- val checked = mutableListOf()
- for ((name, template) in globalConfig.templates)
- if (appConfig.useWhitelist == template.isWhitelist) {
- list.add(name)
- checked.add(appConfig.applyTemplates.contains(name))
- }
- val arrayList = list.toTypedArray()
- val arrayChecked = checked.toBooleanArray()
- MaterialAlertDialogBuilder(requireActivity())
- .setTitle(R.string.template_choose)
- .setMultiChoiceItems(
- arrayList,
- arrayChecked
- ) { _: DialogInterface, i: Int, b: Boolean -> arrayChecked[i] = b }
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok) { _, _ ->
- for (i in arrayList.indices)
- if (arrayChecked[i]) appConfig.applyTemplates.add(arrayList[i])
- else appConfig.applyTemplates.remove(arrayList[i])
- updateView()
- }
- .show()
- true
- }
-
- preferenceScreen.findPreference("extraAppList")
- ?.setOnPreferenceClickListener {
- startFragment(
- AppSelectFragment.newInstance(
- appConfig.extraAppList.toTypedArray(),
- "extraAppList"
- )
- )
- true
- }
-
- setFragmentResultListener("extraAppList") { _, bundle ->
- bundle.getStringArray("selectedApps")?.let {
- appConfig.extraAppList.clear()
- appConfig.extraAppList.addAll(it)
- updateView()
- }
- }
-
- preferenceScreen.findPreference("extraQueryParamRules")
- ?.setOnPreferenceClickListener {
- FilterRulesView.show(requireActivity(), appConfig.extraQueryParamRules) {
- it.title = getString(
- R.string.template_extra_query_param_rules_count,
- appConfig.extraQueryParamRules.size
- )
- }
- true
- }
-
- updateView()
- }
-
- private fun updateView() {
- preferenceScreen.findPreference("applyTemplates")?.title =
- getString(R.string.template_applied_count, appConfig.applyTemplates.size)
-
- preferenceScreen.findPreference("extraAppList")?.title =
- getString(
- if (appConfig.useWhitelist) R.string.template_extra_apps_visible_count
- else R.string.template_extra_apps_invisible_count,
- appConfig.extraAppList.size
- )
-
- preferenceScreen.findPreference("extraQueryParamRules")?.title =
- getString(
- R.string.template_extra_query_param_rules_count,
- appConfig.extraQueryParamRules.size
- )
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/ScopeManageFragment.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/ScopeManageFragment.kt
deleted file mode 100644
index 17f6256..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/ScopeManageFragment.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.fragments
-
-import android.os.Bundle
-import android.view.*
-import androidx.appcompat.widget.SearchView
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.LinearLayoutManager
-import com.tsng.hidemyapplist.BuildConfig
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.JsonConfigManager.globalConfig
-import com.tsng.hidemyapplist.app.helpers.AppInfoHelper
-import com.tsng.hidemyapplist.app.startFragment
-import com.tsng.hidemyapplist.app.ui.adapters.AppSelectAdapter
-import com.tsng.hidemyapplist.app.ui.views.Ads
-import com.tsng.hidemyapplist.databinding.FragmentAppSelectBinding
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.text.Collator
-import java.util.*
-
-class ScopeManageFragment : Fragment() {
-
- private lateinit var binding: FragmentAppSelectBinding
- private var adapter: AppSelectAdapter? = null
- private var isShowSystemApp = false
- private var touchedItemPosition = -1
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setHasOptionsMenu(true)
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- binding = FragmentAppSelectBinding.inflate(inflater, container, false)
- binding.adBanner.loadAd(Ads.appSelectAd)
- binding.refreshLayout.setOnRefreshListener {
- lifecycleScope.launch { refresh() }
- }
- binding.refreshLayout.isRefreshing = true
- lifecycleScope.launch { refresh() }
- return binding.root
- }
-
- override fun onHiddenChanged(hidden: Boolean) {
- if (!hidden && touchedItemPosition != -1)
- adapter?.notifyItemChanged(touchedItemPosition)
- }
-
- override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
- inflater.inflate(R.menu.appselect, menu)
- val searchView = menu.findItem(R.id.toolbar_search).actionView as SearchView
- searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
- override fun onQueryTextSubmit(query: String) = false
-
- override fun onQueryTextChange(newText: String): Boolean {
- adapter?.filter?.filter(newText.lowercase(Locale.getDefault()))
- return true
- }
- })
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- when (item.itemId) {
- R.id.toolbar_show_system_apps -> {
- isShowSystemApp = !isShowSystemApp
- item.isChecked = isShowSystemApp
- adapter?.isShowSystemApp = isShowSystemApp
- adapter?.filter?.filter("")
- }
- else -> return false
- }
- return true
- }
-
- private suspend fun refresh() {
- initAppListView()
- withContext(Dispatchers.Main) {
- binding.refreshLayout.isRefreshing = false
- }
- }
-
- private suspend fun initAppListView() {
- val appInfoList = AppInfoHelper.getAppInfoList()
- appInfoList.removeIf { it.packageName == BuildConfig.APPLICATION_ID }
- val selectedApps = globalConfig.scope.keys
- appInfoList.sortWith { o1, o2 ->
- val b1 = selectedApps.contains(o1.packageName)
- val b2 = selectedApps.contains(o2.packageName)
- if (b1 != b2) return@sortWith if (b1) -1 else 1
- Collator.getInstance(Locale.getDefault()).compare(o1.appName, o2.appName)
- }
- withContext(Dispatchers.Main) {
- binding.appSelect.layoutManager = LinearLayoutManager(activity)
- adapter = AppSelectAdapter(isShowSystemApp, false, appInfoList, selectedApps) {
- itemView.setOnClickListener {
- touchedItemPosition = layoutPosition
- val packageName = packageNameTextView.text.toString()
- startFragment(AppSettingsFragment.newInstance(packageName))
- }
- }
- binding.appSelect.adapter = adapter
- }
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/SettingsFragment.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/SettingsFragment.kt
deleted file mode 100644
index 21942f6..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/SettingsFragment.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.fragments
-
-import android.content.ComponentName
-import android.content.pm.PackageManager
-import android.os.Bundle
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.preference.ListPreference
-import androidx.preference.Preference
-import androidx.preference.PreferenceFragmentCompat
-import androidx.preference.SwitchPreferenceCompat
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.topjohnwu.superuser.Shell
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.JsonConfigManager
-import com.tsng.hidemyapplist.app.MyApplication.Companion.appContext
-import com.tsng.hidemyapplist.app.helpers.ServiceHelper
-import com.tsng.hidemyapplist.app.makeToast
-import icu.nullptr.hidemyapplist.common.BuildConfig
-import icu.nullptr.hidemyapplist.common.JsonConfig
-
-class SettingsFragment : PreferenceFragmentCompat() {
-
- private val backupImportSAFLauncher =
- registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
- if (uri == null) return@registerForActivityResult
- try {
- val backupJson = appContext.contentResolver
- .openInputStream(uri)?.reader().use { it?.readText() }
- ?: throw RuntimeException(getString(R.string.settings_import_file_damaged))
- val backup: JsonConfig
- try {
- backup = JsonConfig.parse(backupJson)
- } catch (e: Exception) {
- throw RuntimeException(getString(R.string.settings_import_file_damaged), e)
- }
- if (backup.configVersion > BuildConfig.SERVICE_VERSION)
- throw RuntimeException(getString(R.string.settings_import_app_version_too_old))
- if (backup.configVersion < BuildConfig.MIN_BACKUP_VERSION)
- throw RuntimeException(getString(R.string.settings_import_backup_version_too_old))
- JsonConfigManager.edit {
- templates.clear()
- templates.putAll(backup.templates)
- scope.clear()
- scope.putAll(backup.scope)
- }
- makeToast(R.string.settings_import_successful)
- } catch (e: Exception) {
- e.printStackTrace()
- MaterialAlertDialogBuilder(requireActivity())
- .setCancelable(false)
- .setTitle(R.string.settings_import_failed)
- .setMessage(e.message)
- .setPositiveButton(android.R.string.ok, null)
- .setNegativeButton(R.string.show_crash_log) { _, _ ->
- MaterialAlertDialogBuilder(requireActivity())
- .setCancelable(false)
- .setTitle(R.string.settings_import_failed)
- .setMessage(e.stackTraceToString())
- .setPositiveButton(android.R.string.ok, null)
- .show()
- }
- .show()
- }
- }
-
- private val backupExportSAFLauncher =
- registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
- if (uri == null) return@registerForActivityResult
- JsonConfigManager.configFile.inputStream().use { fis ->
- appContext.contentResolver.openOutputStream(uri).use { fos ->
- if (fos == null) makeToast(R.string.settings_export_failed)
- else fis.copyTo(fos)
- }
- }
- makeToast(R.string.settings_exported)
- }
-
- override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- preferenceManager.sharedPreferencesName = "settings"
- setPreferencesFromResource(R.xml.settings_preferences, rootKey)
- module()
- service()
- backup()
- }
-
- private fun module() {
- preferenceScreen.findPreference("detailLog")
- ?.setOnPreferenceChangeListener { _, newValue ->
- JsonConfigManager.edit { detailLog = newValue as Boolean }
- true
- }
-
- preferenceScreen.findPreference("maxLogSize")?.apply {
- summary = entry
- setOnPreferenceChangeListener { _, newValue ->
- JsonConfigManager.edit {
- maxLogSize = (newValue as String).toInt()
- }
- summary = entries[findIndexOfValue(newValue as String)]
- true
- }
- }
-
- preferenceScreen.findPreference("hideIcon")
- ?.setOnPreferenceChangeListener { _, newValue ->
- val component =
- ComponentName(appContext, "com.tsng.hidemyapplist.MainActivityLauncher")
- val status =
- if (newValue == true) PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- else PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- appContext.packageManager
- .setComponentEnabledSetting(component, status, PackageManager.DONT_KILL_APP)
- true
- }
- }
-
- private fun service() {
- preferenceScreen.findPreference("stopSystemService")
- ?.setOnPreferenceClickListener {
- if (ServiceHelper.getServiceVersion() != 0) {
- MaterialAlertDialogBuilder(requireActivity())
- .setTitle(R.string.settings_is_clean_env)
- .setMessage(R.string.settings_is_clean_env_summary)
- .setPositiveButton(R.string.yes) { _, _ ->
- ServiceHelper.stopSystemService(true)
- makeToast(R.string.settings_stop_system_service)
- }
- .setNegativeButton(R.string.no) { _, _ ->
- ServiceHelper.stopSystemService(false)
- makeToast(R.string.settings_stop_system_service)
- }
- .setNeutralButton(android.R.string.cancel, null)
- .show()
- } else makeToast(R.string.xposed_service_off)
- true
- }
- preferenceScreen.findPreference("forceCleanEnv")
- ?.setOnPreferenceClickListener {
- MaterialAlertDialogBuilder(requireActivity())
- .setTitle(R.string.settings_force_clean_env)
- .setMessage(R.string.settings_is_clean_env_summary)
- .setPositiveButton(android.R.string.ok) { _, _ ->
- val result =
- Shell.su("rm -rf /data/misc/hide_my_applist /data/misc/hma_selinux_test")
- .exec().isSuccess
- if (result) makeToast(R.string.settings_force_clean_env_toast_successful)
- else makeToast(R.string.settings_force_clean_env_toast_failed)
- }
- .setNegativeButton(android.R.string.cancel, null)
- .show()
- true
- }
- }
-
- private fun backup() {
- preferenceScreen.findPreference("importConfig")
- ?.setOnPreferenceClickListener {
- backupImportSAFLauncher.launch("application/json")
- true
- }
- preferenceScreen.findPreference("exportConfig")
- ?.setOnPreferenceClickListener {
- backupExportSAFLauncher.launch("HMA Config.json")
- true
- }
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/TemplateManageFragment.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/TemplateManageFragment.kt
deleted file mode 100644
index 3deaaa3..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/TemplateManageFragment.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.fragments
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import androidx.recyclerview.widget.LinearLayoutManager
-import com.tsng.hidemyapplist.app.JsonConfigManager.globalConfig
-import com.tsng.hidemyapplist.app.startFragment
-import com.tsng.hidemyapplist.app.ui.adapters.TemplateListAdapter
-import com.tsng.hidemyapplist.databinding.FragmentTemplateManageBinding
-import java.text.Collator
-import java.util.*
-
-class TemplateManageFragment : Fragment() {
- private lateinit var binding: FragmentTemplateManageBinding
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- binding = FragmentTemplateManageBinding.inflate(inflater, container, false)
- binding.createBlacklist.setOnClickListener {
- startFragment(TemplateSettingsFragment.newInstance(false, null))
- }
- binding.createWhitelist.setOnClickListener {
- startFragment(TemplateSettingsFragment.newInstance(true, null))
- }
- buildTemplateList()
- return binding.root
- }
-
- override fun onHiddenChanged(hidden: Boolean) {
- if (!hidden) buildTemplateList()
- }
-
- private fun buildTemplateList() {
- val adapterList = mutableListOf>()
- for ((name, template) in globalConfig.templates)
- adapterList.add(name to template.isWhitelist)
- adapterList.sortWith { o1, o2 ->
- if (o1.second != o2.second) if (o1.second) 1 else -1
- else Collator.getInstance(Locale.getDefault()).compare(o1.first, o2.first)
- }
- binding.templateList.layoutManager = LinearLayoutManager(activity)
- binding.templateList.adapter = TemplateListAdapter(adapterList, this)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/TemplateSettingsFragment.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/TemplateSettingsFragment.kt
deleted file mode 100644
index eb14245..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/fragments/TemplateSettingsFragment.kt
+++ /dev/null
@@ -1,158 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.fragments
-
-import android.app.Activity
-import android.os.Bundle
-import android.view.*
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.setFragmentResultListener
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.tsng.hidemyapplist.R
-import com.tsng.hidemyapplist.app.JsonConfigManager
-import com.tsng.hidemyapplist.app.JsonConfigManager.globalConfig
-import com.tsng.hidemyapplist.app.makeToast
-import com.tsng.hidemyapplist.app.startFragment
-import com.tsng.hidemyapplist.app.ui.views.FilterRulesView
-import com.tsng.hidemyapplist.databinding.FragmentTemplateSettingsBinding
-import icu.nullptr.hidemyapplist.common.JsonConfig
-
-class TemplateSettingsFragment : Fragment() {
- companion object {
- @JvmStatic
- fun newInstance(isWhitelist: Boolean, templateName: String?) =
- TemplateSettingsFragment().apply {
- arguments = Bundle().apply {
- putBoolean("isWhitelist", isWhitelist)
- putString("templateName", templateName)
- }
- }
- }
-
- private lateinit var binding: FragmentTemplateSettingsBinding
- private lateinit var activity: Activity
- private lateinit var template: JsonConfig.Template
- private var oldTemplateName: String? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setHasOptionsMenu(true)
- activity = requireActivity()
- val isWhitelist = requireArguments().getBoolean("isWhitelist")
- oldTemplateName = requireArguments().getString("templateName")
- template = if (oldTemplateName == null) JsonConfig.Template(isWhitelist)
- else globalConfig.templates[oldTemplateName]!!.copy()
-
- setFragmentResultListener("appSelectResult") { _, bundle ->
- bundle.getStringArray("selectedApps")?.let {
- template.appList.clear()
- template.appList.addAll(it)
- binding.appList.setListCount(template.appList.size)
- }
- }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- binding = FragmentTemplateSettingsBinding.inflate(inflater, container, false)
- if (oldTemplateName != null) binding.templateName.setText(oldTemplateName)
- binding.appList.setRawText(
- if (template.isWhitelist) getString(R.string.template_apps_visible_count)
- else getString(R.string.template_apps_invisible_count)
- )
- initAppListView()
- initQueryParamRulesView()
- return binding.root
- }
-
- override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
- inflater.inflate(R.menu.delete_and_save, menu)
- if (oldTemplateName == null)
- menu.findItem(R.id.toolbar_delete).isVisible = false
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- when (item.itemId) {
- R.id.toolbar_delete -> {
- MaterialAlertDialogBuilder(activity)
- .setTitle(R.string.template_delete)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok) { _, _ ->
- JsonConfigManager.edit {
- for ((_, appConfig) in scope)
- appConfig.applyTemplates.remove(oldTemplateName)
- templates.remove(oldTemplateName)
- }
- activity.onBackPressed()
- }
- .show()
- return true
- }
- R.id.toolbar_save -> {
- val newTemplateName = binding.templateName.text.toString()
- if (newTemplateName.isEmpty()) {
- makeToast(R.string.template_name_cannot_be_empty)
- return true
- }
- if (oldTemplateName == null) { // A new template
- if (globalConfig.templates.containsKey(newTemplateName)) {
- makeToast(R.string.template_name_already_exist)
- } else {
- JsonConfigManager.edit { templates[newTemplateName] = template }
- activity.onBackPressed()
- }
- } else when { // Existing template
- oldTemplateName == newTemplateName -> {
- JsonConfigManager.edit { templates[newTemplateName] = template }
- activity.onBackPressed()
- }
- globalConfig.templates.containsKey(newTemplateName) -> {
- makeToast(R.string.template_name_already_exist)
- }
- else -> {
- JsonConfigManager.edit {
- for ((_, appConfig) in scope)
- with(appConfig.applyTemplates) {
- if (contains(oldTemplateName)) {
- remove(oldTemplateName)
- add(newTemplateName)
- }
- }
- templates.remove(oldTemplateName)
- templates[newTemplateName] = template
- }
- activity.onBackPressed()
- }
- }
- return true
- }
- else -> return false
- }
- }
-
- private fun initAppListView() {
- var cnt = 0
- globalConfig.scope.forEach { (_, appConfig) ->
- if (appConfig.applyTemplates.contains(oldTemplateName)) cnt++
- }
- binding.effectiveApps.setListCount(cnt)
- with(binding.appList) {
- setListCount(template.appList.size)
- setOnButtonClickListener {
- startFragment(AppSelectFragment.newInstance(template.appList.toTypedArray()))
- }
- }
- }
-
- private fun initQueryParamRulesView() {
- with(binding.queryParamRules) {
- setListCount(template.queryParamRules.size)
- setOnButtonClickListener {
- FilterRulesView.show(activity, template.queryParamRules) {
- setListCount(template.queryParamRules.size)
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/views/Ads.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/views/Ads.kt
deleted file mode 100644
index de5c17b..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/views/Ads.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.views
-
-import com.google.android.gms.ads.AdRequest
-
-object Ads {
-
- val appSelectAd: AdRequest by lazy {
- AdRequest.Builder().build()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tsng/hidemyapplist/app/ui/views/FilterRulesView.kt b/app/src/main/java/com/tsng/hidemyapplist/app/ui/views/FilterRulesView.kt
deleted file mode 100644
index ca16f70..0000000
--- a/app/src/main/java/com/tsng/hidemyapplist/app/ui/views/FilterRulesView.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.tsng.hidemyapplist.app.ui.views
-
-import android.app.Activity
-import android.view.View
-import android.widget.ArrayAdapter
-import android.widget.Button
-import android.widget.EditText
-import android.widget.ListView
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.tsng.hidemyapplist.R
-
-object FilterRulesView {
- @JvmStatic
- fun show(activity: Activity, ruleSet: MutableSet, updateUi: (() -> Unit)? = null) {
- val rules = ruleSet.toMutableList()
- val adapter = ArrayAdapter(activity, android.R.layout.simple_list_item_1, rules)
- MaterialAlertDialogBuilder(activity)
- .setTitle(R.string.template_add_filter_rules)
- .setView(
- View.inflate(
- activity,
- R.layout.alert_customize_filter_rules,
- null
- ).apply {
- findViewById(R.id.rule_list).apply {
- this.adapter = adapter
- setOnItemLongClickListener { _, _, position, _ ->
- MaterialAlertDialogBuilder(activity)
- .setTitle(R.string.template_delete_filter_rule)
- .setMessage(rules[position])
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok) { _, _ ->
- ruleSet.remove(rules[position])
- activity.runOnUiThread {
- adapter.remove(rules[position])
- updateUi?.let { it() }
- }
- }.show()
- true
- }
- }
- findViewById