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.inject
18 
19 import android.content.Intent
20 import android.net.Uri
21 import android.service.chooser.ChooserAction
22 import androidx.lifecycle.SavedStateHandle
23 import com.android.intentresolver.data.model.ChooserRequest
24 import com.android.intentresolver.ui.model.ActivityModel
25 import com.android.intentresolver.ui.viewmodel.readChooserRequest
26 import com.android.intentresolver.util.ownedByCurrentUser
27 import com.android.intentresolver.validation.Valid
28 import com.android.intentresolver.validation.ValidationResult
29 import dagger.Module
30 import dagger.Provides
31 import dagger.hilt.InstallIn
32 import dagger.hilt.android.components.ViewModelComponent
33 import dagger.hilt.android.scopes.ViewModelScoped
34 import javax.inject.Qualifier
35 
36 @Module
37 @InstallIn(ViewModelComponent::class)
38 object ActivityModelModule {
39     @Provides
40     fun provideActivityModel(savedStateHandle: SavedStateHandle): ActivityModel =
41         requireNotNull(savedStateHandle[ActivityModel.ACTIVITY_MODEL_KEY]) {
42             "ActivityModel missing in SavedStateHandle! (${ActivityModel.ACTIVITY_MODEL_KEY})"
43         }
44 
45     @Provides
46     @ChooserIntent
47     fun chooserIntent(activityModel: ActivityModel): Intent = activityModel.intent
48 
49     @Provides
50     @ViewModelScoped
51     fun provideInitialRequest(
52         activityModel: ActivityModel,
53         flags: ChooserServiceFlags,
54     ): ValidationResult<ChooserRequest> = readChooserRequest(activityModel, flags)
55 
56     @Provides
57     fun provideChooserRequest(
58         initialRequest: ValidationResult<ChooserRequest>,
59     ): ChooserRequest =
60         requireNotNull((initialRequest as? Valid)?.value) {
61             "initialRequest is Invalid, no chooser request available"
62         }
63 
64     @Provides
65     @TargetIntent
66     fun targetIntent(chooserReq: ValidationResult<ChooserRequest>): Intent =
67         requireNotNull((chooserReq as? Valid)?.value?.targetIntent) { "no target intent available" }
68 
69     @Provides
70     fun customActions(chooserReq: ValidationResult<ChooserRequest>): List<ChooserAction> =
71         requireNotNull((chooserReq as? Valid)?.value?.chooserActions) {
72             "no chooser actions available"
73         }
74 
75     @Provides
76     @ViewModelScoped
77     @ContentUris
78     fun selectedUris(chooserRequest: ValidationResult<ChooserRequest>): List<Uri> =
79         requireNotNull((chooserRequest as? Valid)?.value?.targetIntent?.contentUris?.toList()) {
80             "no selected uris available"
81         }
82 
83     @Provides
84     @FocusedItemIndex
85     fun focusedItemIndex(chooserReq: ValidationResult<ChooserRequest>): Int =
86         requireNotNull((chooserReq as? Valid)?.value?.focusedItemPosition) {
87             "no focused item position available"
88         }
89 
90     @Provides
91     @AdditionalContent
92     fun additionalContentUri(chooserReq: ValidationResult<ChooserRequest>): Uri =
93         requireNotNull((chooserReq as? Valid)?.value?.additionalContentUri) {
94             "no additional content uri available"
95         }
96 }
97 
98 @Qualifier
99 @MustBeDocumented
100 @Retention(AnnotationRetention.RUNTIME)
101 annotation class FocusedItemIndex
102 
103 @Qualifier
104 @MustBeDocumented
105 @Retention(AnnotationRetention.RUNTIME)
106 annotation class AdditionalContent
107 
108 @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ChooserIntent
109 
110 @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class ContentUris
111 
112 @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class TargetIntent
113 
114 private val Intent.contentUris: Sequence<Uri>
<lambda>null115     get() = sequence {
116         if (Intent.ACTION_SEND == action) {
117             getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
118                 ?.takeIf { it.ownedByCurrentUser }
119                 ?.let { yield(it) }
120         } else {
121             getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)?.forEach { uri ->
122                 if (uri.ownedByCurrentUser) {
123                     yield(uri)
124                 }
125             }
126         }
127     }
128