• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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.screenshot
18 
19 import android.app.assist.AssistContent
20 import android.content.Context
21 import android.net.Uri
22 import android.util.Log
23 import androidx.appcompat.content.res.AppCompatResources
24 import com.android.internal.logging.UiEventLogger
25 import com.android.systemui.dagger.qualifiers.Application
26 import com.android.systemui.log.DebugLogger.debugLog
27 import com.android.systemui.res.R
28 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_EDIT_TAPPED
29 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED
30 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SHARE_TAPPED
31 import com.android.systemui.screenshot.ui.viewmodel.ActionButtonAppearance
32 import com.android.systemui.screenshot.ui.viewmodel.PreviewAction
33 import com.android.systemui.shared.Flags.screenshotContextUrl
34 import dagger.assisted.Assisted
35 import dagger.assisted.AssistedFactory
36 import dagger.assisted.AssistedInject
37 import java.util.UUID
38 import kotlinx.coroutines.CoroutineScope
39 import kotlinx.coroutines.launch
40 
41 /**
42  * Provides actions for screenshots. This class can be overridden by a vendor-specific SysUI
43  * implementation.
44  */
45 interface ScreenshotActionsProvider {
46     fun onScrollChipReady(onClick: Runnable)
47 
48     fun onScrollChipInvalidated()
49 
50     fun setCompletedScreenshot(result: ScreenshotSavedResult)
51 
52     /**
53      * Provide the AssistContent for the focused task if available, null if the focused task isn't
54      * known or didn't return data.
55      */
56     fun onAssistContent(assistContent: AssistContent?) {}
57 
58     interface Factory {
59         fun create(
60             requestId: UUID,
61             request: ScreenshotData,
62             actionExecutor: ActionExecutor,
63             actionsCallback: ScreenshotActionsController.ActionsCallback,
64         ): ScreenshotActionsProvider
65     }
66 }
67 
68 class DefaultScreenshotActionsProvider
69 @AssistedInject
70 constructor(
71     private val context: Context,
72     private val uiEventLogger: UiEventLogger,
73     private val actionIntentCreator: ActionIntentCreator,
74     @Application private val applicationScope: CoroutineScope,
75     @Assisted val requestId: UUID,
76     @Assisted val request: ScreenshotData,
77     @Assisted val actionExecutor: ActionExecutor,
78     @Assisted val actionsCallback: ScreenshotActionsController.ActionsCallback,
79 ) : ScreenshotActionsProvider {
80     private var addedScrollChip = false
81     private var onScrollClick: Runnable? = null
82     private var pendingAction: (suspend (ScreenshotSavedResult) -> Unit)? = null
83     private var result: ScreenshotSavedResult? = null
84     private var webUri: Uri? = null
85 
86     init {
87         actionsCallback.providePreviewAction(
<lambda>null88             PreviewAction(context.resources.getString(R.string.screenshot_edit_description)) {
89                 debugLog(LogConfig.DEBUG_ACTIONS) { "Preview tapped" }
90                 uiEventLogger.log(SCREENSHOT_PREVIEW_TAPPED, 0, request.packageNameString)
91                 onDeferrableActionTapped { result ->
92                     actionExecutor.startSharedTransition(
93                         actionIntentCreator.createEdit(result.uri),
94                         result.user,
95                         true,
96                     )
97                 }
98             }
99         )
100 
101         actionsCallback.provideActionButton(
102             ActionButtonAppearance(
103                 AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_share),
104                 context.resources.getString(R.string.screenshot_share_label),
105                 context.resources.getString(R.string.screenshot_share_description),
106             ),
107             showDuringEntrance = true,
<lambda>null108         ) {
109             debugLog(LogConfig.DEBUG_ACTIONS) { "Share tapped" }
110             uiEventLogger.log(SCREENSHOT_SHARE_TAPPED, 0, request.packageNameString)
111             onDeferrableActionTapped { result ->
112                 val uri = webUri
113                 val shareIntent =
114                     if (screenshotContextUrl() && uri != null) {
115                         actionIntentCreator.createShareWithText(
116                             result.uri,
117                             extraText = uri.toString(),
118                         )
119                     } else {
120                         actionIntentCreator.createShareWithSubject(result.uri, result.subject)
121                     }
122                 actionExecutor.startSharedTransition(shareIntent, result.user, false)
123             }
124         }
125 
126         actionsCallback.provideActionButton(
127             ActionButtonAppearance(
128                 AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_edit),
129                 context.resources.getString(R.string.screenshot_edit_label),
130                 context.resources.getString(R.string.screenshot_edit_description),
131             ),
132             showDuringEntrance = true,
<lambda>null133         ) {
134             debugLog(LogConfig.DEBUG_ACTIONS) { "Edit tapped" }
135             uiEventLogger.log(SCREENSHOT_EDIT_TAPPED, 0, request.packageNameString)
136             onDeferrableActionTapped { result ->
137                 actionExecutor.startSharedTransition(
138                     actionIntentCreator.createEdit(result.uri),
139                     result.user,
140                     true,
141                 )
142             }
143         }
144     }
145 
onScrollChipReadynull146     override fun onScrollChipReady(onClick: Runnable) {
147         onScrollClick = onClick
148         if (!addedScrollChip) {
149             actionsCallback.provideActionButton(
150                 ActionButtonAppearance(
151                     AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_scroll),
152                     context.resources.getString(R.string.screenshot_scroll_label),
153                     context.resources.getString(R.string.screenshot_scroll_label),
154                 ),
155                 showDuringEntrance = true,
156             ) {
157                 onScrollClick?.run()
158             }
159             addedScrollChip = true
160         }
161     }
162 
onScrollChipInvalidatednull163     override fun onScrollChipInvalidated() {
164         onScrollClick = null
165     }
166 
setCompletedScreenshotnull167     override fun setCompletedScreenshot(result: ScreenshotSavedResult) {
168         if (this.result != null) {
169             Log.e(TAG, "Got a second completed screenshot for existing request!")
170             return
171         }
172         this.result = result
173         pendingAction?.also { applicationScope.launch { it.invoke(result) } }
174     }
175 
onAssistContentnull176     override fun onAssistContent(assistContent: AssistContent?) {
177         webUri = assistContent?.webUri
178     }
179 
onDeferrableActionTappednull180     private fun onDeferrableActionTapped(onResult: suspend (ScreenshotSavedResult) -> Unit) {
181         result?.let { applicationScope.launch { onResult.invoke(it) } }
182             ?: run { pendingAction = onResult }
183     }
184 
185     @AssistedFactory
186     interface Factory : ScreenshotActionsProvider.Factory {
createnull187         override fun create(
188             requestId: UUID,
189             request: ScreenshotData,
190             actionExecutor: ActionExecutor,
191             actionsCallback: ScreenshotActionsController.ActionsCallback,
192         ): DefaultScreenshotActionsProvider
193     }
194 
195     companion object {
196         private const val TAG = "ScreenshotActionsPrvdr"
197     }
198 }
199