OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.bookmarks; | 5 package org.chromium.chrome.browser.bookmarks; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.support.v7.widget.RecyclerView; | 8 import android.support.v7.widget.RecyclerView; |
9 import android.support.v7.widget.RecyclerView.ViewHolder; | 9 import android.support.v7.widget.RecyclerView.ViewHolder; |
10 import android.view.LayoutInflater; | 10 import android.view.LayoutInflater; |
11 import android.view.View; | 11 import android.view.View; |
12 import android.view.ViewGroup; | 12 import android.view.ViewGroup; |
13 | 13 |
14 import org.chromium.base.Callback; | |
15 import org.chromium.base.annotations.SuppressFBWarnings; | 14 import org.chromium.base.annotations.SuppressFBWarnings; |
16 import org.chromium.base.metrics.RecordHistogram; | 15 import org.chromium.base.metrics.RecordHistogram; |
17 import org.chromium.chrome.R; | 16 import org.chromium.chrome.R; |
18 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; | 17 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; |
19 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserve
r; | 18 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserve
r; |
20 import org.chromium.chrome.browser.bookmarks.BookmarkPromoHeader.PromoHeaderShow
ingChangeListener; | 19 import org.chromium.chrome.browser.bookmarks.BookmarkPromoHeader.PromoHeaderShow
ingChangeListener; |
21 import org.chromium.chrome.browser.offlinepages.ClientId; | |
22 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; | |
23 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.OfflinePageMod
elObserver; | |
24 import org.chromium.chrome.browser.offlinepages.OfflinePageFreeUpSpaceCallback; | |
25 import org.chromium.chrome.browser.offlinepages.OfflinePageFreeUpSpaceDialog; | |
26 import org.chromium.chrome.browser.offlinepages.OfflinePageStorageSpaceHeader; | |
27 import org.chromium.chrome.browser.offlinepages.OfflinePageStorageSpacePolicy; | |
28 import org.chromium.components.bookmarks.BookmarkId; | 20 import org.chromium.components.bookmarks.BookmarkId; |
29 | 21 |
30 import java.util.ArrayList; | 22 import java.util.ArrayList; |
31 import java.util.List; | 23 import java.util.List; |
32 | 24 |
33 /** | 25 /** |
34 * BaseAdapter for {@link BookmarkRecyclerView}. It manages bookmarks to list th
ere. | 26 * BaseAdapter for {@link BookmarkRecyclerView}. It manages bookmarks to list th
ere. |
35 */ | 27 */ |
36 class BookmarkItemsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements | 28 class BookmarkItemsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements |
37 BookmarkUIObserver, PromoHeaderShowingChangeListener { | 29 BookmarkUIObserver, PromoHeaderShowingChangeListener { |
38 private static final int PROMO_HEADER_VIEW = 0; | 30 private static final int PROMO_HEADER_VIEW = 0; |
39 private static final int FOLDER_VIEW = 1; | 31 private static final int FOLDER_VIEW = 1; |
40 private static final int DIVIDER_VIEW = 2; | 32 private static final int DIVIDER_VIEW = 2; |
41 private static final int BOOKMARK_VIEW = 3; | 33 private static final int BOOKMARK_VIEW = 3; |
42 private static final int OFFLINE_PAGES_STORAGE_VIEW = 4; | |
43 | 34 |
44 private BookmarkDelegate mDelegate; | 35 private BookmarkDelegate mDelegate; |
45 private Context mContext; | 36 private Context mContext; |
46 private BookmarkPromoHeader mPromoHeaderManager; | 37 private BookmarkPromoHeader mPromoHeaderManager; |
47 private OfflinePageStorageSpaceHeader mOfflineStorageHeader; | |
48 private OfflinePageBridge mOfflinePageBridge; | |
49 | 38 |
50 private List<List<? extends Object>> mSections; | 39 private List<List<? extends Object>> mSections; |
51 private List<Object> mPromoHeaderSection = new ArrayList<>(); | 40 private List<Object> mPromoHeaderSection = new ArrayList<>(); |
52 private List<Object> mOfflineStorageSection = new ArrayList<>(); | |
53 private List<Object> mFolderDividerSection = new ArrayList<>(); | 41 private List<Object> mFolderDividerSection = new ArrayList<>(); |
54 private List<BookmarkId> mFolderSection = new ArrayList<>(); | 42 private List<BookmarkId> mFolderSection = new ArrayList<>(); |
55 private List<Object> mBookmarkDividerSection = new ArrayList<>(); | 43 private List<Object> mBookmarkDividerSection = new ArrayList<>(); |
56 private List<BookmarkId> mBookmarkSection = new ArrayList<>(); | 44 private List<BookmarkId> mBookmarkSection = new ArrayList<>(); |
57 | 45 |
58 private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObse
rver() { | 46 private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObse
rver() { |
59 @Override | 47 @Override |
60 public void bookmarkNodeChanged(BookmarkItem node) { | 48 public void bookmarkNodeChanged(BookmarkItem node) { |
61 assert mDelegate != null; | 49 assert mDelegate != null; |
62 int position = getPositionForBookmark(node.getId()); | 50 int position = getPositionForBookmark(node.getId()); |
(...skipping 14 matching lines...) Expand all Loading... |
77 } | 65 } |
78 } | 66 } |
79 | 67 |
80 @Override | 68 @Override |
81 public void bookmarkModelChanged() { | 69 public void bookmarkModelChanged() { |
82 assert mDelegate != null; | 70 assert mDelegate != null; |
83 mDelegate.notifyStateChange(BookmarkItemsAdapter.this); | 71 mDelegate.notifyStateChange(BookmarkItemsAdapter.this); |
84 } | 72 } |
85 }; | 73 }; |
86 | 74 |
87 private OfflinePageModelObserver mOfflinePageModelObserver; | |
88 | |
89 BookmarkItemsAdapter(Context context) { | 75 BookmarkItemsAdapter(Context context) { |
90 mContext = context; | 76 mContext = context; |
91 | 77 |
92 mSections = new ArrayList<>(); | 78 mSections = new ArrayList<>(); |
93 mSections.add(mPromoHeaderSection); | 79 mSections.add(mPromoHeaderSection); |
94 mSections.add(mOfflineStorageSection); | |
95 mSections.add(mFolderDividerSection); | 80 mSections.add(mFolderDividerSection); |
96 mSections.add(mFolderSection); | 81 mSections.add(mFolderSection); |
97 mSections.add(mBookmarkDividerSection); | 82 mSections.add(mBookmarkDividerSection); |
98 mSections.add(mBookmarkSection); | 83 mSections.add(mBookmarkSection); |
99 } | 84 } |
100 | 85 |
101 BookmarkId getItem(int position) { | 86 BookmarkId getItem(int position) { |
102 return (BookmarkId) getSection(position).get(toSectionPosition(position)
); | 87 return (BookmarkId) getSection(position).get(toSectionPosition(position)
); |
103 } | 88 } |
104 | 89 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 139 |
155 // TODO(kkimlabs): Animation is disabled due to a performance issue on b
ookmark undo. | 140 // TODO(kkimlabs): Animation is disabled due to a performance issue on b
ookmark undo. |
156 // http://crbug.com/484174 | 141 // http://crbug.com/484174 |
157 notifyDataSetChanged(); | 142 notifyDataSetChanged(); |
158 } | 143 } |
159 | 144 |
160 private void updateDividerSections() { | 145 private void updateDividerSections() { |
161 mFolderDividerSection.clear(); | 146 mFolderDividerSection.clear(); |
162 mBookmarkDividerSection.clear(); | 147 mBookmarkDividerSection.clear(); |
163 | 148 |
164 boolean isHeaderPresent = | 149 boolean isHeaderPresent = !mPromoHeaderSection.isEmpty(); |
165 !mPromoHeaderSection.isEmpty() || !mOfflineStorageSection.isEmpt
y(); | |
166 | 150 |
167 if (isHeaderPresent && !mFolderSection.isEmpty()) { | 151 if (isHeaderPresent && !mFolderSection.isEmpty()) { |
168 mFolderDividerSection.add(null); | 152 mFolderDividerSection.add(null); |
169 } | 153 } |
170 if ((isHeaderPresent || !mFolderSection.isEmpty()) && !mBookmarkSection.
isEmpty()) { | 154 if ((isHeaderPresent || !mFolderSection.isEmpty()) && !mBookmarkSection.
isEmpty()) { |
171 mBookmarkDividerSection.add(null); | 155 mBookmarkDividerSection.add(null); |
172 } | 156 } |
173 } | 157 } |
174 | 158 |
175 private void removeItem(int position) { | 159 private void removeItem(int position) { |
(...skipping 13 matching lines...) Expand all Loading... |
189 } | 173 } |
190 return count; | 174 return count; |
191 } | 175 } |
192 | 176 |
193 @Override | 177 @Override |
194 public int getItemViewType(int position) { | 178 public int getItemViewType(int position) { |
195 List<?> section = getSection(position); | 179 List<?> section = getSection(position); |
196 | 180 |
197 if (section == mPromoHeaderSection) { | 181 if (section == mPromoHeaderSection) { |
198 return PROMO_HEADER_VIEW; | 182 return PROMO_HEADER_VIEW; |
199 } else if (section == mOfflineStorageSection) { | |
200 return OFFLINE_PAGES_STORAGE_VIEW; | |
201 } else if (section == mFolderDividerSection | 183 } else if (section == mFolderDividerSection |
202 || section == mBookmarkDividerSection) { | 184 || section == mBookmarkDividerSection) { |
203 return DIVIDER_VIEW; | 185 return DIVIDER_VIEW; |
204 } else if (section == mFolderSection) { | 186 } else if (section == mFolderSection) { |
205 return FOLDER_VIEW; | 187 return FOLDER_VIEW; |
206 } else if (section == mBookmarkSection) { | 188 } else if (section == mBookmarkSection) { |
207 return BOOKMARK_VIEW; | 189 return BOOKMARK_VIEW; |
208 } | 190 } |
209 | 191 |
210 assert false : "Invalid position requested"; | 192 assert false : "Invalid position requested"; |
211 return -1; | 193 return -1; |
212 } | 194 } |
213 | 195 |
214 @Override | 196 @Override |
215 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | 197 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { |
216 assert mDelegate != null; | 198 assert mDelegate != null; |
217 | 199 |
218 switch (viewType) { | 200 switch (viewType) { |
219 case PROMO_HEADER_VIEW: | 201 case PROMO_HEADER_VIEW: |
220 return mPromoHeaderManager.createHolder(parent); | 202 return mPromoHeaderManager.createHolder(parent); |
221 case OFFLINE_PAGES_STORAGE_VIEW: | |
222 return mOfflineStorageHeader.createHolder(parent); | |
223 case DIVIDER_VIEW: | 203 case DIVIDER_VIEW: |
224 return new ViewHolder(LayoutInflater.from(parent.getContext()).i
nflate( | 204 return new ViewHolder(LayoutInflater.from(parent.getContext()).i
nflate( |
225 R.layout.bookmark_divider, parent, false)) {}; | 205 R.layout.bookmark_divider, parent, false)) {}; |
226 case FOLDER_VIEW: | 206 case FOLDER_VIEW: |
227 BookmarkFolderRow folder = (BookmarkFolderRow) LayoutInflater.fr
om( | 207 BookmarkFolderRow folder = (BookmarkFolderRow) LayoutInflater.fr
om( |
228 parent.getContext()).inflate(R.layout.bookmark_folder_ro
w, parent, false); | 208 parent.getContext()).inflate(R.layout.bookmark_folder_ro
w, parent, false); |
229 folder.onBookmarkDelegateInitialized(mDelegate); | 209 folder.onBookmarkDelegateInitialized(mDelegate); |
230 return new ItemViewHolder(folder); | 210 return new ItemViewHolder(folder); |
231 case BOOKMARK_VIEW: | 211 case BOOKMARK_VIEW: |
232 BookmarkItemRow item = (BookmarkItemRow) LayoutInflater.from( | 212 BookmarkItemRow item = (BookmarkItemRow) LayoutInflater.from( |
233 parent.getContext()).inflate(R.layout.bookmark_item_row,
parent, false); | 213 parent.getContext()).inflate(R.layout.bookmark_item_row,
parent, false); |
234 item.onBookmarkDelegateInitialized(mDelegate); | 214 item.onBookmarkDelegateInitialized(mDelegate); |
235 return new ItemViewHolder(item); | 215 return new ItemViewHolder(item); |
236 default: | 216 default: |
237 assert false; | 217 assert false; |
238 return null; | 218 return null; |
239 } | 219 } |
240 } | 220 } |
241 | 221 |
242 @SuppressFBWarnings("BC_UNCONFIRMED_CAST") | 222 @SuppressFBWarnings("BC_UNCONFIRMED_CAST") |
243 @Override | 223 @Override |
244 public void onBindViewHolder(ViewHolder holder, int position) { | 224 public void onBindViewHolder(ViewHolder holder, int position) { |
245 BookmarkId id = getItem(position); | 225 BookmarkId id = getItem(position); |
246 | 226 |
247 switch (getItemViewType(position)) { | 227 switch (getItemViewType(position)) { |
248 case PROMO_HEADER_VIEW: | 228 case PROMO_HEADER_VIEW: |
249 case OFFLINE_PAGES_STORAGE_VIEW: | |
250 case DIVIDER_VIEW: | 229 case DIVIDER_VIEW: |
251 break; | 230 break; |
252 case FOLDER_VIEW: | 231 case FOLDER_VIEW: |
253 ((BookmarkRow) holder.itemView).setBookmarkId(id); | 232 ((BookmarkRow) holder.itemView).setBookmarkId(id); |
254 break; | 233 break; |
255 case BOOKMARK_VIEW: | 234 case BOOKMARK_VIEW: |
256 ((BookmarkRow) holder.itemView).setBookmarkId(id); | 235 ((BookmarkRow) holder.itemView).setBookmarkId(id); |
257 break; | 236 break; |
258 default: | 237 default: |
259 assert false : "View type not supported!"; | 238 assert false : "View type not supported!"; |
(...skipping 16 matching lines...) Expand all Loading... |
276 } | 255 } |
277 | 256 |
278 // BookmarkUIObserver implementations. | 257 // BookmarkUIObserver implementations. |
279 | 258 |
280 @Override | 259 @Override |
281 public void onBookmarkDelegateInitialized(BookmarkDelegate delegate) { | 260 public void onBookmarkDelegateInitialized(BookmarkDelegate delegate) { |
282 mDelegate = delegate; | 261 mDelegate = delegate; |
283 mDelegate.addUIObserver(this); | 262 mDelegate.addUIObserver(this); |
284 mDelegate.getModel().addObserver(mBookmarkModelObserver); | 263 mDelegate.getModel().addObserver(mBookmarkModelObserver); |
285 mPromoHeaderManager = new BookmarkPromoHeader(mContext, this); | 264 mPromoHeaderManager = new BookmarkPromoHeader(mContext, this); |
286 mOfflinePageBridge = mDelegate.getModel().getOfflinePageBridge(); | |
287 if (mOfflinePageBridge != null) { | |
288 mOfflinePageModelObserver = new OfflinePageModelObserver() { | |
289 @Override | |
290 public void offlinePageModelChanged() { | |
291 mDelegate.notifyStateChange(BookmarkItemsAdapter.this); | |
292 } | |
293 | |
294 @Override | |
295 public void offlinePageDeleted(long offlineId, ClientId clientId
) { | |
296 if (mDelegate.getCurrentState() == BookmarkUIState.STATE_FIL
TER) { | |
297 BookmarkId id = BookmarkModel.getBookmarkIdForOfflineCli
entId(clientId); | |
298 int deletedPosition = getPositionForBookmark(id); | |
299 if (deletedPosition >= 0) { | |
300 removeItem(deletedPosition); | |
301 } | |
302 } | |
303 } | |
304 }; | |
305 mOfflinePageBridge.addObserver(mOfflinePageModelObserver); | |
306 | |
307 OfflinePageStorageSpacePolicy.create( | |
308 mOfflinePageBridge, new Callback<OfflinePageStorageSpacePoli
cy>() { | |
309 @Override | |
310 public void onResult(OfflinePageStorageSpacePolicy polic
y) { | |
311 setOfflineStorageHeader(policy); | |
312 } | |
313 }); | |
314 } | |
315 } | 265 } |
316 | 266 |
317 @Override | 267 @Override |
318 public void onDestroy() { | 268 public void onDestroy() { |
319 mDelegate.removeUIObserver(this); | 269 mDelegate.removeUIObserver(this); |
320 mDelegate.getModel().removeObserver(mBookmarkModelObserver); | 270 mDelegate.getModel().removeObserver(mBookmarkModelObserver); |
321 mDelegate = null; | 271 mDelegate = null; |
322 | 272 |
323 mPromoHeaderManager.destroy(); | 273 mPromoHeaderManager.destroy(); |
324 | |
325 if (mOfflinePageBridge != null) { | |
326 mOfflinePageBridge.removeObserver(mOfflinePageModelObserver); | |
327 mOfflinePageBridge = null; | |
328 } | |
329 | |
330 if (mOfflineStorageHeader != null) { | |
331 mOfflineStorageHeader.destroy(); | |
332 } | |
333 } | 274 } |
334 | 275 |
335 @Override | 276 @Override |
336 public void onAllBookmarksStateSet() { | 277 public void onAllBookmarksStateSet() { |
337 assert mDelegate != null; | 278 assert mDelegate != null; |
338 List<BookmarkId> bookmarkIds = | 279 List<BookmarkId> bookmarkIds = |
339 mDelegate.getModel().getAllBookmarkIDsOrderedByCreationDate(); | 280 mDelegate.getModel().getAllBookmarkIDsOrderedByCreationDate(); |
340 RecordHistogram.recordCountHistogram("EnhancedBookmarks.AllBookmarksCoun
t", | 281 RecordHistogram.recordCountHistogram("EnhancedBookmarks.AllBookmarksCoun
t", |
341 bookmarkIds.size()); | 282 bookmarkIds.size()); |
342 setBookmarks(null, bookmarkIds); | 283 setBookmarks(null, bookmarkIds); |
343 } | 284 } |
344 | 285 |
345 @Override | 286 @Override |
346 public void onFolderStateSet(BookmarkId folder) { | 287 public void onFolderStateSet(BookmarkId folder) { |
347 assert mDelegate != null; | 288 assert mDelegate != null; |
348 setBookmarks(mDelegate.getModel().getChildIDs(folder, true, false), | 289 setBookmarks(mDelegate.getModel().getChildIDs(folder, true, false), |
349 mDelegate.getModel().getChildIDs(folder, false, true)); | 290 mDelegate.getModel().getChildIDs(folder, false, true)); |
350 } | 291 } |
351 | 292 |
352 @Override | 293 @Override |
353 public void onFilterStateSet(BookmarkFilter filter) { | |
354 assert filter == BookmarkFilter.OFFLINE_PAGES; | |
355 assert mDelegate != null; | |
356 assert mOfflinePageBridge != null; | |
357 | |
358 setBookmarks(null, new ArrayList<BookmarkId>()); | |
359 mOfflinePageBridge.checkOfflinePageMetadata(); | |
360 BookmarkModel bookmarkModel = mDelegate.getModel(); | |
361 bookmarkModel.getBookmarkIDsByFilter( | |
362 BookmarkFilter.OFFLINE_PAGES, new Callback<List<BookmarkId>>() { | |
363 @Override | |
364 public void onResult(List<BookmarkId> bookmarkIds) { | |
365 if (mDelegate == null) return; | |
366 RecordHistogram.recordCountHistogram( | |
367 "OfflinePages.OfflinePageCount", bookmarkIds.siz
e()); | |
368 | |
369 setBookmarks(null, bookmarkIds); | |
370 } | |
371 }); | |
372 } | |
373 | |
374 @Override | |
375 public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {} | 294 public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {} |
376 | 295 |
377 private static class ItemViewHolder extends RecyclerView.ViewHolder { | 296 private static class ItemViewHolder extends RecyclerView.ViewHolder { |
378 private ItemViewHolder(View view) { | 297 private ItemViewHolder(View view) { |
379 super(view); | 298 super(view); |
380 } | 299 } |
381 } | 300 } |
382 | 301 |
383 private void setOfflineStorageHeader(OfflinePageStorageSpacePolicy policy) { | |
384 if (mOfflinePageBridge == null) return; | |
385 | |
386 mOfflineStorageHeader = new OfflinePageStorageSpaceHeader( | |
387 mContext, mOfflinePageBridge, policy, new OfflinePageFreeUpSpace
Callback() { | |
388 @Override | |
389 public void onFreeUpSpaceDone() { | |
390 if (mDelegate == null) return; | |
391 | |
392 refreshOfflinePagesFilterView(); | |
393 mDelegate.getSnackbarManager().showSnackbar( | |
394 OfflinePageFreeUpSpaceDialog.createStorageCleare
dSnackbar( | |
395 mContext)); | |
396 } | |
397 | |
398 @Override | |
399 public void onFreeUpSpaceCancelled() { | |
400 // No need to refresh, as result outcome should | |
401 // be the same here. | |
402 } | |
403 }); | |
404 | |
405 updateHeader(); | |
406 } | |
407 | |
408 private void updateHeader() { | 302 private void updateHeader() { |
409 if (mDelegate == null) return; | 303 if (mDelegate == null) return; |
410 | 304 |
411 int currentUIState = mDelegate.getCurrentState(); | 305 int currentUIState = mDelegate.getCurrentState(); |
412 if (currentUIState == BookmarkUIState.STATE_LOADING) return; | 306 if (currentUIState == BookmarkUIState.STATE_LOADING) return; |
413 | 307 |
414 mPromoHeaderSection.clear(); | 308 mPromoHeaderSection.clear(); |
415 mOfflineStorageSection.clear(); | 309 assert currentUIState == BookmarkUIState.STATE_ALL_BOOKMARKS |
416 if (currentUIState == BookmarkUIState.STATE_FILTER) { | 310 || currentUIState == BookmarkUIState.STATE_FOLDER : "Unexpected
UI state"; |
417 if (mOfflineStorageHeader != null && mOfflineStorageHeader.shouldSho
w()) { | 311 if (mPromoHeaderManager.shouldShow()) { |
418 mOfflineStorageSection.add(null); | 312 mPromoHeaderSection.add(null); |
419 } | |
420 } else { | |
421 assert currentUIState == BookmarkUIState.STATE_ALL_BOOKMARKS | |
422 || currentUIState == BookmarkUIState.STATE_FOLDER | |
423 : "Unexpected UI state"; | |
424 if (mPromoHeaderManager.shouldShow()) { | |
425 mPromoHeaderSection.add(null); | |
426 } | |
427 } | 313 } |
428 } | 314 } |
429 | |
430 private void refreshOfflinePagesFilterView() { | |
431 if (mDelegate == null || mDelegate.getCurrentState() != BookmarkUIState.
STATE_FILTER) { | |
432 return; | |
433 } | |
434 setBookmarks(null, new ArrayList<BookmarkId>()); | |
435 mDelegate.getModel().getBookmarkIDsByFilter( | |
436 BookmarkFilter.OFFLINE_PAGES, new Callback<List<BookmarkId>>() { | |
437 @Override | |
438 public void onResult(List<BookmarkId> bookmarkIds) { | |
439 if (mDelegate == null) return; | |
440 setBookmarks(null, bookmarkIds); | |
441 } | |
442 }); | |
443 } | |
444 } | 315 } |
OLD | NEW |