diff options
author | Vignesh Ramanathan <vigneshrsastra@google.com> | 2023-12-08 17:17:10 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2023-12-08 17:17:10 +0000 |
commit | 1f89a051e9edad3cbd351448e3dec9c6ee1c4bce (patch) | |
tree | 98432b145cee0211419c0243d8a0ef0fafa02043 | |
parent | 07abef93e29f64ccf214d7cff9683592c07c07cc (diff) | |
parent | 25903669206de662ce9c66432a5ad37e87d7a7fe (diff) | |
download | Permission-1f89a051e9edad3cbd351448e3dec9c6ee1c4bce.tar.gz |
Merge "Fix for Swipe to Dismiss Animation" into main
4 files changed, 126 insertions, 111 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt index c1ce14f03..a017a9c64 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt @@ -26,9 +26,11 @@ import android.view.View import android.view.ViewGroup import androidx.annotation.StringRes import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.core.os.BundleCompat import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.wear.widget.SwipeDismissFrameLayout import com.android.permissioncontroller.Constants import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW @@ -69,8 +71,21 @@ import com.android.settingslib.RestrictedLockUtils */ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { + private val composeViewTag = "wear_app_permission_fragment_compose_view" private lateinit var confirmDialogViewModel: AppPermissionConfirmDialogViewModel + private val swipeDismissCallback = + object : SwipeDismissFrameLayout.Callback() { + override fun onDismissed(layout: SwipeDismissFrameLayout) { + val viewGroup = view as? ViewGroup + val composeView = viewGroup?.findViewWithTag<ComposeView>(composeViewTag) + if (composeView != null) { + viewGroup.removeView(composeView) + } + parentFragmentManager.popBackStackImmediate() + } + } + companion object { private const val GRANT_CATEGORY = "grant_category" @@ -116,7 +131,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { + ): View { val activity = requireActivity() val packageName = arguments?.getString(Intent.EXTRA_PACKAGE_NAME) @@ -150,6 +165,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { ViewModelProvider(this, AppPermissionConfirmDialogViewModelFactory()) .get(AppPermissionConfirmDialogViewModel::class.java) + @Suppress("ktlint:standard:max-line-length") val onLocationSwitchChanged: (Boolean) -> Unit = { checked -> run { val changeRequest = @@ -231,21 +247,32 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { confirmDialogViewModel.showAdvancedConfirmDialogLiveData.value = false } - return ComposeView(activity).apply { - setContent { - WearAppPermissionScreen( - permGroupLabel, - viewModel, - confirmDialogViewModel, - onLocationSwitchChanged, - onGrantedStateChanged, - onFooterClicked, - onConfirmDialogOkButtonClick, - onConfirmDialogCancelButtonClick, - onAdvancedConfirmDialogOkButtonClick, - onAdvancedConfirmDialogCancelButtonClick + val composeView = + ComposeView(activity).apply { + setViewCompositionStrategy( + ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) + setContent { + WearAppPermissionScreen( + permGroupLabel, + viewModel, + confirmDialogViewModel, + onLocationSwitchChanged, + onGrantedStateChanged, + onFooterClicked, + onConfirmDialogOkButtonClick, + onConfirmDialogCancelButtonClick, + onAdvancedConfirmDialogOkButtonClick, + onAdvancedConfirmDialogCancelButtonClick + ) + } + tag = composeViewTag } + + return SwipeDismissFrameLayout(activity).apply { + addView(composeView) + addCallback(swipeDismissCallback) + setSwipeDismissible(true) } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt index 266159733..ee23724c9 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt @@ -21,18 +21,34 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.wear.widget.SwipeDismissFrameLayout import com.android.permissioncontroller.Constants import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment import com.android.permissioncontroller.permission.ui.model.ManageCustomPermissionsViewModel class WearManageCustomPermissionsFragment : Fragment() { + private val composeViewTag = "wear_app_permission_fragment_compose_view" + + private val swipeDismissCallback = + object : SwipeDismissFrameLayout.Callback() { + override fun onDismissed(layout: SwipeDismissFrameLayout) { + val viewGroup = view as? ViewGroup + val composeView = viewGroup?.findViewWithTag<ComposeView>(composeViewTag) + if (composeView != null) { + viewGroup.removeView(composeView) + } + parentFragmentManager.popBackStackImmediate() + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { + ): View { val activity = requireActivity() val application = activity.getApplication() val sessionId: Long = @@ -51,8 +67,19 @@ class WearManageCustomPermissionsFragment : Fragment() { ) } - return ComposeView(activity).apply { - setContent { WearManageCustomPermissionScreen(viewModel, onPermGroupClick) } + val composeView = + ComposeView(activity).apply { + setViewCompositionStrategy( + ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed + ) + setContent { WearManageCustomPermissionScreen(viewModel, onPermGroupClick) } + tag = composeViewTag + } + + return SwipeDismissFrameLayout(activity).apply { + addView(composeView) + addCallback(swipeDismissCallback) + setSwipeDismissible(true) } } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt index d8eb71e0e..2f75c7eae 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt @@ -28,6 +28,7 @@ import androidx.annotation.RequiresApi import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.wear.widget.SwipeDismissFrameLayout import com.android.modules.utils.build.SdkLevel import com.android.permissioncontroller.Constants import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage @@ -50,6 +51,18 @@ import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissi */ class WearPermissionAppsFragment : Fragment(), PermissionsUsagesChangeCallback { private val LOG_TAG = "PermissionAppsFragment" + private val composeViewTag = "wear_permission_app_fragment_compose_view" + private val swipeDismissCallback = + object : SwipeDismissFrameLayout.Callback() { + override fun onDismissed(layout: SwipeDismissFrameLayout) { + val viewGroup = view as? ViewGroup + val composeView = viewGroup?.findViewWithTag<ComposeView>(composeViewTag) + if (composeView != null) { + viewGroup.removeView(composeView) + } + parentFragmentManager.popBackStackImmediate() + } + } private lateinit var permissionUsages: PermissionUsages private lateinit var wearViewModel: WearAppPermissionUsagesViewModel @@ -61,7 +74,7 @@ class WearPermissionAppsFragment : Fragment(), PermissionsUsagesChangeCallback { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { + ): View { val permGroupName = arguments?.getString(Intent.EXTRA_PERMISSION_GROUP_NAME) ?: arguments?.getString(Intent.EXTRA_PERMISSION_NAME) @@ -141,20 +154,38 @@ class WearPermissionAppsFragment : Fragment(), PermissionsUsagesChangeCallback { ) } - return ComposeView(requireContext()).apply { - setContent { - WearPermissionAppsScreen( - WearPermissionAppsHelper( - activity.getApplication(), - permGroupName, - viewModel, - wearViewModel, - isStorageAndLessThanT, - onAppClick, - onShowSystemClick, - logPermissionAppsFragmentCreated + val composeView = + ComposeView(requireContext()).apply { + setContent { + WearPermissionAppsScreen( + WearPermissionAppsHelper( + activity.getApplication(), + permGroupName, + viewModel, + wearViewModel, + isStorageAndLessThanT, + onAppClick, + onShowSystemClick, + logPermissionAppsFragmentCreated + ) ) - ) + } + tag = composeViewTag + } + + val backstackCount = + activity.supportFragmentManager.primaryNavigationFragment + ?.childFragmentManager + ?.backStackEntryCount + ?: 0 + + return if (backstackCount == 0) { + composeView + } else { + SwipeDismissFrameLayout(context).apply { + addView(composeView) + addCallback(swipeDismissCallback) + setSwipeDismissible(true) } } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt index df7a56464..d9a42e33e 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt @@ -16,9 +16,6 @@ package com.android.permissioncontroller.permission.ui.wear.elements -import android.app.Activity -import android.content.Context -import android.content.ContextWrapper import android.graphics.drawable.Drawable import androidx.compose.foundation.Image import androidx.compose.foundation.focusable @@ -30,11 +27,8 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier @@ -42,7 +36,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.input.rotary.onRotaryScrollEvent import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource @@ -50,7 +43,6 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.fragment.app.FragmentActivity import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import androidx.wear.compose.foundation.lazy.ScalingLazyColumn @@ -60,7 +52,6 @@ import androidx.wear.compose.material.CircularProgressIndicator import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.PositionIndicator import androidx.wear.compose.material.Scaffold -import androidx.wear.compose.material.SwipeToDismissBox import androidx.wear.compose.material.Text import androidx.wear.compose.material.TimeText import androidx.wear.compose.material.Vignette @@ -85,45 +76,16 @@ fun ScrollableScreen( subtitleTestTag: String? = null, content: ScalingLazyListScope.() -> Unit, ) { - var dismissed by remember { mutableStateOf(false) } - val activity = LocalContext.current.findActivity() - - // To support Swipe-dismiss effect, - // add the view to SwipeToDismissBox if the screen is not on the top fragment. - if (getBackStackEntryCount(activity) > 0) { - SwipeToDismissBox( - onDismissed = { - dismiss(activity) - dismissed = true - } - ) { isBackground -> - if (isBackground || dismissed) { - Box(modifier = Modifier.fillMaxSize()) - } else { - Scaffold( - showTimeText, - title, - subtitle, - image, - isLoading, - content, - titleTestTag, - subtitleTestTag - ) - } - } - } else { - Scaffold( - showTimeText, - title, - subtitle, - image, - isLoading, - content, - titleTestTag, - subtitleTestTag - ) - } + Scaffold( + showTimeText, + title, + subtitle, + image, + isLoading, + content, + titleTestTag, + subtitleTestTag + ) } @OptIn(ExperimentalComposeUiApi::class) @@ -249,35 +211,3 @@ private fun RequestFocusOnResume(focusRequester: FocusRequester) { } } } - -internal fun dismiss(activity: Activity) { - if (activity is FragmentActivity) { - if (!activity.getSupportFragmentManager().popBackStackImmediate()) { - activity.finish() - } - } else { - activity.finish() - } -} - -internal fun getBackStackEntryCount(activity: Activity): Int { - return if (activity is FragmentActivity) { - activity - .getSupportFragmentManager() - .primaryNavigationFragment - ?.childFragmentManager - ?.backStackEntryCount - ?: 0 - } else { - 0 - } -} - -internal fun Context.findActivity(): Activity { - var context = this - while (context is ContextWrapper) { - if (context is Activity) return context - context = context.baseContext - } - throw IllegalStateException("The screen should be called in the context of an Activity") -} |