Redesign 2 (#31)
* Begin design again * Improve Switch dimensions * Add empty settings preset fragment * Finish settings presets fragment * Add git branch to version name * Add sorting for preset keys, add new replaced settings * Remove unneeded string, fix force stop * Fix CI issue * Remove animation speed spoofing * Add "Use system wallpaper" option * Fix Switch colors * Add GitHub-only translators into translator list * Simplify translator getter * Fix About fragment button colors for wallpaper mode * Add new SwipeRefreshLayout colors * Add no transparency mode for home item background color, optimize imports * Replace ugly serif * Add enabled/disabled state colors for Switch * Dirty fix for system wallpaper mode is not activated * Remove ability to hide something from HMA-OSS itself * Replace Java codes with Kotlin * Move CommonUtils to PropertyUtils, move packages into Constants * Add localBuild as used
This commit is contained in:
parent
150cdb40d6
commit
74c9313c46
58 changed files with 901 additions and 225 deletions
|
|
@ -58,6 +58,18 @@ val officialBuild: Boolean by rootProject.extra
|
|||
|
||||
@Suppress("deprecation")
|
||||
afterEvaluate {
|
||||
val srcDir = android.sourceSets["main"].assets.srcDirs.first()
|
||||
logger.lifecycle("Asset dir: $srcDir")
|
||||
if (!srcDir.exists()) srcDir.mkdirs()
|
||||
|
||||
val translatorsMap = mutableMapOf(
|
||||
// I used GitHub to get translations before moving to Crowdin.
|
||||
// Since nearly all of GitHub translators are listed in Crowdin
|
||||
// too, I wanted to add one profile here.
|
||||
|
||||
"cvnertnc" to "https://avatars.githubusercontent.com/u/148134890?v=4",
|
||||
)
|
||||
|
||||
if (localBuild || officialBuild) {
|
||||
val url = URL("https://crowdin.com/api/v2/projects/$crowdinProjectId/members")
|
||||
val urlConnection = url.openConnection() as HttpURLConnection
|
||||
|
|
@ -70,7 +82,7 @@ afterEvaluate {
|
|||
|
||||
val json = JsonParser.parseString(str).asJsonObject
|
||||
val translators = json.getAsJsonArray("data")
|
||||
val translatorsMap = mutableMapOf<String, String>()
|
||||
|
||||
for (item in translators) {
|
||||
val translator = item.asJsonObject.getAsJsonObject("data")
|
||||
val avatarUrl = translator.get("avatarUrl").asString
|
||||
|
|
@ -87,18 +99,10 @@ afterEvaluate {
|
|||
translatorsMap[username] = avatarUrl
|
||||
}
|
||||
}
|
||||
|
||||
val translatorJson = JSONObject(translatorsMap).toJSONString()
|
||||
val srcDir = android.sourceSets["main"].assets.srcDirs.first()
|
||||
logger.lifecycle("Asset dir: $srcDir")
|
||||
if (!srcDir.exists()) srcDir.mkdirs()
|
||||
File(srcDir, "translators.json").writeText(translatorJson)
|
||||
} else {
|
||||
val srcDir = android.sourceSets["main"].assets.srcDirs.first()
|
||||
logger.lifecycle("Asset dir: $srcDir")
|
||||
if (!srcDir.exists()) srcDir.mkdirs()
|
||||
File(srcDir, "translators.json").writeText("{}")
|
||||
}
|
||||
|
||||
val translatorJson = JSONObject(translatorsMap).toJSONString()
|
||||
File(srcDir, "translators.json").writeText(translatorJson)
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ package icu.nullptr.hidemyapplist
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import icu.nullptr.hidemyapplist.receiver.AppChangeReceiver
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||
import icu.nullptr.hidemyapplist.service.ServiceClient
|
||||
import icu.nullptr.hidemyapplist.ui.util.showToast
|
||||
import icu.nullptr.hidemyapplist.util.ConfigUtils.Companion.getLocale
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -39,5 +41,11 @@ class MyApp : Application() {
|
|||
val config = resources.configuration
|
||||
config.setLocale(getLocale())
|
||||
resources.updateConfiguration(config, resources.displayMetrics)
|
||||
|
||||
val handler = Thread.getDefaultUncaughtExceptionHandler()
|
||||
Thread.setDefaultUncaughtExceptionHandler { t, e ->
|
||||
ServiceClient.log(Log.ERROR, t.name, e.stackTraceToString())
|
||||
handler?.uncaughtException(t, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,13 @@ import org.frknkrc44.hma_oss.common.BuildConfig
|
|||
import java.io.File
|
||||
|
||||
object ConfigManager {
|
||||
enum class PresetType {
|
||||
APP,
|
||||
SETTINGS,
|
||||
}
|
||||
|
||||
data class TemplateInfo(val name: String?, val isWhiteList: Boolean)
|
||||
data class PresetInfo(val name: String, val translation: String)
|
||||
data class PresetInfo(val name: String, val type: PresetType?, val translation: String)
|
||||
|
||||
private const val TAG = "ConfigManager"
|
||||
private lateinit var config: JsonConfig
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ object PrefManager {
|
|||
|
||||
private const val PREF_LOCALE = "language"
|
||||
|
||||
private const val PREF_SYSTEM_WALLPAPER = "system_wallpaper"
|
||||
private const val PREF_DARK_THEME = "dark_theme"
|
||||
private const val PREF_BLACK_DARK_THEME = "black_dark_theme"
|
||||
private const val PREF_FOLLOW_SYSTEM_ACCENT = "follow_system_accent"
|
||||
|
|
@ -45,6 +46,10 @@ object PrefManager {
|
|||
get() = pref.getInt(PREF_DARK_THEME, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
set(value) = pref.edit().putInt(PREF_DARK_THEME, value).apply()
|
||||
|
||||
var systemWallpaper: Boolean
|
||||
get() = pref.getBoolean(PREF_SYSTEM_WALLPAPER, false)
|
||||
set(value) = pref.edit().putBoolean(PREF_SYSTEM_WALLPAPER, value).apply()
|
||||
|
||||
var blackDarkTheme: Boolean
|
||||
get() = pref.getBoolean(PREF_BLACK_DARK_THEME, false)
|
||||
set(value) = pref.edit().putBoolean(PREF_BLACK_DARK_THEME, value).apply()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
package icu.nullptr.hidemyapplist.service
|
||||
|
||||
import android.os.IBinder
|
||||
import android.os.Parcel
|
||||
import android.os.RemoteException
|
||||
import android.os.ServiceManager
|
||||
import android.util.Log
|
||||
import icu.nullptr.hidemyapplist.common.Constants
|
||||
import icu.nullptr.hidemyapplist.common.IHMAService
|
||||
import java.lang.reflect.InvocationHandler
|
||||
import java.lang.reflect.Method
|
||||
|
|
@ -36,37 +32,6 @@ object ServiceClient : IHMAService, IBinder.DeathRecipient {
|
|||
binder.linkToDeath(this, 0)
|
||||
}
|
||||
|
||||
private fun getServiceLegacy(): IHMAService? {
|
||||
if (service != null) return service
|
||||
val pm = ServiceManager.getService("package")
|
||||
val data = Parcel.obtain()
|
||||
val reply = Parcel.obtain()
|
||||
val remote = try {
|
||||
data.writeInterfaceToken(Constants.DESCRIPTOR)
|
||||
data.writeInt(Constants.ACTION_GET_BINDER)
|
||||
pm.transact(Constants.TRANSACTION, data, reply, 0)
|
||||
reply.readException()
|
||||
val binder = reply.readStrongBinder()
|
||||
IHMAService.Stub.asInterface(binder)
|
||||
} catch (e: RemoteException) {
|
||||
Log.d(TAG, "Failed to get binder")
|
||||
null
|
||||
} finally {
|
||||
data.recycle()
|
||||
reply.recycle()
|
||||
}
|
||||
if (remote != null) {
|
||||
Log.i(TAG, "Binder acquired")
|
||||
remote.asBinder().linkToDeath(this, 0)
|
||||
service = Proxy.newProxyInstance(
|
||||
javaClass.classLoader,
|
||||
arrayOf(IHMAService::class.java),
|
||||
ServiceProxy(remote)
|
||||
) as IHMAService
|
||||
}
|
||||
return service
|
||||
}
|
||||
|
||||
override fun binderDied() {
|
||||
service = null
|
||||
Log.e(TAG, "Binder died")
|
||||
|
|
@ -74,30 +39,38 @@ object ServiceClient : IHMAService, IBinder.DeathRecipient {
|
|||
|
||||
override fun asBinder() = service?.asBinder()
|
||||
|
||||
override fun getServiceVersion() = getServiceLegacy()?.serviceVersion ?: 0
|
||||
override fun getServiceVersion() = service?.serviceVersion ?: 0
|
||||
|
||||
override fun getFilterCount() = getServiceLegacy()?.filterCount ?: 0
|
||||
override fun getFilterCount() = service?.filterCount ?: 0
|
||||
|
||||
override fun getLogs() = getServiceLegacy()?.logs
|
||||
override fun getLogs() = service?.logs
|
||||
|
||||
override fun clearLogs() {
|
||||
getServiceLegacy()?.clearLogs()
|
||||
service?.clearLogs()
|
||||
}
|
||||
|
||||
override fun handlePackageEvent(eventType: String?, packageName: String?) {
|
||||
getServiceLegacy()?.handlePackageEvent(eventType, packageName)
|
||||
service?.handlePackageEvent(eventType, packageName)
|
||||
}
|
||||
|
||||
override fun getPackagesForPreset(presetName: String) =
|
||||
getServiceLegacy()?.getPackagesForPreset(presetName)
|
||||
service?.getPackagesForPreset(presetName)
|
||||
|
||||
override fun readConfig() = getServiceLegacy()?.readConfig()
|
||||
override fun readConfig() = service?.readConfig()
|
||||
|
||||
override fun writeConfig(json: String) {
|
||||
getServiceLegacy()?.writeConfig(json)
|
||||
service?.writeConfig(json)
|
||||
}
|
||||
|
||||
override fun stopService(cleanEnv: Boolean) {
|
||||
getServiceLegacy()?.stopService(cleanEnv)
|
||||
service?.stopService(cleanEnv)
|
||||
}
|
||||
|
||||
override fun forceStop(packageName: String, userId: Int) {
|
||||
service?.forceStop(packageName, userId)
|
||||
}
|
||||
|
||||
override fun log(level: Int, tag: String, message: String) {
|
||||
service?.log(level, tag, message)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package icu.nullptr.hidemyapplist.ui.adapter
|
|||
|
||||
import android.view.ViewGroup
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import icu.nullptr.hidemyapplist.common.CommonUtils
|
||||
import icu.nullptr.hidemyapplist.common.Constants
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||
|
|
@ -15,7 +15,7 @@ class AppManageAdapter(
|
|||
inner class ViewHolder(view: AppItemView) : AppSelectAdapter.ViewHolder(view) {
|
||||
init {
|
||||
view.setOnClickListener {
|
||||
if (!PrefManager.bypassRiskyPackageWarning && CommonUtils.riskyPackages.contains(view.binding.packageName.text)) {
|
||||
if (!PrefManager.bypassRiskyPackageWarning && Constants.riskyPackages.contains(view.binding.packageName.text)) {
|
||||
MaterialAlertDialogBuilder(view.context)
|
||||
.setTitle(R.string.app_warning_risky_package_title)
|
||||
.setMessage(R.string.app_warning_risky_package_desc)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||
import icu.nullptr.hidemyapplist.ui.adapter.AppSelectAdapter
|
||||
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.homeItemBackgroundColor
|
||||
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.themeColor
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
|
|
@ -118,8 +120,18 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) {
|
|||
}
|
||||
binding.list.layoutManager = LinearLayoutManager(context)
|
||||
binding.list.adapter = adapter
|
||||
binding.swipeRefresh.setOnRefreshListener {
|
||||
invalidateCache()
|
||||
|
||||
with(binding.swipeRefresh) {
|
||||
setProgressBackgroundColorSchemeColor(homeItemBackgroundColor(true))
|
||||
setColorSchemeColors(
|
||||
themeColor(androidx.appcompat.R.attr.colorPrimary),
|
||||
themeColor(com.google.android.material.R.attr.colorSecondary),
|
||||
themeColor(com.google.android.material.R.attr.colorTertiary),
|
||||
)
|
||||
|
||||
setOnRefreshListener {
|
||||
invalidateCache()
|
||||
}
|
||||
}
|
||||
|
||||
adapter.registerAdapterDataObserver(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package icu.nullptr.hidemyapplist.ui.fragment
|
|||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import android.widget.Toast
|
||||
|
|
@ -23,10 +24,12 @@ import icu.nullptr.hidemyapplist.common.AppPresets
|
|||
import icu.nullptr.hidemyapplist.common.JsonConfig
|
||||
import icu.nullptr.hidemyapplist.common.SettingsPresets
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.service.ServiceClient
|
||||
import icu.nullptr.hidemyapplist.ui.util.enabledString
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import icu.nullptr.hidemyapplist.ui.util.navigate
|
||||
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
|
||||
import icu.nullptr.hidemyapplist.ui.util.showToast
|
||||
import icu.nullptr.hidemyapplist.ui.viewmodel.AppSettingsViewModel
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
import org.frknkrc44.hma_oss.BuildConfig
|
||||
|
|
@ -34,6 +37,9 @@ import org.frknkrc44.hma_oss.R
|
|||
import org.frknkrc44.hma_oss.databinding.FragmentSettingsBinding
|
||||
|
||||
class AppSettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
companion object {
|
||||
private const val TAG = "AppSettingsFragment"
|
||||
}
|
||||
|
||||
private val binding by viewBinding<FragmentSettingsBinding>()
|
||||
private val viewModel by viewModels<AppSettingsViewModel>() {
|
||||
|
|
@ -157,6 +163,24 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) {
|
|||
else getString(R.string.app_extra_apps_invisible_count, pack.config.extraAppList.size)
|
||||
}
|
||||
|
||||
private fun launchMainActivity(packageName: String) {
|
||||
try {
|
||||
val pkgMgr = requireContext().packageManager
|
||||
val pkgInfo = pkgMgr.getPackageInfo(packageName, 0)
|
||||
if (pkgInfo.applicationInfo?.enabled == true) {
|
||||
val resolvedIntent = pkgMgr.getLaunchIntentForPackage(packageName)
|
||||
if (resolvedIntent != null) {
|
||||
startActivity(resolvedIntent)
|
||||
}
|
||||
} else {
|
||||
throw RuntimeException("Package is disabled")
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
showToast(R.string.app_launch_failed)
|
||||
ServiceClient.log(Log.ERROR, TAG, e.stackTraceToString())
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("DiscouragedApi")
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceManager.preferenceDataStore = AppPreferenceDataStore(pack)
|
||||
|
|
@ -164,7 +188,27 @@ class AppSettingsFragment : Fragment(R.layout.fragment_settings) {
|
|||
findPreference<Preference>("appInfo")?.let {
|
||||
it.icon = PackageHelper.loadAppIcon(pack.app).toDrawable(resources)
|
||||
it.title = PackageHelper.loadAppLabel(pack.app)
|
||||
it.summary = PackageHelper.loadPackageInfo(pack.app).packageName
|
||||
it.summary = pack.app
|
||||
it.setOnPreferenceClickListener { pref ->
|
||||
MaterialAlertDialogBuilder(pref.context).apply {
|
||||
setTitle(it.title)
|
||||
setItems(
|
||||
R.array.app_action_texts,
|
||||
) { dialog, which ->
|
||||
when (which) {
|
||||
0 -> {
|
||||
ServiceClient.forceStop(pack.app, 0)
|
||||
launchMainActivity(pack.app)
|
||||
}
|
||||
1 -> {
|
||||
launchMainActivity(pack.app)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.show()
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
findPreference<SwitchPreferenceCompat>("hideInstallationSource")?.setOnPreferenceChangeListener { _, newValue ->
|
||||
Toast.makeText(requireContext(),
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import androidx.preference.SwitchPreferenceCompat
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import icu.nullptr.hidemyapplist.common.CommonUtils
|
||||
import icu.nullptr.hidemyapplist.common.PropertyUtils
|
||||
import icu.nullptr.hidemyapplist.common.Constants
|
||||
import icu.nullptr.hidemyapplist.hmaApp
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
|
|
@ -92,6 +92,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
|||
override fun getBoolean(key: String, defValue: Boolean): Boolean {
|
||||
return when (key) {
|
||||
"followSystemAccent" -> PrefManager.followSystemAccent
|
||||
"systemWallpaper" -> PrefManager.systemWallpaper
|
||||
"blackDarkTheme" -> PrefManager.blackDarkTheme
|
||||
"detailLog" -> ConfigManager.detailLog
|
||||
"hideIcon" -> PrefManager.hideIcon
|
||||
|
|
@ -118,6 +119,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
|||
override fun putBoolean(key: String, value: Boolean) {
|
||||
when (key) {
|
||||
"followSystemAccent" -> PrefManager.followSystemAccent = value
|
||||
"systemWallpaper" -> PrefManager.systemWallpaper = value
|
||||
"blackDarkTheme" -> PrefManager.blackDarkTheme = value
|
||||
"detailLog" -> ConfigManager.detailLog = value
|
||||
"forceMountData" -> ConfigManager.forceMountData = value
|
||||
|
|
@ -151,7 +153,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
|||
it.summary = getString(R.string.settings_need_reboot) + "\n\n" +
|
||||
getString(
|
||||
R.string.settings_default_value,
|
||||
CommonUtils.isAppDataIsolationEnabled.enabledString(resources)
|
||||
PropertyUtils.isAppDataIsolationEnabled.enabledString(resources)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +161,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
|||
it.summary = getString(R.string.settings_need_reboot) + "\n\n" +
|
||||
getString(
|
||||
R.string.settings_default_value,
|
||||
CommonUtils.isVoldAppDataIsolationEnabled.enabledString(resources)
|
||||
PropertyUtils.isVoldAppDataIsolationEnabled.enabledString(resources)
|
||||
)
|
||||
|
||||
it.setOnPreferenceChangeListener { _, newValue ->
|
||||
|
|
@ -191,9 +193,9 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
|||
it.isEnabled -> getString(
|
||||
R.string.settings_data_isolation_summary,
|
||||
if (ConfigManager.altAppDataIsolation) getString(R.string.settings_overwritten)
|
||||
else CommonUtils.isAppDataIsolationEnabled.enabledString(resources),
|
||||
else PropertyUtils.isAppDataIsolationEnabled.enabledString(resources),
|
||||
if (ConfigManager.altVoldAppDataIsolation) getString(R.string.settings_overwritten)
|
||||
else CommonUtils.isVoldAppDataIsolationEnabled.enabledString(resources),
|
||||
else PropertyUtils.isVoldAppDataIsolationEnabled.enabledString(resources),
|
||||
ConfigManager.forceMountData.enabledString(resources)
|
||||
)
|
||||
else -> getString(R.string.settings_data_isolation_unsupported)
|
||||
|
|
@ -270,9 +272,27 @@ class SettingsFragment : Fragment(R.layout.fragment_settings), PreferenceFragmen
|
|||
true
|
||||
}
|
||||
|
||||
findPreference<SwitchPreferenceCompat>("blackDarkTheme")?.setOnPreferenceChangeListener { _, _ ->
|
||||
activity?.recreate()
|
||||
true
|
||||
findPreference<SwitchPreferenceCompat>("systemWallpaper")?.apply {
|
||||
isEnabled = findPreference<SwitchPreferenceCompat>("blackDarkTheme")?.isChecked != true
|
||||
setOnPreferenceChangeListener { _, value ->
|
||||
val activity = requireActivity()
|
||||
if (value as Boolean) {
|
||||
activity.finish()
|
||||
startActivity(Intent(activity, activity.javaClass))
|
||||
} else {
|
||||
activity.recreate()
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
findPreference<SwitchPreferenceCompat>("blackDarkTheme")?.apply {
|
||||
isEnabled = findPreference<SwitchPreferenceCompat>("systemWallpaper")?.isChecked != true
|
||||
setOnPreferenceChangeListener { _, _ ->
|
||||
activity?.recreate()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
configureDataIsolation()
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ val Fragment.navController get() = NavHostFragment.findNavController(this)
|
|||
private val navOptions by lazy {
|
||||
NavOptions.Builder().apply {
|
||||
setEnterAnim(R.anim.activity_open_enter)
|
||||
setExitAnim(R.anim.fade_out)
|
||||
setPopEnterAnim(R.anim.fade_in)
|
||||
setExitAnim(R.anim.activity_open_exit)
|
||||
setPopEnterAnim(R.anim.activity_close_enter)
|
||||
setPopExitAnim(R.anim.activity_close_exit)
|
||||
}.build()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,24 +58,18 @@ object ThemeUtils {
|
|||
"MATERIAL_BLUE_GREY" to R.style.ThemeOverlay_Dark_MaterialBlueGrey
|
||||
)
|
||||
|
||||
private const val THEME_DEFAULT = "DEFAULT"
|
||||
private const val THEME_BLACK = "BLACK"
|
||||
|
||||
val isSystemAccent get() = DynamicColors.isDynamicColorAvailable() && PrefManager.followSystemAccent
|
||||
|
||||
fun isNightMode(context: Context) = (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
|
||||
|
||||
fun isUsingBlackTheme(context: Context) = PrefManager.blackDarkTheme && isNightMode(context)
|
||||
|
||||
fun getNightTheme(context: Context): String {
|
||||
return if (isUsingBlackTheme(context))
|
||||
THEME_BLACK else THEME_DEFAULT
|
||||
}
|
||||
|
||||
@StyleRes
|
||||
fun getNightThemeStyleRes(context: Context): Int {
|
||||
return if (isUsingBlackTheme(context))
|
||||
R.style.ThemeOverlay_Black else R.style.ThemeOverlay
|
||||
fun getOverlayThemeStyleRes(context: Context): Int {
|
||||
if (isUsingBlackTheme(context)) return R.style.ThemeOverlay_Black
|
||||
if (PrefManager.systemWallpaper) return R.style.ThemeOverlay_Wallpaper
|
||||
|
||||
return R.style.ThemeOverlay
|
||||
}
|
||||
|
||||
val colorTheme get() = if (isSystemAccent) "SYSTEM" else PrefManager.themeColor
|
||||
|
|
@ -125,11 +119,14 @@ object ThemeUtils {
|
|||
@ColorRes colorId: Int
|
||||
) = requireContext().getColor(colorId)
|
||||
|
||||
fun Context.homeItemBackgroundColor() = if (isNightMode(this)) {
|
||||
fun Context.homeItemBackgroundColor(forceNoTrans: Boolean = false) = (if (isNightMode(this)) {
|
||||
themeColor(com.google.android.material.R.attr.colorSurfaceContainerHighest)
|
||||
} else {
|
||||
themeColor(com.google.android.material.R.attr.colorSurfaceContainer)
|
||||
}).let {
|
||||
if (!forceNoTrans && PrefManager.systemWallpaper) return@let it - 0x55000000
|
||||
return@let it
|
||||
}
|
||||
|
||||
fun Fragment.homeItemBackgroundColor() = requireContext().homeItemBackgroundColor()
|
||||
fun Fragment.homeItemBackgroundColor(forceNoTrans: Boolean = false) = requireContext().homeItemBackgroundColor(forceNoTrans)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package icu.nullptr.hidemyapplist.ui.view
|
|||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.isVisible
|
||||
import by.kirich1409.viewbindingdelegate.CreateMethod
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import icu.nullptr.hidemyapplist.util.PackageHelper
|
||||
|
|
@ -18,7 +19,7 @@ class AppItemView @JvmOverloads constructor(
|
|||
val binding by viewBinding<AppItemViewBinding>(createMethod = CreateMethod.INFLATE)
|
||||
|
||||
var showEnabled: Boolean
|
||||
get() = binding.enabled.visibility == VISIBLE
|
||||
get() = binding.enabled.isVisible
|
||||
set(value) {
|
||||
binding.enabled.visibility = if (value) VISIBLE else GONE
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
package icu.nullptr.hidemyapplist.ui.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.util.AttributeSet
|
||||
import android.widget.LinearLayout
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.view.isVisible
|
||||
import by.kirich1409.viewbindingdelegate.CreateMethod
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.themeColor
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import org.frknkrc44.hma_oss.databinding.ListItemViewBinding
|
||||
|
||||
|
|
@ -42,8 +45,28 @@ class ListItemView @JvmOverloads constructor(
|
|||
binding.icon.setImageResource(icon)
|
||||
}
|
||||
|
||||
fun showIcon(show: Boolean) {
|
||||
binding.icon.isVisible = show
|
||||
}
|
||||
|
||||
fun showAsHeader() {
|
||||
showIcon(false)
|
||||
|
||||
with(binding.text) {
|
||||
typeface = Typeface.DEFAULT_BOLD
|
||||
|
||||
val textColor = context.themeColor(
|
||||
androidx.appcompat.R.attr.colorPrimary,
|
||||
)
|
||||
setTextColor(textColor)
|
||||
|
||||
val padding = (resources.displayMetrics.density * 8f).toInt()
|
||||
setPaddingRelative(paddingStart, padding, paddingEnd, padding)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setOnClickListener(l: OnClickListener?) {
|
||||
if (binding.button.visibility == VISIBLE) {
|
||||
if (binding.button.isVisible) {
|
||||
binding.button.setOnClickListener(l)
|
||||
} else {
|
||||
super.setOnClickListener(l)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ open class BaseActivity : AppCompatActivity() {
|
|||
theme.applyStyle(ThemeUtils.getColorThemeStyleRes(this), true)
|
||||
}
|
||||
|
||||
theme.applyStyle(ThemeUtils.getNightThemeStyleRes(this), true)
|
||||
theme.applyStyle(ThemeUtils.getOverlayThemeStyleRes(this), true)
|
||||
}
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.content.Context
|
|||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import icu.nullptr.hidemyapplist.common.AppPresets
|
||||
import icu.nullptr.hidemyapplist.common.SettingsPresets
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.ui.view.ListItemView
|
||||
import org.frknkrc44.hma_oss.BuildConfig
|
||||
|
|
@ -15,23 +16,31 @@ class AppPresetListAdapter(
|
|||
private val onClickListener: ((ConfigManager.PresetInfo) -> Unit)?
|
||||
) : RecyclerView.Adapter<AppPresetListAdapter.ViewHolder>() {
|
||||
|
||||
private lateinit var list: List<ConfigManager.PresetInfo>
|
||||
private var list = mutableListOf<ConfigManager.PresetInfo>()
|
||||
|
||||
init {
|
||||
updateList(context)
|
||||
}
|
||||
|
||||
inner class ViewHolder(view: ListItemView) : RecyclerView.ViewHolder(view) {
|
||||
init {
|
||||
view.setOnClickListener {
|
||||
onClickListener?.invoke(list[absoluteAdapterPosition])
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(presetName: String) {
|
||||
fun bind(item: ConfigManager.PresetInfo) {
|
||||
with(itemView as ListItemView) {
|
||||
setIcon(R.drawable.baseline_assignment_24)
|
||||
text = presetName
|
||||
if (item.type == null) {
|
||||
showAsHeader()
|
||||
} else {
|
||||
setIcon(
|
||||
when (item.type) {
|
||||
ConfigManager.PresetType.APP -> R.drawable.baseline_assignment_24
|
||||
ConfigManager.PresetType.SETTINGS -> R.drawable.baseline_settings_24
|
||||
}
|
||||
)
|
||||
|
||||
itemView.setOnClickListener {
|
||||
onClickListener?.invoke(item)
|
||||
}
|
||||
}
|
||||
|
||||
text = item.translation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,12 +58,14 @@ class AppPresetListAdapter(
|
|||
|
||||
override fun getItemId(position: Int) = list[position].name.hashCode().toLong()
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(list[position].translation)
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(list[position])
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged", "DiscouragedApi")
|
||||
private fun updateList(context: Context) {
|
||||
val presetNames = AppPresets.instance.getAllPresetNames()
|
||||
val presetTranslations = presetNames.map { name ->
|
||||
list.clear()
|
||||
|
||||
val appPresetNames = AppPresets.instance.getAllPresetNames()
|
||||
val appPresetTranslations = appPresetNames.map { name ->
|
||||
try {
|
||||
val id = context.resources.getIdentifier(
|
||||
"preset_${name}",
|
||||
|
|
@ -68,9 +79,49 @@ class AppPresetListAdapter(
|
|||
name
|
||||
}
|
||||
|
||||
list = presetNames
|
||||
.map { ConfigManager.PresetInfo(it, presetTranslations[presetNames.indexOf(it)]) }
|
||||
list += ConfigManager.PresetInfo(
|
||||
"preset",
|
||||
null,
|
||||
context.getString(R.string.title_preset),
|
||||
)
|
||||
|
||||
list += appPresetNames
|
||||
.map { ConfigManager.PresetInfo(
|
||||
it,
|
||||
ConfigManager.PresetType.APP,
|
||||
appPresetTranslations[appPresetNames.indexOf(it)]
|
||||
) }
|
||||
.sortedWith { a, b -> a.translation.lowercase().compareTo(b.translation.lowercase()) }
|
||||
|
||||
list += ConfigManager.PresetInfo(
|
||||
"settings_preset",
|
||||
null,
|
||||
context.getString(R.string.title_settings_preset),
|
||||
)
|
||||
|
||||
val settingsPresetNames = SettingsPresets.instance.getAllPresetNames()
|
||||
val settingsPresetTranslations = settingsPresetNames.map { name ->
|
||||
try {
|
||||
val id = context.resources.getIdentifier(
|
||||
"settings_preset_${name}",
|
||||
"string",
|
||||
BuildConfig.APPLICATION_ID
|
||||
)
|
||||
|
||||
return@map if (id != 0) { context.resources.getString(id) } else { name }
|
||||
} catch (_: Throwable) {}
|
||||
|
||||
name
|
||||
}
|
||||
|
||||
list += settingsPresetNames
|
||||
.map { ConfigManager.PresetInfo(
|
||||
it,
|
||||
ConfigManager.PresetType.SETTINGS,
|
||||
settingsPresetTranslations[settingsPresetNames.indexOf(it)]
|
||||
) }
|
||||
.sortedWith { a, b -> a.translation.lowercase().compareTo(b.translation.lowercase()) }
|
||||
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
package org.frknkrc44.hma_oss.ui.adapter
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import icu.nullptr.hidemyapplist.common.SettingsPresets
|
||||
import icu.nullptr.hidemyapplist.common.settings_presets.ReplacementItem
|
||||
import icu.nullptr.hidemyapplist.ui.view.AppItemView
|
||||
|
||||
class SettingsPresetListAdapter(presetName: String) : RecyclerView.Adapter<SettingsPresetListAdapter.ViewHolder>() {
|
||||
private val presetItems by lazy {
|
||||
SettingsPresets.instance.getPresetByName(presetName)!!.settingsKVPairs.sortedBy { it.name }
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = AppItemView(parent.context, false)
|
||||
view.layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(presetItems[position])
|
||||
|
||||
override fun getItemCount() = presetItems.size
|
||||
|
||||
class ViewHolder(view: AppItemView) : RecyclerView.ViewHolder(view) {
|
||||
fun bind(item: ReplacementItem) {
|
||||
(itemView as AppItemView).apply {
|
||||
binding.icon.isVisible = false
|
||||
binding.label.text = item.name
|
||||
binding.packageName.text = item.value ?: "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import androidx.core.net.toUri
|
|||
import androidx.fragment.app.Fragment
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.bumptech.glide.Glide
|
||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.homeItemBackgroundColor
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import org.frknkrc44.hma_oss.R
|
||||
|
|
@ -73,6 +74,11 @@ class AboutFragment : Fragment(R.layout.fragment_about) {
|
|||
appName.setText(R.string.app_name)
|
||||
appVersion.text = BuildConfig.APP_VERSION_NAME
|
||||
|
||||
if (PrefManager.systemWallpaper) {
|
||||
linkGithub.background.alpha = 0xAA
|
||||
linkTelegram.background.alpha = 0xAA
|
||||
}
|
||||
|
||||
setOnClickUrl(linkGithub, "https://github.com/frknkrc44/HMA-OSS")
|
||||
setOnClickUrl(linkTelegram, "https://t.me/aerathfuns")
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import by.kirich1409.viewbindingdelegate.viewBinding
|
|||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import icu.nullptr.hidemyapplist.hmaApp
|
||||
import icu.nullptr.hidemyapplist.service.ConfigManager
|
||||
import icu.nullptr.hidemyapplist.service.PrefManager
|
||||
import icu.nullptr.hidemyapplist.service.ServiceClient
|
||||
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.attrDrawable
|
||||
import icu.nullptr.hidemyapplist.ui.util.ThemeUtils.getColor
|
||||
|
|
@ -115,11 +116,13 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
|||
super.onStart()
|
||||
|
||||
val serviceVersion = ServiceClient.serviceVersion
|
||||
val color = when {
|
||||
var color = when {
|
||||
serviceVersion == 0 -> getColor(R.color.invalid)
|
||||
else -> themeColor(android.R.attr.colorPrimary)
|
||||
}
|
||||
|
||||
if (PrefManager.systemWallpaper) color -= 0x55000000
|
||||
|
||||
with(binding.statusCard) {
|
||||
root.setCardBackgroundColor(color)
|
||||
root.outlineAmbientShadowColor = color
|
||||
|
|
@ -294,12 +297,20 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
|||
}
|
||||
}
|
||||
|
||||
binding.backupConfig.setOnClickListener {
|
||||
backupSAFLauncher.launch("HMA_Config_${System.currentTimeMillis()}.json")
|
||||
with(binding.backupConfig) {
|
||||
if (PrefManager.systemWallpaper) background.alpha = 0xAA
|
||||
|
||||
setOnClickListener {
|
||||
backupSAFLauncher.launch("HMA_Config_${System.currentTimeMillis()}.json")
|
||||
}
|
||||
}
|
||||
|
||||
binding.restoreConfig.setOnClickListener {
|
||||
restoreSAFLauncher.launch("application/json")
|
||||
with(binding.restoreConfig) {
|
||||
if (PrefManager.systemWallpaper) background.alpha = 0xAA
|
||||
|
||||
setOnClickListener {
|
||||
restoreSAFLauncher.launch("application/json")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,15 @@ class PresetManageFragment : Fragment(R.layout.fragment_preset_manage) {
|
|||
}
|
||||
|
||||
private fun navigateToPreset(presetInfo: ConfigManager.PresetInfo) {
|
||||
val args = AppPresetFragmentArgs(presetInfo.name, presetInfo.translation)
|
||||
navigate(R.id.nav_preset_inner_manage, args.toBundle())
|
||||
when (presetInfo.type!!) {
|
||||
ConfigManager.PresetType.APP -> {
|
||||
val args = AppPresetFragmentArgs(presetInfo.name, presetInfo.translation)
|
||||
navigate(R.id.nav_preset_inner_manage, args.toBundle())
|
||||
}
|
||||
ConfigManager.PresetType.SETTINGS -> {
|
||||
val args = SettingsPresetFragmentArgs(presetInfo.name, presetInfo.translation)
|
||||
navigate(R.id.nav_settings_preset_inner_manage, args.toBundle())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
package org.frknkrc44.hma_oss.ui.fragment
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import icu.nullptr.hidemyapplist.ui.util.navController
|
||||
import icu.nullptr.hidemyapplist.ui.util.setupToolbar
|
||||
import org.frknkrc44.hma_oss.R
|
||||
import org.frknkrc44.hma_oss.databinding.FragmentSettingsPresetBinding
|
||||
import org.frknkrc44.hma_oss.ui.adapter.SettingsPresetListAdapter
|
||||
|
||||
/**
|
||||
* Use the [SettingsPresetFragment.newInstance] factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class SettingsPresetFragment : Fragment(R.layout.fragment_settings_preset) {
|
||||
private val binding by viewBinding<FragmentSettingsPresetBinding>()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val args by navArgs<SettingsPresetFragmentArgs>()
|
||||
|
||||
setupToolbar(
|
||||
toolbar = binding.toolbar,
|
||||
title = args.presetTitle,
|
||||
navigationIcon = R.drawable.baseline_arrow_back_24,
|
||||
navigationOnClick = { navController.navigateUp() }
|
||||
)
|
||||
|
||||
binding.list.layoutManager = LinearLayoutManager(context)
|
||||
binding.list.adapter = SettingsPresetListAdapter(args.presetName)
|
||||
|
||||
binding.root.setOnApplyWindowInsetsListener { v, insets ->
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
val barInsets = insets.getInsets(WindowInsets.Type.systemBars())
|
||||
binding.root.setPadding(
|
||||
barInsets.left,
|
||||
barInsets.top,
|
||||
barInsets.right,
|
||||
barInsets.bottom,
|
||||
)
|
||||
} else {
|
||||
@Suppress("deprecation")
|
||||
binding.root.setPadding(
|
||||
insets.systemWindowInsetLeft,
|
||||
insets.systemWindowInsetTop,
|
||||
insets.systemWindowInsetRight,
|
||||
insets.systemWindowInsetBottom,
|
||||
)
|
||||
}
|
||||
|
||||
insets
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ARG_PRESET_NAME = "presetName"
|
||||
private const val ARG_PRESET_TITLE = "presetTitle"
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @param presetName Name of the preset.
|
||||
* @param presetTitle Title of the preset.
|
||||
* @return A new instance of fragment SettingsPresetFragment.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun newInstance(presetName: String, presetTitle: String) =
|
||||
SettingsPresetFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString(ARG_PRESET_NAME, presetName)
|
||||
putString(ARG_PRESET_TITLE, presetTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue