diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 03f98578482e..68ddf4ca388a 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -62,6 +62,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import mozilla.appservices.places.BookmarkRoot import mozilla.components.browser.menu.view.MenuButton import mozilla.components.browser.state.selector.findTab @@ -70,6 +71,7 @@ import mozilla.components.browser.state.selector.privateTabs import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.FrecencyThresholdOption import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.AuthType @@ -308,6 +310,17 @@ class HomeFragment : Fragment() { ) } + internal suspend fun getRecentlySavedBookmarks(): List? = withContext(IO) { + val recentBookmarks = bookmarksStorage.getRecentBookmarks(4) + if (recentBookmarks.isNullOrEmpty()) null else recentBookmarks + } + + /** + * The [SessionControlView] is forced to update with our current state when we call + * [HomeFragment.onCreateView] in order to be able to draw everything at once with the current + * data in our store. The [View.consumeFrom] coroutine dispatch + * doesn't get run right away which means that we won't draw on the first layout pass. + */ /** * The [SessionControlView] is forced to update with our current state when we call * [HomeFragment.onCreateView] in order to be able to draw everything at once with the current @@ -891,6 +904,9 @@ class HomeFragment : Fragment() { requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this) } + /** + * This method will find and scroll to the row of the specified collection Id. + * */ /** * This method will find and scroll to the row of the specified collection Id. * */ @@ -932,6 +948,9 @@ class HomeFragment : Fragment() { } } + /** + * Returns index of the collection with the specified id. + * */ /** * Returns index of the collection with the specified id. * */ @@ -950,6 +969,9 @@ class HomeFragment : Fragment() { return result } + /** + * Will highlight the border of the collection with the specified index. + * */ /** * Will highlight the border of the collection with the specified index. * */ @@ -987,6 +1009,9 @@ class HomeFragment : Fragment() { } } + /** + * Will focus the collection with [indexOfCollection] for accessibility services. + * */ /** * Will focus the collection with [indexOfCollection] for accessibility services. * */ @@ -1064,6 +1089,10 @@ class HomeFragment : Fragment() { private const val FOCUS_ON_ADDRESS_BAR = "focusOnAddressBar" private const val FOCUS_ON_COLLECTION = "focusOnCollection" + /** + * Represents the number of items in [sessionControlView] that are NOT part of + * the list of collections. At the moment these are topSites pager, collections header. + * */ /** * Represents the number of items in [sessionControlView] that are NOT part of * the list of collections. At the moment these are topSites pager, collections header. diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/RecentBookmarksAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/RecentBookmarksAdapter.kt new file mode 100644 index 000000000000..ebe242a43526 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/RecentBookmarksAdapter.kt @@ -0,0 +1,76 @@ +/* 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.home.sessioncontrol + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import kotlinx.android.synthetic.main.component_bookmark.view.* +import mozilla.components.concept.storage.BookmarkNode +import org.mozilla.fenix.home.sessioncontrol.viewholders.recentbookmarks.RecentBookmarksViewHolder + +class RecentBookmarksAdapter( + private val interactor: SessionControlInteractor +) : ListAdapter, RecentBookmarksViewHolder>(RecentBookmarksListDiffCallback) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecentBookmarksViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(RecentBookmarksViewHolder.LAYOUT_ID, parent, false) + return RecentBookmarksViewHolder(view, interactor) + } + + override fun onBindViewHolder( + holder: RecentBookmarksViewHolder, + position: Int, + payloads: MutableList + ) { + if (payloads.isNullOrEmpty()) { + onBindViewHolder(holder, position) + } else { + if (payloads[0] is AdapterItem.RecentBookmarksPayload) { + val adapter = holder.itemView.bookmark_list.adapter as RecentBookmarksItemAdapter + val payload = payloads[0] as AdapterItem.RecentBookmarksPayload + for (item in payload.changed) { + adapter.notifyItemChanged( + item.first % RecentBookmarksViewHolder.MAX_BOOKMARKS, + RecentBookmarksItemAdapter.RecentBookmarkItemPayload(item.second) + ) + } + } + } + } + + override fun onBindViewHolder(holder: RecentBookmarksViewHolder, position: Int) { + val adapter = holder.itemView.bookmark_list.adapter as RecentBookmarksItemAdapter + adapter.submitList(getItem(position)) + } + + internal object RecentBookmarksListDiffCallback : DiffUtil.ItemCallback>() { + override fun areItemsTheSame( + oldItem: List, newItem: List + ): Boolean { + return oldItem.size == newItem.size + } + + override fun areContentsTheSame( + oldItem: List, newItem: List + ): Boolean { + return newItem.zip(oldItem).all { (new, old) -> new == old } + } + + override fun getChangePayload( + oldItem: List, newItem: List + ): Any? { + val changed = mutableSetOf>() + for ((index, item) in newItem.withIndex()) { + if (oldItem.getOrNull(index) != item) { + changed.add(Pair(index, item)) + } + } + return if (changed.isNotEmpty()) AdapterItem.RecentBookmarksPayload(changed) else null + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/RecentBookmarksItemAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/RecentBookmarksItemAdapter.kt new file mode 100644 index 000000000000..7644dc399eb0 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/RecentBookmarksItemAdapter.kt @@ -0,0 +1,63 @@ +/* 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.home.sessioncontrol + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import mozilla.components.concept.storage.BookmarkNode +import org.mozilla.fenix.home.sessioncontrol.viewholders.recentbookmarks.RecentBookmarkItemViewHolder + +class RecentBookmarksItemAdapter( + private val interactor: SessionControlInteractor +) : ListAdapter(RecentBookmarksDiffCallback) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecentBookmarkItemViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(RecentBookmarkItemViewHolder.LAYOUT_ID, parent, false) + return RecentBookmarkItemViewHolder(view, interactor) + } + + override fun onBindViewHolder(holder: RecentBookmarkItemViewHolder, position: Int) { +// StartupTimeline.onTopSitesItemBound(holder) + holder.bind(getItem(position)) + } + + override fun onBindViewHolder( + holder: RecentBookmarkItemViewHolder, + position: Int, + payloads: MutableList + ) { + if (payloads.isNullOrEmpty()) { + onBindViewHolder(holder, position) + } else { + when (payloads[0]) { + is BookmarkNode -> { + holder.bind((payloads[0] as BookmarkNode)) + } + } + } + } + + + data class RecentBookmarkItemPayload( + val newInstance: BookmarkNode + ) + +// object RecentBookmarksHeader : AdapterItem(RecentBookmarksHeaderViewHolder.LAYOUT_ID) +// object RecentBookmarkItem : AdapterItem(.LAYOUT_ID) + + internal object RecentBookmarksDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: BookmarkNode, newItem: BookmarkNode) = oldItem.guid == newItem.guid + + override fun areContentsTheSame(oldItem: BookmarkNode, newItem: BookmarkNode) = + oldItem.guid == newItem.guid && + oldItem.parentGuid == newItem.parentGuid && + oldItem.title == newItem.title && + oldItem.url == newItem.url && + oldItem.type == newItem.type + } +} diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt index 8cf6fd905e54..9f68492e617e 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt @@ -12,6 +12,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import mozilla.components.concept.storage.BookmarkNode import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite import mozilla.components.ui.widgets.WidgetSiteItemView @@ -22,7 +23,7 @@ import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHol import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.NoCollectionsMessageViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.PrivateBrowsingDescriptionViewHolder -import org.mozilla.fenix.home.sessioncontrol.viewholders.RecentBookmarksHeaderViewHolder +import org.mozilla.fenix.home.sessioncontrol.viewholders.recentbookmarks.RecentBookmarksHeaderViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.TabInCollectionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.TopSitePagerViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.ExperimentDefaultBrowserCardViewHolder @@ -37,6 +38,7 @@ import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingTh import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingToolbarPositionPickerViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingTrackingProtectionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingWhatsNewViewHolder +import org.mozilla.fenix.home.sessioncontrol.viewholders.recentbookmarks.RecentBookmarkItemViewHolder import org.mozilla.fenix.home.tips.ButtonTipViewHolder import mozilla.components.feature.tab.collections.Tab as ComponentTab @@ -132,8 +134,12 @@ sealed class AdapterItem(@LayoutRes val viewType: Int) { object OnboardingWhatsNew : AdapterItem(OnboardingWhatsNewViewHolder.LAYOUT_ID) - object RecentBookmarksHeader : AdapterItem(CollectionHeaderViewHolder.LAYOUT_ID) - object RecentBookmarkItem : AdapterItem(CollectionViewHolder.LAYOUT_ID) + object RecentBookmarksHeader : AdapterItem(RecentBookmarksHeaderViewHolder.LAYOUT_ID) + object RecentBookmarkItem : AdapterItem(RecentBookmarkItemViewHolder.LAYOUT_ID) + + data class RecentBookmarksPayload( + val changed: Set> + ) /** * True if this item represents the same value as other. Used by [AdapterItemDiffCallback]. @@ -215,6 +221,7 @@ class SessionControlAdapter( view ) ExperimentDefaultBrowserCardViewHolder.LAYOUT_ID -> ExperimentDefaultBrowserCardViewHolder(view, interactor) + RecentBookmarksHeaderViewHolder.LAYOUT_ID -> RecentBookmarksHeaderViewHolder(view) else -> throw IllegalStateException() } @@ -267,7 +274,8 @@ class SessionControlAdapter( is OnboardingAutomaticSignInViewHolder -> holder.bind( (item as AdapterItem.OnboardingAutomaticSignIn).state.withAccount ) - is RecentBookmarksHeaderViewHolder -> holder.bind() + is RecentBookmarksHeaderViewHolder -> + holder.bind(item as AdapterItem.RecentBookmarksHeader) } } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt index 5efc98120eac..0792f112f576 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt @@ -12,6 +12,7 @@ import androidx.navigation.NavController import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import mozilla.appservices.places.BookmarkRoot import mozilla.components.browser.state.selector.getNormalOrPrivateTabs import mozilla.components.browser.state.state.availableSearchEngines import mozilla.components.browser.state.state.searchEngines @@ -19,6 +20,7 @@ import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.Engine import mozilla.components.concept.engine.prompt.ShareData +import mozilla.components.concept.storage.BookmarkNode import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.tab.collections.ext.invoke @@ -27,6 +29,7 @@ import mozilla.components.feature.top.sites.TopSite import mozilla.components.support.ktx.android.view.showKeyboard import mozilla.components.support.ktx.kotlin.isUrl import org.mozilla.fenix.BrowserDirection +import org.mozilla.fenix.GlobalDirections import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode @@ -178,6 +181,16 @@ interface SessionControlController { * @see [ExperimentCardInteractor.onCloseExperimentCardClicked] */ fun handleCloseExperimentCard() + + /** + * @see [RecentBookmarksInteractor.onRecentBookmarkClicked] + */ + fun handleBookmarkClicked(bookmark: BookmarkNode) + + /** + * @see [RecentBookmarksInteractor.onShowAllBookmarksClicked] + */ + fun handleShowAllBookmarksClicked() } @Suppress("TooManyFunctions", "LargeClass") @@ -576,4 +589,20 @@ class DefaultSessionControlController( metrics.track(Event.CloseExperimentCardClicked) fragmentStore.dispatch(HomeFragmentAction.RemoveSetDefaultBrowserCard) } + + override fun handleBookmarkClicked(bookmark: BookmarkNode) { + with(activity) { + browsingModeManager.mode = browsingModeManager.mode + openToBrowserAndLoad( + searchTermOrURL = bookmark.url!!, + newTab = true, + from = BrowserDirection.FromHome + ) + } + } + + override fun handleShowAllBookmarksClicked() { + val directions = HomeFragmentDirections.actionGlobalBookmarkFragment(BookmarkRoot.Mobile.id) + navController.nav(R.id.homeFragment, directions) + } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt index c88fa0fc1641..24c763c74752 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.home.sessioncontrol +import mozilla.components.concept.storage.BookmarkNode import mozilla.components.feature.tab.collections.Tab import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite @@ -202,6 +203,26 @@ interface ExperimentCardInteractor { fun onCloseExperimentCardClicked() } + +/** + * Interface for recently saved bookmark related actions in the [SessionControlInteractor]. + */ +interface RecentBookmarksInteractor { + /** + * Opens the given bookmark in a new tab. Called when an user clicks on a recently saved + * bookmark on the home screen. + * + * @param bookmark The bookmark that will be opened. + */ + fun onRecentBookmarkClicked(bookmark: BookmarkNode) + + /** + * Navigates to bookmark list. Called when an user clicks on the "Show all" button for + * recently saved bookmarks on the home screen. + */ + fun onShowAllBookmarksClicked() +} + /** * Interactor for the Home screen. * Provides implementations for the CollectionInteractor, OnboardingInteractor, @@ -211,7 +232,7 @@ interface ExperimentCardInteractor { class SessionControlInteractor( private val controller: SessionControlController ) : CollectionInteractor, OnboardingInteractor, TopSiteInteractor, TipInteractor, - TabSessionInteractor, ToolbarInteractor, ExperimentCardInteractor { + TabSessionInteractor, ToolbarInteractor, ExperimentCardInteractor, RecentBookmarksInteractor { override fun onCollectionAddTabTapped(collection: TabCollection) { controller.handleCollectionAddTabTapped(collection) } @@ -315,4 +336,12 @@ class SessionControlInteractor( override fun onCloseExperimentCardClicked() { controller.handleCloseExperimentCard() } + + override fun onRecentBookmarkClicked(bookmark: BookmarkNode) { + controller.handleBookmarkClicked(bookmark) + } + + override fun onShowAllBookmarksClicked() { + controller.handleShowAllBookmarksClicked() + } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt index 859d23d1ac87..617679b42e1b 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt @@ -10,6 +10,8 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kotlinx.android.extensions.LayoutContainer +import mozilla.appservices.places.MsgTypes +import mozilla.components.concept.storage.BookmarkNode import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite import org.mozilla.fenix.components.tips.Tip @@ -27,6 +29,7 @@ private fun normalModeAdapterItems( collections: List, expandedCollections: Set, tip: Tip?, + recentBookmarks: List?, showCollectionsPlaceholder: Boolean, showSetAsDefaultBrowserCard: Boolean ): List { @@ -50,6 +53,10 @@ private fun normalModeAdapterItems( showCollections(collections, expandedCollections, items) } + if (!recentBookmarks.isNullOrEmpty()) { + items.addAll(recentBookmarksAdapterItems(recentBookmarks)) + } + return items } @@ -109,12 +116,27 @@ private fun onboardingAdapterItems(onboardingState: OnboardingState): List +): List { + val items: MutableList = mutableListOf(AdapterItem.RecentBookmarksHeader) + + recentBookmarks.map { + AdapterItem.RecentBookmarkItem + }.forEach { + items.add(it) + } + + return items +} + private fun HomeFragmentState.toAdapterList(): List = when (mode) { is Mode.Normal -> normalModeAdapterItems( topSites, collections, expandedCollections, tip, + recentBookmarks, showCollectionPlaceholder, showSetAsDefaultBrowserCard ) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/RecentBookmarksViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/RecentBookmarksViewHolder.kt deleted file mode 100644 index 50ce6f3ef9f9..000000000000 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/RecentBookmarksViewHolder.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* 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.home.sessioncontrol.viewholders - -import android.content.Context -import android.view.View -import androidx.core.graphics.BlendModeColorFilterCompat.createBlendModeColorFilterCompat -import androidx.core.graphics.BlendModeCompat.SRC_IN -import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.android.synthetic.main.collection_home_list_row.* -import kotlinx.android.synthetic.main.component_top_sites.view.* -import mozilla.components.browser.menu.BrowserMenuBuilder -import mozilla.components.browser.menu.item.SimpleBrowserMenuItem -import mozilla.components.browser.state.selector.normalTabs -import mozilla.components.concept.storage.BookmarkNode -import mozilla.components.feature.tab.collections.TabCollection -import mozilla.components.feature.top.sites.TopSite -import org.mozilla.fenix.R -import org.mozilla.fenix.utils.view.ViewHolder -import org.mozilla.fenix.ext.components -import org.mozilla.fenix.ext.getIconColor -import org.mozilla.fenix.ext.increaseTapArea -import org.mozilla.fenix.ext.removeAndDisable -import org.mozilla.fenix.ext.removeTouchDelegate -import org.mozilla.fenix.ext.showAndEnable -import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor -import org.mozilla.fenix.home.sessioncontrol.viewholders.topsites.TopSitesAdapter -import org.mozilla.fenix.theme.ThemeManager -import org.mozilla.fenix.utils.AccessibilityGridLayoutManager - -class RecentBookmarksViewHolder( - view: View, - val interactor: RecentBookmarksInteractor -) : ViewHolder(view) { - - private val recentBookmarksAdapter = RecentBookmarksAdapter(interactor) - - init { - val linearLayoutManager = LinearLayoutManager(view.context) - - view.top_sites_list.apply { - adapter = recentBookmarksAdapter - layoutManager = linearLayoutManager - } - } - - fun bind(bookmarks: List) { - recentBookmarksAdapter.submitList(bookmarks) - } - - companion object { - const val LAYOUT_ID = R.layout.component_top_sites - } -} diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/RecentBookmarksHeaderViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksHeaderViewHolder.kt similarity index 86% rename from app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/RecentBookmarksHeaderViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksHeaderViewHolder.kt index 8e64caae07fb..a71a358daab9 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/RecentBookmarksHeaderViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksHeaderViewHolder.kt @@ -2,7 +2,7 @@ * 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.home.sessioncontrol.viewholders +package org.mozilla.fenix.home.sessioncontrol.viewholders.recentbookmarks import android.view.View import androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksItemViewHolder.kt new file mode 100644 index 000000000000..33f2b82612ce --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksItemViewHolder.kt @@ -0,0 +1,78 @@ +/* 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.home.sessioncontrol.viewholders.recentbookmarks + +import android.view.View +import androidx.appcompat.content.res.AppCompatResources +import kotlinx.android.synthetic.main.recent_bookmark_item.* +import kotlinx.android.synthetic.main.top_site_item.favicon_image +import mozilla.components.concept.storage.BookmarkNode +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.loadIntoView +import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor +import org.mozilla.fenix.settings.SupportUtils +import org.mozilla.fenix.utils.view.ViewHolder + +class RecentBookmarkItemViewHolder( + view: View, + private val interactor: SessionControlInteractor +) : ViewHolder(view) { + private lateinit var bookmark: BookmarkNode + + init { + bookmark_item.setOnClickListener { + interactor.onRecentBookmarkClicked(bookmark) + } + } + + fun bind(bookmark: BookmarkNode) { + bookmark_title.text = bookmark.title + + when (bookmark.url) { + SupportUtils.POCKET_TRENDING_URL -> { + favicon_image.setImageDrawable( + AppCompatResources.getDrawable( + itemView.context, + R.drawable.ic_pocket + ) + ) + } + SupportUtils.BAIDU_URL -> { + favicon_image.setImageDrawable( + AppCompatResources.getDrawable( + itemView.context, + R.drawable.ic_baidu + ) + ) + } + SupportUtils.JD_URL -> { + favicon_image.setImageDrawable( + AppCompatResources.getDrawable( + itemView.context, + R.drawable.ic_jd + ) + ) + } + SupportUtils.PDD_URL -> { + favicon_image.setImageDrawable( + AppCompatResources.getDrawable( + itemView.context, + R.drawable.ic_pdd + ) + ) + } + else -> { + itemView.context.components.core.icons.loadIntoView(favicon_image, bookmark.url!!) + } + } + + this.bookmark = bookmark + } + + companion object { + const val LAYOUT_ID = R.layout.recent_bookmark_item + } +} diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksViewHolder.kt new file mode 100644 index 000000000000..d6d19b4544af --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/recentbookmarks/RecentBookmarksViewHolder.kt @@ -0,0 +1,40 @@ +/* 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.home.sessioncontrol.viewholders.recentbookmarks + +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.android.synthetic.main.component_recent_bookmarks.view.* +import mozilla.components.concept.storage.BookmarkNode +import org.mozilla.fenix.R +import org.mozilla.fenix.home.sessioncontrol.RecentBookmarksAdapter +import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor +import org.mozilla.fenix.utils.view.ViewHolder + +class RecentBookmarksViewHolder( + view: View, + val interactor: SessionControlInteractor +) : ViewHolder(view) { + + private val adapter = RecentBookmarksAdapter(interactor) + + init { + val linearLayoutManager = LinearLayoutManager(view.context) + + view.recent_bookmarks_list.apply { + adapter = adapter + layoutManager = linearLayoutManager + } + } + + fun bind(bookmarks: List) { + adapter.submitList(bookmarks) + } + + companion object { + const val LAYOUT_ID = R.layout.component_recent_bookmarks + const val MAX_BOOKMARKS = 4 + } +} diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 71b28b4a1f6d..e31f1d20b3da 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -149,6 +149,10 @@ android:name="focusOnCollection" android:defaultValue="-1L" app:argType="long" /> + + #F542414D #FF15141A #0015141A - #15141A - #5B5B66 @color/photonLightGrey30 @color/photonDarkGrey90 #7542E5