1
0
Fork 0

For #2648: Updates trimming of url hostname (#3191)

* For #2648: Updates trimming of url hostname

* For #2648: Fix nits
master
Sawyer Blatz 2019-06-07 09:33:07 -07:00 committed by GitHub
parent 7368a95d29
commit 45c509fbce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 209 additions and 188 deletions

View File

@ -745,21 +745,24 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope {
} }
private fun showSaveToCollection() { private fun showSaveToCollection() {
val context = context ?: return
getSessionById()?.let { getSessionById()?.let {
val tabs = Tab(it.id, it.url, it.url.urlToTrimmedHost(), it.title) launch(Dispatchers.Main) {
val viewModel = activity?.run { val tabs = Tab(it.id, it.url, it.url.urlToTrimmedHost(context), it.title)
ViewModelProviders.of(this).get(CreateCollectionViewModel::class.java) val viewModel = activity?.run {
} ViewModelProviders.of(this).get(CreateCollectionViewModel::class.java)
viewModel?.tabs = listOf(tabs) }
val selectedSet = mutableSetOf(tabs) viewModel?.tabs = listOf(tabs)
viewModel?.selectedTabs = selectedSet val selectedSet = mutableSetOf(tabs)
viewModel?.tabCollections = requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed() viewModel?.selectedTabs = selectedSet
viewModel?.saveCollectionStep = viewModel?.tabCollections = requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed()
viewModel?.tabCollections?.getStepForCollectionsSize() ?: SaveCollectionStep.SelectCollection viewModel?.saveCollectionStep =
viewModel?.snackbarAnchorView = nestedScrollQuickAction viewModel?.tabCollections?.getStepForCollectionsSize() ?: SaveCollectionStep.SelectCollection
view?.let { viewModel?.snackbarAnchorView = nestedScrollQuickAction
val directions = BrowserFragmentDirections.actionBrowserFragmentToCreateCollectionFragment() view?.let {
nav(R.id.browserFragment, directions) val directions = BrowserFragmentDirections.actionBrowserFragmentToCreateCollectionFragment()
nav(R.id.browserFragment, directions)
}
} }
} }
} }

View File

@ -22,6 +22,10 @@ import io.reactivex.Observer
import io.reactivex.functions.Consumer import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.component_collection_creation.* import kotlinx.android.synthetic.main.component_collection_creation.*
import kotlinx.android.synthetic.main.component_collection_creation.view.* import kotlinx.android.synthetic.main.component_collection_creation.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import mozilla.components.support.ktx.android.view.hideKeyboard import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.ktx.android.view.showKeyboard import mozilla.components.support.ktx.android.view.showKeyboard
import org.mozilla.fenix.R import org.mozilla.fenix.R
@ -30,6 +34,7 @@ import org.mozilla.fenix.ext.urlToTrimmedHost
import org.mozilla.fenix.home.sessioncontrol.Tab import org.mozilla.fenix.home.sessioncontrol.Tab
import org.mozilla.fenix.home.sessioncontrol.TabCollection import org.mozilla.fenix.home.sessioncontrol.TabCollection
import org.mozilla.fenix.mvi.UIView import org.mozilla.fenix.mvi.UIView
import kotlin.coroutines.CoroutineContext
class CollectionCreationUIView( class CollectionCreationUIView(
container: ViewGroup, container: ViewGroup,
@ -39,7 +44,11 @@ class CollectionCreationUIView(
container, container,
actionEmitter, actionEmitter,
changesObservable changesObservable
) { ), CoroutineScope {
private lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
override val view = LayoutInflater.from(container.context) override val view = LayoutInflater.from(container.context)
.inflate(R.layout.component_collection_creation, container, true) .inflate(R.layout.component_collection_creation, container, true)
@ -258,16 +267,18 @@ class CollectionCreationUIView(
is SaveCollectionStep.RenameCollection -> { is SaveCollectionStep.RenameCollection -> {
view.tab_list.isClickable = false view.tab_list.isClickable = false
it.selectedTabCollection?.let { tabCollection -> launch(Dispatchers.Main) {
tabCollection.tabs.map { tab -> it.selectedTabCollection?.let { tabCollection ->
Tab( tabCollection.tabs.map { tab ->
tab.id.toString(), Tab(
tab.url, tab.id.toString(),
tab.url.urlToTrimmedHost(), tab.url,
tab.title tab.url.urlToTrimmedHost(view.context),
) tab.title
}.let { tabs -> )
collectionCreationTabListAdapter.updateData(tabs, tabs.toSet(), true) }.let { tabs ->
collectionCreationTabListAdapter.updateData(tabs, tabs.toSet(), true)
}
} }
} }

View File

@ -16,8 +16,9 @@ import kotlinx.android.synthetic.main.collections_list_item.view.collection_icon
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.urlToTrimmedHost import org.mozilla.fenix.components.description
import org.mozilla.fenix.home.sessioncontrol.Tab import org.mozilla.fenix.home.sessioncontrol.Tab
import org.mozilla.fenix.home.sessioncontrol.TabCollection import org.mozilla.fenix.home.sessioncontrol.TabCollection
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -81,36 +82,23 @@ class CollectionViewHolder(
fun bind(collection: TabCollection) { fun bind(collection: TabCollection) {
this.collection = collection this.collection = collection
view.collection_item.text = collection.title launch(Dispatchers.Main) {
view.collection_item.text = collection.title
view.collection_description.text = collection.description(view.context)
val hostNameList = collection.tabs.map { it.url.urlToTrimmedHost().capitalize() } view.collection_icon.setColorFilter(
ContextCompat.getColor(
var tabsDisplayed = 0 view.context,
val tabTitlesList = hostNameList.joinToString(", ") { getIconColor(collection.id)
if (it.length > maxTitleLength) { ),
it.substring( android.graphics.PorterDuff.Mode.SRC_IN
0, )
maxTitleLength
) + "..."
} else {
tabsDisplayed += 1
it
}
} }
view.collection_description.text = tabTitlesList
view.collection_icon.setColorFilter(
ContextCompat.getColor(
view.context,
getIconColor(collection.id)
),
android.graphics.PorterDuff.Mode.SRC_IN
)
} }
@Suppress("ComplexMethod", "MagicNumber") @Suppress("ComplexMethod", "MagicNumber")
private fun getIconColor(id: Long): Int { private fun getIconColor(id: Long): Int {
return when ((id % 4).toInt()) { return when ((id % 5).toInt()) {
0 -> R.color.collection_icon_color_violet 0 -> R.color.collection_icon_color_violet
1 -> R.color.collection_icon_color_blue 1 -> R.color.collection_icon_color_blue
2 -> R.color.collection_icon_color_pink 2 -> R.color.collection_icon_color_pink

View File

@ -5,6 +5,7 @@
package org.mozilla.fenix.components package org.mozilla.fenix.components
import android.content.Context import android.content.Context
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import org.mozilla.fenix.test.Mockable import org.mozilla.fenix.test.Mockable
/** /**
@ -21,4 +22,5 @@ class Components(private val context: Context) {
val useCases by lazy { UseCases(context, core.sessionManager, core.engine.settings, search.searchEngineManager) } val useCases by lazy { UseCases(context, core.sessionManager, core.engine.settings, search.searchEngineManager) }
val utils by lazy { Utilities(context, core.sessionManager, useCases.sessionUseCases, useCases.searchUseCases) } val utils by lazy { Utilities(context, core.sessionManager, useCases.sessionUseCases, useCases.searchUseCases) }
val analytics by lazy { Analytics(context) } val analytics by lazy { Analytics(context) }
val publicSuffixList by lazy { PublicSuffixList(context) }
} }

View File

@ -14,6 +14,8 @@ import mozilla.components.feature.tab.collections.TabCollection
import mozilla.components.feature.tab.collections.TabCollectionStorage import mozilla.components.feature.tab.collections.TabCollectionStorage
import mozilla.components.support.base.observer.Observable import mozilla.components.support.base.observer.Observable
import mozilla.components.support.base.observer.ObserverRegistry import mozilla.components.support.base.observer.ObserverRegistry
import org.mozilla.fenix.ext.urlToTrimmedHost
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder
import org.mozilla.fenix.test.Mockable import org.mozilla.fenix.test.Mockable
@Mockable @Mockable
@ -88,3 +90,18 @@ class TabCollectionStorage(
notifyObservers { onCollectionRenamed(tabCollection, title) } notifyObservers { onCollectionRenamed(tabCollection, title) }
} }
} }
suspend fun TabCollection.description(context: Context): String {
return this.tabs
.map { it.url.urlToTrimmedHost(context).capitalize() }
.map {
if (it.length > CollectionViewHolder.maxTitleLength) {
it.substring(
0,
CollectionViewHolder.maxTitleLength
) + ""
} else {
it
}
}.joinToString(", ")
}

View File

@ -6,8 +6,11 @@
package org.mozilla.fenix.ext package org.mozilla.fenix.ext
import android.content.Context
import java.net.MalformedURLException import java.net.MalformedURLException
import java.net.URL import java.net.URL
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
import mozilla.components.support.ktx.kotlin.toUri
/** /**
* Replaces the keys with the values with the map provided. * Replaces the keys with the values with the map provided.
@ -28,21 +31,14 @@ fun String?.getHostFromUrl(): String? = try {
null null
} }
fun String?.urlToTrimmedHost(): String { /**
* Trim a host's prefix and suffix
*/
suspend fun String.urlToTrimmedHost(context: Context): String {
return try { return try {
val url = URL(this) val host = this.toUri().hostWithoutCommonPrefixes ?: return this
val firstIndex = url.host.indexOfFirst { it == '.' } + 1 context.components.publicSuffixList.stripPublicSuffix(host).await()
val lastIndex = url.host.indexOfLast { it == '.' }
// Trim all but the title of the website from the hostname. 'www.mozilla.org' becomes 'mozilla'
when {
firstIndex - 1 == lastIndex -> url.host.substring(0, lastIndex)
firstIndex < lastIndex -> url.host.substring(firstIndex, lastIndex)
else -> url.host
}
} catch (e: MalformedURLException) { } catch (e: MalformedURLException) {
this.getHostFromUrl() ?: "" this
} catch (e: StringIndexOutOfBoundsException) {
this.getHostFromUrl() ?: ""
} }
} }

View File

@ -134,7 +134,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
) { ) {
SessionControlViewModel( SessionControlViewModel(
SessionControlState( SessionControlState(
getListOfTabs(requireComponents.core.sessionManager), listOf(),
setOf(), setOf(),
requireComponents.core.tabCollectionStorage.cachedTabCollections, requireComponents.core.tabCollectionStorage.cachedTabCollections,
mode mode
@ -280,13 +280,15 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
} }
} }
getManagedEmitter<SessionControlChange>().onNext( launch(Dispatchers.Main) {
SessionControlChange.Change( getManagedEmitter<SessionControlChange>().onNext(
tabs = getListOfTabs(sessionManager = requireComponents.core.sessionManager), SessionControlChange.Change(
mode = currentMode(), tabs = getListOfTabs(sessionManager = requireComponents.core.sessionManager),
collections = requireComponents.core.tabCollectionStorage.cachedTabCollections mode = currentMode(),
collections = requireComponents.core.tabCollectionStorage.cachedTabCollections
)
) )
) }
requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this) requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this)
sessionObserver.onStart() sessionObserver.onStart()
@ -560,82 +562,84 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
val useCases = context?.components?.useCases?.tabsUseCases ?: return val useCases = context?.components?.useCases?.tabsUseCases ?: return
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.TabsChange(listOf())) getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.TabsChange(listOf()))
deleteAllSessionsJob = {
val deleteOperation: (suspend () -> Unit) = {
currentFilteredSessions.forEach { currentFilteredSessions.forEach {
useCases.removeTab.invoke(it) useCases.removeTab.invoke(it)
} }
} }
deleteAllSessionsJob = deleteOperation
allowUndo( allowUndo(
view!!, getString(R.string.snackbar_tabs_deleted), view!!, getString(R.string.snackbar_tabs_deleted),
getString(R.string.snackbar_deleted_undo), { getString(R.string.snackbar_deleted_undo), {
deleteAllSessionsJob = null deleteAllSessionsJob = null
emitSessionChanges() emitSessionChanges()
} },
) { operation = deleteOperation
deleteAllSessionsJob = { )
currentFilteredSessions.forEach {
useCases.removeTab.invoke(it)
}
}
}
} }
private fun removeTabWithUndo(sessionId: String) { private fun removeTabWithUndo(sessionId: String) {
val sessionManager = requireComponents.core.sessionManager launch(Dispatchers.Main) {
val sessionManager = requireComponents.core.sessionManager
// Update the UI with the tab removed, but don't remove it from storage yet // Update the UI with the tab removed, but don't remove it from storage yet
getManagedEmitter<SessionControlChange>().onNext( getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.TabsChange(
sessionManager.sessions SessionControlChange.TabsChange(
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private } sessionManager.sessions
.filter { it.id != sessionId } .filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }
.map { .filter { it.id != sessionId }
val selected = .map {
it == sessionManager.selectedSession val selected = it == sessionManager.selectedSession
Tab( Tab(
it.id, it.id,
it.url, it.url,
it.url.urlToTrimmedHost(), it.url.urlToTrimmedHost(context!!),
it.title, it.title,
selected, selected,
it.thumbnail it.thumbnail
) )
} }
)
) )
)
deleteSessionJob = { val deleteOperation: (suspend () -> Unit) = {
sessionManager.findSessionById(sessionId) sessionManager.findSessionById(sessionId)
?.let { session -> ?.let { session ->
sessionManager.remove(session) sessionManager.remove(session)
} }
}
allowUndo(
view!!, getString(R.string.snackbar_tab_deleted),
getString(R.string.snackbar_deleted_undo), {
deleteSessionJob = null
emitSessionChanges()
} }
) {
sessionManager.findSessionById(sessionId) deleteSessionJob = deleteOperation
?.let { session ->
sessionManager.remove(session) allowUndo(
} view!!, getString(R.string.snackbar_tab_deleted),
getString(R.string.snackbar_deleted_undo), {
deleteSessionJob = null
emitSessionChanges()
},
operation = deleteOperation
)
} }
} }
private fun emitSessionChanges() { private fun emitSessionChanges() {
val sessionManager = context?.components?.core?.sessionManager ?: return val sessionManager = context?.components?.core?.sessionManager ?: return
getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.TabsChange( launch(Dispatchers.Main) {
getListOfTabs(sessionManager) getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.TabsChange(
getListOfTabs(sessionManager)
)
) )
) }
} }
private fun getListOfTabs(sessionManager: SessionManager): List<Tab> { private suspend fun getListOfTabs(sessionManager: SessionManager): List<Tab> {
val context = context ?: return listOf()
return sessionManager.sessions return sessionManager.sessions
.filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private } .filter { (activity as HomeActivity).browsingModeManager.isPrivate == it.private }
.map { .map {
@ -643,7 +647,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
Tab( Tab(
it.id, it.id,
it.url, it.url,
it.url.urlToTrimmedHost(), it.url.urlToTrimmedHost(context),
it.title, it.title,
selected, selected,
it.thumbnail it.thumbnail
@ -663,24 +667,29 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
) { ) {
if (findNavController(this).currentDestination?.id == R.id.createCollectionFragment) return if (findNavController(this).currentDestination?.id == R.id.createCollectionFragment) return
val tabs = requireComponents.core.sessionManager.sessions.filter { !it.private } val context = context?.let { it } ?: return
.map { Tab(it.id, it.url, it.url.urlToTrimmedHost(), it.title) }
val viewModel = activity?.run { launch(Dispatchers.Main) {
ViewModelProviders.of(this).get(CreateCollectionViewModel::class.java) val tabs = requireComponents.core.sessionManager.sessions.filter { !it.private }
} .map { Tab(it.id, it.url, it.url.urlToTrimmedHost(context), it.title) }
viewModel?.tabs = tabs
val selectedTabs = tabs.find { tab -> tab.sessionId == selectedTabId } ?: if (tabs.size == 1) tabs[0] else null
val selectedSet = if (selectedTabs == null) mutableSetOf() else mutableSetOf(selectedTabs)
viewModel?.selectedTabs = selectedSet
viewModel?.tabCollections = requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed()
viewModel?.selectedTabCollection = selectedTabCollection
viewModel?.saveCollectionStep =
step ?: viewModel?.getStepForTabsAndCollectionSize() ?: SaveCollectionStep.SelectTabs
view?.let { val viewModel = activity?.run {
val directions = HomeFragmentDirections.actionHomeFragmentToCreateCollectionFragment() ViewModelProviders.of(this).get(CreateCollectionViewModel::class.java)
nav(R.id.homeFragment, directions) }
viewModel?.tabs = tabs
val selectedTabs =
tabs.find { tab -> tab.sessionId == selectedTabId } ?: if (tabs.size == 1) tabs[0] else null
val selectedSet = if (selectedTabs == null) mutableSetOf() else mutableSetOf(selectedTabs)
viewModel?.selectedTabs = selectedSet
viewModel?.tabCollections = requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed()
viewModel?.selectedTabCollection = selectedTabCollection
viewModel?.saveCollectionStep =
step ?: viewModel?.getStepForTabsAndCollectionSize() ?: SaveCollectionStep.SelectTabs
view?.let {
val directions = HomeFragmentDirections.actionHomeFragmentToCreateCollectionFragment()
nav(R.id.homeFragment, directions)
}
} }
} }

View File

@ -16,13 +16,14 @@ import kotlinx.android.synthetic.main.collection_home_list_row.view.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import mozilla.components.browser.menu.BrowserMenu import mozilla.components.browser.menu.BrowserMenu
import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.BrowserMenuBuilder
import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ThemeManager import org.mozilla.fenix.ThemeManager
import org.mozilla.fenix.components.description
import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.ext.urlToTrimmedHost
import org.mozilla.fenix.home.sessioncontrol.CollectionAction import org.mozilla.fenix.home.sessioncontrol.CollectionAction
import org.mozilla.fenix.home.sessioncontrol.SessionControlAction import org.mozilla.fenix.home.sessioncontrol.SessionControlAction
import org.mozilla.fenix.home.sessioncontrol.TabCollection import org.mozilla.fenix.home.sessioncontrol.TabCollection
@ -92,47 +93,33 @@ class CollectionViewHolder(
} }
private fun updateCollectionUI() { private fun updateCollectionUI() {
view.collection_title.text = collection.title launch(Dispatchers.Main) {
view.collection_title.text = collection.title
view.collection_description.text = collection.description(view.context)
val hostNameList = collection.tabs.map { it.url.urlToTrimmedHost().capitalize() } if (expanded) {
(view.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = 0
collection_title.setPadding(0, 0, 0, EXPANDED_PADDING)
view.background = ContextCompat.getDrawable(view.context, R.drawable.rounded_top_corners)
view.collection_description.visibility = View.GONE
var tabsDisplayed = 0 view.chevron.setBackgroundResource(R.drawable.ic_chevron_up)
val tabTitlesList = hostNameList.joinToString(", ") {
if (it.length > maxTitleLength) {
it.substring(
0,
maxTitleLength
) + "..."
} else { } else {
tabsDisplayed += 1 (view.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = COLLAPSED_MARGIN
it view.background = ContextCompat.getDrawable(view.context, R.drawable.rounded_all_corners)
view.collection_description.visibility = View.VISIBLE
view.chevron.setBackgroundResource(R.drawable.ic_chevron_down)
} }
view.collection_icon.setColorFilter(
ContextCompat.getColor(
view.context,
getIconColor(collection.id)
),
android.graphics.PorterDuff.Mode.SRC_IN
)
} }
view.collection_description.text = tabTitlesList
if (expanded) {
(view.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = 0
collection_title.setPadding(0, 0, 0, EXPANDED_PADDING)
view.background = ContextCompat.getDrawable(view.context, R.drawable.rounded_top_corners)
view.collection_description.visibility = View.GONE
view.chevron.setBackgroundResource(R.drawable.ic_chevron_up)
} else {
(view.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = COLLAPSED_MARGIN
view.background = ContextCompat.getDrawable(view.context, R.drawable.rounded_all_corners)
view.collection_description.visibility = View.VISIBLE
view.chevron.setBackgroundResource(R.drawable.ic_chevron_down)
}
view.collection_icon.setColorFilter(
ContextCompat.getColor(
view.context,
getIconColor(collection.id)
),
android.graphics.PorterDuff.Mode.SRC_IN
)
} }
private fun handleExpansion(isExpanded: Boolean) { private fun handleExpansion(isExpanded: Boolean) {
@ -145,7 +132,7 @@ class CollectionViewHolder(
@Suppress("ComplexMethod", "MagicNumber") @Suppress("ComplexMethod", "MagicNumber")
private fun getIconColor(id: Long): Int { private fun getIconColor(id: Long): Int {
val sessionColorIndex = (id % 4).toInt() val sessionColorIndex = (id % 5).toInt()
return when (sessionColorIndex) { return when (sessionColorIndex) {
0 -> R.color.collection_icon_color_violet 0 -> R.color.collection_icon_color_violet
1 -> R.color.collection_icon_color_blue 1 -> R.color.collection_icon_color_blue

View File

@ -79,7 +79,9 @@ class TabInCollectionViewHolder(
} }
private fun updateTabUI() { private fun updateTabUI() {
collection_tab_hostname.text = tab.url.urlToTrimmedHost() launch(Dispatchers.Main) {
collection_tab_hostname.text = tab.url.urlToTrimmedHost(view.context)
}
collection_tab_title.text = tab.title collection_tab_title.text = tab.title
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
val bitmap = collection_tab_icon.context.components.core.icons val bitmap = collection_tab_icon.context.components.core.icons

View File

@ -24,6 +24,7 @@ import androidx.navigation.NavController
import androidx.navigation.Navigation import androidx.navigation.Navigation
import kotlinx.android.synthetic.main.fragment_bookmark.view.* import kotlinx.android.synthetic.main.fragment_bookmark.view.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -262,17 +263,22 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
} }
} }
is BookmarkAction.Delete -> { is BookmarkAction.Delete -> {
getManagedEmitter<BookmarkChange>() context?.let { context ->
.onNext(BookmarkChange.Change(currentRoot - it.item.guid)) getManagedEmitter<BookmarkChange>()
.onNext(BookmarkChange.Change(currentRoot - it.item.guid))
allowUndo( launch(Dispatchers.Main) {
view!!, allowUndo(
getString(R.string.bookmark_deletion_snackbar_message, it.item.url.urlToTrimmedHost()), view!!,
getString(R.string.bookmark_undo_deletion), { refreshBookmarks() } getString(R.string.bookmark_deletion_snackbar_message,
) { it.item.url?.urlToTrimmedHost(context)),
bookmarkStorage()?.deleteNode(it.item.guid) getString(R.string.bookmark_undo_deletion), { refreshBookmarks() }
metrics()?.track(Event.RemoveBookmark) ) {
refreshBookmarks() bookmarkStorage()?.deleteNode(it.item.guid)
metrics()?.track(Event.RemoveBookmark)
refreshBookmarks()
}
}
} }
} }
is BookmarkAction.SwitchMode -> { is BookmarkAction.SwitchMode -> {