tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit fc157dc79e2b97ed4f5b9c6ea2c73dfdd2dfc174
parent 6225c88e92cc2f2d71265600329aa1191aa76290
Author: fmasalha <fmasalha@mozilla.com>
Date:   Wed, 10 Dec 2025 19:46:29 +0000

Bug 2000269 - Added snackbar confirmation on moved bookmarks r=android-reviewers,android-l10n-reviewers,flod,matt-tighe

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

Diffstat:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksReducer.kt | 13+++++++++++++
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksScreen.kt | 24++++++++++++++++++++++++
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksState.kt | 2++
Mmobile/android/fenix/app/src/main/res/values/strings.xml | 2++
Mmobile/android/fenix/app/src/test/java/org/mozilla/fenix/bookmarks/BookmarksReducerTest.kt | 44++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksReducer.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksReducer.kt @@ -269,6 +269,10 @@ private fun BookmarksState.updateSelectedFolder(folder: SelectFolderItem): Bookm } else { alwaysTryUpdate.copy( bookmarksEditBookmarkState = bookmarksEditBookmarkState.copy(folder = folder.folder, edited = true), + bookmarksSnackbarState = BookmarksSnackbarState.BookmarkMoved( + formatBookmarkTitle(bookmarksEditBookmarkState.bookmark.title), + folder.folder.title, + ), ) } } @@ -276,6 +280,15 @@ private fun BookmarksState.updateSelectedFolder(folder: SelectFolderItem): Bookm else -> this } +internal fun formatBookmarkTitle(raw: String, max: Int = 25): String { + val cleaned = raw + .removePrefix("https://") + .removePrefix("http://") + .removePrefix("www.") + + return if (cleaned.length <= max) cleaned else cleaned.take(max) + "…" +} + private fun BookmarksState.toggleSelectionOf(item: BookmarkItem): BookmarksState = if (selectedItems.any { it.guid == item.guid }) { copy(selectedItems = selectedItems - item) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksScreen.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksScreen.kt @@ -273,6 +273,18 @@ private fun BookmarksList( val (id, titleOrCount) = state.undoSnackbarText() stringResource(id, titleOrCount) } + is BookmarksSnackbarState.BookmarkMoved -> { + stringResource( + R.string.bookmark_moved_single_item, + formatArgs = arrayOf( + (state.bookmarksSnackbarState as BookmarksSnackbarState.BookmarkMoved).from, + (state.bookmarksSnackbarState as BookmarksSnackbarState.BookmarkMoved).to, + ), + ) + } + BookmarksSnackbarState.SelectFolderFailed -> { + stringResource(R.string.bookmark_error_select_folder) + } else -> "" } @@ -304,6 +316,18 @@ private fun BookmarksList( onDismissPerformed = { store.dispatch(SnackbarAction.Dismissed) }, ) } + is BookmarksSnackbarState.BookmarkMoved -> scope.launch { + snackbarHostState.displaySnackbar( + message = snackbarMessage, + onDismissPerformed = { store.dispatch(SnackbarAction.Dismissed) }, + ) + } + BookmarksSnackbarState.SelectFolderFailed -> scope.launch { + snackbarHostState.displaySnackbar( + message = snackbarMessage, + onDismissPerformed = { store.dispatch(SnackbarAction.Dismissed) }, + ) + } } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksState.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/bookmarks/BookmarksState.kt @@ -193,6 +193,8 @@ internal sealed class BookmarksSnackbarState { data object None : BookmarksSnackbarState() data object CantEditDesktopFolders : BookmarksSnackbarState() data class UndoDeletion(val guidsToDelete: List<String>) : BookmarksSnackbarState() + data class BookmarkMoved(val from: String, val to: String) : BookmarksSnackbarState() + data object SelectFolderFailed : BookmarksSnackbarState() } internal fun BookmarksSnackbarState.addGuidToDelete(guid: String) = when (this) { diff --git a/mobile/android/fenix/app/src/main/res/values/strings.xml b/mobile/android/fenix/app/src/main/res/values/strings.xml @@ -1737,6 +1737,8 @@ <string name="bookmark_empty_list_folder_description">Add bookmarks as you browse so you can find your favorite sites later.</string> <!-- Description for the add new folder button when selecting a folder. --> <string name="bookmark_select_folder_new_folder_button_title">New folder</string> + <!-- Bookmark snackbar message for moving a single item. %1$s is the title of the item being moved and %2$s is the new parent folder of the bookmark --> + <string name="bookmark_moved_single_item">Moved %1$s to %2$s</string> <!-- Site Permissions --> <!-- Button label that take the user to the Android App setting --> diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/bookmarks/BookmarksReducerTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/bookmarks/BookmarksReducerTest.kt @@ -10,6 +10,7 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test +import org.mozilla.fenix.components.appstate.AppAction class BookmarksReducerTest { @Test @@ -588,12 +589,55 @@ class BookmarksReducerTest { bookmarksSelectFolderState = state.bookmarksSelectFolderState?.copy( outerSelectionGuid = "guid0", ), + bookmarksSnackbarState = BookmarksSnackbarState.BookmarkMoved("title", "Nested 0"), ) assertEquals(expected, result) } @Test + fun `GIVEN we are on the select folder screen and the bookmark has a url longer than 25 characters WHEN a folder is clicked THEN update the truncate the title and display a snackbar with the truncated title`() { + val longTitle = "https://www.firefox.com/en-US/?utm_source=www.mozilla.org&utm_medium=referral&utm_campaign=nav&utm_content=firefox" + val state = BookmarksState.default.copy( + bookmarksEditBookmarkState = BookmarksEditBookmarkState( + bookmark = generateBookmark().copy(title = longTitle), + folder = BookmarkItem.Folder("Bookmarks", "guid0", null), + ), + bookmarksSelectFolderState = BookmarksSelectFolderState( + outerSelectionGuid = "guid0", + folders = listOf( + SelectFolderItem(0, BookmarkItem.Folder("Bookmarks", "guid0", null)), + SelectFolderItem(0, BookmarkItem.Folder("Nested 0", "guid0", null)), + ), + ), + ) + + val result = bookmarksReducer( + state = state, + action = SelectFolderAction.ItemClicked( + folder = SelectFolderItem(0, BookmarkItem.Folder("Nested 0", "guid0", null)), + ), + ) + + val expected = state.copy( + bookmarksEditBookmarkState = state.bookmarksEditBookmarkState?.copy( + folder = BookmarkItem.Folder("Nested 0", "guid0", null), + edited = true, + ), + bookmarksSelectFolderState = state.bookmarksSelectFolderState?.copy( + outerSelectionGuid = "guid0", + ), + bookmarksSnackbarState = BookmarksSnackbarState.BookmarkMoved(formatBookmarkTitle(longTitle), "Nested 0"), + ) + + assertEquals(expected, result) + + val finalResult = bookmarksReducer(result, BackClicked) + + assertEquals(BookmarksSnackbarState.BookmarkMoved(formatBookmarkTitle(longTitle), "Nested 0"), finalResult.bookmarksSnackbarState) + } + + @Test fun `GIVEN a bookmark WHEN a edit is made THEN the edited state is persisted`() { val bookmarkItem = generateBookmark() val folderItem = SelectFolderItem(0, BookmarkItem.Folder("Bookmarks", "guid0", null))