1 /*
2  * Copyright 2023 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 androidx.paging
18 
19 import androidx.annotation.RestrictTo
20 import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
21 
22 /** Events captured from a [PagingData] that was submitted to the [PagingDataPresenter] */
23 public sealed class PagingDataEvent<T : Any> {
24     /**
25      * A prepend load event
26      *
27      * @param [inserted] The list of newly prepended items.
28      * @param [newPlaceholdersBefore] The count of null items leading the list of loaded data when
29      *   new data has been prepended.
30      * @param [oldPlaceholdersBefore] The count of null items leading the list of loaded data prior
31      *   to new data being prepended
32      */
33     public class Prepend<T : Any>
34     @RestrictTo(LIBRARY_GROUP)
35     constructor(
36         val inserted: List<T>,
37         val newPlaceholdersBefore: Int,
38         val oldPlaceholdersBefore: Int,
39     ) : PagingDataEvent<T>() {
40 
equalsnull41         override fun equals(other: Any?): Boolean {
42             return other is Prepend<*> &&
43                 inserted == other.inserted &&
44                 newPlaceholdersBefore == other.newPlaceholdersBefore &&
45                 oldPlaceholdersBefore == other.oldPlaceholdersBefore
46         }
47 
hashCodenull48         override fun hashCode(): Int {
49             return inserted.hashCode() +
50                 newPlaceholdersBefore.hashCode() +
51                 oldPlaceholdersBefore.hashCode()
52         }
53 
toStringnull54         override fun toString(): String {
55             return """PagingDataEvent.Prepend loaded ${inserted.size} items (
56                     |   first item: ${inserted.firstOrNull()}
57                     |   last item: ${inserted.lastOrNull()}
58                     |   newPlaceholdersBefore: $newPlaceholdersBefore
59                     |   oldPlaceholdersBefore: $oldPlaceholdersBefore
60                     |)
61                     |"""
62                 .trimMargin()
63         }
64     }
65 
66     /**
67      * An append load event
68      *
69      * @param [startIndex] The first index where this append is applied. If placeholders are
70      *   enabled, represents the index of the first placeholder replaced with a real item.
71      *   Otherwise, it represents the index of where the first new item is inserted.
72      * @param [inserted] The list of newly appended items.
73      * @param [newPlaceholdersAfter] The count of null items trailing the list of loaded data when
74      *   new data has been appended.
75      * @param [oldPlaceholdersAfter] The count of null items trailing the list of loaded data prior
76      *   to new data being appended.
77      */
78     public class Append<T : Any>
79     @RestrictTo(LIBRARY_GROUP)
80     constructor(
81         val startIndex: Int,
82         val inserted: List<T>,
83         val newPlaceholdersAfter: Int,
84         val oldPlaceholdersAfter: Int,
85     ) : PagingDataEvent<T>() {
equalsnull86         override fun equals(other: Any?): Boolean {
87             return other is Append<*> &&
88                 startIndex == other.startIndex &&
89                 inserted == other.inserted &&
90                 newPlaceholdersAfter == other.newPlaceholdersAfter &&
91                 oldPlaceholdersAfter == other.oldPlaceholdersAfter
92         }
93 
hashCodenull94         override fun hashCode(): Int {
95             return startIndex.hashCode() +
96                 inserted.hashCode() +
97                 newPlaceholdersAfter.hashCode() +
98                 oldPlaceholdersAfter.hashCode()
99         }
100 
toStringnull101         override fun toString(): String {
102             return """PagingDataEvent.Append loaded ${inserted.size} items (
103                     |   startIndex: $startIndex
104                     |   first item: ${inserted.firstOrNull()}
105                     |   last item: ${inserted.lastOrNull()}
106                     |   newPlaceholdersBefore: $newPlaceholdersAfter
107                     |   oldPlaceholdersBefore: $oldPlaceholdersAfter
108                     |)
109                     |"""
110                 .trimMargin()
111         }
112     }
113 
114     /**
115      * A refresh load event
116      *
117      * @param [newList] A [PlaceholderPaddedList] that contains the metadata of the new list that is
118      *   presented upon this refresh event
119      * @param [previousList] A [PlaceholderPaddedList] that contains the metadata of the list
120      *   presented prior to this refresh load event
121      */
122     public class Refresh<T : Any>
123     @RestrictTo(LIBRARY_GROUP)
124     constructor(
125         val newList: PlaceholderPaddedList<T>,
126         val previousList: PlaceholderPaddedList<T>,
127     ) : PagingDataEvent<T>() {
equalsnull128         override fun equals(other: Any?): Boolean {
129             return other is Refresh<*> &&
130                 newList.placeholdersBefore == other.newList.placeholdersBefore &&
131                 newList.placeholdersAfter == other.newList.placeholdersAfter &&
132                 newList.size == other.newList.size &&
133                 newList.dataCount == other.newList.dataCount &&
134                 previousList.placeholdersBefore == other.previousList.placeholdersBefore &&
135                 previousList.placeholdersAfter == other.previousList.placeholdersAfter &&
136                 previousList.size == other.previousList.size &&
137                 previousList.dataCount == other.previousList.dataCount
138         }
139 
hashCodenull140         override fun hashCode(): Int {
141             return newList.hashCode() + previousList.hashCode()
142         }
143 
toStringnull144         override fun toString(): String {
145             return """PagingDataEvent.Refresh loaded newList
146                     |   newList (
147                     |       placeholdersBefore: ${newList.placeholdersBefore}
148                     |       placeholdersAfter: ${newList.placeholdersAfter}
149                     |       size: ${newList.size}
150                     |       dataCount: ${newList.dataCount}
151                     |   )
152                     |   previousList (
153                     |       placeholdersBefore: ${previousList.placeholdersBefore}
154                     |       placeholdersAfter: ${previousList.placeholdersAfter}
155                     |       size: ${previousList.size}
156                     |       dataCount: ${previousList.dataCount}
157                     |   )
158                     |"""
159                 .trimMargin()
160         }
161     }
162 
163     /**
164      * A drop event from the front of the list
165      *
166      * @param [dropCount] A count of items dropped from loaded items
167      * @param [newPlaceholdersBefore] The count of null items leading the list of loaded data after
168      *   items were dropped.
169      * @param [oldPlaceholdersBefore] The count of null items leading the list of loaded data prior
170      *   to items being dropped.
171      */
172     public class DropPrepend<T : Any>
173     @RestrictTo(LIBRARY_GROUP)
174     constructor(
175         val dropCount: Int,
176         val newPlaceholdersBefore: Int,
177         val oldPlaceholdersBefore: Int,
178     ) : PagingDataEvent<T>() {
179 
equalsnull180         override fun equals(other: Any?): Boolean {
181             return other is DropPrepend<*> &&
182                 dropCount == other.dropCount &&
183                 newPlaceholdersBefore == other.newPlaceholdersBefore &&
184                 oldPlaceholdersBefore == other.oldPlaceholdersBefore
185         }
186 
hashCodenull187         override fun hashCode(): Int {
188             return dropCount.hashCode() +
189                 newPlaceholdersBefore.hashCode() +
190                 oldPlaceholdersBefore.hashCode()
191         }
192 
toStringnull193         override fun toString(): String {
194             return """PagingDataEvent.DropPrepend dropped $dropCount items (
195                     |   dropCount: $dropCount
196                     |   newPlaceholdersBefore: $newPlaceholdersBefore
197                     |   oldPlaceholdersBefore: $oldPlaceholdersBefore
198                     |)
199                     |"""
200                 .trimMargin()
201         }
202     }
203 
204     /**
205      * A drop event from the end of the list
206      *
207      * @param [startIndex] The first index where this drop is applied. If placeholders are enabled,
208      *   represents the index of the first dropped item that was replaced with a placeholder.
209      *   Otherwise, it represents the index of where the first real item was dropped.
210      * @param [dropCount] A count of items dropped from loaded items
211      * @param [newPlaceholdersAfter] The count of null items trailing the list of loaded data after
212      *   items were dropped.
213      * @param [oldPlaceholdersAfter] The count of null items trailing the list of loaded data prior
214      *   to items being dropped.
215      */
216     public class DropAppend<T : Any>
217     @RestrictTo(LIBRARY_GROUP)
218     constructor(
219         val startIndex: Int,
220         val dropCount: Int,
221         val newPlaceholdersAfter: Int,
222         val oldPlaceholdersAfter: Int,
223     ) : PagingDataEvent<T>() {
224 
equalsnull225         override fun equals(other: Any?): Boolean {
226             return other is DropAppend<*> &&
227                 startIndex == other.startIndex &&
228                 dropCount == other.dropCount &&
229                 newPlaceholdersAfter == other.newPlaceholdersAfter &&
230                 oldPlaceholdersAfter == other.oldPlaceholdersAfter
231         }
232 
hashCodenull233         override fun hashCode(): Int {
234             return startIndex.hashCode() +
235                 dropCount.hashCode() +
236                 newPlaceholdersAfter.hashCode() +
237                 oldPlaceholdersAfter.hashCode()
238         }
239 
toStringnull240         override fun toString(): String {
241             return """PagingDataEvent.DropAppend dropped $dropCount items (
242                     |   startIndex: $startIndex
243                     |   dropCount: $dropCount
244                     |   newPlaceholdersBefore: $newPlaceholdersAfter
245                     |   oldPlaceholdersBefore: $oldPlaceholdersAfter
246                     |)
247                     |"""
248                 .trimMargin()
249         }
250     }
251 }
252