Bug 1270535 - Add "undo" action when bookmark is edited or removed; r=petru

Differential Revision: https://phabricator.services.mozilla.com/D32308

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrei Teslovan 2019-06-06 08:50:30 +00:00
parent 834812f141
commit fdbd67ec21
14 changed files with 304 additions and 14 deletions

View File

@ -72,9 +72,11 @@ import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
import org.mozilla.gecko.adjust.AdjustBrowserAppDelegate; import org.mozilla.gecko.adjust.AdjustBrowserAppDelegate;
import org.mozilla.gecko.animation.PropertyAnimator; import org.mozilla.gecko.animation.PropertyAnimator;
import org.mozilla.gecko.annotation.RobocopTarget; import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.bookmarks.EditBookmarkCallback;
import org.mozilla.gecko.bookmarks.BookmarkEditFragment; import org.mozilla.gecko.bookmarks.BookmarkEditFragment;
import org.mozilla.gecko.bookmarks.BookmarkUtils; import org.mozilla.gecko.bookmarks.BookmarkUtils;
import org.mozilla.gecko.bookmarks.EditBookmarkTask; import org.mozilla.gecko.bookmarks.EditBookmarkTask;
import org.mozilla.gecko.bookmarks.UndoEditBookmarkTask;
import org.mozilla.gecko.cleanup.FileCleanupController; import org.mozilla.gecko.cleanup.FileCleanupController;
import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.db.BrowserDB;
@ -94,12 +96,14 @@ import org.mozilla.gecko.home.HomeBanner;
import org.mozilla.gecko.home.HomeConfig; import org.mozilla.gecko.home.HomeConfig;
import org.mozilla.gecko.home.HomeConfig.PanelType; import org.mozilla.gecko.home.HomeConfig.PanelType;
import org.mozilla.gecko.home.HomeConfigPrefsBackend; import org.mozilla.gecko.home.HomeConfigPrefsBackend;
import org.mozilla.gecko.home.HomeContextMenuInfo;
import org.mozilla.gecko.home.HomeFragment; import org.mozilla.gecko.home.HomeFragment;
import org.mozilla.gecko.home.HomePager.OnUrlOpenInBackgroundListener; import org.mozilla.gecko.home.HomePager.OnUrlOpenInBackgroundListener;
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener; import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
import org.mozilla.gecko.home.HomePanelsManager; import org.mozilla.gecko.home.HomePanelsManager;
import org.mozilla.gecko.home.HomeScreen; import org.mozilla.gecko.home.HomeScreen;
import org.mozilla.gecko.home.SearchEngine; import org.mozilla.gecko.home.SearchEngine;
import org.mozilla.gecko.home.UndoRemoveBookmarkTask;
import org.mozilla.gecko.icons.Icons; import org.mozilla.gecko.icons.Icons;
import org.mozilla.gecko.icons.IconsHelper; import org.mozilla.gecko.icons.IconsHelper;
import org.mozilla.gecko.icons.decoders.FaviconDecoder; import org.mozilla.gecko.icons.decoders.FaviconDecoder;
@ -203,7 +207,8 @@ public class BrowserApp extends GeckoApp
PropertyAnimator.PropertyAnimationListener, PropertyAnimator.PropertyAnimationListener,
TabsPanel.TabsLayoutChangeListener, TabsPanel.TabsLayoutChangeListener,
View.OnKeyListener, View.OnKeyListener,
OnboardingHelper.OnboardingListener { OnboardingHelper.OnboardingListener,
EditBookmarkCallback {
private static final String LOGTAG = "GeckoBrowserApp"; private static final String LOGTAG = "GeckoBrowserApp";
private static final int TABS_ANIMATION_DURATION = 450; private static final int TABS_ANIMATION_DURATION = 450;
@ -811,10 +816,18 @@ public class BrowserApp extends GeckoApp
mSearchEngineManager = new SearchEngineManager(this, distribution); mSearchEngineManager = new SearchEngineManager(this, distribution);
// Init suggested sites engine in BrowserDB. // Init suggested sites engine in BrowserDB.
final SuggestedSites suggestedSites = new SuggestedSites(appContext, distribution);
final BrowserDB db = BrowserDB.from(profile); final BrowserDB db = BrowserDB.from(profile);
final SuggestedSites suggestedSites = new SuggestedSites(appContext, distribution);
db.setSuggestedSites(suggestedSites); db.setSuggestedSites(suggestedSites);
// Remove bookmarks that were marked as soft delete
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
db.removeSoftDeleteBookmarks(getContentResolver());
}
});
mSharedPreferencesHelper = new SharedPreferencesHelper(appContext); mSharedPreferencesHelper = new SharedPreferencesHelper(appContext);
mReadingListHelper = new ReadingListHelper(appContext, profile); mReadingListHelper = new ReadingListHelper(appContext, profile);
mAccountsHelper = new AccountsHelper(appContext, profile); mAccountsHelper = new AccountsHelper(appContext, profile);
@ -4177,7 +4190,7 @@ public class BrowserApp extends GeckoApp
@Override @Override
public void onEditBookmark(@NonNull Bundle bundle) { public void onEditBookmark(@NonNull Bundle bundle) {
new EditBookmarkTask(this, bundle).execute(); new EditBookmarkTask(this, bundle, this).execute();
} }
@Override @Override
@ -4236,4 +4249,14 @@ public class BrowserApp extends GeckoApp
private boolean isShutDownOrAbort() { private boolean isShutDownOrAbort() {
return mIsAbortingAppLaunch || mShutdownOnDestroy; return mIsAbortingAppLaunch || mShutdownOnDestroy;
} }
@Override
public void onUndoEditBookmark(Bundle bundle) {
new UndoEditBookmarkTask(this, bundle).execute();
}
@Override
public void onUndoRemoveBookmark(HomeContextMenuInfo info, int position) {
new UndoRemoveBookmarkTask(this, info, position).execute();
}
} }

View File

@ -146,6 +146,9 @@ public class BookmarkEditFragment extends DialogFragment implements SelectFolder
bundle.putString(Bookmarks.TITLE, newTitle); bundle.putString(Bookmarks.TITLE, newTitle);
bundle.putString(Bookmarks.URL, newUrl); bundle.putString(Bookmarks.URL, newUrl);
bundle.putString(Bookmarks.KEYWORD, newKeyword); bundle.putString(Bookmarks.KEYWORD, newKeyword);
bundle.putString(Bookmarks.OLD_TITLE, bookmark.originalTitle);
bundle.putString(Bookmarks.OLD_URL, bookmark.originalUrl);
bundle.putString(Bookmarks.OLD_KEYWORD, bookmark.originalKeyword);
if (bookmark.parentId != bookmark.originalParentId) { if (bookmark.parentId != bookmark.originalParentId) {
bundle.putLong(Bookmarks.PARENT, bookmark.parentId); bundle.putLong(Bookmarks.PARENT, bookmark.parentId);
bundle.putLong(BrowserContract.PARAM_OLD_BOOKMARK_PARENT, bookmark.originalParentId); bundle.putLong(BrowserContract.PARAM_OLD_BOOKMARK_PARENT, bookmark.originalParentId);

View File

@ -0,0 +1,24 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.bookmarks;
import android.os.Bundle;
import org.mozilla.gecko.home.HomeContextMenuInfo;
public interface EditBookmarkCallback {
/**
* A callback method to tell caller that undo action after editing a bookmark has been pressed.
* Caller takes charge for the change(e.g. update database).
*/
void onUndoEditBookmark(Bundle bundle);
/**
* A callback method to tell caller that undo action after deleting a bookmark has been pressed.
* Caller takes charge for the change(e.g. update database).
*/
void onUndoRemoveBookmark(HomeContextMenuInfo info, int position);
}

View File

@ -10,6 +10,7 @@ import android.content.ContentResolver;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.view.View;
import org.mozilla.gecko.R; import org.mozilla.gecko.R;
import org.mozilla.gecko.SnackbarBuilder; import org.mozilla.gecko.SnackbarBuilder;
@ -17,6 +18,7 @@ import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract; import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UIAsyncTask; import org.mozilla.gecko.util.UIAsyncTask;
@ -28,13 +30,16 @@ public class EditBookmarkTask extends UIAsyncTask.WithoutParams<Integer> {
private final ContentResolver contentResolver; private final ContentResolver contentResolver;
private final Bundle bundle; private final Bundle bundle;
public EditBookmarkTask(Activity activity, @NonNull Bundle bundle) { private EditBookmarkCallback editBookmarkCallback;
public EditBookmarkTask(Activity activity, @NonNull Bundle bundle, EditBookmarkCallback editBookmarkCallback) {
super(ThreadUtils.getBackgroundHandler()); super(ThreadUtils.getBackgroundHandler());
this.activityWeakReference = new WeakReference<>(activity); this.activityWeakReference = new WeakReference<>(activity);
this.db = BrowserDB.from(activity); this.db = BrowserDB.from(activity);
this.contentResolver = activity.getContentResolver(); this.contentResolver = activity.getContentResolver();
this.bundle = bundle; this.bundle = bundle;
this.editBookmarkCallback = editBookmarkCallback;
} }
@Override @Override
@ -85,6 +90,13 @@ public class EditBookmarkTask extends UIAsyncTask.WithoutParams<Integer> {
} }
SnackbarBuilder.builder(activity) SnackbarBuilder.builder(activity)
.message(messageResId) .message(messageResId)
.callback(new SnackbarBuilder.SnackbarCallback() {
@Override
public void onClick(View v) {
editBookmarkCallback.onUndoEditBookmark(bundle);
}
})
.action(R.string.bookmark_edit_undo)
.duration(Snackbar.LENGTH_LONG) .duration(Snackbar.LENGTH_LONG)
.buildAndShow(); .buildAndShow();
} }

View File

@ -0,0 +1,92 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.bookmarks;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SnackbarBuilder;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UIAsyncTask;
import java.lang.ref.WeakReference;
public class UndoEditBookmarkTask extends UIAsyncTask.WithoutParams<Integer> {
private final WeakReference<Activity> activityWeakReference;
private final BrowserDB db;
private final ContentResolver contentResolver;
private final Bundle bundle;
public UndoEditBookmarkTask(Activity activity, @NonNull Bundle bundle) {
super(ThreadUtils.getBackgroundHandler());
this.activityWeakReference = new WeakReference<>(activity);
this.db = BrowserDB.from(activity);
this.contentResolver = activity.getContentResolver();
this.bundle = bundle;
}
@Override
public Integer doInBackground() {
final long bookmarkId = bundle.getLong(BrowserContract.Bookmarks._ID);
final String url = bundle.getString(BrowserContract.Bookmarks.OLD_URL);
final String title = bundle.getString(BrowserContract.Bookmarks.OLD_TITLE);
final String keyword = bundle.getString(BrowserContract.Bookmarks.OLD_KEYWORD);
final int type = bundle.getInt(BrowserContract.Bookmarks.TYPE);
boolean parentChanged = false;
if (bundle.containsKey(BrowserContract.Bookmarks.PARENT) &&
bundle.containsKey(BrowserContract.PARAM_OLD_BOOKMARK_PARENT)) {
final long newParentId = bundle.getLong(BrowserContract.Bookmarks.PARENT);
final long oldParentId = bundle.getLong(BrowserContract.PARAM_OLD_BOOKMARK_PARENT);
db.updateBookmark(contentResolver, bookmarkId, url, title, keyword, oldParentId, newParentId);
parentChanged = true;
} else {
db.updateBookmark(contentResolver, bookmarkId, url, title, keyword);
}
String extras;
if (type == BrowserContract.Bookmarks.TYPE_FOLDER) {
extras = "bookmark_folder";
} else {
extras = "bookmark";
}
if (parentChanged) {
extras += "_parent_changed";
}
Telemetry.sendUIEvent(TelemetryContract.Event.EDIT, TelemetryContract.Method.DIALOG, extras);
return type;
}
@Override
public void onPostExecute(Integer type) {
final Activity activity = activityWeakReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
final int messageResId;
if (type == BrowserContract.Bookmarks.TYPE_FOLDER) {
messageResId = R.string.bookmark_folder_updated;
} else {
messageResId = R.string.bookmark_updated;
}
SnackbarBuilder.builder(activity)
.message(messageResId)
.duration(Snackbar.LENGTH_LONG)
.buildAndShow();
}
}

View File

@ -311,6 +311,11 @@ public class BrowserContract {
public static final String ANNOTATION_KEY = "annotation_key"; public static final String ANNOTATION_KEY = "annotation_key";
public static final String ANNOTATION_VALUE = "annotation_value"; public static final String ANNOTATION_VALUE = "annotation_value";
public static final String OLD_TITLE = "old_title";
public static final String OLD_URL = "old_url";
public static final String OLD_KEYWORD = "old_keyword";
} }
@RobocopTarget @RobocopTarget

View File

@ -113,6 +113,8 @@ public abstract class BrowserDB {
@Nullable public abstract Cursor getAllBookmarkFolders(ContentResolver cr); @Nullable public abstract Cursor getAllBookmarkFolders(ContentResolver cr);
public abstract void removeBookmarksWithURL(ContentResolver cr, String uri); public abstract void removeBookmarksWithURL(ContentResolver cr, String uri);
public abstract void removeBookmarkWithId(ContentResolver cr, long id); public abstract void removeBookmarkWithId(ContentResolver cr, long id);
public abstract void removeSoftDeleteBookmarks(ContentResolver cr);
public abstract void updateSoftDeleteForBookmarkWithId(ContentResolver cr, long id, boolean softDelete);
public abstract void registerBookmarkObserver(ContentResolver cr, ContentObserver observer); public abstract void registerBookmarkObserver(ContentResolver cr, ContentObserver observer);
public abstract void updateBookmark(ContentResolver cr, long id, String uri, String title, String keyword); public abstract void updateBookmark(ContentResolver cr, long id, String uri, String title, String keyword);
public abstract void updateBookmark(ContentResolver cr, long id, String uri, String title, String keyword, long newParentId, long oldParentId); public abstract void updateBookmark(ContentResolver cr, long id, String uri, String title, String keyword, long newParentId, long oldParentId);

View File

@ -1223,6 +1223,25 @@ public class LocalBrowserDB extends BrowserDB {
new String[] { String.valueOf(id), String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) }); new String[] { String.valueOf(id), String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) });
} }
@Override
public void removeSoftDeleteBookmarks(ContentResolver cr) {
// BrowserProvider will bump parent's lastModified timestamp after successful deletion.
cr.delete(mBookmarksUriWithProfile,
Bookmarks.IS_DELETED + " = 1 AND " + Bookmarks.PARENT + " != ? ",
new String[] { String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) });
}
public void updateSoftDeleteForBookmarkWithId(ContentResolver cr, long id, boolean safeDelete) {
ContentValues values = new ContentValues();
values.put(Bookmarks.IS_DELETED, safeDelete ? 1 : 0);
// No need to update Bookmarks.SYNC_VERSION at this time. The user might revert this operation.
cr.update(mBookmarksUriWithProfile,
values,
"_id = ?",
new String[] { String.valueOf(id) });
}
@Override @Override
public void registerBookmarkObserver(ContentResolver cr, ContentObserver observer) { public void registerBookmarkObserver(ContentResolver cr, ContentObserver observer) {
cr.registerContentObserver(mBookmarksUriWithProfile, false, observer); cr.registerContentObserver(mBookmarksUriWithProfile, false, observer);

View File

@ -240,7 +240,7 @@ public class BookmarksPanel extends HomeFragment implements BookmarkEditFragment
@Override @Override
public void onEditBookmark(@NonNull Bundle bundle) { public void onEditBookmark(@NonNull Bundle bundle) {
new EditBookmarkTask(getActivity(), bundle).execute(); new EditBookmarkTask(getActivity(), bundle, this).execute();
} }
private void updateUiFromCursor(Cursor c) { private void updateUiFromCursor(Cursor c) {

View File

@ -455,7 +455,7 @@ public class BrowserSearch extends HomeFragment
// Position for Top Sites grid items, but will always be -1 since this is only for BrowserSearch result // Position for Top Sites grid items, but will always be -1 since this is only for BrowserSearch result
final int position = -1; final int position = -1;
new RemoveItemTask(getActivity(), info, position).execute(); new RemoveItemTask(getActivity(), info, position, getContext(), this).execute();
return true; return true;
} }

View File

@ -18,7 +18,9 @@ import org.mozilla.gecko.SnackbarBuilder;
import org.mozilla.gecko.Telemetry; import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract; import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.activitystream.ActivityStream; import org.mozilla.gecko.activitystream.ActivityStream;
import org.mozilla.gecko.bookmarks.EditBookmarkCallback;
import org.mozilla.gecko.bookmarks.BookmarkUtils; import org.mozilla.gecko.bookmarks.BookmarkUtils;
import org.mozilla.gecko.bookmarks.UndoEditBookmarkTask;
import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.db.BrowserContract.SuggestedSites; import org.mozilla.gecko.db.BrowserContract.SuggestedSites;
import org.mozilla.gecko.distribution.PartnerBookmarksProviderProxy; import org.mozilla.gecko.distribution.PartnerBookmarksProviderProxy;
@ -59,7 +61,7 @@ import android.view.View;
* <p> * <p>
* The containing activity <b>must</b> implement {@link OnUrlOpenListener}. * The containing activity <b>must</b> implement {@link OnUrlOpenListener}.
*/ */
public abstract class HomeFragment extends Fragment { public abstract class HomeFragment extends Fragment implements EditBookmarkCallback {
// Log Tag. // Log Tag.
private static final String LOGTAG = "GeckoHomeFragment"; private static final String LOGTAG = "GeckoHomeFragment";
@ -348,7 +350,7 @@ public abstract class HomeFragment extends Fragment {
if (info.hasPartnerBookmarkId()) { if (info.hasPartnerBookmarkId()) {
new RemovePartnerBookmarkTask(getActivity(), info.bookmarkId).execute(); new RemovePartnerBookmarkTask(getActivity(), info.bookmarkId).execute();
} else { } else {
new RemoveItemTask(getActivity(), info, position).execute(); new RemoveItemTask(getActivity(), info, position, getContext(), this).execute();
} }
return true; return true;
} }
@ -440,6 +442,16 @@ public abstract class HomeFragment extends Fragment {
mIsLoaded = true; mIsLoaded = true;
} }
@Override
public void onUndoEditBookmark(Bundle bundle) {
new UndoEditBookmarkTask(getActivity(), bundle).execute();
}
@Override
public void onUndoRemoveBookmark(HomeContextMenuInfo info, int position) {
new UndoRemoveBookmarkTask(getActivity(), info, position).execute();
}
private static class ToggleASPinTask extends UIAsyncTask.WithoutParams<Void> { private static class ToggleASPinTask extends UIAsyncTask.WithoutParams<Void> {
private final WeakReference<Activity> activityWeakReference; private final WeakReference<Activity> activityWeakReference;
private final Context context; private final Context context;
@ -500,11 +512,13 @@ public abstract class HomeFragment extends Fragment {
private final int position; private final int position;
private final BrowserDB db; private final BrowserDB db;
private EditBookmarkCallback editBookmarkCallback;
/** /**
* Remove bookmark/history/reading list type item, and also unpin the * Remove bookmark/history/reading list type item, and also unpin the
* Top Sites grid item at index <code>position</code>. * Top Sites grid item at index <code>position</code>.
*/ */
RemoveItemTask(Activity activity, HomeContextMenuInfo info, int position) { RemoveItemTask(Activity activity, HomeContextMenuInfo info, int position, Context context, EditBookmarkCallback editBookmarkCallback) {
super(ThreadUtils.getBackgroundHandler()); super(ThreadUtils.getBackgroundHandler());
this.activityWeakReference = new WeakReference<>(activity); this.activityWeakReference = new WeakReference<>(activity);
@ -512,6 +526,7 @@ public abstract class HomeFragment extends Fragment {
this.info = info; this.info = info;
this.position = position; this.position = position;
this.db = BrowserDB.from(context); this.db = BrowserDB.from(context);
this.editBookmarkCallback = editBookmarkCallback;
} }
@Override @Override
@ -559,10 +574,26 @@ public abstract class HomeFragment extends Fragment {
} else { } else {
message = R.string.page_removed; message = R.string.page_removed;
} }
SnackbarBuilder.builder(activity)
.message(message) if (RemoveItemType.BOOKMARKS == info.itemType) {
.duration(Snackbar.LENGTH_LONG)
.buildAndShow(); SnackbarBuilder.builder(activity)
.message(message)
.action(R.string.bookmark_edit_undo)
.callback(new SnackbarBuilder.SnackbarCallback() {
@Override
public void onClick(View v) {
editBookmarkCallback.onUndoRemoveBookmark(info, position);
}
})
.duration(Snackbar.LENGTH_LONG)
.buildAndShow();
} else {
SnackbarBuilder.builder(activity)
.message(message)
.duration(Snackbar.LENGTH_LONG)
.buildAndShow();
}
} }
private void removeBookmark(ContentResolver cr) { private void removeBookmark(ContentResolver cr) {
@ -579,7 +610,7 @@ public abstract class HomeFragment extends Fragment {
} }
Telemetry.sendUIEvent(TelemetryContract.Event.UNSAVE, TelemetryContract.Method.CONTEXT_MENU, extra); Telemetry.sendUIEvent(TelemetryContract.Event.UNSAVE, TelemetryContract.Method.CONTEXT_MENU, extra);
db.removeBookmarkWithId(cr, info.bookmarkId); db.updateSoftDeleteForBookmarkWithId(cr, info.bookmarkId, true);
if (isReaderViewPage) { if (isReaderViewPage) {
ReadingListHelper.removeCachedReaderItem(info.url, context); ReadingListHelper.removeCachedReaderItem(info.url, context);

View File

@ -0,0 +1,77 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.support.design.widget.Snackbar;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SnackbarBuilder;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.reader.SavedReaderViewHelper;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UIAsyncTask;
import java.lang.ref.WeakReference;
public class UndoRemoveBookmarkTask extends UIAsyncTask.WithoutParams<Void> {
private static final int NONEXISTENT_POSITION = -1;
private final WeakReference<Activity> activityWeakReference;
private final Context context;
private final HomeContextMenuInfo info;
private final int position;
private final BrowserDB db;
/**
* Remove bookmark/history/reading list type item, and also unpin the
* Top Sites grid item at index <code>position</code>.
*/
public UndoRemoveBookmarkTask(Activity activity, HomeContextMenuInfo info, int position) {
super(ThreadUtils.getBackgroundHandler());
this.activityWeakReference = new WeakReference<>(activity);
this.context = activity.getApplicationContext();
this.info = info;
this.position = position;
this.db = BrowserDB.from(context);
}
@Override
public Void doInBackground() {
ContentResolver cr = context.getContentResolver();
if (position > NONEXISTENT_POSITION) {
db.pinSite(cr, info.url, info.title, position);
if (!db.hideSuggestedSite(info.url)) {
cr.notifyChange(BrowserContract.SuggestedSites.CONTENT_URI, null);
}
}
db.updateSoftDeleteForBookmarkWithId(cr, info.bookmarkId, false);
return null;
}
@Override
public void onPostExecute(Void result) {
final Activity activity = activityWeakReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
SnackbarBuilder.builder(activity)
.message(R.string.bookmark_added)
.duration(Snackbar.LENGTH_LONG)
.buildAndShow();
}
}

View File

@ -588,6 +588,7 @@ shown from Android O while a tab is being queued.-->
<!ENTITY bookmark_edit_location "Location"> <!ENTITY bookmark_edit_location "Location">
<!ENTITY bookmark_edit_keyword "Keyword"> <!ENTITY bookmark_edit_keyword "Keyword">
<!ENTITY bookmark_select_folder "Select folder"> <!ENTITY bookmark_select_folder "Select folder">
<!ENTITY bookmark_edit_undo "Undo">
<!-- Localization note (site_settings_*) : These strings are used in the "Site Settings" <!-- Localization note (site_settings_*) : These strings are used in the "Site Settings"
dialog that appears after selecting the "Edit Site Settings" context menu item. --> dialog that appears after selecting the "Edit Site Settings" context menu item. -->

View File

@ -434,6 +434,7 @@
<string name="bookmark_edit_location">&bookmark_edit_location;</string> <string name="bookmark_edit_location">&bookmark_edit_location;</string>
<string name="bookmark_edit_keyword">&bookmark_edit_keyword;</string> <string name="bookmark_edit_keyword">&bookmark_edit_keyword;</string>
<string name="bookmark_select_folder">&bookmark_select_folder;</string> <string name="bookmark_select_folder">&bookmark_select_folder;</string>
<string name="bookmark_edit_undo">&bookmark_edit_undo;</string>
<string name="pref_use_master_password">&pref_use_master_password;</string> <string name="pref_use_master_password">&pref_use_master_password;</string>
<string name="masterpassword_create_title">&masterpassword_create_title;</string> <string name="masterpassword_create_title">&masterpassword_create_title;</string>