• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.photopicker.features.preview
18 
19 import androidx.compose.runtime.Composable
20 import androidx.compose.ui.Modifier
21 import androidx.compose.ui.window.DialogProperties
22 import androidx.navigation.NamedNavArgument
23 import androidx.navigation.NavBackStackEntry
24 import androidx.navigation.NavDeepLink
25 import com.android.photopicker.core.configuration.PhotopickerConfiguration
26 import com.android.photopicker.core.configuration.PhotopickerRuntimeEnv
27 import com.android.photopicker.core.events.Event
28 import com.android.photopicker.core.events.RegisteredEventClass
29 import com.android.photopicker.core.features.FeatureManager
30 import com.android.photopicker.core.features.FeatureRegistration
31 import com.android.photopicker.core.features.FeatureToken
32 import com.android.photopicker.core.features.Location
33 import com.android.photopicker.core.features.LocationParams
34 import com.android.photopicker.core.features.PhotopickerUiFeature
35 import com.android.photopicker.core.features.PrefetchResultKey
36 import com.android.photopicker.core.features.Priority
37 import com.android.photopicker.core.navigation.PhotopickerDestinations
38 import com.android.photopicker.core.navigation.Route
39 import com.android.photopicker.data.model.Media
40 import kotlinx.coroutines.Deferred
41 
42 /**
43  * Feature class for the Photopicker's media preview.
44  *
45  * This feature adds the [PREVIEW_MEDIA] and [PREVIEW_SELECTION] routes to the application.
46  */
47 class PreviewFeature : PhotopickerUiFeature {
48 
49     companion object Registration : FeatureRegistration {
50         override val TAG: String = "PhotopickerPreviewFeature"
51 
isEnablednull52         override fun isEnabled(
53             config: PhotopickerConfiguration,
54             deferredPrefetchResultsMap: Map<PrefetchResultKey, Deferred<Any?>>,
55         ) = config.runtimeEnv != PhotopickerRuntimeEnv.EMBEDDED
56 
57         override fun build(featureManager: FeatureManager) = PreviewFeature()
58 
59         val PREVIEW_MEDIA_KEY = "preview_media"
60     }
61 
62     override val token = FeatureToken.PREVIEW.token
63 
64     /** Events consumed by the Preview page */
65     override val eventsConsumed = emptySet<RegisteredEventClass>()
66 
67     /** Events produced by the Preview page */
68     override val eventsProduced =
69         setOf<RegisteredEventClass>(
70             Event.LogPhotopickerUIEvent::class.java,
71             Event.LogPhotopickerPreviewInfo::class.java,
72         )
73 
74     override fun registerLocations(): List<Pair<Location, Int>> {
75         return listOf(Pair(Location.SELECTION_BAR_SECONDARY_ACTION, Priority.HIGH.priority))
76     }
77 
registerNavigationRoutesnull78     override fun registerNavigationRoutes(): Set<Route> {
79         return setOf(
80             object : Route {
81                 override val route = PhotopickerDestinations.PREVIEW_SELECTION.route
82                 override val initialRoutePriority = Priority.LAST.priority
83                 override val arguments = emptyList<NamedNavArgument>()
84                 override val deepLinks = emptyList<NavDeepLink>()
85                 override val isDialog = true
86                 override val dialogProperties =
87                     DialogProperties(
88                         dismissOnBackPress = true,
89                         dismissOnClickOutside = true,
90                         usePlatformDefaultWidth = false,
91                         decorFitsSystemWindows = true,
92                     )
93 
94                 override val enterTransition = null
95                 override val exitTransition = null
96                 override val popEnterTransition = null
97                 override val popExitTransition = null
98 
99                 @Composable
100                 override fun composable(navBackStackEntry: NavBackStackEntry?) {
101                     PreviewSelection()
102                 }
103             },
104             object : Route {
105                 override val route = PhotopickerDestinations.PREVIEW_MEDIA.route
106                 override val initialRoutePriority = Priority.LAST.priority
107                 override val arguments = emptyList<NamedNavArgument>()
108                 override val deepLinks = emptyList<NavDeepLink>()
109                 override val isDialog = true
110                 override val dialogProperties =
111                     DialogProperties(
112                         dismissOnBackPress = true,
113                         dismissOnClickOutside = true,
114                         usePlatformDefaultWidth = false,
115                         decorFitsSystemWindows = true,
116                     )
117 
118                 override val enterTransition = null
119                 override val exitTransition = null
120                 override val popEnterTransition = null
121                 override val popExitTransition = null
122 
123                 @Composable
124                 override fun composable(navBackStackEntry: NavBackStackEntry?) {
125                     val flow =
126                         checkNotNull(
127                             navBackStackEntry
128                                 ?.savedStateHandle
129                                 ?.getStateFlow<Media?>(PREVIEW_MEDIA_KEY, null)
130                         ) {
131                             "Unable to get a savedStateHandle for preview media"
132                         }
133                     PreviewSelection(previewItemFlow = flow)
134                 }
135             },
136         )
137     }
138 
139     @Composable
composenull140     override fun compose(location: Location, modifier: Modifier, params: LocationParams) {
141         when (location) {
142             Location.SELECTION_BAR_SECONDARY_ACTION -> PreviewSelectionButton(modifier)
143             else -> {}
144         }
145     }
146 }
147