added sleep timer adjuster and optimized views

This commit is contained in:
X1nto 2020-12-22 21:36:11 +04:00
parent 2a5e46855c
commit 1f9ecfddc0
11 changed files with 213 additions and 38 deletions

View File

@ -16,10 +16,5 @@ class ThemedMaterialCheckbox @JvmOverloads constructor(
) : MaterialCheckBox(context, attributeSet, R.attr.checkboxStyle) { ) : MaterialCheckBox(context, attributeSet, R.attr.checkboxStyle) {
init { init {
buttonTintList = ColorStateList.valueOf(context.getDefaultPrefs().getInt("manager_accent_color", defAccentColor)) buttonTintList = ColorStateList.valueOf(context.getDefaultPrefs().getInt("manager_accent_color", defAccentColor))
context.lifecycleOwner()?.let { owner ->
accentColor.observe(owner) { color ->
buttonTintList = ColorStateList.valueOf(color.toInt())
}
}
} }
} }

View File

@ -16,10 +16,5 @@ class ThemedMaterialRadioButton @JvmOverloads constructor(
) : MaterialRadioButton(context, attributeSet, R.attr.radioButtonStyle) { ) : MaterialRadioButton(context, attributeSet, R.attr.radioButtonStyle) {
init { init {
buttonTintList = ColorStateList.valueOf(context.getDefaultPrefs().getInt("manager_accent_color", defAccentColor)) buttonTintList = ColorStateList.valueOf(context.getDefaultPrefs().getInt("manager_accent_color", defAccentColor))
context.lifecycleOwner()?.let { owner ->
accentColor.observe(owner) { color ->
buttonTintList = ColorStateList.valueOf(color.toInt())
}
}
} }
} }

View File

@ -0,0 +1,25 @@
package com.vanced.manager.ui.core
import android.content.Context
import android.util.AttributeSet
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.vanced.manager.R
import com.vanced.manager.utils.Extensions.getDefaultPrefs
import com.vanced.manager.utils.ThemeHelper.defAccentColor
class ThemedSwipeRefreshlayout @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null
) : SwipeRefreshLayout(context, attributeSet) {
init {
setColorSchemeColors(context.getDefaultPrefs().getInt("manager_accent_color", defAccentColor))
initAttrs(context, attributeSet)
}
private fun initAttrs(context: Context, attributeSet: AttributeSet?) {
attributeSet.let {
val typedAttrs = context.obtainStyledAttributes(it, R.styleable.ThemedSwipeRefreshlayout, 0, 0)
setProgressBackgroundColorSchemeColor(typedAttrs.getColor(R.styleable.ThemedSwipeRefreshlayout_progressBackgroundColor, 0))
typedAttrs.recycle()
}
}
}

View File

@ -0,0 +1,55 @@
package com.vanced.manager.ui.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.edit
import com.vanced.manager.core.ui.base.BindingDialogFragment
import com.vanced.manager.databinding.DialogServicedTimerBinding
import com.vanced.manager.utils.Extensions.getDefaultPrefs
import com.vanced.manager.utils.Extensions.writeServiceDScript
import com.vanced.manager.utils.PackageHelper
import com.vanced.manager.utils.PackageHelper.getPackageDir
import com.vanced.manager.utils.PackageHelper.getPkgNameRoot
import java.io.IOException
import java.util.*
class ServiceDTimerDialog : BindingDialogFragment<DialogServicedTimerBinding>() {
private val prefs by lazy { requireActivity().getDefaultPrefs() }
override fun binding(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): DialogServicedTimerBinding = DialogServicedTimerBinding.inflate(inflater, container, false)
override fun otherSetups() {
bindData()
}
private fun bindData() {
with (binding) {
servicedSlider.value = prefs.getInt("serviced_sleep_timer", 1).toFloat()
servicedCancel.setOnClickListener {
dismiss()
}
servicedSave.setOnClickListener {
try {
arrayOf("vanced", "music").forEach { app ->
val apkFPath = "${PackageHelper.apkInstallPath}/${app.capitalize(Locale.ROOT)}/base.apk"
getPackageDir(requireActivity(), getPkgNameRoot(app))?.let { it1 -> requireActivity().writeServiceDScript(apkFPath, it1, app) }
}
} catch (e: IOException) {
return@setOnClickListener
}
prefs.edit {
putInt("serviced_sleep_timer", servicedSlider.value.toInt())
}
dismiss()
}
}
}
}

View File

@ -1,11 +1,13 @@
package com.vanced.manager.ui.fragments package com.vanced.manager.ui.fragments
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible
import androidx.preference.PreferenceManager.getDefaultSharedPreferences import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
@ -26,12 +28,20 @@ import java.io.File
class SettingsFragment : BindingFragment<FragmentSettingsBinding>() { class SettingsFragment : BindingFragment<FragmentSettingsBinding>() {
private companion object { private companion object {
const val LIGHT = "Light" const val LIGHT = "Light"
const val DARK = "Dark" const val DARK = "Dark"
} }
private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) }
private val listener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
when (key) {
"serviced_sleep_timer" -> {
binding.servicedTimer.setSummary(sharedPreferences.getInt(key, 1).toString())
}
}
}
private lateinit var variant: String
override fun binding( override fun binding(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -41,14 +51,22 @@ class SettingsFragment : BindingFragment<FragmentSettingsBinding>() {
override fun otherSetups() { override fun otherSetups() {
setHasOptionsMenu(true) setHasOptionsMenu(true)
prefs.registerOnSharedPreferenceChangeListener(listener)
bindData() bindData()
} }
override fun onPause() {
super.onPause()
prefs.unregisterOnSharedPreferenceChangeListener(listener)
}
private fun bindData() { private fun bindData() {
with(binding) { with(binding) {
variant = prefs.getString("vanced_variant", "nonroot").toString()
bindRecycler() bindRecycler()
bindFirebase() bindFirebase()
bindManagerVariant() bindManagerVariant()
bindServiceDTimer()
bindClearFiles() bindClearFiles()
bindManagerTheme() bindManagerTheme()
bindManagerAccentColor() bindManagerAccentColor()
@ -74,10 +92,19 @@ class SettingsFragment : BindingFragment<FragmentSettingsBinding>() {
private fun FragmentSettingsBinding.bindManagerVariant() { private fun FragmentSettingsBinding.bindManagerVariant() {
managerVariant.apply { managerVariant.apply {
prefs.getString("vanced_variant", "nonroot")?.let { setSummary(it) } setSummary(variant)
setOnClickListener { showDialog(ManagerVariantDialog()) } setOnClickListener { showDialog(ManagerVariantDialog()) }
} }
} }
private fun FragmentSettingsBinding.bindServiceDTimer() {
servicedTimer.apply {
if (variant == "root") this.isVisible = true
setSummary(prefs.getInt("serviced_sleep_timer", 1).toString())
setOnClickListener { showDialog(ServiceDTimerDialog()) }
}
}
private fun FragmentSettingsBinding.bindClearFiles() { private fun FragmentSettingsBinding.bindClearFiles() {
clearFiles.setOnClickListener { clearFiles.setOnClickListener {
with(requireActivity()) { with(requireActivity()) {
@ -104,11 +131,11 @@ class SettingsFragment : BindingFragment<FragmentSettingsBinding>() {
} }
private fun FragmentSettingsBinding.bindManagerAccentColor() { private fun FragmentSettingsBinding.bindManagerAccentColor() {
managerAccentColor.setSummary(prefs.getInt("manager_accent_color", defAccentColor).toHex()) managerAccentColor.apply{
managerAccentColor.apply { setSummary(prefs.getInt("manager_accent_color", defAccentColor).toHex())
setOnClickListener { showDialog(ManagerAccentColorDialog()) } setOnClickListener { showDialog(ManagerAccentColorDialog()) }
accentColor.observe(viewLifecycleOwner) { accentColor.observe(viewLifecycleOwner) {
managerAccentColor.setSummary(prefs.getInt("manager_accent_color", defAccentColor).toHex()) setSummary(it.toHex())
} }
} }
} }

View File

@ -13,6 +13,8 @@ import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.material.radiobutton.MaterialRadioButton import com.google.android.material.radiobutton.MaterialRadioButton
import com.topjohnwu.superuser.io.SuFile
import com.topjohnwu.superuser.io.SuFileOutputStream
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.utils.InternetTools.baseUrl import com.vanced.manager.utils.InternetTools.baseUrl
import com.vanced.manager.utils.ThemeHelper.accentColor import com.vanced.manager.utils.ThemeHelper.accentColor
@ -86,4 +88,11 @@ object Extensions {
} }
} }
fun Context.writeServiceDScript(path: String, apkFPath: String, app: String) {
val shellFileZ = SuFile.open("/data/adb/service.d/$app.sh")
shellFileZ.createNewFile()
val code = """#!/system/bin/sh${"\n"}while [ "`getprop sys.boot_completed | tr -d '\r' `" != "1" ]; do sleep ${getDefaultPrefs().getInt("serviced_sleep_timer", 1)}; done${"\n"}mount -o bind $apkFPath $path"""
SuFileOutputStream(shellFileZ).use { out -> out.write(code.toByteArray())}
}
} }

View File

@ -10,7 +10,6 @@ import android.os.Build
import android.util.Log import android.util.Log
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFile
import com.topjohnwu.superuser.io.SuFileOutputStream
import com.vanced.manager.BuildConfig import com.vanced.manager.BuildConfig
import com.vanced.manager.core.installer.AppInstallerService import com.vanced.manager.core.installer.AppInstallerService
import com.vanced.manager.core.installer.AppUninstallerService import com.vanced.manager.core.installer.AppUninstallerService
@ -19,6 +18,7 @@ import com.vanced.manager.utils.AppUtils.sendCloseDialog
import com.vanced.manager.utils.AppUtils.sendFailure import com.vanced.manager.utils.AppUtils.sendFailure
import com.vanced.manager.utils.AppUtils.sendRefresh import com.vanced.manager.utils.AppUtils.sendRefresh
import com.vanced.manager.utils.AppUtils.vancedRootPkg import com.vanced.manager.utils.AppUtils.vancedRootPkg
import com.vanced.manager.utils.Extensions.writeServiceDScript
import com.vanced.manager.utils.InternetTools.music import com.vanced.manager.utils.InternetTools.music
import com.vanced.manager.utils.InternetTools.vanced import com.vanced.manager.utils.InternetTools.vanced
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -33,7 +33,7 @@ import kotlin.collections.HashMap
object PackageHelper { object PackageHelper {
private const val apkInstallPath = "/data/adb" const val apkInstallPath = "/data/adb"
private val vancedThemes = arrayOf("black", "dark", "pink", "blue") private val vancedThemes = arrayOf("black", "dark", "pink", "blue")
init { init {
@ -45,7 +45,7 @@ object PackageHelper {
) )
} }
private fun getAppName(pkg: String): String { private fun getAppNameRoot(pkg: String): String {
return when (pkg) { return when (pkg) {
vancedRootPkg -> "vanced" vancedRootPkg -> "vanced"
musicRootPkg -> "music" musicRootPkg -> "music"
@ -53,6 +53,13 @@ object PackageHelper {
} }
} }
fun getPkgNameRoot(app: String): String {
return when (app) {
"vanced" -> vancedRootPkg
"music" -> musicRootPkg
else -> ""
}
}
fun isPackageInstalled(packageName: String, packageManager: PackageManager): Boolean { fun isPackageInstalled(packageName: String, packageManager: PackageManager): Boolean {
return try { return try {
packageManager.getPackageInfo(packageName, 0) packageManager.getPackageInfo(packageName, 0)
@ -127,7 +134,7 @@ object PackageHelper {
} }
fun uninstallRootApk(pkg: String): Boolean { fun uninstallRootApk(pkg: String): Boolean {
val app = getAppName(pkg) val app = getAppNameRoot(pkg)
Shell.su("rm -rf $apkInstallPath/${app.capitalize(Locale.ROOT)}").exec() Shell.su("rm -rf $apkInstallPath/${app.capitalize(Locale.ROOT)}").exec()
Shell.su("rm $apkInstallPath/post-fs-data.d/$app.sh").exec() Shell.su("rm $apkInstallPath/post-fs-data.d/$app.sh").exec()
Shell.su("rm $apkInstallPath/service.d/$app.sh").exec() Shell.su("rm $apkInstallPath/service.d/$app.sh").exec()
@ -432,7 +439,7 @@ object PackageHelper {
val apkFPath = "$apkInstallPath/${app.capitalize(Locale.ROOT)}/base.apk" val apkFPath = "$apkInstallPath/${app.capitalize(Locale.ROOT)}/base.apk"
if (moveAPK(apath, apkFPath, pkg, context)) { if (moveAPK(apath, apkFPath, pkg, context)) {
if (chConV(apkFPath, context)) { if (chConV(apkFPath, context)) {
if (setupScript(apkFPath, path, app, pkg)) { if (setupScript(apkFPath, path, app, pkg, context)) {
return linkApp(apkFPath, pkg, path) return linkApp(apkFPath, pkg, path)
} }
} }
@ -443,21 +450,14 @@ object PackageHelper {
return false return false
} }
private fun setupScript(apkFPath: String, path: String, app: String, pkg: String): Boolean private fun setupScript(apkFPath: String, path: String, app: String, pkg: String, context: Context): Boolean
{ {
try {
val shellFileZ = SuFile.open("/data/adb/service.d/$app.sh") context.writeServiceDScript(apkFPath, path, app)
shellFileZ.createNewFile() Shell.su("""echo "#!/system/bin/sh\nwhile read line; do echo \${"$"}{line} | grep $pkg | awk '{print \${'$'}2}' | xargs umount -l; done< /proc/mounts" > /data/adb/post-fs-data.d/$app.sh""").exec()
return Shell.su("chmod 744 /data/adb/service.d/$app.sh").exec().isSuccess
val code = """#!/system/bin/sh${"\n"}while [ "`getprop sys.boot_completed | tr -d '\r' `" != "1" ]; do sleep 1; done${"\n"}mount -o bind $apkFPath $path""" } catch (e: IOException) {
if (shellFileZ.exists()) { e.printStackTrace()
try {
SuFileOutputStream(shellFileZ).use { out -> out.write(code.toByteArray())}
Shell.su("""echo "#!/system/bin/sh\nwhile read line; do echo \${"$"}{line} | grep $pkg | awk '{print \${'$'}2}' | xargs umount -l; done< /proc/mounts" > /data/adb/post-fs-data.d/$app.sh""").exec()
return Shell.su("chmod 744 /data/adb/service.d/$app.sh").exec().isSuccess
} catch (e: IOException) {
e.printStackTrace()
}
} }
return false return false
} }
@ -603,7 +603,7 @@ object PackageHelper {
} }
//get path of the installed youtube //get path of the installed youtube
private fun getPackageDir(context: Context, pkg: String): String? fun getPackageDir(context: Context, pkg: String): String?
{ {
val p = getPkgInfo(pkg, context) val p = getPkgInfo(pkg, context)
return if(p != null) return if(p != null)

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.dialogs.AppDownloadDialog"
style="@style/DialogCard">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/serviced_header"
tools:text="Script Sleep Timer"
style="@style/DialogCardTitle" />
<com.google.android.material.slider.Slider
android:id="@+id/serviced_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/serviced_header"
android:layout_marginTop="24dp"
android:valueFrom="1"
android:valueTo="50"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/serviced_slider"
android:layout_marginTop="8dp">
<com.vanced.manager.ui.core.ThemedOutlinedMaterialButton
android:id="@+id/serviced_cancel"
android:layout_alignParentStart="true"
android:textSize="15sp"
android:text="@string/cancel"
style="@style/OutlinedButtonStyle"/>
<com.vanced.manager.ui.core.ThemedMaterialButton
android:id="@+id/serviced_save"
android:layout_alignParentEnd="true"
android:text="@string/save"
app:layout_constraintEnd_toEndOf="parent"
style="@style/ButtonStyle"/>
</RelativeLayout>
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" <com.vanced.manager.ui.core.ThemedSwipeRefreshlayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/home_refresh" android:id="@+id/home_refresh"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
app:progressBackgroundColor="?colorSurface">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -58,5 +60,7 @@
tools:itemCount="6" tools:itemCount="6"
tools:listitem="@layout/view_social_link" /> tools:listitem="@layout/view_social_link" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</com.vanced.manager.ui.core.ThemedSwipeRefreshlayout>

View File

@ -49,11 +49,19 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:preference_title="@string/variant" /> app:preference_title="@string/variant" />
<com.vanced.manager.ui.core.EmptyPreference
android:id="@+id/serviced_timer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:preference_title="Script Sleep Timer"
android:visibility="gone"/>
<com.vanced.manager.ui.core.EmptyPreference <com.vanced.manager.ui.core.EmptyPreference
android:id="@+id/clearFiles" android:id="@+id/clearFiles"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:preference_title="@string/clear_files" /> app:preference_title="@string/clear_files" />
</com.vanced.manager.ui.core.PreferenceCategory> </com.vanced.manager.ui.core.PreferenceCategory>
<com.vanced.manager.ui.core.PreferenceCategory <com.vanced.manager.ui.core.PreferenceCategory
@ -86,6 +94,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:preference_title="@string/select_apps" /> app:preference_title="@string/select_apps" />
</com.vanced.manager.ui.core.PreferenceCategory> </com.vanced.manager.ui.core.PreferenceCategory>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@ -32,4 +32,8 @@
<attr name="preference_summary" format="reference|string"/> <attr name="preference_summary" format="reference|string"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="ThemedSwipeRefreshlayout">
<attr name="progressBackgroundColor" format="reference|color" />
</declare-styleable>
</resources> </resources>