• 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.photopicker.data.model
18 
19 import android.net.Uri
20 import android.os.Parcel
21 import android.os.Parcelable
22 import com.android.photopicker.core.glide.GlideLoadable
23 import com.android.photopicker.core.glide.ParcelableGlideLoadable
24 import com.android.photopicker.core.glide.Resolution
25 import com.bumptech.glide.load.DataSource
26 import com.bumptech.glide.signature.ObjectKey
27 
28 /** Holds metadata for a group of media items. */
29 sealed interface Group : Parcelable {
30     /** Unique identifier for this group */
31     val id: String
32 
33     /**
34      * Holds metadata for a album item. It is a type of a [Group] object because it represents a
35      * collection of media items.
36      */
37     data class Album(
38         /** This is the ID provided by the [Provider] of this data */
39         override val id: String,
40 
41         /** This is the Picker ID auto-generated in Picker DB */
42         val pickerId: Long,
43         val authority: String,
44         val dateTakenMillisLong: Long,
45         val displayName: String,
46         val coverUri: Uri,
47         val coverMediaSource: MediaSource,
48     ) : Group, GlideLoadable {
getSignaturenull49         override fun getSignature(resolution: Resolution): ObjectKey {
50             return ObjectKey("${coverUri}_$resolution")
51         }
52 
getLoadableUrinull53         override fun getLoadableUri(): Uri {
54             return coverUri
55         }
56 
getDataSourcenull57         override fun getDataSource(): DataSource {
58             return when (coverMediaSource) {
59                 MediaSource.LOCAL -> DataSource.LOCAL
60                 MediaSource.REMOTE -> DataSource.REMOTE
61             }
62         }
63 
describeContentsnull64         override fun describeContents(): Int {
65             return 0
66         }
67 
68         /** Implemented for [Parcelable], and handles all the common attributes. */
writeToParcelnull69         override fun writeToParcel(out: Parcel, flags: Int) {
70             out.writeString(id)
71             out.writeLong(pickerId)
72             out.writeString(authority)
73             out.writeLong(dateTakenMillisLong)
74             out.writeString(displayName)
75             out.writeString(coverUri.toString())
76             out.writeString(coverMediaSource.name)
77         }
78 
79         companion object CREATOR : Parcelable.Creator<Album> {
80 
createFromParcelnull81             override fun createFromParcel(parcel: Parcel): Album {
82                 val album =
83                     Album(
84                         /* id =*/ parcel.readString() ?: "",
85                         /* pickerId=*/ parcel.readLong(),
86                         /* authority=*/ parcel.readString() ?: "",
87                         /* dateTakenMillisLong=*/ parcel.readLong(),
88                         /* displayName =*/ parcel.readString() ?: "",
89                         /* uri= */ Uri.parse(parcel.readString() ?: ""),
90                         /* coverUriMediaSource =*/ MediaSource.valueOf(
91                             parcel.readString() ?: "LOCAL"
92                         ),
93                     )
94                 return album
95             }
96 
newArraynull97             override fun newArray(size: Int): Array<Album?> {
98                 return arrayOfNulls(size)
99             }
100         }
101     }
102 
103     /**
104      * Holds metadata for a category item. It is a type of a [Group] object which can either hold
105      * other categories or media sets.
106      */
107     data class Category(
108         /** This is the ID provided by the [Provider] of this data */
109         override val id: String,
110 
111         /** This is the Picker ID generated in Picker Backend */
112         val pickerId: Long,
113         /** Authority of the source [Provider]. */
114         val authority: String,
115         val displayName: String?,
116         val categoryType: CategoryType,
117         val icons: List<ParcelableGlideLoadable>,
118         val isLeafCategory: Boolean,
119     ) : Group {
120 
describeContentsnull121         override fun describeContents(): Int {
122             return 0
123         }
124 
125         /** Implemented for [Parcelable], and handles all the common attributes. */
writeToParcelnull126         override fun writeToParcel(out: Parcel, flags: Int) {
127             out.writeString(id)
128             out.writeLong(pickerId)
129             out.writeString(authority)
130             out.writeString(displayName)
131             out.writeString(categoryType.name)
132             out.writeParcelableList(icons, /* flags */ 0)
133             out.writeBoolean(isLeafCategory)
134         }
135 
136         companion object CREATOR : Parcelable.Creator<Category> {
137 
createFromParcelnull138             override fun createFromParcel(parcel: Parcel): Category {
139                 @Suppress("DEPRECATION") // For backward-compatibility
140                 return Category(
141                     id = parcel.readString() ?: "",
142                     pickerId = parcel.readLong(),
143                     authority = parcel.readString() ?: "",
144                     displayName = parcel.readString(),
145                     categoryType =
146                         CategoryType.valueOf(
147                             parcel.readString() ?: CategoryType.PEOPLE_AND_PETS.name
148                         ),
149                     icons =
150                         arrayListOf<ParcelableGlideLoadable>().apply {
151                             parcel.readParcelableList(
152                                 this,
153                                 ParcelableGlideLoadable::class.java.classLoader,
154                             )
155                         },
156                     isLeafCategory = parcel.readBoolean(),
157                 )
158             }
159 
newArraynull160             override fun newArray(size: Int): Array<Category?> {
161                 return arrayOfNulls(size)
162             }
163         }
164     }
165 
166     /**
167      * Holds metadata for a media set item. It is a type of a [Group] object which contains media
168      * items.
169      *
170      * It is very similar to albums because they both contain media items, but it's a bit more
171      * generic and meant to handle a wide range of use cases.
172      */
173     data class MediaSet(
174         /** This is the ID provided by the [Provider] of this data */
175         override val id: String,
176 
177         /** This is the Picker ID generated in Picker Backend */
178         val pickerId: Long,
179         /** Authority of the source [Provider]. */
180         val authority: String,
181         val displayName: String?,
182         val icon: ParcelableGlideLoadable,
183     ) : Group {
184 
describeContentsnull185         override fun describeContents(): Int {
186             return 0
187         }
188 
189         /** Implemented for [Parcelable], and handles all the common attributes. */
writeToParcelnull190         override fun writeToParcel(out: Parcel, flags: Int) {
191             out.writeString(id)
192             out.writeLong(pickerId)
193             out.writeString(authority)
194             out.writeString(displayName)
195             out.writeParcelable(icon, /* flags */ 0)
196         }
197 
198         companion object CREATOR : Parcelable.Creator<MediaSet> {
199 
createFromParcelnull200             override fun createFromParcel(parcel: Parcel): MediaSet {
201                 @Suppress("DEPRECATION") // For backward-compatibility
202                 return MediaSet(
203                     id = parcel.readString() ?: "",
204                     pickerId = parcel.readLong(),
205                     authority = parcel.readString() ?: "",
206                     displayName = parcel.readString(),
207                     icon =
208                         parcel.readParcelable(ParcelableGlideLoadable::class.java.classLoader)
209                             ?: Icon(uri = Uri.parse(""), mediaSource = MediaSource.LOCAL),
210                 )
211             }
212 
newArraynull213             override fun newArray(size: Int): Array<MediaSet?> {
214                 return arrayOfNulls(size)
215             }
216         }
217     }
218 }
219