OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.chrome.browser.enhancedbookmarks; | |
6 | |
7 import android.content.Context; | |
8 import android.support.v7.widget.RecyclerView; | |
9 import android.support.v7.widget.RecyclerView.ViewHolder; | |
10 import android.view.LayoutInflater; | |
11 import android.view.View; | |
12 import android.view.ViewGroup; | |
13 | |
14 import org.chromium.base.annotations.SuppressFBWarnings; | |
15 import org.chromium.base.metrics.RecordHistogram; | |
16 import org.chromium.chrome.R; | |
17 import org.chromium.chrome.browser.bookmark.BookmarksBridge.BookmarkItem; | |
18 import org.chromium.chrome.browser.bookmark.BookmarksBridge.BookmarkModelObserve
r; | |
19 import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkPromoHeader
.PromoHeaderShowingChangeListener; | |
20 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; | |
21 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.OfflinePageMod
elObserver; | |
22 import org.chromium.chrome.browser.offlinepages.OfflinePageFreeUpSpaceCallback; | |
23 import org.chromium.chrome.browser.offlinepages.OfflinePageFreeUpSpaceDialog; | |
24 import org.chromium.chrome.browser.offlinepages.OfflinePageStorageSpaceHeader; | |
25 import org.chromium.components.bookmarks.BookmarkId; | |
26 | |
27 import java.util.ArrayList; | |
28 import java.util.List; | |
29 | |
30 /** | |
31 * BaseAdapter for EnhancedBookmarkItemsContainer. It manages bookmarks to list
there. | |
32 */ | |
33 class EnhancedBookmarkItemsAdapter extends RecyclerView.Adapter<RecyclerView.Vie
wHolder> implements | |
34 EnhancedBookmarkUIObserver, PromoHeaderShowingChangeListener { | |
35 private static final int PROMO_HEADER_VIEW = 0; | |
36 private static final int FOLDER_VIEW = 1; | |
37 private static final int DIVIDER_VIEW = 2; | |
38 private static final int BOOKMARK_VIEW = 3; | |
39 private static final int OFFLINE_PAGES_STORAGE_VIEW = 4; | |
40 | |
41 private EnhancedBookmarkDelegate mDelegate; | |
42 private Context mContext; | |
43 private EnhancedBookmarkPromoHeader mPromoHeaderManager; | |
44 private OfflinePageStorageSpaceHeader mOfflineStorageHeader; | |
45 | |
46 private List<List<? extends Object>> mSections; | |
47 private List<Object> mPromoHeaderSection = new ArrayList<>(); | |
48 private List<Object> mOfflineStorageSection = new ArrayList<>(); | |
49 private List<Object> mFolderDividerSection = new ArrayList<>(); | |
50 private List<BookmarkId> mFolderSection = new ArrayList<>(); | |
51 private List<Object> mBookmarkDividerSection = new ArrayList<>(); | |
52 private List<BookmarkId> mBookmarkSection = new ArrayList<>(); | |
53 | |
54 private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObse
rver() { | |
55 @Override | |
56 public void bookmarkNodeChanged(BookmarkItem node) { | |
57 int position = getPositionForBookmark(node.getId()); | |
58 if (position >= 0) notifyItemChanged(position); | |
59 } | |
60 | |
61 @Override | |
62 public void bookmarkNodeRemoved(BookmarkItem parent, int oldIndex, Bookm
arkItem node, | |
63 boolean isDoingExtensiveChanges) { | |
64 if (node.isFolder()) { | |
65 mDelegate.notifyStateChange(EnhancedBookmarkItemsAdapter.this); | |
66 } else { | |
67 int deletedPosition = getPositionForBookmark(node.getId()); | |
68 if (deletedPosition >= 0) { | |
69 removeItem(deletedPosition); | |
70 } | |
71 } | |
72 } | |
73 | |
74 @Override | |
75 public void bookmarkModelChanged() { | |
76 mDelegate.notifyStateChange(EnhancedBookmarkItemsAdapter.this); | |
77 } | |
78 }; | |
79 | |
80 private OfflinePageModelObserver mOfflinePageModelObserver; | |
81 | |
82 EnhancedBookmarkItemsAdapter(Context context) { | |
83 mContext = context; | |
84 | |
85 mSections = new ArrayList<>(); | |
86 mSections.add(mPromoHeaderSection); | |
87 mSections.add(mOfflineStorageSection); | |
88 mSections.add(mFolderDividerSection); | |
89 mSections.add(mFolderSection); | |
90 mSections.add(mBookmarkDividerSection); | |
91 mSections.add(mBookmarkSection); | |
92 } | |
93 | |
94 BookmarkId getItem(int position) { | |
95 return (BookmarkId) getSection(position).get(toSectionPosition(position)
); | |
96 } | |
97 | |
98 private int toSectionPosition(int globalPosition) { | |
99 int sectionPosition = globalPosition; | |
100 for (List<?> section : mSections) { | |
101 if (sectionPosition < section.size()) break; | |
102 sectionPosition -= section.size(); | |
103 } | |
104 return sectionPosition; | |
105 } | |
106 | |
107 private List<? extends Object> getSection(int position) { | |
108 int i = position; | |
109 for (List<? extends Object> section : mSections) { | |
110 if (i < section.size()) { | |
111 return section; | |
112 } | |
113 i -= section.size(); | |
114 } | |
115 return null; | |
116 } | |
117 | |
118 /** | |
119 * @return The position of the given bookmark in adapter. Will return -1 if
not found. | |
120 */ | |
121 private int getPositionForBookmark(BookmarkId bookmark) { | |
122 assert bookmark != null; | |
123 int position = -1; | |
124 for (int i = 0; i < getItemCount(); i++) { | |
125 if (bookmark.equals(getItem(i))) { | |
126 position = i; | |
127 break; | |
128 } | |
129 } | |
130 return position; | |
131 } | |
132 | |
133 /** | |
134 * Set folders and bookmarks to show. | |
135 * @param folders This can be null if there is no folders to show. | |
136 */ | |
137 private void setBookmarks(List<BookmarkId> folders, List<BookmarkId> bookmar
ks) { | |
138 if (folders == null) folders = new ArrayList<BookmarkId>(); | |
139 | |
140 mFolderSection.clear(); | |
141 mFolderSection.addAll(folders); | |
142 mBookmarkSection.clear(); | |
143 mBookmarkSection.addAll(bookmarks); | |
144 | |
145 updateHeader(); | |
146 updateDividerSections(); | |
147 | |
148 // TODO(kkimlabs): Animation is disabled due to a performance issue on b
ookmark undo. | |
149 // http://crbug.com/484174 | |
150 notifyDataSetChanged(); | |
151 } | |
152 | |
153 private void updateDividerSections() { | |
154 mFolderDividerSection.clear(); | |
155 mBookmarkDividerSection.clear(); | |
156 | |
157 boolean isHeaderPresent = | |
158 !mPromoHeaderSection.isEmpty() || !mOfflineStorageSection.isEmpt
y(); | |
159 | |
160 if (isHeaderPresent && !mFolderSection.isEmpty()) { | |
161 mFolderDividerSection.add(null); | |
162 } | |
163 if ((isHeaderPresent || !mFolderSection.isEmpty()) && !mBookmarkSection.
isEmpty()) { | |
164 mBookmarkDividerSection.add(null); | |
165 } | |
166 } | |
167 | |
168 private void removeItem(int position) { | |
169 List<?> section = getSection(position); | |
170 assert section == mFolderSection || section == mBookmarkSection; | |
171 section.remove(toSectionPosition(position)); | |
172 notifyItemRemoved(position); | |
173 } | |
174 | |
175 // RecyclerView.Adapter implementation. | |
176 | |
177 @Override | |
178 public int getItemCount() { | |
179 int count = 0; | |
180 for (List<?> section : mSections) { | |
181 count += section.size(); | |
182 } | |
183 return count; | |
184 } | |
185 | |
186 @Override | |
187 public int getItemViewType(int position) { | |
188 List<?> section = getSection(position); | |
189 | |
190 if (section == mPromoHeaderSection) { | |
191 return PROMO_HEADER_VIEW; | |
192 } else if (section == mOfflineStorageSection) { | |
193 return OFFLINE_PAGES_STORAGE_VIEW; | |
194 } else if (section == mFolderDividerSection | |
195 || section == mBookmarkDividerSection) { | |
196 return DIVIDER_VIEW; | |
197 } else if (section == mFolderSection) { | |
198 return FOLDER_VIEW; | |
199 } else if (section == mBookmarkSection) { | |
200 return BOOKMARK_VIEW; | |
201 } | |
202 | |
203 assert false : "Invalid position requested"; | |
204 return -1; | |
205 } | |
206 | |
207 @Override | |
208 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |
209 switch (viewType) { | |
210 case PROMO_HEADER_VIEW: | |
211 return mPromoHeaderManager.createHolder(parent); | |
212 case OFFLINE_PAGES_STORAGE_VIEW: | |
213 return mOfflineStorageHeader.createHolder(parent); | |
214 case DIVIDER_VIEW: | |
215 return new ViewHolder(LayoutInflater.from(parent.getContext()).i
nflate( | |
216 R.layout.eb_divider, parent, false)) {}; | |
217 case FOLDER_VIEW: | |
218 EnhancedBookmarkFolderRow folder = (EnhancedBookmarkFolderRow) L
ayoutInflater | |
219 .from(parent.getContext()).inflate(R.layout.eb_folder_ro
w, parent, false); | |
220 folder.onEnhancedBookmarkDelegateInitialized(mDelegate); | |
221 return new ItemViewHolder(folder); | |
222 case BOOKMARK_VIEW: | |
223 EnhancedBookmarkBookmarkRow item = (EnhancedBookmarkBookmarkRow)
LayoutInflater | |
224 .from(parent.getContext()).inflate(R.layout.eb_bookmark_
row, parent, false); | |
225 item.onEnhancedBookmarkDelegateInitialized(mDelegate); | |
226 return new ItemViewHolder(item); | |
227 default: | |
228 assert false; | |
229 return null; | |
230 } | |
231 } | |
232 | |
233 @SuppressFBWarnings("BC_UNCONFIRMED_CAST") | |
234 @Override | |
235 public void onBindViewHolder(ViewHolder holder, int position) { | |
236 BookmarkId id = getItem(position); | |
237 | |
238 switch (getItemViewType(position)) { | |
239 case PROMO_HEADER_VIEW: | |
240 case OFFLINE_PAGES_STORAGE_VIEW: | |
241 case DIVIDER_VIEW: | |
242 break; | |
243 case FOLDER_VIEW: | |
244 ((EnhancedBookmarkRow) holder.itemView).setBookmarkId(id); | |
245 break; | |
246 case BOOKMARK_VIEW: | |
247 ((EnhancedBookmarkRow) holder.itemView).setBookmarkId(id); | |
248 break; | |
249 default: | |
250 assert false : "View type not supported!"; | |
251 } | |
252 } | |
253 | |
254 // PromoHeaderShowingChangeListener implementation. | |
255 | |
256 @Override | |
257 public void onPromoHeaderShowingChanged(boolean isShowing) { | |
258 if (mDelegate.getCurrentState() != EnhancedBookmarkUIState.STATE_ALL_BOO
KMARKS | |
259 && mDelegate.getCurrentState() != EnhancedBookmarkUIState.STATE_
FOLDER) { | |
260 return; | |
261 } | |
262 | |
263 updateHeader(); | |
264 updateDividerSections(); | |
265 notifyDataSetChanged(); | |
266 } | |
267 | |
268 // EnhancedBookmarkUIObserver implementations. | |
269 | |
270 @Override | |
271 public void onEnhancedBookmarkDelegateInitialized(EnhancedBookmarkDelegate d
elegate) { | |
272 mDelegate = delegate; | |
273 mDelegate.addUIObserver(this); | |
274 mDelegate.getModel().addObserver(mBookmarkModelObserver); | |
275 mPromoHeaderManager = new EnhancedBookmarkPromoHeader(mContext, this); | |
276 OfflinePageBridge offlinePageBridge = mDelegate.getModel().getOfflinePag
eBridge(); | |
277 if (offlinePageBridge != null) { | |
278 mOfflinePageModelObserver = new OfflinePageModelObserver() { | |
279 @Override | |
280 public void offlinePageModelChanged() { | |
281 mDelegate.notifyStateChange(EnhancedBookmarkItemsAdapter.thi
s); | |
282 } | |
283 | |
284 @Override | |
285 public void offlinePageDeleted(BookmarkId bookmarkId) { | |
286 if (mDelegate.getCurrentState() == EnhancedBookmarkUIState.S
TATE_FILTER) { | |
287 int deletedPosition = getPositionForBookmark(bookmarkId)
; | |
288 if (deletedPosition >= 0) { | |
289 removeItem(deletedPosition); | |
290 } | |
291 } | |
292 } | |
293 }; | |
294 offlinePageBridge.addObserver(mOfflinePageModelObserver); | |
295 | |
296 mOfflineStorageHeader = new OfflinePageStorageSpaceHeader( | |
297 mContext, offlinePageBridge, new OfflinePageFreeUpSpaceCallb
ack() { | |
298 @Override | |
299 public void onFreeUpSpaceDone() { | |
300 refreshOfflinePagesFilterView(); | |
301 mDelegate.getSnackbarManager().showSnackbar( | |
302 OfflinePageFreeUpSpaceDialog.createStorageCl
earedSnackbar( | |
303 mContext)); | |
304 } | |
305 | |
306 @Override | |
307 public void onFreeUpSpaceCancelled() { | |
308 // No need to refresh, as result outcome should be t
he same here. | |
309 } | |
310 }); | |
311 } | |
312 } | |
313 | |
314 @Override | |
315 public void onDestroy() { | |
316 mDelegate.removeUIObserver(this); | |
317 mDelegate.getModel().removeObserver(mBookmarkModelObserver); | |
318 mPromoHeaderManager.destroy(); | |
319 | |
320 OfflinePageBridge offlinePageBridge = mDelegate.getModel().getOfflinePag
eBridge(); | |
321 if (offlinePageBridge != null) { | |
322 offlinePageBridge.removeObserver(mOfflinePageModelObserver); | |
323 mOfflineStorageHeader.destroy(); | |
324 } | |
325 } | |
326 | |
327 @Override | |
328 public void onAllBookmarksStateSet() { | |
329 List<BookmarkId> bookmarkIds = | |
330 mDelegate.getModel().getAllBookmarkIDsOrderedByCreationDate(); | |
331 RecordHistogram.recordCountHistogram("EnhancedBookmarks.AllBookmarksCoun
t", | |
332 bookmarkIds.size()); | |
333 setBookmarks(null, bookmarkIds); | |
334 } | |
335 | |
336 @Override | |
337 public void onFolderStateSet(BookmarkId folder) { | |
338 setBookmarks(mDelegate.getModel().getChildIDs(folder, true, false), | |
339 mDelegate.getModel().getChildIDs(folder, false, true)); | |
340 } | |
341 | |
342 @Override | |
343 public void onFilterStateSet(EnhancedBookmarkFilter filter) { | |
344 assert filter == EnhancedBookmarkFilter.OFFLINE_PAGES; | |
345 List<BookmarkId> bookmarkIds = mDelegate.getModel().getBookmarkIDsByFilt
er(filter); | |
346 RecordHistogram.recordCountHistogram("OfflinePages.OfflinePageCount", bo
okmarkIds.size()); | |
347 setBookmarks(null, mDelegate.getModel().getBookmarkIDsByFilter(filter)); | |
348 mDelegate.getModel().getOfflinePageBridge().checkOfflinePageMetadata(); | |
349 } | |
350 | |
351 @Override | |
352 public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {} | |
353 | |
354 private static class ItemViewHolder extends RecyclerView.ViewHolder { | |
355 private ItemViewHolder(View view) { | |
356 super(view); | |
357 } | |
358 } | |
359 | |
360 private void updateHeader() { | |
361 int currentUIState = mDelegate.getCurrentState(); | |
362 if (currentUIState == EnhancedBookmarkUIState.STATE_LOADING) return; | |
363 | |
364 mPromoHeaderSection.clear(); | |
365 mOfflineStorageSection.clear(); | |
366 if (currentUIState == EnhancedBookmarkUIState.STATE_FILTER) { | |
367 if (mOfflineStorageHeader != null && mOfflineStorageHeader.shouldSho
w()) { | |
368 mOfflineStorageSection.add(null); | |
369 } | |
370 } else { | |
371 assert currentUIState == EnhancedBookmarkUIState.STATE_ALL_BOOKMARKS | |
372 || currentUIState == EnhancedBookmarkUIState.STATE_FOLDER | |
373 : "Unexpected UI state"; | |
374 if (mPromoHeaderManager.shouldShow()) { | |
375 mPromoHeaderSection.add(null); | |
376 } | |
377 } | |
378 } | |
379 | |
380 private void refreshOfflinePagesFilterView() { | |
381 if (mDelegate.getCurrentState() != EnhancedBookmarkUIState.STATE_FILTER)
return; | |
382 setBookmarks(null, | |
383 mDelegate.getModel().getBookmarkIDsByFilter(EnhancedBookmarkFilt
er.OFFLINE_PAGES)); | |
384 } | |
385 } | |
OLD | NEW |