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.intentresolver.contentpreview.payloadtoggle.domain.cursor
18 
19 import android.content.ContentInterface
20 import android.content.Intent
21 import android.database.Cursor
22 import android.net.Uri
23 import android.service.chooser.AdditionalContentContract.Columns.URI
24 import androidx.core.os.bundleOf
25 import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.CursorRow
26 import com.android.intentresolver.contentpreview.readSize
27 import com.android.intentresolver.inject.AdditionalContent
28 import com.android.intentresolver.inject.ChooserIntent
29 import com.android.intentresolver.util.cursor.CursorView
30 import com.android.intentresolver.util.cursor.viewBy
31 import com.android.intentresolver.util.withCancellationSignal
32 import dagger.Binds
33 import dagger.Module
34 import dagger.hilt.InstallIn
35 import dagger.hilt.android.components.ViewModelComponent
36 import javax.inject.Inject
37 import javax.inject.Qualifier
38 
39 /** [CursorResolver] for the [CursorView] underpinning Shareousel. */
40 class PayloadToggleCursorResolver
41 @Inject
42 constructor(
43     private val contentResolver: ContentInterface,
44     @AdditionalContent private val cursorUri: Uri,
45     @ChooserIntent private val chooserIntent: Intent,
46 ) : CursorResolver<CursorRow?> {
47     override suspend fun getCursor(): CursorView<CursorRow?>? = withCancellationSignal { signal ->
48         runCatching {
49                 contentResolver.query(
50                     cursorUri,
51                     // TODO: uncomment to start using that data
52                     arrayOf(URI /*, WIDTH, HEIGHT*/),
53                     bundleOf(Intent.EXTRA_INTENT to chooserIntent),
54                     signal,
55                 )
56             }
57             .getOrNull()
58             ?.viewBy { readUri()?.let { uri -> CursorRow(uri, readSize(), position) } }
59     }
60 
61     private fun Cursor.readUri(): Uri? {
62         val uriIdx = columnNames.indexOf(URI)
63         if (uriIdx < 0) return null
64         return runCatching {
65                 getString(uriIdx)?.let(Uri::parse)?.takeIf { it.authority != cursorUri.authority }
66             }
67             .getOrNull()
68     }
69 
70     @Module
71     @InstallIn(ViewModelComponent::class)
72     interface Binding {
73         @Binds
74         @PayloadToggle
75         fun bind(cursorResolver: PayloadToggleCursorResolver): CursorResolver<CursorRow?>
76     }
77 }
78 
79 /** [CursorResolver] for the [CursorView] underpinning Shareousel. */
80 @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class PayloadToggle
81