diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml
index 8a0e2b0..74443cb 100644
--- a/.idea/navEditor.xml
+++ b/.idea/navEditor.xml
@@ -75,6 +75,28 @@
+
+
+
+
+
+
+
@@ -245,7 +267,7 @@
-
+
@@ -272,13 +294,13 @@
-
+
@@ -301,8 +323,8 @@
-
-
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..35eb1dd 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/Controls/build.gradle b/Controls/build.gradle
index ae478c2..18b8b58 100644
--- a/Controls/build.gradle
+++ b/Controls/build.gradle
@@ -8,7 +8,7 @@ android {
defaultConfig {
minSdk 30
- targetSdk 34
+ targetSdk 35
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
@@ -31,13 +31,13 @@ android {
}
dependencies {
- implementation 'androidx.core:core-ktx:1.12.0'
- implementation "androidx.lifecycle:lifecycle-common-java8:2.7.0"
+ implementation 'androidx.core:core-ktx:1.13.1'
+ implementation "androidx.lifecycle:lifecycle-common-java8:2.8.4"
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
- implementation 'androidx.fragment:fragment-ktx:1.6.2'
+ implementation 'androidx.fragment:fragment-ktx:1.8.2'
implementation 'androidx.preference:preference-ktx:1.2.1'
- implementation 'androidx.viewpager2:viewpager2:1.0.0'
+ implementation 'androidx.viewpager2:viewpager2:1.1.0'
implementation "io.insert-koin:koin-android:$koin_version"
compileOnly project(path: ':systemstubs')
}
\ No newline at end of file
diff --git a/Controls/src/main/java/com/android/systemui/controls/controller/StatefulControlSubscriber.kt b/Controls/src/main/java/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
index f8dd0d3..e213106 100644
--- a/Controls/src/main/java/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
+++ b/Controls/src/main/java/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
@@ -56,10 +56,8 @@ class StatefulControlSubscriber(
}
override fun onNext(token: IBinder, control: Control) {
- Log.d("SCS", "onNext ${control.title}")
run(token) {
if (!subscriptionOpen) {
- Log.w(TAG, "Refresh outside of window for token:$token")
} else {
controller.refreshStatus(provider.componentName, control)
}
diff --git a/Controls/src/main/java/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/Controls/src/main/java/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index 390c7dd..6be971e 100644
--- a/Controls/src/main/java/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/Controls/src/main/java/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -173,7 +173,6 @@ class ControlActionCoordinatorImpl constructor(
it.show()
}*/
activityStarter.dismissKeyguardThenExecute({
- Log.d("CACI", "startActivity")
activityStarter.dismissPowerMenu()
serviceRunner.startActivity(context, intent.createLaunchIntent()){
serviceRunner.overridePendingTransition(R.anim.bottomsheet_in, R.anim.bottomsheet_out)
diff --git a/QuickAccessWallet/build.gradle b/QuickAccessWallet/build.gradle
index 37ce5ed..bdb4aa3 100644
--- a/QuickAccessWallet/build.gradle
+++ b/QuickAccessWallet/build.gradle
@@ -8,7 +8,7 @@ android {
defaultConfig {
minSdk 30
- targetSdk 34
+ targetSdk 35
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
diff --git a/app/build.gradle b/app/build.gradle
index 7c281f7..7650e83 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,7 +7,7 @@ plugins {
id 'com.google.android.gms.oss-licenses-plugin'
}
-def version = '1.7.2'
+def version = '1.8'
android {
compileSdk 34
@@ -15,8 +15,8 @@ android {
defaultConfig {
applicationId "com.kieronquinn.app.classicpowermenu"
minSdk 30
- targetSdk 34
- versionCode 172
+ targetSdk 35
+ versionCode 180
versionName version
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -70,22 +70,24 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.3.2'
//AndroidX
- def lifecycle_version = "2.7.0"
- implementation 'androidx.core:core-ktx:1.12.0'
- implementation 'androidx.appcompat:appcompat:1.6.1'
+ def lifecycle_version = "2.8.4"
+ implementation 'androidx.core:core-ktx:1.13.1'
+ implementation "androidx.activity:activity-ktx:1.9.1"
+ implementation "androidx.fragment:fragment-ktx:1.8.2"
+ implementation 'androidx.appcompat:appcompat:1.7.0'
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
- implementation 'androidx.work:work-runtime-ktx:2.9.0'
+ implementation 'androidx.work:work-runtime-ktx:2.9.1'
implementation "androidx.core:core-splashscreen:1.0.1"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
//Material
- implementation 'com.google.android.material:material:1.11.0'
+ implementation 'com.google.android.material:material:1.12.0'
//Monet
implementation 'com.github.KieronQuinn:MonetCompat:0.4.1'
@@ -97,7 +99,7 @@ dependencies {
implementation "com.google.protobuf:protobuf-javalite:3.25.2"
//Guava for hashing code (to match what Gpay uses)
- implementation 'com.google.guava:guava:30.1.1-android'
+ implementation 'com.google.guava:guava:31.1-android'
//Stubs for hidden APIs. Shouldn't be included in APK.
compileOnly project(':systemstubs')
@@ -129,7 +131,7 @@ dependencies {
compileOnly 'de.robv.android.xposed:api:82'
//OSS libraries activity
- implementation 'com.google.android.gms:play-services-oss-licenses:17.0.1'
+ implementation 'com.google.android.gms:play-services-oss-licenses:17.1.0'
//Retrofit for update checking
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
@@ -144,6 +146,6 @@ dependencies {
//Test
testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.5'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+ androidTestImplementation 'androidx.test.ext:junit:1.2.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
}
\ No newline at end of file
diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json
index 2b6740e..80d5700 100644
--- a/app/release/output-metadata.json
+++ b/app/release/output-metadata.json
@@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
- "versionCode": 171,
- "versionName": "1.7.1",
+ "versionCode": 172,
+ "versionName": "1.7.2",
"outputFile": "app-release.apk"
}
],
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 56af4f3..a7675a1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,7 +3,8 @@
xmlns:tools="http://schemas.android.com/tools">
-
+
= Build.VERSION_CODES.S) {
- //TODO move when android.core:splashscreen supports it
setupSplashScreen()
- setupSplashDelay()
}
- setupTransition()
setupBringToFront()
setupInsets()
WindowCompat.setDecorFitsSystemWindows(window, false)
UpdateCheckWorker.queueCheckWorker(this)
- lifecycleScope.launchWhenCreated {
+ whenCreated {
monet.awaitMonetReady()
window.setBackgroundDrawable(ColorDrawable(monet.getBackgroundColor(this@MainActivity)))
setContentView(R.layout.activity_main)
setupStatusNav()
}
+ findViewById(android.R.id.content).delayPreDrawUntilFlow(
+ viewModel.appReady,
+ lifecycle
+ )
}
private fun setupInsets(){
@@ -67,22 +71,6 @@ class MainActivity : MonetCompatActivity() {
}
}
- private fun setupSplashDelay(){
- val content: View = findViewById(android.R.id.content)
- content.viewTreeObserver.addOnPreDrawListener(
- object : ViewTreeObserver.OnPreDrawListener {
- override fun onPreDraw(): Boolean {
- return if (viewModel.appReady.value) {
- content.viewTreeObserver.removeOnPreDrawListener(this)
- true
- } else {
- false
- }
- }
- }
- )
- }
-
@RequiresApi(Build.VERSION_CODES.S)
private fun setupSplashScreen() {
//Use the default animation when not loading setup where there's a shared element
@@ -102,7 +90,7 @@ class MainActivity : MonetCompatActivity() {
}
}
- private fun setupBringToFront() = lifecycleScope.launchWhenCreated {
+ private fun setupBringToFront() = whenCreated {
broadcastReceiverAsFlow(CPMAccessibilityService.INTENT_ACTION_BRING_TO_FRONT, oneShot = true).collect {
startActivity(Intent(this@MainActivity, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
@@ -110,9 +98,4 @@ class MainActivity : MonetCompatActivity() {
}
}
- private fun setupTransition() = with(window) {
- exitTransition = TransitionUtils.getMaterialSharedAxis(this@MainActivity, true)
- reenterTransition = TransitionUtils.getMaterialSharedAxis(this@MainActivity, false)
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/MainActivityViewModel.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/MainActivityViewModel.kt
index 8bab56c..843132f 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/MainActivityViewModel.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/MainActivityViewModel.kt
@@ -42,7 +42,7 @@ class MainActivityViewModelImpl(context: Context, private val updateChecker: Upd
emit(true)
}
- private val _appReady = combine(splashDelay, decisionMade){ requirements, _ ->
+ private val _appReady = combine(splashDelay, decisionMade){ requirements, decision ->
requirements
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/PowerMenuActivity.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/PowerMenuActivity.kt
index 192ac62..d3b4e6a 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/PowerMenuActivity.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/activities/PowerMenuActivity.kt
@@ -16,6 +16,8 @@ import com.kieronquinn.app.classicpowermenu.components.starter.PowerMenuStarter
import com.kieronquinn.app.classicpowermenu.service.container.CPMServiceContainer
import com.kieronquinn.app.classicpowermenu.utils.extensions.awaitPost
import com.kieronquinn.app.classicpowermenu.utils.extensions.sendDismissIntent
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenCreated
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import com.kieronquinn.monetcompat.app.MonetCompatActivity
import kotlinx.coroutines.flow.collect
import org.koin.android.ext.android.inject
@@ -39,7 +41,7 @@ class PowerMenuActivity : MonetCompatActivity(), PowerMenuStarter.PowerMenuStart
super.onCreate(savedInstanceState)
requestedOrientation = viewModel.getRequestedOrientation()
hideStatusBar()
- lifecycleScope.launchWhenCreated {
+ whenCreated {
setContentView(R.layout.activity_power_menu)
WindowCompat.setDecorFitsSystemWindows(window, false)
window.setupLayout()
@@ -57,7 +59,7 @@ class PowerMenuActivity : MonetCompatActivity(), PowerMenuStarter.PowerMenuStart
}
}
- private fun sendDismiss(runAfter: () -> Unit) = lifecycleScope.launchWhenResumed {
+ private fun sendDismiss(runAfter: () -> Unit) = whenResumed {
serviceContainer.runWithService {
it.sendDismissIntent(this@PowerMenuActivity)
runAfter()
@@ -67,7 +69,7 @@ class PowerMenuActivity : MonetCompatActivity(), PowerMenuStarter.PowerMenuStart
override fun onResume() {
super.onResume()
starter.setEventListener(this)
- lifecycleScope.launchWhenResumed {
+ whenResumed {
window.decorView.awaitPost()
if(!viewModel.useSolidBackground){
blurProvider.applyBlurToWindow(window, 1.5f)
@@ -80,13 +82,13 @@ class PowerMenuActivity : MonetCompatActivity(), PowerMenuStarter.PowerMenuStart
starter.setEventListener(null)
}
- private fun setupClose() = lifecycleScope.launchWhenCreated {
+ private fun setupClose() = whenCreated {
navigation.closePowerMenuBus.collect {
closePowerMenu()
}
}
- private fun setupCloseBroadcast() = lifecycleScope.launchWhenCreated {
+ private fun setupCloseBroadcast() = whenCreated {
viewModel.closeBroadcast.collect {
closePowerMenu()
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseBottomSheetFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseBottomSheetFragment.kt
index cc27d81..45a77a8 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseBottomSheetFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseBottomSheetFragment.kt
@@ -19,6 +19,7 @@ import com.kieronquinn.app.classicpowermenu.R
import com.kieronquinn.app.classicpowermenu.components.blur.BlurProvider
import com.kieronquinn.app.classicpowermenu.utils.extensions.awaitPost
import com.kieronquinn.app.classicpowermenu.utils.extensions.isDarkMode
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import com.kieronquinn.monetcompat.core.MonetCompat
import org.koin.android.ext.android.inject
@@ -136,7 +137,7 @@ abstract class BaseBottomSheetFragment(private val inflate: (Lay
private fun applyBlur(ratio: Float){
val dialogWindow = dialog?.window ?: return
val appWindow = activity?.window ?: return
- lifecycleScope.launchWhenResumed {
+ whenResumed {
dialogWindow.decorView.awaitPost()
blurProvider.applyDialogBlur(dialogWindow, appWindow, ratio)
}
@@ -145,7 +146,7 @@ abstract class BaseBottomSheetFragment(private val inflate: (Lay
override fun onResume() {
super.onResume()
if(isBlurShowing){
- lifecycleScope.launchWhenResumed {
+ whenResumed {
view?.awaitPost()
applyBlur(1f)
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseDialogFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseDialogFragment.kt
index 30e81ad..1fabe31 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseDialogFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BaseDialogFragment.kt
@@ -12,6 +12,7 @@ import androidx.viewbinding.ViewBinding
import autoCleared
import com.kieronquinn.app.classicpowermenu.components.blur.BlurProvider
import com.kieronquinn.app.classicpowermenu.utils.extensions.awaitPost
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import com.kieronquinn.monetcompat.core.MonetCompat
import org.koin.android.ext.android.inject
@@ -39,7 +40,7 @@ abstract class BaseDialogFragment(private val inflate: (LayoutIn
private var showBlurAnimation: ValueAnimator? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- lifecycleScope.launchWhenResumed {
+ whenResumed {
view.awaitPost()
showBlurAnimation = ValueAnimator.ofFloat(0f, 1.25f).apply {
duration = 250L
@@ -74,7 +75,7 @@ abstract class BaseDialogFragment(private val inflate: (LayoutIn
private fun applyBlur(ratio: Float){
val dialogWindow = dialog?.window ?: return
val appWindow = activity?.window ?: return
- lifecycleScope.launchWhenResumed {
+ whenResumed {
dialogWindow.decorView.awaitPost()
blurProvider.applyDialogBlur(dialogWindow, appWindow, ratio)
}
@@ -83,7 +84,7 @@ abstract class BaseDialogFragment(private val inflate: (LayoutIn
override fun onResume() {
super.onResume()
if(isBlurShowing){
- lifecycleScope.launchWhenResumed {
+ whenResumed {
view?.awaitPost()
applyBlur(1.25f)
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BoundFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BoundFragment.kt
index efee4c7..1802b3b 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BoundFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/base/BoundFragment.kt
@@ -39,19 +39,4 @@ abstract class BoundFragment(private val inflate: (LayoutInflate
return binding.root
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- if(this is StandaloneFragment){
- setupStandaloneFragment()
- }
- }
-
- private fun setupStandaloneFragment(){
- requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object: OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- (this@BoundFragment as StandaloneFragment).onBackPressed()
- }
- })
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/decision/DecisionFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/decision/DecisionFragment.kt
index fcdd787..e7e3af0 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/decision/DecisionFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/decision/DecisionFragment.kt
@@ -8,6 +8,7 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.kieronquinn.app.classicpowermenu.ui.activities.MainActivityViewModel
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import kotlinx.coroutines.flow.collect
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -26,7 +27,7 @@ class DecisionFragment: Fragment() {
return View(context)
}
- private fun setupAppReady() = viewLifecycleOwner.lifecycleScope.launchWhenResumed {
+ private fun setupAppReady() = whenResumed {
viewModel.decisionMade.collect {
appViewModel.onDecisionMade()
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/container/PowerMenuContainerFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/container/PowerMenuContainerFragment.kt
index e326c2a..35c5e4c 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/container/PowerMenuContainerFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/container/PowerMenuContainerFragment.kt
@@ -11,6 +11,7 @@ import com.kieronquinn.app.classicpowermenu.components.navigation.PowerMenuNavig
import com.kieronquinn.app.classicpowermenu.databinding.FragmentPowerMenuContainerBinding
import com.kieronquinn.app.classicpowermenu.ui.base.BoundFragment
import com.kieronquinn.app.classicpowermenu.utils.extensions.navigateSafely
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import kotlinx.coroutines.flow.collect
import org.koin.android.ext.android.inject
@@ -31,7 +32,7 @@ class PowerMenuContainerFragment: BoundFragment
onDragEvent(dragEvent)
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/main/PowerMenuFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/main/PowerMenuFragment.kt
index 99f5e3f..1e957db 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/main/PowerMenuFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/main/PowerMenuFragment.kt
@@ -39,6 +39,7 @@ import com.kieronquinn.app.classicpowermenu.utils.extensions.isScrolled
import com.kieronquinn.app.classicpowermenu.utils.extensions.scrollPercentage
import com.kieronquinn.app.classicpowermenu.utils.extensions.sendDismissIntent
import com.kieronquinn.app.classicpowermenu.utils.extensions.setSecondaryAlpha
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.launch
@@ -189,7 +190,7 @@ class PowerMenuFragment :
}
}
- private fun setupService() = lifecycleScope.launchWhenResumed {
+ private fun setupService() = whenResumed {
serviceContainer.runWithService {
setupWallet(it)
setupControls()
@@ -197,7 +198,7 @@ class PowerMenuFragment :
}
private var appBarBackgroundAnimation: ValueAnimator? = null
- private fun setupAppbar() = lifecycleScope.launchWhenResumed {
+ private fun setupAppbar() = whenResumed {
//Start alpha is 0
binding.powerMenuAppbar.background.alpha = 0
binding.powerMenuAppbar.backgroundTintList = ColorStateList.valueOf(monet.getBackgroundColor(requireContext()))
@@ -226,7 +227,7 @@ class PowerMenuFragment :
return roundToInt()
}
- private fun setupSecondaryAlpha() = lifecycleScope.launchWhenResumed {
+ private fun setupSecondaryAlpha() = whenResumed {
binding.powerMenuAppbar.scrollPercentage.collect {
buttonsLayoutManager.setSecondaryAlpha(1 - it)
}
@@ -251,7 +252,7 @@ class PowerMenuFragment :
contentAdapter.notifyItemChangeOfType(PowerMenuContentItem.Controls)
}
- private fun setupButtons() = lifecycleScope.launchWhenResumed {
+ private fun setupButtons() = whenResumed {
buttonsAdapter.items = powerMenuButtons.filter { it.shouldShow() }.toMutableList()
buttonsAdapter.notifyDataSetChanged()
}
@@ -260,7 +261,7 @@ class PowerMenuFragment :
sendDismiss()
}
- private fun sendDismiss() = lifecycleScope.launchWhenResumed {
+ private fun sendDismiss() = whenResumed {
serviceContainer.runWithService {
it.sendDismissIntent(requireContext())
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/walletcode/WalletCodeDialogFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/walletcode/WalletCodeDialogFragment.kt
index db0afe0..7082b91 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/walletcode/WalletCodeDialogFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/powermenu/walletcode/WalletCodeDialogFragment.kt
@@ -31,6 +31,7 @@ import org.koin.android.ext.android.inject
import com.google.zxing.BarcodeFormat
import com.kieronquinn.app.classicpowermenu.components.settings.Settings
import com.kieronquinn.app.classicpowermenu.utils.extensions.awaitPost
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
class WalletCodeDialogFragment: BaseDialogFragment(FragmentDialogWalletCodeBinding::inflate) {
@@ -165,7 +166,7 @@ class WalletCodeDialogFragment: BaseDialogFragment
collapsingToolbar.title = getString(R.string.app_name)
appBar.setExpanded(!requireContext().isLandscape && getTopFragment() is AutoExpandOnRotate)
toolbar.setNavigationOnClickListener {
- lifecycleScope.launchWhenResumed {
+ whenResumed {
navigation.navigateBack()
}
}
@@ -118,7 +121,7 @@ class SettingsContainerFragment: BoundFragment
}
}
- private fun setupNavigation() = viewLifecycleOwner.lifecycleScope.launchWhenResumed {
+ private fun setupNavigation() = viewLifecycleOwner.whenResumed {
navigation.navigationBus.collect {
handleNavigationEvent(it)
}
@@ -126,19 +129,28 @@ class SettingsContainerFragment: BoundFragment
private fun shouldBackDispatcherBeEnabled(): Boolean {
val top = navHostFragment.getTopFragment()
- return top is StandaloneFragment || top !is Root
+ return top is StandaloneFragment
}
+ @SuppressLint("RestrictedApi")
private fun setupBack() {
- val callback = requireActivity().onBackPressedDispatcher.addCallback(
- this,
- shouldBackDispatcherBeEnabled()
- ) {
- if(!navController.navigateUp()) requireActivity().finish()
+ val callback = object: OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ (navHostFragment.getTopFragment() as? StandaloneFragment)?.let {
+ it.onBackPressed()
+ return
+ }
+ if(!navController.popBackStack()) {
+ requireActivity().finish()
+ }
+ }
}
- viewLifecycleOwner.lifecycleScope.launchWhenResumed {
+ navController.setOnBackPressedCallback(callback)
+ navController.enableOnBackPressed(shouldBackDispatcherBeEnabled())
+ navController.setOnBackPressedDispatcher(requireActivity().onBackPressedDispatcher)
+ whenResumed {
navController.onDestinationChanged().collect {
- callback.isEnabled = shouldBackDispatcherBeEnabled()
+ navController.enableOnBackPressed(shouldBackDispatcherBeEnabled())
}
}
}
@@ -148,15 +160,10 @@ class SettingsContainerFragment: BoundFragment
return navHostFragment.childFragmentManager.fragments.firstOrNull()
}
- private fun setupFragmentListener(){
- navHostFragment.childFragmentManager.addOnBackStackChangedListener {
- getTopFragment()?.let {
- onTopFragmentChanged(it)
- }
- }
- lifecycleScope.launchWhenResumed {
- binding.navHostFragment.awaitPost()
- onTopFragmentChanged(getTopFragment() ?: return@launchWhenResumed)
+ private fun setupFragmentListener() = whenResumed {
+ navController.onDestinationChanged().collect {
+ binding.root.awaitPost()
+ onTopFragmentChanged(navHostFragment.getTopFragment() ?: return@collect)
}
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/generic/SettingsGenericAdapter.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/generic/SettingsGenericAdapter.kt
index 9b891de..e029310 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/generic/SettingsGenericAdapter.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/generic/SettingsGenericAdapter.kt
@@ -19,6 +19,7 @@ import com.kieronquinn.app.classicpowermenu.utils.extensions.applyMonet
import com.kieronquinn.app.classicpowermenu.utils.openLink
import com.kieronquinn.monetcompat.core.MonetCompat
import com.kieronquinn.monetcompat.extensions.views.applyMonet
+import com.kieronquinn.monetcompat.extensions.views.applyMonetLight
class SettingsGenericAdapter(context: Context, private var items: List, var isAdapterEnabled: Boolean): RecyclerView.Adapter() {
@@ -202,7 +203,7 @@ class SettingsGenericAdapter(context: Context, private var items: List(private val inflate:
}
private fun SettingsGenericAdapter.setup() = adapterEnabled?.let {
- lifecycleScope.launchWhenResumed {
+ whenResumed {
it.collect { enabled ->
isAdapterEnabled = enabled
notifyDataSetChanged()
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/main/SettingsMainFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/main/SettingsMainFragment.kt
index ce9f5ab..3c9b1a2 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/main/SettingsMainFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/main/SettingsMainFragment.kt
@@ -14,6 +14,7 @@ import com.kieronquinn.app.classicpowermenu.ui.base.AutoExpandOnRotate
import com.kieronquinn.app.classicpowermenu.ui.base.ProvidesOverflow
import com.kieronquinn.app.classicpowermenu.ui.base.Root
import com.kieronquinn.app.classicpowermenu.ui.screens.settings.switched.SettingsSwitchedFragment
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -120,13 +121,13 @@ class SettingsMainFragment : SettingsSwitchedFragment(), AutoExpandOnRotate, Pro
viewModel.onResume()
}
- private fun setupDeveloperOptions() = lifecycleScope.launchWhenResumed {
+ private fun setupDeveloperOptions() = whenResumed {
viewModel.developerOptionsEnabled.collect {
recyclerView().adapter?.notifyDataSetChanged()
}
}
- private fun setupAccessibilityWarning() = lifecycleScope.launchWhenResumed {
+ private fun setupAccessibilityWarning() = whenResumed {
viewModel.accessibilityServiceDisabledFlow.collect {
recyclerView().adapter?.notifyDataSetChanged()
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/poweroptions/rearrange/SettingsPowerOptionsRearrangeFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/poweroptions/rearrange/SettingsPowerOptionsRearrangeFragment.kt
index 8bf1302..bdea6fe 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/poweroptions/rearrange/SettingsPowerOptionsRearrangeFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/poweroptions/rearrange/SettingsPowerOptionsRearrangeFragment.kt
@@ -117,7 +117,7 @@ class SettingsPowerOptionsRearrangeFragment: BoundFragment(FragmentS
setupUpdateChecker()
}
- private fun setupNavigation() = viewLifecycleOwner.lifecycleScope.launchWhenResumed {
+ private fun setupNavigation() = whenResumed {
navigation.navigationBus.collect {
handleNavigationEvent(it)
}
@@ -53,7 +54,8 @@ class SettingsRootFragment: BoundFragment(FragmentS
}
private fun setupUpdateChecker(){
- lifecycleScope.launchWhenResumed {
+ return
+ whenResumed {
sharedViewModel.update.collect {
if(it != null) {
navigation.navigate(SettingsRootCheckFragmentDirections.actionGlobalUpdateAvailableBottomSheetFragment())
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/rootcheck/SettingsRootCheckFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/rootcheck/SettingsRootCheckFragment.kt
index 4413401..4cb802e 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/rootcheck/SettingsRootCheckFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/rootcheck/SettingsRootCheckFragment.kt
@@ -5,6 +5,7 @@ import android.view.View
import androidx.lifecycle.lifecycleScope
import com.kieronquinn.app.classicpowermenu.databinding.FragmentSettingsRootCheckBinding
import com.kieronquinn.app.classicpowermenu.ui.base.BoundFragment
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import com.kieronquinn.monetcompat.extensions.views.applyMonet
import kotlinx.coroutines.flow.collect
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -27,7 +28,7 @@ class SettingsRootCheckFragment: BoundFragment
}
private fun setupState() {
- viewLifecycleOwner.lifecycleScope.launchWhenResumed {
+ whenResumed {
viewModel.state.collect {
handleState(it)
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/switched/SettingsSwitchedFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/switched/SettingsSwitchedFragment.kt
index 6cfc3bd..08966b9 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/switched/SettingsSwitchedFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/settings/switched/SettingsSwitchedFragment.kt
@@ -5,6 +5,7 @@ import android.view.View
import androidx.lifecycle.lifecycleScope
import com.kieronquinn.app.classicpowermenu.databinding.FragmentSettingsSwitchedBinding
import com.kieronquinn.app.classicpowermenu.ui.screens.settings.generic.SettingsGenericBaseFragment
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
@@ -33,7 +34,7 @@ abstract class SettingsSwitchedFragment: SettingsGenericBaseFragment(Fragmen
setOnClickListener {
viewModel.onControlsSwitchClicked()
}
- lifecycleScope.launchWhenResumed {
+ whenResumed {
viewModel.controlsEnabledFlow.collect {
isChecked = it
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/rootcheck/SetupRootCheckFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/rootcheck/SetupRootCheckFragment.kt
index 4af3525..82b6463 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/rootcheck/SetupRootCheckFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/rootcheck/SetupRootCheckFragment.kt
@@ -5,6 +5,7 @@ import android.view.View
import androidx.lifecycle.lifecycleScope
import com.kieronquinn.app.classicpowermenu.databinding.FragmentSetupRootcheckBinding
import com.kieronquinn.app.classicpowermenu.ui.base.BoundFragment
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import com.kieronquinn.monetcompat.extensions.views.applyMonet
import kotlinx.coroutines.flow.collect
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -25,7 +26,7 @@ class SetupRootCheckFragment: BoundFragment(Fragm
}
private fun setupState() {
- viewLifecycleOwner.lifecycleScope.launchWhenResumed {
+ whenResumed {
viewModel.state.collect {
handleState(it)
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/wallet/SetupWalletFragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/wallet/SetupWalletFragment.kt
index 3852ed8..ffcc818 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/wallet/SetupWalletFragment.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/screens/setup/wallet/SetupWalletFragment.kt
@@ -10,6 +10,7 @@ import com.kieronquinn.app.classicpowermenu.databinding.FragmentSetupWalletBindi
import com.kieronquinn.app.classicpowermenu.ui.base.BoundFragment
import com.kieronquinn.app.classicpowermenu.ui.base.StandaloneFragment
import com.kieronquinn.app.classicpowermenu.utils.extensions.onApplyInsets
+import com.kieronquinn.app.classicpowermenu.utils.extensions.whenResumed
import com.kieronquinn.monetcompat.extensions.views.overrideRippleColor
import kotlinx.coroutines.flow.collect
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -63,7 +64,7 @@ class SetupWalletFragment: BoundFragment(FragmentSet
setOnClickListener {
viewModel.onWalletSwitchClicked()
}
- lifecycleScope.launchWhenResumed {
+ whenResumed {
viewModel.walletEnabledFlow.collect {
isChecked = it
}
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/views/MonetSwitch.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/views/MonetSwitch.kt
new file mode 100644
index 0000000..af19b7f
--- /dev/null
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/ui/views/MonetSwitch.kt
@@ -0,0 +1,166 @@
+package com.kieronquinn.app.classicpowermenu.ui.views
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.res.ColorStateList
+import android.graphics.Color
+import android.graphics.PorterDuff
+import android.os.Build
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import android.widget.Switch
+import android.widget.TextView
+import androidx.annotation.ColorInt
+import com.google.android.material.materialswitch.MaterialSwitch
+import com.kieronquinn.app.classicpowermenu.R
+import com.kieronquinn.monetcompat.core.MonetCompat
+import com.kieronquinn.monetcompat.extensions.views.applyMonet
+import com.kieronquinn.monetcompat.extensions.views.overrideRippleColor
+import com.kieronquinn.monetcompat.interfaces.MonetColorsChangedListener
+import dev.kdrag0n.monet.theme.ColorScheme
+
+/**
+ * A full-width Switch designed to look like the primary ones in Android 12's Settings app. It has
+ * its own background, tinted to Monet's colors, with the [Switch] thumb set to the same color,
+ * and the track a darker color. The background/track color changes depending on the switch state.
+ */
+open class MonetSwitch: FrameLayout, MonetColorsChangedListener {
+
+ constructor(context: Context): super(context, null)
+
+ constructor(context: Context, attributeSet: AttributeSet?) : super(context, attributeSet, R.attr.switchStyle) {
+ readAttributes(attributeSet)
+ }
+
+ constructor(context: Context, attributeSet: AttributeSet?, styleResId: Int): super(context, attributeSet, styleResId){
+ readAttributes(attributeSet)
+ }
+
+ private val layoutInflater = LayoutInflater.from(context)
+ private var suppressCheckChange = false
+
+ private val layout by lazy {
+ layoutInflater.inflate(R.layout.view_monet_switch, this, false)
+ }
+
+ private val label by lazy {
+ layout.findViewById(R.id.view_monet_switch_text)
+ }
+
+ private val switch by lazy {
+ layout.findViewById(R.id.view_monet_switch_switch)
+ }
+
+ private val root by lazy {
+ layout.findViewById(R.id.view_monet_switch_root)
+ }
+
+ var isChecked: Boolean
+ get() = switch.isChecked
+ set(value) {
+ suppressCheckChange = true
+ switch.isChecked = value
+ suppressCheckChange = false
+ }
+
+ var text: CharSequence
+ get() = label.text
+ set(value) {
+ label.text = value
+ }
+
+ @SuppressLint("PrivateResource", "CustomViewStyleable")
+ private fun readAttributes(attributeSet: AttributeSet?){
+ if(attributeSet == null || isInEditMode) return
+ addView(layout)
+ val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.MonetSwitch)
+ var textAppearance = typedArray.getResourceId(R.styleable.MonetSwitch_android_textAppearance, R.style.TextAppearance_AppCompat_Medium)
+ //Sometimes the field will default to TextAppearance.Material so we need to counter that
+ if(textAppearance == android.R.style.TextAppearance_Material) textAppearance = R.style.TextAppearance_AppCompat_Medium
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ label.setTextAppearance(textAppearance)
+ }else{
+ label.setTextAppearance(context, textAppearance)
+ }
+ val materialTypedArray = context.obtainStyledAttributes(attributeSet, com.google.android.material.R.styleable.MaterialSwitch)
+ val thumbIcon = materialTypedArray.getResourceId(com.google.android.material.R.styleable.MaterialSwitch_thumbIcon, 0)
+ val thumbTint = materialTypedArray.getColor(com.google.android.material.R.styleable.MaterialSwitch_thumbIconTint, 0)
+ val thumbTintMode = materialTypedArray.getInt(com.google.android.material.R.styleable.MaterialSwitch_thumbIconTintMode, 0)
+ if(thumbIcon != 0){
+ switch.setThumbIconResource(thumbIcon)
+ }
+ if(thumbTint != 0){
+ switch.thumbIconTintList = ColorStateList.valueOf(thumbTint)
+ }
+ if(thumbTintMode != 0){
+ switch.thumbIconTintMode = PorterDuff.Mode.values()[thumbTintMode]
+ }
+ val textColor = typedArray.getColor(R.styleable.MonetSwitch_android_textColor, Color.BLACK)
+ label.setTextColor(textColor)
+ val switchText = typedArray.getText(R.styleable.MonetSwitch_android_text) ?: ""
+ label.text = switchText
+ typedArray.recycle()
+ materialTypedArray.recycle()
+ }
+
+ private val monet by lazy {
+ MonetCompat.getInstance()
+ }
+
+ init {
+ isClickable = true
+ isFocusable = true
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ if(!isInEditMode) {
+ monet.addMonetColorsChangedListener(this, true)
+ }
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ monet.removeMonetColorsChangedListener(this)
+ }
+
+ override fun onMonetColorsChanged(
+ monet: MonetCompat,
+ monetColors: ColorScheme,
+ isInitialChange: Boolean
+ ) {
+ applyMonet()
+ }
+
+ private fun applyMonet() = with(monet) {
+ val checkedThumbColor = monet.getPrimaryColor(context, false)
+ val uncheckedThumbColor = monet.getSecondaryColor(context, false)
+ setTint(uncheckedThumbColor, checkedThumbColor)
+ }
+
+ private fun setTint(
+ @ColorInt uncheckedThumbColor: Int,
+ @ColorInt checkedThumbColor: Int
+ ){
+ val bgTintList = ColorStateList(
+ arrayOf(intArrayOf(android.R.attr.state_activated), intArrayOf()),
+ intArrayOf(checkedThumbColor, uncheckedThumbColor)
+ )
+ root.backgroundTintList = bgTintList
+ root.backgroundTintMode = PorterDuff.Mode.SRC_ATOP
+ root.isActivated = switch.isChecked
+ switch.setOnCheckedChangeListener { _, checked ->
+ root.isActivated = switch.isChecked
+ if(!suppressCheckChange){
+ isChecked = !checked
+ performClick()
+ }
+ }
+ switch.applyMonet()
+ switch.thumbTintMode = PorterDuff.Mode.SRC_ATOP
+ overrideRippleColor(colorStateList = bgTintList)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/TransitionUtils.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/TransitionUtils.kt
index d37d254..e6c1973 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/TransitionUtils.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/TransitionUtils.kt
@@ -2,9 +2,9 @@ package com.kieronquinn.app.classicpowermenu.utils
import android.content.Context
import android.view.animation.AnimationUtils
-import com.google.android.material.transition.platform.FadeThroughProvider
-import com.google.android.material.transition.platform.MaterialSharedAxis
-import com.google.android.material.transition.platform.SlideDistanceProvider
+import com.google.android.material.transition.FadeThroughProvider
+import com.google.android.material.transition.MaterialSharedAxis
+import com.google.android.material.transition.SlideDistanceProvider
import com.kieronquinn.app.classicpowermenu.R
import kotlin.math.roundToInt
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Fragment.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Fragment.kt
new file mode 100644
index 0000000..6ea0912
--- /dev/null
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Fragment.kt
@@ -0,0 +1,19 @@
+package com.kieronquinn.app.classicpowermenu.utils.extensions
+
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.LifecycleOwner
+import kotlinx.coroutines.CoroutineScope
+
+/**
+ * Helper for [LifecycleOwner].[whenResumed]
+ */
+fun Fragment.whenResumed(block: suspend CoroutineScope.() -> Unit) {
+ viewLifecycleOwner.whenResumed(block)
+}
+
+/**
+ * Helper for [LifecycleOwner].[whenCreated]
+ */
+fun Fragment.whenCreated(block: suspend CoroutineScope.() -> Unit) {
+ viewLifecycleOwner.whenCreated(block)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Lifecycle.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Lifecycle.kt
new file mode 100644
index 0000000..a4e82ee
--- /dev/null
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Lifecycle.kt
@@ -0,0 +1,36 @@
+package com.kieronquinn.app.classicpowermenu.utils.extensions
+
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.OnLifecycleEvent
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+
+fun LifecycleOwner.whenResumed(block: suspend CoroutineScope.() -> Unit): Job {
+ return lifecycleScope.launch {
+ lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
+ block()
+ }
+ }
+}
+
+fun LifecycleOwner.whenCreated(block: suspend CoroutineScope.() -> Unit): Job {
+ return lifecycleScope.launch {
+ lifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) {
+ block()
+ }
+ }
+}
+
+fun Lifecycle.runOnDestroy(block: () -> Unit) {
+ addObserver(object: LifecycleObserver {
+ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ fun onDestroy() {
+ block()
+ }
+ })
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Navigation.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Navigation.kt
index 80bc7ed..161e0c4 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Navigation.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+Navigation.kt
@@ -1,5 +1,6 @@
package com.kieronquinn.app.classicpowermenu.utils.extensions
+import androidx.activity.OnBackPressedCallback
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
@@ -26,7 +27,16 @@ fun NavController.onDestinationChanged() = callbackFlow {
trySend(destination)
}
addOnDestinationChangedListener(listener)
+ currentDestination?.let {
+ trySend(it)
+ }
awaitClose {
removeOnDestinationChangedListener(listener)
}
-}.debounce(250L)
\ No newline at end of file
+}.debounce(250L)
+
+fun NavController.setOnBackPressedCallback(callback: OnBackPressedCallback) {
+ NavController::class.java.getDeclaredField("onBackPressedCallback").apply {
+ isAccessible = true
+ }.set(this, callback)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+View.kt b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+View.kt
index 81dee4b..953f38c 100644
--- a/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+View.kt
+++ b/app/src/main/java/com/kieronquinn/app/classicpowermenu/utils/extensions/Extensions+View.kt
@@ -3,6 +3,10 @@ package com.kieronquinn.app.classicpowermenu.utils.extensions
import android.graphics.Point
import android.graphics.Rect
import android.view.View
+import android.view.ViewTreeObserver
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.coroutineScope
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
@@ -32,4 +36,24 @@ fun View.contains(point: Point): Boolean {
Rect(this[0], this[1], this[0] + width, this[0] + height)
}
return position.contains(point.x, point.y)
+}
+
+fun View.delayPreDrawUntilFlow(flow: Flow, lifecycle: Lifecycle) {
+ val listener = ViewTreeObserver.OnPreDrawListener {
+ false
+ }
+ val removeListener = {
+ if (viewTreeObserver.isAlive) {
+ viewTreeObserver.removeOnPreDrawListener(listener)
+ }
+ }
+ lifecycle.runOnDestroy {
+ removeListener()
+ }
+ viewTreeObserver.addOnPreDrawListener(listener)
+ lifecycle.coroutineScope.launchWhenResumed {
+ flow.collect {
+ removeListener()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/switch_background_ripple.xml b/app/src/main/res/drawable/switch_background_ripple.xml
new file mode 100644
index 0000000..c286d3c
--- /dev/null
+++ b/app/src/main/res/drawable/switch_background_ripple.xml
@@ -0,0 +1,18 @@
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 82f2512..ac218c9 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -10,7 +10,9 @@
+ app:defaultNavHost="true"
+ app:navGraph="@navigation/nav_graph_root" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_power_menu.xml b/app/src/main/res/layout/fragment_power_menu.xml
index 03884e6..2cbcbe9 100644
--- a/app/src/main/res/layout/fragment_power_menu.xml
+++ b/app/src/main/res/layout/fragment_power_menu.xml
@@ -4,6 +4,7 @@
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
+ android:transitionGroup="true"
android:orientation="vertical">
+ android:layout_height="match_parent"
+ android:transitionGroup="true">
-
+ android:padding="16dp"
+ tools:src="@drawable/ic_settings_power_options" />
+ android:orientation="vertical"
+ android:paddingTop="@dimen/margin_8"
+ android:paddingBottom="@dimen/margin_8">
+ android:textColor="?android:textColorPrimary"
+ tools:text="Setting Title" />
+ tools:visibility="visible" />
-
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/margin_16"
+ android:theme="@style/Theme.Material3.DayNight.NoActionBar"
+ app:showText="false"
+ tools:checked="true" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_monet_switch.xml b/app/src/main/res/layout/view_monet_switch.xml
new file mode 100644
index 0000000..fbe1571
--- /dev/null
+++ b/app/src/main/res/layout/view_monet_switch.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph_root.xml b/app/src/main/res/navigation/nav_graph_root.xml
new file mode 100644
index 0000000..908de5b
--- /dev/null
+++ b/app/src/main/res/navigation/nav_graph_root.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph_settings_container.xml b/app/src/main/res/navigation/nav_graph_settings_container.xml
index 71a06db..e069a11 100644
--- a/app/src/main/res/navigation/nav_graph_settings_container.xml
+++ b/app/src/main/res/navigation/nav_graph_settings_container.xml
@@ -43,7 +43,7 @@
+ app:popUpTo="@id/nav_graph_settings_container"/>
diff --git a/app/src/main/res/navigation/nav_graph_settings_root.xml b/app/src/main/res/navigation/nav_graph_settings_root.xml
index 754db03..33ff63a 100644
--- a/app/src/main/res/navigation/nav_graph_settings_root.xml
+++ b/app/src/main/res/navigation/nav_graph_settings_root.xml
@@ -9,10 +9,12 @@
android:label="DecisionFragment" >
+ app:destination="@id/nav_graph_settings_container"
+ app:popUpTo="@id/nav_graph_settings_root" />
+ app:destination="@id/nav_graph_setup"
+ app:popUpTo="@id/nav_graph_settings_root" />
@@ -21,5 +23,5 @@
app:destination="@id/nav_graph_settings_container"
app:enterAnim="@anim/activity_fade_in"
app:exitAnim="@anim/activity_fade_out"
- app:popUpTo="@null" />
+ app:popUpTo="@string/root_check_checking_root" />
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index a865d7c..494009f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.nav_version = "2.7.6"
- ext.koin_version = "3.5.0"
+ ext.nav_version = "2.7.7"
+ ext.koin_version = "3.5.3"
ext.protobuf_version = '0.9.1'
dependencies {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
@@ -11,9 +11,9 @@ buildscript {
}
plugins {
- id 'com.android.application' version '8.2.2' apply false
- id 'com.android.library' version '8.2.2' apply false
- id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
+ id 'com.android.application' version '8.5.2' apply false
+ id 'com.android.library' version '8.5.2' apply false
+ id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
}
task clean(type: Delete) {
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 174e1ef..78c8b71 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sat Feb 03 22:31:39 GMT 2024
+#Fri Aug 23 23:23:13 BST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/systemstubs/build.gradle b/systemstubs/build.gradle
index c71dbeb..791d191 100644
--- a/systemstubs/build.gradle
+++ b/systemstubs/build.gradle
@@ -3,12 +3,12 @@ plugins {
}
android {
- compileSdkVersion 34
- buildToolsVersion "31.0.0"
+ compileSdk 34
defaultConfig {
- minSdkVersion 28
- targetSdkVersion 34
+ minSdk 30
+ targetSdk 35
+
consumerProguardFiles "consumer-rules.pro"
}
@@ -29,5 +29,5 @@ android {
}
dependencies {
- implementation 'androidx.annotation:annotation:1.7.1'
+ implementation 'androidx.annotation:annotation:1.8.2'
}
\ No newline at end of file