Ugly material you
This commit is contained in:
parent
50a6fe27bf
commit
6c6af8dd54
128 changed files with 709 additions and 3235 deletions
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
12
app/proguard-rules.pro
vendored
12
app/proguard-rules.pro
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".app.MyApplication"
|
||||
android:name="icu.nullptr.hidemyapplist.MyApp"
|
||||
android:allowBackup="true"
|
||||
android:fullBackupOnly="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
|
@ -19,30 +19,11 @@
|
|||
android:supportsRtl="false"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.tsng.hidemyapplist.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_provider_paths" />
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name=".app.SubmitConfigService"
|
||||
android:enabled="true" />
|
||||
|
||||
<activity android:name=".app.ui.activities.ModuleActivity" />
|
||||
|
||||
<activity
|
||||
android:name="com.tsng.hidemyapplist.app.ui.activities.LogActivity"
|
||||
android:label="@string/title_logs" />
|
||||
<activity
|
||||
android:name="com.tsng.hidemyapplist.app.ui.activities.AboutActivity"
|
||||
android:name="icu.nullptr.hidemyapplist.ui.activity.AboutActivity"
|
||||
android:theme="@style/AppTheme.About" />
|
||||
<activity
|
||||
android:name=".app.ui.activities.MainActivity"
|
||||
android:name="icu.nullptr.hidemyapplist.ui.activity.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
|
@ -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">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
|
@ -77,5 +58,4 @@
|
|||
android:name="xposedscope"
|
||||
android:resource="@array/xposed_scope" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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<String>())
|
||||
}
|
||||
}
|
||||
globalConfig.scope.forEach { (_, data) ->
|
||||
JsonConfig.AppConfig::class.java.getDeclaredField("extraQueryParamRules").apply {
|
||||
isAccessible = true
|
||||
set(data, mutableSetOf<String>())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MyAppInfo>
|
||||
|
||||
fun getAppInfoList(): MutableList<MyAppInfo> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String>?): MutableSet<String> {
|
||||
return JsonConfig.AppConfig::class.java.getDeclaredField(key)
|
||||
.also { it.isAccessible = true }
|
||||
.get(appConfig) as MutableSet<String>
|
||||
}
|
||||
|
||||
override fun putStringSet(key: String, values: MutableSet<String>?) {
|
||||
JsonConfig.AppConfig::class.java.getDeclaredField(key)
|
||||
.also { it.isAccessible = true }
|
||||
.set(appConfig, values)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MyAppInfo>,
|
||||
private val selectedApps: MutableSet<String>,
|
||||
private val onClick: (ViewHolder.() -> Unit)? = null
|
||||
) : Filterable,
|
||||
RecyclerView.Adapter<AppSelectAdapter.ViewHolder>() {
|
||||
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<MyAppInfo> = listOf()
|
||||
|
||||
init {
|
||||
filter.filter("")
|
||||
}
|
||||
|
||||
override fun getFilter() = object : Filter() {
|
||||
override fun performFiltering(constraint: CharSequence): FilterResults {
|
||||
val filteredList = mutableListOf<MyAppInfo>()
|
||||
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<MyAppInfo>
|
||||
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
|
||||
}
|
||||
|
|
@ -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<Pair<String, Boolean>>,
|
||||
private val mFragment: Fragment
|
||||
) : RecyclerView.Adapter<TemplateListAdapter.ViewHolder>() {
|
||||
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
|
||||
}
|
||||
|
|
@ -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<String>, requestKey: String? = null) =
|
||||
AppSelectFragment().apply {
|
||||
arguments = bundleOf(
|
||||
"selectedApps" to selectedApps,
|
||||
"requestKey" to requestKey
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var binding: FragmentAppSelectBinding
|
||||
private lateinit var selectedApps: MutableSet<String>
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Preference>("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<Preference>("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<SwitchPreferenceCompat>("useWhitelist")
|
||||
?.setOnPreferenceClickListener {
|
||||
appConfig.applyTemplates.clear()
|
||||
appConfig.extraAppList.clear()
|
||||
updateView()
|
||||
true
|
||||
}
|
||||
|
||||
preferenceScreen.findPreference<Preference>("applyTemplates")
|
||||
?.setOnPreferenceClickListener {
|
||||
val list = mutableListOf<String>()
|
||||
val checked = mutableListOf<Boolean>()
|
||||
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<Preference>("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<Preference>("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<Preference>("applyTemplates")?.title =
|
||||
getString(R.string.template_applied_count, appConfig.applyTemplates.size)
|
||||
|
||||
preferenceScreen.findPreference<Preference>("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<Preference>("extraQueryParamRules")?.title =
|
||||
getString(
|
||||
R.string.template_extra_query_param_rules_count,
|
||||
appConfig.extraQueryParamRules.size
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<SwitchPreferenceCompat>("detailLog")
|
||||
?.setOnPreferenceChangeListener { _, newValue ->
|
||||
JsonConfigManager.edit { detailLog = newValue as Boolean }
|
||||
true
|
||||
}
|
||||
|
||||
preferenceScreen.findPreference<ListPreference>("maxLogSize")?.apply {
|
||||
summary = entry
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
JsonConfigManager.edit {
|
||||
maxLogSize = (newValue as String).toInt()
|
||||
}
|
||||
summary = entries[findIndexOfValue(newValue as String)]
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
preferenceScreen.findPreference<SwitchPreferenceCompat>("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<Preference>("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<Preference>("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<Preference>("importConfig")
|
||||
?.setOnPreferenceClickListener {
|
||||
backupImportSAFLauncher.launch("application/json")
|
||||
true
|
||||
}
|
||||
preferenceScreen.findPreference<Preference>("exportConfig")
|
||||
?.setOnPreferenceClickListener {
|
||||
backupExportSAFLauncher.launch("HMA Config.json")
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Pair<String, Boolean>>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue