• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.communal.util
18 
19 import android.app.ActivityOptions
20 import android.app.PendingIntent
21 import android.content.Intent
22 import android.view.View
23 import android.widget.RemoteViews
24 import androidx.core.util.component1
25 import androidx.core.util.component2
26 import com.android.systemui.animation.ActivityTransitionAnimator
27 
28 
29 /** A delegate that can be used to launch activities from [RemoteViews] */
30 class InteractionHandlerDelegate(
31     private val findViewToAnimate: (View) -> Boolean,
32     private val intentStarter: IntentStarter,
33 ) : RemoteViews.InteractionHandler {
34 
35     /**
36      * Responsible for starting the pending intent for launching activities.
37      */
interfacenull38     fun interface IntentStarter {
39         fun startPendingIntent(
40             intent: PendingIntent,
41             fillInIntent: Intent,
42             activityOptions: ActivityOptions,
43             controller: ActivityTransitionAnimator.Controller?,
44         ): Boolean
45     }
46 
onInteractionnull47     override fun onInteraction(
48         view: View,
49         pendingIntent: PendingIntent,
50         response: RemoteViews.RemoteResponse
51     ): Boolean {
52         val launchOptions = response.getLaunchOptions(view)
53         return when {
54             pendingIntent.isActivity -> {
55                 // Forward the fill-in intent and activity options retrieved from the response
56                 // to populate the pending intent, so that list items can launch respective
57                 // activities.
58                 val hostView = getNearestParent(view)
59                 val animationController =
60                     hostView?.let(ActivityTransitionAnimator.Controller::fromView)
61                 val (fillInIntent, activityOptions) = launchOptions
62                 intentStarter.startPendingIntent(
63                     pendingIntent,
64                     fillInIntent,
65                     activityOptions,
66                     animationController
67                 )
68             }
69 
70             else -> RemoteViews.startPendingIntent(view, pendingIntent, launchOptions)
71         }
72     }
73 
getNearestParentnull74     private fun getNearestParent(child: View): View? {
75         var view: Any? = child
76         while (view is View) {
77             if (findViewToAnimate(view)) return view
78             view = view.parent
79         }
80         return null
81     }
82 }
83