From 9b1c1b5f4d679c3262de68e03d14b14cb72b77dc Mon Sep 17 00:00:00 2001 From: Colin Lee Date: Thu, 11 Apr 2019 13:58:07 -0500 Subject: [PATCH] For #1571: Make bookmark deletion undoable --- CHANGELOG.md | 1 + .../org/mozilla/fenix/ext/CoroutineScope.kt | 26 +++++++++++++++++++ .../main/java/org/mozilla/fenix/ext/String.kt | 12 +++++++++ .../library/bookmarks/BookmarkFragment.kt | 23 +++++++--------- app/src/main/res/values/strings.xml | 3 ++- 5 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/ext/CoroutineScope.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fa9c2be4..73a4d8f48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - #1539 - Added bookmarks multi-select related features - #1603 - Remove deprecated success path for Firefox Accounts login - #619 - Sets toolbar behavior based on accessibility and if session is loading +- #1571 - Added a snackbar for undoing bookmark deletion ### Changed - #1429 - Updated site permissions ui for MVP diff --git a/app/src/main/java/org/mozilla/fenix/ext/CoroutineScope.kt b/app/src/main/java/org/mozilla/fenix/ext/CoroutineScope.kt new file mode 100644 index 000000000..c22f01d24 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/ext/CoroutineScope.kt @@ -0,0 +1,26 @@ +/* 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.fenix.ext + +import android.view.View +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.mozilla.fenix.components.FenixSnackbar + +fun CoroutineScope.allowUndo(view: View, message: String, undoActionTitle: String, operation: suspend () -> Unit) { + val undoJob = launch(Dispatchers.IO) { + delay(UNDO_DELAY) + operation.invoke() + } + FenixSnackbar.make(view, FenixSnackbar.LENGTH_LONG) + .setText(message) + .setAction(undoActionTitle) { + undoJob.cancel() + }.show() +} + +internal const val UNDO_DELAY = 3000L diff --git a/app/src/main/java/org/mozilla/fenix/ext/String.kt b/app/src/main/java/org/mozilla/fenix/ext/String.kt index 04421f26f..9e1d127e4 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/String.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/String.kt @@ -6,6 +6,9 @@ package org.mozilla.fenix.ext +import java.net.MalformedURLException +import java.net.URL + /** * Replaces the keys with the values with the map provided. */ @@ -14,3 +17,12 @@ fun String.replace(pairs: Map): String { pairs.forEach { (l, r) -> result = result.replace(l, r) } return result } + +fun String?.urlToHost(): String { + return try { + val url = URL(this) + url.host + } catch (e: MalformedURLException) { + "" + } +} diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt index fbd13005b..87933d74c 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt @@ -31,7 +31,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Job -import kotlinx.coroutines.delay import kotlinx.coroutines.launch import mozilla.appservices.places.BookmarkRoot import mozilla.components.concept.storage.BookmarkNode @@ -45,9 +44,11 @@ import org.mozilla.fenix.BrowsingModeManager import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar +import org.mozilla.fenix.ext.allowUndo import org.mozilla.fenix.ext.getColorFromAttr import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.share +import org.mozilla.fenix.ext.urlToHost import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.getAutoDisposeObservable import org.mozilla.fenix.mvi.getManagedEmitter @@ -216,7 +217,10 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve } } is BookmarkAction.Delete -> { - launch(IO) { + allowUndo( + view!!, getString(R.string.bookmark_deletion_snackbar_message, it.item.url.urlToHost()), + getString(R.string.bookmark_undo_deletion) + ) { requireComponents.core.bookmarksStorage.deleteNode(it.item.guid) refreshBookmarks() } @@ -277,16 +281,13 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve true } R.id.delete_bookmarks_multi_select -> { - val deleteJob = launch(IO) { - delay(bookmarkDeletionDelay) + allowUndo( + view!!, getString(R.string.bookmark_deletion_multiple_snackbar_message), + getString(R.string.bookmark_undo_deletion) + ) { deleteSelectedBookmarks() refreshBookmarks() } - FenixSnackbar.make(view!!, FenixSnackbar.LENGTH_LONG) - .setText(getString(R.string.bookmark_deletion_multiple_snackbar_message)) - .setAction(getString(R.string.bookmark_undo_deletion)) { - deleteJob.cancel() - }.show() true } else -> super.onOptionsItemSelected(item) @@ -344,8 +345,4 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve val uri = Uri.parse(url) clipBoard.primaryClip = ClipData.newRawUri("Uri", uri) } - - companion object { - private const val bookmarkDeletionDelay = 3000L - } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2964275fe..f7e8a1357 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -327,7 +327,8 @@ Invalid URL No bookmarks here - + Deleted %1$s Deleting selected bookmarks