Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java

Issue 2758753003: 📰 Refresh the tiles when a removal is undone (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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.suggestions; 5 package org.chromium.chrome.browser.suggestions;
6 6
7 import android.content.Context; 7 import android.content.Context;
8 import android.content.res.Resources; 8 import android.content.res.Resources;
9 import android.graphics.Bitmap; 9 import android.graphics.Bitmap;
10 import android.graphics.BitmapFactory; 10 import android.graphics.BitmapFactory;
11 import android.graphics.Color; 11 import android.graphics.Color;
12 import android.graphics.drawable.BitmapDrawable; 12 import android.graphics.drawable.BitmapDrawable;
13 import android.support.annotation.Nullable; 13 import android.support.annotation.Nullable;
14 import android.support.v4.graphics.drawable.RoundedBitmapDrawable; 14 import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
15 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; 15 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
16 import android.view.ContextMenu; 16 import android.view.ContextMenu;
17 import android.view.ContextMenu.ContextMenuInfo; 17 import android.view.ContextMenu.ContextMenuInfo;
18 import android.view.LayoutInflater; 18 import android.view.LayoutInflater;
19 import android.view.View; 19 import android.view.View;
20 import android.view.View.OnClickListener; 20 import android.view.View.OnClickListener;
21 import android.view.View.OnCreateContextMenuListener; 21 import android.view.View.OnCreateContextMenuListener;
22 import android.view.ViewGroup; 22 import android.view.ViewGroup;
23 23
24 import org.chromium.base.ApiCompatibilityUtils; 24 import org.chromium.base.ApiCompatibilityUtils;
25 import org.chromium.base.Callback;
25 import org.chromium.base.Log; 26 import org.chromium.base.Log;
26 import org.chromium.base.VisibleForTesting; 27 import org.chromium.base.VisibleForTesting;
27 import org.chromium.chrome.R; 28 import org.chromium.chrome.R;
28 import org.chromium.chrome.browser.ChromeFeatureList; 29 import org.chromium.chrome.browser.ChromeFeatureList;
29 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; 30 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback;
30 import org.chromium.chrome.browser.ntp.ContextMenuManager; 31 import org.chromium.chrome.browser.ntp.ContextMenuManager;
31 import org.chromium.chrome.browser.ntp.ContextMenuManager.ContextMenuItemId; 32 import org.chromium.chrome.browser.ntp.ContextMenuManager.ContextMenuItemId;
32 import org.chromium.chrome.browser.ntp.MostVisitedTileType; 33 import org.chromium.chrome.browser.ntp.MostVisitedTileType;
33 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; 34 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
34 import org.chromium.chrome.browser.widget.RoundedIconGenerator; 35 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
35 import org.chromium.ui.mojom.WindowOpenDisposition; 36 import org.chromium.ui.mojom.WindowOpenDisposition;
36 37
37 import java.util.Arrays; 38 import java.util.Arrays;
38 import java.util.HashMap; 39 import java.util.HashMap;
39 import java.util.HashSet; 40 import java.util.HashSet;
40 import java.util.Map; 41 import java.util.Map;
41 import java.util.Set; 42 import java.util.Set;
42 43
43 /** 44 /**
44 * The model and controller for a group of site suggestion tiles. 45 * The model and controller for a group of site suggestion tiles.
45 */ 46 */
46 public class TileGroup implements MostVisitedSites.Observer { 47 public class TileGroup implements MostVisitedSites.Observer {
47 /** 48 /**
48 * Performs work in other parts of the system that the {@link TileGroup} sho uld not know about. 49 * Performs work in other parts of the system that the {@link TileGroup} sho uld not know about.
49 */ 50 */
50 public interface Delegate { 51 public interface Delegate {
51 void removeMostVisitedItem(Tile tile); 52 /**
53 * @param tile The tile corresponding to the most visited item to remove .
54 * @param removalUndoneCallback The callback to invoke if the removal is reverted.
55 */
56 void removeMostVisitedItem(Tile tile, @Nullable Callback<String> removal UndoneCallback);
Michael van Ouwerkerk 2017/03/17 15:53:07 Why is the callback nullable? Please document what
dgn 2017/03/17 16:13:45 I intended the callback to be optional but there i
52 57
53 void openMostVisitedItem(int windowDisposition, Tile tile); 58 void openMostVisitedItem(int windowDisposition, Tile tile);
54 59
55 /** 60 /**
56 * Gets the list of most visited sites. 61 * Gets the list of most visited sites.
57 * @param observer The observer to be notified with the list of sites. 62 * @param observer The observer to be notified with the list of sites.
58 * @param maxResults The maximum number of sites to retrieve. 63 * @param maxResults The maximum number of sites to retrieve.
59 */ 64 */
60 void setMostVisitedSitesObserver(MostVisitedSites.Observer observer, int maxResults); 65 void setMostVisitedSitesObserver(MostVisitedSites.Observer observer, int maxResults);
61 66
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 @Nullable 151 @Nullable
147 private Tile[] mPendingTileData; 152 private Tile[] mPendingTileData;
148 153
149 /** 154 /**
150 * URL of the most recently removed tile. Used to identify when a tile remov al is confirmed by 155 * URL of the most recently removed tile. Used to identify when a tile remov al is confirmed by
151 * the tile backend. 156 * the tile backend.
152 */ 157 */
153 @Nullable 158 @Nullable
154 private String mPendingRemovalUrl; 159 private String mPendingRemovalUrl;
155 160
161 /**
162 * URL of the most recently added tile. Used to identify when a given tile's insertion is
163 * confirmed by the tile backend. This is relevant when a previously existin g tile is removed,
164 * then the user undoes the action and wants that tile back.
165 */
166 @Nullable
167 private String mPendingInsertionUrl;
168
156 private boolean mHasReceivedData; 169 private boolean mHasReceivedData;
157 170
158 /** 171 /**
159 * @param context Used for initialisation and resolving resources. 172 * @param context Used for initialisation and resolving resources.
160 * @param uiDelegate Delegate used to interact with the rest of the system. 173 * @param uiDelegate Delegate used to interact with the rest of the system.
161 * @param contextMenuManager Used to handle context menu invocations on the tiles. 174 * @param contextMenuManager Used to handle context menu invocations on the tiles.
162 * @param tileGroupDelegate Used for interactions with the Most Visited back end. 175 * @param tileGroupDelegate Used for interactions with the Most Visited back end.
163 * @param observer Will be notified of changes to the tile data. 176 * @param observer Will be notified of changes to the tile data.
164 * @param titleLines The number of text lines to use for each tile title. 177 * @param titleLines The number of text lines to use for each tile title.
165 */ 178 */
(...skipping 23 matching lines...) Expand all
189 mUiDelegate.addDestructionObserver(mOfflineModelObserver); 202 mUiDelegate.addDestructionObserver(mOfflineModelObserver);
190 } else { 203 } else {
191 mOfflineModelObserver = null; 204 mOfflineModelObserver = null;
192 } 205 }
193 } 206 }
194 207
195 @Override 208 @Override
196 public void onMostVisitedURLsAvailable(final String[] titles, final String[] urls, 209 public void onMostVisitedURLsAvailable(final String[] titles, final String[] urls,
197 final String[] whitelistIconPaths, final int[] sources) { 210 final String[] whitelistIconPaths, final int[] sources) {
198 boolean removalCompleted = mPendingRemovalUrl != null; 211 boolean removalCompleted = mPendingRemovalUrl != null;
212 boolean insertionCompleted = mPendingInsertionUrl == null;
213
199 Set<String> addedUrls = new HashSet<>(); 214 Set<String> addedUrls = new HashSet<>();
200 mPendingTileData = new Tile[titles.length]; 215 mPendingTileData = new Tile[titles.length];
201 for (int i = 0; i < titles.length; i++) { 216 for (int i = 0; i < titles.length; i++) {
202 assert urls[i] != null; // We assume everywhere that the url is not null. 217 assert urls[i] != null; // We assume everywhere that the url is not null.
203 218
204 // TODO(dgn): Add UMA to track the cause of https://crbug.com/690926 . Checking this 219 // TODO(dgn): Add UMA to track the cause of https://crbug.com/690926 . Checking this
205 // should not even be necessary as the backend is supposed to send n on dupes URLs. 220 // should not even be necessary as the backend is supposed to send n on dupes URLs.
206 if (addedUrls.contains(urls[i])) { 221 if (addedUrls.contains(urls[i])) {
207 assert false : "Incoming NTP Tiles are not unique. Dupe on " + u rls[i]; 222 assert false : "Incoming NTP Tiles are not unique. Dupe on " + u rls[i];
208 continue; 223 continue;
209 } 224 }
210 225
211 mPendingTileData[i] = 226 mPendingTileData[i] =
212 new Tile(titles[i], urls[i], whitelistIconPaths[i], i, sourc es[i]); 227 new Tile(titles[i], urls[i], whitelistIconPaths[i], i, sourc es[i]);
213 addedUrls.add(urls[i]); 228 addedUrls.add(urls[i]);
214 229
215 if (urls[i].equals(mPendingRemovalUrl)) removalCompleted = false; 230 if (urls[i].equals(mPendingRemovalUrl)) removalCompleted = false;
231 if (urls[i].equals(mPendingInsertionUrl)) insertionCompleted = true;
216 } 232 }
217 233
218 if (removalCompleted) mPendingRemovalUrl = null; 234 boolean expectedChangeCompleted = false;
219 if (!mHasReceivedData || !mUiDelegate.isVisible() || removalCompleted) l oadTiles(); 235 if (mPendingRemovalUrl != null && removalCompleted) {
236 mPendingRemovalUrl = null;
237 expectedChangeCompleted = true;
238 }
239 if (mPendingInsertionUrl != null && insertionCompleted) {
240 mPendingInsertionUrl = null;
241 expectedChangeCompleted = true;
242 }
243
244 if (!mHasReceivedData || !mUiDelegate.isVisible() || expectedChangeCompl eted) loadTiles();
220 } 245 }
221 246
222 @Override 247 @Override
223 public void onIconMadeAvailable(String siteUrl) { 248 public void onIconMadeAvailable(String siteUrl) {
224 Tile tile = getTile(siteUrl); 249 Tile tile = getTile(siteUrl);
225 if (tile == null) return; // The tile might have been removed. 250 if (tile == null) return; // The tile might have been removed.
226 251
227 LargeIconCallback iconCallback = 252 LargeIconCallback iconCallback =
228 new LargeIconCallbackImpl(siteUrl, /* trackLoadTask = */ false); 253 new LargeIconCallbackImpl(siteUrl, /* trackLoadTask = */ false);
229 mUiDelegate.getLargeIconForUrl(siteUrl, mMinIconSize, iconCallback); 254 mUiDelegate.getLargeIconForUrl(siteUrl, mMinIconSize, iconCallback);
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 } 454 }
430 455
431 @Override 456 @Override
432 public void removeItem() { 457 public void removeItem() {
433 Tile tile = getTile(mUrl); 458 Tile tile = getTile(mUrl);
434 if (tile == null) return; 459 if (tile == null) return;
435 460
436 // Note: This does not track all the removals, but will track the mo st recent one. If 461 // Note: This does not track all the removals, but will track the mo st recent one. If
437 // that removal is committed, it's good enough for change detection. 462 // that removal is committed, it's good enough for change detection.
438 mPendingRemovalUrl = mUrl; 463 mPendingRemovalUrl = mUrl;
439 mTileGroupDelegate.removeMostVisitedItem(tile); 464 mTileGroupDelegate.removeMostVisitedItem(tile, new RemovalUndoneCall back());
440 } 465 }
441 466
442 @Override 467 @Override
443 public String getUrl() { 468 public String getUrl() {
444 return mUrl; 469 return mUrl;
445 } 470 }
446 471
447 @Override 472 @Override
448 public boolean isItemSupported(@ContextMenuItemId int menuItemId) { 473 public boolean isItemSupported(@ContextMenuItemId int menuItemId) {
449 return true; 474 return true;
450 } 475 }
451 476
452 @Override 477 @Override
453 public void onContextMenuCreated() {} 478 public void onContextMenuCreated() {}
454 479
455 @Override 480 @Override
456 public void onCreateContextMenu( 481 public void onCreateContextMenu(
457 ContextMenu contextMenu, View view, ContextMenuInfo contextMenuI nfo) { 482 ContextMenu contextMenu, View view, ContextMenuInfo contextMenuI nfo) {
458 mContextMenuManager.createContextMenu(contextMenu, view, this); 483 mContextMenuManager.createContextMenu(contextMenu, view, this);
459 } 484 }
460 } 485 }
461 486
487 private class RemovalUndoneCallback extends Callback<String> {
488 @Override
489 public void onResult(String result) {
490 mPendingInsertionUrl = result;
491 }
492 }
493
462 private class OfflineModelObserver extends SuggestionsOfflineModelObserver<T ile> { 494 private class OfflineModelObserver extends SuggestionsOfflineModelObserver<T ile> {
463 public OfflineModelObserver(OfflinePageBridge bridge) { 495 public OfflineModelObserver(OfflinePageBridge bridge) {
464 super(bridge); 496 super(bridge);
465 } 497 }
466 498
467 @Override 499 @Override
468 public void onSuggestionOfflineIdChanged(Tile suggestion, @Nullable Long id) { 500 public void onSuggestionOfflineIdChanged(Tile suggestion, @Nullable Long id) {
469 // Retrieve a tile from the internal data, to make sure we don't upd ate a stale object. 501 // Retrieve a tile from the internal data, to make sure we don't upd ate a stale object.
470 Tile tile = getTile(suggestion.getUrl()); 502 Tile tile = getTile(suggestion.getUrl());
471 if (tile == null) return; 503 if (tile == null) return;
472 504
473 boolean oldOfflineAvailable = tile.isOfflineAvailable(); 505 boolean oldOfflineAvailable = tile.isOfflineAvailable();
474 tile.setOfflinePageOfflineId(id); 506 tile.setOfflinePageOfflineId(id);
475 507
476 // Only notify to update the view if there will be a visible change. 508 // Only notify to update the view if there will be a visible change.
477 if (oldOfflineAvailable == tile.isOfflineAvailable()) return; 509 if (oldOfflineAvailable == tile.isOfflineAvailable()) return;
478 mObserver.onTileOfflineBadgeVisibilityChanged(tile); 510 mObserver.onTileOfflineBadgeVisibilityChanged(tile);
479 } 511 }
480 512
481 @Override 513 @Override
482 public Iterable<Tile> getOfflinableSuggestions() { 514 public Iterable<Tile> getOfflinableSuggestions() {
483 return Arrays.asList(mTiles); 515 return Arrays.asList(mTiles);
484 } 516 }
485 } 517 }
486 } 518 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroupDelegateImpl.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698